1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
22 #include <sys/reboot.h>
28 #include <sys/ioctl.h>
32 #include <sys/socket.h>
35 #include <sys/prctl.h>
36 #include <dbus/dbus.h>
38 #include <systemd/sd-daemon.h>
39 #include <systemd/sd-shutdown.h>
45 #include "utmp-wtmp.h"
48 #include "path-util.h"
50 #include "dbus-common.h"
51 #include "cgroup-show.h"
52 #include "cgroup-util.h"
54 #include "path-lookup.h"
55 #include "conf-parser.h"
56 #include "exit-status.h"
57 #include "bus-errors.h"
59 #include "unit-name.h"
61 #include "spawn-ask-password-agent.h"
62 #include "spawn-polkit-agent.h"
64 #include "logs-show.h"
65 #include "path-util.h"
66 #include "socket-util.h"
68 static const char *arg_type = NULL;
69 static const char *arg_load_state = NULL;
70 static char **arg_property = NULL;
71 static bool arg_all = false;
72 static const char *arg_job_mode = "replace";
73 static UnitFileScope arg_scope = UNIT_FILE_SYSTEM;
74 static bool arg_no_block = false;
75 static bool arg_no_legend = false;
76 static bool arg_no_pager = false;
77 static bool arg_no_wtmp = false;
78 static bool arg_no_wall = false;
79 static bool arg_no_reload = false;
80 static bool arg_dry = false;
81 static bool arg_quiet = false;
82 static bool arg_full = false;
83 static int arg_force = 0;
84 static bool arg_ask_password = true;
85 static bool arg_failed = false;
86 static bool arg_runtime = false;
87 static char **arg_wall = NULL;
88 static const char *arg_kill_who = NULL;
89 static int arg_signal = SIGTERM;
90 static const char *arg_root = NULL;
91 static usec_t arg_when = 0;
113 ACTION_CANCEL_SHUTDOWN,
115 } arg_action = ACTION_SYSTEMCTL;
121 static enum transport {
125 } arg_transport = TRANSPORT_NORMAL;
126 static const char *arg_host = NULL;
127 static unsigned arg_lines = 10;
128 static OutputMode arg_output = OUTPUT_SHORT;
130 static bool private_bus = false;
132 static int daemon_reload(DBusConnection *bus, char **args);
133 static void halt_now(enum action a);
135 static void pager_open_if_enabled(void) {
143 static void ask_password_agent_open_if_enabled(void) {
145 /* Open the password agent as a child process if necessary */
147 if (!arg_ask_password)
150 if (arg_scope != UNIT_FILE_SYSTEM)
153 ask_password_agent_open();
157 static void polkit_agent_open_if_enabled(void) {
159 /* Open the polkit agent as a child process if necessary */
161 if (!arg_ask_password)
164 if (arg_scope != UNIT_FILE_SYSTEM)
171 static const char *ansi_highlight(bool b) {
176 return b ? ANSI_HIGHLIGHT_ON : ANSI_HIGHLIGHT_OFF;
179 static const char *ansi_highlight_red(bool b) {
184 return b ? ANSI_HIGHLIGHT_RED_ON : ANSI_HIGHLIGHT_OFF;
187 static const char *ansi_highlight_green(bool b) {
192 return b ? ANSI_HIGHLIGHT_GREEN_ON : ANSI_HIGHLIGHT_OFF;
195 static int translate_bus_error_to_exit_status(int r, const DBusError *error) {
198 if (!dbus_error_is_set(error))
201 if (dbus_error_has_name(error, DBUS_ERROR_ACCESS_DENIED) ||
202 dbus_error_has_name(error, BUS_ERROR_ONLY_BY_DEPENDENCY) ||
203 dbus_error_has_name(error, BUS_ERROR_NO_ISOLATION) ||
204 dbus_error_has_name(error, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE))
205 return EXIT_NOPERMISSION;
207 if (dbus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT))
208 return EXIT_NOTINSTALLED;
210 if (dbus_error_has_name(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE) ||
211 dbus_error_has_name(error, BUS_ERROR_NOT_SUPPORTED))
212 return EXIT_NOTIMPLEMENTED;
214 if (dbus_error_has_name(error, BUS_ERROR_LOAD_FAILED))
215 return EXIT_NOTCONFIGURED;
223 static void warn_wall(enum action a) {
224 static const char *table[_ACTION_MAX] = {
225 [ACTION_HALT] = "The system is going down for system halt NOW!",
226 [ACTION_REBOOT] = "The system is going down for reboot NOW!",
227 [ACTION_POWEROFF] = "The system is going down for power-off NOW!",
228 [ACTION_KEXEC] = "The system is going down for kexec reboot NOW!",
229 [ACTION_RESCUE] = "The system is going down to rescue mode NOW!",
230 [ACTION_EMERGENCY] = "The system is going down to emergency mode NOW!",
231 [ACTION_CANCEL_SHUTDOWN] = "The system shutdown has been cancelled NOW!"
240 p = strv_join(arg_wall, " ");
242 log_error("Failed to join strings.");
258 utmp_wall(table[a], NULL);
261 static bool avoid_bus(void) {
263 if (running_in_chroot() > 0)
266 if (sd_booted() <= 0)
269 if (!isempty(arg_root))
272 if (arg_scope == UNIT_FILE_GLOBAL)
280 const char *description;
281 const char *load_state;
282 const char *active_state;
283 const char *sub_state;
284 const char *following;
285 const char *unit_path;
287 const char *job_type;
288 const char *job_path;
291 static int compare_unit_info(const void *a, const void *b) {
293 const struct unit_info *u = a, *v = b;
295 d1 = strrchr(u->id, '.');
296 d2 = strrchr(v->id, '.');
301 if ((r = strcasecmp(d1, d2)) != 0)
305 return strcasecmp(u->id, v->id);
308 static bool output_show_unit(const struct unit_info *u) {
312 return streq(u->active_state, "failed");
314 return (!arg_type || ((dot = strrchr(u->id, '.')) &&
315 streq(dot+1, arg_type))) &&
316 (!arg_load_state || streq(u->load_state, arg_load_state)) &&
317 (arg_all || !(streq(u->active_state, "inactive")
318 || u->following[0]) || u->job_id > 0);
321 static void output_units_list(const struct unit_info *unit_infos, unsigned c) {
322 unsigned id_len, max_id_len, active_len, sub_len, job_len, desc_len, n_shown = 0;
323 const struct unit_info *u;
326 max_id_len = sizeof("UNIT")-1;
327 active_len = sizeof("ACTIVE")-1;
328 sub_len = sizeof("SUB")-1;
329 job_len = sizeof("JOB")-1;
332 for (u = unit_infos; u < unit_infos + c; u++) {
333 if (!output_show_unit(u))
336 max_id_len = MAX(max_id_len, strlen(u->id));
337 active_len = MAX(active_len, strlen(u->active_state));
338 sub_len = MAX(sub_len, strlen(u->sub_state));
339 if (u->job_id != 0) {
340 job_len = MAX(job_len, strlen(u->job_type));
347 id_len = MIN(max_id_len, 25);
348 basic_len = 5 + id_len + 5 + active_len + sub_len;
350 basic_len += job_len + 1;
351 if (basic_len < (unsigned) columns()) {
352 unsigned extra_len, incr;
353 extra_len = columns() - basic_len;
354 /* Either UNIT already got 25, or is fully satisfied.
355 * Grant up to 25 to DESC now. */
356 incr = MIN(extra_len, 25);
359 /* split the remaining space between UNIT and DESC,
360 * but do not give UNIT more than it needs. */
362 incr = MIN(extra_len / 2, max_id_len - id_len);
364 desc_len += extra_len - incr;
370 for (u = unit_infos; u < unit_infos + c; u++) {
372 const char *on_loaded, *off_loaded;
373 const char *on_active, *off_active;
375 if (!output_show_unit(u))
378 if (!n_shown && !arg_no_legend) {
379 printf("%-*s %-6s %-*s %-*s ", id_len, "UNIT", "LOAD",
380 active_len, "ACTIVE", sub_len, "SUB");
382 printf("%-*s ", job_len, "JOB");
383 if (!arg_full && arg_no_pager)
384 printf("%.*s\n", desc_len, "DESCRIPTION");
386 printf("%s\n", "DESCRIPTION");
391 if (streq(u->load_state, "error")) {
392 on_loaded = ansi_highlight_red(true);
393 off_loaded = ansi_highlight_red(false);
395 on_loaded = off_loaded = "";
397 if (streq(u->active_state, "failed")) {
398 on_active = ansi_highlight_red(true);
399 off_active = ansi_highlight_red(false);
401 on_active = off_active = "";
403 e = arg_full ? NULL : ellipsize(u->id, id_len, 33);
405 printf("%-*s %s%-6s%s %s%-*s %-*s%s %-*s",
406 id_len, e ? e : u->id,
407 on_loaded, u->load_state, off_loaded,
408 on_active, active_len, u->active_state,
409 sub_len, u->sub_state, off_active,
410 job_count ? job_len + 1 : 0, u->job_id ? u->job_type : "");
411 if (!arg_full && arg_no_pager)
412 printf("%.*s\n", desc_len, u->description);
414 printf("%s\n", u->description);
419 if (!arg_no_legend) {
420 const char *on, *off;
423 printf("\nLOAD = Reflects whether the unit definition was properly loaded.\n"
424 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
425 "SUB = The low-level unit activation state, values depend on unit type.\n");
427 printf("JOB = Pending job for the unit.\n");
428 on = ansi_highlight(true);
429 off = ansi_highlight(false);
431 on = ansi_highlight_red(true);
432 off = ansi_highlight_red(false);
436 printf("\n%s%u loaded units listed.%s\n"
437 "To show all installed unit files use 'systemctl list-unit-files'.\n",
440 printf("\n%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
441 "To show all installed unit files use 'systemctl list-unit-files'.\n",
446 static int list_units(DBusConnection *bus, char **args) {
447 DBusMessage *reply = NULL;
449 DBusMessageIter iter, sub, sub2;
450 unsigned c = 0, n_units = 0;
451 struct unit_info *unit_infos = NULL;
453 pager_open_if_enabled();
455 r = bus_method_call_with_reply (
457 "org.freedesktop.systemd1",
458 "/org/freedesktop/systemd1",
459 "org.freedesktop.systemd1.Manager",
467 if (!dbus_message_iter_init(reply, &iter) ||
468 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
469 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
470 log_error("Failed to parse reply.");
475 dbus_message_iter_recurse(&iter, &sub);
477 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
480 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
481 log_error("Failed to parse reply.");
489 n_units = MAX(2*c, 16);
490 w = realloc(unit_infos, sizeof(struct unit_info) * n_units);
493 log_error("Failed to allocate unit array.");
503 dbus_message_iter_recurse(&sub, &sub2);
505 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->id, true) < 0 ||
506 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->description, true) < 0 ||
507 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->load_state, true) < 0 ||
508 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->active_state, true) < 0 ||
509 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->sub_state, true) < 0 ||
510 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->following, true) < 0 ||
511 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &u->unit_path, true) < 0 ||
512 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &u->job_id, true) < 0 ||
513 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->job_type, true) < 0 ||
514 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &u->job_path, false) < 0) {
515 log_error("Failed to parse reply.");
520 dbus_message_iter_next(&sub);
525 qsort(unit_infos, c, sizeof(struct unit_info), compare_unit_info);
526 output_units_list(unit_infos, c);
531 dbus_message_unref(reply);
538 static int compare_unit_file_list(const void *a, const void *b) {
540 const UnitFileList *u = a, *v = b;
542 d1 = strrchr(u->path, '.');
543 d2 = strrchr(v->path, '.');
548 r = strcasecmp(d1, d2);
553 return strcasecmp(path_get_file_name(u->path), path_get_file_name(v->path));
556 static bool output_show_unit_file(const UnitFileList *u) {
559 return !arg_type || ((dot = strrchr(u->path, '.')) && streq(dot+1, arg_type));
562 static void output_unit_file_list(const UnitFileList *units, unsigned c) {
563 unsigned max_id_len, id_cols, state_cols, n_shown = 0;
564 const UnitFileList *u;
566 max_id_len = sizeof("UNIT FILE")-1;
567 state_cols = sizeof("STATE")-1;
568 for (u = units; u < units + c; u++) {
569 if (!output_show_unit_file(u))
572 max_id_len = MAX(max_id_len, strlen(path_get_file_name(u->path)));
573 state_cols = MAX(state_cols, strlen(unit_file_state_to_string(u->state)));
578 id_cols = MIN(max_id_len, 25);
579 basic_cols = 1 + id_cols + state_cols;
580 if (basic_cols < (unsigned) columns())
581 id_cols += MIN(columns() - basic_cols, max_id_len - id_cols);
583 id_cols = max_id_len;
586 printf("%-*s %-*s\n", id_cols, "UNIT FILE", state_cols, "STATE");
588 for (u = units; u < units + c; u++) {
590 const char *on, *off;
593 if (!output_show_unit_file(u))
598 if (u->state == UNIT_FILE_MASKED ||
599 u->state == UNIT_FILE_MASKED_RUNTIME ||
600 u->state == UNIT_FILE_DISABLED ||
601 u->state == UNIT_FILE_INVALID) {
602 on = ansi_highlight_red(true);
603 off = ansi_highlight_red(false);
604 } else if (u->state == UNIT_FILE_ENABLED) {
605 on = ansi_highlight_green(true);
606 off = ansi_highlight_green(false);
610 id = path_get_file_name(u->path);
612 e = arg_full ? NULL : ellipsize(id, id_cols, 33);
614 printf("%-*s %s%-*s%s\n",
616 on, state_cols, unit_file_state_to_string(u->state), off);
622 printf("\n%u unit files listed.\n", n_shown);
625 static int list_unit_files(DBusConnection *bus, char **args) {
626 DBusMessage *reply = NULL;
628 DBusMessageIter iter, sub, sub2;
629 unsigned c = 0, n_units = 0;
630 UnitFileList *units = NULL;
632 pager_open_if_enabled();
639 h = hashmap_new(string_hash_func, string_compare_func);
643 r = unit_file_get_list(arg_scope, arg_root, h);
645 unit_file_list_free(h);
646 log_error("Failed to get unit file list: %s", strerror(-r));
650 n_units = hashmap_size(h);
651 units = new(UnitFileList, n_units);
653 unit_file_list_free(h);
657 HASHMAP_FOREACH(u, h, i) {
658 memcpy(units + c++, u, sizeof(UnitFileList));
664 r = bus_method_call_with_reply (
666 "org.freedesktop.systemd1",
667 "/org/freedesktop/systemd1",
668 "org.freedesktop.systemd1.Manager",
676 if (!dbus_message_iter_init(reply, &iter) ||
677 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
678 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
679 log_error("Failed to parse reply.");
684 dbus_message_iter_recurse(&iter, &sub);
686 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
690 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
691 log_error("Failed to parse reply.");
699 n_units = MAX(2*c, 16);
700 w = realloc(units, sizeof(struct UnitFileList) * n_units);
703 log_error("Failed to allocate unit array.");
713 dbus_message_iter_recurse(&sub, &sub2);
715 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->path, true) < 0 ||
716 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, false) < 0) {
717 log_error("Failed to parse reply.");
722 u->state = unit_file_state_from_string(state);
724 dbus_message_iter_next(&sub);
730 qsort(units, c, sizeof(UnitFileList), compare_unit_file_list);
731 output_unit_file_list(units, c);
738 dbus_message_unref(reply);
745 static int dot_one_property(const char *name, const char *prop, DBusMessageIter *iter) {
746 static const char * const colors[] = {
747 "Requires", "[color=\"black\"]",
748 "RequiresOverridable", "[color=\"black\"]",
749 "Requisite", "[color=\"darkblue\"]",
750 "RequisiteOverridable", "[color=\"darkblue\"]",
751 "Wants", "[color=\"grey66\"]",
752 "Conflicts", "[color=\"red\"]",
753 "ConflictedBy", "[color=\"red\"]",
754 "After", "[color=\"green\"]"
757 const char *c = NULL;
764 for (i = 0; i < ELEMENTSOF(colors); i += 2)
765 if (streq(colors[i], prop)) {
773 if (arg_dot != DOT_ALL)
774 if ((arg_dot == DOT_ORDER) != streq(prop, "After"))
777 switch (dbus_message_iter_get_arg_type(iter)) {
779 case DBUS_TYPE_ARRAY:
781 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING) {
784 dbus_message_iter_recurse(iter, &sub);
786 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
789 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING);
790 dbus_message_iter_get_basic(&sub, &s);
791 printf("\t\"%s\"->\"%s\" %s;\n", name, s, c);
793 dbus_message_iter_next(&sub);
803 static int dot_one(DBusConnection *bus, const char *name, const char *path) {
804 DBusMessage *reply = NULL;
805 const char *interface = "org.freedesktop.systemd1.Unit";
807 DBusMessageIter iter, sub, sub2, sub3;
811 r = bus_method_call_with_reply (
813 "org.freedesktop.systemd1",
815 "org.freedesktop.DBus.Properties",
819 DBUS_TYPE_STRING, &interface,
824 if (!dbus_message_iter_init(reply, &iter) ||
825 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
826 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
827 log_error("Failed to parse reply.");
832 dbus_message_iter_recurse(&iter, &sub);
834 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
837 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_DICT_ENTRY) {
838 log_error("Failed to parse reply.");
843 dbus_message_iter_recurse(&sub, &sub2);
845 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &prop, true) < 0) {
846 log_error("Failed to parse reply.");
851 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
852 log_error("Failed to parse reply.");
857 dbus_message_iter_recurse(&sub2, &sub3);
859 if (dot_one_property(name, prop, &sub3)) {
860 log_error("Failed to parse reply.");
865 dbus_message_iter_next(&sub);
870 dbus_message_unref(reply);
875 static int dot(DBusConnection *bus, char **args) {
876 DBusMessage *reply = NULL;
878 DBusMessageIter iter, sub, sub2;
880 r = bus_method_call_with_reply (
882 "org.freedesktop.systemd1",
883 "/org/freedesktop/systemd1",
884 "org.freedesktop.systemd1.Manager",
892 if (!dbus_message_iter_init(reply, &iter) ||
893 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
894 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
895 log_error("Failed to parse reply.");
900 printf("digraph systemd {\n");
902 dbus_message_iter_recurse(&iter, &sub);
903 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
904 const char *id, *description, *load_state, *active_state, *sub_state, *following, *unit_path;
906 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
907 log_error("Failed to parse reply.");
912 dbus_message_iter_recurse(&sub, &sub2);
914 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &id, true) < 0 ||
915 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &description, true) < 0 ||
916 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &load_state, true) < 0 ||
917 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &active_state, true) < 0 ||
918 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &sub_state, true) < 0 ||
919 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &following, true) < 0 ||
920 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, true) < 0) {
921 log_error("Failed to parse reply.");
926 if ((r = dot_one(bus, id, unit_path)) < 0)
929 /* printf("\t\"%s\";\n", id); */
930 dbus_message_iter_next(&sub);
935 log_info(" Color legend: black = Requires\n"
936 " dark blue = Requisite\n"
937 " dark grey = Wants\n"
942 log_notice("-- You probably want to process this output with graphviz' dot tool.\n"
943 "-- Try a shell pipeline like 'systemctl dot | dot -Tsvg > systemd.svg'!\n");
949 dbus_message_unref(reply);
954 static int list_jobs(DBusConnection *bus, char **args) {
955 DBusMessage *reply = NULL;
957 DBusMessageIter iter, sub, sub2;
960 pager_open_if_enabled();
962 r = bus_method_call_with_reply (
964 "org.freedesktop.systemd1",
965 "/org/freedesktop/systemd1",
966 "org.freedesktop.systemd1.Manager",
974 if (!dbus_message_iter_init(reply, &iter) ||
975 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
976 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
977 log_error("Failed to parse reply.");
982 dbus_message_iter_recurse(&iter, &sub);
985 printf("%4s %-25s %-15s %-7s\n", "JOB", "UNIT", "TYPE", "STATE");
987 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
988 const char *name, *type, *state, *job_path, *unit_path;
992 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
993 log_error("Failed to parse reply.");
998 dbus_message_iter_recurse(&sub, &sub2);
1000 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &id, true) < 0 ||
1001 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
1002 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
1003 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, true) < 0 ||
1004 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &job_path, true) < 0 ||
1005 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, false) < 0) {
1006 log_error("Failed to parse reply.");
1011 e = arg_full ? NULL : ellipsize(name, 25, 33);
1012 printf("%4u %-25s %-15s %-7s\n", id, e ? e : name, type, state);
1017 dbus_message_iter_next(&sub);
1021 printf("\n%u jobs listed.\n", k);
1027 dbus_message_unref(reply);
1032 static int load_unit(DBusConnection *bus, char **args) {
1038 STRV_FOREACH(name, args+1) {
1039 n = unit_name_mangle(*name);
1040 r = bus_method_call_with_reply (
1042 "org.freedesktop.systemd1",
1043 "/org/freedesktop/systemd1",
1044 "org.freedesktop.systemd1.Manager",
1048 DBUS_TYPE_STRING, n ? &n : name,
1059 static int cancel_job(DBusConnection *bus, char **args) {
1060 DBusMessage *reply = NULL;
1066 if (strv_length(args) <= 1)
1067 return daemon_reload(bus, args);
1069 STRV_FOREACH(name, args+1) {
1073 r = safe_atou(*name, &id);
1075 log_error("Failed to parse job id: %s", strerror(-r));
1078 assert_cc(sizeof(uint32_t) == sizeof(id));
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,
1093 if (!dbus_message_get_args(reply, NULL,
1094 DBUS_TYPE_OBJECT_PATH, &path,
1095 DBUS_TYPE_INVALID)) {
1096 log_error("Failed to parse reply");
1097 dbus_message_unref(reply);
1101 dbus_message_unref(reply);
1103 r = bus_method_call_with_reply (
1105 "org.freedesktop.systemd1",
1107 "org.freedesktop.systemd1.Job",
1120 static bool need_daemon_reload(DBusConnection *bus, const char *unit) {
1121 DBusMessage *reply = NULL;
1122 dbus_bool_t b = FALSE;
1123 DBusMessageIter iter, sub;
1125 *interface = "org.freedesktop.systemd1.Unit",
1126 *property = "NeedDaemonReload",
1131 /* We ignore all errors here, since this is used to show a warning only */
1133 n = unit_name_mangle(unit);
1134 r = bus_method_call_with_reply (
1136 "org.freedesktop.systemd1",
1137 "/org/freedesktop/systemd1",
1138 "org.freedesktop.systemd1.Manager",
1142 DBUS_TYPE_STRING, n ? (const char**) &n : &unit,
1148 if (!dbus_message_get_args(reply, NULL,
1149 DBUS_TYPE_OBJECT_PATH, &path,
1153 dbus_message_unref(reply);
1154 r = bus_method_call_with_reply (
1156 "org.freedesktop.systemd1",
1158 "org.freedesktop.DBus.Properties",
1162 DBUS_TYPE_STRING, &interface,
1163 DBUS_TYPE_STRING, &property,
1168 if (!dbus_message_iter_init(reply, &iter) ||
1169 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
1172 dbus_message_iter_recurse(&iter, &sub);
1174 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_BOOLEAN)
1177 dbus_message_iter_get_basic(&sub, &b);
1181 dbus_message_unref(reply);
1186 typedef struct WaitData {
1193 static DBusHandlerResult wait_filter(DBusConnection *connection, DBusMessage *message, void *data) {
1201 dbus_error_init(&error);
1203 log_debug("Got D-Bus request: %s.%s() on %s",
1204 dbus_message_get_interface(message),
1205 dbus_message_get_member(message),
1206 dbus_message_get_path(message));
1208 if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
1209 log_error("Warning! D-Bus connection terminated.");
1210 dbus_connection_close(connection);
1212 } else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
1214 const char *path, *result, *unit;
1215 dbus_bool_t success = true;
1217 if (dbus_message_get_args(message, &error,
1218 DBUS_TYPE_UINT32, &id,
1219 DBUS_TYPE_OBJECT_PATH, &path,
1220 DBUS_TYPE_STRING, &unit,
1221 DBUS_TYPE_STRING, &result,
1222 DBUS_TYPE_INVALID)) {
1225 p = set_remove(d->set, (char*) path);
1228 if (!isempty(result))
1229 d->result = strdup(result);
1232 d->name = strdup(unit);
1237 dbus_error_free(&error);
1238 if (dbus_message_get_args(message, &error,
1239 DBUS_TYPE_UINT32, &id,
1240 DBUS_TYPE_OBJECT_PATH, &path,
1241 DBUS_TYPE_STRING, &result,
1242 DBUS_TYPE_INVALID)) {
1245 /* Compatibility with older systemd versions <
1246 * 183 during upgrades. This should be dropped
1248 p = set_remove(d->set, (char*) path);
1252 d->result = strdup(result);
1257 dbus_error_free(&error);
1258 if (dbus_message_get_args(message, &error,
1259 DBUS_TYPE_UINT32, &id,
1260 DBUS_TYPE_OBJECT_PATH, &path,
1261 DBUS_TYPE_BOOLEAN, &success,
1262 DBUS_TYPE_INVALID)) {
1265 /* Compatibility with older systemd versions <
1266 * 19 during upgrades. This should be dropped
1269 p = set_remove(d->set, (char*) path);
1273 d->result = strdup("failed");
1279 log_error("Failed to parse message: %s", bus_error_message(&error));
1283 dbus_error_free(&error);
1284 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1287 static int enable_wait_for_jobs(DBusConnection *bus) {
1295 dbus_error_init(&error);
1296 dbus_bus_add_match(bus,
1298 "sender='org.freedesktop.systemd1',"
1299 "interface='org.freedesktop.systemd1.Manager',"
1300 "member='JobRemoved',"
1301 "path='/org/freedesktop/systemd1'",
1304 if (dbus_error_is_set(&error)) {
1305 log_error("Failed to add match: %s", bus_error_message(&error));
1306 dbus_error_free(&error);
1310 /* This is slightly dirty, since we don't undo the match registrations. */
1314 static int wait_for_jobs(DBusConnection *bus, Set *s) {
1324 if (!dbus_connection_add_filter(bus, wait_filter, &d, NULL))
1327 while (!set_isempty(s)) {
1329 if (!dbus_connection_read_write_dispatch(bus, -1)) {
1330 log_error("Disconnected from bus.");
1331 return -ECONNREFUSED;
1338 if (streq(d.result, "timeout"))
1339 log_error("Job for %s timed out.", strna(d.name));
1340 else if (streq(d.result, "canceled"))
1341 log_error("Job for %s canceled.", strna(d.name));
1342 else if (streq(d.result, "dependency"))
1343 log_error("A dependency job for %s failed. See 'journalctl -n' for details.", strna(d.name));
1344 else if (!streq(d.result, "done") && !streq(d.result, "skipped"))
1345 log_error("Job for %s failed. See 'systemctl status %s' and 'journalctl -n' for details.", strna(d.name), strna(d.name));
1348 if (streq_ptr(d.result, "timeout"))
1350 else if (streq_ptr(d.result, "canceled"))
1352 else if (!streq_ptr(d.result, "done") && !streq_ptr(d.result, "skipped"))
1363 dbus_connection_remove_filter(bus, wait_filter, &d);
1367 static int check_one_unit(DBusConnection *bus, char *name, bool quiet) {
1368 DBusMessage *reply = NULL;
1369 DBusMessageIter iter, sub;
1371 *interface = "org.freedesktop.systemd1.Unit",
1372 *property = "ActiveState";
1373 const char *path = NULL;
1380 n = unit_name_mangle(name);
1381 r = bus_method_call_with_reply (
1383 "org.freedesktop.systemd1",
1384 "/org/freedesktop/systemd1",
1385 "org.freedesktop.systemd1.Manager",
1389 DBUS_TYPE_STRING, n ? &n : &name,
1393 if ((r != -ENOMEM) && (!quiet))
1398 if (!dbus_message_get_args(reply, NULL,
1399 DBUS_TYPE_OBJECT_PATH, &path,
1400 DBUS_TYPE_INVALID)) {
1401 log_error("Failed to parse reply.");
1406 dbus_message_unref(reply);
1407 r = bus_method_call_with_reply (
1409 "org.freedesktop.systemd1",
1411 "org.freedesktop.DBus.Properties",
1415 DBUS_TYPE_STRING, &interface,
1416 DBUS_TYPE_STRING, &property,
1421 if (!dbus_message_iter_init(reply, &iter) ||
1422 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1423 log_error("Failed to parse reply.");
1428 dbus_message_iter_recurse(&iter, &sub);
1430 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1431 log_error("Failed to parse reply.");
1436 dbus_message_iter_get_basic(&sub, &state);
1441 if (streq(state, "active") || streq(state, "reloading"))
1444 r = 3; /* According to LSB: "program is not running" */
1448 dbus_message_unref(reply);
1453 static void check_triggering_units(
1454 DBusConnection *bus,
1455 const char *unit_name) {
1457 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1458 DBusMessageIter iter, sub;
1459 char *service_trigger = NULL;
1460 const char *interface = "org.freedesktop.systemd1.Unit",
1461 *triggered_by_property = "TriggeredBy";
1463 char _cleanup_free_ *unit_path = NULL, *n = NULL;
1464 bool print_warning_label = true;
1467 n = unit_name_mangle(unit_name);
1473 unit_path = unit_dbus_path_from_name(n);
1479 r = bus_method_call_with_reply (
1481 "org.freedesktop.systemd1",
1483 "org.freedesktop.DBus.Properties",
1487 DBUS_TYPE_STRING, &interface,
1488 DBUS_TYPE_STRING, &triggered_by_property,
1493 if (!dbus_message_iter_init(reply, &iter) ||
1494 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1495 log_error("Failed to parse reply.");
1499 dbus_message_iter_recurse(&iter, &sub);
1500 dbus_message_iter_recurse(&sub, &iter);
1503 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1505 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1506 log_error("Failed to parse reply.");
1510 dbus_message_iter_get_basic(&sub, &service_trigger);
1512 r = check_one_unit(bus, service_trigger, true);
1516 if (print_warning_label) {
1517 log_warning("Warning: Stopping %s, but it can still be activated by:", unit_name);
1518 print_warning_label = false;
1520 log_warning(" %s", service_trigger);
1523 dbus_message_iter_next(&sub);
1527 static int start_unit_one(
1528 DBusConnection *bus,
1535 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1538 _cleanup_free_ char *n, *p = NULL;
1545 n = unit_name_mangle(name);
1549 r = bus_method_call_with_reply(
1551 "org.freedesktop.systemd1",
1552 "/org/freedesktop/systemd1",
1553 "org.freedesktop.systemd1.Manager",
1557 DBUS_TYPE_STRING, &n,
1558 DBUS_TYPE_STRING, &mode,
1561 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
1562 /* There's always a fallback possible for
1563 * legacy actions. */
1566 log_error("Failed to issue method call: %s", bus_error_message(error));
1571 if (!dbus_message_get_args(reply, error,
1572 DBUS_TYPE_OBJECT_PATH, &path,
1573 DBUS_TYPE_INVALID)) {
1574 log_error("Failed to parse reply: %s", bus_error_message(error));
1578 if (need_daemon_reload(bus, n))
1579 log_warning("Warning: Unit file of %s changed on disk, 'systemctl %s daemon-reload' recommended.",
1580 n, arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
1589 log_error("Failed to add path to set.");
1599 static enum action verb_to_action(const char *verb) {
1600 if (streq(verb, "halt"))
1602 else if (streq(verb, "poweroff"))
1603 return ACTION_POWEROFF;
1604 else if (streq(verb, "reboot"))
1605 return ACTION_REBOOT;
1606 else if (streq(verb, "kexec"))
1607 return ACTION_KEXEC;
1608 else if (streq(verb, "rescue"))
1609 return ACTION_RESCUE;
1610 else if (streq(verb, "emergency"))
1611 return ACTION_EMERGENCY;
1612 else if (streq(verb, "default"))
1613 return ACTION_DEFAULT;
1614 else if (streq(verb, "exit"))
1616 else if (streq(verb, "suspend"))
1617 return ACTION_SUSPEND;
1618 else if (streq(verb, "hibernate"))
1619 return ACTION_HIBERNATE;
1620 else if (streq(verb, "hybrid-sleep"))
1621 return ACTION_HYBRID_SLEEP;
1623 return ACTION_INVALID;
1626 static int start_unit(DBusConnection *bus, char **args) {
1628 static const char * const table[_ACTION_MAX] = {
1629 [ACTION_HALT] = SPECIAL_HALT_TARGET,
1630 [ACTION_POWEROFF] = SPECIAL_POWEROFF_TARGET,
1631 [ACTION_REBOOT] = SPECIAL_REBOOT_TARGET,
1632 [ACTION_KEXEC] = SPECIAL_KEXEC_TARGET,
1633 [ACTION_RUNLEVEL2] = SPECIAL_RUNLEVEL2_TARGET,
1634 [ACTION_RUNLEVEL3] = SPECIAL_RUNLEVEL3_TARGET,
1635 [ACTION_RUNLEVEL4] = SPECIAL_RUNLEVEL4_TARGET,
1636 [ACTION_RUNLEVEL5] = SPECIAL_RUNLEVEL5_TARGET,
1637 [ACTION_RESCUE] = SPECIAL_RESCUE_TARGET,
1638 [ACTION_EMERGENCY] = SPECIAL_EMERGENCY_TARGET,
1639 [ACTION_DEFAULT] = SPECIAL_DEFAULT_TARGET,
1640 [ACTION_EXIT] = SPECIAL_EXIT_TARGET,
1641 [ACTION_SUSPEND] = SPECIAL_SUSPEND_TARGET,
1642 [ACTION_HIBERNATE] = SPECIAL_HIBERNATE_TARGET,
1643 [ACTION_HYBRID_SLEEP] = SPECIAL_HYBRID_SLEEP_TARGET
1647 const char *method, *mode, *one_name;
1652 dbus_error_init(&error);
1656 ask_password_agent_open_if_enabled();
1658 if (arg_action == ACTION_SYSTEMCTL) {
1660 streq(args[0], "stop") ||
1661 streq(args[0], "condstop") ? "StopUnit" :
1662 streq(args[0], "reload") ? "ReloadUnit" :
1663 streq(args[0], "restart") ? "RestartUnit" :
1665 streq(args[0], "try-restart") ||
1666 streq(args[0], "condrestart") ? "TryRestartUnit" :
1668 streq(args[0], "reload-or-restart") ? "ReloadOrRestartUnit" :
1670 streq(args[0], "reload-or-try-restart") ||
1671 streq(args[0], "condreload") ||
1673 streq(args[0], "force-reload") ? "ReloadOrTryRestartUnit" :
1677 (streq(args[0], "isolate") ||
1678 streq(args[0], "rescue") ||
1679 streq(args[0], "emergency")) ? "isolate" : arg_job_mode;
1681 one_name = table[verb_to_action(args[0])];
1684 assert(arg_action < ELEMENTSOF(table));
1685 assert(table[arg_action]);
1687 method = "StartUnit";
1689 mode = (arg_action == ACTION_EMERGENCY ||
1690 arg_action == ACTION_RESCUE ||
1691 arg_action == ACTION_RUNLEVEL2 ||
1692 arg_action == ACTION_RUNLEVEL3 ||
1693 arg_action == ACTION_RUNLEVEL4 ||
1694 arg_action == ACTION_RUNLEVEL5) ? "isolate" : "replace";
1696 one_name = table[arg_action];
1699 if (!arg_no_block) {
1700 ret = enable_wait_for_jobs(bus);
1702 log_error("Could not watch jobs: %s", strerror(-ret));
1706 s = set_new(string_hash_func, string_compare_func);
1714 ret = start_unit_one(bus, method, one_name, mode, &error, s);
1716 ret = translate_bus_error_to_exit_status(ret, &error);
1718 STRV_FOREACH(name, args+1) {
1719 r = start_unit_one(bus, method, *name, mode, &error, s);
1721 ret = translate_bus_error_to_exit_status(r, &error);
1722 dbus_error_free(&error);
1727 if (!arg_no_block) {
1728 r = wait_for_jobs(bus, s);
1734 /* When stopping units, warn if they can still be triggered by
1735 * another active unit (socket, path, timer) */
1736 if (!arg_quiet && streq(method, "StopUnit")) {
1738 check_triggering_units(bus, one_name);
1740 STRV_FOREACH(name, args+1)
1741 check_triggering_units(bus, *name);
1747 dbus_error_free(&error);
1752 /* Ask systemd-logind, which might grant access to unprivileged users
1753 * through PolicyKit */
1754 static int reboot_with_logind(DBusConnection *bus, enum action a) {
1757 dbus_bool_t interactive = true;
1759 polkit_agent_open_if_enabled();
1767 case ACTION_POWEROFF:
1768 method = "PowerOff";
1771 case ACTION_SUSPEND:
1775 case ACTION_HIBERNATE:
1776 method = "Hibernate";
1779 case ACTION_HYBRID_SLEEP:
1780 method = "HybridSleep";
1787 return bus_method_call_with_reply (
1789 "org.freedesktop.login1",
1790 "/org/freedesktop/login1",
1791 "org.freedesktop.login1.Manager",
1795 DBUS_TYPE_BOOLEAN, &interactive,
1802 static int start_special(DBusConnection *bus, char **args) {
1808 a = verb_to_action(args[0]);
1810 if (arg_force >= 2 && geteuid() != 0) {
1811 log_error("Must be root.");
1815 if (arg_force >= 2 &&
1816 (a == ACTION_HALT ||
1817 a == ACTION_POWEROFF ||
1818 a == ACTION_REBOOT))
1821 if (arg_force >= 1 &&
1822 (a == ACTION_HALT ||
1823 a == ACTION_POWEROFF ||
1824 a == ACTION_REBOOT ||
1825 a == ACTION_KEXEC ||
1827 return daemon_reload(bus, args);
1829 /* first try logind, to allow authentication with polkit */
1830 if (geteuid() != 0 &&
1831 (a == ACTION_POWEROFF ||
1832 a == ACTION_REBOOT ||
1833 a == ACTION_SUSPEND ||
1834 a == ACTION_HIBERNATE ||
1835 a == ACTION_HYBRID_SLEEP)) {
1836 r = reboot_with_logind(bus, a);
1841 r = start_unit(bus, args);
1848 static int check_unit(DBusConnection *bus, char **args) {
1850 int r = 3; /* According to LSB: "program is not running" */
1855 STRV_FOREACH(name, args+1) {
1856 int state = check_one_unit(bus, *name, arg_quiet);
1866 static int kill_unit(DBusConnection *bus, char **args) {
1873 arg_kill_who = "all";
1875 STRV_FOREACH(name, args+1) {
1876 n = unit_name_mangle(*name);
1877 r = bus_method_call_with_reply (
1879 "org.freedesktop.systemd1",
1880 "/org/freedesktop/systemd1",
1881 "org.freedesktop.systemd1.Manager",
1885 DBUS_TYPE_STRING, n ? &n : name,
1886 DBUS_TYPE_STRING, &arg_kill_who,
1887 DBUS_TYPE_INT32, &arg_signal,
1896 typedef struct ExecStatusInfo {
1904 usec_t start_timestamp;
1905 usec_t exit_timestamp;
1910 LIST_FIELDS(struct ExecStatusInfo, exec);
1913 static void exec_status_info_free(ExecStatusInfo *i) {
1922 static int exec_status_info_deserialize(DBusMessageIter *sub, ExecStatusInfo *i) {
1923 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
1924 DBusMessageIter sub2, sub3;
1928 int32_t code, status;
1934 if (dbus_message_iter_get_arg_type(sub) != DBUS_TYPE_STRUCT)
1937 dbus_message_iter_recurse(sub, &sub2);
1939 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0)
1942 if (!(i->path = strdup(path)))
1945 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_ARRAY ||
1946 dbus_message_iter_get_element_type(&sub2) != DBUS_TYPE_STRING)
1950 dbus_message_iter_recurse(&sub2, &sub3);
1951 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
1952 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
1953 dbus_message_iter_next(&sub3);
1958 if (!(i->argv = new0(char*, n+1)))
1962 dbus_message_iter_recurse(&sub2, &sub3);
1963 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
1966 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
1967 dbus_message_iter_get_basic(&sub3, &s);
1968 dbus_message_iter_next(&sub3);
1970 if (!(i->argv[n++] = strdup(s)))
1974 if (!dbus_message_iter_next(&sub2) ||
1975 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, true) < 0 ||
1976 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp, true) < 0 ||
1977 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp_monotonic, true) < 0 ||
1978 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp, true) < 0 ||
1979 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp_monotonic, true) < 0 ||
1980 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, true) < 0 ||
1981 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &code, true) < 0 ||
1982 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &status, false) < 0)
1986 i->start_timestamp = (usec_t) start_timestamp;
1987 i->exit_timestamp = (usec_t) exit_timestamp;
1988 i->pid = (pid_t) pid;
1995 typedef struct UnitStatusInfo {
1997 const char *load_state;
1998 const char *active_state;
1999 const char *sub_state;
2000 const char *unit_file_state;
2002 const char *description;
2003 const char *following;
2005 char **documentation;
2007 const char *fragment_path;
2008 const char *source_path;
2009 const char *default_control_group;
2011 const char *load_error;
2014 usec_t inactive_exit_timestamp;
2015 usec_t inactive_exit_timestamp_monotonic;
2016 usec_t active_enter_timestamp;
2017 usec_t active_exit_timestamp;
2018 usec_t inactive_enter_timestamp;
2020 bool need_daemon_reload;
2025 const char *status_text;
2028 usec_t start_timestamp;
2029 usec_t exit_timestamp;
2031 int exit_code, exit_status;
2033 usec_t condition_timestamp;
2034 bool condition_result;
2037 unsigned n_accepted;
2038 unsigned n_connections;
2042 const char *sysfs_path;
2044 /* Mount, Automount */
2050 LIST_HEAD(ExecStatusInfo, exec);
2053 static void print_status_info(UnitStatusInfo *i) {
2055 const char *on, *off, *ss;
2057 char since1[FORMAT_TIMESTAMP_PRETTY_MAX], *s1;
2058 char since2[FORMAT_TIMESTAMP_MAX], *s2;
2063 /* This shows pretty information about a unit. See
2064 * print_property() for a low-level property printer */
2066 printf("%s", strna(i->id));
2068 if (i->description && !streq_ptr(i->id, i->description))
2069 printf(" - %s", i->description);
2074 printf("\t Follow: unit currently follows state of %s\n", i->following);
2076 if (streq_ptr(i->load_state, "error")) {
2077 on = ansi_highlight_red(true);
2078 off = ansi_highlight_red(false);
2082 path = i->source_path ? i->source_path : i->fragment_path;
2085 printf("\t Loaded: %s%s%s (Reason: %s)\n", on, strna(i->load_state), off, i->load_error);
2086 else if (path && i->unit_file_state)
2087 printf("\t Loaded: %s%s%s (%s; %s)\n", on, strna(i->load_state), off, path, i->unit_file_state);
2089 printf("\t Loaded: %s%s%s (%s)\n", on, strna(i->load_state), off, path);
2091 printf("\t Loaded: %s%s%s\n", on, strna(i->load_state), off);
2093 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
2095 if (streq_ptr(i->active_state, "failed")) {
2096 on = ansi_highlight_red(true);
2097 off = ansi_highlight_red(false);
2098 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
2099 on = ansi_highlight_green(true);
2100 off = ansi_highlight_green(false);
2105 printf("\t Active: %s%s (%s)%s",
2107 strna(i->active_state),
2111 printf("\t Active: %s%s%s",
2113 strna(i->active_state),
2116 if (!isempty(i->result) && !streq(i->result, "success"))
2117 printf(" (Result: %s)", i->result);
2119 timestamp = (streq_ptr(i->active_state, "active") ||
2120 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
2121 (streq_ptr(i->active_state, "inactive") ||
2122 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
2123 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
2124 i->active_exit_timestamp;
2126 s1 = format_timestamp_pretty(since1, sizeof(since1), timestamp);
2127 s2 = format_timestamp(since2, sizeof(since2), timestamp);
2130 printf(" since %s; %s\n", s2, s1);
2132 printf(" since %s\n", s2);
2136 if (!i->condition_result && i->condition_timestamp > 0) {
2137 s1 = format_timestamp_pretty(since1, sizeof(since1), i->condition_timestamp);
2138 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
2141 printf("\t start condition failed at %s; %s\n", s2, s1);
2143 printf("\t start condition failed at %s\n", s2);
2147 printf("\t Device: %s\n", i->sysfs_path);
2149 printf("\t Where: %s\n", i->where);
2151 printf("\t What: %s\n", i->what);
2153 if (!strv_isempty(i->documentation)) {
2157 STRV_FOREACH(t, i->documentation) {
2159 printf("\t Docs: %s\n", *t);
2162 printf("\t %s\n", *t);
2167 printf("\tAccepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
2169 LIST_FOREACH(exec, p, i->exec) {
2173 /* Only show exited processes here */
2177 t = strv_join(p->argv, " ");
2178 printf("\t Process: %u %s=%s ", p->pid, p->name, strna(t));
2181 good = is_clean_exit_lsb(p->code, p->status, NULL);
2183 on = ansi_highlight_red(true);
2184 off = ansi_highlight_red(false);
2188 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
2190 if (p->code == CLD_EXITED) {
2193 printf("status=%i", p->status);
2195 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
2200 printf("signal=%s", signal_to_string(p->status));
2202 printf(")%s\n", off);
2204 if (i->main_pid == p->pid &&
2205 i->start_timestamp == p->start_timestamp &&
2206 i->exit_timestamp == p->start_timestamp)
2207 /* Let's not show this twice */
2210 if (p->pid == i->control_pid)
2214 if (i->main_pid > 0 || i->control_pid > 0) {
2217 if (i->main_pid > 0) {
2218 printf("Main PID: %u", (unsigned) i->main_pid);
2222 get_process_comm(i->main_pid, &t);
2227 } else if (i->exit_code > 0) {
2228 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
2230 if (i->exit_code == CLD_EXITED) {
2233 printf("status=%i", i->exit_status);
2235 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
2240 printf("signal=%s", signal_to_string(i->exit_status));
2245 if (i->main_pid > 0 && i->control_pid > 0)
2248 if (i->control_pid > 0) {
2251 printf(" Control: %u", (unsigned) i->control_pid);
2253 get_process_comm(i->control_pid, &t);
2264 printf("\t Status: \"%s\"\n", i->status_text);
2266 if (i->default_control_group) {
2269 printf("\t CGroup: %s\n", i->default_control_group);
2271 if (arg_transport != TRANSPORT_SSH) {
2281 if (i->main_pid > 0)
2282 extra[k++] = i->main_pid;
2284 if (i->control_pid > 0)
2285 extra[k++] = i->control_pid;
2287 show_cgroup_and_extra_by_spec(i->default_control_group, "\t\t ", c, false, arg_all, extra, k);
2291 if (i->id && arg_transport != TRANSPORT_SSH) {
2293 arg_all * OUTPUT_SHOW_ALL |
2294 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
2295 on_tty() * OUTPUT_COLOR |
2296 !arg_quiet * OUTPUT_WARN_CUTOFF;
2299 show_journal_by_unit(stdout,
2303 i->inactive_exit_timestamp_monotonic,
2308 if (i->need_daemon_reload)
2309 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %s daemon-reload' recommended.\n",
2310 ansi_highlight_red(true),
2311 ansi_highlight_red(false),
2312 arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
2315 static void show_unit_help(UnitStatusInfo *i) {
2320 if (!i->documentation) {
2321 log_info("Documentation for %s not known.", i->id);
2325 STRV_FOREACH(p, i->documentation) {
2327 if (startswith(*p, "man:")) {
2330 char *page = NULL, *section = NULL;
2331 const char *args[4] = { "man", NULL, NULL, NULL };
2336 if ((*p)[k-1] == ')')
2337 e = strrchr(*p, '(');
2340 page = strndup((*p) + 4, e - *p - 4);
2346 section = strndup(e + 1, *p + k - e - 2);
2360 log_error("Failed to fork: %m");
2368 execvp(args[0], (char**) args);
2369 log_error("Failed to execute man: %m");
2370 _exit(EXIT_FAILURE);
2376 wait_for_terminate(pid, NULL);
2378 log_info("Can't show: %s", *p);
2382 static int status_property(const char *name, DBusMessageIter *iter, UnitStatusInfo *i) {
2388 switch (dbus_message_iter_get_arg_type(iter)) {
2390 case DBUS_TYPE_STRING: {
2393 dbus_message_iter_get_basic(iter, &s);
2396 if (streq(name, "Id"))
2398 else if (streq(name, "LoadState"))
2400 else if (streq(name, "ActiveState"))
2401 i->active_state = s;
2402 else if (streq(name, "SubState"))
2404 else if (streq(name, "Description"))
2406 else if (streq(name, "FragmentPath"))
2407 i->fragment_path = s;
2408 else if (streq(name, "SourcePath"))
2410 else if (streq(name, "DefaultControlGroup"))
2411 i->default_control_group = s;
2412 else if (streq(name, "StatusText"))
2414 else if (streq(name, "SysFSPath"))
2416 else if (streq(name, "Where"))
2418 else if (streq(name, "What"))
2420 else if (streq(name, "Following"))
2422 else if (streq(name, "UnitFileState"))
2423 i->unit_file_state = s;
2424 else if (streq(name, "Result"))
2431 case DBUS_TYPE_BOOLEAN: {
2434 dbus_message_iter_get_basic(iter, &b);
2436 if (streq(name, "Accept"))
2438 else if (streq(name, "NeedDaemonReload"))
2439 i->need_daemon_reload = b;
2440 else if (streq(name, "ConditionResult"))
2441 i->condition_result = b;
2446 case DBUS_TYPE_UINT32: {
2449 dbus_message_iter_get_basic(iter, &u);
2451 if (streq(name, "MainPID")) {
2453 i->main_pid = (pid_t) u;
2456 } else if (streq(name, "ControlPID"))
2457 i->control_pid = (pid_t) u;
2458 else if (streq(name, "ExecMainPID")) {
2460 i->main_pid = (pid_t) u;
2461 } else if (streq(name, "NAccepted"))
2463 else if (streq(name, "NConnections"))
2464 i->n_connections = u;
2469 case DBUS_TYPE_INT32: {
2472 dbus_message_iter_get_basic(iter, &j);
2474 if (streq(name, "ExecMainCode"))
2475 i->exit_code = (int) j;
2476 else if (streq(name, "ExecMainStatus"))
2477 i->exit_status = (int) j;
2482 case DBUS_TYPE_UINT64: {
2485 dbus_message_iter_get_basic(iter, &u);
2487 if (streq(name, "ExecMainStartTimestamp"))
2488 i->start_timestamp = (usec_t) u;
2489 else if (streq(name, "ExecMainExitTimestamp"))
2490 i->exit_timestamp = (usec_t) u;
2491 else if (streq(name, "ActiveEnterTimestamp"))
2492 i->active_enter_timestamp = (usec_t) u;
2493 else if (streq(name, "InactiveEnterTimestamp"))
2494 i->inactive_enter_timestamp = (usec_t) u;
2495 else if (streq(name, "InactiveExitTimestamp"))
2496 i->inactive_exit_timestamp = (usec_t) u;
2497 else if (streq(name, "InactiveExitTimestampMonotonic"))
2498 i->inactive_exit_timestamp_monotonic = (usec_t) u;
2499 else if (streq(name, "ActiveExitTimestamp"))
2500 i->active_exit_timestamp = (usec_t) u;
2501 else if (streq(name, "ConditionTimestamp"))
2502 i->condition_timestamp = (usec_t) u;
2507 case DBUS_TYPE_ARRAY: {
2509 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
2510 startswith(name, "Exec")) {
2511 DBusMessageIter sub;
2513 dbus_message_iter_recurse(iter, &sub);
2514 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2515 ExecStatusInfo *info;
2518 if (!(info = new0(ExecStatusInfo, 1)))
2521 if (!(info->name = strdup(name))) {
2526 if ((r = exec_status_info_deserialize(&sub, info)) < 0) {
2531 LIST_PREPEND(ExecStatusInfo, exec, i->exec, info);
2533 dbus_message_iter_next(&sub);
2535 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
2536 streq(name, "Documentation")) {
2538 DBusMessageIter sub;
2540 dbus_message_iter_recurse(iter, &sub);
2541 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING) {
2545 dbus_message_iter_get_basic(&sub, &s);
2547 l = strv_append(i->documentation, s);
2551 strv_free(i->documentation);
2552 i->documentation = l;
2554 dbus_message_iter_next(&sub);
2561 case DBUS_TYPE_STRUCT: {
2563 if (streq(name, "LoadError")) {
2564 DBusMessageIter sub;
2565 const char *n, *message;
2568 dbus_message_iter_recurse(iter, &sub);
2570 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &n, true);
2574 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &message, false);
2578 if (!isempty(message))
2579 i->load_error = message;
2589 static int print_property(const char *name, DBusMessageIter *iter) {
2593 /* This is a low-level property printer, see
2594 * print_status_info() for the nicer output */
2596 if (arg_property && !strv_find(arg_property, name))
2599 switch (dbus_message_iter_get_arg_type(iter)) {
2601 case DBUS_TYPE_STRUCT: {
2602 DBusMessageIter sub;
2603 dbus_message_iter_recurse(iter, &sub);
2605 if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32 && streq(name, "Job")) {
2608 dbus_message_iter_get_basic(&sub, &u);
2611 printf("%s=%u\n", name, (unsigned) u);
2613 printf("%s=\n", name);
2616 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "Unit")) {
2619 dbus_message_iter_get_basic(&sub, &s);
2621 if (arg_all || s[0])
2622 printf("%s=%s\n", name, s);
2625 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "LoadError")) {
2626 const char *a = NULL, *b = NULL;
2628 if (bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &a, true) >= 0)
2629 bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &b, false);
2631 if (arg_all || !isempty(a) || !isempty(b))
2632 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
2640 case DBUS_TYPE_ARRAY:
2642 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "EnvironmentFiles")) {
2643 DBusMessageIter sub, sub2;
2645 dbus_message_iter_recurse(iter, &sub);
2646 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2650 dbus_message_iter_recurse(&sub, &sub2);
2652 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
2653 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) >= 0)
2654 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
2656 dbus_message_iter_next(&sub);
2661 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Paths")) {
2662 DBusMessageIter sub, sub2;
2664 dbus_message_iter_recurse(iter, &sub);
2665 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2666 const char *type, *path;
2668 dbus_message_iter_recurse(&sub, &sub2);
2670 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
2671 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
2672 printf("%s=%s\n", type, path);
2674 dbus_message_iter_next(&sub);
2679 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Timers")) {
2680 DBusMessageIter sub, sub2;
2682 dbus_message_iter_recurse(iter, &sub);
2683 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2685 uint64_t value, next_elapse;
2687 dbus_message_iter_recurse(&sub, &sub2);
2689 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &base, true) >= 0 &&
2690 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &value, true) >= 0 &&
2691 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &next_elapse, false) >= 0) {
2692 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
2694 printf("%s={ value=%s ; next_elapse=%s }\n",
2696 format_timespan(timespan1, sizeof(timespan1), value),
2697 format_timespan(timespan2, sizeof(timespan2), next_elapse));
2700 dbus_message_iter_next(&sub);
2705 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "ControlGroupAttributes")) {
2706 DBusMessageIter sub, sub2;
2708 dbus_message_iter_recurse(iter, &sub);
2709 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2710 const char *controller, *attr, *value;
2712 dbus_message_iter_recurse(&sub, &sub2);
2714 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &controller, true) >= 0 &&
2715 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &attr, true) >= 0 &&
2716 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &value, false) >= 0) {
2718 printf("ControlGroupAttribute={ controller=%s ; attribute=%s ; value=\"%s\" }\n",
2724 dbus_message_iter_next(&sub);
2729 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && startswith(name, "Exec")) {
2730 DBusMessageIter sub;
2732 dbus_message_iter_recurse(iter, &sub);
2733 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2734 ExecStatusInfo info;
2737 if (exec_status_info_deserialize(&sub, &info) >= 0) {
2738 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
2741 t = strv_join(info.argv, " ");
2743 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
2747 yes_no(info.ignore),
2748 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
2749 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
2750 (unsigned) info. pid,
2751 sigchld_code_to_string(info.code),
2753 info.code == CLD_EXITED ? "" : "/",
2754 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
2760 strv_free(info.argv);
2762 dbus_message_iter_next(&sub);
2771 if (generic_print_property(name, iter, arg_all) > 0)
2775 printf("%s=[unprintable]\n", name);
2780 static int show_one(const char *verb, DBusConnection *bus, const char *path, bool show_properties, bool *new_line) {
2781 DBusMessage *reply = NULL;
2782 const char *interface = "";
2784 DBusMessageIter iter, sub, sub2, sub3;
2785 UnitStatusInfo info;
2793 r = bus_method_call_with_reply (
2795 "org.freedesktop.systemd1",
2797 "org.freedesktop.DBus.Properties",
2801 DBUS_TYPE_STRING, &interface,
2806 if (!dbus_message_iter_init(reply, &iter) ||
2807 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
2808 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
2809 log_error("Failed to parse reply.");
2814 dbus_message_iter_recurse(&iter, &sub);
2821 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
2824 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_DICT_ENTRY) {
2825 log_error("Failed to parse reply.");
2830 dbus_message_iter_recurse(&sub, &sub2);
2832 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0) {
2833 log_error("Failed to parse reply.");
2838 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
2839 log_error("Failed to parse reply.");
2844 dbus_message_iter_recurse(&sub2, &sub3);
2846 if (show_properties)
2847 r = print_property(name, &sub3);
2849 r = status_property(name, &sub3, &info);
2852 log_error("Failed to parse reply.");
2857 dbus_message_iter_next(&sub);
2862 if (!show_properties) {
2863 if (streq(verb, "help"))
2864 show_unit_help(&info);
2866 print_status_info(&info);
2869 strv_free(info.documentation);
2871 if (!streq_ptr(info.active_state, "active") &&
2872 !streq_ptr(info.active_state, "reloading") &&
2873 streq(verb, "status"))
2874 /* According to LSB: "program not running" */
2877 while ((p = info.exec)) {
2878 LIST_REMOVE(ExecStatusInfo, exec, info.exec, p);
2879 exec_status_info_free(p);
2884 dbus_message_unref(reply);
2889 static int show_one_by_pid(const char *verb, DBusConnection *bus, uint32_t pid, bool *new_line) {
2890 DBusMessage *reply = NULL;
2891 const char *path = NULL;
2895 dbus_error_init(&error);
2897 r = bus_method_call_with_reply (
2899 "org.freedesktop.systemd1",
2900 "/org/freedesktop/systemd1",
2901 "org.freedesktop.systemd1.Manager",
2905 DBUS_TYPE_UINT32, &pid,
2910 if (!dbus_message_get_args(reply, &error,
2911 DBUS_TYPE_OBJECT_PATH, &path,
2912 DBUS_TYPE_INVALID)) {
2913 log_error("Failed to parse reply: %s", bus_error_message(&error));
2918 r = show_one(verb, bus, path, false, new_line);
2922 dbus_message_unref(reply);
2924 dbus_error_free(&error);
2929 static int show(DBusConnection *bus, char **args) {
2931 bool show_properties, new_line = false;
2937 show_properties = streq(args[0], "show");
2939 if (show_properties)
2940 pager_open_if_enabled();
2942 if (show_properties && strv_length(args) <= 1) {
2943 /* If not argument is specified inspect the manager
2946 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line);
2949 STRV_FOREACH(name, args+1) {
2952 if (safe_atou32(*name, &id) < 0) {
2954 /* Interpret as unit name */
2956 n = unit_name_mangle(*name);
2957 p = unit_dbus_path_from_name(n ? n : *name);
2962 r = show_one(args[0], bus, p, show_properties, &new_line);
2968 } else if (show_properties) {
2970 /* Interpret as job id */
2973 if (asprintf(&p, "/org/freedesktop/systemd1/job/%u", id) < 0)
2976 r = show_one(args[0], bus, p, show_properties, &new_line);
2984 /* Interpret as PID */
2986 r = show_one_by_pid(args[0], bus, id, &new_line);
2995 static int dump(DBusConnection *bus, char **args) {
2996 DBusMessage *reply = NULL;
3001 dbus_error_init(&error);
3003 pager_open_if_enabled();
3005 r = bus_method_call_with_reply (
3007 "org.freedesktop.systemd1",
3008 "/org/freedesktop/systemd1",
3009 "org.freedesktop.systemd1.Manager",
3017 if (!dbus_message_get_args(reply, &error,
3018 DBUS_TYPE_STRING, &text,
3019 DBUS_TYPE_INVALID)) {
3020 log_error("Failed to parse reply: %s", bus_error_message(&error));
3025 fputs(text, stdout);
3029 dbus_message_unref(reply);
3031 dbus_error_free(&error);
3036 static int snapshot(DBusConnection *bus, char **args) {
3037 DBusMessage *reply = NULL;
3040 dbus_bool_t cleanup = FALSE;
3041 DBusMessageIter iter, sub;
3043 *name = "", *path, *id,
3044 *interface = "org.freedesktop.systemd1.Unit",
3048 dbus_error_init(&error);
3050 if (strv_length(args) > 1)
3053 n = unit_name_mangle(name);
3054 r = bus_method_call_with_reply (
3056 "org.freedesktop.systemd1",
3057 "/org/freedesktop/systemd1",
3058 "org.freedesktop.systemd1.Manager",
3062 DBUS_TYPE_STRING, n ? (const char**) &n : &name,
3063 DBUS_TYPE_BOOLEAN, &cleanup,
3069 if (!dbus_message_get_args(reply, &error,
3070 DBUS_TYPE_OBJECT_PATH, &path,
3071 DBUS_TYPE_INVALID)) {
3072 log_error("Failed to parse reply: %s", bus_error_message(&error));
3077 dbus_message_unref(reply);
3078 r = bus_method_call_with_reply (
3080 "org.freedesktop.systemd1",
3082 "org.freedesktop.DBus.Properties",
3086 DBUS_TYPE_STRING, &interface,
3087 DBUS_TYPE_STRING, &property,
3092 if (!dbus_message_iter_init(reply, &iter) ||
3093 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3094 log_error("Failed to parse reply.");
3099 dbus_message_iter_recurse(&iter, &sub);
3101 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
3102 log_error("Failed to parse reply.");
3107 dbus_message_iter_get_basic(&sub, &id);
3114 dbus_message_unref(reply);
3116 dbus_error_free(&error);
3121 static int delete_snapshot(DBusConnection *bus, char **args) {
3122 DBusMessage *reply = NULL;
3129 dbus_error_init(&error);
3131 STRV_FOREACH(name, args+1) {
3132 const char *path = NULL;
3135 n = unit_name_mangle(*name);
3136 r = bus_method_call_with_reply (
3138 "org.freedesktop.systemd1",
3139 "/org/freedesktop/systemd1",
3140 "org.freedesktop.systemd1.Manager",
3144 DBUS_TYPE_STRING, n ? &n : name,
3150 if (!dbus_message_get_args(reply, &error,
3151 DBUS_TYPE_OBJECT_PATH, &path,
3152 DBUS_TYPE_INVALID)) {
3153 log_error("Failed to parse reply: %s", bus_error_message(&error));
3155 dbus_message_unref(reply);
3156 dbus_error_free(&error);
3159 dbus_message_unref(reply);
3161 r = bus_method_call_with_reply (
3163 "org.freedesktop.systemd1",
3165 "org.freedesktop.systemd1.Snapshot",
3178 static int daemon_reload(DBusConnection *bus, char **args) {
3183 if (arg_action == ACTION_RELOAD)
3185 else if (arg_action == ACTION_REEXEC)
3186 method = "Reexecute";
3188 assert(arg_action == ACTION_SYSTEMCTL);
3191 streq(args[0], "clear-jobs") ||
3192 streq(args[0], "cancel") ? "ClearJobs" :
3193 streq(args[0], "daemon-reexec") ? "Reexecute" :
3194 streq(args[0], "reset-failed") ? "ResetFailed" :
3195 streq(args[0], "halt") ? "Halt" :
3196 streq(args[0], "poweroff") ? "PowerOff" :
3197 streq(args[0], "reboot") ? "Reboot" :
3198 streq(args[0], "kexec") ? "KExec" :
3199 streq(args[0], "exit") ? "Exit" :
3200 /* "daemon-reload" */ "Reload";
3203 r = bus_method_call_with_reply (
3205 "org.freedesktop.systemd1",
3206 "/org/freedesktop/systemd1",
3207 "org.freedesktop.systemd1.Manager",
3213 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
3214 /* There's always a fallback possible for
3215 * legacy actions. */
3217 else if (r == -ETIMEDOUT && streq(method, "Reexecute"))
3218 /* On reexecution, we expect a disconnect, not
3222 log_error("Failed to issue method call: %s", bus_error_message(&error));
3223 dbus_error_free(&error);
3228 static int reset_failed(DBusConnection *bus, char **args) {
3232 if (strv_length(args) <= 1)
3233 return daemon_reload(bus, args);
3235 STRV_FOREACH(name, args+1) {
3236 n = unit_name_mangle(*name);
3237 r = bus_method_call_with_reply (
3239 "org.freedesktop.systemd1",
3240 "/org/freedesktop/systemd1",
3241 "org.freedesktop.systemd1.Manager",
3245 DBUS_TYPE_STRING, n ? &n : name,
3256 static int show_enviroment(DBusConnection *bus, char **args) {
3257 DBusMessage *reply = NULL;
3258 DBusMessageIter iter, sub, sub2;
3261 *interface = "org.freedesktop.systemd1.Manager",
3262 *property = "Environment";
3264 pager_open_if_enabled();
3266 r = bus_method_call_with_reply (
3268 "org.freedesktop.systemd1",
3269 "/org/freedesktop/systemd1",
3270 "org.freedesktop.DBus.Properties",
3274 DBUS_TYPE_STRING, &interface,
3275 DBUS_TYPE_STRING, &property,
3280 if (!dbus_message_iter_init(reply, &iter) ||
3281 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3282 log_error("Failed to parse reply.");
3287 dbus_message_iter_recurse(&iter, &sub);
3289 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_ARRAY ||
3290 dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_STRING) {
3291 log_error("Failed to parse reply.");
3296 dbus_message_iter_recurse(&sub, &sub2);
3298 while (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_INVALID) {
3301 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
3302 log_error("Failed to parse reply.");
3307 dbus_message_iter_get_basic(&sub2, &text);
3308 printf("%s\n", text);
3310 dbus_message_iter_next(&sub2);
3317 dbus_message_unref(reply);
3322 static int switch_root(DBusConnection *bus, char **args) {
3324 const char *root, *init;
3326 l = strv_length(args);
3327 if (l < 2 || l > 3) {
3328 log_error("Wrong number of arguments.");
3333 init = l >= 3 ? args[2] : "";
3335 return bus_method_call_with_reply (
3337 "org.freedesktop.systemd1",
3338 "/org/freedesktop/systemd1",
3339 "org.freedesktop.systemd1.Manager",
3343 DBUS_TYPE_STRING, &root,
3344 DBUS_TYPE_STRING, &init,
3348 static int set_environment(DBusConnection *bus, char **args) {
3349 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
3352 DBusMessageIter iter;
3357 dbus_error_init(&error);
3359 method = streq(args[0], "set-environment")
3361 : "UnsetEnvironment";
3363 m = dbus_message_new_method_call(
3364 "org.freedesktop.systemd1",
3365 "/org/freedesktop/systemd1",
3366 "org.freedesktop.systemd1.Manager",
3371 dbus_message_iter_init_append(m, &iter);
3373 r = bus_append_strv_iter(&iter, args + 1);
3377 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3379 log_error("Failed to issue method call: %s", bus_error_message(&error));
3387 dbus_error_free(&error);
3391 static int enable_sysv_units(char **args) {
3394 #if defined (HAVE_SYSV_COMPAT) && (defined(TARGET_FEDORA) || defined(TARGET_MANDRIVA) || defined(TARGET_SUSE) || defined(TARGET_ALTLINUX) || defined(TARGET_MAGEIA))
3395 const char *verb = args[0];
3396 unsigned f = 1, t = 1;
3399 if (arg_scope != UNIT_FILE_SYSTEM)
3402 if (!streq(verb, "enable") &&
3403 !streq(verb, "disable") &&
3404 !streq(verb, "is-enabled"))
3407 /* Processes all SysV units, and reshuffles the array so that
3408 * afterwards only the native units remain */
3411 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, NULL, NULL, NULL);
3416 for (f = 1; args[f]; f++) {
3419 bool found_native = false, found_sysv;
3421 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
3422 char **k, *l, *q = NULL;
3429 if (!endswith(name, ".service"))
3432 if (path_is_absolute(name))
3435 STRV_FOREACH(k, paths.unit_path) {
3438 if (!isempty(arg_root))
3439 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
3441 asprintf(&p, "%s/%s", *k, name);
3448 found_native = access(p, F_OK) >= 0;
3459 if (!isempty(arg_root))
3460 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
3462 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
3468 p[strlen(p) - sizeof(".service") + 1] = 0;
3469 found_sysv = access(p, F_OK) >= 0;
3476 /* Mark this entry, so that we don't try enabling it as native unit */
3477 args[f] = (char*) "";
3479 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
3481 if (!isempty(arg_root))
3482 argv[c++] = q = strappend("--root=", arg_root);
3484 argv[c++] = path_get_file_name(p);
3486 streq(verb, "enable") ? "on" :
3487 streq(verb, "disable") ? "off" : "--level=5";
3490 l = strv_join((char**)argv, " ");
3498 log_info("Executing %s", l);
3503 log_error("Failed to fork: %m");
3508 } else if (pid == 0) {
3511 execv(argv[0], (char**) argv);
3512 _exit(EXIT_FAILURE);
3518 j = wait_for_terminate(pid, &status);
3520 log_error("Failed to wait for child: %s", strerror(-r));
3525 if (status.si_code == CLD_EXITED) {
3526 if (streq(verb, "is-enabled")) {
3527 if (status.si_status == 0) {
3536 } else if (status.si_status != 0) {
3547 lookup_paths_free(&paths);
3549 /* Drop all SysV units */
3550 for (f = 1, t = 1; args[f]; f++) {
3552 if (isempty(args[f]))
3555 args[t++] = args[f];
3564 static int mangle_names(char **original_names, char ***mangled_names) {
3565 char **i, **l, **name;
3567 l = new(char*, strv_length(original_names) + 1);
3572 STRV_FOREACH(name, original_names) {
3574 /* When enabling units qualified path names are OK,
3575 * too, hence allow them explicitly. */
3580 *i = unit_name_mangle(*name);
3596 static int enable_unit(DBusConnection *bus, char **args) {
3597 const char *verb = args[0];
3598 UnitFileChange *changes = NULL;
3599 unsigned n_changes = 0, i;
3600 int carries_install_info = -1;
3601 DBusMessage *m = NULL, *reply = NULL;
3604 char **mangled_names = NULL;
3606 r = enable_sysv_units(args);
3613 dbus_error_init(&error);
3615 if (!bus || avoid_bus()) {
3616 if (streq(verb, "enable")) {
3617 r = unit_file_enable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3618 carries_install_info = r;
3619 } else if (streq(verb, "disable"))
3620 r = unit_file_disable(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3621 else if (streq(verb, "reenable")) {
3622 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3623 carries_install_info = r;
3624 } else if (streq(verb, "link"))
3625 r = unit_file_link(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3626 else if (streq(verb, "preset")) {
3627 r = unit_file_preset(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3628 carries_install_info = r;
3629 } else if (streq(verb, "mask"))
3630 r = unit_file_mask(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3631 else if (streq(verb, "unmask"))
3632 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3634 assert_not_reached("Unknown verb");
3637 log_error("Operation failed: %s", strerror(-r));
3642 for (i = 0; i < n_changes; i++) {
3643 if (changes[i].type == UNIT_FILE_SYMLINK)
3644 log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
3646 log_info("rm '%s'", changes[i].path);
3653 bool send_force = true, expect_carries_install_info = false;
3655 DBusMessageIter iter, sub, sub2;
3657 if (streq(verb, "enable")) {
3658 method = "EnableUnitFiles";
3659 expect_carries_install_info = true;
3660 } else if (streq(verb, "disable")) {
3661 method = "DisableUnitFiles";
3663 } else if (streq(verb, "reenable")) {
3664 method = "ReenableUnitFiles";
3665 expect_carries_install_info = true;
3666 } else if (streq(verb, "link"))
3667 method = "LinkUnitFiles";
3668 else if (streq(verb, "preset")) {
3669 method = "PresetUnitFiles";
3670 expect_carries_install_info = true;
3671 } else if (streq(verb, "mask"))
3672 method = "MaskUnitFiles";
3673 else if (streq(verb, "unmask")) {
3674 method = "UnmaskUnitFiles";
3677 assert_not_reached("Unknown verb");
3679 m = dbus_message_new_method_call(
3680 "org.freedesktop.systemd1",
3681 "/org/freedesktop/systemd1",
3682 "org.freedesktop.systemd1.Manager",
3689 dbus_message_iter_init_append(m, &iter);
3691 r = mangle_names(args+1, &mangled_names);
3695 r = bus_append_strv_iter(&iter, mangled_names);
3697 log_error("Failed to append unit files.");
3702 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &a)) {
3703 log_error("Failed to append runtime boolean.");
3711 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b)) {
3712 log_error("Failed to append force boolean.");
3718 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3720 log_error("Failed to issue method call: %s", bus_error_message(&error));
3725 if (!dbus_message_iter_init(reply, &iter)) {
3726 log_error("Failed to initialize iterator.");
3730 if (expect_carries_install_info) {
3731 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &b, true);
3733 log_error("Failed to parse reply.");
3737 carries_install_info = b;
3740 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3741 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
3742 log_error("Failed to parse reply.");
3747 dbus_message_iter_recurse(&iter, &sub);
3748 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
3749 const char *type, *path, *source;
3751 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
3752 log_error("Failed to parse reply.");
3757 dbus_message_iter_recurse(&sub, &sub2);
3759 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
3760 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
3761 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &source, false) < 0) {
3762 log_error("Failed to parse reply.");
3768 if (streq(type, "symlink"))
3769 log_info("ln -s '%s' '%s'", source, path);
3771 log_info("rm '%s'", path);
3774 dbus_message_iter_next(&sub);
3777 /* Try to reload if enabeld */
3779 r = daemon_reload(bus, args);
3782 if (carries_install_info == 0)
3783 log_warning("The unit files have no [Install] section. They are not meant to be enabled using systemctl.");
3787 dbus_message_unref(m);
3790 dbus_message_unref(reply);
3792 unit_file_changes_free(changes, n_changes);
3794 dbus_error_free(&error);
3796 strv_free(mangled_names);
3801 static int unit_is_enabled(DBusConnection *bus, char **args) {
3804 DBusMessage *reply = NULL;
3808 dbus_error_init(&error);
3810 r = enable_sysv_units(args);
3816 if (!bus || avoid_bus()) {
3818 STRV_FOREACH(name, args+1) {
3819 UnitFileState state;
3821 state = unit_file_get_state(arg_scope, arg_root, *name);
3827 if (state == UNIT_FILE_ENABLED ||
3828 state == UNIT_FILE_ENABLED_RUNTIME ||
3829 state == UNIT_FILE_STATIC)
3833 puts(unit_file_state_to_string(state));
3837 STRV_FOREACH(name, args+1) {
3840 r = bus_method_call_with_reply (
3842 "org.freedesktop.systemd1",
3843 "/org/freedesktop/systemd1",
3844 "org.freedesktop.systemd1.Manager",
3848 DBUS_TYPE_STRING, name,
3853 if (!dbus_message_get_args(reply, &error,
3854 DBUS_TYPE_STRING, &s,
3855 DBUS_TYPE_INVALID)) {
3856 log_error("Failed to parse reply: %s", bus_error_message(&error));
3861 dbus_message_unref(reply);
3864 if (streq(s, "enabled") ||
3865 streq(s, "enabled-runtime") ||
3874 r = enabled ? 0 : 1;
3878 dbus_message_unref(reply);
3880 dbus_error_free(&error);
3884 static int systemctl_help(void) {
3886 pager_open_if_enabled();
3888 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
3889 "Query or send control commands to the systemd manager.\n\n"
3890 " -h --help Show this help\n"
3891 " --version Show package version\n"
3892 " -t --type=TYPE List only units of a particular type\n"
3893 " -p --property=NAME Show only properties by this name\n"
3894 " -a --all Show all units/properties, including dead/empty ones\n"
3895 " --failed Show only failed units\n"
3896 " --full Don't ellipsize unit names on output\n"
3897 " --fail When queueing a new job, fail if conflicting jobs are\n"
3899 " --ignore-dependencies\n"
3900 " When queueing a new job, ignore all its dependencies\n"
3901 " --kill-who=WHO Who to send signal to\n"
3902 " -s --signal=SIGNAL Which signal to send\n"
3903 " -H --host=[USER@]HOST\n"
3904 " Show information for remote host\n"
3905 " -P --privileged Acquire privileges before execution\n"
3906 " -q --quiet Suppress output\n"
3907 " --no-block Do not wait until operation finished\n"
3908 " --no-wall Don't send wall message before halt/power-off/reboot\n"
3909 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
3911 " --no-legend Do not print a legend (column headers and hints)\n"
3912 " --no-pager Do not pipe output into a pager\n"
3913 " --no-ask-password\n"
3914 " Do not ask for system passwords\n"
3915 " --order When generating graph for dot, show only order\n"
3916 " --require When generating graph for dot, show only requirement\n"
3917 " --system Connect to system manager\n"
3918 " --user Connect to user service manager\n"
3919 " --global Enable/disable unit files globally\n"
3920 " -f --force When enabling unit files, override existing symlinks\n"
3921 " When shutting down, execute action immediately\n"
3922 " --root=PATH Enable unit files in the specified root directory\n"
3923 " --runtime Enable unit files only temporarily until next reboot\n"
3924 " -n --lines=INTEGER Journal entries to show\n"
3925 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
3926 " verbose, export, json, json-pretty, json-sse, cat)\n\n"
3928 " list-units List loaded units\n"
3929 " start [NAME...] Start (activate) one or more units\n"
3930 " stop [NAME...] Stop (deactivate) one or more units\n"
3931 " reload [NAME...] Reload one or more units\n"
3932 " restart [NAME...] Start or restart one or more units\n"
3933 " try-restart [NAME...] Restart one or more units if active\n"
3934 " reload-or-restart [NAME...] Reload one or more units is possible,\n"
3935 " otherwise start or restart\n"
3936 " reload-or-try-restart [NAME...] Reload one or more units is possible,\n"
3937 " otherwise restart if active\n"
3938 " isolate [NAME] Start one unit and stop all others\n"
3939 " kill [NAME...] Send signal to processes of a unit\n"
3940 " is-active [NAME...] Check whether units are active\n"
3941 " status [NAME...|PID...] Show runtime status of one or more units\n"
3942 " show [NAME...|JOB...] Show properties of one or more\n"
3943 " units/jobs or the manager\n"
3944 " help [NAME...|PID...] Show manual for one or more units\n"
3945 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
3947 " load [NAME...] Load one or more units\n\n"
3948 "Unit File Commands:\n"
3949 " list-unit-files List installed unit files\n"
3950 " enable [NAME...] Enable one or more unit files\n"
3951 " disable [NAME...] Disable one or more unit files\n"
3952 " reenable [NAME...] Reenable one or more unit files\n"
3953 " preset [NAME...] Enable/disable one or more unit files\n"
3954 " based on preset configuration\n"
3955 " mask [NAME...] Mask one or more units\n"
3956 " unmask [NAME...] Unmask one or more units\n"
3957 " link [PATH...] Link one or more units files into\n"
3958 " the search path\n"
3959 " is-enabled [NAME...] Check whether unit files are enabled\n\n"
3961 " list-jobs List jobs\n"
3962 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
3963 "Status Commands:\n"
3964 " dump Dump server status\n"
3965 " dot Dump dependency graph for dot(1)\n\n"
3966 "Snapshot Commands:\n"
3967 " snapshot [NAME] Create a snapshot\n"
3968 " delete [NAME...] Remove one or more snapshots\n\n"
3969 "Environment Commands:\n"
3970 " show-environment Dump environment\n"
3971 " set-environment [NAME=VALUE...] Set one or more environment variables\n"
3972 " unset-environment [NAME...] Unset one or more environment variables\n\n"
3973 "Manager Lifecycle Commands:\n"
3974 " daemon-reload Reload systemd manager configuration\n"
3975 " daemon-reexec Reexecute systemd manager\n\n"
3976 "System Commands:\n"
3977 " default Enter system default mode\n"
3978 " rescue Enter system rescue mode\n"
3979 " emergency Enter system emergency mode\n"
3980 " halt Shut down and halt the system\n"
3981 " poweroff Shut down and power-off the system\n"
3982 " reboot Shut down and reboot the system\n"
3983 " kexec Shut down and reboot the system with kexec\n"
3984 " exit Request user instance exit\n"
3985 " switch-root [ROOT] [INIT] Change to a different root file system\n"
3986 " suspend Suspend the system\n"
3987 " hibernate Hibernate the system\n"
3988 " hybrid-sleep Hibernate and suspend the system\n",
3989 program_invocation_short_name);
3994 static int halt_help(void) {
3996 printf("%s [OPTIONS...]\n\n"
3997 "%s the system.\n\n"
3998 " --help Show this help\n"
3999 " --halt Halt the machine\n"
4000 " -p --poweroff Switch off the machine\n"
4001 " --reboot Reboot the machine\n"
4002 " -f --force Force immediate halt/power-off/reboot\n"
4003 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
4004 " -d --no-wtmp Don't write wtmp record\n"
4005 " --no-wall Don't send wall message before halt/power-off/reboot\n",
4006 program_invocation_short_name,
4007 arg_action == ACTION_REBOOT ? "Reboot" :
4008 arg_action == ACTION_POWEROFF ? "Power off" :
4014 static int shutdown_help(void) {
4016 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
4017 "Shut down the system.\n\n"
4018 " --help Show this help\n"
4019 " -H --halt Halt the machine\n"
4020 " -P --poweroff Power-off the machine\n"
4021 " -r --reboot Reboot the machine\n"
4022 " -h Equivalent to --poweroff, overridden by --halt\n"
4023 " -k Don't halt/power-off/reboot, just send warnings\n"
4024 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4025 " -c Cancel a pending shutdown\n",
4026 program_invocation_short_name);
4031 static int telinit_help(void) {
4033 printf("%s [OPTIONS...] {COMMAND}\n\n"
4034 "Send control commands to the init daemon.\n\n"
4035 " --help Show this help\n"
4036 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
4038 " 0 Power-off the machine\n"
4039 " 6 Reboot the machine\n"
4040 " 2, 3, 4, 5 Start runlevelX.target unit\n"
4041 " 1, s, S Enter rescue mode\n"
4042 " q, Q Reload init daemon configuration\n"
4043 " u, U Reexecute init daemon\n",
4044 program_invocation_short_name);
4049 static int runlevel_help(void) {
4051 printf("%s [OPTIONS...]\n\n"
4052 "Prints the previous and current runlevel of the init system.\n\n"
4053 " --help Show this help\n",
4054 program_invocation_short_name);
4059 static int systemctl_parse_argv(int argc, char *argv[]) {
4063 ARG_IGNORE_DEPENDENCIES,
4078 ARG_NO_ASK_PASSWORD,
4084 static const struct option options[] = {
4085 { "help", no_argument, NULL, 'h' },
4086 { "version", no_argument, NULL, ARG_VERSION },
4087 { "type", required_argument, NULL, 't' },
4088 { "property", required_argument, NULL, 'p' },
4089 { "all", no_argument, NULL, 'a' },
4090 { "failed", no_argument, NULL, ARG_FAILED },
4091 { "full", no_argument, NULL, ARG_FULL },
4092 { "fail", no_argument, NULL, ARG_FAIL },
4093 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
4094 { "user", no_argument, NULL, ARG_USER },
4095 { "system", no_argument, NULL, ARG_SYSTEM },
4096 { "global", no_argument, NULL, ARG_GLOBAL },
4097 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
4098 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
4099 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
4100 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4101 { "quiet", no_argument, NULL, 'q' },
4102 { "order", no_argument, NULL, ARG_ORDER },
4103 { "require", no_argument, NULL, ARG_REQUIRE },
4104 { "root", required_argument, NULL, ARG_ROOT },
4105 { "force", no_argument, NULL, ARG_FORCE },
4106 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
4107 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
4108 { "signal", required_argument, NULL, 's' },
4109 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
4110 { "host", required_argument, NULL, 'H' },
4111 { "privileged",no_argument, NULL, 'P' },
4112 { "runtime", no_argument, NULL, ARG_RUNTIME },
4113 { "lines", required_argument, NULL, 'n' },
4114 { "output", required_argument, NULL, 'o' },
4115 { NULL, 0, NULL, 0 }
4123 while ((c = getopt_long(argc, argv, "ht:p:aqfs:H:Pn:o:", options, NULL)) >= 0) {
4132 puts(PACKAGE_STRING);
4134 puts(SYSTEMD_FEATURES);
4138 if (unit_type_from_string(optarg) >= 0) {
4142 if (unit_load_state_from_string(optarg) >= 0) {
4143 arg_load_state = optarg;
4146 log_error("Unkown unit type or load state '%s'.",
4152 if (!(l = strv_append(arg_property, optarg)))
4155 strv_free(arg_property);
4158 /* If the user asked for a particular
4159 * property, show it to him, even if it is
4170 arg_job_mode = "fail";
4173 case ARG_IGNORE_DEPENDENCIES:
4174 arg_job_mode = "ignore-dependencies";
4178 arg_scope = UNIT_FILE_USER;
4182 arg_scope = UNIT_FILE_SYSTEM;
4186 arg_scope = UNIT_FILE_GLOBAL;
4190 arg_no_block = true;
4194 arg_no_legend = true;
4198 arg_no_pager = true;
4206 arg_dot = DOT_ORDER;
4210 arg_dot = DOT_REQUIRE;
4238 arg_no_reload = true;
4242 arg_kill_who = optarg;
4246 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
4247 log_error("Failed to parse signal string %s.", optarg);
4252 case ARG_NO_ASK_PASSWORD:
4253 arg_ask_password = false;
4257 arg_transport = TRANSPORT_POLKIT;
4261 arg_transport = TRANSPORT_SSH;
4270 if (safe_atou(optarg, &arg_lines) < 0) {
4271 log_error("Failed to parse lines '%s'", optarg);
4277 arg_output = output_mode_from_string(optarg);
4278 if (arg_output < 0) {
4279 log_error("Unknown output '%s'.", optarg);
4288 log_error("Unknown option code '%c'.", c);
4293 if (arg_transport != TRANSPORT_NORMAL && arg_scope != UNIT_FILE_SYSTEM) {
4294 log_error("Cannot access user instance remotely.");
4301 static int halt_parse_argv(int argc, char *argv[]) {
4310 static const struct option options[] = {
4311 { "help", no_argument, NULL, ARG_HELP },
4312 { "halt", no_argument, NULL, ARG_HALT },
4313 { "poweroff", no_argument, NULL, 'p' },
4314 { "reboot", no_argument, NULL, ARG_REBOOT },
4315 { "force", no_argument, NULL, 'f' },
4316 { "wtmp-only", no_argument, NULL, 'w' },
4317 { "no-wtmp", no_argument, NULL, 'd' },
4318 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4319 { NULL, 0, NULL, 0 }
4327 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
4328 if (runlevel == '0' || runlevel == '6')
4331 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
4339 arg_action = ACTION_HALT;
4343 if (arg_action != ACTION_REBOOT)
4344 arg_action = ACTION_POWEROFF;
4348 arg_action = ACTION_REBOOT;
4370 /* Compatibility nops */
4377 log_error("Unknown option code '%c'.", c);
4382 if (optind < argc) {
4383 log_error("Too many arguments.");
4390 static int parse_time_spec(const char *t, usec_t *_u) {
4394 if (streq(t, "now"))
4396 else if (!strchr(t, ':')) {
4399 if (safe_atou64(t, &u) < 0)
4402 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
4411 hour = strtol(t, &e, 10);
4412 if (errno != 0 || *e != ':' || hour < 0 || hour > 23)
4415 minute = strtol(e+1, &e, 10);
4416 if (errno != 0 || *e != 0 || minute < 0 || minute > 59)
4419 n = now(CLOCK_REALTIME);
4420 s = (time_t) (n / USEC_PER_SEC);
4423 assert_se(localtime_r(&s, &tm));
4425 tm.tm_hour = (int) hour;
4426 tm.tm_min = (int) minute;
4429 assert_se(s = mktime(&tm));
4431 *_u = (usec_t) s * USEC_PER_SEC;
4434 *_u += USEC_PER_DAY;
4440 static int shutdown_parse_argv(int argc, char *argv[]) {
4447 static const struct option options[] = {
4448 { "help", no_argument, NULL, ARG_HELP },
4449 { "halt", no_argument, NULL, 'H' },
4450 { "poweroff", no_argument, NULL, 'P' },
4451 { "reboot", no_argument, NULL, 'r' },
4452 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
4453 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4454 { NULL, 0, NULL, 0 }
4462 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
4470 arg_action = ACTION_HALT;
4474 arg_action = ACTION_POWEROFF;
4479 arg_action = ACTION_KEXEC;
4481 arg_action = ACTION_REBOOT;
4485 arg_action = ACTION_KEXEC;
4489 if (arg_action != ACTION_HALT)
4490 arg_action = ACTION_POWEROFF;
4503 /* Compatibility nops */
4507 arg_action = ACTION_CANCEL_SHUTDOWN;
4514 log_error("Unknown option code '%c'.", c);
4519 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
4520 r = parse_time_spec(argv[optind], &arg_when);
4522 log_error("Failed to parse time specification: %s", argv[optind]);
4526 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
4528 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
4529 /* No time argument for shutdown cancel */
4530 arg_wall = argv + optind;
4531 else if (argc > optind + 1)
4532 /* We skip the time argument */
4533 arg_wall = argv + optind + 1;
4540 static int telinit_parse_argv(int argc, char *argv[]) {
4547 static const struct option options[] = {
4548 { "help", no_argument, NULL, ARG_HELP },
4549 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4550 { NULL, 0, NULL, 0 }
4553 static const struct {
4557 { '0', ACTION_POWEROFF },
4558 { '6', ACTION_REBOOT },
4559 { '1', ACTION_RESCUE },
4560 { '2', ACTION_RUNLEVEL2 },
4561 { '3', ACTION_RUNLEVEL3 },
4562 { '4', ACTION_RUNLEVEL4 },
4563 { '5', ACTION_RUNLEVEL5 },
4564 { 's', ACTION_RESCUE },
4565 { 'S', ACTION_RESCUE },
4566 { 'q', ACTION_RELOAD },
4567 { 'Q', ACTION_RELOAD },
4568 { 'u', ACTION_REEXEC },
4569 { 'U', ACTION_REEXEC }
4578 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4593 log_error("Unknown option code '%c'.", c);
4598 if (optind >= argc) {
4603 if (optind + 1 < argc) {
4604 log_error("Too many arguments.");
4608 if (strlen(argv[optind]) != 1) {
4609 log_error("Expected single character argument.");
4613 for (i = 0; i < ELEMENTSOF(table); i++)
4614 if (table[i].from == argv[optind][0])
4617 if (i >= ELEMENTSOF(table)) {
4618 log_error("Unknown command '%s'.", argv[optind]);
4622 arg_action = table[i].to;
4629 static int runlevel_parse_argv(int argc, char *argv[]) {
4635 static const struct option options[] = {
4636 { "help", no_argument, NULL, ARG_HELP },
4637 { NULL, 0, NULL, 0 }
4645 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4656 log_error("Unknown option code '%c'.", c);
4661 if (optind < argc) {
4662 log_error("Too many arguments.");
4669 static int parse_argv(int argc, char *argv[]) {
4673 if (program_invocation_short_name) {
4675 if (strstr(program_invocation_short_name, "halt")) {
4676 arg_action = ACTION_HALT;
4677 return halt_parse_argv(argc, argv);
4678 } else if (strstr(program_invocation_short_name, "poweroff")) {
4679 arg_action = ACTION_POWEROFF;
4680 return halt_parse_argv(argc, argv);
4681 } else if (strstr(program_invocation_short_name, "reboot")) {
4683 arg_action = ACTION_KEXEC;
4685 arg_action = ACTION_REBOOT;
4686 return halt_parse_argv(argc, argv);
4687 } else if (strstr(program_invocation_short_name, "shutdown")) {
4688 arg_action = ACTION_POWEROFF;
4689 return shutdown_parse_argv(argc, argv);
4690 } else if (strstr(program_invocation_short_name, "init")) {
4692 if (sd_booted() > 0) {
4693 arg_action = ACTION_INVALID;
4694 return telinit_parse_argv(argc, argv);
4696 /* Hmm, so some other init system is
4697 * running, we need to forward this
4698 * request to it. For now we simply
4699 * guess that it is Upstart. */
4701 execv("/lib/upstart/telinit", argv);
4703 log_error("Couldn't find an alternative telinit implementation to spawn.");
4707 } else if (strstr(program_invocation_short_name, "runlevel")) {
4708 arg_action = ACTION_RUNLEVEL;
4709 return runlevel_parse_argv(argc, argv);
4713 arg_action = ACTION_SYSTEMCTL;
4714 return systemctl_parse_argv(argc, argv);
4717 static int action_to_runlevel(void) {
4719 static const char table[_ACTION_MAX] = {
4720 [ACTION_HALT] = '0',
4721 [ACTION_POWEROFF] = '0',
4722 [ACTION_REBOOT] = '6',
4723 [ACTION_RUNLEVEL2] = '2',
4724 [ACTION_RUNLEVEL3] = '3',
4725 [ACTION_RUNLEVEL4] = '4',
4726 [ACTION_RUNLEVEL5] = '5',
4727 [ACTION_RESCUE] = '1'
4730 assert(arg_action < _ACTION_MAX);
4732 return table[arg_action];
4735 static int talk_upstart(void) {
4736 DBusMessage *m = NULL, *reply = NULL;
4738 int previous, rl, r;
4740 env1_buf[] = "RUNLEVEL=X",
4741 env2_buf[] = "PREVLEVEL=X";
4742 char *env1 = env1_buf, *env2 = env2_buf;
4743 const char *emit = "runlevel";
4744 dbus_bool_t b_false = FALSE;
4745 DBusMessageIter iter, sub;
4746 DBusConnection *bus;
4748 dbus_error_init(&error);
4750 if (!(rl = action_to_runlevel()))
4753 if (utmp_get_runlevel(&previous, NULL) < 0)
4756 if (!(bus = dbus_connection_open_private("unix:abstract=/com/ubuntu/upstart", &error))) {
4757 if (dbus_error_has_name(&error, DBUS_ERROR_NO_SERVER)) {
4762 log_error("Failed to connect to Upstart bus: %s", bus_error_message(&error));
4767 if ((r = bus_check_peercred(bus)) < 0) {
4768 log_error("Failed to verify owner of bus.");
4772 if (!(m = dbus_message_new_method_call(
4773 "com.ubuntu.Upstart",
4774 "/com/ubuntu/Upstart",
4775 "com.ubuntu.Upstart0_6",
4778 log_error("Could not allocate message.");
4783 dbus_message_iter_init_append(m, &iter);
4785 env1_buf[sizeof(env1_buf)-2] = rl;
4786 env2_buf[sizeof(env2_buf)-2] = previous;
4788 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &emit) ||
4789 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub) ||
4790 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env1) ||
4791 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env2) ||
4792 !dbus_message_iter_close_container(&iter, &sub) ||
4793 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b_false)) {
4794 log_error("Could not append arguments to message.");
4799 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
4801 if (bus_error_is_no_service(&error)) {
4806 log_error("Failed to issue method call: %s", bus_error_message(&error));
4815 dbus_message_unref(m);
4818 dbus_message_unref(reply);
4821 dbus_connection_flush(bus);
4822 dbus_connection_close(bus);
4823 dbus_connection_unref(bus);
4826 dbus_error_free(&error);
4831 static int talk_initctl(void) {
4832 struct init_request request;
4836 if (!(rl = action_to_runlevel()))
4840 request.magic = INIT_MAGIC;
4841 request.sleeptime = 0;
4842 request.cmd = INIT_CMD_RUNLVL;
4843 request.runlevel = rl;
4845 if ((fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY)) < 0) {
4847 if (errno == ENOENT)
4850 log_error("Failed to open "INIT_FIFO": %m");
4855 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
4856 close_nointr_nofail(fd);
4859 log_error("Failed to write to "INIT_FIFO": %m");
4860 return errno ? -errno : -EIO;
4866 static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
4868 static const struct {
4876 int (* const dispatch)(DBusConnection *bus, char **args);
4878 { "list-units", LESS, 1, list_units },
4879 { "list-unit-files", EQUAL, 1, list_unit_files },
4880 { "list-jobs", EQUAL, 1, list_jobs },
4881 { "clear-jobs", EQUAL, 1, daemon_reload },
4882 { "load", MORE, 2, load_unit },
4883 { "cancel", MORE, 2, cancel_job },
4884 { "start", MORE, 2, start_unit },
4885 { "stop", MORE, 2, start_unit },
4886 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
4887 { "reload", MORE, 2, start_unit },
4888 { "restart", MORE, 2, start_unit },
4889 { "try-restart", MORE, 2, start_unit },
4890 { "reload-or-restart", MORE, 2, start_unit },
4891 { "reload-or-try-restart", MORE, 2, start_unit },
4892 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
4893 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
4894 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
4895 { "isolate", EQUAL, 2, start_unit },
4896 { "kill", MORE, 2, kill_unit },
4897 { "is-active", MORE, 2, check_unit },
4898 { "check", MORE, 2, check_unit },
4899 { "show", MORE, 1, show },
4900 { "status", MORE, 2, show },
4901 { "help", MORE, 2, show },
4902 { "dump", EQUAL, 1, dump },
4903 { "dot", EQUAL, 1, dot },
4904 { "snapshot", LESS, 2, snapshot },
4905 { "delete", MORE, 2, delete_snapshot },
4906 { "daemon-reload", EQUAL, 1, daemon_reload },
4907 { "daemon-reexec", EQUAL, 1, daemon_reload },
4908 { "show-environment", EQUAL, 1, show_enviroment },
4909 { "set-environment", MORE, 2, set_environment },
4910 { "unset-environment", MORE, 2, set_environment },
4911 { "halt", EQUAL, 1, start_special },
4912 { "poweroff", EQUAL, 1, start_special },
4913 { "reboot", EQUAL, 1, start_special },
4914 { "kexec", EQUAL, 1, start_special },
4915 { "suspend", EQUAL, 1, start_special },
4916 { "hibernate", EQUAL, 1, start_special },
4917 { "hybrid-sleep", EQUAL, 1, start_special },
4918 { "default", EQUAL, 1, start_special },
4919 { "rescue", EQUAL, 1, start_special },
4920 { "emergency", EQUAL, 1, start_special },
4921 { "exit", EQUAL, 1, start_special },
4922 { "reset-failed", MORE, 1, reset_failed },
4923 { "enable", MORE, 2, enable_unit },
4924 { "disable", MORE, 2, enable_unit },
4925 { "is-enabled", MORE, 2, unit_is_enabled },
4926 { "reenable", MORE, 2, enable_unit },
4927 { "preset", MORE, 2, enable_unit },
4928 { "mask", MORE, 2, enable_unit },
4929 { "unmask", MORE, 2, enable_unit },
4930 { "link", MORE, 2, enable_unit },
4931 { "switch-root", MORE, 2, switch_root },
4941 left = argc - optind;
4944 /* Special rule: no arguments means "list-units" */
4947 if (streq(argv[optind], "help") && !argv[optind+1]) {
4948 log_error("This command expects one or more "
4949 "unit names. Did you mean --help?");
4953 for (i = 0; i < ELEMENTSOF(verbs); i++)
4954 if (streq(argv[optind], verbs[i].verb))
4957 if (i >= ELEMENTSOF(verbs)) {
4958 log_error("Unknown operation '%s'.", argv[optind]);
4963 switch (verbs[i].argc_cmp) {
4966 if (left != verbs[i].argc) {
4967 log_error("Invalid number of arguments.");
4974 if (left < verbs[i].argc) {
4975 log_error("Too few arguments.");
4982 if (left > verbs[i].argc) {
4983 log_error("Too many arguments.");
4990 assert_not_reached("Unknown comparison operator.");
4993 /* Require a bus connection for all operations but
4995 if (!streq(verbs[i].verb, "enable") &&
4996 !streq(verbs[i].verb, "disable") &&
4997 !streq(verbs[i].verb, "is-enabled") &&
4998 !streq(verbs[i].verb, "list-unit-files") &&
4999 !streq(verbs[i].verb, "reenable") &&
5000 !streq(verbs[i].verb, "preset") &&
5001 !streq(verbs[i].verb, "mask") &&
5002 !streq(verbs[i].verb, "unmask") &&
5003 !streq(verbs[i].verb, "link")) {
5005 if (running_in_chroot() > 0) {
5006 log_info("Running in chroot, ignoring request.");
5010 if (((!streq(verbs[i].verb, "reboot") &&
5011 !streq(verbs[i].verb, "halt") &&
5012 !streq(verbs[i].verb, "poweroff")) || arg_force <= 0) && !bus) {
5013 log_error("Failed to get D-Bus connection: %s",
5014 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5020 if (!bus && !avoid_bus()) {
5021 log_error("Failed to get D-Bus connection: %s",
5022 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5027 return verbs[i].dispatch(bus, argv + optind);
5030 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
5032 struct msghdr msghdr;
5033 struct iovec iovec[2];
5034 union sockaddr_union sockaddr;
5035 struct sd_shutdown_command c;
5037 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
5044 c.dry_run = dry_run;
5048 sockaddr.sa.sa_family = AF_UNIX;
5049 strncpy(sockaddr.un.sun_path, "/run/systemd/shutdownd", sizeof(sockaddr.un.sun_path));
5052 msghdr.msg_name = &sockaddr;
5053 msghdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + sizeof("/run/systemd/shutdownd") - 1;
5056 iovec[0].iov_base = (char*) &c;
5057 iovec[0].iov_len = offsetof(struct sd_shutdown_command, wall_message);
5059 if (isempty(message))
5060 msghdr.msg_iovlen = 1;
5062 iovec[1].iov_base = (char*) message;
5063 iovec[1].iov_len = strlen(message);
5064 msghdr.msg_iovlen = 2;
5066 msghdr.msg_iov = iovec;
5068 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0) {
5069 close_nointr_nofail(fd);
5073 close_nointr_nofail(fd);
5077 static int reload_with_fallback(DBusConnection *bus) {
5080 /* First, try systemd via D-Bus. */
5081 if (daemon_reload(bus, NULL) >= 0)
5085 /* Nothing else worked, so let's try signals */
5086 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
5088 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
5089 log_error("kill() failed: %m");
5096 static int start_with_fallback(DBusConnection *bus) {
5099 /* First, try systemd via D-Bus. */
5100 if (start_unit(bus, NULL) >= 0)
5104 /* Hmm, talking to systemd via D-Bus didn't work. Then
5105 * let's try to talk to Upstart via D-Bus. */
5106 if (talk_upstart() > 0)
5109 /* Nothing else worked, so let's try
5111 if (talk_initctl() > 0)
5114 log_error("Failed to talk to init daemon.");
5118 warn_wall(arg_action);
5122 static _noreturn_ void halt_now(enum action a) {
5124 /* Make sure C-A-D is handled by the kernel from this
5126 reboot(RB_ENABLE_CAD);
5131 log_info("Halting.");
5132 reboot(RB_HALT_SYSTEM);
5135 case ACTION_POWEROFF:
5136 log_info("Powering off.");
5137 reboot(RB_POWER_OFF);
5141 log_info("Rebooting.");
5142 reboot(RB_AUTOBOOT);
5146 assert_not_reached("Unknown halt action.");
5149 assert_not_reached("Uh? This shouldn't happen.");
5152 static int halt_main(DBusConnection *bus) {
5155 if (geteuid() != 0) {
5156 /* Try logind if we are a normal user and no special
5157 * mode applies. Maybe PolicyKit allows us to shutdown
5160 if (arg_when <= 0 &&
5163 (arg_action == ACTION_POWEROFF ||
5164 arg_action == ACTION_REBOOT)) {
5165 r = reboot_with_logind(bus, arg_action);
5170 log_error("Must be root.");
5177 m = strv_join(arg_wall, " ");
5178 r = send_shutdownd(arg_when,
5179 arg_action == ACTION_HALT ? 'H' :
5180 arg_action == ACTION_POWEROFF ? 'P' :
5181 arg_action == ACTION_KEXEC ? 'K' :
5189 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
5191 char date[FORMAT_TIMESTAMP_MAX];
5193 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
5194 format_timestamp(date, sizeof(date), arg_when));
5199 if (!arg_dry && !arg_force)
5200 return start_with_fallback(bus);
5203 if (sd_booted() > 0)
5204 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
5206 r = utmp_put_shutdown();
5208 log_warning("Failed to write utmp record: %s", strerror(-r));
5215 halt_now(arg_action);
5216 /* We should never reach this. */
5220 static int runlevel_main(void) {
5221 int r, runlevel, previous;
5223 r = utmp_get_runlevel(&runlevel, &previous);
5230 previous <= 0 ? 'N' : previous,
5231 runlevel <= 0 ? 'N' : runlevel);
5236 int main(int argc, char*argv[]) {
5237 int r, retval = EXIT_FAILURE;
5238 DBusConnection *bus = NULL;
5241 dbus_error_init(&error);
5243 log_parse_environment();
5246 r = parse_argv(argc, argv);
5250 retval = EXIT_SUCCESS;
5254 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
5255 * let's shortcut this */
5256 if (arg_action == ACTION_RUNLEVEL) {
5257 r = runlevel_main();
5258 retval = r < 0 ? EXIT_FAILURE : r;
5262 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
5263 log_info("Running in chroot, ignoring request.");
5269 if (arg_transport == TRANSPORT_NORMAL)
5270 bus_connect(arg_scope == UNIT_FILE_SYSTEM ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &bus, &private_bus, &error);
5271 else if (arg_transport == TRANSPORT_POLKIT) {
5272 bus_connect_system_polkit(&bus, &error);
5273 private_bus = false;
5274 } else if (arg_transport == TRANSPORT_SSH) {
5275 bus_connect_system_ssh(NULL, arg_host, &bus, &error);
5276 private_bus = false;
5278 assert_not_reached("Uh, invalid transport...");
5281 switch (arg_action) {
5283 case ACTION_SYSTEMCTL:
5284 r = systemctl_main(bus, argc, argv, &error);
5288 case ACTION_POWEROFF:
5294 case ACTION_RUNLEVEL2:
5295 case ACTION_RUNLEVEL3:
5296 case ACTION_RUNLEVEL4:
5297 case ACTION_RUNLEVEL5:
5299 case ACTION_EMERGENCY:
5300 case ACTION_DEFAULT:
5301 r = start_with_fallback(bus);
5306 r = reload_with_fallback(bus);
5309 case ACTION_CANCEL_SHUTDOWN: {
5313 m = strv_join(arg_wall, " ");
5315 retval = EXIT_FAILURE;
5319 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
5321 log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r));
5326 case ACTION_INVALID:
5327 case ACTION_RUNLEVEL:
5329 assert_not_reached("Unknown action");
5332 retval = r < 0 ? EXIT_FAILURE : r;
5336 dbus_connection_flush(bus);
5337 dbus_connection_close(bus);
5338 dbus_connection_unref(bus);
5341 dbus_error_free(&error);
5345 strv_free(arg_property);
5348 ask_password_agent_close();
5349 polkit_agent_close();