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>
41 #include <systemd/sd-login.h>
47 #include "utmp-wtmp.h"
50 #include "path-util.h"
52 #include "dbus-common.h"
53 #include "cgroup-show.h"
54 #include "cgroup-util.h"
56 #include "path-lookup.h"
57 #include "conf-parser.h"
58 #include "exit-status.h"
59 #include "bus-errors.h"
61 #include "unit-name.h"
63 #include "spawn-ask-password-agent.h"
64 #include "spawn-polkit-agent.h"
66 #include "logs-show.h"
67 #include "path-util.h"
68 #include "socket-util.h"
70 static const char *arg_type = NULL;
71 static const char *arg_load_state = NULL;
72 static char **arg_property = NULL;
73 static bool arg_all = false;
74 static const char *arg_job_mode = "replace";
75 static UnitFileScope arg_scope = UNIT_FILE_SYSTEM;
76 static bool arg_no_block = false;
77 static bool arg_no_legend = false;
78 static bool arg_no_pager = false;
79 static bool arg_no_wtmp = false;
80 static bool arg_no_wall = false;
81 static bool arg_no_reload = false;
82 static bool arg_ignore_inhibitors = false;
83 static bool arg_dry = false;
84 static bool arg_quiet = false;
85 static bool arg_full = false;
86 static int arg_force = 0;
87 static bool arg_ask_password = true;
88 static bool arg_failed = false;
89 static bool arg_runtime = false;
90 static char **arg_wall = NULL;
91 static const char *arg_kill_who = NULL;
92 static int arg_signal = SIGTERM;
93 static const char *arg_root = NULL;
94 static usec_t arg_when = 0;
116 ACTION_CANCEL_SHUTDOWN,
118 } arg_action = ACTION_SYSTEMCTL;
124 static enum transport {
128 } arg_transport = TRANSPORT_NORMAL;
129 static const char *arg_host = NULL;
130 static unsigned arg_lines = 10;
131 static OutputMode arg_output = OUTPUT_SHORT;
133 static bool private_bus = false;
135 static int daemon_reload(DBusConnection *bus, char **args);
136 static void halt_now(enum action a);
138 static void pager_open_if_enabled(void) {
146 static void ask_password_agent_open_if_enabled(void) {
148 /* Open the password agent as a child process if necessary */
150 if (!arg_ask_password)
153 if (arg_scope != UNIT_FILE_SYSTEM)
156 ask_password_agent_open();
160 static void polkit_agent_open_if_enabled(void) {
162 /* Open the polkit agent as a child process if necessary */
164 if (!arg_ask_password)
167 if (arg_scope != UNIT_FILE_SYSTEM)
174 static const char *ansi_highlight(bool b) {
179 return b ? ANSI_HIGHLIGHT_ON : ANSI_HIGHLIGHT_OFF;
182 static const char *ansi_highlight_red(bool b) {
187 return b ? ANSI_HIGHLIGHT_RED_ON : ANSI_HIGHLIGHT_OFF;
190 static const char *ansi_highlight_green(bool b) {
195 return b ? ANSI_HIGHLIGHT_GREEN_ON : ANSI_HIGHLIGHT_OFF;
198 static int translate_bus_error_to_exit_status(int r, const DBusError *error) {
201 if (!dbus_error_is_set(error))
204 if (dbus_error_has_name(error, DBUS_ERROR_ACCESS_DENIED) ||
205 dbus_error_has_name(error, BUS_ERROR_ONLY_BY_DEPENDENCY) ||
206 dbus_error_has_name(error, BUS_ERROR_NO_ISOLATION) ||
207 dbus_error_has_name(error, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE))
208 return EXIT_NOPERMISSION;
210 if (dbus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT))
211 return EXIT_NOTINSTALLED;
213 if (dbus_error_has_name(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE) ||
214 dbus_error_has_name(error, BUS_ERROR_NOT_SUPPORTED))
215 return EXIT_NOTIMPLEMENTED;
217 if (dbus_error_has_name(error, BUS_ERROR_LOAD_FAILED))
218 return EXIT_NOTCONFIGURED;
226 static void warn_wall(enum action a) {
227 static const char *table[_ACTION_MAX] = {
228 [ACTION_HALT] = "The system is going down for system halt NOW!",
229 [ACTION_REBOOT] = "The system is going down for reboot NOW!",
230 [ACTION_POWEROFF] = "The system is going down for power-off NOW!",
231 [ACTION_KEXEC] = "The system is going down for kexec reboot NOW!",
232 [ACTION_RESCUE] = "The system is going down to rescue mode NOW!",
233 [ACTION_EMERGENCY] = "The system is going down to emergency mode NOW!",
234 [ACTION_CANCEL_SHUTDOWN] = "The system shutdown has been cancelled NOW!"
241 _cleanup_free_ char *p;
243 p = strv_join(arg_wall, " ");
258 utmp_wall(table[a], NULL);
261 static bool avoid_bus(void) {
263 if (running_in_chroot() > 0)
266 if (sd_booted() <= 0)
269 if (!isempty(arg_root))
272 if (arg_scope == UNIT_FILE_GLOBAL)
280 const char *description;
281 const char *load_state;
282 const char *active_state;
283 const char *sub_state;
284 const char *following;
285 const char *unit_path;
287 const char *job_type;
288 const char *job_path;
291 static int compare_unit_info(const void *a, const void *b) {
293 const struct unit_info *u = a, *v = b;
295 d1 = strrchr(u->id, '.');
296 d2 = strrchr(v->id, '.');
301 r = strcasecmp(d1, d2);
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 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
450 _cleanup_free_ struct unit_info *unit_infos = NULL;
451 DBusMessageIter iter, sub, sub2;
452 unsigned c = 0, n_units = 0;
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.");
476 dbus_message_iter_recurse(&iter, &sub);
478 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
481 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT);
486 n_units = MAX(2*c, 16);
487 w = realloc(unit_infos, sizeof(struct unit_info) * n_units);
496 dbus_message_iter_recurse(&sub, &sub2);
498 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->id, true) < 0 ||
499 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->description, true) < 0 ||
500 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->load_state, true) < 0 ||
501 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->active_state, true) < 0 ||
502 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->sub_state, true) < 0 ||
503 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->following, true) < 0 ||
504 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &u->unit_path, true) < 0 ||
505 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &u->job_id, true) < 0 ||
506 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->job_type, true) < 0 ||
507 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &u->job_path, false) < 0) {
508 log_error("Failed to parse reply.");
512 dbus_message_iter_next(&sub);
517 qsort(unit_infos, c, sizeof(struct unit_info), compare_unit_info);
518 output_units_list(unit_infos, c);
524 static int compare_unit_file_list(const void *a, const void *b) {
526 const UnitFileList *u = a, *v = b;
528 d1 = strrchr(u->path, '.');
529 d2 = strrchr(v->path, '.');
534 r = strcasecmp(d1, d2);
539 return strcasecmp(path_get_file_name(u->path), path_get_file_name(v->path));
542 static bool output_show_unit_file(const UnitFileList *u) {
545 return !arg_type || ((dot = strrchr(u->path, '.')) && streq(dot+1, arg_type));
548 static void output_unit_file_list(const UnitFileList *units, unsigned c) {
549 unsigned max_id_len, id_cols, state_cols, n_shown = 0;
550 const UnitFileList *u;
552 max_id_len = sizeof("UNIT FILE")-1;
553 state_cols = sizeof("STATE")-1;
554 for (u = units; u < units + c; u++) {
555 if (!output_show_unit_file(u))
558 max_id_len = MAX(max_id_len, strlen(path_get_file_name(u->path)));
559 state_cols = MAX(state_cols, strlen(unit_file_state_to_string(u->state)));
564 id_cols = MIN(max_id_len, 25);
565 basic_cols = 1 + id_cols + state_cols;
566 if (basic_cols < (unsigned) columns())
567 id_cols += MIN(columns() - basic_cols, max_id_len - id_cols);
569 id_cols = max_id_len;
572 printf("%-*s %-*s\n", id_cols, "UNIT FILE", state_cols, "STATE");
574 for (u = units; u < units + c; u++) {
576 const char *on, *off;
579 if (!output_show_unit_file(u))
584 if (u->state == UNIT_FILE_MASKED ||
585 u->state == UNIT_FILE_MASKED_RUNTIME ||
586 u->state == UNIT_FILE_DISABLED ||
587 u->state == UNIT_FILE_INVALID) {
588 on = ansi_highlight_red(true);
589 off = ansi_highlight_red(false);
590 } else if (u->state == UNIT_FILE_ENABLED) {
591 on = ansi_highlight_green(true);
592 off = ansi_highlight_green(false);
596 id = path_get_file_name(u->path);
598 e = arg_full ? NULL : ellipsize(id, id_cols, 33);
600 printf("%-*s %s%-*s%s\n",
602 on, state_cols, unit_file_state_to_string(u->state), off);
608 printf("\n%u unit files listed.\n", n_shown);
611 static int list_unit_files(DBusConnection *bus, char **args) {
612 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
613 _cleanup_free_ UnitFileList *units = NULL;
614 DBusMessageIter iter, sub, sub2;
615 unsigned c = 0, n_units = 0;
618 pager_open_if_enabled();
625 h = hashmap_new(string_hash_func, string_compare_func);
629 r = unit_file_get_list(arg_scope, arg_root, h);
631 unit_file_list_free(h);
632 log_error("Failed to get unit file list: %s", strerror(-r));
636 n_units = hashmap_size(h);
637 units = new(UnitFileList, n_units);
639 unit_file_list_free(h);
643 HASHMAP_FOREACH(u, h, i) {
644 memcpy(units + c++, u, sizeof(UnitFileList));
650 r = bus_method_call_with_reply(
652 "org.freedesktop.systemd1",
653 "/org/freedesktop/systemd1",
654 "org.freedesktop.systemd1.Manager",
662 if (!dbus_message_iter_init(reply, &iter) ||
663 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
664 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
665 log_error("Failed to parse reply.");
669 dbus_message_iter_recurse(&iter, &sub);
671 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
675 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT);
680 n_units = MAX(2*c, 16);
681 w = realloc(units, sizeof(struct UnitFileList) * n_units);
690 dbus_message_iter_recurse(&sub, &sub2);
692 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->path, true) < 0 ||
693 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, false) < 0) {
694 log_error("Failed to parse reply.");
698 u->state = unit_file_state_from_string(state);
700 dbus_message_iter_next(&sub);
706 qsort(units, c, sizeof(UnitFileList), compare_unit_file_list);
707 output_unit_file_list(units, c);
713 static int dot_one_property(const char *name, const char *prop, DBusMessageIter *iter) {
715 static const char * const colors[] = {
716 "Requires", "[color=\"black\"]",
717 "RequiresOverridable", "[color=\"black\"]",
718 "Requisite", "[color=\"darkblue\"]",
719 "RequisiteOverridable", "[color=\"darkblue\"]",
720 "Wants", "[color=\"grey66\"]",
721 "Conflicts", "[color=\"red\"]",
722 "ConflictedBy", "[color=\"red\"]",
723 "After", "[color=\"green\"]"
726 const char *c = NULL;
733 for (i = 0; i < ELEMENTSOF(colors); i += 2)
734 if (streq(colors[i], prop)) {
742 if (arg_dot != DOT_ALL)
743 if ((arg_dot == DOT_ORDER) != streq(prop, "After"))
746 switch (dbus_message_iter_get_arg_type(iter)) {
748 case DBUS_TYPE_ARRAY:
750 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING) {
753 dbus_message_iter_recurse(iter, &sub);
755 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
758 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING);
759 dbus_message_iter_get_basic(&sub, &s);
760 printf("\t\"%s\"->\"%s\" %s;\n", name, s, c);
762 dbus_message_iter_next(&sub);
772 static int dot_one(DBusConnection *bus, const char *name, const char *path) {
773 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
774 const char *interface = "org.freedesktop.systemd1.Unit";
776 DBusMessageIter iter, sub, sub2, sub3;
781 r = bus_method_call_with_reply(
783 "org.freedesktop.systemd1",
785 "org.freedesktop.DBus.Properties",
789 DBUS_TYPE_STRING, &interface,
794 if (!dbus_message_iter_init(reply, &iter) ||
795 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
796 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
797 log_error("Failed to parse reply.");
801 dbus_message_iter_recurse(&iter, &sub);
803 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
806 assert(dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_DICT_ENTRY);
807 dbus_message_iter_recurse(&sub, &sub2);
809 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &prop, true) < 0 ||
810 dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
811 log_error("Failed to parse reply.");
815 dbus_message_iter_recurse(&sub2, &sub3);
816 r = dot_one_property(name, prop, &sub3);
820 dbus_message_iter_next(&sub);
826 static int dot(DBusConnection *bus, char **args) {
827 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
828 DBusMessageIter iter, sub, sub2;
831 r = bus_method_call_with_reply(
833 "org.freedesktop.systemd1",
834 "/org/freedesktop/systemd1",
835 "org.freedesktop.systemd1.Manager",
843 if (!dbus_message_iter_init(reply, &iter) ||
844 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
845 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
846 log_error("Failed to parse reply.");
850 printf("digraph systemd {\n");
852 dbus_message_iter_recurse(&iter, &sub);
853 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
854 const char *id, *description, *load_state, *active_state, *sub_state, *following, *unit_path;
856 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
857 log_error("Failed to parse reply.");
861 dbus_message_iter_recurse(&sub, &sub2);
863 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &id, true) < 0 ||
864 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &description, true) < 0 ||
865 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &load_state, true) < 0 ||
866 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &active_state, true) < 0 ||
867 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &sub_state, true) < 0 ||
868 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &following, true) < 0 ||
869 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, true) < 0) {
870 log_error("Failed to parse reply.");
874 r = dot_one(bus, id, unit_path);
878 /* printf("\t\"%s\";\n", id); */
879 dbus_message_iter_next(&sub);
884 log_info(" Color legend: black = Requires\n"
885 " dark blue = Requisite\n"
886 " dark grey = Wants\n"
891 log_notice("-- You probably want to process this output with graphviz' dot tool.\n"
892 "-- Try a shell pipeline like 'systemctl dot | dot -Tsvg > systemd.svg'!\n");
897 static int list_jobs(DBusConnection *bus, char **args) {
898 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
899 DBusMessageIter iter, sub, sub2;
903 pager_open_if_enabled();
905 r = bus_method_call_with_reply(
907 "org.freedesktop.systemd1",
908 "/org/freedesktop/systemd1",
909 "org.freedesktop.systemd1.Manager",
917 if (!dbus_message_iter_init(reply, &iter) ||
918 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
919 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
920 log_error("Failed to parse reply.");
924 dbus_message_iter_recurse(&iter, &sub);
927 printf("%4s %-25s %-15s %-7s\n", "JOB", "UNIT", "TYPE", "STATE");
929 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
930 const char *name, *type, *state, *job_path, *unit_path;
934 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
935 log_error("Failed to parse reply.");
939 dbus_message_iter_recurse(&sub, &sub2);
941 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &id, true) < 0 ||
942 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
943 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
944 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, true) < 0 ||
945 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &job_path, true) < 0 ||
946 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, false) < 0) {
947 log_error("Failed to parse reply.");
951 e = arg_full ? NULL : ellipsize(name, 25, 33);
952 printf("%4u %-25s %-15s %-7s\n", id, e ? e : name, type, state);
957 dbus_message_iter_next(&sub);
961 printf("\n%u jobs listed.\n", k);
966 static int load_unit(DBusConnection *bus, char **args) {
971 STRV_FOREACH(name, args+1) {
972 _cleanup_free_ char *n = NULL;
975 n = unit_name_mangle(*name);
979 r = bus_method_call_with_reply(
981 "org.freedesktop.systemd1",
982 "/org/freedesktop/systemd1",
983 "org.freedesktop.systemd1.Manager",
987 DBUS_TYPE_STRING, &n,
996 static int cancel_job(DBusConnection *bus, char **args) {
1001 if (strv_length(args) <= 1)
1002 return daemon_reload(bus, args);
1004 STRV_FOREACH(name, args+1) {
1008 r = safe_atou32(*name, &id);
1010 log_error("Failed to parse job id: %s", strerror(-r));
1014 r = bus_method_call_with_reply(
1016 "org.freedesktop.systemd1",
1017 "/org/freedesktop/systemd1",
1018 "org.freedesktop.systemd1.Manager",
1022 DBUS_TYPE_UINT32, &id,
1031 static bool need_daemon_reload(DBusConnection *bus, const char *unit) {
1032 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1033 dbus_bool_t b = FALSE;
1034 DBusMessageIter iter, sub;
1036 *interface = "org.freedesktop.systemd1.Unit",
1037 *property = "NeedDaemonReload",
1039 _cleanup_free_ char *n = NULL;
1042 /* We ignore all errors here, since this is used to show a warning only */
1044 n = unit_name_mangle(unit);
1048 r = bus_method_call_with_reply (
1050 "org.freedesktop.systemd1",
1051 "/org/freedesktop/systemd1",
1052 "org.freedesktop.systemd1.Manager",
1056 DBUS_TYPE_STRING, &n,
1061 if (!dbus_message_get_args(reply, NULL,
1062 DBUS_TYPE_OBJECT_PATH, &path,
1066 dbus_message_unref(reply);
1069 r = bus_method_call_with_reply(
1071 "org.freedesktop.systemd1",
1073 "org.freedesktop.DBus.Properties",
1077 DBUS_TYPE_STRING, &interface,
1078 DBUS_TYPE_STRING, &property,
1083 if (!dbus_message_iter_init(reply, &iter) ||
1084 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
1087 dbus_message_iter_recurse(&iter, &sub);
1088 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_BOOLEAN)
1091 dbus_message_iter_get_basic(&sub, &b);
1095 typedef struct WaitData {
1102 static DBusHandlerResult wait_filter(DBusConnection *connection, DBusMessage *message, void *data) {
1110 dbus_error_init(&error);
1112 log_debug("Got D-Bus request: %s.%s() on %s",
1113 dbus_message_get_interface(message),
1114 dbus_message_get_member(message),
1115 dbus_message_get_path(message));
1117 if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
1118 log_error("Warning! D-Bus connection terminated.");
1119 dbus_connection_close(connection);
1121 } else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
1123 const char *path, *result, *unit;
1125 if (dbus_message_get_args(message, &error,
1126 DBUS_TYPE_UINT32, &id,
1127 DBUS_TYPE_OBJECT_PATH, &path,
1128 DBUS_TYPE_STRING, &unit,
1129 DBUS_TYPE_STRING, &result,
1130 DBUS_TYPE_INVALID)) {
1132 free(set_remove(d->set, (char*) path));
1134 if (!isempty(result))
1135 d->result = strdup(result);
1138 d->name = strdup(unit);
1143 dbus_error_free(&error);
1144 if (dbus_message_get_args(message, &error,
1145 DBUS_TYPE_UINT32, &id,
1146 DBUS_TYPE_OBJECT_PATH, &path,
1147 DBUS_TYPE_STRING, &result,
1148 DBUS_TYPE_INVALID)) {
1149 /* Compatibility with older systemd versions <
1150 * 183 during upgrades. This should be dropped
1152 free(set_remove(d->set, (char*) path));
1155 d->result = strdup(result);
1161 log_error("Failed to parse message: %s", bus_error_message(&error));
1165 dbus_error_free(&error);
1166 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1169 static int enable_wait_for_jobs(DBusConnection *bus) {
1177 dbus_error_init(&error);
1178 dbus_bus_add_match(bus,
1180 "sender='org.freedesktop.systemd1',"
1181 "interface='org.freedesktop.systemd1.Manager',"
1182 "member='JobRemoved',"
1183 "path='/org/freedesktop/systemd1'",
1186 if (dbus_error_is_set(&error)) {
1187 log_error("Failed to add match: %s", bus_error_message(&error));
1188 dbus_error_free(&error);
1192 /* This is slightly dirty, since we don't undo the match registrations. */
1196 static int wait_for_jobs(DBusConnection *bus, Set *s) {
1206 if (!dbus_connection_add_filter(bus, wait_filter, &d, NULL))
1209 while (!set_isempty(s)) {
1211 if (!dbus_connection_read_write_dispatch(bus, -1)) {
1212 log_error("Disconnected from bus.");
1213 return -ECONNREFUSED;
1220 if (streq(d.result, "timeout"))
1221 log_error("Job for %s timed out.", strna(d.name));
1222 else if (streq(d.result, "canceled"))
1223 log_error("Job for %s canceled.", strna(d.name));
1224 else if (streq(d.result, "dependency"))
1225 log_error("A dependency job for %s failed. See 'journalctl -xn' for details.", strna(d.name));
1226 else if (!streq(d.result, "done") && !streq(d.result, "skipped"))
1227 log_error("Job for %s failed. See 'systemctl status %s' and 'journalctl -xn' for details.", strna(d.name), strna(d.name));
1230 if (streq_ptr(d.result, "timeout"))
1232 else if (streq_ptr(d.result, "canceled"))
1234 else if (!streq_ptr(d.result, "done") && !streq_ptr(d.result, "skipped"))
1245 dbus_connection_remove_filter(bus, wait_filter, &d);
1249 static int check_one_unit(DBusConnection *bus, const char *name, char **check_states, bool quiet) {
1250 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1251 _cleanup_free_ char *n = NULL;
1252 DBusMessageIter iter, sub;
1254 *interface = "org.freedesktop.systemd1.Unit",
1255 *property = "ActiveState";
1256 const char *state, *path;
1262 dbus_error_init(&error);
1264 n = unit_name_mangle(name);
1268 r = bus_method_call_with_reply (
1270 "org.freedesktop.systemd1",
1271 "/org/freedesktop/systemd1",
1272 "org.freedesktop.systemd1.Manager",
1276 DBUS_TYPE_STRING, &n,
1279 dbus_error_free(&error);
1286 if (!dbus_message_get_args(reply, NULL,
1287 DBUS_TYPE_OBJECT_PATH, &path,
1288 DBUS_TYPE_INVALID)) {
1289 log_error("Failed to parse reply.");
1293 dbus_message_unref(reply);
1296 r = bus_method_call_with_reply(
1298 "org.freedesktop.systemd1",
1300 "org.freedesktop.DBus.Properties",
1304 DBUS_TYPE_STRING, &interface,
1305 DBUS_TYPE_STRING, &property,
1313 if (!dbus_message_iter_init(reply, &iter) ||
1314 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1315 log_error("Failed to parse reply.");
1319 dbus_message_iter_recurse(&iter, &sub);
1321 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1322 log_error("Failed to parse reply.");
1326 dbus_message_iter_get_basic(&sub, &state);
1331 return strv_find(check_states, state) ? 1 : 0;
1334 static void check_triggering_units(
1335 DBusConnection *bus,
1336 const char *unit_name) {
1338 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1339 DBusMessageIter iter, sub;
1340 const char *interface = "org.freedesktop.systemd1.Unit",
1341 *triggered_by_property = "TriggeredBy";
1342 char _cleanup_free_ *unit_path = NULL, *n = NULL;
1343 bool print_warning_label = true;
1346 n = unit_name_mangle(unit_name);
1352 unit_path = unit_dbus_path_from_name(n);
1358 r = bus_method_call_with_reply(
1360 "org.freedesktop.systemd1",
1362 "org.freedesktop.DBus.Properties",
1366 DBUS_TYPE_STRING, &interface,
1367 DBUS_TYPE_STRING, &triggered_by_property,
1372 if (!dbus_message_iter_init(reply, &iter) ||
1373 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1374 log_error("Failed to parse reply.");
1378 dbus_message_iter_recurse(&iter, &sub);
1379 dbus_message_iter_recurse(&sub, &iter);
1382 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1383 const char * const check_states[] = {
1388 const char *service_trigger;
1390 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1391 log_error("Failed to parse reply.");
1395 dbus_message_iter_get_basic(&sub, &service_trigger);
1397 r = check_one_unit(bus, service_trigger, (char**) check_states, true);
1401 if (print_warning_label) {
1402 log_warning("Warning: Stopping %s, but it can still be activated by:", unit_name);
1403 print_warning_label = false;
1406 log_warning(" %s", service_trigger);
1409 dbus_message_iter_next(&sub);
1413 static int start_unit_one(
1414 DBusConnection *bus,
1421 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1422 _cleanup_free_ char *n;
1431 n = unit_name_mangle(name);
1435 r = bus_method_call_with_reply(
1437 "org.freedesktop.systemd1",
1438 "/org/freedesktop/systemd1",
1439 "org.freedesktop.systemd1.Manager",
1443 DBUS_TYPE_STRING, &n,
1444 DBUS_TYPE_STRING, &mode,
1447 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
1448 /* There's always a fallback possible for
1449 * legacy actions. */
1452 log_error("Failed to issue method call: %s", bus_error_message(error));
1457 if (!dbus_message_get_args(reply, error,
1458 DBUS_TYPE_OBJECT_PATH, &path,
1459 DBUS_TYPE_INVALID)) {
1460 log_error("Failed to parse reply: %s", bus_error_message(error));
1464 if (need_daemon_reload(bus, n))
1465 log_warning("Warning: Unit file of %s changed on disk, 'systemctl %s daemon-reload' recommended.",
1466 n, arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
1478 log_error("Failed to add path to set.");
1486 static enum action verb_to_action(const char *verb) {
1487 if (streq(verb, "halt"))
1489 else if (streq(verb, "poweroff"))
1490 return ACTION_POWEROFF;
1491 else if (streq(verb, "reboot"))
1492 return ACTION_REBOOT;
1493 else if (streq(verb, "kexec"))
1494 return ACTION_KEXEC;
1495 else if (streq(verb, "rescue"))
1496 return ACTION_RESCUE;
1497 else if (streq(verb, "emergency"))
1498 return ACTION_EMERGENCY;
1499 else if (streq(verb, "default"))
1500 return ACTION_DEFAULT;
1501 else if (streq(verb, "exit"))
1503 else if (streq(verb, "suspend"))
1504 return ACTION_SUSPEND;
1505 else if (streq(verb, "hibernate"))
1506 return ACTION_HIBERNATE;
1507 else if (streq(verb, "hybrid-sleep"))
1508 return ACTION_HYBRID_SLEEP;
1510 return ACTION_INVALID;
1513 static int start_unit(DBusConnection *bus, char **args) {
1515 static const char * const table[_ACTION_MAX] = {
1516 [ACTION_HALT] = SPECIAL_HALT_TARGET,
1517 [ACTION_POWEROFF] = SPECIAL_POWEROFF_TARGET,
1518 [ACTION_REBOOT] = SPECIAL_REBOOT_TARGET,
1519 [ACTION_KEXEC] = SPECIAL_KEXEC_TARGET,
1520 [ACTION_RUNLEVEL2] = SPECIAL_RUNLEVEL2_TARGET,
1521 [ACTION_RUNLEVEL3] = SPECIAL_RUNLEVEL3_TARGET,
1522 [ACTION_RUNLEVEL4] = SPECIAL_RUNLEVEL4_TARGET,
1523 [ACTION_RUNLEVEL5] = SPECIAL_RUNLEVEL5_TARGET,
1524 [ACTION_RESCUE] = SPECIAL_RESCUE_TARGET,
1525 [ACTION_EMERGENCY] = SPECIAL_EMERGENCY_TARGET,
1526 [ACTION_DEFAULT] = SPECIAL_DEFAULT_TARGET,
1527 [ACTION_EXIT] = SPECIAL_EXIT_TARGET,
1528 [ACTION_SUSPEND] = SPECIAL_SUSPEND_TARGET,
1529 [ACTION_HIBERNATE] = SPECIAL_HIBERNATE_TARGET,
1530 [ACTION_HYBRID_SLEEP] = SPECIAL_HYBRID_SLEEP_TARGET
1534 const char *method, *mode, *one_name;
1539 dbus_error_init(&error);
1543 ask_password_agent_open_if_enabled();
1545 if (arg_action == ACTION_SYSTEMCTL) {
1547 streq(args[0], "stop") ||
1548 streq(args[0], "condstop") ? "StopUnit" :
1549 streq(args[0], "reload") ? "ReloadUnit" :
1550 streq(args[0], "restart") ? "RestartUnit" :
1552 streq(args[0], "try-restart") ||
1553 streq(args[0], "condrestart") ? "TryRestartUnit" :
1555 streq(args[0], "reload-or-restart") ? "ReloadOrRestartUnit" :
1557 streq(args[0], "reload-or-try-restart") ||
1558 streq(args[0], "condreload") ||
1560 streq(args[0], "force-reload") ? "ReloadOrTryRestartUnit" :
1564 (streq(args[0], "isolate") ||
1565 streq(args[0], "rescue") ||
1566 streq(args[0], "emergency")) ? "isolate" : arg_job_mode;
1568 one_name = table[verb_to_action(args[0])];
1571 assert(arg_action < ELEMENTSOF(table));
1572 assert(table[arg_action]);
1574 method = "StartUnit";
1576 mode = (arg_action == ACTION_EMERGENCY ||
1577 arg_action == ACTION_RESCUE ||
1578 arg_action == ACTION_RUNLEVEL2 ||
1579 arg_action == ACTION_RUNLEVEL3 ||
1580 arg_action == ACTION_RUNLEVEL4 ||
1581 arg_action == ACTION_RUNLEVEL5) ? "isolate" : "replace";
1583 one_name = table[arg_action];
1586 if (!arg_no_block) {
1587 ret = enable_wait_for_jobs(bus);
1589 log_error("Could not watch jobs: %s", strerror(-ret));
1593 s = set_new(string_hash_func, string_compare_func);
1601 ret = start_unit_one(bus, method, one_name, mode, &error, s);
1603 ret = translate_bus_error_to_exit_status(ret, &error);
1605 STRV_FOREACH(name, args+1) {
1606 r = start_unit_one(bus, method, *name, mode, &error, s);
1608 ret = translate_bus_error_to_exit_status(r, &error);
1609 dbus_error_free(&error);
1614 if (!arg_no_block) {
1615 r = wait_for_jobs(bus, s);
1621 /* When stopping units, warn if they can still be triggered by
1622 * another active unit (socket, path, timer) */
1623 if (!arg_quiet && streq(method, "StopUnit")) {
1625 check_triggering_units(bus, one_name);
1627 STRV_FOREACH(name, args+1)
1628 check_triggering_units(bus, *name);
1634 dbus_error_free(&error);
1639 /* Ask systemd-logind, which might grant access to unprivileged users
1640 * through PolicyKit */
1641 static int reboot_with_logind(DBusConnection *bus, enum action a) {
1644 dbus_bool_t interactive = true;
1649 polkit_agent_open_if_enabled();
1657 case ACTION_POWEROFF:
1658 method = "PowerOff";
1661 case ACTION_SUSPEND:
1665 case ACTION_HIBERNATE:
1666 method = "Hibernate";
1669 case ACTION_HYBRID_SLEEP:
1670 method = "HybridSleep";
1677 return bus_method_call_with_reply(
1679 "org.freedesktop.login1",
1680 "/org/freedesktop/login1",
1681 "org.freedesktop.login1.Manager",
1685 DBUS_TYPE_BOOLEAN, &interactive,
1692 static int check_inhibitors(DBusConnection *bus, enum action a) {
1694 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1695 DBusMessageIter iter, sub, sub2;
1698 _cleanup_strv_free_ char **sessions = NULL;
1704 if (arg_ignore_inhibitors || arg_force > 0)
1716 r = bus_method_call_with_reply(
1718 "org.freedesktop.login1",
1719 "/org/freedesktop/login1",
1720 "org.freedesktop.login1.Manager",
1726 /* If logind is not around, then there are no inhibitors... */
1729 if (!dbus_message_iter_init(reply, &iter) ||
1730 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
1731 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
1732 log_error("Failed to parse reply.");
1736 dbus_message_iter_recurse(&iter, &sub);
1737 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1738 const char *what, *who, *why, *mode;
1740 _cleanup_strv_free_ char **sv = NULL;
1741 _cleanup_free_ char *comm = NULL, *user = NULL;
1743 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
1744 log_error("Failed to parse reply.");
1748 dbus_message_iter_recurse(&sub, &sub2);
1750 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &what, true) < 0 ||
1751 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &who, true) < 0 ||
1752 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &why, true) < 0 ||
1753 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &mode, true) < 0 ||
1754 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &uid, true) < 0 ||
1755 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, false) < 0) {
1756 log_error("Failed to parse reply.");
1760 if (!streq(mode, "block"))
1763 sv = strv_split(what, ":");
1767 if (!strv_contains(sv,
1769 a == ACTION_POWEROFF ||
1770 a == ACTION_REBOOT ||
1771 a == ACTION_KEXEC ? "shutdown" : "sleep"))
1774 get_process_comm(pid, &comm);
1775 user = uid_to_name(uid);
1776 log_warning("Operation inhibited by \"%s\" (PID %lu \"%s\", user %s), reason is \"%s\".",
1777 who, (unsigned long) pid, strna(comm), strna(user), why);
1781 dbus_message_iter_next(&sub);
1784 dbus_message_iter_recurse(&iter, &sub);
1786 /* Check for current sessions */
1787 sd_get_sessions(&sessions);
1788 STRV_FOREACH(s, sessions) {
1790 _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL;
1792 if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid())
1795 if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
1798 if (sd_session_get_type(*s, &type) < 0 || (!streq(type, "x11") && !streq(type, "tty")))
1801 sd_session_get_tty(*s, &tty);
1802 sd_session_get_seat(*s, &seat);
1803 sd_session_get_service(*s, &service);
1804 user = uid_to_name(uid);
1806 log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty);
1813 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
1814 a == ACTION_HALT ? "halt" :
1815 a == ACTION_POWEROFF ? "poweroff" :
1816 a == ACTION_REBOOT ? "reboot" :
1817 a == ACTION_KEXEC ? "kexec" :
1818 a == ACTION_SUSPEND ? "suspend" :
1819 a == ACTION_HIBERNATE ? "hibernate" : "hybrid-sleep");
1827 static int start_special(DBusConnection *bus, char **args) {
1833 a = verb_to_action(args[0]);
1835 r = check_inhibitors(bus, a);
1839 if (arg_force >= 2 && geteuid() != 0) {
1840 log_error("Must be root.");
1844 if (arg_force >= 2 &&
1845 (a == ACTION_HALT ||
1846 a == ACTION_POWEROFF ||
1847 a == ACTION_REBOOT))
1850 if (arg_force >= 1 &&
1851 (a == ACTION_HALT ||
1852 a == ACTION_POWEROFF ||
1853 a == ACTION_REBOOT ||
1854 a == ACTION_KEXEC ||
1856 return daemon_reload(bus, args);
1858 /* first try logind, to allow authentication with polkit */
1859 if (geteuid() != 0 &&
1860 (a == ACTION_POWEROFF ||
1861 a == ACTION_REBOOT ||
1862 a == ACTION_SUSPEND ||
1863 a == ACTION_HIBERNATE ||
1864 a == ACTION_HYBRID_SLEEP)) {
1865 r = reboot_with_logind(bus, a);
1870 r = start_unit(bus, args);
1877 static int check_unit_active(DBusConnection *bus, char **args) {
1878 const char * const check_states[] = {
1885 int r = 3; /* According to LSB: "program is not running" */
1890 STRV_FOREACH(name, args+1) {
1893 state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
1903 static int check_unit_failed(DBusConnection *bus, char **args) {
1904 const char * const check_states[] = {
1915 STRV_FOREACH(name, args+1) {
1918 state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
1928 static int kill_unit(DBusConnection *bus, char **args) {
1936 arg_kill_who = "all";
1938 STRV_FOREACH(name, args+1) {
1939 _cleanup_free_ char *n = NULL;
1941 n = unit_name_mangle(*name);
1945 r = bus_method_call_with_reply(
1947 "org.freedesktop.systemd1",
1948 "/org/freedesktop/systemd1",
1949 "org.freedesktop.systemd1.Manager",
1953 DBUS_TYPE_STRING, &n,
1954 DBUS_TYPE_STRING, &arg_kill_who,
1955 DBUS_TYPE_INT32, &arg_signal,
1963 static int set_cgroup(DBusConnection *bus, char **args) {
1964 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
1967 DBusMessageIter iter;
1969 _cleanup_free_ char *n = NULL;
1974 dbus_error_init(&error);
1977 streq(args[0], "set-cgroup") ? "SetUnitControlGroups" :
1978 streq(args[0], "unset-group") ? "UnsetUnitControlGroups"
1979 : "UnsetUnitControlGroupAttributes";
1981 n = unit_name_mangle(args[1]);
1985 m = dbus_message_new_method_call(
1986 "org.freedesktop.systemd1",
1987 "/org/freedesktop/systemd1",
1988 "org.freedesktop.systemd1.Manager",
1993 dbus_message_iter_init_append(m, &iter);
1994 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &n))
1997 r = bus_append_strv_iter(&iter, args + 2);
2001 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
2003 log_error("Failed to issue method call: %s", bus_error_message(&error));
2004 dbus_error_free(&error);
2011 static int set_cgroup_attr(DBusConnection *bus, char **args) {
2012 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
2014 DBusMessageIter iter, sub, sub2;
2016 _cleanup_free_ char *n = NULL;
2021 dbus_error_init(&error);
2023 if (strv_length(args) % 2 != 0) {
2024 log_error("Expecting an uneven number of arguments!");
2028 n = unit_name_mangle(args[1]);
2032 m = dbus_message_new_method_call(
2033 "org.freedesktop.systemd1",
2034 "/org/freedesktop/systemd1",
2035 "org.freedesktop.systemd1.Manager",
2036 "SetUnitControlGroupAttributes");
2040 dbus_message_iter_init_append(m, &iter);
2041 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &n) ||
2042 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ss)", &sub))
2045 STRV_FOREACH_PAIR(x, y, args + 2) {
2046 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
2047 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, x) ||
2048 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, y) ||
2049 !dbus_message_iter_close_container(&sub, &sub2))
2053 if (!dbus_message_iter_close_container(&iter, &sub))
2056 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
2058 log_error("Failed to issue method call: %s", bus_error_message(&error));
2059 dbus_error_free(&error);
2066 typedef struct ExecStatusInfo {
2074 usec_t start_timestamp;
2075 usec_t exit_timestamp;
2080 LIST_FIELDS(struct ExecStatusInfo, exec);
2083 static void exec_status_info_free(ExecStatusInfo *i) {
2092 static int exec_status_info_deserialize(DBusMessageIter *sub, ExecStatusInfo *i) {
2093 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
2094 DBusMessageIter sub2, sub3;
2098 int32_t code, status;
2104 if (dbus_message_iter_get_arg_type(sub) != DBUS_TYPE_STRUCT)
2107 dbus_message_iter_recurse(sub, &sub2);
2109 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0)
2112 i->path = strdup(path);
2116 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_ARRAY ||
2117 dbus_message_iter_get_element_type(&sub2) != DBUS_TYPE_STRING)
2121 dbus_message_iter_recurse(&sub2, &sub3);
2122 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2123 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2124 dbus_message_iter_next(&sub3);
2128 i->argv = new0(char*, n+1);
2133 dbus_message_iter_recurse(&sub2, &sub3);
2134 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2137 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2138 dbus_message_iter_get_basic(&sub3, &s);
2139 dbus_message_iter_next(&sub3);
2141 i->argv[n] = strdup(s);
2148 if (!dbus_message_iter_next(&sub2) ||
2149 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, true) < 0 ||
2150 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp, true) < 0 ||
2151 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp_monotonic, true) < 0 ||
2152 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp, true) < 0 ||
2153 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp_monotonic, true) < 0 ||
2154 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, true) < 0 ||
2155 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &code, true) < 0 ||
2156 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &status, false) < 0)
2160 i->start_timestamp = (usec_t) start_timestamp;
2161 i->exit_timestamp = (usec_t) exit_timestamp;
2162 i->pid = (pid_t) pid;
2169 typedef struct UnitStatusInfo {
2171 const char *load_state;
2172 const char *active_state;
2173 const char *sub_state;
2174 const char *unit_file_state;
2176 const char *description;
2177 const char *following;
2179 char **documentation;
2181 const char *fragment_path;
2182 const char *source_path;
2183 const char *default_control_group;
2185 const char *load_error;
2188 usec_t inactive_exit_timestamp;
2189 usec_t inactive_exit_timestamp_monotonic;
2190 usec_t active_enter_timestamp;
2191 usec_t active_exit_timestamp;
2192 usec_t inactive_enter_timestamp;
2194 bool need_daemon_reload;
2199 const char *status_text;
2202 usec_t start_timestamp;
2203 usec_t exit_timestamp;
2205 int exit_code, exit_status;
2207 usec_t condition_timestamp;
2208 bool condition_result;
2211 unsigned n_accepted;
2212 unsigned n_connections;
2216 const char *sysfs_path;
2218 /* Mount, Automount */
2224 LIST_HEAD(ExecStatusInfo, exec);
2227 static void print_status_info(UnitStatusInfo *i) {
2229 const char *on, *off, *ss;
2231 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
2232 char since2[FORMAT_TIMESTAMP_MAX], *s2;
2235 arg_all * OUTPUT_SHOW_ALL |
2236 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
2237 on_tty() * OUTPUT_COLOR |
2238 !arg_quiet * OUTPUT_WARN_CUTOFF |
2239 arg_full * OUTPUT_FULL_WIDTH;
2243 /* This shows pretty information about a unit. See
2244 * print_property() for a low-level property printer */
2246 printf("%s", strna(i->id));
2248 if (i->description && !streq_ptr(i->id, i->description))
2249 printf(" - %s", i->description);
2254 printf("\t Follow: unit currently follows state of %s\n", i->following);
2256 if (streq_ptr(i->load_state, "error")) {
2257 on = ansi_highlight_red(true);
2258 off = ansi_highlight_red(false);
2262 path = i->source_path ? i->source_path : i->fragment_path;
2265 printf("\t Loaded: %s%s%s (Reason: %s)\n", on, strna(i->load_state), off, i->load_error);
2266 else if (path && i->unit_file_state)
2267 printf("\t Loaded: %s%s%s (%s; %s)\n", on, strna(i->load_state), off, path, i->unit_file_state);
2269 printf("\t Loaded: %s%s%s (%s)\n", on, strna(i->load_state), off, path);
2271 printf("\t Loaded: %s%s%s\n", on, strna(i->load_state), off);
2273 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
2275 if (streq_ptr(i->active_state, "failed")) {
2276 on = ansi_highlight_red(true);
2277 off = ansi_highlight_red(false);
2278 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
2279 on = ansi_highlight_green(true);
2280 off = ansi_highlight_green(false);
2285 printf("\t Active: %s%s (%s)%s",
2287 strna(i->active_state),
2291 printf("\t Active: %s%s%s",
2293 strna(i->active_state),
2296 if (!isempty(i->result) && !streq(i->result, "success"))
2297 printf(" (Result: %s)", i->result);
2299 timestamp = (streq_ptr(i->active_state, "active") ||
2300 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
2301 (streq_ptr(i->active_state, "inactive") ||
2302 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
2303 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
2304 i->active_exit_timestamp;
2306 s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
2307 s2 = format_timestamp(since2, sizeof(since2), timestamp);
2310 printf(" since %s; %s\n", s2, s1);
2312 printf(" since %s\n", s2);
2316 if (!i->condition_result && i->condition_timestamp > 0) {
2317 s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
2318 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
2321 printf("\t start condition failed at %s; %s\n", s2, s1);
2323 printf("\t start condition failed at %s\n", s2);
2327 printf("\t Device: %s\n", i->sysfs_path);
2329 printf("\t Where: %s\n", i->where);
2331 printf("\t What: %s\n", i->what);
2333 if (!strv_isempty(i->documentation)) {
2337 STRV_FOREACH(t, i->documentation) {
2339 printf("\t Docs: %s\n", *t);
2342 printf("\t %s\n", *t);
2347 printf("\tAccepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
2349 LIST_FOREACH(exec, p, i->exec) {
2350 _cleanup_free_ char *t = NULL;
2353 /* Only show exited processes here */
2357 t = strv_join(p->argv, " ");
2358 printf("\t Process: %u %s=%s ", p->pid, p->name, strna(t));
2360 good = is_clean_exit_lsb(p->code, p->status, NULL);
2362 on = ansi_highlight_red(true);
2363 off = ansi_highlight_red(false);
2367 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
2369 if (p->code == CLD_EXITED) {
2372 printf("status=%i", p->status);
2374 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
2379 printf("signal=%s", signal_to_string(p->status));
2381 printf(")%s\n", off);
2383 if (i->main_pid == p->pid &&
2384 i->start_timestamp == p->start_timestamp &&
2385 i->exit_timestamp == p->start_timestamp)
2386 /* Let's not show this twice */
2389 if (p->pid == i->control_pid)
2393 if (i->main_pid > 0 || i->control_pid > 0) {
2396 if (i->main_pid > 0) {
2397 printf("Main PID: %u", (unsigned) i->main_pid);
2400 _cleanup_free_ char *t = NULL;
2401 get_process_comm(i->main_pid, &t);
2404 } else if (i->exit_code > 0) {
2405 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
2407 if (i->exit_code == CLD_EXITED) {
2410 printf("status=%i", i->exit_status);
2412 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
2417 printf("signal=%s", signal_to_string(i->exit_status));
2422 if (i->main_pid > 0 && i->control_pid > 0)
2425 if (i->control_pid > 0) {
2426 _cleanup_free_ char *t = NULL;
2428 printf(" Control: %u", (unsigned) i->control_pid);
2430 get_process_comm(i->control_pid, &t);
2439 printf("\t Status: \"%s\"\n", i->status_text);
2441 if (i->default_control_group &&
2442 (i->main_pid > 0 || i->control_pid > 0 || cg_is_empty_by_spec(i->default_control_group, false) == 0)) {
2445 printf("\t CGroup: %s\n", i->default_control_group);
2447 if (arg_transport != TRANSPORT_SSH) {
2457 if (i->main_pid > 0)
2458 extra[k++] = i->main_pid;
2460 if (i->control_pid > 0)
2461 extra[k++] = i->control_pid;
2463 show_cgroup_and_extra_by_spec(i->default_control_group, "\t\t ", c, false, extra, k, flags);
2467 if (i->id && arg_transport != TRANSPORT_SSH) {
2469 show_journal_by_unit(stdout,
2473 i->inactive_exit_timestamp_monotonic,
2478 if (i->need_daemon_reload)
2479 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %s daemon-reload' recommended.\n",
2480 ansi_highlight_red(true),
2481 ansi_highlight_red(false),
2482 arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
2485 static void show_unit_help(UnitStatusInfo *i) {
2490 if (!i->documentation) {
2491 log_info("Documentation for %s not known.", i->id);
2495 STRV_FOREACH(p, i->documentation) {
2497 if (startswith(*p, "man:")) {
2500 char *page = NULL, *section = NULL;
2501 const char *args[4] = { "man", NULL, NULL, NULL };
2506 if ((*p)[k-1] == ')')
2507 e = strrchr(*p, '(');
2510 page = strndup((*p) + 4, e - *p - 4);
2516 section = strndup(e + 1, *p + k - e - 2);
2530 log_error("Failed to fork: %m");
2538 execvp(args[0], (char**) args);
2539 log_error("Failed to execute man: %m");
2540 _exit(EXIT_FAILURE);
2546 wait_for_terminate(pid, NULL);
2548 log_info("Can't show: %s", *p);
2552 static int status_property(const char *name, DBusMessageIter *iter, UnitStatusInfo *i) {
2558 switch (dbus_message_iter_get_arg_type(iter)) {
2560 case DBUS_TYPE_STRING: {
2563 dbus_message_iter_get_basic(iter, &s);
2566 if (streq(name, "Id"))
2568 else if (streq(name, "LoadState"))
2570 else if (streq(name, "ActiveState"))
2571 i->active_state = s;
2572 else if (streq(name, "SubState"))
2574 else if (streq(name, "Description"))
2576 else if (streq(name, "FragmentPath"))
2577 i->fragment_path = s;
2578 else if (streq(name, "SourcePath"))
2580 else if (streq(name, "DefaultControlGroup"))
2581 i->default_control_group = s;
2582 else if (streq(name, "StatusText"))
2584 else if (streq(name, "SysFSPath"))
2586 else if (streq(name, "Where"))
2588 else if (streq(name, "What"))
2590 else if (streq(name, "Following"))
2592 else if (streq(name, "UnitFileState"))
2593 i->unit_file_state = s;
2594 else if (streq(name, "Result"))
2601 case DBUS_TYPE_BOOLEAN: {
2604 dbus_message_iter_get_basic(iter, &b);
2606 if (streq(name, "Accept"))
2608 else if (streq(name, "NeedDaemonReload"))
2609 i->need_daemon_reload = b;
2610 else if (streq(name, "ConditionResult"))
2611 i->condition_result = b;
2616 case DBUS_TYPE_UINT32: {
2619 dbus_message_iter_get_basic(iter, &u);
2621 if (streq(name, "MainPID")) {
2623 i->main_pid = (pid_t) u;
2626 } else if (streq(name, "ControlPID"))
2627 i->control_pid = (pid_t) u;
2628 else if (streq(name, "ExecMainPID")) {
2630 i->main_pid = (pid_t) u;
2631 } else if (streq(name, "NAccepted"))
2633 else if (streq(name, "NConnections"))
2634 i->n_connections = u;
2639 case DBUS_TYPE_INT32: {
2642 dbus_message_iter_get_basic(iter, &j);
2644 if (streq(name, "ExecMainCode"))
2645 i->exit_code = (int) j;
2646 else if (streq(name, "ExecMainStatus"))
2647 i->exit_status = (int) j;
2652 case DBUS_TYPE_UINT64: {
2655 dbus_message_iter_get_basic(iter, &u);
2657 if (streq(name, "ExecMainStartTimestamp"))
2658 i->start_timestamp = (usec_t) u;
2659 else if (streq(name, "ExecMainExitTimestamp"))
2660 i->exit_timestamp = (usec_t) u;
2661 else if (streq(name, "ActiveEnterTimestamp"))
2662 i->active_enter_timestamp = (usec_t) u;
2663 else if (streq(name, "InactiveEnterTimestamp"))
2664 i->inactive_enter_timestamp = (usec_t) u;
2665 else if (streq(name, "InactiveExitTimestamp"))
2666 i->inactive_exit_timestamp = (usec_t) u;
2667 else if (streq(name, "InactiveExitTimestampMonotonic"))
2668 i->inactive_exit_timestamp_monotonic = (usec_t) u;
2669 else if (streq(name, "ActiveExitTimestamp"))
2670 i->active_exit_timestamp = (usec_t) u;
2671 else if (streq(name, "ConditionTimestamp"))
2672 i->condition_timestamp = (usec_t) u;
2677 case DBUS_TYPE_ARRAY: {
2679 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
2680 startswith(name, "Exec")) {
2681 DBusMessageIter sub;
2683 dbus_message_iter_recurse(iter, &sub);
2684 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2685 ExecStatusInfo *info;
2688 if (!(info = new0(ExecStatusInfo, 1)))
2691 if (!(info->name = strdup(name))) {
2696 if ((r = exec_status_info_deserialize(&sub, info)) < 0) {
2701 LIST_PREPEND(ExecStatusInfo, exec, i->exec, info);
2703 dbus_message_iter_next(&sub);
2705 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
2706 streq(name, "Documentation")) {
2708 DBusMessageIter sub;
2710 dbus_message_iter_recurse(iter, &sub);
2711 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING) {
2715 dbus_message_iter_get_basic(&sub, &s);
2717 l = strv_append(i->documentation, s);
2721 strv_free(i->documentation);
2722 i->documentation = l;
2724 dbus_message_iter_next(&sub);
2731 case DBUS_TYPE_STRUCT: {
2733 if (streq(name, "LoadError")) {
2734 DBusMessageIter sub;
2735 const char *n, *message;
2738 dbus_message_iter_recurse(iter, &sub);
2740 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &n, true);
2744 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &message, false);
2748 if (!isempty(message))
2749 i->load_error = message;
2759 static int print_property(const char *name, DBusMessageIter *iter) {
2763 /* This is a low-level property printer, see
2764 * print_status_info() for the nicer output */
2766 if (arg_property && !strv_find(arg_property, name))
2769 switch (dbus_message_iter_get_arg_type(iter)) {
2771 case DBUS_TYPE_STRUCT: {
2772 DBusMessageIter sub;
2773 dbus_message_iter_recurse(iter, &sub);
2775 if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32 && streq(name, "Job")) {
2778 dbus_message_iter_get_basic(&sub, &u);
2781 printf("%s=%u\n", name, (unsigned) u);
2783 printf("%s=\n", name);
2786 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "Unit")) {
2789 dbus_message_iter_get_basic(&sub, &s);
2791 if (arg_all || s[0])
2792 printf("%s=%s\n", name, s);
2795 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "LoadError")) {
2796 const char *a = NULL, *b = NULL;
2798 if (bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &a, true) >= 0)
2799 bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &b, false);
2801 if (arg_all || !isempty(a) || !isempty(b))
2802 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
2810 case DBUS_TYPE_ARRAY:
2812 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "EnvironmentFiles")) {
2813 DBusMessageIter sub, sub2;
2815 dbus_message_iter_recurse(iter, &sub);
2816 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2820 dbus_message_iter_recurse(&sub, &sub2);
2822 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
2823 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) >= 0)
2824 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
2826 dbus_message_iter_next(&sub);
2831 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Paths")) {
2832 DBusMessageIter sub, sub2;
2834 dbus_message_iter_recurse(iter, &sub);
2835 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2836 const char *type, *path;
2838 dbus_message_iter_recurse(&sub, &sub2);
2840 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
2841 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
2842 printf("%s=%s\n", type, path);
2844 dbus_message_iter_next(&sub);
2849 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Timers")) {
2850 DBusMessageIter sub, sub2;
2852 dbus_message_iter_recurse(iter, &sub);
2853 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2855 uint64_t value, next_elapse;
2857 dbus_message_iter_recurse(&sub, &sub2);
2859 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &base, true) >= 0 &&
2860 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &value, true) >= 0 &&
2861 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &next_elapse, false) >= 0) {
2862 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
2864 printf("%s={ value=%s ; next_elapse=%s }\n",
2866 format_timespan(timespan1, sizeof(timespan1), value),
2867 format_timespan(timespan2, sizeof(timespan2), next_elapse));
2870 dbus_message_iter_next(&sub);
2875 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "ControlGroupAttributes")) {
2876 DBusMessageIter sub, sub2;
2878 dbus_message_iter_recurse(iter, &sub);
2879 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2880 const char *controller, *attr, *value;
2882 dbus_message_iter_recurse(&sub, &sub2);
2884 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &controller, true) >= 0 &&
2885 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &attr, true) >= 0 &&
2886 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &value, false) >= 0) {
2888 printf("ControlGroupAttribute={ controller=%s ; attribute=%s ; value=\"%s\" }\n",
2894 dbus_message_iter_next(&sub);
2899 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && startswith(name, "Exec")) {
2900 DBusMessageIter sub;
2902 dbus_message_iter_recurse(iter, &sub);
2903 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2904 ExecStatusInfo info;
2907 if (exec_status_info_deserialize(&sub, &info) >= 0) {
2908 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
2911 t = strv_join(info.argv, " ");
2913 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
2917 yes_no(info.ignore),
2918 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
2919 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
2920 (unsigned) info. pid,
2921 sigchld_code_to_string(info.code),
2923 info.code == CLD_EXITED ? "" : "/",
2924 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
2930 strv_free(info.argv);
2932 dbus_message_iter_next(&sub);
2941 if (generic_print_property(name, iter, arg_all) > 0)
2945 printf("%s=[unprintable]\n", name);
2950 static int show_one(const char *verb, DBusConnection *bus, const char *path, bool show_properties, bool *new_line) {
2951 _cleanup_free_ DBusMessage *reply = NULL;
2952 const char *interface = "";
2954 DBusMessageIter iter, sub, sub2, sub3;
2955 UnitStatusInfo info;
2963 r = bus_method_call_with_reply(
2965 "org.freedesktop.systemd1",
2967 "org.freedesktop.DBus.Properties",
2971 DBUS_TYPE_STRING, &interface,
2976 if (!dbus_message_iter_init(reply, &iter) ||
2977 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
2978 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
2979 log_error("Failed to parse reply.");
2983 dbus_message_iter_recurse(&iter, &sub);
2990 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
2993 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_DICT_ENTRY);
2994 dbus_message_iter_recurse(&sub, &sub2);
2996 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
2997 dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
2998 log_error("Failed to parse reply.");
3002 dbus_message_iter_recurse(&sub2, &sub3);
3004 if (show_properties)
3005 r = print_property(name, &sub3);
3007 r = status_property(name, &sub3, &info);
3009 log_error("Failed to parse reply.");
3013 dbus_message_iter_next(&sub);
3018 if (!show_properties) {
3019 if (streq(verb, "help"))
3020 show_unit_help(&info);
3022 print_status_info(&info);
3025 strv_free(info.documentation);
3027 if (!streq_ptr(info.active_state, "active") &&
3028 !streq_ptr(info.active_state, "reloading") &&
3029 streq(verb, "status"))
3030 /* According to LSB: "program not running" */
3033 while ((p = info.exec)) {
3034 LIST_REMOVE(ExecStatusInfo, exec, info.exec, p);
3035 exec_status_info_free(p);
3041 static int show_one_by_pid(const char *verb, DBusConnection *bus, uint32_t pid, bool *new_line) {
3042 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3043 const char *path = NULL;
3047 dbus_error_init(&error);
3049 r = bus_method_call_with_reply(
3051 "org.freedesktop.systemd1",
3052 "/org/freedesktop/systemd1",
3053 "org.freedesktop.systemd1.Manager",
3057 DBUS_TYPE_UINT32, &pid,
3062 if (!dbus_message_get_args(reply, &error,
3063 DBUS_TYPE_OBJECT_PATH, &path,
3064 DBUS_TYPE_INVALID)) {
3065 log_error("Failed to parse reply: %s", bus_error_message(&error));
3070 r = show_one(verb, bus, path, false, new_line);
3073 dbus_error_free(&error);
3078 static int show(DBusConnection *bus, char **args) {
3080 bool show_properties, new_line = false;
3086 show_properties = streq(args[0], "show");
3088 if (show_properties)
3089 pager_open_if_enabled();
3091 /* If no argument is specified inspect the manager itself */
3093 if (show_properties && strv_length(args) <= 1)
3094 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line);
3096 STRV_FOREACH(name, args+1) {
3099 if (safe_atou32(*name, &id) < 0) {
3100 _cleanup_free_ char *p = NULL, *n = NULL;
3101 /* Interpret as unit name */
3103 n = unit_name_mangle(*name);
3107 p = unit_dbus_path_from_name(n);
3111 r = show_one(args[0], bus, p, show_properties, &new_line);
3115 } else if (show_properties) {
3116 _cleanup_free_ char *p = NULL;
3118 /* Interpret as job id */
3119 if (asprintf(&p, "/org/freedesktop/systemd1/job/%u", id) < 0)
3122 r = show_one(args[0], bus, p, show_properties, &new_line);
3127 /* Interpret as PID */
3128 r = show_one_by_pid(args[0], bus, id, &new_line);
3137 static int dump(DBusConnection *bus, char **args) {
3138 _cleanup_free_ DBusMessage *reply = NULL;
3143 dbus_error_init(&error);
3145 pager_open_if_enabled();
3147 r = bus_method_call_with_reply(
3149 "org.freedesktop.systemd1",
3150 "/org/freedesktop/systemd1",
3151 "org.freedesktop.systemd1.Manager",
3159 if (!dbus_message_get_args(reply, &error,
3160 DBUS_TYPE_STRING, &text,
3161 DBUS_TYPE_INVALID)) {
3162 log_error("Failed to parse reply: %s", bus_error_message(&error));
3163 dbus_error_free(&error);
3167 fputs(text, stdout);
3171 static int snapshot(DBusConnection *bus, char **args) {
3172 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3175 dbus_bool_t cleanup = FALSE;
3176 DBusMessageIter iter, sub;
3179 *interface = "org.freedesktop.systemd1.Unit",
3181 _cleanup_free_ char *n = NULL;
3183 dbus_error_init(&error);
3185 if (strv_length(args) > 1)
3186 n = snapshot_name_mangle(args[1]);
3192 r = bus_method_call_with_reply (
3194 "org.freedesktop.systemd1",
3195 "/org/freedesktop/systemd1",
3196 "org.freedesktop.systemd1.Manager",
3200 DBUS_TYPE_STRING, &n,
3201 DBUS_TYPE_BOOLEAN, &cleanup,
3206 if (!dbus_message_get_args(reply, &error,
3207 DBUS_TYPE_OBJECT_PATH, &path,
3208 DBUS_TYPE_INVALID)) {
3209 log_error("Failed to parse reply: %s", bus_error_message(&error));
3210 dbus_error_free(&error);
3214 dbus_message_unref(reply);
3217 r = bus_method_call_with_reply (
3219 "org.freedesktop.systemd1",
3221 "org.freedesktop.DBus.Properties",
3225 DBUS_TYPE_STRING, &interface,
3226 DBUS_TYPE_STRING, &property,
3231 if (!dbus_message_iter_init(reply, &iter) ||
3232 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3233 log_error("Failed to parse reply.");
3237 dbus_message_iter_recurse(&iter, &sub);
3239 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
3240 log_error("Failed to parse reply.");
3244 dbus_message_iter_get_basic(&sub, &id);
3252 static int delete_snapshot(DBusConnection *bus, char **args) {
3257 STRV_FOREACH(name, args+1) {
3258 _cleanup_free_ char *n = NULL;
3261 n = snapshot_name_mangle(*name);
3265 r = bus_method_call_with_reply(
3267 "org.freedesktop.systemd1",
3268 "/org/freedesktop/systemd1",
3269 "org.freedesktop.systemd1.Manager",
3273 DBUS_TYPE_STRING, &n,
3282 static int daemon_reload(DBusConnection *bus, char **args) {
3287 if (arg_action == ACTION_RELOAD)
3289 else if (arg_action == ACTION_REEXEC)
3290 method = "Reexecute";
3292 assert(arg_action == ACTION_SYSTEMCTL);
3295 streq(args[0], "clear-jobs") ||
3296 streq(args[0], "cancel") ? "ClearJobs" :
3297 streq(args[0], "daemon-reexec") ? "Reexecute" :
3298 streq(args[0], "reset-failed") ? "ResetFailed" :
3299 streq(args[0], "halt") ? "Halt" :
3300 streq(args[0], "poweroff") ? "PowerOff" :
3301 streq(args[0], "reboot") ? "Reboot" :
3302 streq(args[0], "kexec") ? "KExec" :
3303 streq(args[0], "exit") ? "Exit" :
3304 /* "daemon-reload" */ "Reload";
3307 r = bus_method_call_with_reply(
3309 "org.freedesktop.systemd1",
3310 "/org/freedesktop/systemd1",
3311 "org.freedesktop.systemd1.Manager",
3317 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
3318 /* There's always a fallback possible for
3319 * legacy actions. */
3321 else if (r == -ETIMEDOUT && streq(method, "Reexecute"))
3322 /* On reexecution, we expect a disconnect, not
3326 log_error("Failed to issue method call: %s", bus_error_message(&error));
3328 dbus_error_free(&error);
3332 static int reset_failed(DBusConnection *bus, char **args) {
3336 if (strv_length(args) <= 1)
3337 return daemon_reload(bus, args);
3339 STRV_FOREACH(name, args+1) {
3340 _cleanup_free_ char *n;
3342 n = unit_name_mangle(*name);
3346 r = bus_method_call_with_reply(
3348 "org.freedesktop.systemd1",
3349 "/org/freedesktop/systemd1",
3350 "org.freedesktop.systemd1.Manager",
3354 DBUS_TYPE_STRING, &n,
3363 static int show_enviroment(DBusConnection *bus, char **args) {
3364 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3365 DBusMessageIter iter, sub, sub2;
3368 *interface = "org.freedesktop.systemd1.Manager",
3369 *property = "Environment";
3371 pager_open_if_enabled();
3373 r = bus_method_call_with_reply(
3375 "org.freedesktop.systemd1",
3376 "/org/freedesktop/systemd1",
3377 "org.freedesktop.DBus.Properties",
3381 DBUS_TYPE_STRING, &interface,
3382 DBUS_TYPE_STRING, &property,
3387 if (!dbus_message_iter_init(reply, &iter) ||
3388 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3389 log_error("Failed to parse reply.");
3393 dbus_message_iter_recurse(&iter, &sub);
3395 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_ARRAY ||
3396 dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_STRING) {
3397 log_error("Failed to parse reply.");
3401 dbus_message_iter_recurse(&sub, &sub2);
3403 while (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_INVALID) {
3406 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
3407 log_error("Failed to parse reply.");
3411 dbus_message_iter_get_basic(&sub2, &text);
3414 dbus_message_iter_next(&sub2);
3420 static int switch_root(DBusConnection *bus, char **args) {
3423 _cleanup_free_ char *init = NULL;
3425 l = strv_length(args);
3426 if (l < 2 || l > 3) {
3427 log_error("Wrong number of arguments.");
3434 init = strdup(args[2]);
3436 parse_env_file("/proc/cmdline", WHITESPACE,
3446 log_debug("switching root - root: %s; init: %s", root, init);
3448 return bus_method_call_with_reply(
3450 "org.freedesktop.systemd1",
3451 "/org/freedesktop/systemd1",
3452 "org.freedesktop.systemd1.Manager",
3456 DBUS_TYPE_STRING, &root,
3457 DBUS_TYPE_STRING, &init,
3461 static int set_environment(DBusConnection *bus, char **args) {
3462 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
3465 DBusMessageIter iter;
3471 dbus_error_init(&error);
3473 method = streq(args[0], "set-environment")
3475 : "UnsetEnvironment";
3477 m = dbus_message_new_method_call(
3478 "org.freedesktop.systemd1",
3479 "/org/freedesktop/systemd1",
3480 "org.freedesktop.systemd1.Manager",
3485 dbus_message_iter_init_append(m, &iter);
3487 r = bus_append_strv_iter(&iter, args + 1);
3491 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3493 log_error("Failed to issue method call: %s", bus_error_message(&error));
3494 dbus_error_free(&error);
3501 static int enable_sysv_units(char **args) {
3504 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
3505 const char *verb = args[0];
3506 unsigned f = 1, t = 1;
3509 if (arg_scope != UNIT_FILE_SYSTEM)
3512 if (!streq(verb, "enable") &&
3513 !streq(verb, "disable") &&
3514 !streq(verb, "is-enabled"))
3517 /* Processes all SysV units, and reshuffles the array so that
3518 * afterwards only the native units remain */
3521 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, NULL, NULL, NULL);
3526 for (f = 1; args[f]; f++) {
3529 bool found_native = false, found_sysv;
3531 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
3532 char **k, *l, *q = NULL;
3539 if (!endswith(name, ".service"))
3542 if (path_is_absolute(name))
3545 STRV_FOREACH(k, paths.unit_path) {
3548 if (!isempty(arg_root))
3549 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
3551 asprintf(&p, "%s/%s", *k, name);
3558 found_native = access(p, F_OK) >= 0;
3569 if (!isempty(arg_root))
3570 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
3572 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
3578 p[strlen(p) - sizeof(".service") + 1] = 0;
3579 found_sysv = access(p, F_OK) >= 0;
3586 /* Mark this entry, so that we don't try enabling it as native unit */
3587 args[f] = (char*) "";
3589 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
3591 if (!isempty(arg_root))
3592 argv[c++] = q = strappend("--root=", arg_root);
3594 argv[c++] = path_get_file_name(p);
3596 streq(verb, "enable") ? "on" :
3597 streq(verb, "disable") ? "off" : "--level=5";
3600 l = strv_join((char**)argv, " ");
3608 log_info("Executing %s", l);
3613 log_error("Failed to fork: %m");
3618 } else if (pid == 0) {
3621 execv(argv[0], (char**) argv);
3622 _exit(EXIT_FAILURE);
3628 j = wait_for_terminate(pid, &status);
3630 log_error("Failed to wait for child: %s", strerror(-r));
3635 if (status.si_code == CLD_EXITED) {
3636 if (streq(verb, "is-enabled")) {
3637 if (status.si_status == 0) {
3646 } else if (status.si_status != 0) {
3657 lookup_paths_free(&paths);
3659 /* Drop all SysV units */
3660 for (f = 1, t = 1; args[f]; f++) {
3662 if (isempty(args[f]))
3665 args[t++] = args[f];
3674 static int mangle_names(char **original_names, char ***mangled_names) {
3675 char **i, **l, **name;
3677 l = new(char*, strv_length(original_names) + 1);
3682 STRV_FOREACH(name, original_names) {
3684 /* When enabling units qualified path names are OK,
3685 * too, hence allow them explicitly. */
3690 *i = unit_name_mangle(*name);
3706 static int enable_unit(DBusConnection *bus, char **args) {
3707 const char *verb = args[0];
3708 UnitFileChange *changes = NULL;
3709 unsigned n_changes = 0, i;
3710 int carries_install_info = -1;
3711 DBusMessage *m = NULL, *reply = NULL;
3714 char **mangled_names = NULL;
3716 r = enable_sysv_units(args);
3723 dbus_error_init(&error);
3725 if (!bus || avoid_bus()) {
3726 if (streq(verb, "enable")) {
3727 r = unit_file_enable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3728 carries_install_info = r;
3729 } else if (streq(verb, "disable"))
3730 r = unit_file_disable(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3731 else if (streq(verb, "reenable")) {
3732 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3733 carries_install_info = r;
3734 } else if (streq(verb, "link"))
3735 r = unit_file_link(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3736 else if (streq(verb, "preset")) {
3737 r = unit_file_preset(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3738 carries_install_info = r;
3739 } else if (streq(verb, "mask"))
3740 r = unit_file_mask(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3741 else if (streq(verb, "unmask"))
3742 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3744 assert_not_reached("Unknown verb");
3747 log_error("Operation failed: %s", strerror(-r));
3752 for (i = 0; i < n_changes; i++) {
3753 if (changes[i].type == UNIT_FILE_SYMLINK)
3754 log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
3756 log_info("rm '%s'", changes[i].path);
3763 bool send_force = true, expect_carries_install_info = false;
3765 DBusMessageIter iter, sub, sub2;
3767 if (streq(verb, "enable")) {
3768 method = "EnableUnitFiles";
3769 expect_carries_install_info = true;
3770 } else if (streq(verb, "disable")) {
3771 method = "DisableUnitFiles";
3773 } else if (streq(verb, "reenable")) {
3774 method = "ReenableUnitFiles";
3775 expect_carries_install_info = true;
3776 } else if (streq(verb, "link"))
3777 method = "LinkUnitFiles";
3778 else if (streq(verb, "preset")) {
3779 method = "PresetUnitFiles";
3780 expect_carries_install_info = true;
3781 } else if (streq(verb, "mask"))
3782 method = "MaskUnitFiles";
3783 else if (streq(verb, "unmask")) {
3784 method = "UnmaskUnitFiles";
3787 assert_not_reached("Unknown verb");
3789 m = dbus_message_new_method_call(
3790 "org.freedesktop.systemd1",
3791 "/org/freedesktop/systemd1",
3792 "org.freedesktop.systemd1.Manager",
3799 dbus_message_iter_init_append(m, &iter);
3801 r = mangle_names(args+1, &mangled_names);
3805 r = bus_append_strv_iter(&iter, mangled_names);
3807 log_error("Failed to append unit files.");
3812 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &a)) {
3813 log_error("Failed to append runtime boolean.");
3821 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b)) {
3822 log_error("Failed to append force boolean.");
3828 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3830 log_error("Failed to issue method call: %s", bus_error_message(&error));
3835 if (!dbus_message_iter_init(reply, &iter)) {
3836 log_error("Failed to initialize iterator.");
3840 if (expect_carries_install_info) {
3841 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &b, true);
3843 log_error("Failed to parse reply.");
3847 carries_install_info = b;
3850 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3851 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
3852 log_error("Failed to parse reply.");
3857 dbus_message_iter_recurse(&iter, &sub);
3858 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
3859 const char *type, *path, *source;
3861 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
3862 log_error("Failed to parse reply.");
3867 dbus_message_iter_recurse(&sub, &sub2);
3869 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
3870 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
3871 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &source, false) < 0) {
3872 log_error("Failed to parse reply.");
3878 if (streq(type, "symlink"))
3879 log_info("ln -s '%s' '%s'", source, path);
3881 log_info("rm '%s'", path);
3884 dbus_message_iter_next(&sub);
3887 /* Try to reload if enabeld */
3889 r = daemon_reload(bus, args);
3892 if (carries_install_info == 0)
3894 "The unit files have no [Install] section. They are not meant to be enabled\n"
3895 "using systemctl.\n"
3896 "Possible reasons for having this kind of units are:\n"
3897 "1) A unit may be statically enabled by being symlinked from another unit's\n"
3898 " .wants/ or .requires/ directory.\n"
3899 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
3900 " a requirement dependency on it.\n"
3901 "3) A unit may be started when needed via activation (socket, path, timer,\n"
3902 " D-Bus, udev, scripted systemctl call, ...).\n");
3906 dbus_message_unref(m);
3909 dbus_message_unref(reply);
3911 unit_file_changes_free(changes, n_changes);
3913 dbus_error_free(&error);
3915 strv_free(mangled_names);
3920 static int unit_is_enabled(DBusConnection *bus, char **args) {
3923 DBusMessage *reply = NULL;
3927 dbus_error_init(&error);
3929 r = enable_sysv_units(args);
3935 if (!bus || avoid_bus()) {
3937 STRV_FOREACH(name, args+1) {
3938 UnitFileState state;
3940 state = unit_file_get_state(arg_scope, arg_root, *name);
3946 if (state == UNIT_FILE_ENABLED ||
3947 state == UNIT_FILE_ENABLED_RUNTIME ||
3948 state == UNIT_FILE_STATIC)
3952 puts(unit_file_state_to_string(state));
3956 STRV_FOREACH(name, args+1) {
3959 r = bus_method_call_with_reply (
3961 "org.freedesktop.systemd1",
3962 "/org/freedesktop/systemd1",
3963 "org.freedesktop.systemd1.Manager",
3967 DBUS_TYPE_STRING, name,
3972 if (!dbus_message_get_args(reply, &error,
3973 DBUS_TYPE_STRING, &s,
3974 DBUS_TYPE_INVALID)) {
3975 log_error("Failed to parse reply: %s", bus_error_message(&error));
3980 dbus_message_unref(reply);
3983 if (streq(s, "enabled") ||
3984 streq(s, "enabled-runtime") ||
3993 r = enabled ? 0 : 1;
3997 dbus_message_unref(reply);
3999 dbus_error_free(&error);
4003 static int systemctl_help(void) {
4005 pager_open_if_enabled();
4007 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
4008 "Query or send control commands to the systemd manager.\n\n"
4009 " -h --help Show this help\n"
4010 " --version Show package version\n"
4011 " -t --type=TYPE List only units of a particular type\n"
4012 " -p --property=NAME Show only properties by this name\n"
4013 " -a --all Show all units/properties, including dead/empty ones\n"
4014 " --failed Show only failed units\n"
4015 " --full Don't ellipsize unit names on output\n"
4016 " --fail When queueing a new job, fail if conflicting jobs are\n"
4018 " --ignore-dependencies\n"
4019 " When queueing a new job, ignore all its dependencies\n"
4020 " -i --ignore-inhibitors\n"
4021 " When shutting down or sleeping, ignore inhibitors\n"
4022 " --kill-who=WHO Who to send signal to\n"
4023 " -s --signal=SIGNAL Which signal to send\n"
4024 " -H --host=[USER@]HOST\n"
4025 " Show information for remote host\n"
4026 " -P --privileged Acquire privileges before execution\n"
4027 " -q --quiet Suppress output\n"
4028 " --no-block Do not wait until operation finished\n"
4029 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4030 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
4032 " --no-legend Do not print a legend (column headers and hints)\n"
4033 " --no-pager Do not pipe output into a pager\n"
4034 " --no-ask-password\n"
4035 " Do not ask for system passwords\n"
4036 " --order When generating graph for dot, show only order\n"
4037 " --require When generating graph for dot, show only requirement\n"
4038 " --system Connect to system manager\n"
4039 " --user Connect to user service manager\n"
4040 " --global Enable/disable unit files globally\n"
4041 " -f --force When enabling unit files, override existing symlinks\n"
4042 " When shutting down, execute action immediately\n"
4043 " --root=PATH Enable unit files in the specified root directory\n"
4044 " --runtime Enable unit files only temporarily until next reboot\n"
4045 " -n --lines=INTEGER Journal entries to show\n"
4046 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
4047 " verbose, export, json, json-pretty, json-sse, cat)\n\n"
4049 " list-units List loaded units\n"
4050 " start [NAME...] Start (activate) one or more units\n"
4051 " stop [NAME...] Stop (deactivate) one or more units\n"
4052 " reload [NAME...] Reload one or more units\n"
4053 " restart [NAME...] Start or restart one or more units\n"
4054 " try-restart [NAME...] Restart one or more units if active\n"
4055 " reload-or-restart [NAME...] Reload one or more units if possible,\n"
4056 " otherwise start or restart\n"
4057 " reload-or-try-restart [NAME...] Reload one or more units if possible,\n"
4058 " otherwise restart if active\n"
4059 " isolate [NAME] Start one unit and stop all others\n"
4060 " kill [NAME...] Send signal to processes of a unit\n"
4061 " is-active [NAME...] Check whether units are active\n"
4062 " is-failed [NAME...] Check whether units are failed\n"
4063 " status [NAME...|PID...] Show runtime status of one or more units\n"
4064 " show [NAME...|JOB...] Show properties of one or more\n"
4065 " units/jobs or the manager\n"
4066 " help [NAME...|PID...] Show manual for one or more units\n"
4067 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
4069 " set-cgroup [NAME] [CGROUP...] Add unit to a control group\n"
4070 " unset-cgroup [NAME] [CGROUP...] Remove unit from a control group\n"
4071 " set-cgroup-attr [NAME] [ATTR] [VALUE] ...\n"
4072 " Set control group attribute\n"
4073 " unset-cgroup-attr [NAME] [ATTR...]\n"
4074 " Unset control group attribute\n"
4075 " load [NAME...] Load one or more units\n\n"
4076 "Unit File Commands:\n"
4077 " list-unit-files List installed unit files\n"
4078 " enable [NAME...] Enable one or more unit files\n"
4079 " disable [NAME...] Disable one or more unit files\n"
4080 " reenable [NAME...] Reenable one or more unit files\n"
4081 " preset [NAME...] Enable/disable one or more unit files\n"
4082 " based on preset configuration\n"
4083 " mask [NAME...] Mask one or more units\n"
4084 " unmask [NAME...] Unmask one or more units\n"
4085 " link [PATH...] Link one or more units files into\n"
4086 " the search path\n"
4087 " is-enabled [NAME...] Check whether unit files are enabled\n\n"
4089 " list-jobs List jobs\n"
4090 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
4091 "Status Commands:\n"
4092 " dump Dump server status\n"
4093 " dot Dump dependency graph for dot(1)\n\n"
4094 "Snapshot Commands:\n"
4095 " snapshot [NAME] Create a snapshot\n"
4096 " delete [NAME...] Remove one or more snapshots\n\n"
4097 "Environment Commands:\n"
4098 " show-environment Dump environment\n"
4099 " set-environment [NAME=VALUE...] Set one or more environment variables\n"
4100 " unset-environment [NAME...] Unset one or more environment variables\n\n"
4101 "Manager Lifecycle Commands:\n"
4102 " daemon-reload Reload systemd manager configuration\n"
4103 " daemon-reexec Reexecute systemd manager\n\n"
4104 "System Commands:\n"
4105 " default Enter system default mode\n"
4106 " rescue Enter system rescue mode\n"
4107 " emergency Enter system emergency mode\n"
4108 " halt Shut down and halt the system\n"
4109 " poweroff Shut down and power-off the system\n"
4110 " reboot Shut down and reboot the system\n"
4111 " kexec Shut down and reboot the system with kexec\n"
4112 " exit Request user instance exit\n"
4113 " switch-root [ROOT] [INIT] Change to a different root file system\n"
4114 " suspend Suspend the system\n"
4115 " hibernate Hibernate the system\n"
4116 " hybrid-sleep Hibernate and suspend the system\n",
4117 program_invocation_short_name);
4122 static int halt_help(void) {
4124 printf("%s [OPTIONS...]\n\n"
4125 "%s the system.\n\n"
4126 " --help Show this help\n"
4127 " --halt Halt the machine\n"
4128 " -p --poweroff Switch off the machine\n"
4129 " --reboot Reboot the machine\n"
4130 " -f --force Force immediate halt/power-off/reboot\n"
4131 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
4132 " -d --no-wtmp Don't write wtmp record\n"
4133 " --no-wall Don't send wall message before halt/power-off/reboot\n",
4134 program_invocation_short_name,
4135 arg_action == ACTION_REBOOT ? "Reboot" :
4136 arg_action == ACTION_POWEROFF ? "Power off" :
4142 static int shutdown_help(void) {
4144 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
4145 "Shut down the system.\n\n"
4146 " --help Show this help\n"
4147 " -H --halt Halt the machine\n"
4148 " -P --poweroff Power-off the machine\n"
4149 " -r --reboot Reboot the machine\n"
4150 " -h Equivalent to --poweroff, overridden by --halt\n"
4151 " -k Don't halt/power-off/reboot, just send warnings\n"
4152 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4153 " -c Cancel a pending shutdown\n",
4154 program_invocation_short_name);
4159 static int telinit_help(void) {
4161 printf("%s [OPTIONS...] {COMMAND}\n\n"
4162 "Send control commands to the init daemon.\n\n"
4163 " --help Show this help\n"
4164 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
4166 " 0 Power-off the machine\n"
4167 " 6 Reboot the machine\n"
4168 " 2, 3, 4, 5 Start runlevelX.target unit\n"
4169 " 1, s, S Enter rescue mode\n"
4170 " q, Q Reload init daemon configuration\n"
4171 " u, U Reexecute init daemon\n",
4172 program_invocation_short_name);
4177 static int runlevel_help(void) {
4179 printf("%s [OPTIONS...]\n\n"
4180 "Prints the previous and current runlevel of the init system.\n\n"
4181 " --help Show this help\n",
4182 program_invocation_short_name);
4187 static int help_types(void) {
4190 puts("Available unit types:");
4191 for(i = UNIT_SERVICE; i < _UNIT_TYPE_MAX; i++)
4192 if (unit_type_table[i])
4193 puts(unit_type_table[i]);
4195 puts("\nAvailable unit load states: ");
4196 for(i = UNIT_STUB; i < _UNIT_LOAD_STATE_MAX; i++)
4197 if (unit_type_table[i])
4198 puts(unit_load_state_table[i]);
4203 static int systemctl_parse_argv(int argc, char *argv[]) {
4207 ARG_IGNORE_DEPENDENCIES,
4222 ARG_NO_ASK_PASSWORD,
4228 static const struct option options[] = {
4229 { "help", no_argument, NULL, 'h' },
4230 { "version", no_argument, NULL, ARG_VERSION },
4231 { "type", required_argument, NULL, 't' },
4232 { "property", required_argument, NULL, 'p' },
4233 { "all", no_argument, NULL, 'a' },
4234 { "failed", no_argument, NULL, ARG_FAILED },
4235 { "full", no_argument, NULL, ARG_FULL },
4236 { "fail", no_argument, NULL, ARG_FAIL },
4237 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
4238 { "ignore-inhibitors", no_argument, NULL, 'i' },
4239 { "user", no_argument, NULL, ARG_USER },
4240 { "system", no_argument, NULL, ARG_SYSTEM },
4241 { "global", no_argument, NULL, ARG_GLOBAL },
4242 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
4243 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
4244 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
4245 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4246 { "quiet", no_argument, NULL, 'q' },
4247 { "order", no_argument, NULL, ARG_ORDER },
4248 { "require", no_argument, NULL, ARG_REQUIRE },
4249 { "root", required_argument, NULL, ARG_ROOT },
4250 { "force", no_argument, NULL, ARG_FORCE },
4251 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
4252 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
4253 { "signal", required_argument, NULL, 's' },
4254 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
4255 { "host", required_argument, NULL, 'H' },
4256 { "privileged",no_argument, NULL, 'P' },
4257 { "runtime", no_argument, NULL, ARG_RUNTIME },
4258 { "lines", required_argument, NULL, 'n' },
4259 { "output", required_argument, NULL, 'o' },
4260 { NULL, 0, NULL, 0 }
4268 while ((c = getopt_long(argc, argv, "ht:p:aqfs:H:Pn:o:i", options, NULL)) >= 0) {
4277 puts(PACKAGE_STRING);
4278 puts(SYSTEMD_FEATURES);
4282 if (streq(optarg, "help")) {
4287 if (unit_type_from_string(optarg) >= 0) {
4291 if (unit_load_state_from_string(optarg) >= 0) {
4292 arg_load_state = optarg;
4295 log_error("Unkown unit type or load state '%s'.",
4297 log_info("Use -t help to see a list of allowed values.");
4302 if (!(l = strv_append(arg_property, optarg)))
4305 strv_free(arg_property);
4308 /* If the user asked for a particular
4309 * property, show it to him, even if it is
4320 arg_job_mode = "fail";
4323 case ARG_IGNORE_DEPENDENCIES:
4324 arg_job_mode = "ignore-dependencies";
4328 arg_scope = UNIT_FILE_USER;
4332 arg_scope = UNIT_FILE_SYSTEM;
4336 arg_scope = UNIT_FILE_GLOBAL;
4340 arg_no_block = true;
4344 arg_no_legend = true;
4348 arg_no_pager = true;
4356 arg_dot = DOT_ORDER;
4360 arg_dot = DOT_REQUIRE;
4388 arg_no_reload = true;
4392 arg_kill_who = optarg;
4396 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
4397 log_error("Failed to parse signal string %s.", optarg);
4402 case ARG_NO_ASK_PASSWORD:
4403 arg_ask_password = false;
4407 arg_transport = TRANSPORT_POLKIT;
4411 arg_transport = TRANSPORT_SSH;
4420 if (safe_atou(optarg, &arg_lines) < 0) {
4421 log_error("Failed to parse lines '%s'", optarg);
4427 arg_output = output_mode_from_string(optarg);
4428 if (arg_output < 0) {
4429 log_error("Unknown output '%s'.", optarg);
4435 arg_ignore_inhibitors = true;
4442 log_error("Unknown option code '%c'.", c);
4447 if (arg_transport != TRANSPORT_NORMAL && arg_scope != UNIT_FILE_SYSTEM) {
4448 log_error("Cannot access user instance remotely.");
4455 static int halt_parse_argv(int argc, char *argv[]) {
4464 static const struct option options[] = {
4465 { "help", no_argument, NULL, ARG_HELP },
4466 { "halt", no_argument, NULL, ARG_HALT },
4467 { "poweroff", no_argument, NULL, 'p' },
4468 { "reboot", no_argument, NULL, ARG_REBOOT },
4469 { "force", no_argument, NULL, 'f' },
4470 { "wtmp-only", no_argument, NULL, 'w' },
4471 { "no-wtmp", no_argument, NULL, 'd' },
4472 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4473 { NULL, 0, NULL, 0 }
4481 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
4482 if (runlevel == '0' || runlevel == '6')
4485 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
4493 arg_action = ACTION_HALT;
4497 if (arg_action != ACTION_REBOOT)
4498 arg_action = ACTION_POWEROFF;
4502 arg_action = ACTION_REBOOT;
4524 /* Compatibility nops */
4531 log_error("Unknown option code '%c'.", c);
4536 if (optind < argc) {
4537 log_error("Too many arguments.");
4544 static int parse_time_spec(const char *t, usec_t *_u) {
4548 if (streq(t, "now"))
4550 else if (!strchr(t, ':')) {
4553 if (safe_atou64(t, &u) < 0)
4556 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
4565 hour = strtol(t, &e, 10);
4566 if (errno != 0 || *e != ':' || hour < 0 || hour > 23)
4569 minute = strtol(e+1, &e, 10);
4570 if (errno != 0 || *e != 0 || minute < 0 || minute > 59)
4573 n = now(CLOCK_REALTIME);
4574 s = (time_t) (n / USEC_PER_SEC);
4577 assert_se(localtime_r(&s, &tm));
4579 tm.tm_hour = (int) hour;
4580 tm.tm_min = (int) minute;
4583 assert_se(s = mktime(&tm));
4585 *_u = (usec_t) s * USEC_PER_SEC;
4588 *_u += USEC_PER_DAY;
4594 static int shutdown_parse_argv(int argc, char *argv[]) {
4601 static const struct option options[] = {
4602 { "help", no_argument, NULL, ARG_HELP },
4603 { "halt", no_argument, NULL, 'H' },
4604 { "poweroff", no_argument, NULL, 'P' },
4605 { "reboot", no_argument, NULL, 'r' },
4606 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
4607 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4608 { NULL, 0, NULL, 0 }
4616 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
4624 arg_action = ACTION_HALT;
4628 arg_action = ACTION_POWEROFF;
4633 arg_action = ACTION_KEXEC;
4635 arg_action = ACTION_REBOOT;
4639 arg_action = ACTION_KEXEC;
4643 if (arg_action != ACTION_HALT)
4644 arg_action = ACTION_POWEROFF;
4657 /* Compatibility nops */
4661 arg_action = ACTION_CANCEL_SHUTDOWN;
4668 log_error("Unknown option code '%c'.", c);
4673 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
4674 r = parse_time_spec(argv[optind], &arg_when);
4676 log_error("Failed to parse time specification: %s", argv[optind]);
4680 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
4682 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
4683 /* No time argument for shutdown cancel */
4684 arg_wall = argv + optind;
4685 else if (argc > optind + 1)
4686 /* We skip the time argument */
4687 arg_wall = argv + optind + 1;
4694 static int telinit_parse_argv(int argc, char *argv[]) {
4701 static const struct option options[] = {
4702 { "help", no_argument, NULL, ARG_HELP },
4703 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4704 { NULL, 0, NULL, 0 }
4707 static const struct {
4711 { '0', ACTION_POWEROFF },
4712 { '6', ACTION_REBOOT },
4713 { '1', ACTION_RESCUE },
4714 { '2', ACTION_RUNLEVEL2 },
4715 { '3', ACTION_RUNLEVEL3 },
4716 { '4', ACTION_RUNLEVEL4 },
4717 { '5', ACTION_RUNLEVEL5 },
4718 { 's', ACTION_RESCUE },
4719 { 'S', ACTION_RESCUE },
4720 { 'q', ACTION_RELOAD },
4721 { 'Q', ACTION_RELOAD },
4722 { 'u', ACTION_REEXEC },
4723 { 'U', ACTION_REEXEC }
4732 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4747 log_error("Unknown option code '%c'.", c);
4752 if (optind >= argc) {
4757 if (optind + 1 < argc) {
4758 log_error("Too many arguments.");
4762 if (strlen(argv[optind]) != 1) {
4763 log_error("Expected single character argument.");
4767 for (i = 0; i < ELEMENTSOF(table); i++)
4768 if (table[i].from == argv[optind][0])
4771 if (i >= ELEMENTSOF(table)) {
4772 log_error("Unknown command '%s'.", argv[optind]);
4776 arg_action = table[i].to;
4783 static int runlevel_parse_argv(int argc, char *argv[]) {
4789 static const struct option options[] = {
4790 { "help", no_argument, NULL, ARG_HELP },
4791 { NULL, 0, NULL, 0 }
4799 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4810 log_error("Unknown option code '%c'.", c);
4815 if (optind < argc) {
4816 log_error("Too many arguments.");
4823 static int parse_argv(int argc, char *argv[]) {
4827 if (program_invocation_short_name) {
4829 if (strstr(program_invocation_short_name, "halt")) {
4830 arg_action = ACTION_HALT;
4831 return halt_parse_argv(argc, argv);
4832 } else if (strstr(program_invocation_short_name, "poweroff")) {
4833 arg_action = ACTION_POWEROFF;
4834 return halt_parse_argv(argc, argv);
4835 } else if (strstr(program_invocation_short_name, "reboot")) {
4837 arg_action = ACTION_KEXEC;
4839 arg_action = ACTION_REBOOT;
4840 return halt_parse_argv(argc, argv);
4841 } else if (strstr(program_invocation_short_name, "shutdown")) {
4842 arg_action = ACTION_POWEROFF;
4843 return shutdown_parse_argv(argc, argv);
4844 } else if (strstr(program_invocation_short_name, "init")) {
4846 if (sd_booted() > 0) {
4847 arg_action = ACTION_INVALID;
4848 return telinit_parse_argv(argc, argv);
4850 /* Hmm, so some other init system is
4851 * running, we need to forward this
4852 * request to it. For now we simply
4853 * guess that it is Upstart. */
4855 execv("/lib/upstart/telinit", argv);
4857 log_error("Couldn't find an alternative telinit implementation to spawn.");
4861 } else if (strstr(program_invocation_short_name, "runlevel")) {
4862 arg_action = ACTION_RUNLEVEL;
4863 return runlevel_parse_argv(argc, argv);
4867 arg_action = ACTION_SYSTEMCTL;
4868 return systemctl_parse_argv(argc, argv);
4871 static int action_to_runlevel(void) {
4873 static const char table[_ACTION_MAX] = {
4874 [ACTION_HALT] = '0',
4875 [ACTION_POWEROFF] = '0',
4876 [ACTION_REBOOT] = '6',
4877 [ACTION_RUNLEVEL2] = '2',
4878 [ACTION_RUNLEVEL3] = '3',
4879 [ACTION_RUNLEVEL4] = '4',
4880 [ACTION_RUNLEVEL5] = '5',
4881 [ACTION_RESCUE] = '1'
4884 assert(arg_action < _ACTION_MAX);
4886 return table[arg_action];
4889 static int talk_upstart(void) {
4890 DBusMessage *m = NULL, *reply = NULL;
4892 int previous, rl, r;
4894 env1_buf[] = "RUNLEVEL=X",
4895 env2_buf[] = "PREVLEVEL=X";
4896 char *env1 = env1_buf, *env2 = env2_buf;
4897 const char *emit = "runlevel";
4898 dbus_bool_t b_false = FALSE;
4899 DBusMessageIter iter, sub;
4900 DBusConnection *bus;
4902 dbus_error_init(&error);
4904 if (!(rl = action_to_runlevel()))
4907 if (utmp_get_runlevel(&previous, NULL) < 0)
4910 if (!(bus = dbus_connection_open_private("unix:abstract=/com/ubuntu/upstart", &error))) {
4911 if (dbus_error_has_name(&error, DBUS_ERROR_NO_SERVER)) {
4916 log_error("Failed to connect to Upstart bus: %s", bus_error_message(&error));
4921 if ((r = bus_check_peercred(bus)) < 0) {
4922 log_error("Failed to verify owner of bus.");
4926 if (!(m = dbus_message_new_method_call(
4927 "com.ubuntu.Upstart",
4928 "/com/ubuntu/Upstart",
4929 "com.ubuntu.Upstart0_6",
4932 log_error("Could not allocate message.");
4937 dbus_message_iter_init_append(m, &iter);
4939 env1_buf[sizeof(env1_buf)-2] = rl;
4940 env2_buf[sizeof(env2_buf)-2] = previous;
4942 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &emit) ||
4943 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub) ||
4944 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env1) ||
4945 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env2) ||
4946 !dbus_message_iter_close_container(&iter, &sub) ||
4947 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b_false)) {
4948 log_error("Could not append arguments to message.");
4953 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
4955 if (bus_error_is_no_service(&error)) {
4960 log_error("Failed to issue method call: %s", bus_error_message(&error));
4969 dbus_message_unref(m);
4972 dbus_message_unref(reply);
4975 dbus_connection_flush(bus);
4976 dbus_connection_close(bus);
4977 dbus_connection_unref(bus);
4980 dbus_error_free(&error);
4985 static int talk_initctl(void) {
4986 struct init_request request;
4990 if (!(rl = action_to_runlevel()))
4994 request.magic = INIT_MAGIC;
4995 request.sleeptime = 0;
4996 request.cmd = INIT_CMD_RUNLVL;
4997 request.runlevel = rl;
4999 if ((fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY)) < 0) {
5001 if (errno == ENOENT)
5004 log_error("Failed to open "INIT_FIFO": %m");
5009 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
5010 close_nointr_nofail(fd);
5013 log_error("Failed to write to "INIT_FIFO": %m");
5014 return errno ? -errno : -EIO;
5020 static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
5022 static const struct {
5030 int (* const dispatch)(DBusConnection *bus, char **args);
5032 { "list-units", LESS, 1, list_units },
5033 { "list-unit-files", EQUAL, 1, list_unit_files },
5034 { "list-jobs", EQUAL, 1, list_jobs },
5035 { "clear-jobs", EQUAL, 1, daemon_reload },
5036 { "load", MORE, 2, load_unit },
5037 { "cancel", MORE, 2, cancel_job },
5038 { "start", MORE, 2, start_unit },
5039 { "stop", MORE, 2, start_unit },
5040 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5041 { "reload", MORE, 2, start_unit },
5042 { "restart", MORE, 2, start_unit },
5043 { "try-restart", MORE, 2, start_unit },
5044 { "reload-or-restart", MORE, 2, start_unit },
5045 { "reload-or-try-restart", MORE, 2, start_unit },
5046 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
5047 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5048 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
5049 { "isolate", EQUAL, 2, start_unit },
5050 { "set-cgroup", MORE, 2, set_cgroup },
5051 { "unset-cgroup", MORE, 2, set_cgroup },
5052 { "set-cgroup-attr", MORE, 2, set_cgroup_attr },
5053 { "unset-cgroup-attr", MORE, 2, set_cgroup },
5054 { "kill", MORE, 2, kill_unit },
5055 { "is-active", MORE, 2, check_unit_active },
5056 { "check", MORE, 2, check_unit_active },
5057 { "is-failed", MORE, 2, check_unit_failed },
5058 { "show", MORE, 1, show },
5059 { "status", MORE, 2, show },
5060 { "help", MORE, 2, show },
5061 { "dump", EQUAL, 1, dump },
5062 { "dot", EQUAL, 1, dot },
5063 { "snapshot", LESS, 2, snapshot },
5064 { "delete", MORE, 2, delete_snapshot },
5065 { "daemon-reload", EQUAL, 1, daemon_reload },
5066 { "daemon-reexec", EQUAL, 1, daemon_reload },
5067 { "show-environment", EQUAL, 1, show_enviroment },
5068 { "set-environment", MORE, 2, set_environment },
5069 { "unset-environment", MORE, 2, set_environment },
5070 { "halt", EQUAL, 1, start_special },
5071 { "poweroff", EQUAL, 1, start_special },
5072 { "reboot", EQUAL, 1, start_special },
5073 { "kexec", EQUAL, 1, start_special },
5074 { "suspend", EQUAL, 1, start_special },
5075 { "hibernate", EQUAL, 1, start_special },
5076 { "hybrid-sleep", EQUAL, 1, start_special },
5077 { "default", EQUAL, 1, start_special },
5078 { "rescue", EQUAL, 1, start_special },
5079 { "emergency", EQUAL, 1, start_special },
5080 { "exit", EQUAL, 1, start_special },
5081 { "reset-failed", MORE, 1, reset_failed },
5082 { "enable", MORE, 2, enable_unit },
5083 { "disable", MORE, 2, enable_unit },
5084 { "is-enabled", MORE, 2, unit_is_enabled },
5085 { "reenable", MORE, 2, enable_unit },
5086 { "preset", MORE, 2, enable_unit },
5087 { "mask", MORE, 2, enable_unit },
5088 { "unmask", MORE, 2, enable_unit },
5089 { "link", MORE, 2, enable_unit },
5090 { "switch-root", MORE, 2, switch_root },
5100 left = argc - optind;
5103 /* Special rule: no arguments means "list-units" */
5106 if (streq(argv[optind], "help") && !argv[optind+1]) {
5107 log_error("This command expects one or more "
5108 "unit names. Did you mean --help?");
5112 for (i = 0; i < ELEMENTSOF(verbs); i++)
5113 if (streq(argv[optind], verbs[i].verb))
5116 if (i >= ELEMENTSOF(verbs)) {
5117 log_error("Unknown operation '%s'.", argv[optind]);
5122 switch (verbs[i].argc_cmp) {
5125 if (left != verbs[i].argc) {
5126 log_error("Invalid number of arguments.");
5133 if (left < verbs[i].argc) {
5134 log_error("Too few arguments.");
5141 if (left > verbs[i].argc) {
5142 log_error("Too many arguments.");
5149 assert_not_reached("Unknown comparison operator.");
5152 /* Require a bus connection for all operations but
5154 if (!streq(verbs[i].verb, "enable") &&
5155 !streq(verbs[i].verb, "disable") &&
5156 !streq(verbs[i].verb, "is-enabled") &&
5157 !streq(verbs[i].verb, "list-unit-files") &&
5158 !streq(verbs[i].verb, "reenable") &&
5159 !streq(verbs[i].verb, "preset") &&
5160 !streq(verbs[i].verb, "mask") &&
5161 !streq(verbs[i].verb, "unmask") &&
5162 !streq(verbs[i].verb, "link")) {
5164 if (running_in_chroot() > 0) {
5165 log_info("Running in chroot, ignoring request.");
5169 if (((!streq(verbs[i].verb, "reboot") &&
5170 !streq(verbs[i].verb, "halt") &&
5171 !streq(verbs[i].verb, "poweroff")) || arg_force <= 0) && !bus) {
5172 log_error("Failed to get D-Bus connection: %s",
5173 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5179 if (!bus && !avoid_bus()) {
5180 log_error("Failed to get D-Bus connection: %s",
5181 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5186 return verbs[i].dispatch(bus, argv + optind);
5189 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
5191 struct msghdr msghdr;
5192 struct iovec iovec[2];
5193 union sockaddr_union sockaddr;
5194 struct sd_shutdown_command c;
5196 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
5203 c.dry_run = dry_run;
5207 sockaddr.sa.sa_family = AF_UNIX;
5208 strncpy(sockaddr.un.sun_path, "/run/systemd/shutdownd", sizeof(sockaddr.un.sun_path));
5211 msghdr.msg_name = &sockaddr;
5212 msghdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + sizeof("/run/systemd/shutdownd") - 1;
5215 iovec[0].iov_base = (char*) &c;
5216 iovec[0].iov_len = offsetof(struct sd_shutdown_command, wall_message);
5218 if (isempty(message))
5219 msghdr.msg_iovlen = 1;
5221 iovec[1].iov_base = (char*) message;
5222 iovec[1].iov_len = strlen(message);
5223 msghdr.msg_iovlen = 2;
5225 msghdr.msg_iov = iovec;
5227 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0) {
5228 close_nointr_nofail(fd);
5232 close_nointr_nofail(fd);
5236 static int reload_with_fallback(DBusConnection *bus) {
5239 /* First, try systemd via D-Bus. */
5240 if (daemon_reload(bus, NULL) >= 0)
5244 /* Nothing else worked, so let's try signals */
5245 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
5247 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
5248 log_error("kill() failed: %m");
5255 static int start_with_fallback(DBusConnection *bus) {
5258 /* First, try systemd via D-Bus. */
5259 if (start_unit(bus, NULL) >= 0)
5263 /* Hmm, talking to systemd via D-Bus didn't work. Then
5264 * let's try to talk to Upstart via D-Bus. */
5265 if (talk_upstart() > 0)
5268 /* Nothing else worked, so let's try
5270 if (talk_initctl() > 0)
5273 log_error("Failed to talk to init daemon.");
5277 warn_wall(arg_action);
5281 static _noreturn_ void halt_now(enum action a) {
5283 /* Make sure C-A-D is handled by the kernel from this
5285 reboot(RB_ENABLE_CAD);
5290 log_info("Halting.");
5291 reboot(RB_HALT_SYSTEM);
5294 case ACTION_POWEROFF:
5295 log_info("Powering off.");
5296 reboot(RB_POWER_OFF);
5300 log_info("Rebooting.");
5301 reboot(RB_AUTOBOOT);
5305 assert_not_reached("Unknown halt action.");
5308 assert_not_reached("Uh? This shouldn't happen.");
5311 static int halt_main(DBusConnection *bus) {
5314 r = check_inhibitors(bus, arg_action);
5318 if (geteuid() != 0) {
5319 /* Try logind if we are a normal user and no special
5320 * mode applies. Maybe PolicyKit allows us to shutdown
5323 if (arg_when <= 0 &&
5326 (arg_action == ACTION_POWEROFF ||
5327 arg_action == ACTION_REBOOT)) {
5328 r = reboot_with_logind(bus, arg_action);
5333 log_error("Must be root.");
5340 m = strv_join(arg_wall, " ");
5341 r = send_shutdownd(arg_when,
5342 arg_action == ACTION_HALT ? 'H' :
5343 arg_action == ACTION_POWEROFF ? 'P' :
5344 arg_action == ACTION_KEXEC ? 'K' :
5352 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
5354 char date[FORMAT_TIMESTAMP_MAX];
5356 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
5357 format_timestamp(date, sizeof(date), arg_when));
5362 if (!arg_dry && !arg_force)
5363 return start_with_fallback(bus);
5366 if (sd_booted() > 0)
5367 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
5369 r = utmp_put_shutdown();
5371 log_warning("Failed to write utmp record: %s", strerror(-r));
5378 halt_now(arg_action);
5379 /* We should never reach this. */
5383 static int runlevel_main(void) {
5384 int r, runlevel, previous;
5386 r = utmp_get_runlevel(&runlevel, &previous);
5393 previous <= 0 ? 'N' : previous,
5394 runlevel <= 0 ? 'N' : runlevel);
5399 int main(int argc, char*argv[]) {
5400 int r, retval = EXIT_FAILURE;
5401 DBusConnection *bus = NULL;
5404 dbus_error_init(&error);
5406 setlocale(LC_ALL, "");
5407 log_parse_environment();
5410 r = parse_argv(argc, argv);
5414 retval = EXIT_SUCCESS;
5418 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
5419 * let's shortcut this */
5420 if (arg_action == ACTION_RUNLEVEL) {
5421 r = runlevel_main();
5422 retval = r < 0 ? EXIT_FAILURE : r;
5426 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
5427 log_info("Running in chroot, ignoring request.");
5433 if (arg_transport == TRANSPORT_NORMAL)
5434 bus_connect(arg_scope == UNIT_FILE_SYSTEM ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &bus, &private_bus, &error);
5435 else if (arg_transport == TRANSPORT_POLKIT) {
5436 bus_connect_system_polkit(&bus, &error);
5437 private_bus = false;
5438 } else if (arg_transport == TRANSPORT_SSH) {
5439 bus_connect_system_ssh(NULL, arg_host, &bus, &error);
5440 private_bus = false;
5442 assert_not_reached("Uh, invalid transport...");
5445 switch (arg_action) {
5447 case ACTION_SYSTEMCTL:
5448 r = systemctl_main(bus, argc, argv, &error);
5452 case ACTION_POWEROFF:
5458 case ACTION_RUNLEVEL2:
5459 case ACTION_RUNLEVEL3:
5460 case ACTION_RUNLEVEL4:
5461 case ACTION_RUNLEVEL5:
5463 case ACTION_EMERGENCY:
5464 case ACTION_DEFAULT:
5465 r = start_with_fallback(bus);
5470 r = reload_with_fallback(bus);
5473 case ACTION_CANCEL_SHUTDOWN: {
5477 m = strv_join(arg_wall, " ");
5479 retval = EXIT_FAILURE;
5483 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
5485 log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r));
5490 case ACTION_INVALID:
5491 case ACTION_RUNLEVEL:
5493 assert_not_reached("Unknown action");
5496 retval = r < 0 ? EXIT_FAILURE : r;
5500 dbus_connection_flush(bus);
5501 dbus_connection_close(bus);
5502 dbus_connection_unref(bus);
5505 dbus_error_free(&error);
5509 strv_free(arg_property);
5512 ask_password_agent_close();
5513 polkit_agent_close();