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, 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 (streq(state, "active") || streq(state, "reloading"))
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) {
1507 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1508 log_error("Failed to parse reply.");
1512 dbus_message_iter_get_basic(&sub, &service_trigger);
1514 r = check_one_unit(bus, service_trigger, true);
1518 if (print_warning_label) {
1519 log_warning("Warning: Stopping %s, but it can still be activated by:", unit_name);
1520 print_warning_label = false;
1522 log_warning(" %s", service_trigger);
1525 dbus_message_iter_next(&sub);
1529 static int start_unit_one(
1530 DBusConnection *bus,
1537 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1540 _cleanup_free_ char *n, *p = NULL;
1547 n = unit_name_mangle(name);
1551 r = bus_method_call_with_reply(
1553 "org.freedesktop.systemd1",
1554 "/org/freedesktop/systemd1",
1555 "org.freedesktop.systemd1.Manager",
1559 DBUS_TYPE_STRING, &n,
1560 DBUS_TYPE_STRING, &mode,
1563 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
1564 /* There's always a fallback possible for
1565 * legacy actions. */
1568 log_error("Failed to issue method call: %s", bus_error_message(error));
1573 if (!dbus_message_get_args(reply, error,
1574 DBUS_TYPE_OBJECT_PATH, &path,
1575 DBUS_TYPE_INVALID)) {
1576 log_error("Failed to parse reply: %s", bus_error_message(error));
1580 if (need_daemon_reload(bus, n))
1581 log_warning("Warning: Unit file of %s changed on disk, 'systemctl %s daemon-reload' recommended.",
1582 n, arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
1591 log_error("Failed to add path to set.");
1601 static enum action verb_to_action(const char *verb) {
1602 if (streq(verb, "halt"))
1604 else if (streq(verb, "poweroff"))
1605 return ACTION_POWEROFF;
1606 else if (streq(verb, "reboot"))
1607 return ACTION_REBOOT;
1608 else if (streq(verb, "kexec"))
1609 return ACTION_KEXEC;
1610 else if (streq(verb, "rescue"))
1611 return ACTION_RESCUE;
1612 else if (streq(verb, "emergency"))
1613 return ACTION_EMERGENCY;
1614 else if (streq(verb, "default"))
1615 return ACTION_DEFAULT;
1616 else if (streq(verb, "exit"))
1618 else if (streq(verb, "suspend"))
1619 return ACTION_SUSPEND;
1620 else if (streq(verb, "hibernate"))
1621 return ACTION_HIBERNATE;
1622 else if (streq(verb, "hybrid-sleep"))
1623 return ACTION_HYBRID_SLEEP;
1625 return ACTION_INVALID;
1628 static int start_unit(DBusConnection *bus, char **args) {
1630 static const char * const table[_ACTION_MAX] = {
1631 [ACTION_HALT] = SPECIAL_HALT_TARGET,
1632 [ACTION_POWEROFF] = SPECIAL_POWEROFF_TARGET,
1633 [ACTION_REBOOT] = SPECIAL_REBOOT_TARGET,
1634 [ACTION_KEXEC] = SPECIAL_KEXEC_TARGET,
1635 [ACTION_RUNLEVEL2] = SPECIAL_RUNLEVEL2_TARGET,
1636 [ACTION_RUNLEVEL3] = SPECIAL_RUNLEVEL3_TARGET,
1637 [ACTION_RUNLEVEL4] = SPECIAL_RUNLEVEL4_TARGET,
1638 [ACTION_RUNLEVEL5] = SPECIAL_RUNLEVEL5_TARGET,
1639 [ACTION_RESCUE] = SPECIAL_RESCUE_TARGET,
1640 [ACTION_EMERGENCY] = SPECIAL_EMERGENCY_TARGET,
1641 [ACTION_DEFAULT] = SPECIAL_DEFAULT_TARGET,
1642 [ACTION_EXIT] = SPECIAL_EXIT_TARGET,
1643 [ACTION_SUSPEND] = SPECIAL_SUSPEND_TARGET,
1644 [ACTION_HIBERNATE] = SPECIAL_HIBERNATE_TARGET,
1645 [ACTION_HYBRID_SLEEP] = SPECIAL_HYBRID_SLEEP_TARGET
1649 const char *method, *mode, *one_name;
1654 dbus_error_init(&error);
1658 ask_password_agent_open_if_enabled();
1660 if (arg_action == ACTION_SYSTEMCTL) {
1662 streq(args[0], "stop") ||
1663 streq(args[0], "condstop") ? "StopUnit" :
1664 streq(args[0], "reload") ? "ReloadUnit" :
1665 streq(args[0], "restart") ? "RestartUnit" :
1667 streq(args[0], "try-restart") ||
1668 streq(args[0], "condrestart") ? "TryRestartUnit" :
1670 streq(args[0], "reload-or-restart") ? "ReloadOrRestartUnit" :
1672 streq(args[0], "reload-or-try-restart") ||
1673 streq(args[0], "condreload") ||
1675 streq(args[0], "force-reload") ? "ReloadOrTryRestartUnit" :
1679 (streq(args[0], "isolate") ||
1680 streq(args[0], "rescue") ||
1681 streq(args[0], "emergency")) ? "isolate" : arg_job_mode;
1683 one_name = table[verb_to_action(args[0])];
1686 assert(arg_action < ELEMENTSOF(table));
1687 assert(table[arg_action]);
1689 method = "StartUnit";
1691 mode = (arg_action == ACTION_EMERGENCY ||
1692 arg_action == ACTION_RESCUE ||
1693 arg_action == ACTION_RUNLEVEL2 ||
1694 arg_action == ACTION_RUNLEVEL3 ||
1695 arg_action == ACTION_RUNLEVEL4 ||
1696 arg_action == ACTION_RUNLEVEL5) ? "isolate" : "replace";
1698 one_name = table[arg_action];
1701 if (!arg_no_block) {
1702 ret = enable_wait_for_jobs(bus);
1704 log_error("Could not watch jobs: %s", strerror(-ret));
1708 s = set_new(string_hash_func, string_compare_func);
1716 ret = start_unit_one(bus, method, one_name, mode, &error, s);
1718 ret = translate_bus_error_to_exit_status(ret, &error);
1720 STRV_FOREACH(name, args+1) {
1721 r = start_unit_one(bus, method, *name, mode, &error, s);
1723 ret = translate_bus_error_to_exit_status(r, &error);
1724 dbus_error_free(&error);
1729 if (!arg_no_block) {
1730 r = wait_for_jobs(bus, s);
1736 /* When stopping units, warn if they can still be triggered by
1737 * another active unit (socket, path, timer) */
1738 if (!arg_quiet && streq(method, "StopUnit")) {
1740 check_triggering_units(bus, one_name);
1742 STRV_FOREACH(name, args+1)
1743 check_triggering_units(bus, *name);
1749 dbus_error_free(&error);
1754 /* Ask systemd-logind, which might grant access to unprivileged users
1755 * through PolicyKit */
1756 static int reboot_with_logind(DBusConnection *bus, enum action a) {
1759 dbus_bool_t interactive = true;
1761 polkit_agent_open_if_enabled();
1769 case ACTION_POWEROFF:
1770 method = "PowerOff";
1773 case ACTION_SUSPEND:
1777 case ACTION_HIBERNATE:
1778 method = "Hibernate";
1781 case ACTION_HYBRID_SLEEP:
1782 method = "HybridSleep";
1789 return bus_method_call_with_reply (
1791 "org.freedesktop.login1",
1792 "/org/freedesktop/login1",
1793 "org.freedesktop.login1.Manager",
1797 DBUS_TYPE_BOOLEAN, &interactive,
1804 static int start_special(DBusConnection *bus, char **args) {
1810 a = verb_to_action(args[0]);
1812 if (arg_force >= 2 && geteuid() != 0) {
1813 log_error("Must be root.");
1817 if (arg_force >= 2 &&
1818 (a == ACTION_HALT ||
1819 a == ACTION_POWEROFF ||
1820 a == ACTION_REBOOT))
1823 if (arg_force >= 1 &&
1824 (a == ACTION_HALT ||
1825 a == ACTION_POWEROFF ||
1826 a == ACTION_REBOOT ||
1827 a == ACTION_KEXEC ||
1829 return daemon_reload(bus, args);
1831 /* first try logind, to allow authentication with polkit */
1832 if (geteuid() != 0 &&
1833 (a == ACTION_POWEROFF ||
1834 a == ACTION_REBOOT ||
1835 a == ACTION_SUSPEND ||
1836 a == ACTION_HIBERNATE ||
1837 a == ACTION_HYBRID_SLEEP)) {
1838 r = reboot_with_logind(bus, a);
1843 r = start_unit(bus, args);
1850 static int check_unit(DBusConnection *bus, char **args) {
1852 int r = 3; /* According to LSB: "program is not running" */
1857 STRV_FOREACH(name, args+1) {
1858 int state = check_one_unit(bus, *name, arg_quiet);
1868 static int kill_unit(DBusConnection *bus, char **args) {
1875 arg_kill_who = "all";
1877 STRV_FOREACH(name, args+1) {
1878 n = unit_name_mangle(*name);
1879 r = bus_method_call_with_reply (
1881 "org.freedesktop.systemd1",
1882 "/org/freedesktop/systemd1",
1883 "org.freedesktop.systemd1.Manager",
1887 DBUS_TYPE_STRING, n ? &n : name,
1888 DBUS_TYPE_STRING, &arg_kill_who,
1889 DBUS_TYPE_INT32, &arg_signal,
1898 typedef struct ExecStatusInfo {
1906 usec_t start_timestamp;
1907 usec_t exit_timestamp;
1912 LIST_FIELDS(struct ExecStatusInfo, exec);
1915 static void exec_status_info_free(ExecStatusInfo *i) {
1924 static int exec_status_info_deserialize(DBusMessageIter *sub, ExecStatusInfo *i) {
1925 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
1926 DBusMessageIter sub2, sub3;
1930 int32_t code, status;
1936 if (dbus_message_iter_get_arg_type(sub) != DBUS_TYPE_STRUCT)
1939 dbus_message_iter_recurse(sub, &sub2);
1941 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0)
1944 if (!(i->path = strdup(path)))
1947 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_ARRAY ||
1948 dbus_message_iter_get_element_type(&sub2) != DBUS_TYPE_STRING)
1952 dbus_message_iter_recurse(&sub2, &sub3);
1953 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
1954 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
1955 dbus_message_iter_next(&sub3);
1960 if (!(i->argv = new0(char*, n+1)))
1964 dbus_message_iter_recurse(&sub2, &sub3);
1965 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
1968 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
1969 dbus_message_iter_get_basic(&sub3, &s);
1970 dbus_message_iter_next(&sub3);
1972 if (!(i->argv[n++] = strdup(s)))
1976 if (!dbus_message_iter_next(&sub2) ||
1977 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, true) < 0 ||
1978 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp, true) < 0 ||
1979 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp_monotonic, true) < 0 ||
1980 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp, true) < 0 ||
1981 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp_monotonic, true) < 0 ||
1982 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, true) < 0 ||
1983 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &code, true) < 0 ||
1984 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &status, false) < 0)
1988 i->start_timestamp = (usec_t) start_timestamp;
1989 i->exit_timestamp = (usec_t) exit_timestamp;
1990 i->pid = (pid_t) pid;
1997 typedef struct UnitStatusInfo {
1999 const char *load_state;
2000 const char *active_state;
2001 const char *sub_state;
2002 const char *unit_file_state;
2004 const char *description;
2005 const char *following;
2007 char **documentation;
2009 const char *fragment_path;
2010 const char *source_path;
2011 const char *default_control_group;
2013 const char *load_error;
2016 usec_t inactive_exit_timestamp;
2017 usec_t inactive_exit_timestamp_monotonic;
2018 usec_t active_enter_timestamp;
2019 usec_t active_exit_timestamp;
2020 usec_t inactive_enter_timestamp;
2022 bool need_daemon_reload;
2027 const char *status_text;
2030 usec_t start_timestamp;
2031 usec_t exit_timestamp;
2033 int exit_code, exit_status;
2035 usec_t condition_timestamp;
2036 bool condition_result;
2039 unsigned n_accepted;
2040 unsigned n_connections;
2044 const char *sysfs_path;
2046 /* Mount, Automount */
2052 LIST_HEAD(ExecStatusInfo, exec);
2055 static void print_status_info(UnitStatusInfo *i) {
2057 const char *on, *off, *ss;
2059 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
2060 char since2[FORMAT_TIMESTAMP_MAX], *s2;
2065 /* This shows pretty information about a unit. See
2066 * print_property() for a low-level property printer */
2068 printf("%s", strna(i->id));
2070 if (i->description && !streq_ptr(i->id, i->description))
2071 printf(" - %s", i->description);
2076 printf("\t Follow: unit currently follows state of %s\n", i->following);
2078 if (streq_ptr(i->load_state, "error")) {
2079 on = ansi_highlight_red(true);
2080 off = ansi_highlight_red(false);
2084 path = i->source_path ? i->source_path : i->fragment_path;
2087 printf("\t Loaded: %s%s%s (Reason: %s)\n", on, strna(i->load_state), off, i->load_error);
2088 else if (path && i->unit_file_state)
2089 printf("\t Loaded: %s%s%s (%s; %s)\n", on, strna(i->load_state), off, path, i->unit_file_state);
2091 printf("\t Loaded: %s%s%s (%s)\n", on, strna(i->load_state), off, path);
2093 printf("\t Loaded: %s%s%s\n", on, strna(i->load_state), off);
2095 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
2097 if (streq_ptr(i->active_state, "failed")) {
2098 on = ansi_highlight_red(true);
2099 off = ansi_highlight_red(false);
2100 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
2101 on = ansi_highlight_green(true);
2102 off = ansi_highlight_green(false);
2107 printf("\t Active: %s%s (%s)%s",
2109 strna(i->active_state),
2113 printf("\t Active: %s%s%s",
2115 strna(i->active_state),
2118 if (!isempty(i->result) && !streq(i->result, "success"))
2119 printf(" (Result: %s)", i->result);
2121 timestamp = (streq_ptr(i->active_state, "active") ||
2122 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
2123 (streq_ptr(i->active_state, "inactive") ||
2124 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
2125 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
2126 i->active_exit_timestamp;
2128 s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
2129 s2 = format_timestamp(since2, sizeof(since2), timestamp);
2132 printf(" since %s; %s\n", s2, s1);
2134 printf(" since %s\n", s2);
2138 if (!i->condition_result && i->condition_timestamp > 0) {
2139 s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
2140 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
2143 printf("\t start condition failed at %s; %s\n", s2, s1);
2145 printf("\t start condition failed at %s\n", s2);
2149 printf("\t Device: %s\n", i->sysfs_path);
2151 printf("\t Where: %s\n", i->where);
2153 printf("\t What: %s\n", i->what);
2155 if (!strv_isempty(i->documentation)) {
2159 STRV_FOREACH(t, i->documentation) {
2161 printf("\t Docs: %s\n", *t);
2164 printf("\t %s\n", *t);
2169 printf("\tAccepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
2171 LIST_FOREACH(exec, p, i->exec) {
2175 /* Only show exited processes here */
2179 t = strv_join(p->argv, " ");
2180 printf("\t Process: %u %s=%s ", p->pid, p->name, strna(t));
2183 good = is_clean_exit_lsb(p->code, p->status, NULL);
2185 on = ansi_highlight_red(true);
2186 off = ansi_highlight_red(false);
2190 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
2192 if (p->code == CLD_EXITED) {
2195 printf("status=%i", p->status);
2197 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
2202 printf("signal=%s", signal_to_string(p->status));
2204 printf(")%s\n", off);
2206 if (i->main_pid == p->pid &&
2207 i->start_timestamp == p->start_timestamp &&
2208 i->exit_timestamp == p->start_timestamp)
2209 /* Let's not show this twice */
2212 if (p->pid == i->control_pid)
2216 if (i->main_pid > 0 || i->control_pid > 0) {
2219 if (i->main_pid > 0) {
2220 printf("Main PID: %u", (unsigned) i->main_pid);
2224 get_process_comm(i->main_pid, &t);
2229 } else if (i->exit_code > 0) {
2230 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
2232 if (i->exit_code == CLD_EXITED) {
2235 printf("status=%i", i->exit_status);
2237 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
2242 printf("signal=%s", signal_to_string(i->exit_status));
2247 if (i->main_pid > 0 && i->control_pid > 0)
2250 if (i->control_pid > 0) {
2253 printf(" Control: %u", (unsigned) i->control_pid);
2255 get_process_comm(i->control_pid, &t);
2266 printf("\t Status: \"%s\"\n", i->status_text);
2268 if (i->default_control_group &&
2269 (i->main_pid > 0 || i->control_pid > 0 || cg_is_empty_by_spec(i->default_control_group, false) == 0)) {
2272 printf("\t CGroup: %s\n", i->default_control_group);
2274 if (arg_transport != TRANSPORT_SSH) {
2284 if (i->main_pid > 0)
2285 extra[k++] = i->main_pid;
2287 if (i->control_pid > 0)
2288 extra[k++] = i->control_pid;
2290 show_cgroup_and_extra_by_spec(i->default_control_group, "\t\t ", c, false, arg_all, extra, k);
2294 if (i->id && arg_transport != TRANSPORT_SSH) {
2296 arg_all * OUTPUT_SHOW_ALL |
2297 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
2298 on_tty() * OUTPUT_COLOR |
2299 !arg_quiet * OUTPUT_WARN_CUTOFF;
2302 show_journal_by_unit(stdout,
2306 i->inactive_exit_timestamp_monotonic,
2311 if (i->need_daemon_reload)
2312 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %s daemon-reload' recommended.\n",
2313 ansi_highlight_red(true),
2314 ansi_highlight_red(false),
2315 arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
2318 static void show_unit_help(UnitStatusInfo *i) {
2323 if (!i->documentation) {
2324 log_info("Documentation for %s not known.", i->id);
2328 STRV_FOREACH(p, i->documentation) {
2330 if (startswith(*p, "man:")) {
2333 char *page = NULL, *section = NULL;
2334 const char *args[4] = { "man", NULL, NULL, NULL };
2339 if ((*p)[k-1] == ')')
2340 e = strrchr(*p, '(');
2343 page = strndup((*p) + 4, e - *p - 4);
2349 section = strndup(e + 1, *p + k - e - 2);
2363 log_error("Failed to fork: %m");
2371 execvp(args[0], (char**) args);
2372 log_error("Failed to execute man: %m");
2373 _exit(EXIT_FAILURE);
2379 wait_for_terminate(pid, NULL);
2381 log_info("Can't show: %s", *p);
2385 static int status_property(const char *name, DBusMessageIter *iter, UnitStatusInfo *i) {
2391 switch (dbus_message_iter_get_arg_type(iter)) {
2393 case DBUS_TYPE_STRING: {
2396 dbus_message_iter_get_basic(iter, &s);
2399 if (streq(name, "Id"))
2401 else if (streq(name, "LoadState"))
2403 else if (streq(name, "ActiveState"))
2404 i->active_state = s;
2405 else if (streq(name, "SubState"))
2407 else if (streq(name, "Description"))
2409 else if (streq(name, "FragmentPath"))
2410 i->fragment_path = s;
2411 else if (streq(name, "SourcePath"))
2413 else if (streq(name, "DefaultControlGroup"))
2414 i->default_control_group = s;
2415 else if (streq(name, "StatusText"))
2417 else if (streq(name, "SysFSPath"))
2419 else if (streq(name, "Where"))
2421 else if (streq(name, "What"))
2423 else if (streq(name, "Following"))
2425 else if (streq(name, "UnitFileState"))
2426 i->unit_file_state = s;
2427 else if (streq(name, "Result"))
2434 case DBUS_TYPE_BOOLEAN: {
2437 dbus_message_iter_get_basic(iter, &b);
2439 if (streq(name, "Accept"))
2441 else if (streq(name, "NeedDaemonReload"))
2442 i->need_daemon_reload = b;
2443 else if (streq(name, "ConditionResult"))
2444 i->condition_result = b;
2449 case DBUS_TYPE_UINT32: {
2452 dbus_message_iter_get_basic(iter, &u);
2454 if (streq(name, "MainPID")) {
2456 i->main_pid = (pid_t) u;
2459 } else if (streq(name, "ControlPID"))
2460 i->control_pid = (pid_t) u;
2461 else if (streq(name, "ExecMainPID")) {
2463 i->main_pid = (pid_t) u;
2464 } else if (streq(name, "NAccepted"))
2466 else if (streq(name, "NConnections"))
2467 i->n_connections = u;
2472 case DBUS_TYPE_INT32: {
2475 dbus_message_iter_get_basic(iter, &j);
2477 if (streq(name, "ExecMainCode"))
2478 i->exit_code = (int) j;
2479 else if (streq(name, "ExecMainStatus"))
2480 i->exit_status = (int) j;
2485 case DBUS_TYPE_UINT64: {
2488 dbus_message_iter_get_basic(iter, &u);
2490 if (streq(name, "ExecMainStartTimestamp"))
2491 i->start_timestamp = (usec_t) u;
2492 else if (streq(name, "ExecMainExitTimestamp"))
2493 i->exit_timestamp = (usec_t) u;
2494 else if (streq(name, "ActiveEnterTimestamp"))
2495 i->active_enter_timestamp = (usec_t) u;
2496 else if (streq(name, "InactiveEnterTimestamp"))
2497 i->inactive_enter_timestamp = (usec_t) u;
2498 else if (streq(name, "InactiveExitTimestamp"))
2499 i->inactive_exit_timestamp = (usec_t) u;
2500 else if (streq(name, "InactiveExitTimestampMonotonic"))
2501 i->inactive_exit_timestamp_monotonic = (usec_t) u;
2502 else if (streq(name, "ActiveExitTimestamp"))
2503 i->active_exit_timestamp = (usec_t) u;
2504 else if (streq(name, "ConditionTimestamp"))
2505 i->condition_timestamp = (usec_t) u;
2510 case DBUS_TYPE_ARRAY: {
2512 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
2513 startswith(name, "Exec")) {
2514 DBusMessageIter sub;
2516 dbus_message_iter_recurse(iter, &sub);
2517 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2518 ExecStatusInfo *info;
2521 if (!(info = new0(ExecStatusInfo, 1)))
2524 if (!(info->name = strdup(name))) {
2529 if ((r = exec_status_info_deserialize(&sub, info)) < 0) {
2534 LIST_PREPEND(ExecStatusInfo, exec, i->exec, info);
2536 dbus_message_iter_next(&sub);
2538 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
2539 streq(name, "Documentation")) {
2541 DBusMessageIter sub;
2543 dbus_message_iter_recurse(iter, &sub);
2544 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING) {
2548 dbus_message_iter_get_basic(&sub, &s);
2550 l = strv_append(i->documentation, s);
2554 strv_free(i->documentation);
2555 i->documentation = l;
2557 dbus_message_iter_next(&sub);
2564 case DBUS_TYPE_STRUCT: {
2566 if (streq(name, "LoadError")) {
2567 DBusMessageIter sub;
2568 const char *n, *message;
2571 dbus_message_iter_recurse(iter, &sub);
2573 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &n, true);
2577 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &message, false);
2581 if (!isempty(message))
2582 i->load_error = message;
2592 static int print_property(const char *name, DBusMessageIter *iter) {
2596 /* This is a low-level property printer, see
2597 * print_status_info() for the nicer output */
2599 if (arg_property && !strv_find(arg_property, name))
2602 switch (dbus_message_iter_get_arg_type(iter)) {
2604 case DBUS_TYPE_STRUCT: {
2605 DBusMessageIter sub;
2606 dbus_message_iter_recurse(iter, &sub);
2608 if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32 && streq(name, "Job")) {
2611 dbus_message_iter_get_basic(&sub, &u);
2614 printf("%s=%u\n", name, (unsigned) u);
2616 printf("%s=\n", name);
2619 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "Unit")) {
2622 dbus_message_iter_get_basic(&sub, &s);
2624 if (arg_all || s[0])
2625 printf("%s=%s\n", name, s);
2628 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "LoadError")) {
2629 const char *a = NULL, *b = NULL;
2631 if (bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &a, true) >= 0)
2632 bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &b, false);
2634 if (arg_all || !isempty(a) || !isempty(b))
2635 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
2643 case DBUS_TYPE_ARRAY:
2645 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "EnvironmentFiles")) {
2646 DBusMessageIter sub, sub2;
2648 dbus_message_iter_recurse(iter, &sub);
2649 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2653 dbus_message_iter_recurse(&sub, &sub2);
2655 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
2656 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) >= 0)
2657 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
2659 dbus_message_iter_next(&sub);
2664 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Paths")) {
2665 DBusMessageIter sub, sub2;
2667 dbus_message_iter_recurse(iter, &sub);
2668 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2669 const char *type, *path;
2671 dbus_message_iter_recurse(&sub, &sub2);
2673 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
2674 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
2675 printf("%s=%s\n", type, path);
2677 dbus_message_iter_next(&sub);
2682 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Timers")) {
2683 DBusMessageIter sub, sub2;
2685 dbus_message_iter_recurse(iter, &sub);
2686 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2688 uint64_t value, next_elapse;
2690 dbus_message_iter_recurse(&sub, &sub2);
2692 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &base, true) >= 0 &&
2693 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &value, true) >= 0 &&
2694 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &next_elapse, false) >= 0) {
2695 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
2697 printf("%s={ value=%s ; next_elapse=%s }\n",
2699 format_timespan(timespan1, sizeof(timespan1), value),
2700 format_timespan(timespan2, sizeof(timespan2), next_elapse));
2703 dbus_message_iter_next(&sub);
2708 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "ControlGroupAttributes")) {
2709 DBusMessageIter sub, sub2;
2711 dbus_message_iter_recurse(iter, &sub);
2712 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2713 const char *controller, *attr, *value;
2715 dbus_message_iter_recurse(&sub, &sub2);
2717 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &controller, true) >= 0 &&
2718 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &attr, true) >= 0 &&
2719 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &value, false) >= 0) {
2721 printf("ControlGroupAttribute={ controller=%s ; attribute=%s ; value=\"%s\" }\n",
2727 dbus_message_iter_next(&sub);
2732 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && startswith(name, "Exec")) {
2733 DBusMessageIter sub;
2735 dbus_message_iter_recurse(iter, &sub);
2736 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2737 ExecStatusInfo info;
2740 if (exec_status_info_deserialize(&sub, &info) >= 0) {
2741 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
2744 t = strv_join(info.argv, " ");
2746 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
2750 yes_no(info.ignore),
2751 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
2752 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
2753 (unsigned) info. pid,
2754 sigchld_code_to_string(info.code),
2756 info.code == CLD_EXITED ? "" : "/",
2757 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
2763 strv_free(info.argv);
2765 dbus_message_iter_next(&sub);
2774 if (generic_print_property(name, iter, arg_all) > 0)
2778 printf("%s=[unprintable]\n", name);
2783 static int show_one(const char *verb, DBusConnection *bus, const char *path, bool show_properties, bool *new_line) {
2784 DBusMessage *reply = NULL;
2785 const char *interface = "";
2787 DBusMessageIter iter, sub, sub2, sub3;
2788 UnitStatusInfo info;
2796 r = bus_method_call_with_reply (
2798 "org.freedesktop.systemd1",
2800 "org.freedesktop.DBus.Properties",
2804 DBUS_TYPE_STRING, &interface,
2809 if (!dbus_message_iter_init(reply, &iter) ||
2810 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
2811 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
2812 log_error("Failed to parse reply.");
2817 dbus_message_iter_recurse(&iter, &sub);
2824 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
2827 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_DICT_ENTRY) {
2828 log_error("Failed to parse reply.");
2833 dbus_message_iter_recurse(&sub, &sub2);
2835 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0) {
2836 log_error("Failed to parse reply.");
2841 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
2842 log_error("Failed to parse reply.");
2847 dbus_message_iter_recurse(&sub2, &sub3);
2849 if (show_properties)
2850 r = print_property(name, &sub3);
2852 r = status_property(name, &sub3, &info);
2855 log_error("Failed to parse reply.");
2860 dbus_message_iter_next(&sub);
2865 if (!show_properties) {
2866 if (streq(verb, "help"))
2867 show_unit_help(&info);
2869 print_status_info(&info);
2872 strv_free(info.documentation);
2874 if (!streq_ptr(info.active_state, "active") &&
2875 !streq_ptr(info.active_state, "reloading") &&
2876 streq(verb, "status"))
2877 /* According to LSB: "program not running" */
2880 while ((p = info.exec)) {
2881 LIST_REMOVE(ExecStatusInfo, exec, info.exec, p);
2882 exec_status_info_free(p);
2887 dbus_message_unref(reply);
2892 static int show_one_by_pid(const char *verb, DBusConnection *bus, uint32_t pid, bool *new_line) {
2893 DBusMessage *reply = NULL;
2894 const char *path = NULL;
2898 dbus_error_init(&error);
2900 r = bus_method_call_with_reply (
2902 "org.freedesktop.systemd1",
2903 "/org/freedesktop/systemd1",
2904 "org.freedesktop.systemd1.Manager",
2908 DBUS_TYPE_UINT32, &pid,
2913 if (!dbus_message_get_args(reply, &error,
2914 DBUS_TYPE_OBJECT_PATH, &path,
2915 DBUS_TYPE_INVALID)) {
2916 log_error("Failed to parse reply: %s", bus_error_message(&error));
2921 r = show_one(verb, bus, path, false, new_line);
2925 dbus_message_unref(reply);
2927 dbus_error_free(&error);
2932 static int show(DBusConnection *bus, char **args) {
2934 bool show_properties, new_line = false;
2940 show_properties = streq(args[0], "show");
2942 if (show_properties)
2943 pager_open_if_enabled();
2945 if (show_properties && strv_length(args) <= 1) {
2946 /* If not argument is specified inspect the manager
2949 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line);
2952 STRV_FOREACH(name, args+1) {
2955 if (safe_atou32(*name, &id) < 0) {
2957 /* Interpret as unit name */
2959 n = unit_name_mangle(*name);
2960 p = unit_dbus_path_from_name(n ? n : *name);
2965 r = show_one(args[0], bus, p, show_properties, &new_line);
2971 } else if (show_properties) {
2973 /* Interpret as job id */
2976 if (asprintf(&p, "/org/freedesktop/systemd1/job/%u", id) < 0)
2979 r = show_one(args[0], bus, p, show_properties, &new_line);
2987 /* Interpret as PID */
2989 r = show_one_by_pid(args[0], bus, id, &new_line);
2998 static int dump(DBusConnection *bus, char **args) {
2999 DBusMessage *reply = NULL;
3004 dbus_error_init(&error);
3006 pager_open_if_enabled();
3008 r = bus_method_call_with_reply (
3010 "org.freedesktop.systemd1",
3011 "/org/freedesktop/systemd1",
3012 "org.freedesktop.systemd1.Manager",
3020 if (!dbus_message_get_args(reply, &error,
3021 DBUS_TYPE_STRING, &text,
3022 DBUS_TYPE_INVALID)) {
3023 log_error("Failed to parse reply: %s", bus_error_message(&error));
3028 fputs(text, stdout);
3032 dbus_message_unref(reply);
3034 dbus_error_free(&error);
3039 static int snapshot(DBusConnection *bus, char **args) {
3040 DBusMessage *reply = NULL;
3043 dbus_bool_t cleanup = FALSE;
3044 DBusMessageIter iter, sub;
3046 *name = "", *path, *id,
3047 *interface = "org.freedesktop.systemd1.Unit",
3051 dbus_error_init(&error);
3053 if (strv_length(args) > 1)
3056 n = unit_name_mangle(name);
3057 r = bus_method_call_with_reply (
3059 "org.freedesktop.systemd1",
3060 "/org/freedesktop/systemd1",
3061 "org.freedesktop.systemd1.Manager",
3065 DBUS_TYPE_STRING, n ? (const char**) &n : &name,
3066 DBUS_TYPE_BOOLEAN, &cleanup,
3072 if (!dbus_message_get_args(reply, &error,
3073 DBUS_TYPE_OBJECT_PATH, &path,
3074 DBUS_TYPE_INVALID)) {
3075 log_error("Failed to parse reply: %s", bus_error_message(&error));
3080 dbus_message_unref(reply);
3081 r = bus_method_call_with_reply (
3083 "org.freedesktop.systemd1",
3085 "org.freedesktop.DBus.Properties",
3089 DBUS_TYPE_STRING, &interface,
3090 DBUS_TYPE_STRING, &property,
3095 if (!dbus_message_iter_init(reply, &iter) ||
3096 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3097 log_error("Failed to parse reply.");
3102 dbus_message_iter_recurse(&iter, &sub);
3104 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
3105 log_error("Failed to parse reply.");
3110 dbus_message_iter_get_basic(&sub, &id);
3117 dbus_message_unref(reply);
3119 dbus_error_free(&error);
3124 static int delete_snapshot(DBusConnection *bus, char **args) {
3125 DBusMessage *reply = NULL;
3132 dbus_error_init(&error);
3134 STRV_FOREACH(name, args+1) {
3135 const char *path = NULL;
3138 n = unit_name_mangle(*name);
3139 r = bus_method_call_with_reply (
3141 "org.freedesktop.systemd1",
3142 "/org/freedesktop/systemd1",
3143 "org.freedesktop.systemd1.Manager",
3147 DBUS_TYPE_STRING, n ? &n : name,
3153 if (!dbus_message_get_args(reply, &error,
3154 DBUS_TYPE_OBJECT_PATH, &path,
3155 DBUS_TYPE_INVALID)) {
3156 log_error("Failed to parse reply: %s", bus_error_message(&error));
3158 dbus_message_unref(reply);
3159 dbus_error_free(&error);
3162 dbus_message_unref(reply);
3164 r = bus_method_call_with_reply (
3166 "org.freedesktop.systemd1",
3168 "org.freedesktop.systemd1.Snapshot",
3181 static int daemon_reload(DBusConnection *bus, char **args) {
3186 if (arg_action == ACTION_RELOAD)
3188 else if (arg_action == ACTION_REEXEC)
3189 method = "Reexecute";
3191 assert(arg_action == ACTION_SYSTEMCTL);
3194 streq(args[0], "clear-jobs") ||
3195 streq(args[0], "cancel") ? "ClearJobs" :
3196 streq(args[0], "daemon-reexec") ? "Reexecute" :
3197 streq(args[0], "reset-failed") ? "ResetFailed" :
3198 streq(args[0], "halt") ? "Halt" :
3199 streq(args[0], "poweroff") ? "PowerOff" :
3200 streq(args[0], "reboot") ? "Reboot" :
3201 streq(args[0], "kexec") ? "KExec" :
3202 streq(args[0], "exit") ? "Exit" :
3203 /* "daemon-reload" */ "Reload";
3206 r = bus_method_call_with_reply (
3208 "org.freedesktop.systemd1",
3209 "/org/freedesktop/systemd1",
3210 "org.freedesktop.systemd1.Manager",
3216 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
3217 /* There's always a fallback possible for
3218 * legacy actions. */
3220 else if (r == -ETIMEDOUT && streq(method, "Reexecute"))
3221 /* On reexecution, we expect a disconnect, not
3225 log_error("Failed to issue method call: %s", bus_error_message(&error));
3226 dbus_error_free(&error);
3231 static int reset_failed(DBusConnection *bus, char **args) {
3235 if (strv_length(args) <= 1)
3236 return daemon_reload(bus, args);
3238 STRV_FOREACH(name, args+1) {
3239 n = unit_name_mangle(*name);
3240 r = bus_method_call_with_reply (
3242 "org.freedesktop.systemd1",
3243 "/org/freedesktop/systemd1",
3244 "org.freedesktop.systemd1.Manager",
3248 DBUS_TYPE_STRING, n ? &n : name,
3259 static int show_enviroment(DBusConnection *bus, char **args) {
3260 DBusMessage *reply = NULL;
3261 DBusMessageIter iter, sub, sub2;
3264 *interface = "org.freedesktop.systemd1.Manager",
3265 *property = "Environment";
3267 pager_open_if_enabled();
3269 r = bus_method_call_with_reply (
3271 "org.freedesktop.systemd1",
3272 "/org/freedesktop/systemd1",
3273 "org.freedesktop.DBus.Properties",
3277 DBUS_TYPE_STRING, &interface,
3278 DBUS_TYPE_STRING, &property,
3283 if (!dbus_message_iter_init(reply, &iter) ||
3284 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3285 log_error("Failed to parse reply.");
3290 dbus_message_iter_recurse(&iter, &sub);
3292 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_ARRAY ||
3293 dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_STRING) {
3294 log_error("Failed to parse reply.");
3299 dbus_message_iter_recurse(&sub, &sub2);
3301 while (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_INVALID) {
3304 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
3305 log_error("Failed to parse reply.");
3310 dbus_message_iter_get_basic(&sub2, &text);
3311 printf("%s\n", text);
3313 dbus_message_iter_next(&sub2);
3320 dbus_message_unref(reply);
3325 static int switch_root(DBusConnection *bus, char **args) {
3328 _cleanup_free_ char *init = NULL;
3330 l = strv_length(args);
3331 if (l < 2 || l > 3) {
3332 log_error("Wrong number of arguments.");
3339 init = strdup(args[2]);
3341 parse_env_file("/proc/cmdline", WHITESPACE,
3353 log_debug("switching root - root: %s; init: %s", root, init);
3355 return bus_method_call_with_reply (
3357 "org.freedesktop.systemd1",
3358 "/org/freedesktop/systemd1",
3359 "org.freedesktop.systemd1.Manager",
3363 DBUS_TYPE_STRING, &root,
3364 DBUS_TYPE_STRING, &init,
3368 static int set_environment(DBusConnection *bus, char **args) {
3369 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
3372 DBusMessageIter iter;
3377 dbus_error_init(&error);
3379 method = streq(args[0], "set-environment")
3381 : "UnsetEnvironment";
3383 m = dbus_message_new_method_call(
3384 "org.freedesktop.systemd1",
3385 "/org/freedesktop/systemd1",
3386 "org.freedesktop.systemd1.Manager",
3391 dbus_message_iter_init_append(m, &iter);
3393 r = bus_append_strv_iter(&iter, args + 1);
3397 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3399 log_error("Failed to issue method call: %s", bus_error_message(&error));
3407 dbus_error_free(&error);
3411 static int enable_sysv_units(char **args) {
3414 #if defined (HAVE_SYSV_COMPAT) && (defined(TARGET_FEDORA) || defined(TARGET_MANDRIVA) || defined(TARGET_SUSE) || defined(TARGET_ALTLINUX) || defined(TARGET_MAGEIA))
3415 const char *verb = args[0];
3416 unsigned f = 1, t = 1;
3419 if (arg_scope != UNIT_FILE_SYSTEM)
3422 if (!streq(verb, "enable") &&
3423 !streq(verb, "disable") &&
3424 !streq(verb, "is-enabled"))
3427 /* Processes all SysV units, and reshuffles the array so that
3428 * afterwards only the native units remain */
3431 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, NULL, NULL, NULL);
3436 for (f = 1; args[f]; f++) {
3439 bool found_native = false, found_sysv;
3441 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
3442 char **k, *l, *q = NULL;
3449 if (!endswith(name, ".service"))
3452 if (path_is_absolute(name))
3455 STRV_FOREACH(k, paths.unit_path) {
3458 if (!isempty(arg_root))
3459 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
3461 asprintf(&p, "%s/%s", *k, name);
3468 found_native = access(p, F_OK) >= 0;
3479 if (!isempty(arg_root))
3480 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
3482 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
3488 p[strlen(p) - sizeof(".service") + 1] = 0;
3489 found_sysv = access(p, F_OK) >= 0;
3496 /* Mark this entry, so that we don't try enabling it as native unit */
3497 args[f] = (char*) "";
3499 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
3501 if (!isempty(arg_root))
3502 argv[c++] = q = strappend("--root=", arg_root);
3504 argv[c++] = path_get_file_name(p);
3506 streq(verb, "enable") ? "on" :
3507 streq(verb, "disable") ? "off" : "--level=5";
3510 l = strv_join((char**)argv, " ");
3518 log_info("Executing %s", l);
3523 log_error("Failed to fork: %m");
3528 } else if (pid == 0) {
3531 execv(argv[0], (char**) argv);
3532 _exit(EXIT_FAILURE);
3538 j = wait_for_terminate(pid, &status);
3540 log_error("Failed to wait for child: %s", strerror(-r));
3545 if (status.si_code == CLD_EXITED) {
3546 if (streq(verb, "is-enabled")) {
3547 if (status.si_status == 0) {
3556 } else if (status.si_status != 0) {
3567 lookup_paths_free(&paths);
3569 /* Drop all SysV units */
3570 for (f = 1, t = 1; args[f]; f++) {
3572 if (isempty(args[f]))
3575 args[t++] = args[f];
3584 static int mangle_names(char **original_names, char ***mangled_names) {
3585 char **i, **l, **name;
3587 l = new(char*, strv_length(original_names) + 1);
3592 STRV_FOREACH(name, original_names) {
3594 /* When enabling units qualified path names are OK,
3595 * too, hence allow them explicitly. */
3600 *i = unit_name_mangle(*name);
3616 static int enable_unit(DBusConnection *bus, char **args) {
3617 const char *verb = args[0];
3618 UnitFileChange *changes = NULL;
3619 unsigned n_changes = 0, i;
3620 int carries_install_info = -1;
3621 DBusMessage *m = NULL, *reply = NULL;
3624 char **mangled_names = NULL;
3626 r = enable_sysv_units(args);
3633 dbus_error_init(&error);
3635 if (!bus || avoid_bus()) {
3636 if (streq(verb, "enable")) {
3637 r = unit_file_enable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3638 carries_install_info = r;
3639 } else if (streq(verb, "disable"))
3640 r = unit_file_disable(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3641 else if (streq(verb, "reenable")) {
3642 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3643 carries_install_info = r;
3644 } else if (streq(verb, "link"))
3645 r = unit_file_link(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3646 else if (streq(verb, "preset")) {
3647 r = unit_file_preset(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3648 carries_install_info = r;
3649 } else if (streq(verb, "mask"))
3650 r = unit_file_mask(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3651 else if (streq(verb, "unmask"))
3652 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3654 assert_not_reached("Unknown verb");
3657 log_error("Operation failed: %s", strerror(-r));
3662 for (i = 0; i < n_changes; i++) {
3663 if (changes[i].type == UNIT_FILE_SYMLINK)
3664 log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
3666 log_info("rm '%s'", changes[i].path);
3673 bool send_force = true, expect_carries_install_info = false;
3675 DBusMessageIter iter, sub, sub2;
3677 if (streq(verb, "enable")) {
3678 method = "EnableUnitFiles";
3679 expect_carries_install_info = true;
3680 } else if (streq(verb, "disable")) {
3681 method = "DisableUnitFiles";
3683 } else if (streq(verb, "reenable")) {
3684 method = "ReenableUnitFiles";
3685 expect_carries_install_info = true;
3686 } else if (streq(verb, "link"))
3687 method = "LinkUnitFiles";
3688 else if (streq(verb, "preset")) {
3689 method = "PresetUnitFiles";
3690 expect_carries_install_info = true;
3691 } else if (streq(verb, "mask"))
3692 method = "MaskUnitFiles";
3693 else if (streq(verb, "unmask")) {
3694 method = "UnmaskUnitFiles";
3697 assert_not_reached("Unknown verb");
3699 m = dbus_message_new_method_call(
3700 "org.freedesktop.systemd1",
3701 "/org/freedesktop/systemd1",
3702 "org.freedesktop.systemd1.Manager",
3709 dbus_message_iter_init_append(m, &iter);
3711 r = mangle_names(args+1, &mangled_names);
3715 r = bus_append_strv_iter(&iter, mangled_names);
3717 log_error("Failed to append unit files.");
3722 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &a)) {
3723 log_error("Failed to append runtime boolean.");
3731 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b)) {
3732 log_error("Failed to append force boolean.");
3738 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3740 log_error("Failed to issue method call: %s", bus_error_message(&error));
3745 if (!dbus_message_iter_init(reply, &iter)) {
3746 log_error("Failed to initialize iterator.");
3750 if (expect_carries_install_info) {
3751 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &b, true);
3753 log_error("Failed to parse reply.");
3757 carries_install_info = b;
3760 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3761 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
3762 log_error("Failed to parse reply.");
3767 dbus_message_iter_recurse(&iter, &sub);
3768 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
3769 const char *type, *path, *source;
3771 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
3772 log_error("Failed to parse reply.");
3777 dbus_message_iter_recurse(&sub, &sub2);
3779 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
3780 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
3781 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &source, false) < 0) {
3782 log_error("Failed to parse reply.");
3788 if (streq(type, "symlink"))
3789 log_info("ln -s '%s' '%s'", source, path);
3791 log_info("rm '%s'", path);
3794 dbus_message_iter_next(&sub);
3797 /* Try to reload if enabeld */
3799 r = daemon_reload(bus, args);
3802 if (carries_install_info == 0)
3804 "The unit files have no [Install] section. They are not meant to be enabled\n"
3805 "using systemctl.\n"
3806 "Possible reasons for having this kind of units are:\n"
3807 "1) A unit may be statically enabled by being symlinked from another unit's\n"
3808 " .wants/ or .requires/ directory.\n"
3809 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
3810 " a requirement dependency on it.\n"
3811 "3) A unit may be started when needed via activation (socket, path, timer,\n"
3812 " D-Bus, udev, scripted systemctl call, ...).\n");
3816 dbus_message_unref(m);
3819 dbus_message_unref(reply);
3821 unit_file_changes_free(changes, n_changes);
3823 dbus_error_free(&error);
3825 strv_free(mangled_names);
3830 static int unit_is_enabled(DBusConnection *bus, char **args) {
3833 DBusMessage *reply = NULL;
3837 dbus_error_init(&error);
3839 r = enable_sysv_units(args);
3845 if (!bus || avoid_bus()) {
3847 STRV_FOREACH(name, args+1) {
3848 UnitFileState state;
3850 state = unit_file_get_state(arg_scope, arg_root, *name);
3856 if (state == UNIT_FILE_ENABLED ||
3857 state == UNIT_FILE_ENABLED_RUNTIME ||
3858 state == UNIT_FILE_STATIC)
3862 puts(unit_file_state_to_string(state));
3866 STRV_FOREACH(name, args+1) {
3869 r = bus_method_call_with_reply (
3871 "org.freedesktop.systemd1",
3872 "/org/freedesktop/systemd1",
3873 "org.freedesktop.systemd1.Manager",
3877 DBUS_TYPE_STRING, name,
3882 if (!dbus_message_get_args(reply, &error,
3883 DBUS_TYPE_STRING, &s,
3884 DBUS_TYPE_INVALID)) {
3885 log_error("Failed to parse reply: %s", bus_error_message(&error));
3890 dbus_message_unref(reply);
3893 if (streq(s, "enabled") ||
3894 streq(s, "enabled-runtime") ||
3903 r = enabled ? 0 : 1;
3907 dbus_message_unref(reply);
3909 dbus_error_free(&error);
3913 static int systemctl_help(void) {
3915 pager_open_if_enabled();
3917 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
3918 "Query or send control commands to the systemd manager.\n\n"
3919 " -h --help Show this help\n"
3920 " --version Show package version\n"
3921 " -t --type=TYPE List only units of a particular type\n"
3922 " -p --property=NAME Show only properties by this name\n"
3923 " -a --all Show all units/properties, including dead/empty ones\n"
3924 " --failed Show only failed units\n"
3925 " --full Don't ellipsize unit names on output\n"
3926 " --fail When queueing a new job, fail if conflicting jobs are\n"
3928 " --ignore-dependencies\n"
3929 " When queueing a new job, ignore all its dependencies\n"
3930 " --kill-who=WHO Who to send signal to\n"
3931 " -s --signal=SIGNAL Which signal to send\n"
3932 " -H --host=[USER@]HOST\n"
3933 " Show information for remote host\n"
3934 " -P --privileged Acquire privileges before execution\n"
3935 " -q --quiet Suppress output\n"
3936 " --no-block Do not wait until operation finished\n"
3937 " --no-wall Don't send wall message before halt/power-off/reboot\n"
3938 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
3940 " --no-legend Do not print a legend (column headers and hints)\n"
3941 " --no-pager Do not pipe output into a pager\n"
3942 " --no-ask-password\n"
3943 " Do not ask for system passwords\n"
3944 " --order When generating graph for dot, show only order\n"
3945 " --require When generating graph for dot, show only requirement\n"
3946 " --system Connect to system manager\n"
3947 " --user Connect to user service manager\n"
3948 " --global Enable/disable unit files globally\n"
3949 " -f --force When enabling unit files, override existing symlinks\n"
3950 " When shutting down, execute action immediately\n"
3951 " --root=PATH Enable unit files in the specified root directory\n"
3952 " --runtime Enable unit files only temporarily until next reboot\n"
3953 " -n --lines=INTEGER Journal entries to show\n"
3954 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
3955 " verbose, export, json, json-pretty, json-sse, cat)\n\n"
3957 " list-units List loaded units\n"
3958 " start [NAME...] Start (activate) one or more units\n"
3959 " stop [NAME...] Stop (deactivate) one or more units\n"
3960 " reload [NAME...] Reload one or more units\n"
3961 " restart [NAME...] Start or restart one or more units\n"
3962 " try-restart [NAME...] Restart one or more units if active\n"
3963 " reload-or-restart [NAME...] Reload one or more units if possible,\n"
3964 " otherwise start or restart\n"
3965 " reload-or-try-restart [NAME...] Reload one or more units if possible,\n"
3966 " otherwise restart if active\n"
3967 " isolate [NAME] Start one unit and stop all others\n"
3968 " kill [NAME...] Send signal to processes of a unit\n"
3969 " is-active [NAME...] Check whether units are active\n"
3970 " status [NAME...|PID...] Show runtime status of one or more units\n"
3971 " show [NAME...|JOB...] Show properties of one or more\n"
3972 " units/jobs or the manager\n"
3973 " help [NAME...|PID...] Show manual for one or more units\n"
3974 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
3976 " load [NAME...] Load one or more units\n\n"
3977 "Unit File Commands:\n"
3978 " list-unit-files List installed unit files\n"
3979 " enable [NAME...] Enable one or more unit files\n"
3980 " disable [NAME...] Disable one or more unit files\n"
3981 " reenable [NAME...] Reenable one or more unit files\n"
3982 " preset [NAME...] Enable/disable one or more unit files\n"
3983 " based on preset configuration\n"
3984 " mask [NAME...] Mask one or more units\n"
3985 " unmask [NAME...] Unmask one or more units\n"
3986 " link [PATH...] Link one or more units files into\n"
3987 " the search path\n"
3988 " is-enabled [NAME...] Check whether unit files are enabled\n\n"
3990 " list-jobs List jobs\n"
3991 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
3992 "Status Commands:\n"
3993 " dump Dump server status\n"
3994 " dot Dump dependency graph for dot(1)\n\n"
3995 "Snapshot Commands:\n"
3996 " snapshot [NAME] Create a snapshot\n"
3997 " delete [NAME...] Remove one or more snapshots\n\n"
3998 "Environment Commands:\n"
3999 " show-environment Dump environment\n"
4000 " set-environment [NAME=VALUE...] Set one or more environment variables\n"
4001 " unset-environment [NAME...] Unset one or more environment variables\n\n"
4002 "Manager Lifecycle Commands:\n"
4003 " daemon-reload Reload systemd manager configuration\n"
4004 " daemon-reexec Reexecute systemd manager\n\n"
4005 "System Commands:\n"
4006 " default Enter system default mode\n"
4007 " rescue Enter system rescue mode\n"
4008 " emergency Enter system emergency mode\n"
4009 " halt Shut down and halt the system\n"
4010 " poweroff Shut down and power-off the system\n"
4011 " reboot Shut down and reboot the system\n"
4012 " kexec Shut down and reboot the system with kexec\n"
4013 " exit Request user instance exit\n"
4014 " switch-root [ROOT] [INIT] Change to a different root file system\n"
4015 " suspend Suspend the system\n"
4016 " hibernate Hibernate the system\n"
4017 " hybrid-sleep Hibernate and suspend the system\n",
4018 program_invocation_short_name);
4023 static int halt_help(void) {
4025 printf("%s [OPTIONS...]\n\n"
4026 "%s the system.\n\n"
4027 " --help Show this help\n"
4028 " --halt Halt the machine\n"
4029 " -p --poweroff Switch off the machine\n"
4030 " --reboot Reboot the machine\n"
4031 " -f --force Force immediate halt/power-off/reboot\n"
4032 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
4033 " -d --no-wtmp Don't write wtmp record\n"
4034 " --no-wall Don't send wall message before halt/power-off/reboot\n",
4035 program_invocation_short_name,
4036 arg_action == ACTION_REBOOT ? "Reboot" :
4037 arg_action == ACTION_POWEROFF ? "Power off" :
4043 static int shutdown_help(void) {
4045 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
4046 "Shut down the system.\n\n"
4047 " --help Show this help\n"
4048 " -H --halt Halt the machine\n"
4049 " -P --poweroff Power-off the machine\n"
4050 " -r --reboot Reboot the machine\n"
4051 " -h Equivalent to --poweroff, overridden by --halt\n"
4052 " -k Don't halt/power-off/reboot, just send warnings\n"
4053 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4054 " -c Cancel a pending shutdown\n",
4055 program_invocation_short_name);
4060 static int telinit_help(void) {
4062 printf("%s [OPTIONS...] {COMMAND}\n\n"
4063 "Send control commands to the init daemon.\n\n"
4064 " --help Show this help\n"
4065 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
4067 " 0 Power-off the machine\n"
4068 " 6 Reboot the machine\n"
4069 " 2, 3, 4, 5 Start runlevelX.target unit\n"
4070 " 1, s, S Enter rescue mode\n"
4071 " q, Q Reload init daemon configuration\n"
4072 " u, U Reexecute init daemon\n",
4073 program_invocation_short_name);
4078 static int runlevel_help(void) {
4080 printf("%s [OPTIONS...]\n\n"
4081 "Prints the previous and current runlevel of the init system.\n\n"
4082 " --help Show this help\n",
4083 program_invocation_short_name);
4088 static int help_types(void) {
4091 puts("Available unit types:");
4092 for(i = UNIT_SERVICE; i < _UNIT_TYPE_MAX; i++)
4093 if (unit_type_table[i])
4094 puts(unit_type_table[i]);
4096 puts("\nAvailable unit load states: ");
4097 for(i = UNIT_STUB; i < _UNIT_LOAD_STATE_MAX; i++)
4098 if (unit_type_table[i])
4099 puts(unit_load_state_table[i]);
4104 static int systemctl_parse_argv(int argc, char *argv[]) {
4108 ARG_IGNORE_DEPENDENCIES,
4123 ARG_NO_ASK_PASSWORD,
4129 static const struct option options[] = {
4130 { "help", no_argument, NULL, 'h' },
4131 { "version", no_argument, NULL, ARG_VERSION },
4132 { "type", required_argument, NULL, 't' },
4133 { "property", required_argument, NULL, 'p' },
4134 { "all", no_argument, NULL, 'a' },
4135 { "failed", no_argument, NULL, ARG_FAILED },
4136 { "full", no_argument, NULL, ARG_FULL },
4137 { "fail", no_argument, NULL, ARG_FAIL },
4138 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
4139 { "user", no_argument, NULL, ARG_USER },
4140 { "system", no_argument, NULL, ARG_SYSTEM },
4141 { "global", no_argument, NULL, ARG_GLOBAL },
4142 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
4143 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
4144 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
4145 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4146 { "quiet", no_argument, NULL, 'q' },
4147 { "order", no_argument, NULL, ARG_ORDER },
4148 { "require", no_argument, NULL, ARG_REQUIRE },
4149 { "root", required_argument, NULL, ARG_ROOT },
4150 { "force", no_argument, NULL, ARG_FORCE },
4151 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
4152 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
4153 { "signal", required_argument, NULL, 's' },
4154 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
4155 { "host", required_argument, NULL, 'H' },
4156 { "privileged",no_argument, NULL, 'P' },
4157 { "runtime", no_argument, NULL, ARG_RUNTIME },
4158 { "lines", required_argument, NULL, 'n' },
4159 { "output", required_argument, NULL, 'o' },
4160 { NULL, 0, NULL, 0 }
4168 while ((c = getopt_long(argc, argv, "ht:p:aqfs:H:Pn:o:", options, NULL)) >= 0) {
4177 puts(PACKAGE_STRING);
4179 puts(SYSTEMD_FEATURES);
4183 if (streq(optarg, "help")) {
4188 if (unit_type_from_string(optarg) >= 0) {
4192 if (unit_load_state_from_string(optarg) >= 0) {
4193 arg_load_state = optarg;
4196 log_error("Unkown unit type or load state '%s'.",
4198 log_info("Use -t help to see a list of allowed values.");
4203 if (!(l = strv_append(arg_property, optarg)))
4206 strv_free(arg_property);
4209 /* If the user asked for a particular
4210 * property, show it to him, even if it is
4221 arg_job_mode = "fail";
4224 case ARG_IGNORE_DEPENDENCIES:
4225 arg_job_mode = "ignore-dependencies";
4229 arg_scope = UNIT_FILE_USER;
4233 arg_scope = UNIT_FILE_SYSTEM;
4237 arg_scope = UNIT_FILE_GLOBAL;
4241 arg_no_block = true;
4245 arg_no_legend = true;
4249 arg_no_pager = true;
4257 arg_dot = DOT_ORDER;
4261 arg_dot = DOT_REQUIRE;
4289 arg_no_reload = true;
4293 arg_kill_who = optarg;
4297 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
4298 log_error("Failed to parse signal string %s.", optarg);
4303 case ARG_NO_ASK_PASSWORD:
4304 arg_ask_password = false;
4308 arg_transport = TRANSPORT_POLKIT;
4312 arg_transport = TRANSPORT_SSH;
4321 if (safe_atou(optarg, &arg_lines) < 0) {
4322 log_error("Failed to parse lines '%s'", optarg);
4328 arg_output = output_mode_from_string(optarg);
4329 if (arg_output < 0) {
4330 log_error("Unknown output '%s'.", optarg);
4339 log_error("Unknown option code '%c'.", c);
4344 if (arg_transport != TRANSPORT_NORMAL && arg_scope != UNIT_FILE_SYSTEM) {
4345 log_error("Cannot access user instance remotely.");
4352 static int halt_parse_argv(int argc, char *argv[]) {
4361 static const struct option options[] = {
4362 { "help", no_argument, NULL, ARG_HELP },
4363 { "halt", no_argument, NULL, ARG_HALT },
4364 { "poweroff", no_argument, NULL, 'p' },
4365 { "reboot", no_argument, NULL, ARG_REBOOT },
4366 { "force", no_argument, NULL, 'f' },
4367 { "wtmp-only", no_argument, NULL, 'w' },
4368 { "no-wtmp", no_argument, NULL, 'd' },
4369 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4370 { NULL, 0, NULL, 0 }
4378 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
4379 if (runlevel == '0' || runlevel == '6')
4382 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
4390 arg_action = ACTION_HALT;
4394 if (arg_action != ACTION_REBOOT)
4395 arg_action = ACTION_POWEROFF;
4399 arg_action = ACTION_REBOOT;
4421 /* Compatibility nops */
4428 log_error("Unknown option code '%c'.", c);
4433 if (optind < argc) {
4434 log_error("Too many arguments.");
4441 static int parse_time_spec(const char *t, usec_t *_u) {
4445 if (streq(t, "now"))
4447 else if (!strchr(t, ':')) {
4450 if (safe_atou64(t, &u) < 0)
4453 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
4462 hour = strtol(t, &e, 10);
4463 if (errno != 0 || *e != ':' || hour < 0 || hour > 23)
4466 minute = strtol(e+1, &e, 10);
4467 if (errno != 0 || *e != 0 || minute < 0 || minute > 59)
4470 n = now(CLOCK_REALTIME);
4471 s = (time_t) (n / USEC_PER_SEC);
4474 assert_se(localtime_r(&s, &tm));
4476 tm.tm_hour = (int) hour;
4477 tm.tm_min = (int) minute;
4480 assert_se(s = mktime(&tm));
4482 *_u = (usec_t) s * USEC_PER_SEC;
4485 *_u += USEC_PER_DAY;
4491 static int shutdown_parse_argv(int argc, char *argv[]) {
4498 static const struct option options[] = {
4499 { "help", no_argument, NULL, ARG_HELP },
4500 { "halt", no_argument, NULL, 'H' },
4501 { "poweroff", no_argument, NULL, 'P' },
4502 { "reboot", no_argument, NULL, 'r' },
4503 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
4504 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4505 { NULL, 0, NULL, 0 }
4513 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
4521 arg_action = ACTION_HALT;
4525 arg_action = ACTION_POWEROFF;
4530 arg_action = ACTION_KEXEC;
4532 arg_action = ACTION_REBOOT;
4536 arg_action = ACTION_KEXEC;
4540 if (arg_action != ACTION_HALT)
4541 arg_action = ACTION_POWEROFF;
4554 /* Compatibility nops */
4558 arg_action = ACTION_CANCEL_SHUTDOWN;
4565 log_error("Unknown option code '%c'.", c);
4570 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
4571 r = parse_time_spec(argv[optind], &arg_when);
4573 log_error("Failed to parse time specification: %s", argv[optind]);
4577 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
4579 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
4580 /* No time argument for shutdown cancel */
4581 arg_wall = argv + optind;
4582 else if (argc > optind + 1)
4583 /* We skip the time argument */
4584 arg_wall = argv + optind + 1;
4591 static int telinit_parse_argv(int argc, char *argv[]) {
4598 static const struct option options[] = {
4599 { "help", no_argument, NULL, ARG_HELP },
4600 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4601 { NULL, 0, NULL, 0 }
4604 static const struct {
4608 { '0', ACTION_POWEROFF },
4609 { '6', ACTION_REBOOT },
4610 { '1', ACTION_RESCUE },
4611 { '2', ACTION_RUNLEVEL2 },
4612 { '3', ACTION_RUNLEVEL3 },
4613 { '4', ACTION_RUNLEVEL4 },
4614 { '5', ACTION_RUNLEVEL5 },
4615 { 's', ACTION_RESCUE },
4616 { 'S', ACTION_RESCUE },
4617 { 'q', ACTION_RELOAD },
4618 { 'Q', ACTION_RELOAD },
4619 { 'u', ACTION_REEXEC },
4620 { 'U', ACTION_REEXEC }
4629 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4644 log_error("Unknown option code '%c'.", c);
4649 if (optind >= argc) {
4654 if (optind + 1 < argc) {
4655 log_error("Too many arguments.");
4659 if (strlen(argv[optind]) != 1) {
4660 log_error("Expected single character argument.");
4664 for (i = 0; i < ELEMENTSOF(table); i++)
4665 if (table[i].from == argv[optind][0])
4668 if (i >= ELEMENTSOF(table)) {
4669 log_error("Unknown command '%s'.", argv[optind]);
4673 arg_action = table[i].to;
4680 static int runlevel_parse_argv(int argc, char *argv[]) {
4686 static const struct option options[] = {
4687 { "help", no_argument, NULL, ARG_HELP },
4688 { NULL, 0, NULL, 0 }
4696 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4707 log_error("Unknown option code '%c'.", c);
4712 if (optind < argc) {
4713 log_error("Too many arguments.");
4720 static int parse_argv(int argc, char *argv[]) {
4724 if (program_invocation_short_name) {
4726 if (strstr(program_invocation_short_name, "halt")) {
4727 arg_action = ACTION_HALT;
4728 return halt_parse_argv(argc, argv);
4729 } else if (strstr(program_invocation_short_name, "poweroff")) {
4730 arg_action = ACTION_POWEROFF;
4731 return halt_parse_argv(argc, argv);
4732 } else if (strstr(program_invocation_short_name, "reboot")) {
4734 arg_action = ACTION_KEXEC;
4736 arg_action = ACTION_REBOOT;
4737 return halt_parse_argv(argc, argv);
4738 } else if (strstr(program_invocation_short_name, "shutdown")) {
4739 arg_action = ACTION_POWEROFF;
4740 return shutdown_parse_argv(argc, argv);
4741 } else if (strstr(program_invocation_short_name, "init")) {
4743 if (sd_booted() > 0) {
4744 arg_action = ACTION_INVALID;
4745 return telinit_parse_argv(argc, argv);
4747 /* Hmm, so some other init system is
4748 * running, we need to forward this
4749 * request to it. For now we simply
4750 * guess that it is Upstart. */
4752 execv("/lib/upstart/telinit", argv);
4754 log_error("Couldn't find an alternative telinit implementation to spawn.");
4758 } else if (strstr(program_invocation_short_name, "runlevel")) {
4759 arg_action = ACTION_RUNLEVEL;
4760 return runlevel_parse_argv(argc, argv);
4764 arg_action = ACTION_SYSTEMCTL;
4765 return systemctl_parse_argv(argc, argv);
4768 static int action_to_runlevel(void) {
4770 static const char table[_ACTION_MAX] = {
4771 [ACTION_HALT] = '0',
4772 [ACTION_POWEROFF] = '0',
4773 [ACTION_REBOOT] = '6',
4774 [ACTION_RUNLEVEL2] = '2',
4775 [ACTION_RUNLEVEL3] = '3',
4776 [ACTION_RUNLEVEL4] = '4',
4777 [ACTION_RUNLEVEL5] = '5',
4778 [ACTION_RESCUE] = '1'
4781 assert(arg_action < _ACTION_MAX);
4783 return table[arg_action];
4786 static int talk_upstart(void) {
4787 DBusMessage *m = NULL, *reply = NULL;
4789 int previous, rl, r;
4791 env1_buf[] = "RUNLEVEL=X",
4792 env2_buf[] = "PREVLEVEL=X";
4793 char *env1 = env1_buf, *env2 = env2_buf;
4794 const char *emit = "runlevel";
4795 dbus_bool_t b_false = FALSE;
4796 DBusMessageIter iter, sub;
4797 DBusConnection *bus;
4799 dbus_error_init(&error);
4801 if (!(rl = action_to_runlevel()))
4804 if (utmp_get_runlevel(&previous, NULL) < 0)
4807 if (!(bus = dbus_connection_open_private("unix:abstract=/com/ubuntu/upstart", &error))) {
4808 if (dbus_error_has_name(&error, DBUS_ERROR_NO_SERVER)) {
4813 log_error("Failed to connect to Upstart bus: %s", bus_error_message(&error));
4818 if ((r = bus_check_peercred(bus)) < 0) {
4819 log_error("Failed to verify owner of bus.");
4823 if (!(m = dbus_message_new_method_call(
4824 "com.ubuntu.Upstart",
4825 "/com/ubuntu/Upstart",
4826 "com.ubuntu.Upstart0_6",
4829 log_error("Could not allocate message.");
4834 dbus_message_iter_init_append(m, &iter);
4836 env1_buf[sizeof(env1_buf)-2] = rl;
4837 env2_buf[sizeof(env2_buf)-2] = previous;
4839 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &emit) ||
4840 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub) ||
4841 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env1) ||
4842 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env2) ||
4843 !dbus_message_iter_close_container(&iter, &sub) ||
4844 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b_false)) {
4845 log_error("Could not append arguments to message.");
4850 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
4852 if (bus_error_is_no_service(&error)) {
4857 log_error("Failed to issue method call: %s", bus_error_message(&error));
4866 dbus_message_unref(m);
4869 dbus_message_unref(reply);
4872 dbus_connection_flush(bus);
4873 dbus_connection_close(bus);
4874 dbus_connection_unref(bus);
4877 dbus_error_free(&error);
4882 static int talk_initctl(void) {
4883 struct init_request request;
4887 if (!(rl = action_to_runlevel()))
4891 request.magic = INIT_MAGIC;
4892 request.sleeptime = 0;
4893 request.cmd = INIT_CMD_RUNLVL;
4894 request.runlevel = rl;
4896 if ((fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY)) < 0) {
4898 if (errno == ENOENT)
4901 log_error("Failed to open "INIT_FIFO": %m");
4906 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
4907 close_nointr_nofail(fd);
4910 log_error("Failed to write to "INIT_FIFO": %m");
4911 return errno ? -errno : -EIO;
4917 static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
4919 static const struct {
4927 int (* const dispatch)(DBusConnection *bus, char **args);
4929 { "list-units", LESS, 1, list_units },
4930 { "list-unit-files", EQUAL, 1, list_unit_files },
4931 { "list-jobs", EQUAL, 1, list_jobs },
4932 { "clear-jobs", EQUAL, 1, daemon_reload },
4933 { "load", MORE, 2, load_unit },
4934 { "cancel", MORE, 2, cancel_job },
4935 { "start", MORE, 2, start_unit },
4936 { "stop", MORE, 2, start_unit },
4937 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
4938 { "reload", MORE, 2, start_unit },
4939 { "restart", MORE, 2, start_unit },
4940 { "try-restart", MORE, 2, start_unit },
4941 { "reload-or-restart", MORE, 2, start_unit },
4942 { "reload-or-try-restart", MORE, 2, start_unit },
4943 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
4944 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
4945 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
4946 { "isolate", EQUAL, 2, start_unit },
4947 { "kill", MORE, 2, kill_unit },
4948 { "is-active", MORE, 2, check_unit },
4949 { "check", MORE, 2, check_unit },
4950 { "show", MORE, 1, show },
4951 { "status", MORE, 2, show },
4952 { "help", MORE, 2, show },
4953 { "dump", EQUAL, 1, dump },
4954 { "dot", EQUAL, 1, dot },
4955 { "snapshot", LESS, 2, snapshot },
4956 { "delete", MORE, 2, delete_snapshot },
4957 { "daemon-reload", EQUAL, 1, daemon_reload },
4958 { "daemon-reexec", EQUAL, 1, daemon_reload },
4959 { "show-environment", EQUAL, 1, show_enviroment },
4960 { "set-environment", MORE, 2, set_environment },
4961 { "unset-environment", MORE, 2, set_environment },
4962 { "halt", EQUAL, 1, start_special },
4963 { "poweroff", EQUAL, 1, start_special },
4964 { "reboot", EQUAL, 1, start_special },
4965 { "kexec", EQUAL, 1, start_special },
4966 { "suspend", EQUAL, 1, start_special },
4967 { "hibernate", EQUAL, 1, start_special },
4968 { "hybrid-sleep", EQUAL, 1, start_special },
4969 { "default", EQUAL, 1, start_special },
4970 { "rescue", EQUAL, 1, start_special },
4971 { "emergency", EQUAL, 1, start_special },
4972 { "exit", EQUAL, 1, start_special },
4973 { "reset-failed", MORE, 1, reset_failed },
4974 { "enable", MORE, 2, enable_unit },
4975 { "disable", MORE, 2, enable_unit },
4976 { "is-enabled", MORE, 2, unit_is_enabled },
4977 { "reenable", MORE, 2, enable_unit },
4978 { "preset", MORE, 2, enable_unit },
4979 { "mask", MORE, 2, enable_unit },
4980 { "unmask", MORE, 2, enable_unit },
4981 { "link", MORE, 2, enable_unit },
4982 { "switch-root", MORE, 2, switch_root },
4992 left = argc - optind;
4995 /* Special rule: no arguments means "list-units" */
4998 if (streq(argv[optind], "help") && !argv[optind+1]) {
4999 log_error("This command expects one or more "
5000 "unit names. Did you mean --help?");
5004 for (i = 0; i < ELEMENTSOF(verbs); i++)
5005 if (streq(argv[optind], verbs[i].verb))
5008 if (i >= ELEMENTSOF(verbs)) {
5009 log_error("Unknown operation '%s'.", argv[optind]);
5014 switch (verbs[i].argc_cmp) {
5017 if (left != verbs[i].argc) {
5018 log_error("Invalid number of arguments.");
5025 if (left < verbs[i].argc) {
5026 log_error("Too few arguments.");
5033 if (left > verbs[i].argc) {
5034 log_error("Too many arguments.");
5041 assert_not_reached("Unknown comparison operator.");
5044 /* Require a bus connection for all operations but
5046 if (!streq(verbs[i].verb, "enable") &&
5047 !streq(verbs[i].verb, "disable") &&
5048 !streq(verbs[i].verb, "is-enabled") &&
5049 !streq(verbs[i].verb, "list-unit-files") &&
5050 !streq(verbs[i].verb, "reenable") &&
5051 !streq(verbs[i].verb, "preset") &&
5052 !streq(verbs[i].verb, "mask") &&
5053 !streq(verbs[i].verb, "unmask") &&
5054 !streq(verbs[i].verb, "link")) {
5056 if (running_in_chroot() > 0) {
5057 log_info("Running in chroot, ignoring request.");
5061 if (((!streq(verbs[i].verb, "reboot") &&
5062 !streq(verbs[i].verb, "halt") &&
5063 !streq(verbs[i].verb, "poweroff")) || arg_force <= 0) && !bus) {
5064 log_error("Failed to get D-Bus connection: %s",
5065 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5071 if (!bus && !avoid_bus()) {
5072 log_error("Failed to get D-Bus connection: %s",
5073 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5078 return verbs[i].dispatch(bus, argv + optind);
5081 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
5083 struct msghdr msghdr;
5084 struct iovec iovec[2];
5085 union sockaddr_union sockaddr;
5086 struct sd_shutdown_command c;
5088 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
5095 c.dry_run = dry_run;
5099 sockaddr.sa.sa_family = AF_UNIX;
5100 strncpy(sockaddr.un.sun_path, "/run/systemd/shutdownd", sizeof(sockaddr.un.sun_path));
5103 msghdr.msg_name = &sockaddr;
5104 msghdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + sizeof("/run/systemd/shutdownd") - 1;
5107 iovec[0].iov_base = (char*) &c;
5108 iovec[0].iov_len = offsetof(struct sd_shutdown_command, wall_message);
5110 if (isempty(message))
5111 msghdr.msg_iovlen = 1;
5113 iovec[1].iov_base = (char*) message;
5114 iovec[1].iov_len = strlen(message);
5115 msghdr.msg_iovlen = 2;
5117 msghdr.msg_iov = iovec;
5119 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0) {
5120 close_nointr_nofail(fd);
5124 close_nointr_nofail(fd);
5128 static int reload_with_fallback(DBusConnection *bus) {
5131 /* First, try systemd via D-Bus. */
5132 if (daemon_reload(bus, NULL) >= 0)
5136 /* Nothing else worked, so let's try signals */
5137 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
5139 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
5140 log_error("kill() failed: %m");
5147 static int start_with_fallback(DBusConnection *bus) {
5150 /* First, try systemd via D-Bus. */
5151 if (start_unit(bus, NULL) >= 0)
5155 /* Hmm, talking to systemd via D-Bus didn't work. Then
5156 * let's try to talk to Upstart via D-Bus. */
5157 if (talk_upstart() > 0)
5160 /* Nothing else worked, so let's try
5162 if (talk_initctl() > 0)
5165 log_error("Failed to talk to init daemon.");
5169 warn_wall(arg_action);
5173 static _noreturn_ void halt_now(enum action a) {
5175 /* Make sure C-A-D is handled by the kernel from this
5177 reboot(RB_ENABLE_CAD);
5182 log_info("Halting.");
5183 reboot(RB_HALT_SYSTEM);
5186 case ACTION_POWEROFF:
5187 log_info("Powering off.");
5188 reboot(RB_POWER_OFF);
5192 log_info("Rebooting.");
5193 reboot(RB_AUTOBOOT);
5197 assert_not_reached("Unknown halt action.");
5200 assert_not_reached("Uh? This shouldn't happen.");
5203 static int halt_main(DBusConnection *bus) {
5206 if (geteuid() != 0) {
5207 /* Try logind if we are a normal user and no special
5208 * mode applies. Maybe PolicyKit allows us to shutdown
5211 if (arg_when <= 0 &&
5214 (arg_action == ACTION_POWEROFF ||
5215 arg_action == ACTION_REBOOT)) {
5216 r = reboot_with_logind(bus, arg_action);
5221 log_error("Must be root.");
5228 m = strv_join(arg_wall, " ");
5229 r = send_shutdownd(arg_when,
5230 arg_action == ACTION_HALT ? 'H' :
5231 arg_action == ACTION_POWEROFF ? 'P' :
5232 arg_action == ACTION_KEXEC ? 'K' :
5240 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
5242 char date[FORMAT_TIMESTAMP_MAX];
5244 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
5245 format_timestamp(date, sizeof(date), arg_when));
5250 if (!arg_dry && !arg_force)
5251 return start_with_fallback(bus);
5254 if (sd_booted() > 0)
5255 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
5257 r = utmp_put_shutdown();
5259 log_warning("Failed to write utmp record: %s", strerror(-r));
5266 halt_now(arg_action);
5267 /* We should never reach this. */
5271 static int runlevel_main(void) {
5272 int r, runlevel, previous;
5274 r = utmp_get_runlevel(&runlevel, &previous);
5281 previous <= 0 ? 'N' : previous,
5282 runlevel <= 0 ? 'N' : runlevel);
5287 int main(int argc, char*argv[]) {
5288 int r, retval = EXIT_FAILURE;
5289 DBusConnection *bus = NULL;
5292 dbus_error_init(&error);
5294 setlocale(LC_ALL, "");
5295 log_parse_environment();
5298 r = parse_argv(argc, argv);
5302 retval = EXIT_SUCCESS;
5306 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
5307 * let's shortcut this */
5308 if (arg_action == ACTION_RUNLEVEL) {
5309 r = runlevel_main();
5310 retval = r < 0 ? EXIT_FAILURE : r;
5314 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
5315 log_info("Running in chroot, ignoring request.");
5321 if (arg_transport == TRANSPORT_NORMAL)
5322 bus_connect(arg_scope == UNIT_FILE_SYSTEM ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &bus, &private_bus, &error);
5323 else if (arg_transport == TRANSPORT_POLKIT) {
5324 bus_connect_system_polkit(&bus, &error);
5325 private_bus = false;
5326 } else if (arg_transport == TRANSPORT_SSH) {
5327 bus_connect_system_ssh(NULL, arg_host, &bus, &error);
5328 private_bus = false;
5330 assert_not_reached("Uh, invalid transport...");
5333 switch (arg_action) {
5335 case ACTION_SYSTEMCTL:
5336 r = systemctl_main(bus, argc, argv, &error);
5340 case ACTION_POWEROFF:
5346 case ACTION_RUNLEVEL2:
5347 case ACTION_RUNLEVEL3:
5348 case ACTION_RUNLEVEL4:
5349 case ACTION_RUNLEVEL5:
5351 case ACTION_EMERGENCY:
5352 case ACTION_DEFAULT:
5353 r = start_with_fallback(bus);
5358 r = reload_with_fallback(bus);
5361 case ACTION_CANCEL_SHUTDOWN: {
5365 m = strv_join(arg_wall, " ");
5367 retval = EXIT_FAILURE;
5371 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
5373 log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r));
5378 case ACTION_INVALID:
5379 case ACTION_RUNLEVEL:
5381 assert_not_reached("Unknown action");
5384 retval = r < 0 ? EXIT_FAILURE : r;
5388 dbus_connection_flush(bus);
5389 dbus_connection_close(bus);
5390 dbus_connection_unref(bus);
5393 dbus_error_free(&error);
5397 strv_free(arg_property);
5400 ask_password_agent_close();
5401 polkit_agent_close();