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) {
1040 STRV_FOREACH(name, args+1) {
1041 n = unit_name_mangle(*name);
1042 r = bus_method_call_with_reply (
1044 "org.freedesktop.systemd1",
1045 "/org/freedesktop/systemd1",
1046 "org.freedesktop.systemd1.Manager",
1050 DBUS_TYPE_STRING, n ? &n : name,
1061 static int cancel_job(DBusConnection *bus, char **args) {
1062 DBusMessage *reply = NULL;
1068 if (strv_length(args) <= 1)
1069 return daemon_reload(bus, args);
1071 STRV_FOREACH(name, args+1) {
1075 r = safe_atou(*name, &id);
1077 log_error("Failed to parse job id: %s", strerror(-r));
1080 assert_cc(sizeof(uint32_t) == sizeof(id));
1082 r = bus_method_call_with_reply (
1084 "org.freedesktop.systemd1",
1085 "/org/freedesktop/systemd1",
1086 "org.freedesktop.systemd1.Manager",
1090 DBUS_TYPE_UINT32, &id,
1095 if (!dbus_message_get_args(reply, NULL,
1096 DBUS_TYPE_OBJECT_PATH, &path,
1097 DBUS_TYPE_INVALID)) {
1098 log_error("Failed to parse reply");
1099 dbus_message_unref(reply);
1103 dbus_message_unref(reply);
1105 r = bus_method_call_with_reply (
1107 "org.freedesktop.systemd1",
1109 "org.freedesktop.systemd1.Job",
1122 static bool need_daemon_reload(DBusConnection *bus, const char *unit) {
1123 DBusMessage *reply = NULL;
1124 dbus_bool_t b = FALSE;
1125 DBusMessageIter iter, sub;
1127 *interface = "org.freedesktop.systemd1.Unit",
1128 *property = "NeedDaemonReload",
1133 /* We ignore all errors here, since this is used to show a warning only */
1135 n = unit_name_mangle(unit);
1136 r = bus_method_call_with_reply (
1138 "org.freedesktop.systemd1",
1139 "/org/freedesktop/systemd1",
1140 "org.freedesktop.systemd1.Manager",
1144 DBUS_TYPE_STRING, n ? (const char**) &n : &unit,
1150 if (!dbus_message_get_args(reply, NULL,
1151 DBUS_TYPE_OBJECT_PATH, &path,
1155 dbus_message_unref(reply);
1156 r = bus_method_call_with_reply (
1158 "org.freedesktop.systemd1",
1160 "org.freedesktop.DBus.Properties",
1164 DBUS_TYPE_STRING, &interface,
1165 DBUS_TYPE_STRING, &property,
1170 if (!dbus_message_iter_init(reply, &iter) ||
1171 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
1174 dbus_message_iter_recurse(&iter, &sub);
1176 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_BOOLEAN)
1179 dbus_message_iter_get_basic(&sub, &b);
1183 dbus_message_unref(reply);
1188 typedef struct WaitData {
1195 static DBusHandlerResult wait_filter(DBusConnection *connection, DBusMessage *message, void *data) {
1203 dbus_error_init(&error);
1205 log_debug("Got D-Bus request: %s.%s() on %s",
1206 dbus_message_get_interface(message),
1207 dbus_message_get_member(message),
1208 dbus_message_get_path(message));
1210 if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
1211 log_error("Warning! D-Bus connection terminated.");
1212 dbus_connection_close(connection);
1214 } else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
1216 const char *path, *result, *unit;
1217 dbus_bool_t success = true;
1219 if (dbus_message_get_args(message, &error,
1220 DBUS_TYPE_UINT32, &id,
1221 DBUS_TYPE_OBJECT_PATH, &path,
1222 DBUS_TYPE_STRING, &unit,
1223 DBUS_TYPE_STRING, &result,
1224 DBUS_TYPE_INVALID)) {
1227 p = set_remove(d->set, (char*) path);
1230 if (!isempty(result))
1231 d->result = strdup(result);
1234 d->name = strdup(unit);
1239 dbus_error_free(&error);
1240 if (dbus_message_get_args(message, &error,
1241 DBUS_TYPE_UINT32, &id,
1242 DBUS_TYPE_OBJECT_PATH, &path,
1243 DBUS_TYPE_STRING, &result,
1244 DBUS_TYPE_INVALID)) {
1247 /* Compatibility with older systemd versions <
1248 * 183 during upgrades. This should be dropped
1250 p = set_remove(d->set, (char*) path);
1254 d->result = strdup(result);
1259 dbus_error_free(&error);
1260 if (dbus_message_get_args(message, &error,
1261 DBUS_TYPE_UINT32, &id,
1262 DBUS_TYPE_OBJECT_PATH, &path,
1263 DBUS_TYPE_BOOLEAN, &success,
1264 DBUS_TYPE_INVALID)) {
1267 /* Compatibility with older systemd versions <
1268 * 19 during upgrades. This should be dropped
1271 p = set_remove(d->set, (char*) path);
1275 d->result = strdup("failed");
1281 log_error("Failed to parse message: %s", bus_error_message(&error));
1285 dbus_error_free(&error);
1286 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1289 static int enable_wait_for_jobs(DBusConnection *bus) {
1297 dbus_error_init(&error);
1298 dbus_bus_add_match(bus,
1300 "sender='org.freedesktop.systemd1',"
1301 "interface='org.freedesktop.systemd1.Manager',"
1302 "member='JobRemoved',"
1303 "path='/org/freedesktop/systemd1'",
1306 if (dbus_error_is_set(&error)) {
1307 log_error("Failed to add match: %s", bus_error_message(&error));
1308 dbus_error_free(&error);
1312 /* This is slightly dirty, since we don't undo the match registrations. */
1316 static int wait_for_jobs(DBusConnection *bus, Set *s) {
1326 if (!dbus_connection_add_filter(bus, wait_filter, &d, NULL))
1329 while (!set_isempty(s)) {
1331 if (!dbus_connection_read_write_dispatch(bus, -1)) {
1332 log_error("Disconnected from bus.");
1333 return -ECONNREFUSED;
1340 if (streq(d.result, "timeout"))
1341 log_error("Job for %s timed out.", strna(d.name));
1342 else if (streq(d.result, "canceled"))
1343 log_error("Job for %s canceled.", strna(d.name));
1344 else if (streq(d.result, "dependency"))
1345 log_error("A dependency job for %s failed. See 'journalctl -xn' for details.", strna(d.name));
1346 else if (!streq(d.result, "done") && !streq(d.result, "skipped"))
1347 log_error("Job for %s failed. See 'systemctl status %s' and 'journalctl -xn' for details.", strna(d.name), strna(d.name));
1350 if (streq_ptr(d.result, "timeout"))
1352 else if (streq_ptr(d.result, "canceled"))
1354 else if (!streq_ptr(d.result, "done") && !streq_ptr(d.result, "skipped"))
1365 dbus_connection_remove_filter(bus, wait_filter, &d);
1369 static int check_one_unit(DBusConnection *bus, char *name, char **check_states, bool quiet) {
1370 DBusMessage *reply = NULL;
1371 DBusMessageIter iter, sub;
1373 *interface = "org.freedesktop.systemd1.Unit",
1374 *property = "ActiveState";
1375 const char *path = NULL;
1382 n = unit_name_mangle(name);
1383 r = bus_method_call_with_reply (
1385 "org.freedesktop.systemd1",
1386 "/org/freedesktop/systemd1",
1387 "org.freedesktop.systemd1.Manager",
1391 DBUS_TYPE_STRING, n ? &n : &name,
1395 if ((r != -ENOMEM) && (!quiet))
1400 if (!dbus_message_get_args(reply, NULL,
1401 DBUS_TYPE_OBJECT_PATH, &path,
1402 DBUS_TYPE_INVALID)) {
1403 log_error("Failed to parse reply.");
1408 dbus_message_unref(reply);
1409 r = bus_method_call_with_reply (
1411 "org.freedesktop.systemd1",
1413 "org.freedesktop.DBus.Properties",
1417 DBUS_TYPE_STRING, &interface,
1418 DBUS_TYPE_STRING, &property,
1423 if (!dbus_message_iter_init(reply, &iter) ||
1424 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1425 log_error("Failed to parse reply.");
1430 dbus_message_iter_recurse(&iter, &sub);
1432 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1433 log_error("Failed to parse reply.");
1438 dbus_message_iter_get_basic(&sub, &state);
1443 if (strv_find(check_states, state))
1446 r = 3; /* According to LSB: "program is not running" */
1450 dbus_message_unref(reply);
1455 static void check_triggering_units(
1456 DBusConnection *bus,
1457 const char *unit_name) {
1459 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1460 DBusMessageIter iter, sub;
1461 char *service_trigger = NULL;
1462 const char *interface = "org.freedesktop.systemd1.Unit",
1463 *triggered_by_property = "TriggeredBy";
1465 char _cleanup_free_ *unit_path = NULL, *n = NULL;
1466 bool print_warning_label = true;
1469 n = unit_name_mangle(unit_name);
1475 unit_path = unit_dbus_path_from_name(n);
1481 r = bus_method_call_with_reply (
1483 "org.freedesktop.systemd1",
1485 "org.freedesktop.DBus.Properties",
1489 DBUS_TYPE_STRING, &interface,
1490 DBUS_TYPE_STRING, &triggered_by_property,
1495 if (!dbus_message_iter_init(reply, &iter) ||
1496 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1497 log_error("Failed to parse reply.");
1501 dbus_message_iter_recurse(&iter, &sub);
1502 dbus_message_iter_recurse(&sub, &iter);
1505 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1506 char **check_states = NULL;
1508 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1509 log_error("Failed to parse reply.");
1513 dbus_message_iter_get_basic(&sub, &service_trigger);
1515 check_states = strv_new("active", "reloading", NULL);
1516 r = check_one_unit(bus, service_trigger, check_states, true);
1517 strv_free(check_states);
1521 if (print_warning_label) {
1522 log_warning("Warning: Stopping %s, but it can still be activated by:", unit_name);
1523 print_warning_label = false;
1525 log_warning(" %s", service_trigger);
1528 dbus_message_iter_next(&sub);
1532 static int start_unit_one(
1533 DBusConnection *bus,
1540 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1543 _cleanup_free_ char *n, *p = NULL;
1550 n = unit_name_mangle(name);
1554 r = bus_method_call_with_reply(
1556 "org.freedesktop.systemd1",
1557 "/org/freedesktop/systemd1",
1558 "org.freedesktop.systemd1.Manager",
1562 DBUS_TYPE_STRING, &n,
1563 DBUS_TYPE_STRING, &mode,
1566 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
1567 /* There's always a fallback possible for
1568 * legacy actions. */
1571 log_error("Failed to issue method call: %s", bus_error_message(error));
1576 if (!dbus_message_get_args(reply, error,
1577 DBUS_TYPE_OBJECT_PATH, &path,
1578 DBUS_TYPE_INVALID)) {
1579 log_error("Failed to parse reply: %s", bus_error_message(error));
1583 if (need_daemon_reload(bus, n))
1584 log_warning("Warning: Unit file of %s changed on disk, 'systemctl %s daemon-reload' recommended.",
1585 n, arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
1594 log_error("Failed to add path to set.");
1604 static enum action verb_to_action(const char *verb) {
1605 if (streq(verb, "halt"))
1607 else if (streq(verb, "poweroff"))
1608 return ACTION_POWEROFF;
1609 else if (streq(verb, "reboot"))
1610 return ACTION_REBOOT;
1611 else if (streq(verb, "kexec"))
1612 return ACTION_KEXEC;
1613 else if (streq(verb, "rescue"))
1614 return ACTION_RESCUE;
1615 else if (streq(verb, "emergency"))
1616 return ACTION_EMERGENCY;
1617 else if (streq(verb, "default"))
1618 return ACTION_DEFAULT;
1619 else if (streq(verb, "exit"))
1621 else if (streq(verb, "suspend"))
1622 return ACTION_SUSPEND;
1623 else if (streq(verb, "hibernate"))
1624 return ACTION_HIBERNATE;
1625 else if (streq(verb, "hybrid-sleep"))
1626 return ACTION_HYBRID_SLEEP;
1628 return ACTION_INVALID;
1631 static int start_unit(DBusConnection *bus, char **args) {
1633 static const char * const table[_ACTION_MAX] = {
1634 [ACTION_HALT] = SPECIAL_HALT_TARGET,
1635 [ACTION_POWEROFF] = SPECIAL_POWEROFF_TARGET,
1636 [ACTION_REBOOT] = SPECIAL_REBOOT_TARGET,
1637 [ACTION_KEXEC] = SPECIAL_KEXEC_TARGET,
1638 [ACTION_RUNLEVEL2] = SPECIAL_RUNLEVEL2_TARGET,
1639 [ACTION_RUNLEVEL3] = SPECIAL_RUNLEVEL3_TARGET,
1640 [ACTION_RUNLEVEL4] = SPECIAL_RUNLEVEL4_TARGET,
1641 [ACTION_RUNLEVEL5] = SPECIAL_RUNLEVEL5_TARGET,
1642 [ACTION_RESCUE] = SPECIAL_RESCUE_TARGET,
1643 [ACTION_EMERGENCY] = SPECIAL_EMERGENCY_TARGET,
1644 [ACTION_DEFAULT] = SPECIAL_DEFAULT_TARGET,
1645 [ACTION_EXIT] = SPECIAL_EXIT_TARGET,
1646 [ACTION_SUSPEND] = SPECIAL_SUSPEND_TARGET,
1647 [ACTION_HIBERNATE] = SPECIAL_HIBERNATE_TARGET,
1648 [ACTION_HYBRID_SLEEP] = SPECIAL_HYBRID_SLEEP_TARGET
1652 const char *method, *mode, *one_name;
1657 dbus_error_init(&error);
1661 ask_password_agent_open_if_enabled();
1663 if (arg_action == ACTION_SYSTEMCTL) {
1665 streq(args[0], "stop") ||
1666 streq(args[0], "condstop") ? "StopUnit" :
1667 streq(args[0], "reload") ? "ReloadUnit" :
1668 streq(args[0], "restart") ? "RestartUnit" :
1670 streq(args[0], "try-restart") ||
1671 streq(args[0], "condrestart") ? "TryRestartUnit" :
1673 streq(args[0], "reload-or-restart") ? "ReloadOrRestartUnit" :
1675 streq(args[0], "reload-or-try-restart") ||
1676 streq(args[0], "condreload") ||
1678 streq(args[0], "force-reload") ? "ReloadOrTryRestartUnit" :
1682 (streq(args[0], "isolate") ||
1683 streq(args[0], "rescue") ||
1684 streq(args[0], "emergency")) ? "isolate" : arg_job_mode;
1686 one_name = table[verb_to_action(args[0])];
1689 assert(arg_action < ELEMENTSOF(table));
1690 assert(table[arg_action]);
1692 method = "StartUnit";
1694 mode = (arg_action == ACTION_EMERGENCY ||
1695 arg_action == ACTION_RESCUE ||
1696 arg_action == ACTION_RUNLEVEL2 ||
1697 arg_action == ACTION_RUNLEVEL3 ||
1698 arg_action == ACTION_RUNLEVEL4 ||
1699 arg_action == ACTION_RUNLEVEL5) ? "isolate" : "replace";
1701 one_name = table[arg_action];
1704 if (!arg_no_block) {
1705 ret = enable_wait_for_jobs(bus);
1707 log_error("Could not watch jobs: %s", strerror(-ret));
1711 s = set_new(string_hash_func, string_compare_func);
1719 ret = start_unit_one(bus, method, one_name, mode, &error, s);
1721 ret = translate_bus_error_to_exit_status(ret, &error);
1723 STRV_FOREACH(name, args+1) {
1724 r = start_unit_one(bus, method, *name, mode, &error, s);
1726 ret = translate_bus_error_to_exit_status(r, &error);
1727 dbus_error_free(&error);
1732 if (!arg_no_block) {
1733 r = wait_for_jobs(bus, s);
1739 /* When stopping units, warn if they can still be triggered by
1740 * another active unit (socket, path, timer) */
1741 if (!arg_quiet && streq(method, "StopUnit")) {
1743 check_triggering_units(bus, one_name);
1745 STRV_FOREACH(name, args+1)
1746 check_triggering_units(bus, *name);
1752 dbus_error_free(&error);
1757 /* Ask systemd-logind, which might grant access to unprivileged users
1758 * through PolicyKit */
1759 static int reboot_with_logind(DBusConnection *bus, enum action a) {
1762 dbus_bool_t interactive = true;
1764 polkit_agent_open_if_enabled();
1772 case ACTION_POWEROFF:
1773 method = "PowerOff";
1776 case ACTION_SUSPEND:
1780 case ACTION_HIBERNATE:
1781 method = "Hibernate";
1784 case ACTION_HYBRID_SLEEP:
1785 method = "HybridSleep";
1792 return bus_method_call_with_reply (
1794 "org.freedesktop.login1",
1795 "/org/freedesktop/login1",
1796 "org.freedesktop.login1.Manager",
1800 DBUS_TYPE_BOOLEAN, &interactive,
1807 static int start_special(DBusConnection *bus, char **args) {
1813 a = verb_to_action(args[0]);
1815 if (arg_force >= 2 && geteuid() != 0) {
1816 log_error("Must be root.");
1820 if (arg_force >= 2 &&
1821 (a == ACTION_HALT ||
1822 a == ACTION_POWEROFF ||
1823 a == ACTION_REBOOT))
1826 if (arg_force >= 1 &&
1827 (a == ACTION_HALT ||
1828 a == ACTION_POWEROFF ||
1829 a == ACTION_REBOOT ||
1830 a == ACTION_KEXEC ||
1832 return daemon_reload(bus, args);
1834 /* first try logind, to allow authentication with polkit */
1835 if (geteuid() != 0 &&
1836 (a == ACTION_POWEROFF ||
1837 a == ACTION_REBOOT ||
1838 a == ACTION_SUSPEND ||
1839 a == ACTION_HIBERNATE ||
1840 a == ACTION_HYBRID_SLEEP)) {
1841 r = reboot_with_logind(bus, a);
1846 r = start_unit(bus, args);
1853 static int check_unit_active(DBusConnection *bus, char **args) {
1855 int r = 3; /* According to LSB: "program is not running" */
1860 STRV_FOREACH(name, args+1) {
1861 char **check_states = strv_new("active", "reloading", NULL);
1862 int state = check_one_unit(bus, *name, check_states, arg_quiet);
1863 strv_free(check_states);
1873 static int check_unit_failed(DBusConnection *bus, char **args) {
1880 STRV_FOREACH(name, args+1) {
1881 char **check_states = strv_new("failed", NULL);
1882 int state = check_one_unit(bus, *name, check_states, arg_quiet);
1883 strv_free(check_states);
1893 static int kill_unit(DBusConnection *bus, char **args) {
1900 arg_kill_who = "all";
1902 STRV_FOREACH(name, args+1) {
1903 n = unit_name_mangle(*name);
1904 r = bus_method_call_with_reply (
1906 "org.freedesktop.systemd1",
1907 "/org/freedesktop/systemd1",
1908 "org.freedesktop.systemd1.Manager",
1912 DBUS_TYPE_STRING, n ? &n : name,
1913 DBUS_TYPE_STRING, &arg_kill_who,
1914 DBUS_TYPE_INT32, &arg_signal,
1923 typedef struct ExecStatusInfo {
1931 usec_t start_timestamp;
1932 usec_t exit_timestamp;
1937 LIST_FIELDS(struct ExecStatusInfo, exec);
1940 static void exec_status_info_free(ExecStatusInfo *i) {
1949 static int exec_status_info_deserialize(DBusMessageIter *sub, ExecStatusInfo *i) {
1950 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
1951 DBusMessageIter sub2, sub3;
1955 int32_t code, status;
1961 if (dbus_message_iter_get_arg_type(sub) != DBUS_TYPE_STRUCT)
1964 dbus_message_iter_recurse(sub, &sub2);
1966 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0)
1969 if (!(i->path = strdup(path)))
1972 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_ARRAY ||
1973 dbus_message_iter_get_element_type(&sub2) != DBUS_TYPE_STRING)
1977 dbus_message_iter_recurse(&sub2, &sub3);
1978 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
1979 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
1980 dbus_message_iter_next(&sub3);
1985 if (!(i->argv = new0(char*, n+1)))
1989 dbus_message_iter_recurse(&sub2, &sub3);
1990 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
1993 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
1994 dbus_message_iter_get_basic(&sub3, &s);
1995 dbus_message_iter_next(&sub3);
1997 if (!(i->argv[n++] = strdup(s)))
2001 if (!dbus_message_iter_next(&sub2) ||
2002 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, true) < 0 ||
2003 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp, true) < 0 ||
2004 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp_monotonic, true) < 0 ||
2005 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp, true) < 0 ||
2006 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp_monotonic, true) < 0 ||
2007 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, true) < 0 ||
2008 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &code, true) < 0 ||
2009 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &status, false) < 0)
2013 i->start_timestamp = (usec_t) start_timestamp;
2014 i->exit_timestamp = (usec_t) exit_timestamp;
2015 i->pid = (pid_t) pid;
2022 typedef struct UnitStatusInfo {
2024 const char *load_state;
2025 const char *active_state;
2026 const char *sub_state;
2027 const char *unit_file_state;
2029 const char *description;
2030 const char *following;
2032 char **documentation;
2034 const char *fragment_path;
2035 const char *source_path;
2036 const char *default_control_group;
2038 const char *load_error;
2041 usec_t inactive_exit_timestamp;
2042 usec_t inactive_exit_timestamp_monotonic;
2043 usec_t active_enter_timestamp;
2044 usec_t active_exit_timestamp;
2045 usec_t inactive_enter_timestamp;
2047 bool need_daemon_reload;
2052 const char *status_text;
2055 usec_t start_timestamp;
2056 usec_t exit_timestamp;
2058 int exit_code, exit_status;
2060 usec_t condition_timestamp;
2061 bool condition_result;
2064 unsigned n_accepted;
2065 unsigned n_connections;
2069 const char *sysfs_path;
2071 /* Mount, Automount */
2077 LIST_HEAD(ExecStatusInfo, exec);
2080 static void print_status_info(UnitStatusInfo *i) {
2082 const char *on, *off, *ss;
2084 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
2085 char since2[FORMAT_TIMESTAMP_MAX], *s2;
2090 /* This shows pretty information about a unit. See
2091 * print_property() for a low-level property printer */
2093 printf("%s", strna(i->id));
2095 if (i->description && !streq_ptr(i->id, i->description))
2096 printf(" - %s", i->description);
2101 printf("\t Follow: unit currently follows state of %s\n", i->following);
2103 if (streq_ptr(i->load_state, "error")) {
2104 on = ansi_highlight_red(true);
2105 off = ansi_highlight_red(false);
2109 path = i->source_path ? i->source_path : i->fragment_path;
2112 printf("\t Loaded: %s%s%s (Reason: %s)\n", on, strna(i->load_state), off, i->load_error);
2113 else if (path && i->unit_file_state)
2114 printf("\t Loaded: %s%s%s (%s; %s)\n", on, strna(i->load_state), off, path, i->unit_file_state);
2116 printf("\t Loaded: %s%s%s (%s)\n", on, strna(i->load_state), off, path);
2118 printf("\t Loaded: %s%s%s\n", on, strna(i->load_state), off);
2120 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
2122 if (streq_ptr(i->active_state, "failed")) {
2123 on = ansi_highlight_red(true);
2124 off = ansi_highlight_red(false);
2125 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
2126 on = ansi_highlight_green(true);
2127 off = ansi_highlight_green(false);
2132 printf("\t Active: %s%s (%s)%s",
2134 strna(i->active_state),
2138 printf("\t Active: %s%s%s",
2140 strna(i->active_state),
2143 if (!isempty(i->result) && !streq(i->result, "success"))
2144 printf(" (Result: %s)", i->result);
2146 timestamp = (streq_ptr(i->active_state, "active") ||
2147 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
2148 (streq_ptr(i->active_state, "inactive") ||
2149 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
2150 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
2151 i->active_exit_timestamp;
2153 s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
2154 s2 = format_timestamp(since2, sizeof(since2), timestamp);
2157 printf(" since %s; %s\n", s2, s1);
2159 printf(" since %s\n", s2);
2163 if (!i->condition_result && i->condition_timestamp > 0) {
2164 s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
2165 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
2168 printf("\t start condition failed at %s; %s\n", s2, s1);
2170 printf("\t start condition failed at %s\n", s2);
2174 printf("\t Device: %s\n", i->sysfs_path);
2176 printf("\t Where: %s\n", i->where);
2178 printf("\t What: %s\n", i->what);
2180 if (!strv_isempty(i->documentation)) {
2184 STRV_FOREACH(t, i->documentation) {
2186 printf("\t Docs: %s\n", *t);
2189 printf("\t %s\n", *t);
2194 printf("\tAccepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
2196 LIST_FOREACH(exec, p, i->exec) {
2200 /* Only show exited processes here */
2204 t = strv_join(p->argv, " ");
2205 printf("\t Process: %u %s=%s ", p->pid, p->name, strna(t));
2208 good = is_clean_exit_lsb(p->code, p->status, NULL);
2210 on = ansi_highlight_red(true);
2211 off = ansi_highlight_red(false);
2215 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
2217 if (p->code == CLD_EXITED) {
2220 printf("status=%i", p->status);
2222 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
2227 printf("signal=%s", signal_to_string(p->status));
2229 printf(")%s\n", off);
2231 if (i->main_pid == p->pid &&
2232 i->start_timestamp == p->start_timestamp &&
2233 i->exit_timestamp == p->start_timestamp)
2234 /* Let's not show this twice */
2237 if (p->pid == i->control_pid)
2241 if (i->main_pid > 0 || i->control_pid > 0) {
2244 if (i->main_pid > 0) {
2245 printf("Main PID: %u", (unsigned) i->main_pid);
2249 get_process_comm(i->main_pid, &t);
2254 } else if (i->exit_code > 0) {
2255 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
2257 if (i->exit_code == CLD_EXITED) {
2260 printf("status=%i", i->exit_status);
2262 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
2267 printf("signal=%s", signal_to_string(i->exit_status));
2272 if (i->main_pid > 0 && i->control_pid > 0)
2275 if (i->control_pid > 0) {
2278 printf(" Control: %u", (unsigned) i->control_pid);
2280 get_process_comm(i->control_pid, &t);
2291 printf("\t Status: \"%s\"\n", i->status_text);
2293 if (i->default_control_group &&
2294 (i->main_pid > 0 || i->control_pid > 0 || cg_is_empty_by_spec(i->default_control_group, false) == 0)) {
2297 printf("\t CGroup: %s\n", i->default_control_group);
2299 if (arg_transport != TRANSPORT_SSH) {
2309 if (i->main_pid > 0)
2310 extra[k++] = i->main_pid;
2312 if (i->control_pid > 0)
2313 extra[k++] = i->control_pid;
2315 show_cgroup_and_extra_by_spec(i->default_control_group, "\t\t ", c, false, arg_all, extra, k);
2319 if (i->id && arg_transport != TRANSPORT_SSH) {
2321 arg_all * OUTPUT_SHOW_ALL |
2322 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
2323 on_tty() * OUTPUT_COLOR |
2324 !arg_quiet * OUTPUT_WARN_CUTOFF;
2327 show_journal_by_unit(stdout,
2331 i->inactive_exit_timestamp_monotonic,
2336 if (i->need_daemon_reload)
2337 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %s daemon-reload' recommended.\n",
2338 ansi_highlight_red(true),
2339 ansi_highlight_red(false),
2340 arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
2343 static void show_unit_help(UnitStatusInfo *i) {
2348 if (!i->documentation) {
2349 log_info("Documentation for %s not known.", i->id);
2353 STRV_FOREACH(p, i->documentation) {
2355 if (startswith(*p, "man:")) {
2358 char *page = NULL, *section = NULL;
2359 const char *args[4] = { "man", NULL, NULL, NULL };
2364 if ((*p)[k-1] == ')')
2365 e = strrchr(*p, '(');
2368 page = strndup((*p) + 4, e - *p - 4);
2374 section = strndup(e + 1, *p + k - e - 2);
2388 log_error("Failed to fork: %m");
2396 execvp(args[0], (char**) args);
2397 log_error("Failed to execute man: %m");
2398 _exit(EXIT_FAILURE);
2404 wait_for_terminate(pid, NULL);
2406 log_info("Can't show: %s", *p);
2410 static int status_property(const char *name, DBusMessageIter *iter, UnitStatusInfo *i) {
2416 switch (dbus_message_iter_get_arg_type(iter)) {
2418 case DBUS_TYPE_STRING: {
2421 dbus_message_iter_get_basic(iter, &s);
2424 if (streq(name, "Id"))
2426 else if (streq(name, "LoadState"))
2428 else if (streq(name, "ActiveState"))
2429 i->active_state = s;
2430 else if (streq(name, "SubState"))
2432 else if (streq(name, "Description"))
2434 else if (streq(name, "FragmentPath"))
2435 i->fragment_path = s;
2436 else if (streq(name, "SourcePath"))
2438 else if (streq(name, "DefaultControlGroup"))
2439 i->default_control_group = s;
2440 else if (streq(name, "StatusText"))
2442 else if (streq(name, "SysFSPath"))
2444 else if (streq(name, "Where"))
2446 else if (streq(name, "What"))
2448 else if (streq(name, "Following"))
2450 else if (streq(name, "UnitFileState"))
2451 i->unit_file_state = s;
2452 else if (streq(name, "Result"))
2459 case DBUS_TYPE_BOOLEAN: {
2462 dbus_message_iter_get_basic(iter, &b);
2464 if (streq(name, "Accept"))
2466 else if (streq(name, "NeedDaemonReload"))
2467 i->need_daemon_reload = b;
2468 else if (streq(name, "ConditionResult"))
2469 i->condition_result = b;
2474 case DBUS_TYPE_UINT32: {
2477 dbus_message_iter_get_basic(iter, &u);
2479 if (streq(name, "MainPID")) {
2481 i->main_pid = (pid_t) u;
2484 } else if (streq(name, "ControlPID"))
2485 i->control_pid = (pid_t) u;
2486 else if (streq(name, "ExecMainPID")) {
2488 i->main_pid = (pid_t) u;
2489 } else if (streq(name, "NAccepted"))
2491 else if (streq(name, "NConnections"))
2492 i->n_connections = u;
2497 case DBUS_TYPE_INT32: {
2500 dbus_message_iter_get_basic(iter, &j);
2502 if (streq(name, "ExecMainCode"))
2503 i->exit_code = (int) j;
2504 else if (streq(name, "ExecMainStatus"))
2505 i->exit_status = (int) j;
2510 case DBUS_TYPE_UINT64: {
2513 dbus_message_iter_get_basic(iter, &u);
2515 if (streq(name, "ExecMainStartTimestamp"))
2516 i->start_timestamp = (usec_t) u;
2517 else if (streq(name, "ExecMainExitTimestamp"))
2518 i->exit_timestamp = (usec_t) u;
2519 else if (streq(name, "ActiveEnterTimestamp"))
2520 i->active_enter_timestamp = (usec_t) u;
2521 else if (streq(name, "InactiveEnterTimestamp"))
2522 i->inactive_enter_timestamp = (usec_t) u;
2523 else if (streq(name, "InactiveExitTimestamp"))
2524 i->inactive_exit_timestamp = (usec_t) u;
2525 else if (streq(name, "InactiveExitTimestampMonotonic"))
2526 i->inactive_exit_timestamp_monotonic = (usec_t) u;
2527 else if (streq(name, "ActiveExitTimestamp"))
2528 i->active_exit_timestamp = (usec_t) u;
2529 else if (streq(name, "ConditionTimestamp"))
2530 i->condition_timestamp = (usec_t) u;
2535 case DBUS_TYPE_ARRAY: {
2537 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
2538 startswith(name, "Exec")) {
2539 DBusMessageIter sub;
2541 dbus_message_iter_recurse(iter, &sub);
2542 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2543 ExecStatusInfo *info;
2546 if (!(info = new0(ExecStatusInfo, 1)))
2549 if (!(info->name = strdup(name))) {
2554 if ((r = exec_status_info_deserialize(&sub, info)) < 0) {
2559 LIST_PREPEND(ExecStatusInfo, exec, i->exec, info);
2561 dbus_message_iter_next(&sub);
2563 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
2564 streq(name, "Documentation")) {
2566 DBusMessageIter sub;
2568 dbus_message_iter_recurse(iter, &sub);
2569 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING) {
2573 dbus_message_iter_get_basic(&sub, &s);
2575 l = strv_append(i->documentation, s);
2579 strv_free(i->documentation);
2580 i->documentation = l;
2582 dbus_message_iter_next(&sub);
2589 case DBUS_TYPE_STRUCT: {
2591 if (streq(name, "LoadError")) {
2592 DBusMessageIter sub;
2593 const char *n, *message;
2596 dbus_message_iter_recurse(iter, &sub);
2598 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &n, true);
2602 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &message, false);
2606 if (!isempty(message))
2607 i->load_error = message;
2617 static int print_property(const char *name, DBusMessageIter *iter) {
2621 /* This is a low-level property printer, see
2622 * print_status_info() for the nicer output */
2624 if (arg_property && !strv_find(arg_property, name))
2627 switch (dbus_message_iter_get_arg_type(iter)) {
2629 case DBUS_TYPE_STRUCT: {
2630 DBusMessageIter sub;
2631 dbus_message_iter_recurse(iter, &sub);
2633 if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32 && streq(name, "Job")) {
2636 dbus_message_iter_get_basic(&sub, &u);
2639 printf("%s=%u\n", name, (unsigned) u);
2641 printf("%s=\n", name);
2644 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "Unit")) {
2647 dbus_message_iter_get_basic(&sub, &s);
2649 if (arg_all || s[0])
2650 printf("%s=%s\n", name, s);
2653 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "LoadError")) {
2654 const char *a = NULL, *b = NULL;
2656 if (bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &a, true) >= 0)
2657 bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &b, false);
2659 if (arg_all || !isempty(a) || !isempty(b))
2660 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
2668 case DBUS_TYPE_ARRAY:
2670 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "EnvironmentFiles")) {
2671 DBusMessageIter sub, sub2;
2673 dbus_message_iter_recurse(iter, &sub);
2674 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2678 dbus_message_iter_recurse(&sub, &sub2);
2680 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
2681 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) >= 0)
2682 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
2684 dbus_message_iter_next(&sub);
2689 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Paths")) {
2690 DBusMessageIter sub, sub2;
2692 dbus_message_iter_recurse(iter, &sub);
2693 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2694 const char *type, *path;
2696 dbus_message_iter_recurse(&sub, &sub2);
2698 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
2699 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
2700 printf("%s=%s\n", type, path);
2702 dbus_message_iter_next(&sub);
2707 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Timers")) {
2708 DBusMessageIter sub, sub2;
2710 dbus_message_iter_recurse(iter, &sub);
2711 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2713 uint64_t value, next_elapse;
2715 dbus_message_iter_recurse(&sub, &sub2);
2717 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &base, true) >= 0 &&
2718 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &value, true) >= 0 &&
2719 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &next_elapse, false) >= 0) {
2720 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
2722 printf("%s={ value=%s ; next_elapse=%s }\n",
2724 format_timespan(timespan1, sizeof(timespan1), value),
2725 format_timespan(timespan2, sizeof(timespan2), next_elapse));
2728 dbus_message_iter_next(&sub);
2733 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "ControlGroupAttributes")) {
2734 DBusMessageIter sub, sub2;
2736 dbus_message_iter_recurse(iter, &sub);
2737 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2738 const char *controller, *attr, *value;
2740 dbus_message_iter_recurse(&sub, &sub2);
2742 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &controller, true) >= 0 &&
2743 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &attr, true) >= 0 &&
2744 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &value, false) >= 0) {
2746 printf("ControlGroupAttribute={ controller=%s ; attribute=%s ; value=\"%s\" }\n",
2752 dbus_message_iter_next(&sub);
2757 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && startswith(name, "Exec")) {
2758 DBusMessageIter sub;
2760 dbus_message_iter_recurse(iter, &sub);
2761 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2762 ExecStatusInfo info;
2765 if (exec_status_info_deserialize(&sub, &info) >= 0) {
2766 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
2769 t = strv_join(info.argv, " ");
2771 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
2775 yes_no(info.ignore),
2776 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
2777 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
2778 (unsigned) info. pid,
2779 sigchld_code_to_string(info.code),
2781 info.code == CLD_EXITED ? "" : "/",
2782 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
2788 strv_free(info.argv);
2790 dbus_message_iter_next(&sub);
2799 if (generic_print_property(name, iter, arg_all) > 0)
2803 printf("%s=[unprintable]\n", name);
2808 static int show_one(const char *verb, DBusConnection *bus, const char *path, bool show_properties, bool *new_line) {
2809 DBusMessage *reply = NULL;
2810 const char *interface = "";
2812 DBusMessageIter iter, sub, sub2, sub3;
2813 UnitStatusInfo info;
2821 r = bus_method_call_with_reply (
2823 "org.freedesktop.systemd1",
2825 "org.freedesktop.DBus.Properties",
2829 DBUS_TYPE_STRING, &interface,
2834 if (!dbus_message_iter_init(reply, &iter) ||
2835 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
2836 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
2837 log_error("Failed to parse reply.");
2842 dbus_message_iter_recurse(&iter, &sub);
2849 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
2852 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_DICT_ENTRY) {
2853 log_error("Failed to parse reply.");
2858 dbus_message_iter_recurse(&sub, &sub2);
2860 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0) {
2861 log_error("Failed to parse reply.");
2866 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
2867 log_error("Failed to parse reply.");
2872 dbus_message_iter_recurse(&sub2, &sub3);
2874 if (show_properties)
2875 r = print_property(name, &sub3);
2877 r = status_property(name, &sub3, &info);
2880 log_error("Failed to parse reply.");
2885 dbus_message_iter_next(&sub);
2890 if (!show_properties) {
2891 if (streq(verb, "help"))
2892 show_unit_help(&info);
2894 print_status_info(&info);
2897 strv_free(info.documentation);
2899 if (!streq_ptr(info.active_state, "active") &&
2900 !streq_ptr(info.active_state, "reloading") &&
2901 streq(verb, "status"))
2902 /* According to LSB: "program not running" */
2905 while ((p = info.exec)) {
2906 LIST_REMOVE(ExecStatusInfo, exec, info.exec, p);
2907 exec_status_info_free(p);
2912 dbus_message_unref(reply);
2917 static int show_one_by_pid(const char *verb, DBusConnection *bus, uint32_t pid, bool *new_line) {
2918 DBusMessage *reply = NULL;
2919 const char *path = NULL;
2923 dbus_error_init(&error);
2925 r = bus_method_call_with_reply (
2927 "org.freedesktop.systemd1",
2928 "/org/freedesktop/systemd1",
2929 "org.freedesktop.systemd1.Manager",
2933 DBUS_TYPE_UINT32, &pid,
2938 if (!dbus_message_get_args(reply, &error,
2939 DBUS_TYPE_OBJECT_PATH, &path,
2940 DBUS_TYPE_INVALID)) {
2941 log_error("Failed to parse reply: %s", bus_error_message(&error));
2946 r = show_one(verb, bus, path, false, new_line);
2950 dbus_message_unref(reply);
2952 dbus_error_free(&error);
2957 static int show(DBusConnection *bus, char **args) {
2959 bool show_properties, new_line = false;
2965 show_properties = streq(args[0], "show");
2967 if (show_properties)
2968 pager_open_if_enabled();
2970 if (show_properties && strv_length(args) <= 1) {
2971 /* If not argument is specified inspect the manager
2974 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line);
2977 STRV_FOREACH(name, args+1) {
2980 if (safe_atou32(*name, &id) < 0) {
2982 /* Interpret as unit name */
2984 n = unit_name_mangle(*name);
2985 p = unit_dbus_path_from_name(n ? n : *name);
2990 r = show_one(args[0], bus, p, show_properties, &new_line);
2996 } else if (show_properties) {
2998 /* Interpret as job id */
3001 if (asprintf(&p, "/org/freedesktop/systemd1/job/%u", id) < 0)
3004 r = show_one(args[0], bus, p, show_properties, &new_line);
3012 /* Interpret as PID */
3014 r = show_one_by_pid(args[0], bus, id, &new_line);
3023 static int dump(DBusConnection *bus, char **args) {
3024 DBusMessage *reply = NULL;
3029 dbus_error_init(&error);
3031 pager_open_if_enabled();
3033 r = bus_method_call_with_reply (
3035 "org.freedesktop.systemd1",
3036 "/org/freedesktop/systemd1",
3037 "org.freedesktop.systemd1.Manager",
3045 if (!dbus_message_get_args(reply, &error,
3046 DBUS_TYPE_STRING, &text,
3047 DBUS_TYPE_INVALID)) {
3048 log_error("Failed to parse reply: %s", bus_error_message(&error));
3053 fputs(text, stdout);
3057 dbus_message_unref(reply);
3059 dbus_error_free(&error);
3064 static int snapshot(DBusConnection *bus, char **args) {
3065 DBusMessage *reply = NULL;
3068 dbus_bool_t cleanup = FALSE;
3069 DBusMessageIter iter, sub;
3071 *name = "", *path, *id,
3072 *interface = "org.freedesktop.systemd1.Unit",
3076 dbus_error_init(&error);
3078 if (strv_length(args) > 1)
3081 n = unit_name_mangle(name);
3082 r = bus_method_call_with_reply (
3084 "org.freedesktop.systemd1",
3085 "/org/freedesktop/systemd1",
3086 "org.freedesktop.systemd1.Manager",
3090 DBUS_TYPE_STRING, n ? (const char**) &n : &name,
3091 DBUS_TYPE_BOOLEAN, &cleanup,
3097 if (!dbus_message_get_args(reply, &error,
3098 DBUS_TYPE_OBJECT_PATH, &path,
3099 DBUS_TYPE_INVALID)) {
3100 log_error("Failed to parse reply: %s", bus_error_message(&error));
3105 dbus_message_unref(reply);
3106 r = bus_method_call_with_reply (
3108 "org.freedesktop.systemd1",
3110 "org.freedesktop.DBus.Properties",
3114 DBUS_TYPE_STRING, &interface,
3115 DBUS_TYPE_STRING, &property,
3120 if (!dbus_message_iter_init(reply, &iter) ||
3121 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3122 log_error("Failed to parse reply.");
3127 dbus_message_iter_recurse(&iter, &sub);
3129 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
3130 log_error("Failed to parse reply.");
3135 dbus_message_iter_get_basic(&sub, &id);
3142 dbus_message_unref(reply);
3144 dbus_error_free(&error);
3149 static int delete_snapshot(DBusConnection *bus, char **args) {
3150 DBusMessage *reply = NULL;
3157 dbus_error_init(&error);
3159 STRV_FOREACH(name, args+1) {
3160 const char *path = NULL;
3163 n = unit_name_mangle(*name);
3164 r = bus_method_call_with_reply (
3166 "org.freedesktop.systemd1",
3167 "/org/freedesktop/systemd1",
3168 "org.freedesktop.systemd1.Manager",
3172 DBUS_TYPE_STRING, n ? &n : name,
3178 if (!dbus_message_get_args(reply, &error,
3179 DBUS_TYPE_OBJECT_PATH, &path,
3180 DBUS_TYPE_INVALID)) {
3181 log_error("Failed to parse reply: %s", bus_error_message(&error));
3183 dbus_message_unref(reply);
3184 dbus_error_free(&error);
3187 dbus_message_unref(reply);
3189 r = bus_method_call_with_reply (
3191 "org.freedesktop.systemd1",
3193 "org.freedesktop.systemd1.Snapshot",
3206 static int daemon_reload(DBusConnection *bus, char **args) {
3211 if (arg_action == ACTION_RELOAD)
3213 else if (arg_action == ACTION_REEXEC)
3214 method = "Reexecute";
3216 assert(arg_action == ACTION_SYSTEMCTL);
3219 streq(args[0], "clear-jobs") ||
3220 streq(args[0], "cancel") ? "ClearJobs" :
3221 streq(args[0], "daemon-reexec") ? "Reexecute" :
3222 streq(args[0], "reset-failed") ? "ResetFailed" :
3223 streq(args[0], "halt") ? "Halt" :
3224 streq(args[0], "poweroff") ? "PowerOff" :
3225 streq(args[0], "reboot") ? "Reboot" :
3226 streq(args[0], "kexec") ? "KExec" :
3227 streq(args[0], "exit") ? "Exit" :
3228 /* "daemon-reload" */ "Reload";
3231 r = bus_method_call_with_reply (
3233 "org.freedesktop.systemd1",
3234 "/org/freedesktop/systemd1",
3235 "org.freedesktop.systemd1.Manager",
3241 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
3242 /* There's always a fallback possible for
3243 * legacy actions. */
3245 else if (r == -ETIMEDOUT && streq(method, "Reexecute"))
3246 /* On reexecution, we expect a disconnect, not
3250 log_error("Failed to issue method call: %s", bus_error_message(&error));
3251 dbus_error_free(&error);
3256 static int reset_failed(DBusConnection *bus, char **args) {
3260 if (strv_length(args) <= 1)
3261 return daemon_reload(bus, args);
3263 STRV_FOREACH(name, args+1) {
3264 n = unit_name_mangle(*name);
3265 r = bus_method_call_with_reply (
3267 "org.freedesktop.systemd1",
3268 "/org/freedesktop/systemd1",
3269 "org.freedesktop.systemd1.Manager",
3273 DBUS_TYPE_STRING, n ? &n : name,
3284 static int show_enviroment(DBusConnection *bus, char **args) {
3285 DBusMessage *reply = NULL;
3286 DBusMessageIter iter, sub, sub2;
3289 *interface = "org.freedesktop.systemd1.Manager",
3290 *property = "Environment";
3292 pager_open_if_enabled();
3294 r = bus_method_call_with_reply (
3296 "org.freedesktop.systemd1",
3297 "/org/freedesktop/systemd1",
3298 "org.freedesktop.DBus.Properties",
3302 DBUS_TYPE_STRING, &interface,
3303 DBUS_TYPE_STRING, &property,
3308 if (!dbus_message_iter_init(reply, &iter) ||
3309 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3310 log_error("Failed to parse reply.");
3315 dbus_message_iter_recurse(&iter, &sub);
3317 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_ARRAY ||
3318 dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_STRING) {
3319 log_error("Failed to parse reply.");
3324 dbus_message_iter_recurse(&sub, &sub2);
3326 while (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_INVALID) {
3329 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
3330 log_error("Failed to parse reply.");
3335 dbus_message_iter_get_basic(&sub2, &text);
3336 printf("%s\n", text);
3338 dbus_message_iter_next(&sub2);
3345 dbus_message_unref(reply);
3350 static int switch_root(DBusConnection *bus, char **args) {
3353 _cleanup_free_ char *init = NULL;
3355 l = strv_length(args);
3356 if (l < 2 || l > 3) {
3357 log_error("Wrong number of arguments.");
3364 init = strdup(args[2]);
3366 parse_env_file("/proc/cmdline", WHITESPACE,
3378 log_debug("switching root - root: %s; init: %s", root, init);
3380 return bus_method_call_with_reply (
3382 "org.freedesktop.systemd1",
3383 "/org/freedesktop/systemd1",
3384 "org.freedesktop.systemd1.Manager",
3388 DBUS_TYPE_STRING, &root,
3389 DBUS_TYPE_STRING, &init,
3393 static int set_environment(DBusConnection *bus, char **args) {
3394 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
3397 DBusMessageIter iter;
3402 dbus_error_init(&error);
3404 method = streq(args[0], "set-environment")
3406 : "UnsetEnvironment";
3408 m = dbus_message_new_method_call(
3409 "org.freedesktop.systemd1",
3410 "/org/freedesktop/systemd1",
3411 "org.freedesktop.systemd1.Manager",
3416 dbus_message_iter_init_append(m, &iter);
3418 r = bus_append_strv_iter(&iter, args + 1);
3422 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3424 log_error("Failed to issue method call: %s", bus_error_message(&error));
3432 dbus_error_free(&error);
3436 static int enable_sysv_units(char **args) {
3439 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
3440 const char *verb = args[0];
3441 unsigned f = 1, t = 1;
3444 if (arg_scope != UNIT_FILE_SYSTEM)
3447 if (!streq(verb, "enable") &&
3448 !streq(verb, "disable") &&
3449 !streq(verb, "is-enabled"))
3452 /* Processes all SysV units, and reshuffles the array so that
3453 * afterwards only the native units remain */
3456 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, NULL, NULL, NULL);
3461 for (f = 1; args[f]; f++) {
3464 bool found_native = false, found_sysv;
3466 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
3467 char **k, *l, *q = NULL;
3474 if (!endswith(name, ".service"))
3477 if (path_is_absolute(name))
3480 STRV_FOREACH(k, paths.unit_path) {
3483 if (!isempty(arg_root))
3484 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
3486 asprintf(&p, "%s/%s", *k, name);
3493 found_native = access(p, F_OK) >= 0;
3504 if (!isempty(arg_root))
3505 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
3507 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
3513 p[strlen(p) - sizeof(".service") + 1] = 0;
3514 found_sysv = access(p, F_OK) >= 0;
3521 /* Mark this entry, so that we don't try enabling it as native unit */
3522 args[f] = (char*) "";
3524 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
3526 if (!isempty(arg_root))
3527 argv[c++] = q = strappend("--root=", arg_root);
3529 argv[c++] = path_get_file_name(p);
3531 streq(verb, "enable") ? "on" :
3532 streq(verb, "disable") ? "off" : "--level=5";
3535 l = strv_join((char**)argv, " ");
3543 log_info("Executing %s", l);
3548 log_error("Failed to fork: %m");
3553 } else if (pid == 0) {
3556 execv(argv[0], (char**) argv);
3557 _exit(EXIT_FAILURE);
3563 j = wait_for_terminate(pid, &status);
3565 log_error("Failed to wait for child: %s", strerror(-r));
3570 if (status.si_code == CLD_EXITED) {
3571 if (streq(verb, "is-enabled")) {
3572 if (status.si_status == 0) {
3581 } else if (status.si_status != 0) {
3592 lookup_paths_free(&paths);
3594 /* Drop all SysV units */
3595 for (f = 1, t = 1; args[f]; f++) {
3597 if (isempty(args[f]))
3600 args[t++] = args[f];
3609 static int mangle_names(char **original_names, char ***mangled_names) {
3610 char **i, **l, **name;
3612 l = new(char*, strv_length(original_names) + 1);
3617 STRV_FOREACH(name, original_names) {
3619 /* When enabling units qualified path names are OK,
3620 * too, hence allow them explicitly. */
3625 *i = unit_name_mangle(*name);
3641 static int enable_unit(DBusConnection *bus, char **args) {
3642 const char *verb = args[0];
3643 UnitFileChange *changes = NULL;
3644 unsigned n_changes = 0, i;
3645 int carries_install_info = -1;
3646 DBusMessage *m = NULL, *reply = NULL;
3649 char **mangled_names = NULL;
3651 r = enable_sysv_units(args);
3658 dbus_error_init(&error);
3660 if (!bus || avoid_bus()) {
3661 if (streq(verb, "enable")) {
3662 r = unit_file_enable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3663 carries_install_info = r;
3664 } else if (streq(verb, "disable"))
3665 r = unit_file_disable(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3666 else if (streq(verb, "reenable")) {
3667 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3668 carries_install_info = r;
3669 } else if (streq(verb, "link"))
3670 r = unit_file_link(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3671 else if (streq(verb, "preset")) {
3672 r = unit_file_preset(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3673 carries_install_info = r;
3674 } else if (streq(verb, "mask"))
3675 r = unit_file_mask(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3676 else if (streq(verb, "unmask"))
3677 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3679 assert_not_reached("Unknown verb");
3682 log_error("Operation failed: %s", strerror(-r));
3687 for (i = 0; i < n_changes; i++) {
3688 if (changes[i].type == UNIT_FILE_SYMLINK)
3689 log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
3691 log_info("rm '%s'", changes[i].path);
3698 bool send_force = true, expect_carries_install_info = false;
3700 DBusMessageIter iter, sub, sub2;
3702 if (streq(verb, "enable")) {
3703 method = "EnableUnitFiles";
3704 expect_carries_install_info = true;
3705 } else if (streq(verb, "disable")) {
3706 method = "DisableUnitFiles";
3708 } else if (streq(verb, "reenable")) {
3709 method = "ReenableUnitFiles";
3710 expect_carries_install_info = true;
3711 } else if (streq(verb, "link"))
3712 method = "LinkUnitFiles";
3713 else if (streq(verb, "preset")) {
3714 method = "PresetUnitFiles";
3715 expect_carries_install_info = true;
3716 } else if (streq(verb, "mask"))
3717 method = "MaskUnitFiles";
3718 else if (streq(verb, "unmask")) {
3719 method = "UnmaskUnitFiles";
3722 assert_not_reached("Unknown verb");
3724 m = dbus_message_new_method_call(
3725 "org.freedesktop.systemd1",
3726 "/org/freedesktop/systemd1",
3727 "org.freedesktop.systemd1.Manager",
3734 dbus_message_iter_init_append(m, &iter);
3736 r = mangle_names(args+1, &mangled_names);
3740 r = bus_append_strv_iter(&iter, mangled_names);
3742 log_error("Failed to append unit files.");
3747 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &a)) {
3748 log_error("Failed to append runtime boolean.");
3756 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b)) {
3757 log_error("Failed to append force boolean.");
3763 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3765 log_error("Failed to issue method call: %s", bus_error_message(&error));
3770 if (!dbus_message_iter_init(reply, &iter)) {
3771 log_error("Failed to initialize iterator.");
3775 if (expect_carries_install_info) {
3776 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &b, true);
3778 log_error("Failed to parse reply.");
3782 carries_install_info = b;
3785 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3786 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
3787 log_error("Failed to parse reply.");
3792 dbus_message_iter_recurse(&iter, &sub);
3793 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
3794 const char *type, *path, *source;
3796 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
3797 log_error("Failed to parse reply.");
3802 dbus_message_iter_recurse(&sub, &sub2);
3804 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
3805 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
3806 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &source, false) < 0) {
3807 log_error("Failed to parse reply.");
3813 if (streq(type, "symlink"))
3814 log_info("ln -s '%s' '%s'", source, path);
3816 log_info("rm '%s'", path);
3819 dbus_message_iter_next(&sub);
3822 /* Try to reload if enabeld */
3824 r = daemon_reload(bus, args);
3827 if (carries_install_info == 0)
3829 "The unit files have no [Install] section. They are not meant to be enabled\n"
3830 "using systemctl.\n"
3831 "Possible reasons for having this kind of units are:\n"
3832 "1) A unit may be statically enabled by being symlinked from another unit's\n"
3833 " .wants/ or .requires/ directory.\n"
3834 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
3835 " a requirement dependency on it.\n"
3836 "3) A unit may be started when needed via activation (socket, path, timer,\n"
3837 " D-Bus, udev, scripted systemctl call, ...).\n");
3841 dbus_message_unref(m);
3844 dbus_message_unref(reply);
3846 unit_file_changes_free(changes, n_changes);
3848 dbus_error_free(&error);
3850 strv_free(mangled_names);
3855 static int unit_is_enabled(DBusConnection *bus, char **args) {
3858 DBusMessage *reply = NULL;
3862 dbus_error_init(&error);
3864 r = enable_sysv_units(args);
3870 if (!bus || avoid_bus()) {
3872 STRV_FOREACH(name, args+1) {
3873 UnitFileState state;
3875 state = unit_file_get_state(arg_scope, arg_root, *name);
3881 if (state == UNIT_FILE_ENABLED ||
3882 state == UNIT_FILE_ENABLED_RUNTIME ||
3883 state == UNIT_FILE_STATIC)
3887 puts(unit_file_state_to_string(state));
3891 STRV_FOREACH(name, args+1) {
3894 r = bus_method_call_with_reply (
3896 "org.freedesktop.systemd1",
3897 "/org/freedesktop/systemd1",
3898 "org.freedesktop.systemd1.Manager",
3902 DBUS_TYPE_STRING, name,
3907 if (!dbus_message_get_args(reply, &error,
3908 DBUS_TYPE_STRING, &s,
3909 DBUS_TYPE_INVALID)) {
3910 log_error("Failed to parse reply: %s", bus_error_message(&error));
3915 dbus_message_unref(reply);
3918 if (streq(s, "enabled") ||
3919 streq(s, "enabled-runtime") ||
3928 r = enabled ? 0 : 1;
3932 dbus_message_unref(reply);
3934 dbus_error_free(&error);
3938 static int systemctl_help(void) {
3940 pager_open_if_enabled();
3942 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
3943 "Query or send control commands to the systemd manager.\n\n"
3944 " -h --help Show this help\n"
3945 " --version Show package version\n"
3946 " -t --type=TYPE List only units of a particular type\n"
3947 " -p --property=NAME Show only properties by this name\n"
3948 " -a --all Show all units/properties, including dead/empty ones\n"
3949 " --failed Show only failed units\n"
3950 " --full Don't ellipsize unit names on output\n"
3951 " --fail When queueing a new job, fail if conflicting jobs are\n"
3953 " --ignore-dependencies\n"
3954 " When queueing a new job, ignore all its dependencies\n"
3955 " --kill-who=WHO Who to send signal to\n"
3956 " -s --signal=SIGNAL Which signal to send\n"
3957 " -H --host=[USER@]HOST\n"
3958 " Show information for remote host\n"
3959 " -P --privileged Acquire privileges before execution\n"
3960 " -q --quiet Suppress output\n"
3961 " --no-block Do not wait until operation finished\n"
3962 " --no-wall Don't send wall message before halt/power-off/reboot\n"
3963 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
3965 " --no-legend Do not print a legend (column headers and hints)\n"
3966 " --no-pager Do not pipe output into a pager\n"
3967 " --no-ask-password\n"
3968 " Do not ask for system passwords\n"
3969 " --order When generating graph for dot, show only order\n"
3970 " --require When generating graph for dot, show only requirement\n"
3971 " --system Connect to system manager\n"
3972 " --user Connect to user service manager\n"
3973 " --global Enable/disable unit files globally\n"
3974 " -f --force When enabling unit files, override existing symlinks\n"
3975 " When shutting down, execute action immediately\n"
3976 " --root=PATH Enable unit files in the specified root directory\n"
3977 " --runtime Enable unit files only temporarily until next reboot\n"
3978 " -n --lines=INTEGER Journal entries to show\n"
3979 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
3980 " verbose, export, json, json-pretty, json-sse, cat)\n\n"
3982 " list-units List loaded units\n"
3983 " start [NAME...] Start (activate) one or more units\n"
3984 " stop [NAME...] Stop (deactivate) one or more units\n"
3985 " reload [NAME...] Reload one or more units\n"
3986 " restart [NAME...] Start or restart one or more units\n"
3987 " try-restart [NAME...] Restart one or more units if active\n"
3988 " reload-or-restart [NAME...] Reload one or more units if possible,\n"
3989 " otherwise start or restart\n"
3990 " reload-or-try-restart [NAME...] Reload one or more units if possible,\n"
3991 " otherwise restart if active\n"
3992 " isolate [NAME] Start one unit and stop all others\n"
3993 " kill [NAME...] Send signal to processes of a unit\n"
3994 " is-active [NAME...] Check whether units are active\n"
3995 " is-failed [NAME...] Check whether units are failed\n"
3996 " status [NAME...|PID...] Show runtime status of one or more units\n"
3997 " show [NAME...|JOB...] Show properties of one or more\n"
3998 " units/jobs or the manager\n"
3999 " help [NAME...|PID...] Show manual for one or more units\n"
4000 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
4002 " load [NAME...] Load one or more units\n\n"
4003 "Unit File Commands:\n"
4004 " list-unit-files List installed unit files\n"
4005 " enable [NAME...] Enable one or more unit files\n"
4006 " disable [NAME...] Disable one or more unit files\n"
4007 " reenable [NAME...] Reenable one or more unit files\n"
4008 " preset [NAME...] Enable/disable one or more unit files\n"
4009 " based on preset configuration\n"
4010 " mask [NAME...] Mask one or more units\n"
4011 " unmask [NAME...] Unmask one or more units\n"
4012 " link [PATH...] Link one or more units files into\n"
4013 " the search path\n"
4014 " is-enabled [NAME...] Check whether unit files are enabled\n\n"
4016 " list-jobs List jobs\n"
4017 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
4018 "Status Commands:\n"
4019 " dump Dump server status\n"
4020 " dot Dump dependency graph for dot(1)\n\n"
4021 "Snapshot Commands:\n"
4022 " snapshot [NAME] Create a snapshot\n"
4023 " delete [NAME...] Remove one or more snapshots\n\n"
4024 "Environment Commands:\n"
4025 " show-environment Dump environment\n"
4026 " set-environment [NAME=VALUE...] Set one or more environment variables\n"
4027 " unset-environment [NAME...] Unset one or more environment variables\n\n"
4028 "Manager Lifecycle Commands:\n"
4029 " daemon-reload Reload systemd manager configuration\n"
4030 " daemon-reexec Reexecute systemd manager\n\n"
4031 "System Commands:\n"
4032 " default Enter system default mode\n"
4033 " rescue Enter system rescue mode\n"
4034 " emergency Enter system emergency mode\n"
4035 " halt Shut down and halt the system\n"
4036 " poweroff Shut down and power-off the system\n"
4037 " reboot Shut down and reboot the system\n"
4038 " kexec Shut down and reboot the system with kexec\n"
4039 " exit Request user instance exit\n"
4040 " switch-root [ROOT] [INIT] Change to a different root file system\n"
4041 " suspend Suspend the system\n"
4042 " hibernate Hibernate the system\n"
4043 " hybrid-sleep Hibernate and suspend the system\n",
4044 program_invocation_short_name);
4049 static int halt_help(void) {
4051 printf("%s [OPTIONS...]\n\n"
4052 "%s the system.\n\n"
4053 " --help Show this help\n"
4054 " --halt Halt the machine\n"
4055 " -p --poweroff Switch off the machine\n"
4056 " --reboot Reboot the machine\n"
4057 " -f --force Force immediate halt/power-off/reboot\n"
4058 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
4059 " -d --no-wtmp Don't write wtmp record\n"
4060 " --no-wall Don't send wall message before halt/power-off/reboot\n",
4061 program_invocation_short_name,
4062 arg_action == ACTION_REBOOT ? "Reboot" :
4063 arg_action == ACTION_POWEROFF ? "Power off" :
4069 static int shutdown_help(void) {
4071 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
4072 "Shut down the system.\n\n"
4073 " --help Show this help\n"
4074 " -H --halt Halt the machine\n"
4075 " -P --poweroff Power-off the machine\n"
4076 " -r --reboot Reboot the machine\n"
4077 " -h Equivalent to --poweroff, overridden by --halt\n"
4078 " -k Don't halt/power-off/reboot, just send warnings\n"
4079 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4080 " -c Cancel a pending shutdown\n",
4081 program_invocation_short_name);
4086 static int telinit_help(void) {
4088 printf("%s [OPTIONS...] {COMMAND}\n\n"
4089 "Send control commands to the init daemon.\n\n"
4090 " --help Show this help\n"
4091 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
4093 " 0 Power-off the machine\n"
4094 " 6 Reboot the machine\n"
4095 " 2, 3, 4, 5 Start runlevelX.target unit\n"
4096 " 1, s, S Enter rescue mode\n"
4097 " q, Q Reload init daemon configuration\n"
4098 " u, U Reexecute init daemon\n",
4099 program_invocation_short_name);
4104 static int runlevel_help(void) {
4106 printf("%s [OPTIONS...]\n\n"
4107 "Prints the previous and current runlevel of the init system.\n\n"
4108 " --help Show this help\n",
4109 program_invocation_short_name);
4114 static int help_types(void) {
4117 puts("Available unit types:");
4118 for(i = UNIT_SERVICE; i < _UNIT_TYPE_MAX; i++)
4119 if (unit_type_table[i])
4120 puts(unit_type_table[i]);
4122 puts("\nAvailable unit load states: ");
4123 for(i = UNIT_STUB; i < _UNIT_LOAD_STATE_MAX; i++)
4124 if (unit_type_table[i])
4125 puts(unit_load_state_table[i]);
4130 static int systemctl_parse_argv(int argc, char *argv[]) {
4134 ARG_IGNORE_DEPENDENCIES,
4149 ARG_NO_ASK_PASSWORD,
4155 static const struct option options[] = {
4156 { "help", no_argument, NULL, 'h' },
4157 { "version", no_argument, NULL, ARG_VERSION },
4158 { "type", required_argument, NULL, 't' },
4159 { "property", required_argument, NULL, 'p' },
4160 { "all", no_argument, NULL, 'a' },
4161 { "failed", no_argument, NULL, ARG_FAILED },
4162 { "full", no_argument, NULL, ARG_FULL },
4163 { "fail", no_argument, NULL, ARG_FAIL },
4164 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
4165 { "user", no_argument, NULL, ARG_USER },
4166 { "system", no_argument, NULL, ARG_SYSTEM },
4167 { "global", no_argument, NULL, ARG_GLOBAL },
4168 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
4169 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
4170 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
4171 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4172 { "quiet", no_argument, NULL, 'q' },
4173 { "order", no_argument, NULL, ARG_ORDER },
4174 { "require", no_argument, NULL, ARG_REQUIRE },
4175 { "root", required_argument, NULL, ARG_ROOT },
4176 { "force", no_argument, NULL, ARG_FORCE },
4177 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
4178 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
4179 { "signal", required_argument, NULL, 's' },
4180 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
4181 { "host", required_argument, NULL, 'H' },
4182 { "privileged",no_argument, NULL, 'P' },
4183 { "runtime", no_argument, NULL, ARG_RUNTIME },
4184 { "lines", required_argument, NULL, 'n' },
4185 { "output", required_argument, NULL, 'o' },
4186 { NULL, 0, NULL, 0 }
4194 while ((c = getopt_long(argc, argv, "ht:p:aqfs:H:Pn:o:", options, NULL)) >= 0) {
4203 puts(PACKAGE_STRING);
4204 puts(SYSTEMD_FEATURES);
4208 if (streq(optarg, "help")) {
4213 if (unit_type_from_string(optarg) >= 0) {
4217 if (unit_load_state_from_string(optarg) >= 0) {
4218 arg_load_state = optarg;
4221 log_error("Unkown unit type or load state '%s'.",
4223 log_info("Use -t help to see a list of allowed values.");
4228 if (!(l = strv_append(arg_property, optarg)))
4231 strv_free(arg_property);
4234 /* If the user asked for a particular
4235 * property, show it to him, even if it is
4246 arg_job_mode = "fail";
4249 case ARG_IGNORE_DEPENDENCIES:
4250 arg_job_mode = "ignore-dependencies";
4254 arg_scope = UNIT_FILE_USER;
4258 arg_scope = UNIT_FILE_SYSTEM;
4262 arg_scope = UNIT_FILE_GLOBAL;
4266 arg_no_block = true;
4270 arg_no_legend = true;
4274 arg_no_pager = true;
4282 arg_dot = DOT_ORDER;
4286 arg_dot = DOT_REQUIRE;
4314 arg_no_reload = true;
4318 arg_kill_who = optarg;
4322 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
4323 log_error("Failed to parse signal string %s.", optarg);
4328 case ARG_NO_ASK_PASSWORD:
4329 arg_ask_password = false;
4333 arg_transport = TRANSPORT_POLKIT;
4337 arg_transport = TRANSPORT_SSH;
4346 if (safe_atou(optarg, &arg_lines) < 0) {
4347 log_error("Failed to parse lines '%s'", optarg);
4353 arg_output = output_mode_from_string(optarg);
4354 if (arg_output < 0) {
4355 log_error("Unknown output '%s'.", optarg);
4364 log_error("Unknown option code '%c'.", c);
4369 if (arg_transport != TRANSPORT_NORMAL && arg_scope != UNIT_FILE_SYSTEM) {
4370 log_error("Cannot access user instance remotely.");
4377 static int halt_parse_argv(int argc, char *argv[]) {
4386 static const struct option options[] = {
4387 { "help", no_argument, NULL, ARG_HELP },
4388 { "halt", no_argument, NULL, ARG_HALT },
4389 { "poweroff", no_argument, NULL, 'p' },
4390 { "reboot", no_argument, NULL, ARG_REBOOT },
4391 { "force", no_argument, NULL, 'f' },
4392 { "wtmp-only", no_argument, NULL, 'w' },
4393 { "no-wtmp", no_argument, NULL, 'd' },
4394 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4395 { NULL, 0, NULL, 0 }
4403 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
4404 if (runlevel == '0' || runlevel == '6')
4407 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
4415 arg_action = ACTION_HALT;
4419 if (arg_action != ACTION_REBOOT)
4420 arg_action = ACTION_POWEROFF;
4424 arg_action = ACTION_REBOOT;
4446 /* Compatibility nops */
4453 log_error("Unknown option code '%c'.", c);
4458 if (optind < argc) {
4459 log_error("Too many arguments.");
4466 static int parse_time_spec(const char *t, usec_t *_u) {
4470 if (streq(t, "now"))
4472 else if (!strchr(t, ':')) {
4475 if (safe_atou64(t, &u) < 0)
4478 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
4487 hour = strtol(t, &e, 10);
4488 if (errno != 0 || *e != ':' || hour < 0 || hour > 23)
4491 minute = strtol(e+1, &e, 10);
4492 if (errno != 0 || *e != 0 || minute < 0 || minute > 59)
4495 n = now(CLOCK_REALTIME);
4496 s = (time_t) (n / USEC_PER_SEC);
4499 assert_se(localtime_r(&s, &tm));
4501 tm.tm_hour = (int) hour;
4502 tm.tm_min = (int) minute;
4505 assert_se(s = mktime(&tm));
4507 *_u = (usec_t) s * USEC_PER_SEC;
4510 *_u += USEC_PER_DAY;
4516 static int shutdown_parse_argv(int argc, char *argv[]) {
4523 static const struct option options[] = {
4524 { "help", no_argument, NULL, ARG_HELP },
4525 { "halt", no_argument, NULL, 'H' },
4526 { "poweroff", no_argument, NULL, 'P' },
4527 { "reboot", no_argument, NULL, 'r' },
4528 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
4529 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4530 { NULL, 0, NULL, 0 }
4538 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
4546 arg_action = ACTION_HALT;
4550 arg_action = ACTION_POWEROFF;
4555 arg_action = ACTION_KEXEC;
4557 arg_action = ACTION_REBOOT;
4561 arg_action = ACTION_KEXEC;
4565 if (arg_action != ACTION_HALT)
4566 arg_action = ACTION_POWEROFF;
4579 /* Compatibility nops */
4583 arg_action = ACTION_CANCEL_SHUTDOWN;
4590 log_error("Unknown option code '%c'.", c);
4595 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
4596 r = parse_time_spec(argv[optind], &arg_when);
4598 log_error("Failed to parse time specification: %s", argv[optind]);
4602 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
4604 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
4605 /* No time argument for shutdown cancel */
4606 arg_wall = argv + optind;
4607 else if (argc > optind + 1)
4608 /* We skip the time argument */
4609 arg_wall = argv + optind + 1;
4616 static int telinit_parse_argv(int argc, char *argv[]) {
4623 static const struct option options[] = {
4624 { "help", no_argument, NULL, ARG_HELP },
4625 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4626 { NULL, 0, NULL, 0 }
4629 static const struct {
4633 { '0', ACTION_POWEROFF },
4634 { '6', ACTION_REBOOT },
4635 { '1', ACTION_RESCUE },
4636 { '2', ACTION_RUNLEVEL2 },
4637 { '3', ACTION_RUNLEVEL3 },
4638 { '4', ACTION_RUNLEVEL4 },
4639 { '5', ACTION_RUNLEVEL5 },
4640 { 's', ACTION_RESCUE },
4641 { 'S', ACTION_RESCUE },
4642 { 'q', ACTION_RELOAD },
4643 { 'Q', ACTION_RELOAD },
4644 { 'u', ACTION_REEXEC },
4645 { 'U', ACTION_REEXEC }
4654 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4669 log_error("Unknown option code '%c'.", c);
4674 if (optind >= argc) {
4679 if (optind + 1 < argc) {
4680 log_error("Too many arguments.");
4684 if (strlen(argv[optind]) != 1) {
4685 log_error("Expected single character argument.");
4689 for (i = 0; i < ELEMENTSOF(table); i++)
4690 if (table[i].from == argv[optind][0])
4693 if (i >= ELEMENTSOF(table)) {
4694 log_error("Unknown command '%s'.", argv[optind]);
4698 arg_action = table[i].to;
4705 static int runlevel_parse_argv(int argc, char *argv[]) {
4711 static const struct option options[] = {
4712 { "help", no_argument, NULL, ARG_HELP },
4713 { NULL, 0, NULL, 0 }
4721 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4732 log_error("Unknown option code '%c'.", c);
4737 if (optind < argc) {
4738 log_error("Too many arguments.");
4745 static int parse_argv(int argc, char *argv[]) {
4749 if (program_invocation_short_name) {
4751 if (strstr(program_invocation_short_name, "halt")) {
4752 arg_action = ACTION_HALT;
4753 return halt_parse_argv(argc, argv);
4754 } else if (strstr(program_invocation_short_name, "poweroff")) {
4755 arg_action = ACTION_POWEROFF;
4756 return halt_parse_argv(argc, argv);
4757 } else if (strstr(program_invocation_short_name, "reboot")) {
4759 arg_action = ACTION_KEXEC;
4761 arg_action = ACTION_REBOOT;
4762 return halt_parse_argv(argc, argv);
4763 } else if (strstr(program_invocation_short_name, "shutdown")) {
4764 arg_action = ACTION_POWEROFF;
4765 return shutdown_parse_argv(argc, argv);
4766 } else if (strstr(program_invocation_short_name, "init")) {
4768 if (sd_booted() > 0) {
4769 arg_action = ACTION_INVALID;
4770 return telinit_parse_argv(argc, argv);
4772 /* Hmm, so some other init system is
4773 * running, we need to forward this
4774 * request to it. For now we simply
4775 * guess that it is Upstart. */
4777 execv("/lib/upstart/telinit", argv);
4779 log_error("Couldn't find an alternative telinit implementation to spawn.");
4783 } else if (strstr(program_invocation_short_name, "runlevel")) {
4784 arg_action = ACTION_RUNLEVEL;
4785 return runlevel_parse_argv(argc, argv);
4789 arg_action = ACTION_SYSTEMCTL;
4790 return systemctl_parse_argv(argc, argv);
4793 static int action_to_runlevel(void) {
4795 static const char table[_ACTION_MAX] = {
4796 [ACTION_HALT] = '0',
4797 [ACTION_POWEROFF] = '0',
4798 [ACTION_REBOOT] = '6',
4799 [ACTION_RUNLEVEL2] = '2',
4800 [ACTION_RUNLEVEL3] = '3',
4801 [ACTION_RUNLEVEL4] = '4',
4802 [ACTION_RUNLEVEL5] = '5',
4803 [ACTION_RESCUE] = '1'
4806 assert(arg_action < _ACTION_MAX);
4808 return table[arg_action];
4811 static int talk_upstart(void) {
4812 DBusMessage *m = NULL, *reply = NULL;
4814 int previous, rl, r;
4816 env1_buf[] = "RUNLEVEL=X",
4817 env2_buf[] = "PREVLEVEL=X";
4818 char *env1 = env1_buf, *env2 = env2_buf;
4819 const char *emit = "runlevel";
4820 dbus_bool_t b_false = FALSE;
4821 DBusMessageIter iter, sub;
4822 DBusConnection *bus;
4824 dbus_error_init(&error);
4826 if (!(rl = action_to_runlevel()))
4829 if (utmp_get_runlevel(&previous, NULL) < 0)
4832 if (!(bus = dbus_connection_open_private("unix:abstract=/com/ubuntu/upstart", &error))) {
4833 if (dbus_error_has_name(&error, DBUS_ERROR_NO_SERVER)) {
4838 log_error("Failed to connect to Upstart bus: %s", bus_error_message(&error));
4843 if ((r = bus_check_peercred(bus)) < 0) {
4844 log_error("Failed to verify owner of bus.");
4848 if (!(m = dbus_message_new_method_call(
4849 "com.ubuntu.Upstart",
4850 "/com/ubuntu/Upstart",
4851 "com.ubuntu.Upstart0_6",
4854 log_error("Could not allocate message.");
4859 dbus_message_iter_init_append(m, &iter);
4861 env1_buf[sizeof(env1_buf)-2] = rl;
4862 env2_buf[sizeof(env2_buf)-2] = previous;
4864 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &emit) ||
4865 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub) ||
4866 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env1) ||
4867 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env2) ||
4868 !dbus_message_iter_close_container(&iter, &sub) ||
4869 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b_false)) {
4870 log_error("Could not append arguments to message.");
4875 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
4877 if (bus_error_is_no_service(&error)) {
4882 log_error("Failed to issue method call: %s", bus_error_message(&error));
4891 dbus_message_unref(m);
4894 dbus_message_unref(reply);
4897 dbus_connection_flush(bus);
4898 dbus_connection_close(bus);
4899 dbus_connection_unref(bus);
4902 dbus_error_free(&error);
4907 static int talk_initctl(void) {
4908 struct init_request request;
4912 if (!(rl = action_to_runlevel()))
4916 request.magic = INIT_MAGIC;
4917 request.sleeptime = 0;
4918 request.cmd = INIT_CMD_RUNLVL;
4919 request.runlevel = rl;
4921 if ((fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY)) < 0) {
4923 if (errno == ENOENT)
4926 log_error("Failed to open "INIT_FIFO": %m");
4931 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
4932 close_nointr_nofail(fd);
4935 log_error("Failed to write to "INIT_FIFO": %m");
4936 return errno ? -errno : -EIO;
4942 static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
4944 static const struct {
4952 int (* const dispatch)(DBusConnection *bus, char **args);
4954 { "list-units", LESS, 1, list_units },
4955 { "list-unit-files", EQUAL, 1, list_unit_files },
4956 { "list-jobs", EQUAL, 1, list_jobs },
4957 { "clear-jobs", EQUAL, 1, daemon_reload },
4958 { "load", MORE, 2, load_unit },
4959 { "cancel", MORE, 2, cancel_job },
4960 { "start", MORE, 2, start_unit },
4961 { "stop", MORE, 2, start_unit },
4962 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
4963 { "reload", MORE, 2, start_unit },
4964 { "restart", MORE, 2, start_unit },
4965 { "try-restart", MORE, 2, start_unit },
4966 { "reload-or-restart", MORE, 2, start_unit },
4967 { "reload-or-try-restart", MORE, 2, start_unit },
4968 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
4969 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
4970 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
4971 { "isolate", EQUAL, 2, start_unit },
4972 { "kill", MORE, 2, kill_unit },
4973 { "is-active", MORE, 2, check_unit_active },
4974 { "check", MORE, 2, check_unit_active },
4975 { "is-failed", MORE, 2, check_unit_failed },
4976 { "show", MORE, 1, show },
4977 { "status", MORE, 2, show },
4978 { "help", MORE, 2, show },
4979 { "dump", EQUAL, 1, dump },
4980 { "dot", EQUAL, 1, dot },
4981 { "snapshot", LESS, 2, snapshot },
4982 { "delete", MORE, 2, delete_snapshot },
4983 { "daemon-reload", EQUAL, 1, daemon_reload },
4984 { "daemon-reexec", EQUAL, 1, daemon_reload },
4985 { "show-environment", EQUAL, 1, show_enviroment },
4986 { "set-environment", MORE, 2, set_environment },
4987 { "unset-environment", MORE, 2, set_environment },
4988 { "halt", EQUAL, 1, start_special },
4989 { "poweroff", EQUAL, 1, start_special },
4990 { "reboot", EQUAL, 1, start_special },
4991 { "kexec", EQUAL, 1, start_special },
4992 { "suspend", EQUAL, 1, start_special },
4993 { "hibernate", EQUAL, 1, start_special },
4994 { "hybrid-sleep", EQUAL, 1, start_special },
4995 { "default", EQUAL, 1, start_special },
4996 { "rescue", EQUAL, 1, start_special },
4997 { "emergency", EQUAL, 1, start_special },
4998 { "exit", EQUAL, 1, start_special },
4999 { "reset-failed", MORE, 1, reset_failed },
5000 { "enable", MORE, 2, enable_unit },
5001 { "disable", MORE, 2, enable_unit },
5002 { "is-enabled", MORE, 2, unit_is_enabled },
5003 { "reenable", MORE, 2, enable_unit },
5004 { "preset", MORE, 2, enable_unit },
5005 { "mask", MORE, 2, enable_unit },
5006 { "unmask", MORE, 2, enable_unit },
5007 { "link", MORE, 2, enable_unit },
5008 { "switch-root", MORE, 2, switch_root },
5018 left = argc - optind;
5021 /* Special rule: no arguments means "list-units" */
5024 if (streq(argv[optind], "help") && !argv[optind+1]) {
5025 log_error("This command expects one or more "
5026 "unit names. Did you mean --help?");
5030 for (i = 0; i < ELEMENTSOF(verbs); i++)
5031 if (streq(argv[optind], verbs[i].verb))
5034 if (i >= ELEMENTSOF(verbs)) {
5035 log_error("Unknown operation '%s'.", argv[optind]);
5040 switch (verbs[i].argc_cmp) {
5043 if (left != verbs[i].argc) {
5044 log_error("Invalid number of arguments.");
5051 if (left < verbs[i].argc) {
5052 log_error("Too few arguments.");
5059 if (left > verbs[i].argc) {
5060 log_error("Too many arguments.");
5067 assert_not_reached("Unknown comparison operator.");
5070 /* Require a bus connection for all operations but
5072 if (!streq(verbs[i].verb, "enable") &&
5073 !streq(verbs[i].verb, "disable") &&
5074 !streq(verbs[i].verb, "is-enabled") &&
5075 !streq(verbs[i].verb, "list-unit-files") &&
5076 !streq(verbs[i].verb, "reenable") &&
5077 !streq(verbs[i].verb, "preset") &&
5078 !streq(verbs[i].verb, "mask") &&
5079 !streq(verbs[i].verb, "unmask") &&
5080 !streq(verbs[i].verb, "link")) {
5082 if (running_in_chroot() > 0) {
5083 log_info("Running in chroot, ignoring request.");
5087 if (((!streq(verbs[i].verb, "reboot") &&
5088 !streq(verbs[i].verb, "halt") &&
5089 !streq(verbs[i].verb, "poweroff")) || arg_force <= 0) && !bus) {
5090 log_error("Failed to get D-Bus connection: %s",
5091 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5097 if (!bus && !avoid_bus()) {
5098 log_error("Failed to get D-Bus connection: %s",
5099 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5104 return verbs[i].dispatch(bus, argv + optind);
5107 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
5109 struct msghdr msghdr;
5110 struct iovec iovec[2];
5111 union sockaddr_union sockaddr;
5112 struct sd_shutdown_command c;
5114 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
5121 c.dry_run = dry_run;
5125 sockaddr.sa.sa_family = AF_UNIX;
5126 strncpy(sockaddr.un.sun_path, "/run/systemd/shutdownd", sizeof(sockaddr.un.sun_path));
5129 msghdr.msg_name = &sockaddr;
5130 msghdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + sizeof("/run/systemd/shutdownd") - 1;
5133 iovec[0].iov_base = (char*) &c;
5134 iovec[0].iov_len = offsetof(struct sd_shutdown_command, wall_message);
5136 if (isempty(message))
5137 msghdr.msg_iovlen = 1;
5139 iovec[1].iov_base = (char*) message;
5140 iovec[1].iov_len = strlen(message);
5141 msghdr.msg_iovlen = 2;
5143 msghdr.msg_iov = iovec;
5145 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0) {
5146 close_nointr_nofail(fd);
5150 close_nointr_nofail(fd);
5154 static int reload_with_fallback(DBusConnection *bus) {
5157 /* First, try systemd via D-Bus. */
5158 if (daemon_reload(bus, NULL) >= 0)
5162 /* Nothing else worked, so let's try signals */
5163 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
5165 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
5166 log_error("kill() failed: %m");
5173 static int start_with_fallback(DBusConnection *bus) {
5176 /* First, try systemd via D-Bus. */
5177 if (start_unit(bus, NULL) >= 0)
5181 /* Hmm, talking to systemd via D-Bus didn't work. Then
5182 * let's try to talk to Upstart via D-Bus. */
5183 if (talk_upstart() > 0)
5186 /* Nothing else worked, so let's try
5188 if (talk_initctl() > 0)
5191 log_error("Failed to talk to init daemon.");
5195 warn_wall(arg_action);
5199 static _noreturn_ void halt_now(enum action a) {
5201 /* Make sure C-A-D is handled by the kernel from this
5203 reboot(RB_ENABLE_CAD);
5208 log_info("Halting.");
5209 reboot(RB_HALT_SYSTEM);
5212 case ACTION_POWEROFF:
5213 log_info("Powering off.");
5214 reboot(RB_POWER_OFF);
5218 log_info("Rebooting.");
5219 reboot(RB_AUTOBOOT);
5223 assert_not_reached("Unknown halt action.");
5226 assert_not_reached("Uh? This shouldn't happen.");
5229 static int halt_main(DBusConnection *bus) {
5232 if (geteuid() != 0) {
5233 /* Try logind if we are a normal user and no special
5234 * mode applies. Maybe PolicyKit allows us to shutdown
5237 if (arg_when <= 0 &&
5240 (arg_action == ACTION_POWEROFF ||
5241 arg_action == ACTION_REBOOT)) {
5242 r = reboot_with_logind(bus, arg_action);
5247 log_error("Must be root.");
5254 m = strv_join(arg_wall, " ");
5255 r = send_shutdownd(arg_when,
5256 arg_action == ACTION_HALT ? 'H' :
5257 arg_action == ACTION_POWEROFF ? 'P' :
5258 arg_action == ACTION_KEXEC ? 'K' :
5266 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
5268 char date[FORMAT_TIMESTAMP_MAX];
5270 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
5271 format_timestamp(date, sizeof(date), arg_when));
5276 if (!arg_dry && !arg_force)
5277 return start_with_fallback(bus);
5280 if (sd_booted() > 0)
5281 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
5283 r = utmp_put_shutdown();
5285 log_warning("Failed to write utmp record: %s", strerror(-r));
5292 halt_now(arg_action);
5293 /* We should never reach this. */
5297 static int runlevel_main(void) {
5298 int r, runlevel, previous;
5300 r = utmp_get_runlevel(&runlevel, &previous);
5307 previous <= 0 ? 'N' : previous,
5308 runlevel <= 0 ? 'N' : runlevel);
5313 int main(int argc, char*argv[]) {
5314 int r, retval = EXIT_FAILURE;
5315 DBusConnection *bus = NULL;
5318 dbus_error_init(&error);
5320 setlocale(LC_ALL, "");
5321 log_parse_environment();
5324 r = parse_argv(argc, argv);
5328 retval = EXIT_SUCCESS;
5332 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
5333 * let's shortcut this */
5334 if (arg_action == ACTION_RUNLEVEL) {
5335 r = runlevel_main();
5336 retval = r < 0 ? EXIT_FAILURE : r;
5340 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
5341 log_info("Running in chroot, ignoring request.");
5347 if (arg_transport == TRANSPORT_NORMAL)
5348 bus_connect(arg_scope == UNIT_FILE_SYSTEM ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &bus, &private_bus, &error);
5349 else if (arg_transport == TRANSPORT_POLKIT) {
5350 bus_connect_system_polkit(&bus, &error);
5351 private_bus = false;
5352 } else if (arg_transport == TRANSPORT_SSH) {
5353 bus_connect_system_ssh(NULL, arg_host, &bus, &error);
5354 private_bus = false;
5356 assert_not_reached("Uh, invalid transport...");
5359 switch (arg_action) {
5361 case ACTION_SYSTEMCTL:
5362 r = systemctl_main(bus, argc, argv, &error);
5366 case ACTION_POWEROFF:
5372 case ACTION_RUNLEVEL2:
5373 case ACTION_RUNLEVEL3:
5374 case ACTION_RUNLEVEL4:
5375 case ACTION_RUNLEVEL5:
5377 case ACTION_EMERGENCY:
5378 case ACTION_DEFAULT:
5379 r = start_with_fallback(bus);
5384 r = reload_with_fallback(bus);
5387 case ACTION_CANCEL_SHUTDOWN: {
5391 m = strv_join(arg_wall, " ");
5393 retval = EXIT_FAILURE;
5397 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
5399 log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r));
5404 case ACTION_INVALID:
5405 case ACTION_RUNLEVEL:
5407 assert_not_reached("Unknown action");
5410 retval = r < 0 ? EXIT_FAILURE : r;
5414 dbus_connection_flush(bus);
5415 dbus_connection_close(bus);
5416 dbus_connection_unref(bus);
5419 dbus_error_free(&error);
5423 strv_free(arg_property);
5426 ask_password_agent_close();
5427 polkit_agent_close();