1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
22 #include <sys/reboot.h>
29 #include <sys/ioctl.h>
33 #include <sys/socket.h>
36 #include <sys/prctl.h>
37 #include <dbus/dbus.h>
39 #include <systemd/sd-daemon.h>
40 #include <systemd/sd-shutdown.h>
46 #include "utmp-wtmp.h"
49 #include "path-util.h"
51 #include "dbus-common.h"
52 #include "cgroup-show.h"
53 #include "cgroup-util.h"
55 #include "path-lookup.h"
56 #include "conf-parser.h"
57 #include "exit-status.h"
58 #include "bus-errors.h"
60 #include "unit-name.h"
62 #include "spawn-ask-password-agent.h"
63 #include "spawn-polkit-agent.h"
65 #include "logs-show.h"
66 #include "path-util.h"
67 #include "socket-util.h"
69 static const char *arg_type = NULL;
70 static const char *arg_load_state = NULL;
71 static char **arg_property = NULL;
72 static bool arg_all = false;
73 static const char *arg_job_mode = "replace";
74 static UnitFileScope arg_scope = UNIT_FILE_SYSTEM;
75 static bool arg_no_block = false;
76 static bool arg_no_legend = false;
77 static bool arg_no_pager = false;
78 static bool arg_no_wtmp = false;
79 static bool arg_no_wall = false;
80 static bool arg_no_reload = false;
81 static bool arg_dry = false;
82 static bool arg_quiet = false;
83 static bool arg_full = false;
84 static int arg_force = 0;
85 static bool arg_ask_password = true;
86 static bool arg_failed = false;
87 static bool arg_runtime = false;
88 static char **arg_wall = NULL;
89 static const char *arg_kill_who = NULL;
90 static int arg_signal = SIGTERM;
91 static const char *arg_root = NULL;
92 static usec_t arg_when = 0;
114 ACTION_CANCEL_SHUTDOWN,
116 } arg_action = ACTION_SYSTEMCTL;
122 static enum transport {
126 } arg_transport = TRANSPORT_NORMAL;
127 static const char *arg_host = NULL;
128 static unsigned arg_lines = 10;
129 static OutputMode arg_output = OUTPUT_SHORT;
131 static bool private_bus = false;
133 static int daemon_reload(DBusConnection *bus, char **args);
134 static void halt_now(enum action a);
136 static void pager_open_if_enabled(void) {
144 static void ask_password_agent_open_if_enabled(void) {
146 /* Open the password agent as a child process if necessary */
148 if (!arg_ask_password)
151 if (arg_scope != UNIT_FILE_SYSTEM)
154 ask_password_agent_open();
158 static void polkit_agent_open_if_enabled(void) {
160 /* Open the polkit agent as a child process if necessary */
162 if (!arg_ask_password)
165 if (arg_scope != UNIT_FILE_SYSTEM)
172 static const char *ansi_highlight(bool b) {
177 return b ? ANSI_HIGHLIGHT_ON : ANSI_HIGHLIGHT_OFF;
180 static const char *ansi_highlight_red(bool b) {
185 return b ? ANSI_HIGHLIGHT_RED_ON : ANSI_HIGHLIGHT_OFF;
188 static const char *ansi_highlight_green(bool b) {
193 return b ? ANSI_HIGHLIGHT_GREEN_ON : ANSI_HIGHLIGHT_OFF;
196 static int translate_bus_error_to_exit_status(int r, const DBusError *error) {
199 if (!dbus_error_is_set(error))
202 if (dbus_error_has_name(error, DBUS_ERROR_ACCESS_DENIED) ||
203 dbus_error_has_name(error, BUS_ERROR_ONLY_BY_DEPENDENCY) ||
204 dbus_error_has_name(error, BUS_ERROR_NO_ISOLATION) ||
205 dbus_error_has_name(error, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE))
206 return EXIT_NOPERMISSION;
208 if (dbus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT))
209 return EXIT_NOTINSTALLED;
211 if (dbus_error_has_name(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE) ||
212 dbus_error_has_name(error, BUS_ERROR_NOT_SUPPORTED))
213 return EXIT_NOTIMPLEMENTED;
215 if (dbus_error_has_name(error, BUS_ERROR_LOAD_FAILED))
216 return EXIT_NOTCONFIGURED;
224 static void warn_wall(enum action a) {
225 static const char *table[_ACTION_MAX] = {
226 [ACTION_HALT] = "The system is going down for system halt NOW!",
227 [ACTION_REBOOT] = "The system is going down for reboot NOW!",
228 [ACTION_POWEROFF] = "The system is going down for power-off NOW!",
229 [ACTION_KEXEC] = "The system is going down for kexec reboot NOW!",
230 [ACTION_RESCUE] = "The system is going down to rescue mode NOW!",
231 [ACTION_EMERGENCY] = "The system is going down to emergency mode NOW!",
232 [ACTION_CANCEL_SHUTDOWN] = "The system shutdown has been cancelled NOW!"
241 p = strv_join(arg_wall, " ");
243 log_error("Failed to join strings.");
259 utmp_wall(table[a], NULL);
262 static bool avoid_bus(void) {
264 if (running_in_chroot() > 0)
267 if (sd_booted() <= 0)
270 if (!isempty(arg_root))
273 if (arg_scope == UNIT_FILE_GLOBAL)
281 const char *description;
282 const char *load_state;
283 const char *active_state;
284 const char *sub_state;
285 const char *following;
286 const char *unit_path;
288 const char *job_type;
289 const char *job_path;
292 static int compare_unit_info(const void *a, const void *b) {
294 const struct unit_info *u = a, *v = b;
296 d1 = strrchr(u->id, '.');
297 d2 = strrchr(v->id, '.');
302 if ((r = strcasecmp(d1, d2)) != 0)
306 return strcasecmp(u->id, v->id);
309 static bool output_show_unit(const struct unit_info *u) {
313 return streq(u->active_state, "failed");
315 return (!arg_type || ((dot = strrchr(u->id, '.')) &&
316 streq(dot+1, arg_type))) &&
317 (!arg_load_state || streq(u->load_state, arg_load_state)) &&
318 (arg_all || !(streq(u->active_state, "inactive")
319 || u->following[0]) || u->job_id > 0);
322 static void output_units_list(const struct unit_info *unit_infos, unsigned c) {
323 unsigned id_len, max_id_len, active_len, sub_len, job_len, desc_len, n_shown = 0;
324 const struct unit_info *u;
327 max_id_len = sizeof("UNIT")-1;
328 active_len = sizeof("ACTIVE")-1;
329 sub_len = sizeof("SUB")-1;
330 job_len = sizeof("JOB")-1;
333 for (u = unit_infos; u < unit_infos + c; u++) {
334 if (!output_show_unit(u))
337 max_id_len = MAX(max_id_len, strlen(u->id));
338 active_len = MAX(active_len, strlen(u->active_state));
339 sub_len = MAX(sub_len, strlen(u->sub_state));
340 if (u->job_id != 0) {
341 job_len = MAX(job_len, strlen(u->job_type));
348 id_len = MIN(max_id_len, 25);
349 basic_len = 5 + id_len + 5 + active_len + sub_len;
351 basic_len += job_len + 1;
352 if (basic_len < (unsigned) columns()) {
353 unsigned extra_len, incr;
354 extra_len = columns() - basic_len;
355 /* Either UNIT already got 25, or is fully satisfied.
356 * Grant up to 25 to DESC now. */
357 incr = MIN(extra_len, 25);
360 /* split the remaining space between UNIT and DESC,
361 * but do not give UNIT more than it needs. */
363 incr = MIN(extra_len / 2, max_id_len - id_len);
365 desc_len += extra_len - incr;
371 for (u = unit_infos; u < unit_infos + c; u++) {
373 const char *on_loaded, *off_loaded;
374 const char *on_active, *off_active;
376 if (!output_show_unit(u))
379 if (!n_shown && !arg_no_legend) {
380 printf("%-*s %-6s %-*s %-*s ", id_len, "UNIT", "LOAD",
381 active_len, "ACTIVE", sub_len, "SUB");
383 printf("%-*s ", job_len, "JOB");
384 if (!arg_full && arg_no_pager)
385 printf("%.*s\n", desc_len, "DESCRIPTION");
387 printf("%s\n", "DESCRIPTION");
392 if (streq(u->load_state, "error")) {
393 on_loaded = ansi_highlight_red(true);
394 off_loaded = ansi_highlight_red(false);
396 on_loaded = off_loaded = "";
398 if (streq(u->active_state, "failed")) {
399 on_active = ansi_highlight_red(true);
400 off_active = ansi_highlight_red(false);
402 on_active = off_active = "";
404 e = arg_full ? NULL : ellipsize(u->id, id_len, 33);
406 printf("%-*s %s%-6s%s %s%-*s %-*s%s %-*s",
407 id_len, e ? e : u->id,
408 on_loaded, u->load_state, off_loaded,
409 on_active, active_len, u->active_state,
410 sub_len, u->sub_state, off_active,
411 job_count ? job_len + 1 : 0, u->job_id ? u->job_type : "");
412 if (!arg_full && arg_no_pager)
413 printf("%.*s\n", desc_len, u->description);
415 printf("%s\n", u->description);
420 if (!arg_no_legend) {
421 const char *on, *off;
424 printf("\nLOAD = Reflects whether the unit definition was properly loaded.\n"
425 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
426 "SUB = The low-level unit activation state, values depend on unit type.\n");
428 printf("JOB = Pending job for the unit.\n");
430 on = ansi_highlight(true);
431 off = ansi_highlight(false);
433 on = ansi_highlight_red(true);
434 off = ansi_highlight_red(false);
438 printf("%s%u loaded units listed.%s\n"
439 "To show all installed unit files use 'systemctl list-unit-files'.\n",
442 printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
443 "To show all installed unit files use 'systemctl list-unit-files'.\n",
448 static int list_units(DBusConnection *bus, char **args) {
449 DBusMessage *reply = NULL;
451 DBusMessageIter iter, sub, sub2;
452 unsigned c = 0, n_units = 0;
453 struct unit_info *unit_infos = NULL;
455 pager_open_if_enabled();
457 r = bus_method_call_with_reply (
459 "org.freedesktop.systemd1",
460 "/org/freedesktop/systemd1",
461 "org.freedesktop.systemd1.Manager",
469 if (!dbus_message_iter_init(reply, &iter) ||
470 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
471 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
472 log_error("Failed to parse reply.");
477 dbus_message_iter_recurse(&iter, &sub);
479 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
482 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
483 log_error("Failed to parse reply.");
491 n_units = MAX(2*c, 16);
492 w = realloc(unit_infos, sizeof(struct unit_info) * n_units);
495 log_error("Failed to allocate unit array.");
505 dbus_message_iter_recurse(&sub, &sub2);
507 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->id, true) < 0 ||
508 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->description, true) < 0 ||
509 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->load_state, true) < 0 ||
510 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->active_state, true) < 0 ||
511 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->sub_state, true) < 0 ||
512 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->following, true) < 0 ||
513 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &u->unit_path, true) < 0 ||
514 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &u->job_id, true) < 0 ||
515 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->job_type, true) < 0 ||
516 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &u->job_path, false) < 0) {
517 log_error("Failed to parse reply.");
522 dbus_message_iter_next(&sub);
527 qsort(unit_infos, c, sizeof(struct unit_info), compare_unit_info);
528 output_units_list(unit_infos, c);
533 dbus_message_unref(reply);
540 static int compare_unit_file_list(const void *a, const void *b) {
542 const UnitFileList *u = a, *v = b;
544 d1 = strrchr(u->path, '.');
545 d2 = strrchr(v->path, '.');
550 r = strcasecmp(d1, d2);
555 return strcasecmp(path_get_file_name(u->path), path_get_file_name(v->path));
558 static bool output_show_unit_file(const UnitFileList *u) {
561 return !arg_type || ((dot = strrchr(u->path, '.')) && streq(dot+1, arg_type));
564 static void output_unit_file_list(const UnitFileList *units, unsigned c) {
565 unsigned max_id_len, id_cols, state_cols, n_shown = 0;
566 const UnitFileList *u;
568 max_id_len = sizeof("UNIT FILE")-1;
569 state_cols = sizeof("STATE")-1;
570 for (u = units; u < units + c; u++) {
571 if (!output_show_unit_file(u))
574 max_id_len = MAX(max_id_len, strlen(path_get_file_name(u->path)));
575 state_cols = MAX(state_cols, strlen(unit_file_state_to_string(u->state)));
580 id_cols = MIN(max_id_len, 25);
581 basic_cols = 1 + id_cols + state_cols;
582 if (basic_cols < (unsigned) columns())
583 id_cols += MIN(columns() - basic_cols, max_id_len - id_cols);
585 id_cols = max_id_len;
588 printf("%-*s %-*s\n", id_cols, "UNIT FILE", state_cols, "STATE");
590 for (u = units; u < units + c; u++) {
592 const char *on, *off;
595 if (!output_show_unit_file(u))
600 if (u->state == UNIT_FILE_MASKED ||
601 u->state == UNIT_FILE_MASKED_RUNTIME ||
602 u->state == UNIT_FILE_DISABLED ||
603 u->state == UNIT_FILE_INVALID) {
604 on = ansi_highlight_red(true);
605 off = ansi_highlight_red(false);
606 } else if (u->state == UNIT_FILE_ENABLED) {
607 on = ansi_highlight_green(true);
608 off = ansi_highlight_green(false);
612 id = path_get_file_name(u->path);
614 e = arg_full ? NULL : ellipsize(id, id_cols, 33);
616 printf("%-*s %s%-*s%s\n",
618 on, state_cols, unit_file_state_to_string(u->state), off);
624 printf("\n%u unit files listed.\n", n_shown);
627 static int list_unit_files(DBusConnection *bus, char **args) {
628 DBusMessage *reply = NULL;
630 DBusMessageIter iter, sub, sub2;
631 unsigned c = 0, n_units = 0;
632 UnitFileList *units = NULL;
634 pager_open_if_enabled();
641 h = hashmap_new(string_hash_func, string_compare_func);
645 r = unit_file_get_list(arg_scope, arg_root, h);
647 unit_file_list_free(h);
648 log_error("Failed to get unit file list: %s", strerror(-r));
652 n_units = hashmap_size(h);
653 units = new(UnitFileList, n_units);
655 unit_file_list_free(h);
659 HASHMAP_FOREACH(u, h, i) {
660 memcpy(units + c++, u, sizeof(UnitFileList));
666 r = bus_method_call_with_reply (
668 "org.freedesktop.systemd1",
669 "/org/freedesktop/systemd1",
670 "org.freedesktop.systemd1.Manager",
678 if (!dbus_message_iter_init(reply, &iter) ||
679 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
680 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
681 log_error("Failed to parse reply.");
686 dbus_message_iter_recurse(&iter, &sub);
688 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
692 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
693 log_error("Failed to parse reply.");
701 n_units = MAX(2*c, 16);
702 w = realloc(units, sizeof(struct UnitFileList) * n_units);
705 log_error("Failed to allocate unit array.");
715 dbus_message_iter_recurse(&sub, &sub2);
717 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->path, true) < 0 ||
718 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, false) < 0) {
719 log_error("Failed to parse reply.");
724 u->state = unit_file_state_from_string(state);
726 dbus_message_iter_next(&sub);
732 qsort(units, c, sizeof(UnitFileList), compare_unit_file_list);
733 output_unit_file_list(units, c);
740 dbus_message_unref(reply);
747 static int dot_one_property(const char *name, const char *prop, DBusMessageIter *iter) {
748 static const char * const colors[] = {
749 "Requires", "[color=\"black\"]",
750 "RequiresOverridable", "[color=\"black\"]",
751 "Requisite", "[color=\"darkblue\"]",
752 "RequisiteOverridable", "[color=\"darkblue\"]",
753 "Wants", "[color=\"grey66\"]",
754 "Conflicts", "[color=\"red\"]",
755 "ConflictedBy", "[color=\"red\"]",
756 "After", "[color=\"green\"]"
759 const char *c = NULL;
766 for (i = 0; i < ELEMENTSOF(colors); i += 2)
767 if (streq(colors[i], prop)) {
775 if (arg_dot != DOT_ALL)
776 if ((arg_dot == DOT_ORDER) != streq(prop, "After"))
779 switch (dbus_message_iter_get_arg_type(iter)) {
781 case DBUS_TYPE_ARRAY:
783 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING) {
786 dbus_message_iter_recurse(iter, &sub);
788 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
791 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING);
792 dbus_message_iter_get_basic(&sub, &s);
793 printf("\t\"%s\"->\"%s\" %s;\n", name, s, c);
795 dbus_message_iter_next(&sub);
805 static int dot_one(DBusConnection *bus, const char *name, const char *path) {
806 DBusMessage *reply = NULL;
807 const char *interface = "org.freedesktop.systemd1.Unit";
809 DBusMessageIter iter, sub, sub2, sub3;
813 r = bus_method_call_with_reply (
815 "org.freedesktop.systemd1",
817 "org.freedesktop.DBus.Properties",
821 DBUS_TYPE_STRING, &interface,
826 if (!dbus_message_iter_init(reply, &iter) ||
827 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
828 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
829 log_error("Failed to parse reply.");
834 dbus_message_iter_recurse(&iter, &sub);
836 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
839 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_DICT_ENTRY) {
840 log_error("Failed to parse reply.");
845 dbus_message_iter_recurse(&sub, &sub2);
847 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &prop, true) < 0) {
848 log_error("Failed to parse reply.");
853 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
854 log_error("Failed to parse reply.");
859 dbus_message_iter_recurse(&sub2, &sub3);
861 if (dot_one_property(name, prop, &sub3)) {
862 log_error("Failed to parse reply.");
867 dbus_message_iter_next(&sub);
872 dbus_message_unref(reply);
877 static int dot(DBusConnection *bus, char **args) {
878 DBusMessage *reply = NULL;
880 DBusMessageIter iter, sub, sub2;
882 r = bus_method_call_with_reply (
884 "org.freedesktop.systemd1",
885 "/org/freedesktop/systemd1",
886 "org.freedesktop.systemd1.Manager",
894 if (!dbus_message_iter_init(reply, &iter) ||
895 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
896 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
897 log_error("Failed to parse reply.");
902 printf("digraph systemd {\n");
904 dbus_message_iter_recurse(&iter, &sub);
905 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
906 const char *id, *description, *load_state, *active_state, *sub_state, *following, *unit_path;
908 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
909 log_error("Failed to parse reply.");
914 dbus_message_iter_recurse(&sub, &sub2);
916 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &id, true) < 0 ||
917 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &description, true) < 0 ||
918 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &load_state, true) < 0 ||
919 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &active_state, true) < 0 ||
920 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &sub_state, true) < 0 ||
921 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &following, true) < 0 ||
922 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, true) < 0) {
923 log_error("Failed to parse reply.");
928 if ((r = dot_one(bus, id, unit_path)) < 0)
931 /* printf("\t\"%s\";\n", id); */
932 dbus_message_iter_next(&sub);
937 log_info(" Color legend: black = Requires\n"
938 " dark blue = Requisite\n"
939 " dark grey = Wants\n"
944 log_notice("-- You probably want to process this output with graphviz' dot tool.\n"
945 "-- Try a shell pipeline like 'systemctl dot | dot -Tsvg > systemd.svg'!\n");
951 dbus_message_unref(reply);
956 static int list_jobs(DBusConnection *bus, char **args) {
957 DBusMessage *reply = NULL;
959 DBusMessageIter iter, sub, sub2;
962 pager_open_if_enabled();
964 r = bus_method_call_with_reply (
966 "org.freedesktop.systemd1",
967 "/org/freedesktop/systemd1",
968 "org.freedesktop.systemd1.Manager",
976 if (!dbus_message_iter_init(reply, &iter) ||
977 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
978 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
979 log_error("Failed to parse reply.");
984 dbus_message_iter_recurse(&iter, &sub);
987 printf("%4s %-25s %-15s %-7s\n", "JOB", "UNIT", "TYPE", "STATE");
989 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
990 const char *name, *type, *state, *job_path, *unit_path;
994 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
995 log_error("Failed to parse reply.");
1000 dbus_message_iter_recurse(&sub, &sub2);
1002 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &id, true) < 0 ||
1003 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
1004 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
1005 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, true) < 0 ||
1006 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &job_path, true) < 0 ||
1007 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, false) < 0) {
1008 log_error("Failed to parse reply.");
1013 e = arg_full ? NULL : ellipsize(name, 25, 33);
1014 printf("%4u %-25s %-15s %-7s\n", id, e ? e : name, type, state);
1019 dbus_message_iter_next(&sub);
1023 printf("\n%u jobs listed.\n", k);
1029 dbus_message_unref(reply);
1034 static int load_unit(DBusConnection *bus, char **args) {
1039 STRV_FOREACH(name, args+1) {
1040 _cleanup_free_ char *n = NULL;
1043 n = unit_name_mangle(*name);
1044 r = bus_method_call_with_reply (
1046 "org.freedesktop.systemd1",
1047 "/org/freedesktop/systemd1",
1048 "org.freedesktop.systemd1.Manager",
1052 DBUS_TYPE_STRING, n ? &n : name,
1061 static int cancel_job(DBusConnection *bus, char **args) {
1066 if (strv_length(args) <= 1)
1067 return daemon_reload(bus, args);
1069 STRV_FOREACH(name, args+1) {
1073 r = safe_atou32(*name, &id);
1075 log_error("Failed to parse job id: %s", strerror(-r));
1079 r = bus_method_call_with_reply(
1081 "org.freedesktop.systemd1",
1082 "/org/freedesktop/systemd1",
1083 "org.freedesktop.systemd1.Manager",
1087 DBUS_TYPE_UINT32, &id,
1096 static bool need_daemon_reload(DBusConnection *bus, const char *unit) {
1097 DBusMessage *reply = NULL;
1098 dbus_bool_t b = FALSE;
1099 DBusMessageIter iter, sub;
1101 *interface = "org.freedesktop.systemd1.Unit",
1102 *property = "NeedDaemonReload",
1107 /* We ignore all errors here, since this is used to show a warning only */
1109 n = unit_name_mangle(unit);
1110 r = bus_method_call_with_reply (
1112 "org.freedesktop.systemd1",
1113 "/org/freedesktop/systemd1",
1114 "org.freedesktop.systemd1.Manager",
1118 DBUS_TYPE_STRING, n ? (const char**) &n : &unit,
1124 if (!dbus_message_get_args(reply, NULL,
1125 DBUS_TYPE_OBJECT_PATH, &path,
1129 dbus_message_unref(reply);
1130 r = bus_method_call_with_reply (
1132 "org.freedesktop.systemd1",
1134 "org.freedesktop.DBus.Properties",
1138 DBUS_TYPE_STRING, &interface,
1139 DBUS_TYPE_STRING, &property,
1144 if (!dbus_message_iter_init(reply, &iter) ||
1145 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
1148 dbus_message_iter_recurse(&iter, &sub);
1150 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_BOOLEAN)
1153 dbus_message_iter_get_basic(&sub, &b);
1157 dbus_message_unref(reply);
1162 typedef struct WaitData {
1169 static DBusHandlerResult wait_filter(DBusConnection *connection, DBusMessage *message, void *data) {
1177 dbus_error_init(&error);
1179 log_debug("Got D-Bus request: %s.%s() on %s",
1180 dbus_message_get_interface(message),
1181 dbus_message_get_member(message),
1182 dbus_message_get_path(message));
1184 if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
1185 log_error("Warning! D-Bus connection terminated.");
1186 dbus_connection_close(connection);
1188 } else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
1190 const char *path, *result, *unit;
1191 dbus_bool_t success = true;
1193 if (dbus_message_get_args(message, &error,
1194 DBUS_TYPE_UINT32, &id,
1195 DBUS_TYPE_OBJECT_PATH, &path,
1196 DBUS_TYPE_STRING, &unit,
1197 DBUS_TYPE_STRING, &result,
1198 DBUS_TYPE_INVALID)) {
1201 p = set_remove(d->set, (char*) path);
1204 if (!isempty(result))
1205 d->result = strdup(result);
1208 d->name = strdup(unit);
1213 dbus_error_free(&error);
1214 if (dbus_message_get_args(message, &error,
1215 DBUS_TYPE_UINT32, &id,
1216 DBUS_TYPE_OBJECT_PATH, &path,
1217 DBUS_TYPE_STRING, &result,
1218 DBUS_TYPE_INVALID)) {
1221 /* Compatibility with older systemd versions <
1222 * 183 during upgrades. This should be dropped
1224 p = set_remove(d->set, (char*) path);
1228 d->result = strdup(result);
1233 dbus_error_free(&error);
1234 if (dbus_message_get_args(message, &error,
1235 DBUS_TYPE_UINT32, &id,
1236 DBUS_TYPE_OBJECT_PATH, &path,
1237 DBUS_TYPE_BOOLEAN, &success,
1238 DBUS_TYPE_INVALID)) {
1241 /* Compatibility with older systemd versions <
1242 * 19 during upgrades. This should be dropped
1245 p = set_remove(d->set, (char*) path);
1249 d->result = strdup("failed");
1255 log_error("Failed to parse message: %s", bus_error_message(&error));
1259 dbus_error_free(&error);
1260 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1263 static int enable_wait_for_jobs(DBusConnection *bus) {
1271 dbus_error_init(&error);
1272 dbus_bus_add_match(bus,
1274 "sender='org.freedesktop.systemd1',"
1275 "interface='org.freedesktop.systemd1.Manager',"
1276 "member='JobRemoved',"
1277 "path='/org/freedesktop/systemd1'",
1280 if (dbus_error_is_set(&error)) {
1281 log_error("Failed to add match: %s", bus_error_message(&error));
1282 dbus_error_free(&error);
1286 /* This is slightly dirty, since we don't undo the match registrations. */
1290 static int wait_for_jobs(DBusConnection *bus, Set *s) {
1300 if (!dbus_connection_add_filter(bus, wait_filter, &d, NULL))
1303 while (!set_isempty(s)) {
1305 if (!dbus_connection_read_write_dispatch(bus, -1)) {
1306 log_error("Disconnected from bus.");
1307 return -ECONNREFUSED;
1314 if (streq(d.result, "timeout"))
1315 log_error("Job for %s timed out.", strna(d.name));
1316 else if (streq(d.result, "canceled"))
1317 log_error("Job for %s canceled.", strna(d.name));
1318 else if (streq(d.result, "dependency"))
1319 log_error("A dependency job for %s failed. See 'journalctl -xn' for details.", strna(d.name));
1320 else if (!streq(d.result, "done") && !streq(d.result, "skipped"))
1321 log_error("Job for %s failed. See 'systemctl status %s' and 'journalctl -xn' for details.", strna(d.name), strna(d.name));
1324 if (streq_ptr(d.result, "timeout"))
1326 else if (streq_ptr(d.result, "canceled"))
1328 else if (!streq_ptr(d.result, "done") && !streq_ptr(d.result, "skipped"))
1339 dbus_connection_remove_filter(bus, wait_filter, &d);
1343 static int check_one_unit(DBusConnection *bus, char *name, char **check_states, bool quiet) {
1344 DBusMessage *reply = NULL;
1345 DBusMessageIter iter, sub;
1347 *interface = "org.freedesktop.systemd1.Unit",
1348 *property = "ActiveState";
1349 const char *path = NULL;
1356 n = unit_name_mangle(name);
1357 r = bus_method_call_with_reply (
1359 "org.freedesktop.systemd1",
1360 "/org/freedesktop/systemd1",
1361 "org.freedesktop.systemd1.Manager",
1365 DBUS_TYPE_STRING, n ? &n : &name,
1369 if ((r != -ENOMEM) && (!quiet))
1374 if (!dbus_message_get_args(reply, NULL,
1375 DBUS_TYPE_OBJECT_PATH, &path,
1376 DBUS_TYPE_INVALID)) {
1377 log_error("Failed to parse reply.");
1382 dbus_message_unref(reply);
1383 r = bus_method_call_with_reply (
1385 "org.freedesktop.systemd1",
1387 "org.freedesktop.DBus.Properties",
1391 DBUS_TYPE_STRING, &interface,
1392 DBUS_TYPE_STRING, &property,
1397 if (!dbus_message_iter_init(reply, &iter) ||
1398 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1399 log_error("Failed to parse reply.");
1404 dbus_message_iter_recurse(&iter, &sub);
1406 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1407 log_error("Failed to parse reply.");
1412 dbus_message_iter_get_basic(&sub, &state);
1417 if (strv_find(check_states, state))
1420 r = 3; /* According to LSB: "program is not running" */
1424 dbus_message_unref(reply);
1429 static void check_triggering_units(
1430 DBusConnection *bus,
1431 const char *unit_name) {
1433 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1434 DBusMessageIter iter, sub;
1435 char *service_trigger = NULL;
1436 const char *interface = "org.freedesktop.systemd1.Unit",
1437 *triggered_by_property = "TriggeredBy";
1439 char _cleanup_free_ *unit_path = NULL, *n = NULL;
1440 bool print_warning_label = true;
1443 n = unit_name_mangle(unit_name);
1449 unit_path = unit_dbus_path_from_name(n);
1455 r = bus_method_call_with_reply (
1457 "org.freedesktop.systemd1",
1459 "org.freedesktop.DBus.Properties",
1463 DBUS_TYPE_STRING, &interface,
1464 DBUS_TYPE_STRING, &triggered_by_property,
1469 if (!dbus_message_iter_init(reply, &iter) ||
1470 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1471 log_error("Failed to parse reply.");
1475 dbus_message_iter_recurse(&iter, &sub);
1476 dbus_message_iter_recurse(&sub, &iter);
1479 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1480 char **check_states = NULL;
1482 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1483 log_error("Failed to parse reply.");
1487 dbus_message_iter_get_basic(&sub, &service_trigger);
1489 check_states = strv_new("active", "reloading", NULL);
1490 r = check_one_unit(bus, service_trigger, check_states, true);
1491 strv_free(check_states);
1495 if (print_warning_label) {
1496 log_warning("Warning: Stopping %s, but it can still be activated by:", unit_name);
1497 print_warning_label = false;
1499 log_warning(" %s", service_trigger);
1502 dbus_message_iter_next(&sub);
1506 static int start_unit_one(
1507 DBusConnection *bus,
1514 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1517 _cleanup_free_ char *n, *p = NULL;
1524 n = unit_name_mangle(name);
1528 r = bus_method_call_with_reply(
1530 "org.freedesktop.systemd1",
1531 "/org/freedesktop/systemd1",
1532 "org.freedesktop.systemd1.Manager",
1536 DBUS_TYPE_STRING, &n,
1537 DBUS_TYPE_STRING, &mode,
1540 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
1541 /* There's always a fallback possible for
1542 * legacy actions. */
1545 log_error("Failed to issue method call: %s", bus_error_message(error));
1550 if (!dbus_message_get_args(reply, error,
1551 DBUS_TYPE_OBJECT_PATH, &path,
1552 DBUS_TYPE_INVALID)) {
1553 log_error("Failed to parse reply: %s", bus_error_message(error));
1557 if (need_daemon_reload(bus, n))
1558 log_warning("Warning: Unit file of %s changed on disk, 'systemctl %s daemon-reload' recommended.",
1559 n, arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
1568 log_error("Failed to add path to set.");
1578 static enum action verb_to_action(const char *verb) {
1579 if (streq(verb, "halt"))
1581 else if (streq(verb, "poweroff"))
1582 return ACTION_POWEROFF;
1583 else if (streq(verb, "reboot"))
1584 return ACTION_REBOOT;
1585 else if (streq(verb, "kexec"))
1586 return ACTION_KEXEC;
1587 else if (streq(verb, "rescue"))
1588 return ACTION_RESCUE;
1589 else if (streq(verb, "emergency"))
1590 return ACTION_EMERGENCY;
1591 else if (streq(verb, "default"))
1592 return ACTION_DEFAULT;
1593 else if (streq(verb, "exit"))
1595 else if (streq(verb, "suspend"))
1596 return ACTION_SUSPEND;
1597 else if (streq(verb, "hibernate"))
1598 return ACTION_HIBERNATE;
1599 else if (streq(verb, "hybrid-sleep"))
1600 return ACTION_HYBRID_SLEEP;
1602 return ACTION_INVALID;
1605 static int start_unit(DBusConnection *bus, char **args) {
1607 static const char * const table[_ACTION_MAX] = {
1608 [ACTION_HALT] = SPECIAL_HALT_TARGET,
1609 [ACTION_POWEROFF] = SPECIAL_POWEROFF_TARGET,
1610 [ACTION_REBOOT] = SPECIAL_REBOOT_TARGET,
1611 [ACTION_KEXEC] = SPECIAL_KEXEC_TARGET,
1612 [ACTION_RUNLEVEL2] = SPECIAL_RUNLEVEL2_TARGET,
1613 [ACTION_RUNLEVEL3] = SPECIAL_RUNLEVEL3_TARGET,
1614 [ACTION_RUNLEVEL4] = SPECIAL_RUNLEVEL4_TARGET,
1615 [ACTION_RUNLEVEL5] = SPECIAL_RUNLEVEL5_TARGET,
1616 [ACTION_RESCUE] = SPECIAL_RESCUE_TARGET,
1617 [ACTION_EMERGENCY] = SPECIAL_EMERGENCY_TARGET,
1618 [ACTION_DEFAULT] = SPECIAL_DEFAULT_TARGET,
1619 [ACTION_EXIT] = SPECIAL_EXIT_TARGET,
1620 [ACTION_SUSPEND] = SPECIAL_SUSPEND_TARGET,
1621 [ACTION_HIBERNATE] = SPECIAL_HIBERNATE_TARGET,
1622 [ACTION_HYBRID_SLEEP] = SPECIAL_HYBRID_SLEEP_TARGET
1626 const char *method, *mode, *one_name;
1631 dbus_error_init(&error);
1635 ask_password_agent_open_if_enabled();
1637 if (arg_action == ACTION_SYSTEMCTL) {
1639 streq(args[0], "stop") ||
1640 streq(args[0], "condstop") ? "StopUnit" :
1641 streq(args[0], "reload") ? "ReloadUnit" :
1642 streq(args[0], "restart") ? "RestartUnit" :
1644 streq(args[0], "try-restart") ||
1645 streq(args[0], "condrestart") ? "TryRestartUnit" :
1647 streq(args[0], "reload-or-restart") ? "ReloadOrRestartUnit" :
1649 streq(args[0], "reload-or-try-restart") ||
1650 streq(args[0], "condreload") ||
1652 streq(args[0], "force-reload") ? "ReloadOrTryRestartUnit" :
1656 (streq(args[0], "isolate") ||
1657 streq(args[0], "rescue") ||
1658 streq(args[0], "emergency")) ? "isolate" : arg_job_mode;
1660 one_name = table[verb_to_action(args[0])];
1663 assert(arg_action < ELEMENTSOF(table));
1664 assert(table[arg_action]);
1666 method = "StartUnit";
1668 mode = (arg_action == ACTION_EMERGENCY ||
1669 arg_action == ACTION_RESCUE ||
1670 arg_action == ACTION_RUNLEVEL2 ||
1671 arg_action == ACTION_RUNLEVEL3 ||
1672 arg_action == ACTION_RUNLEVEL4 ||
1673 arg_action == ACTION_RUNLEVEL5) ? "isolate" : "replace";
1675 one_name = table[arg_action];
1678 if (!arg_no_block) {
1679 ret = enable_wait_for_jobs(bus);
1681 log_error("Could not watch jobs: %s", strerror(-ret));
1685 s = set_new(string_hash_func, string_compare_func);
1693 ret = start_unit_one(bus, method, one_name, mode, &error, s);
1695 ret = translate_bus_error_to_exit_status(ret, &error);
1697 STRV_FOREACH(name, args+1) {
1698 r = start_unit_one(bus, method, *name, mode, &error, s);
1700 ret = translate_bus_error_to_exit_status(r, &error);
1701 dbus_error_free(&error);
1706 if (!arg_no_block) {
1707 r = wait_for_jobs(bus, s);
1713 /* When stopping units, warn if they can still be triggered by
1714 * another active unit (socket, path, timer) */
1715 if (!arg_quiet && streq(method, "StopUnit")) {
1717 check_triggering_units(bus, one_name);
1719 STRV_FOREACH(name, args+1)
1720 check_triggering_units(bus, *name);
1726 dbus_error_free(&error);
1731 /* Ask systemd-logind, which might grant access to unprivileged users
1732 * through PolicyKit */
1733 static int reboot_with_logind(DBusConnection *bus, enum action a) {
1736 dbus_bool_t interactive = true;
1738 polkit_agent_open_if_enabled();
1746 case ACTION_POWEROFF:
1747 method = "PowerOff";
1750 case ACTION_SUSPEND:
1754 case ACTION_HIBERNATE:
1755 method = "Hibernate";
1758 case ACTION_HYBRID_SLEEP:
1759 method = "HybridSleep";
1766 return bus_method_call_with_reply (
1768 "org.freedesktop.login1",
1769 "/org/freedesktop/login1",
1770 "org.freedesktop.login1.Manager",
1774 DBUS_TYPE_BOOLEAN, &interactive,
1781 static int start_special(DBusConnection *bus, char **args) {
1787 a = verb_to_action(args[0]);
1789 if (arg_force >= 2 && geteuid() != 0) {
1790 log_error("Must be root.");
1794 if (arg_force >= 2 &&
1795 (a == ACTION_HALT ||
1796 a == ACTION_POWEROFF ||
1797 a == ACTION_REBOOT))
1800 if (arg_force >= 1 &&
1801 (a == ACTION_HALT ||
1802 a == ACTION_POWEROFF ||
1803 a == ACTION_REBOOT ||
1804 a == ACTION_KEXEC ||
1806 return daemon_reload(bus, args);
1808 /* first try logind, to allow authentication with polkit */
1809 if (geteuid() != 0 &&
1810 (a == ACTION_POWEROFF ||
1811 a == ACTION_REBOOT ||
1812 a == ACTION_SUSPEND ||
1813 a == ACTION_HIBERNATE ||
1814 a == ACTION_HYBRID_SLEEP)) {
1815 r = reboot_with_logind(bus, a);
1820 r = start_unit(bus, args);
1827 static int check_unit_active(DBusConnection *bus, char **args) {
1829 int r = 3; /* According to LSB: "program is not running" */
1834 STRV_FOREACH(name, args+1) {
1835 char **check_states = strv_new("active", "reloading", NULL);
1836 int state = check_one_unit(bus, *name, check_states, arg_quiet);
1837 strv_free(check_states);
1847 static int check_unit_failed(DBusConnection *bus, char **args) {
1854 STRV_FOREACH(name, args+1) {
1855 char **check_states = strv_new("failed", NULL);
1856 int state = check_one_unit(bus, *name, check_states, arg_quiet);
1857 strv_free(check_states);
1867 static int kill_unit(DBusConnection *bus, char **args) {
1874 arg_kill_who = "all";
1876 STRV_FOREACH(name, args+1) {
1877 n = unit_name_mangle(*name);
1878 r = bus_method_call_with_reply (
1880 "org.freedesktop.systemd1",
1881 "/org/freedesktop/systemd1",
1882 "org.freedesktop.systemd1.Manager",
1886 DBUS_TYPE_STRING, n ? &n : name,
1887 DBUS_TYPE_STRING, &arg_kill_who,
1888 DBUS_TYPE_INT32, &arg_signal,
1897 typedef struct ExecStatusInfo {
1905 usec_t start_timestamp;
1906 usec_t exit_timestamp;
1911 LIST_FIELDS(struct ExecStatusInfo, exec);
1914 static void exec_status_info_free(ExecStatusInfo *i) {
1923 static int exec_status_info_deserialize(DBusMessageIter *sub, ExecStatusInfo *i) {
1924 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
1925 DBusMessageIter sub2, sub3;
1929 int32_t code, status;
1935 if (dbus_message_iter_get_arg_type(sub) != DBUS_TYPE_STRUCT)
1938 dbus_message_iter_recurse(sub, &sub2);
1940 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0)
1943 if (!(i->path = strdup(path)))
1946 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_ARRAY ||
1947 dbus_message_iter_get_element_type(&sub2) != DBUS_TYPE_STRING)
1951 dbus_message_iter_recurse(&sub2, &sub3);
1952 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
1953 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
1954 dbus_message_iter_next(&sub3);
1959 if (!(i->argv = new0(char*, n+1)))
1963 dbus_message_iter_recurse(&sub2, &sub3);
1964 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
1967 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
1968 dbus_message_iter_get_basic(&sub3, &s);
1969 dbus_message_iter_next(&sub3);
1971 if (!(i->argv[n++] = strdup(s)))
1975 if (!dbus_message_iter_next(&sub2) ||
1976 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, true) < 0 ||
1977 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp, true) < 0 ||
1978 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp_monotonic, true) < 0 ||
1979 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp, true) < 0 ||
1980 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp_monotonic, true) < 0 ||
1981 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, true) < 0 ||
1982 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &code, true) < 0 ||
1983 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &status, false) < 0)
1987 i->start_timestamp = (usec_t) start_timestamp;
1988 i->exit_timestamp = (usec_t) exit_timestamp;
1989 i->pid = (pid_t) pid;
1996 typedef struct UnitStatusInfo {
1998 const char *load_state;
1999 const char *active_state;
2000 const char *sub_state;
2001 const char *unit_file_state;
2003 const char *description;
2004 const char *following;
2006 char **documentation;
2008 const char *fragment_path;
2009 const char *source_path;
2010 const char *default_control_group;
2012 const char *load_error;
2015 usec_t inactive_exit_timestamp;
2016 usec_t inactive_exit_timestamp_monotonic;
2017 usec_t active_enter_timestamp;
2018 usec_t active_exit_timestamp;
2019 usec_t inactive_enter_timestamp;
2021 bool need_daemon_reload;
2026 const char *status_text;
2029 usec_t start_timestamp;
2030 usec_t exit_timestamp;
2032 int exit_code, exit_status;
2034 usec_t condition_timestamp;
2035 bool condition_result;
2038 unsigned n_accepted;
2039 unsigned n_connections;
2043 const char *sysfs_path;
2045 /* Mount, Automount */
2051 LIST_HEAD(ExecStatusInfo, exec);
2054 static void print_status_info(UnitStatusInfo *i) {
2056 const char *on, *off, *ss;
2058 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
2059 char since2[FORMAT_TIMESTAMP_MAX], *s2;
2064 /* This shows pretty information about a unit. See
2065 * print_property() for a low-level property printer */
2067 printf("%s", strna(i->id));
2069 if (i->description && !streq_ptr(i->id, i->description))
2070 printf(" - %s", i->description);
2075 printf("\t Follow: unit currently follows state of %s\n", i->following);
2077 if (streq_ptr(i->load_state, "error")) {
2078 on = ansi_highlight_red(true);
2079 off = ansi_highlight_red(false);
2083 path = i->source_path ? i->source_path : i->fragment_path;
2086 printf("\t Loaded: %s%s%s (Reason: %s)\n", on, strna(i->load_state), off, i->load_error);
2087 else if (path && i->unit_file_state)
2088 printf("\t Loaded: %s%s%s (%s; %s)\n", on, strna(i->load_state), off, path, i->unit_file_state);
2090 printf("\t Loaded: %s%s%s (%s)\n", on, strna(i->load_state), off, path);
2092 printf("\t Loaded: %s%s%s\n", on, strna(i->load_state), off);
2094 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
2096 if (streq_ptr(i->active_state, "failed")) {
2097 on = ansi_highlight_red(true);
2098 off = ansi_highlight_red(false);
2099 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
2100 on = ansi_highlight_green(true);
2101 off = ansi_highlight_green(false);
2106 printf("\t Active: %s%s (%s)%s",
2108 strna(i->active_state),
2112 printf("\t Active: %s%s%s",
2114 strna(i->active_state),
2117 if (!isempty(i->result) && !streq(i->result, "success"))
2118 printf(" (Result: %s)", i->result);
2120 timestamp = (streq_ptr(i->active_state, "active") ||
2121 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
2122 (streq_ptr(i->active_state, "inactive") ||
2123 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
2124 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
2125 i->active_exit_timestamp;
2127 s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
2128 s2 = format_timestamp(since2, sizeof(since2), timestamp);
2131 printf(" since %s; %s\n", s2, s1);
2133 printf(" since %s\n", s2);
2137 if (!i->condition_result && i->condition_timestamp > 0) {
2138 s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
2139 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
2142 printf("\t start condition failed at %s; %s\n", s2, s1);
2144 printf("\t start condition failed at %s\n", s2);
2148 printf("\t Device: %s\n", i->sysfs_path);
2150 printf("\t Where: %s\n", i->where);
2152 printf("\t What: %s\n", i->what);
2154 if (!strv_isempty(i->documentation)) {
2158 STRV_FOREACH(t, i->documentation) {
2160 printf("\t Docs: %s\n", *t);
2163 printf("\t %s\n", *t);
2168 printf("\tAccepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
2170 LIST_FOREACH(exec, p, i->exec) {
2174 /* Only show exited processes here */
2178 t = strv_join(p->argv, " ");
2179 printf("\t Process: %u %s=%s ", p->pid, p->name, strna(t));
2182 good = is_clean_exit_lsb(p->code, p->status, NULL);
2184 on = ansi_highlight_red(true);
2185 off = ansi_highlight_red(false);
2189 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
2191 if (p->code == CLD_EXITED) {
2194 printf("status=%i", p->status);
2196 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
2201 printf("signal=%s", signal_to_string(p->status));
2203 printf(")%s\n", off);
2205 if (i->main_pid == p->pid &&
2206 i->start_timestamp == p->start_timestamp &&
2207 i->exit_timestamp == p->start_timestamp)
2208 /* Let's not show this twice */
2211 if (p->pid == i->control_pid)
2215 if (i->main_pid > 0 || i->control_pid > 0) {
2218 if (i->main_pid > 0) {
2219 printf("Main PID: %u", (unsigned) i->main_pid);
2223 get_process_comm(i->main_pid, &t);
2228 } else if (i->exit_code > 0) {
2229 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
2231 if (i->exit_code == CLD_EXITED) {
2234 printf("status=%i", i->exit_status);
2236 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
2241 printf("signal=%s", signal_to_string(i->exit_status));
2246 if (i->main_pid > 0 && i->control_pid > 0)
2249 if (i->control_pid > 0) {
2252 printf(" Control: %u", (unsigned) i->control_pid);
2254 get_process_comm(i->control_pid, &t);
2265 printf("\t Status: \"%s\"\n", i->status_text);
2267 if (i->default_control_group &&
2268 (i->main_pid > 0 || i->control_pid > 0 || cg_is_empty_by_spec(i->default_control_group, false) == 0)) {
2271 printf("\t CGroup: %s\n", i->default_control_group);
2273 if (arg_transport != TRANSPORT_SSH) {
2283 if (i->main_pid > 0)
2284 extra[k++] = i->main_pid;
2286 if (i->control_pid > 0)
2287 extra[k++] = i->control_pid;
2289 show_cgroup_and_extra_by_spec(i->default_control_group, "\t\t ", c, false, arg_all, extra, k);
2293 if (i->id && arg_transport != TRANSPORT_SSH) {
2295 arg_all * OUTPUT_SHOW_ALL |
2296 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
2297 on_tty() * OUTPUT_COLOR |
2298 !arg_quiet * OUTPUT_WARN_CUTOFF;
2301 show_journal_by_unit(stdout,
2305 i->inactive_exit_timestamp_monotonic,
2310 if (i->need_daemon_reload)
2311 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %s daemon-reload' recommended.\n",
2312 ansi_highlight_red(true),
2313 ansi_highlight_red(false),
2314 arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
2317 static void show_unit_help(UnitStatusInfo *i) {
2322 if (!i->documentation) {
2323 log_info("Documentation for %s not known.", i->id);
2327 STRV_FOREACH(p, i->documentation) {
2329 if (startswith(*p, "man:")) {
2332 char *page = NULL, *section = NULL;
2333 const char *args[4] = { "man", NULL, NULL, NULL };
2338 if ((*p)[k-1] == ')')
2339 e = strrchr(*p, '(');
2342 page = strndup((*p) + 4, e - *p - 4);
2348 section = strndup(e + 1, *p + k - e - 2);
2362 log_error("Failed to fork: %m");
2370 execvp(args[0], (char**) args);
2371 log_error("Failed to execute man: %m");
2372 _exit(EXIT_FAILURE);
2378 wait_for_terminate(pid, NULL);
2380 log_info("Can't show: %s", *p);
2384 static int status_property(const char *name, DBusMessageIter *iter, UnitStatusInfo *i) {
2390 switch (dbus_message_iter_get_arg_type(iter)) {
2392 case DBUS_TYPE_STRING: {
2395 dbus_message_iter_get_basic(iter, &s);
2398 if (streq(name, "Id"))
2400 else if (streq(name, "LoadState"))
2402 else if (streq(name, "ActiveState"))
2403 i->active_state = s;
2404 else if (streq(name, "SubState"))
2406 else if (streq(name, "Description"))
2408 else if (streq(name, "FragmentPath"))
2409 i->fragment_path = s;
2410 else if (streq(name, "SourcePath"))
2412 else if (streq(name, "DefaultControlGroup"))
2413 i->default_control_group = s;
2414 else if (streq(name, "StatusText"))
2416 else if (streq(name, "SysFSPath"))
2418 else if (streq(name, "Where"))
2420 else if (streq(name, "What"))
2422 else if (streq(name, "Following"))
2424 else if (streq(name, "UnitFileState"))
2425 i->unit_file_state = s;
2426 else if (streq(name, "Result"))
2433 case DBUS_TYPE_BOOLEAN: {
2436 dbus_message_iter_get_basic(iter, &b);
2438 if (streq(name, "Accept"))
2440 else if (streq(name, "NeedDaemonReload"))
2441 i->need_daemon_reload = b;
2442 else if (streq(name, "ConditionResult"))
2443 i->condition_result = b;
2448 case DBUS_TYPE_UINT32: {
2451 dbus_message_iter_get_basic(iter, &u);
2453 if (streq(name, "MainPID")) {
2455 i->main_pid = (pid_t) u;
2458 } else if (streq(name, "ControlPID"))
2459 i->control_pid = (pid_t) u;
2460 else if (streq(name, "ExecMainPID")) {
2462 i->main_pid = (pid_t) u;
2463 } else if (streq(name, "NAccepted"))
2465 else if (streq(name, "NConnections"))
2466 i->n_connections = u;
2471 case DBUS_TYPE_INT32: {
2474 dbus_message_iter_get_basic(iter, &j);
2476 if (streq(name, "ExecMainCode"))
2477 i->exit_code = (int) j;
2478 else if (streq(name, "ExecMainStatus"))
2479 i->exit_status = (int) j;
2484 case DBUS_TYPE_UINT64: {
2487 dbus_message_iter_get_basic(iter, &u);
2489 if (streq(name, "ExecMainStartTimestamp"))
2490 i->start_timestamp = (usec_t) u;
2491 else if (streq(name, "ExecMainExitTimestamp"))
2492 i->exit_timestamp = (usec_t) u;
2493 else if (streq(name, "ActiveEnterTimestamp"))
2494 i->active_enter_timestamp = (usec_t) u;
2495 else if (streq(name, "InactiveEnterTimestamp"))
2496 i->inactive_enter_timestamp = (usec_t) u;
2497 else if (streq(name, "InactiveExitTimestamp"))
2498 i->inactive_exit_timestamp = (usec_t) u;
2499 else if (streq(name, "InactiveExitTimestampMonotonic"))
2500 i->inactive_exit_timestamp_monotonic = (usec_t) u;
2501 else if (streq(name, "ActiveExitTimestamp"))
2502 i->active_exit_timestamp = (usec_t) u;
2503 else if (streq(name, "ConditionTimestamp"))
2504 i->condition_timestamp = (usec_t) u;
2509 case DBUS_TYPE_ARRAY: {
2511 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
2512 startswith(name, "Exec")) {
2513 DBusMessageIter sub;
2515 dbus_message_iter_recurse(iter, &sub);
2516 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2517 ExecStatusInfo *info;
2520 if (!(info = new0(ExecStatusInfo, 1)))
2523 if (!(info->name = strdup(name))) {
2528 if ((r = exec_status_info_deserialize(&sub, info)) < 0) {
2533 LIST_PREPEND(ExecStatusInfo, exec, i->exec, info);
2535 dbus_message_iter_next(&sub);
2537 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
2538 streq(name, "Documentation")) {
2540 DBusMessageIter sub;
2542 dbus_message_iter_recurse(iter, &sub);
2543 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING) {
2547 dbus_message_iter_get_basic(&sub, &s);
2549 l = strv_append(i->documentation, s);
2553 strv_free(i->documentation);
2554 i->documentation = l;
2556 dbus_message_iter_next(&sub);
2563 case DBUS_TYPE_STRUCT: {
2565 if (streq(name, "LoadError")) {
2566 DBusMessageIter sub;
2567 const char *n, *message;
2570 dbus_message_iter_recurse(iter, &sub);
2572 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &n, true);
2576 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &message, false);
2580 if (!isempty(message))
2581 i->load_error = message;
2591 static int print_property(const char *name, DBusMessageIter *iter) {
2595 /* This is a low-level property printer, see
2596 * print_status_info() for the nicer output */
2598 if (arg_property && !strv_find(arg_property, name))
2601 switch (dbus_message_iter_get_arg_type(iter)) {
2603 case DBUS_TYPE_STRUCT: {
2604 DBusMessageIter sub;
2605 dbus_message_iter_recurse(iter, &sub);
2607 if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32 && streq(name, "Job")) {
2610 dbus_message_iter_get_basic(&sub, &u);
2613 printf("%s=%u\n", name, (unsigned) u);
2615 printf("%s=\n", name);
2618 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "Unit")) {
2621 dbus_message_iter_get_basic(&sub, &s);
2623 if (arg_all || s[0])
2624 printf("%s=%s\n", name, s);
2627 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "LoadError")) {
2628 const char *a = NULL, *b = NULL;
2630 if (bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &a, true) >= 0)
2631 bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &b, false);
2633 if (arg_all || !isempty(a) || !isempty(b))
2634 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
2642 case DBUS_TYPE_ARRAY:
2644 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "EnvironmentFiles")) {
2645 DBusMessageIter sub, sub2;
2647 dbus_message_iter_recurse(iter, &sub);
2648 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2652 dbus_message_iter_recurse(&sub, &sub2);
2654 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
2655 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) >= 0)
2656 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
2658 dbus_message_iter_next(&sub);
2663 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Paths")) {
2664 DBusMessageIter sub, sub2;
2666 dbus_message_iter_recurse(iter, &sub);
2667 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2668 const char *type, *path;
2670 dbus_message_iter_recurse(&sub, &sub2);
2672 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
2673 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
2674 printf("%s=%s\n", type, path);
2676 dbus_message_iter_next(&sub);
2681 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Timers")) {
2682 DBusMessageIter sub, sub2;
2684 dbus_message_iter_recurse(iter, &sub);
2685 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2687 uint64_t value, next_elapse;
2689 dbus_message_iter_recurse(&sub, &sub2);
2691 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &base, true) >= 0 &&
2692 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &value, true) >= 0 &&
2693 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &next_elapse, false) >= 0) {
2694 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
2696 printf("%s={ value=%s ; next_elapse=%s }\n",
2698 format_timespan(timespan1, sizeof(timespan1), value),
2699 format_timespan(timespan2, sizeof(timespan2), next_elapse));
2702 dbus_message_iter_next(&sub);
2707 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "ControlGroupAttributes")) {
2708 DBusMessageIter sub, sub2;
2710 dbus_message_iter_recurse(iter, &sub);
2711 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2712 const char *controller, *attr, *value;
2714 dbus_message_iter_recurse(&sub, &sub2);
2716 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &controller, true) >= 0 &&
2717 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &attr, true) >= 0 &&
2718 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &value, false) >= 0) {
2720 printf("ControlGroupAttribute={ controller=%s ; attribute=%s ; value=\"%s\" }\n",
2726 dbus_message_iter_next(&sub);
2731 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && startswith(name, "Exec")) {
2732 DBusMessageIter sub;
2734 dbus_message_iter_recurse(iter, &sub);
2735 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2736 ExecStatusInfo info;
2739 if (exec_status_info_deserialize(&sub, &info) >= 0) {
2740 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
2743 t = strv_join(info.argv, " ");
2745 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
2749 yes_no(info.ignore),
2750 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
2751 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
2752 (unsigned) info. pid,
2753 sigchld_code_to_string(info.code),
2755 info.code == CLD_EXITED ? "" : "/",
2756 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
2762 strv_free(info.argv);
2764 dbus_message_iter_next(&sub);
2773 if (generic_print_property(name, iter, arg_all) > 0)
2777 printf("%s=[unprintable]\n", name);
2782 static int show_one(const char *verb, DBusConnection *bus, const char *path, bool show_properties, bool *new_line) {
2783 DBusMessage *reply = NULL;
2784 const char *interface = "";
2786 DBusMessageIter iter, sub, sub2, sub3;
2787 UnitStatusInfo info;
2795 r = bus_method_call_with_reply (
2797 "org.freedesktop.systemd1",
2799 "org.freedesktop.DBus.Properties",
2803 DBUS_TYPE_STRING, &interface,
2808 if (!dbus_message_iter_init(reply, &iter) ||
2809 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
2810 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
2811 log_error("Failed to parse reply.");
2816 dbus_message_iter_recurse(&iter, &sub);
2823 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
2826 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_DICT_ENTRY) {
2827 log_error("Failed to parse reply.");
2832 dbus_message_iter_recurse(&sub, &sub2);
2834 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0) {
2835 log_error("Failed to parse reply.");
2840 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
2841 log_error("Failed to parse reply.");
2846 dbus_message_iter_recurse(&sub2, &sub3);
2848 if (show_properties)
2849 r = print_property(name, &sub3);
2851 r = status_property(name, &sub3, &info);
2854 log_error("Failed to parse reply.");
2859 dbus_message_iter_next(&sub);
2864 if (!show_properties) {
2865 if (streq(verb, "help"))
2866 show_unit_help(&info);
2868 print_status_info(&info);
2871 strv_free(info.documentation);
2873 if (!streq_ptr(info.active_state, "active") &&
2874 !streq_ptr(info.active_state, "reloading") &&
2875 streq(verb, "status"))
2876 /* According to LSB: "program not running" */
2879 while ((p = info.exec)) {
2880 LIST_REMOVE(ExecStatusInfo, exec, info.exec, p);
2881 exec_status_info_free(p);
2886 dbus_message_unref(reply);
2891 static int show_one_by_pid(const char *verb, DBusConnection *bus, uint32_t pid, bool *new_line) {
2892 DBusMessage *reply = NULL;
2893 const char *path = NULL;
2897 dbus_error_init(&error);
2899 r = bus_method_call_with_reply (
2901 "org.freedesktop.systemd1",
2902 "/org/freedesktop/systemd1",
2903 "org.freedesktop.systemd1.Manager",
2907 DBUS_TYPE_UINT32, &pid,
2912 if (!dbus_message_get_args(reply, &error,
2913 DBUS_TYPE_OBJECT_PATH, &path,
2914 DBUS_TYPE_INVALID)) {
2915 log_error("Failed to parse reply: %s", bus_error_message(&error));
2920 r = show_one(verb, bus, path, false, new_line);
2924 dbus_message_unref(reply);
2926 dbus_error_free(&error);
2931 static int show(DBusConnection *bus, char **args) {
2933 bool show_properties, new_line = false;
2939 show_properties = streq(args[0], "show");
2941 if (show_properties)
2942 pager_open_if_enabled();
2944 if (show_properties && strv_length(args) <= 1) {
2945 /* If not argument is specified inspect the manager
2948 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line);
2951 STRV_FOREACH(name, args+1) {
2954 if (safe_atou32(*name, &id) < 0) {
2956 /* Interpret as unit name */
2958 n = unit_name_mangle(*name);
2959 p = unit_dbus_path_from_name(n ? n : *name);
2964 r = show_one(args[0], bus, p, show_properties, &new_line);
2970 } else if (show_properties) {
2972 /* Interpret as job id */
2975 if (asprintf(&p, "/org/freedesktop/systemd1/job/%u", id) < 0)
2978 r = show_one(args[0], bus, p, show_properties, &new_line);
2986 /* Interpret as PID */
2988 r = show_one_by_pid(args[0], bus, id, &new_line);
2997 static int dump(DBusConnection *bus, char **args) {
2998 DBusMessage *reply = NULL;
3003 dbus_error_init(&error);
3005 pager_open_if_enabled();
3007 r = bus_method_call_with_reply (
3009 "org.freedesktop.systemd1",
3010 "/org/freedesktop/systemd1",
3011 "org.freedesktop.systemd1.Manager",
3019 if (!dbus_message_get_args(reply, &error,
3020 DBUS_TYPE_STRING, &text,
3021 DBUS_TYPE_INVALID)) {
3022 log_error("Failed to parse reply: %s", bus_error_message(&error));
3027 fputs(text, stdout);
3031 dbus_message_unref(reply);
3033 dbus_error_free(&error);
3038 static int snapshot(DBusConnection *bus, char **args) {
3039 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3042 dbus_bool_t cleanup = FALSE;
3043 DBusMessageIter iter, sub;
3045 *name = "", *path, *id,
3046 *interface = "org.freedesktop.systemd1.Unit",
3048 _cleanup_free_ char *n = NULL;
3050 dbus_error_init(&error);
3052 if (strv_length(args) > 1) {
3054 n = unit_name_mangle(name);
3057 r = bus_method_call_with_reply (
3059 "org.freedesktop.systemd1",
3060 "/org/freedesktop/systemd1",
3061 "org.freedesktop.systemd1.Manager",
3065 DBUS_TYPE_STRING, n ? (const char**) &n : &name,
3066 DBUS_TYPE_BOOLEAN, &cleanup,
3071 if (!dbus_message_get_args(reply, &error,
3072 DBUS_TYPE_OBJECT_PATH, &path,
3073 DBUS_TYPE_INVALID)) {
3074 log_error("Failed to parse reply: %s", bus_error_message(&error));
3079 dbus_message_unref(reply);
3082 r = bus_method_call_with_reply (
3084 "org.freedesktop.systemd1",
3086 "org.freedesktop.DBus.Properties",
3090 DBUS_TYPE_STRING, &interface,
3091 DBUS_TYPE_STRING, &property,
3096 if (!dbus_message_iter_init(reply, &iter) ||
3097 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3098 log_error("Failed to parse reply.");
3103 dbus_message_iter_recurse(&iter, &sub);
3105 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
3106 log_error("Failed to parse reply.");
3111 dbus_message_iter_get_basic(&sub, &id);
3117 dbus_error_free(&error);
3122 static int delete_snapshot(DBusConnection *bus, char **args) {
3127 STRV_FOREACH(name, args+1) {
3128 _cleanup_free_ char *n = NULL;
3131 n = unit_name_mangle(*name);
3132 r = bus_method_call_with_reply(
3134 "org.freedesktop.systemd1",
3135 "/org/freedesktop/systemd1",
3136 "org.freedesktop.systemd1.Manager",
3140 DBUS_TYPE_STRING, n ? &n : name,
3149 static int daemon_reload(DBusConnection *bus, char **args) {
3154 if (arg_action == ACTION_RELOAD)
3156 else if (arg_action == ACTION_REEXEC)
3157 method = "Reexecute";
3159 assert(arg_action == ACTION_SYSTEMCTL);
3162 streq(args[0], "clear-jobs") ||
3163 streq(args[0], "cancel") ? "ClearJobs" :
3164 streq(args[0], "daemon-reexec") ? "Reexecute" :
3165 streq(args[0], "reset-failed") ? "ResetFailed" :
3166 streq(args[0], "halt") ? "Halt" :
3167 streq(args[0], "poweroff") ? "PowerOff" :
3168 streq(args[0], "reboot") ? "Reboot" :
3169 streq(args[0], "kexec") ? "KExec" :
3170 streq(args[0], "exit") ? "Exit" :
3171 /* "daemon-reload" */ "Reload";
3174 r = bus_method_call_with_reply (
3176 "org.freedesktop.systemd1",
3177 "/org/freedesktop/systemd1",
3178 "org.freedesktop.systemd1.Manager",
3184 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
3185 /* There's always a fallback possible for
3186 * legacy actions. */
3188 else if (r == -ETIMEDOUT && streq(method, "Reexecute"))
3189 /* On reexecution, we expect a disconnect, not
3193 log_error("Failed to issue method call: %s", bus_error_message(&error));
3194 dbus_error_free(&error);
3199 static int reset_failed(DBusConnection *bus, char **args) {
3203 if (strv_length(args) <= 1)
3204 return daemon_reload(bus, args);
3206 STRV_FOREACH(name, args+1) {
3207 n = unit_name_mangle(*name);
3208 r = bus_method_call_with_reply (
3210 "org.freedesktop.systemd1",
3211 "/org/freedesktop/systemd1",
3212 "org.freedesktop.systemd1.Manager",
3216 DBUS_TYPE_STRING, n ? &n : name,
3227 static int show_enviroment(DBusConnection *bus, char **args) {
3228 DBusMessage *reply = NULL;
3229 DBusMessageIter iter, sub, sub2;
3232 *interface = "org.freedesktop.systemd1.Manager",
3233 *property = "Environment";
3235 pager_open_if_enabled();
3237 r = bus_method_call_with_reply (
3239 "org.freedesktop.systemd1",
3240 "/org/freedesktop/systemd1",
3241 "org.freedesktop.DBus.Properties",
3245 DBUS_TYPE_STRING, &interface,
3246 DBUS_TYPE_STRING, &property,
3251 if (!dbus_message_iter_init(reply, &iter) ||
3252 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3253 log_error("Failed to parse reply.");
3258 dbus_message_iter_recurse(&iter, &sub);
3260 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_ARRAY ||
3261 dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_STRING) {
3262 log_error("Failed to parse reply.");
3267 dbus_message_iter_recurse(&sub, &sub2);
3269 while (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_INVALID) {
3272 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
3273 log_error("Failed to parse reply.");
3278 dbus_message_iter_get_basic(&sub2, &text);
3279 printf("%s\n", text);
3281 dbus_message_iter_next(&sub2);
3288 dbus_message_unref(reply);
3293 static int switch_root(DBusConnection *bus, char **args) {
3296 _cleanup_free_ char *init = NULL;
3298 l = strv_length(args);
3299 if (l < 2 || l > 3) {
3300 log_error("Wrong number of arguments.");
3307 init = strdup(args[2]);
3309 parse_env_file("/proc/cmdline", WHITESPACE,
3321 log_debug("switching root - root: %s; init: %s", root, init);
3323 return bus_method_call_with_reply (
3325 "org.freedesktop.systemd1",
3326 "/org/freedesktop/systemd1",
3327 "org.freedesktop.systemd1.Manager",
3331 DBUS_TYPE_STRING, &root,
3332 DBUS_TYPE_STRING, &init,
3336 static int set_environment(DBusConnection *bus, char **args) {
3337 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
3340 DBusMessageIter iter;
3345 dbus_error_init(&error);
3347 method = streq(args[0], "set-environment")
3349 : "UnsetEnvironment";
3351 m = dbus_message_new_method_call(
3352 "org.freedesktop.systemd1",
3353 "/org/freedesktop/systemd1",
3354 "org.freedesktop.systemd1.Manager",
3359 dbus_message_iter_init_append(m, &iter);
3361 r = bus_append_strv_iter(&iter, args + 1);
3365 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3367 log_error("Failed to issue method call: %s", bus_error_message(&error));
3375 dbus_error_free(&error);
3379 static int enable_sysv_units(char **args) {
3382 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
3383 const char *verb = args[0];
3384 unsigned f = 1, t = 1;
3387 if (arg_scope != UNIT_FILE_SYSTEM)
3390 if (!streq(verb, "enable") &&
3391 !streq(verb, "disable") &&
3392 !streq(verb, "is-enabled"))
3395 /* Processes all SysV units, and reshuffles the array so that
3396 * afterwards only the native units remain */
3399 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, NULL, NULL, NULL);
3404 for (f = 1; args[f]; f++) {
3407 bool found_native = false, found_sysv;
3409 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
3410 char **k, *l, *q = NULL;
3417 if (!endswith(name, ".service"))
3420 if (path_is_absolute(name))
3423 STRV_FOREACH(k, paths.unit_path) {
3426 if (!isempty(arg_root))
3427 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
3429 asprintf(&p, "%s/%s", *k, name);
3436 found_native = access(p, F_OK) >= 0;
3447 if (!isempty(arg_root))
3448 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
3450 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
3456 p[strlen(p) - sizeof(".service") + 1] = 0;
3457 found_sysv = access(p, F_OK) >= 0;
3464 /* Mark this entry, so that we don't try enabling it as native unit */
3465 args[f] = (char*) "";
3467 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
3469 if (!isempty(arg_root))
3470 argv[c++] = q = strappend("--root=", arg_root);
3472 argv[c++] = path_get_file_name(p);
3474 streq(verb, "enable") ? "on" :
3475 streq(verb, "disable") ? "off" : "--level=5";
3478 l = strv_join((char**)argv, " ");
3486 log_info("Executing %s", l);
3491 log_error("Failed to fork: %m");
3496 } else if (pid == 0) {
3499 execv(argv[0], (char**) argv);
3500 _exit(EXIT_FAILURE);
3506 j = wait_for_terminate(pid, &status);
3508 log_error("Failed to wait for child: %s", strerror(-r));
3513 if (status.si_code == CLD_EXITED) {
3514 if (streq(verb, "is-enabled")) {
3515 if (status.si_status == 0) {
3524 } else if (status.si_status != 0) {
3535 lookup_paths_free(&paths);
3537 /* Drop all SysV units */
3538 for (f = 1, t = 1; args[f]; f++) {
3540 if (isempty(args[f]))
3543 args[t++] = args[f];
3552 static int mangle_names(char **original_names, char ***mangled_names) {
3553 char **i, **l, **name;
3555 l = new(char*, strv_length(original_names) + 1);
3560 STRV_FOREACH(name, original_names) {
3562 /* When enabling units qualified path names are OK,
3563 * too, hence allow them explicitly. */
3568 *i = unit_name_mangle(*name);
3584 static int enable_unit(DBusConnection *bus, char **args) {
3585 const char *verb = args[0];
3586 UnitFileChange *changes = NULL;
3587 unsigned n_changes = 0, i;
3588 int carries_install_info = -1;
3589 DBusMessage *m = NULL, *reply = NULL;
3592 char **mangled_names = NULL;
3594 r = enable_sysv_units(args);
3601 dbus_error_init(&error);
3603 if (!bus || avoid_bus()) {
3604 if (streq(verb, "enable")) {
3605 r = unit_file_enable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3606 carries_install_info = r;
3607 } else if (streq(verb, "disable"))
3608 r = unit_file_disable(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3609 else if (streq(verb, "reenable")) {
3610 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3611 carries_install_info = r;
3612 } else if (streq(verb, "link"))
3613 r = unit_file_link(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3614 else if (streq(verb, "preset")) {
3615 r = unit_file_preset(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3616 carries_install_info = r;
3617 } else if (streq(verb, "mask"))
3618 r = unit_file_mask(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3619 else if (streq(verb, "unmask"))
3620 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3622 assert_not_reached("Unknown verb");
3625 log_error("Operation failed: %s", strerror(-r));
3630 for (i = 0; i < n_changes; i++) {
3631 if (changes[i].type == UNIT_FILE_SYMLINK)
3632 log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
3634 log_info("rm '%s'", changes[i].path);
3641 bool send_force = true, expect_carries_install_info = false;
3643 DBusMessageIter iter, sub, sub2;
3645 if (streq(verb, "enable")) {
3646 method = "EnableUnitFiles";
3647 expect_carries_install_info = true;
3648 } else if (streq(verb, "disable")) {
3649 method = "DisableUnitFiles";
3651 } else if (streq(verb, "reenable")) {
3652 method = "ReenableUnitFiles";
3653 expect_carries_install_info = true;
3654 } else if (streq(verb, "link"))
3655 method = "LinkUnitFiles";
3656 else if (streq(verb, "preset")) {
3657 method = "PresetUnitFiles";
3658 expect_carries_install_info = true;
3659 } else if (streq(verb, "mask"))
3660 method = "MaskUnitFiles";
3661 else if (streq(verb, "unmask")) {
3662 method = "UnmaskUnitFiles";
3665 assert_not_reached("Unknown verb");
3667 m = dbus_message_new_method_call(
3668 "org.freedesktop.systemd1",
3669 "/org/freedesktop/systemd1",
3670 "org.freedesktop.systemd1.Manager",
3677 dbus_message_iter_init_append(m, &iter);
3679 r = mangle_names(args+1, &mangled_names);
3683 r = bus_append_strv_iter(&iter, mangled_names);
3685 log_error("Failed to append unit files.");
3690 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &a)) {
3691 log_error("Failed to append runtime boolean.");
3699 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b)) {
3700 log_error("Failed to append force boolean.");
3706 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3708 log_error("Failed to issue method call: %s", bus_error_message(&error));
3713 if (!dbus_message_iter_init(reply, &iter)) {
3714 log_error("Failed to initialize iterator.");
3718 if (expect_carries_install_info) {
3719 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &b, true);
3721 log_error("Failed to parse reply.");
3725 carries_install_info = b;
3728 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3729 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
3730 log_error("Failed to parse reply.");
3735 dbus_message_iter_recurse(&iter, &sub);
3736 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
3737 const char *type, *path, *source;
3739 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
3740 log_error("Failed to parse reply.");
3745 dbus_message_iter_recurse(&sub, &sub2);
3747 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
3748 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
3749 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &source, false) < 0) {
3750 log_error("Failed to parse reply.");
3756 if (streq(type, "symlink"))
3757 log_info("ln -s '%s' '%s'", source, path);
3759 log_info("rm '%s'", path);
3762 dbus_message_iter_next(&sub);
3765 /* Try to reload if enabeld */
3767 r = daemon_reload(bus, args);
3770 if (carries_install_info == 0)
3772 "The unit files have no [Install] section. They are not meant to be enabled\n"
3773 "using systemctl.\n"
3774 "Possible reasons for having this kind of units are:\n"
3775 "1) A unit may be statically enabled by being symlinked from another unit's\n"
3776 " .wants/ or .requires/ directory.\n"
3777 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
3778 " a requirement dependency on it.\n"
3779 "3) A unit may be started when needed via activation (socket, path, timer,\n"
3780 " D-Bus, udev, scripted systemctl call, ...).\n");
3784 dbus_message_unref(m);
3787 dbus_message_unref(reply);
3789 unit_file_changes_free(changes, n_changes);
3791 dbus_error_free(&error);
3793 strv_free(mangled_names);
3798 static int unit_is_enabled(DBusConnection *bus, char **args) {
3801 DBusMessage *reply = NULL;
3805 dbus_error_init(&error);
3807 r = enable_sysv_units(args);
3813 if (!bus || avoid_bus()) {
3815 STRV_FOREACH(name, args+1) {
3816 UnitFileState state;
3818 state = unit_file_get_state(arg_scope, arg_root, *name);
3824 if (state == UNIT_FILE_ENABLED ||
3825 state == UNIT_FILE_ENABLED_RUNTIME ||
3826 state == UNIT_FILE_STATIC)
3830 puts(unit_file_state_to_string(state));
3834 STRV_FOREACH(name, args+1) {
3837 r = bus_method_call_with_reply (
3839 "org.freedesktop.systemd1",
3840 "/org/freedesktop/systemd1",
3841 "org.freedesktop.systemd1.Manager",
3845 DBUS_TYPE_STRING, name,
3850 if (!dbus_message_get_args(reply, &error,
3851 DBUS_TYPE_STRING, &s,
3852 DBUS_TYPE_INVALID)) {
3853 log_error("Failed to parse reply: %s", bus_error_message(&error));
3858 dbus_message_unref(reply);
3861 if (streq(s, "enabled") ||
3862 streq(s, "enabled-runtime") ||
3871 r = enabled ? 0 : 1;
3875 dbus_message_unref(reply);
3877 dbus_error_free(&error);
3881 static int systemctl_help(void) {
3883 pager_open_if_enabled();
3885 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
3886 "Query or send control commands to the systemd manager.\n\n"
3887 " -h --help Show this help\n"
3888 " --version Show package version\n"
3889 " -t --type=TYPE List only units of a particular type\n"
3890 " -p --property=NAME Show only properties by this name\n"
3891 " -a --all Show all units/properties, including dead/empty ones\n"
3892 " --failed Show only failed units\n"
3893 " --full Don't ellipsize unit names on output\n"
3894 " --fail When queueing a new job, fail if conflicting jobs are\n"
3896 " --ignore-dependencies\n"
3897 " When queueing a new job, ignore all its dependencies\n"
3898 " --kill-who=WHO Who to send signal to\n"
3899 " -s --signal=SIGNAL Which signal to send\n"
3900 " -H --host=[USER@]HOST\n"
3901 " Show information for remote host\n"
3902 " -P --privileged Acquire privileges before execution\n"
3903 " -q --quiet Suppress output\n"
3904 " --no-block Do not wait until operation finished\n"
3905 " --no-wall Don't send wall message before halt/power-off/reboot\n"
3906 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
3908 " --no-legend Do not print a legend (column headers and hints)\n"
3909 " --no-pager Do not pipe output into a pager\n"
3910 " --no-ask-password\n"
3911 " Do not ask for system passwords\n"
3912 " --order When generating graph for dot, show only order\n"
3913 " --require When generating graph for dot, show only requirement\n"
3914 " --system Connect to system manager\n"
3915 " --user Connect to user service manager\n"
3916 " --global Enable/disable unit files globally\n"
3917 " -f --force When enabling unit files, override existing symlinks\n"
3918 " When shutting down, execute action immediately\n"
3919 " --root=PATH Enable unit files in the specified root directory\n"
3920 " --runtime Enable unit files only temporarily until next reboot\n"
3921 " -n --lines=INTEGER Journal entries to show\n"
3922 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
3923 " verbose, export, json, json-pretty, json-sse, cat)\n\n"
3925 " list-units List loaded units\n"
3926 " start [NAME...] Start (activate) one or more units\n"
3927 " stop [NAME...] Stop (deactivate) one or more units\n"
3928 " reload [NAME...] Reload one or more units\n"
3929 " restart [NAME...] Start or restart one or more units\n"
3930 " try-restart [NAME...] Restart one or more units if active\n"
3931 " reload-or-restart [NAME...] Reload one or more units if possible,\n"
3932 " otherwise start or restart\n"
3933 " reload-or-try-restart [NAME...] Reload one or more units if possible,\n"
3934 " otherwise restart if active\n"
3935 " isolate [NAME] Start one unit and stop all others\n"
3936 " kill [NAME...] Send signal to processes of a unit\n"
3937 " is-active [NAME...] Check whether units are active\n"
3938 " is-failed [NAME...] Check whether units are failed\n"
3939 " status [NAME...|PID...] Show runtime status of one or more units\n"
3940 " show [NAME...|JOB...] Show properties of one or more\n"
3941 " units/jobs or the manager\n"
3942 " help [NAME...|PID...] Show manual for one or more units\n"
3943 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
3945 " load [NAME...] Load one or more units\n\n"
3946 "Unit File Commands:\n"
3947 " list-unit-files List installed unit files\n"
3948 " enable [NAME...] Enable one or more unit files\n"
3949 " disable [NAME...] Disable one or more unit files\n"
3950 " reenable [NAME...] Reenable one or more unit files\n"
3951 " preset [NAME...] Enable/disable one or more unit files\n"
3952 " based on preset configuration\n"
3953 " mask [NAME...] Mask one or more units\n"
3954 " unmask [NAME...] Unmask one or more units\n"
3955 " link [PATH...] Link one or more units files into\n"
3956 " the search path\n"
3957 " is-enabled [NAME...] Check whether unit files are enabled\n\n"
3959 " list-jobs List jobs\n"
3960 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
3961 "Status Commands:\n"
3962 " dump Dump server status\n"
3963 " dot Dump dependency graph for dot(1)\n\n"
3964 "Snapshot Commands:\n"
3965 " snapshot [NAME] Create a snapshot\n"
3966 " delete [NAME...] Remove one or more snapshots\n\n"
3967 "Environment Commands:\n"
3968 " show-environment Dump environment\n"
3969 " set-environment [NAME=VALUE...] Set one or more environment variables\n"
3970 " unset-environment [NAME...] Unset one or more environment variables\n\n"
3971 "Manager Lifecycle Commands:\n"
3972 " daemon-reload Reload systemd manager configuration\n"
3973 " daemon-reexec Reexecute systemd manager\n\n"
3974 "System Commands:\n"
3975 " default Enter system default mode\n"
3976 " rescue Enter system rescue mode\n"
3977 " emergency Enter system emergency mode\n"
3978 " halt Shut down and halt the system\n"
3979 " poweroff Shut down and power-off the system\n"
3980 " reboot Shut down and reboot the system\n"
3981 " kexec Shut down and reboot the system with kexec\n"
3982 " exit Request user instance exit\n"
3983 " switch-root [ROOT] [INIT] Change to a different root file system\n"
3984 " suspend Suspend the system\n"
3985 " hibernate Hibernate the system\n"
3986 " hybrid-sleep Hibernate and suspend the system\n",
3987 program_invocation_short_name);
3992 static int halt_help(void) {
3994 printf("%s [OPTIONS...]\n\n"
3995 "%s the system.\n\n"
3996 " --help Show this help\n"
3997 " --halt Halt the machine\n"
3998 " -p --poweroff Switch off the machine\n"
3999 " --reboot Reboot the machine\n"
4000 " -f --force Force immediate halt/power-off/reboot\n"
4001 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
4002 " -d --no-wtmp Don't write wtmp record\n"
4003 " --no-wall Don't send wall message before halt/power-off/reboot\n",
4004 program_invocation_short_name,
4005 arg_action == ACTION_REBOOT ? "Reboot" :
4006 arg_action == ACTION_POWEROFF ? "Power off" :
4012 static int shutdown_help(void) {
4014 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
4015 "Shut down the system.\n\n"
4016 " --help Show this help\n"
4017 " -H --halt Halt the machine\n"
4018 " -P --poweroff Power-off the machine\n"
4019 " -r --reboot Reboot the machine\n"
4020 " -h Equivalent to --poweroff, overridden by --halt\n"
4021 " -k Don't halt/power-off/reboot, just send warnings\n"
4022 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4023 " -c Cancel a pending shutdown\n",
4024 program_invocation_short_name);
4029 static int telinit_help(void) {
4031 printf("%s [OPTIONS...] {COMMAND}\n\n"
4032 "Send control commands to the init daemon.\n\n"
4033 " --help Show this help\n"
4034 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
4036 " 0 Power-off the machine\n"
4037 " 6 Reboot the machine\n"
4038 " 2, 3, 4, 5 Start runlevelX.target unit\n"
4039 " 1, s, S Enter rescue mode\n"
4040 " q, Q Reload init daemon configuration\n"
4041 " u, U Reexecute init daemon\n",
4042 program_invocation_short_name);
4047 static int runlevel_help(void) {
4049 printf("%s [OPTIONS...]\n\n"
4050 "Prints the previous and current runlevel of the init system.\n\n"
4051 " --help Show this help\n",
4052 program_invocation_short_name);
4057 static int help_types(void) {
4060 puts("Available unit types:");
4061 for(i = UNIT_SERVICE; i < _UNIT_TYPE_MAX; i++)
4062 if (unit_type_table[i])
4063 puts(unit_type_table[i]);
4065 puts("\nAvailable unit load states: ");
4066 for(i = UNIT_STUB; i < _UNIT_LOAD_STATE_MAX; i++)
4067 if (unit_type_table[i])
4068 puts(unit_load_state_table[i]);
4073 static int systemctl_parse_argv(int argc, char *argv[]) {
4077 ARG_IGNORE_DEPENDENCIES,
4092 ARG_NO_ASK_PASSWORD,
4098 static const struct option options[] = {
4099 { "help", no_argument, NULL, 'h' },
4100 { "version", no_argument, NULL, ARG_VERSION },
4101 { "type", required_argument, NULL, 't' },
4102 { "property", required_argument, NULL, 'p' },
4103 { "all", no_argument, NULL, 'a' },
4104 { "failed", no_argument, NULL, ARG_FAILED },
4105 { "full", no_argument, NULL, ARG_FULL },
4106 { "fail", no_argument, NULL, ARG_FAIL },
4107 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
4108 { "user", no_argument, NULL, ARG_USER },
4109 { "system", no_argument, NULL, ARG_SYSTEM },
4110 { "global", no_argument, NULL, ARG_GLOBAL },
4111 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
4112 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
4113 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
4114 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4115 { "quiet", no_argument, NULL, 'q' },
4116 { "order", no_argument, NULL, ARG_ORDER },
4117 { "require", no_argument, NULL, ARG_REQUIRE },
4118 { "root", required_argument, NULL, ARG_ROOT },
4119 { "force", no_argument, NULL, ARG_FORCE },
4120 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
4121 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
4122 { "signal", required_argument, NULL, 's' },
4123 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
4124 { "host", required_argument, NULL, 'H' },
4125 { "privileged",no_argument, NULL, 'P' },
4126 { "runtime", no_argument, NULL, ARG_RUNTIME },
4127 { "lines", required_argument, NULL, 'n' },
4128 { "output", required_argument, NULL, 'o' },
4129 { NULL, 0, NULL, 0 }
4137 while ((c = getopt_long(argc, argv, "ht:p:aqfs:H:Pn:o:", options, NULL)) >= 0) {
4146 puts(PACKAGE_STRING);
4147 puts(SYSTEMD_FEATURES);
4151 if (streq(optarg, "help")) {
4156 if (unit_type_from_string(optarg) >= 0) {
4160 if (unit_load_state_from_string(optarg) >= 0) {
4161 arg_load_state = optarg;
4164 log_error("Unkown unit type or load state '%s'.",
4166 log_info("Use -t help to see a list of allowed values.");
4171 if (!(l = strv_append(arg_property, optarg)))
4174 strv_free(arg_property);
4177 /* If the user asked for a particular
4178 * property, show it to him, even if it is
4189 arg_job_mode = "fail";
4192 case ARG_IGNORE_DEPENDENCIES:
4193 arg_job_mode = "ignore-dependencies";
4197 arg_scope = UNIT_FILE_USER;
4201 arg_scope = UNIT_FILE_SYSTEM;
4205 arg_scope = UNIT_FILE_GLOBAL;
4209 arg_no_block = true;
4213 arg_no_legend = true;
4217 arg_no_pager = true;
4225 arg_dot = DOT_ORDER;
4229 arg_dot = DOT_REQUIRE;
4257 arg_no_reload = true;
4261 arg_kill_who = optarg;
4265 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
4266 log_error("Failed to parse signal string %s.", optarg);
4271 case ARG_NO_ASK_PASSWORD:
4272 arg_ask_password = false;
4276 arg_transport = TRANSPORT_POLKIT;
4280 arg_transport = TRANSPORT_SSH;
4289 if (safe_atou(optarg, &arg_lines) < 0) {
4290 log_error("Failed to parse lines '%s'", optarg);
4296 arg_output = output_mode_from_string(optarg);
4297 if (arg_output < 0) {
4298 log_error("Unknown output '%s'.", optarg);
4307 log_error("Unknown option code '%c'.", c);
4312 if (arg_transport != TRANSPORT_NORMAL && arg_scope != UNIT_FILE_SYSTEM) {
4313 log_error("Cannot access user instance remotely.");
4320 static int halt_parse_argv(int argc, char *argv[]) {
4329 static const struct option options[] = {
4330 { "help", no_argument, NULL, ARG_HELP },
4331 { "halt", no_argument, NULL, ARG_HALT },
4332 { "poweroff", no_argument, NULL, 'p' },
4333 { "reboot", no_argument, NULL, ARG_REBOOT },
4334 { "force", no_argument, NULL, 'f' },
4335 { "wtmp-only", no_argument, NULL, 'w' },
4336 { "no-wtmp", no_argument, NULL, 'd' },
4337 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4338 { NULL, 0, NULL, 0 }
4346 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
4347 if (runlevel == '0' || runlevel == '6')
4350 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
4358 arg_action = ACTION_HALT;
4362 if (arg_action != ACTION_REBOOT)
4363 arg_action = ACTION_POWEROFF;
4367 arg_action = ACTION_REBOOT;
4389 /* Compatibility nops */
4396 log_error("Unknown option code '%c'.", c);
4401 if (optind < argc) {
4402 log_error("Too many arguments.");
4409 static int parse_time_spec(const char *t, usec_t *_u) {
4413 if (streq(t, "now"))
4415 else if (!strchr(t, ':')) {
4418 if (safe_atou64(t, &u) < 0)
4421 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
4430 hour = strtol(t, &e, 10);
4431 if (errno != 0 || *e != ':' || hour < 0 || hour > 23)
4434 minute = strtol(e+1, &e, 10);
4435 if (errno != 0 || *e != 0 || minute < 0 || minute > 59)
4438 n = now(CLOCK_REALTIME);
4439 s = (time_t) (n / USEC_PER_SEC);
4442 assert_se(localtime_r(&s, &tm));
4444 tm.tm_hour = (int) hour;
4445 tm.tm_min = (int) minute;
4448 assert_se(s = mktime(&tm));
4450 *_u = (usec_t) s * USEC_PER_SEC;
4453 *_u += USEC_PER_DAY;
4459 static int shutdown_parse_argv(int argc, char *argv[]) {
4466 static const struct option options[] = {
4467 { "help", no_argument, NULL, ARG_HELP },
4468 { "halt", no_argument, NULL, 'H' },
4469 { "poweroff", no_argument, NULL, 'P' },
4470 { "reboot", no_argument, NULL, 'r' },
4471 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
4472 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4473 { NULL, 0, NULL, 0 }
4481 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
4489 arg_action = ACTION_HALT;
4493 arg_action = ACTION_POWEROFF;
4498 arg_action = ACTION_KEXEC;
4500 arg_action = ACTION_REBOOT;
4504 arg_action = ACTION_KEXEC;
4508 if (arg_action != ACTION_HALT)
4509 arg_action = ACTION_POWEROFF;
4522 /* Compatibility nops */
4526 arg_action = ACTION_CANCEL_SHUTDOWN;
4533 log_error("Unknown option code '%c'.", c);
4538 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
4539 r = parse_time_spec(argv[optind], &arg_when);
4541 log_error("Failed to parse time specification: %s", argv[optind]);
4545 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
4547 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
4548 /* No time argument for shutdown cancel */
4549 arg_wall = argv + optind;
4550 else if (argc > optind + 1)
4551 /* We skip the time argument */
4552 arg_wall = argv + optind + 1;
4559 static int telinit_parse_argv(int argc, char *argv[]) {
4566 static const struct option options[] = {
4567 { "help", no_argument, NULL, ARG_HELP },
4568 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4569 { NULL, 0, NULL, 0 }
4572 static const struct {
4576 { '0', ACTION_POWEROFF },
4577 { '6', ACTION_REBOOT },
4578 { '1', ACTION_RESCUE },
4579 { '2', ACTION_RUNLEVEL2 },
4580 { '3', ACTION_RUNLEVEL3 },
4581 { '4', ACTION_RUNLEVEL4 },
4582 { '5', ACTION_RUNLEVEL5 },
4583 { 's', ACTION_RESCUE },
4584 { 'S', ACTION_RESCUE },
4585 { 'q', ACTION_RELOAD },
4586 { 'Q', ACTION_RELOAD },
4587 { 'u', ACTION_REEXEC },
4588 { 'U', ACTION_REEXEC }
4597 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4612 log_error("Unknown option code '%c'.", c);
4617 if (optind >= argc) {
4622 if (optind + 1 < argc) {
4623 log_error("Too many arguments.");
4627 if (strlen(argv[optind]) != 1) {
4628 log_error("Expected single character argument.");
4632 for (i = 0; i < ELEMENTSOF(table); i++)
4633 if (table[i].from == argv[optind][0])
4636 if (i >= ELEMENTSOF(table)) {
4637 log_error("Unknown command '%s'.", argv[optind]);
4641 arg_action = table[i].to;
4648 static int runlevel_parse_argv(int argc, char *argv[]) {
4654 static const struct option options[] = {
4655 { "help", no_argument, NULL, ARG_HELP },
4656 { NULL, 0, NULL, 0 }
4664 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4675 log_error("Unknown option code '%c'.", c);
4680 if (optind < argc) {
4681 log_error("Too many arguments.");
4688 static int parse_argv(int argc, char *argv[]) {
4692 if (program_invocation_short_name) {
4694 if (strstr(program_invocation_short_name, "halt")) {
4695 arg_action = ACTION_HALT;
4696 return halt_parse_argv(argc, argv);
4697 } else if (strstr(program_invocation_short_name, "poweroff")) {
4698 arg_action = ACTION_POWEROFF;
4699 return halt_parse_argv(argc, argv);
4700 } else if (strstr(program_invocation_short_name, "reboot")) {
4702 arg_action = ACTION_KEXEC;
4704 arg_action = ACTION_REBOOT;
4705 return halt_parse_argv(argc, argv);
4706 } else if (strstr(program_invocation_short_name, "shutdown")) {
4707 arg_action = ACTION_POWEROFF;
4708 return shutdown_parse_argv(argc, argv);
4709 } else if (strstr(program_invocation_short_name, "init")) {
4711 if (sd_booted() > 0) {
4712 arg_action = ACTION_INVALID;
4713 return telinit_parse_argv(argc, argv);
4715 /* Hmm, so some other init system is
4716 * running, we need to forward this
4717 * request to it. For now we simply
4718 * guess that it is Upstart. */
4720 execv("/lib/upstart/telinit", argv);
4722 log_error("Couldn't find an alternative telinit implementation to spawn.");
4726 } else if (strstr(program_invocation_short_name, "runlevel")) {
4727 arg_action = ACTION_RUNLEVEL;
4728 return runlevel_parse_argv(argc, argv);
4732 arg_action = ACTION_SYSTEMCTL;
4733 return systemctl_parse_argv(argc, argv);
4736 static int action_to_runlevel(void) {
4738 static const char table[_ACTION_MAX] = {
4739 [ACTION_HALT] = '0',
4740 [ACTION_POWEROFF] = '0',
4741 [ACTION_REBOOT] = '6',
4742 [ACTION_RUNLEVEL2] = '2',
4743 [ACTION_RUNLEVEL3] = '3',
4744 [ACTION_RUNLEVEL4] = '4',
4745 [ACTION_RUNLEVEL5] = '5',
4746 [ACTION_RESCUE] = '1'
4749 assert(arg_action < _ACTION_MAX);
4751 return table[arg_action];
4754 static int talk_upstart(void) {
4755 DBusMessage *m = NULL, *reply = NULL;
4757 int previous, rl, r;
4759 env1_buf[] = "RUNLEVEL=X",
4760 env2_buf[] = "PREVLEVEL=X";
4761 char *env1 = env1_buf, *env2 = env2_buf;
4762 const char *emit = "runlevel";
4763 dbus_bool_t b_false = FALSE;
4764 DBusMessageIter iter, sub;
4765 DBusConnection *bus;
4767 dbus_error_init(&error);
4769 if (!(rl = action_to_runlevel()))
4772 if (utmp_get_runlevel(&previous, NULL) < 0)
4775 if (!(bus = dbus_connection_open_private("unix:abstract=/com/ubuntu/upstart", &error))) {
4776 if (dbus_error_has_name(&error, DBUS_ERROR_NO_SERVER)) {
4781 log_error("Failed to connect to Upstart bus: %s", bus_error_message(&error));
4786 if ((r = bus_check_peercred(bus)) < 0) {
4787 log_error("Failed to verify owner of bus.");
4791 if (!(m = dbus_message_new_method_call(
4792 "com.ubuntu.Upstart",
4793 "/com/ubuntu/Upstart",
4794 "com.ubuntu.Upstart0_6",
4797 log_error("Could not allocate message.");
4802 dbus_message_iter_init_append(m, &iter);
4804 env1_buf[sizeof(env1_buf)-2] = rl;
4805 env2_buf[sizeof(env2_buf)-2] = previous;
4807 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &emit) ||
4808 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub) ||
4809 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env1) ||
4810 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env2) ||
4811 !dbus_message_iter_close_container(&iter, &sub) ||
4812 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b_false)) {
4813 log_error("Could not append arguments to message.");
4818 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
4820 if (bus_error_is_no_service(&error)) {
4825 log_error("Failed to issue method call: %s", bus_error_message(&error));
4834 dbus_message_unref(m);
4837 dbus_message_unref(reply);
4840 dbus_connection_flush(bus);
4841 dbus_connection_close(bus);
4842 dbus_connection_unref(bus);
4845 dbus_error_free(&error);
4850 static int talk_initctl(void) {
4851 struct init_request request;
4855 if (!(rl = action_to_runlevel()))
4859 request.magic = INIT_MAGIC;
4860 request.sleeptime = 0;
4861 request.cmd = INIT_CMD_RUNLVL;
4862 request.runlevel = rl;
4864 if ((fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY)) < 0) {
4866 if (errno == ENOENT)
4869 log_error("Failed to open "INIT_FIFO": %m");
4874 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
4875 close_nointr_nofail(fd);
4878 log_error("Failed to write to "INIT_FIFO": %m");
4879 return errno ? -errno : -EIO;
4885 static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
4887 static const struct {
4895 int (* const dispatch)(DBusConnection *bus, char **args);
4897 { "list-units", LESS, 1, list_units },
4898 { "list-unit-files", EQUAL, 1, list_unit_files },
4899 { "list-jobs", EQUAL, 1, list_jobs },
4900 { "clear-jobs", EQUAL, 1, daemon_reload },
4901 { "load", MORE, 2, load_unit },
4902 { "cancel", MORE, 2, cancel_job },
4903 { "start", MORE, 2, start_unit },
4904 { "stop", MORE, 2, start_unit },
4905 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
4906 { "reload", MORE, 2, start_unit },
4907 { "restart", MORE, 2, start_unit },
4908 { "try-restart", MORE, 2, start_unit },
4909 { "reload-or-restart", MORE, 2, start_unit },
4910 { "reload-or-try-restart", MORE, 2, start_unit },
4911 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
4912 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
4913 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
4914 { "isolate", EQUAL, 2, start_unit },
4915 { "kill", MORE, 2, kill_unit },
4916 { "is-active", MORE, 2, check_unit_active },
4917 { "check", MORE, 2, check_unit_active },
4918 { "is-failed", MORE, 2, check_unit_failed },
4919 { "show", MORE, 1, show },
4920 { "status", MORE, 2, show },
4921 { "help", MORE, 2, show },
4922 { "dump", EQUAL, 1, dump },
4923 { "dot", EQUAL, 1, dot },
4924 { "snapshot", LESS, 2, snapshot },
4925 { "delete", MORE, 2, delete_snapshot },
4926 { "daemon-reload", EQUAL, 1, daemon_reload },
4927 { "daemon-reexec", EQUAL, 1, daemon_reload },
4928 { "show-environment", EQUAL, 1, show_enviroment },
4929 { "set-environment", MORE, 2, set_environment },
4930 { "unset-environment", MORE, 2, set_environment },
4931 { "halt", EQUAL, 1, start_special },
4932 { "poweroff", EQUAL, 1, start_special },
4933 { "reboot", EQUAL, 1, start_special },
4934 { "kexec", EQUAL, 1, start_special },
4935 { "suspend", EQUAL, 1, start_special },
4936 { "hibernate", EQUAL, 1, start_special },
4937 { "hybrid-sleep", EQUAL, 1, start_special },
4938 { "default", EQUAL, 1, start_special },
4939 { "rescue", EQUAL, 1, start_special },
4940 { "emergency", EQUAL, 1, start_special },
4941 { "exit", EQUAL, 1, start_special },
4942 { "reset-failed", MORE, 1, reset_failed },
4943 { "enable", MORE, 2, enable_unit },
4944 { "disable", MORE, 2, enable_unit },
4945 { "is-enabled", MORE, 2, unit_is_enabled },
4946 { "reenable", MORE, 2, enable_unit },
4947 { "preset", MORE, 2, enable_unit },
4948 { "mask", MORE, 2, enable_unit },
4949 { "unmask", MORE, 2, enable_unit },
4950 { "link", MORE, 2, enable_unit },
4951 { "switch-root", MORE, 2, switch_root },
4961 left = argc - optind;
4964 /* Special rule: no arguments means "list-units" */
4967 if (streq(argv[optind], "help") && !argv[optind+1]) {
4968 log_error("This command expects one or more "
4969 "unit names. Did you mean --help?");
4973 for (i = 0; i < ELEMENTSOF(verbs); i++)
4974 if (streq(argv[optind], verbs[i].verb))
4977 if (i >= ELEMENTSOF(verbs)) {
4978 log_error("Unknown operation '%s'.", argv[optind]);
4983 switch (verbs[i].argc_cmp) {
4986 if (left != verbs[i].argc) {
4987 log_error("Invalid number of arguments.");
4994 if (left < verbs[i].argc) {
4995 log_error("Too few arguments.");
5002 if (left > verbs[i].argc) {
5003 log_error("Too many arguments.");
5010 assert_not_reached("Unknown comparison operator.");
5013 /* Require a bus connection for all operations but
5015 if (!streq(verbs[i].verb, "enable") &&
5016 !streq(verbs[i].verb, "disable") &&
5017 !streq(verbs[i].verb, "is-enabled") &&
5018 !streq(verbs[i].verb, "list-unit-files") &&
5019 !streq(verbs[i].verb, "reenable") &&
5020 !streq(verbs[i].verb, "preset") &&
5021 !streq(verbs[i].verb, "mask") &&
5022 !streq(verbs[i].verb, "unmask") &&
5023 !streq(verbs[i].verb, "link")) {
5025 if (running_in_chroot() > 0) {
5026 log_info("Running in chroot, ignoring request.");
5030 if (((!streq(verbs[i].verb, "reboot") &&
5031 !streq(verbs[i].verb, "halt") &&
5032 !streq(verbs[i].verb, "poweroff")) || arg_force <= 0) && !bus) {
5033 log_error("Failed to get D-Bus connection: %s",
5034 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5040 if (!bus && !avoid_bus()) {
5041 log_error("Failed to get D-Bus connection: %s",
5042 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5047 return verbs[i].dispatch(bus, argv + optind);
5050 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
5052 struct msghdr msghdr;
5053 struct iovec iovec[2];
5054 union sockaddr_union sockaddr;
5055 struct sd_shutdown_command c;
5057 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
5064 c.dry_run = dry_run;
5068 sockaddr.sa.sa_family = AF_UNIX;
5069 strncpy(sockaddr.un.sun_path, "/run/systemd/shutdownd", sizeof(sockaddr.un.sun_path));
5072 msghdr.msg_name = &sockaddr;
5073 msghdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + sizeof("/run/systemd/shutdownd") - 1;
5076 iovec[0].iov_base = (char*) &c;
5077 iovec[0].iov_len = offsetof(struct sd_shutdown_command, wall_message);
5079 if (isempty(message))
5080 msghdr.msg_iovlen = 1;
5082 iovec[1].iov_base = (char*) message;
5083 iovec[1].iov_len = strlen(message);
5084 msghdr.msg_iovlen = 2;
5086 msghdr.msg_iov = iovec;
5088 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0) {
5089 close_nointr_nofail(fd);
5093 close_nointr_nofail(fd);
5097 static int reload_with_fallback(DBusConnection *bus) {
5100 /* First, try systemd via D-Bus. */
5101 if (daemon_reload(bus, NULL) >= 0)
5105 /* Nothing else worked, so let's try signals */
5106 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
5108 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
5109 log_error("kill() failed: %m");
5116 static int start_with_fallback(DBusConnection *bus) {
5119 /* First, try systemd via D-Bus. */
5120 if (start_unit(bus, NULL) >= 0)
5124 /* Hmm, talking to systemd via D-Bus didn't work. Then
5125 * let's try to talk to Upstart via D-Bus. */
5126 if (talk_upstart() > 0)
5129 /* Nothing else worked, so let's try
5131 if (talk_initctl() > 0)
5134 log_error("Failed to talk to init daemon.");
5138 warn_wall(arg_action);
5142 static _noreturn_ void halt_now(enum action a) {
5144 /* Make sure C-A-D is handled by the kernel from this
5146 reboot(RB_ENABLE_CAD);
5151 log_info("Halting.");
5152 reboot(RB_HALT_SYSTEM);
5155 case ACTION_POWEROFF:
5156 log_info("Powering off.");
5157 reboot(RB_POWER_OFF);
5161 log_info("Rebooting.");
5162 reboot(RB_AUTOBOOT);
5166 assert_not_reached("Unknown halt action.");
5169 assert_not_reached("Uh? This shouldn't happen.");
5172 static int halt_main(DBusConnection *bus) {
5175 if (geteuid() != 0) {
5176 /* Try logind if we are a normal user and no special
5177 * mode applies. Maybe PolicyKit allows us to shutdown
5180 if (arg_when <= 0 &&
5183 (arg_action == ACTION_POWEROFF ||
5184 arg_action == ACTION_REBOOT)) {
5185 r = reboot_with_logind(bus, arg_action);
5190 log_error("Must be root.");
5197 m = strv_join(arg_wall, " ");
5198 r = send_shutdownd(arg_when,
5199 arg_action == ACTION_HALT ? 'H' :
5200 arg_action == ACTION_POWEROFF ? 'P' :
5201 arg_action == ACTION_KEXEC ? 'K' :
5209 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
5211 char date[FORMAT_TIMESTAMP_MAX];
5213 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
5214 format_timestamp(date, sizeof(date), arg_when));
5219 if (!arg_dry && !arg_force)
5220 return start_with_fallback(bus);
5223 if (sd_booted() > 0)
5224 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
5226 r = utmp_put_shutdown();
5228 log_warning("Failed to write utmp record: %s", strerror(-r));
5235 halt_now(arg_action);
5236 /* We should never reach this. */
5240 static int runlevel_main(void) {
5241 int r, runlevel, previous;
5243 r = utmp_get_runlevel(&runlevel, &previous);
5250 previous <= 0 ? 'N' : previous,
5251 runlevel <= 0 ? 'N' : runlevel);
5256 int main(int argc, char*argv[]) {
5257 int r, retval = EXIT_FAILURE;
5258 DBusConnection *bus = NULL;
5261 dbus_error_init(&error);
5263 setlocale(LC_ALL, "");
5264 log_parse_environment();
5267 r = parse_argv(argc, argv);
5271 retval = EXIT_SUCCESS;
5275 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
5276 * let's shortcut this */
5277 if (arg_action == ACTION_RUNLEVEL) {
5278 r = runlevel_main();
5279 retval = r < 0 ? EXIT_FAILURE : r;
5283 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
5284 log_info("Running in chroot, ignoring request.");
5290 if (arg_transport == TRANSPORT_NORMAL)
5291 bus_connect(arg_scope == UNIT_FILE_SYSTEM ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &bus, &private_bus, &error);
5292 else if (arg_transport == TRANSPORT_POLKIT) {
5293 bus_connect_system_polkit(&bus, &error);
5294 private_bus = false;
5295 } else if (arg_transport == TRANSPORT_SSH) {
5296 bus_connect_system_ssh(NULL, arg_host, &bus, &error);
5297 private_bus = false;
5299 assert_not_reached("Uh, invalid transport...");
5302 switch (arg_action) {
5304 case ACTION_SYSTEMCTL:
5305 r = systemctl_main(bus, argc, argv, &error);
5309 case ACTION_POWEROFF:
5315 case ACTION_RUNLEVEL2:
5316 case ACTION_RUNLEVEL3:
5317 case ACTION_RUNLEVEL4:
5318 case ACTION_RUNLEVEL5:
5320 case ACTION_EMERGENCY:
5321 case ACTION_DEFAULT:
5322 r = start_with_fallback(bus);
5327 r = reload_with_fallback(bus);
5330 case ACTION_CANCEL_SHUTDOWN: {
5334 m = strv_join(arg_wall, " ");
5336 retval = EXIT_FAILURE;
5340 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
5342 log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r));
5347 case ACTION_INVALID:
5348 case ACTION_RUNLEVEL:
5350 assert_not_reached("Unknown action");
5353 retval = r < 0 ? EXIT_FAILURE : r;
5357 dbus_connection_flush(bus);
5358 dbus_connection_close(bus);
5359 dbus_connection_unref(bus);
5362 dbus_error_free(&error);
5366 strv_free(arg_property);
5369 ask_password_agent_close();
5370 polkit_agent_close();