1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
22 #include <sys/reboot.h>
29 #include <sys/ioctl.h>
33 #include <sys/socket.h>
36 #include <sys/prctl.h>
37 #include <dbus/dbus.h>
39 #include <systemd/sd-daemon.h>
40 #include <systemd/sd-shutdown.h>
46 #include "utmp-wtmp.h"
49 #include "path-util.h"
51 #include "dbus-common.h"
52 #include "cgroup-show.h"
53 #include "cgroup-util.h"
55 #include "path-lookup.h"
56 #include "conf-parser.h"
57 #include "exit-status.h"
58 #include "bus-errors.h"
60 #include "unit-name.h"
62 #include "spawn-ask-password-agent.h"
63 #include "spawn-polkit-agent.h"
65 #include "logs-show.h"
66 #include "path-util.h"
67 #include "socket-util.h"
69 static const char *arg_type = NULL;
70 static const char *arg_load_state = NULL;
71 static char **arg_property = NULL;
72 static bool arg_all = false;
73 static const char *arg_job_mode = "replace";
74 static UnitFileScope arg_scope = UNIT_FILE_SYSTEM;
75 static bool arg_no_block = false;
76 static bool arg_no_legend = false;
77 static bool arg_no_pager = false;
78 static bool arg_no_wtmp = false;
79 static bool arg_no_wall = false;
80 static bool arg_no_reload = false;
81 static bool arg_ignore_inhibitors = false;
82 static bool arg_dry = false;
83 static bool arg_quiet = false;
84 static bool arg_full = false;
85 static int arg_force = 0;
86 static bool arg_ask_password = true;
87 static bool arg_failed = false;
88 static bool arg_runtime = false;
89 static char **arg_wall = NULL;
90 static const char *arg_kill_who = NULL;
91 static int arg_signal = SIGTERM;
92 static const char *arg_root = NULL;
93 static usec_t arg_when = 0;
115 ACTION_CANCEL_SHUTDOWN,
117 } arg_action = ACTION_SYSTEMCTL;
123 static enum transport {
127 } arg_transport = TRANSPORT_NORMAL;
128 static const char *arg_host = NULL;
129 static unsigned arg_lines = 10;
130 static OutputMode arg_output = OUTPUT_SHORT;
132 static bool private_bus = false;
134 static int daemon_reload(DBusConnection *bus, char **args);
135 static void halt_now(enum action a);
137 static void pager_open_if_enabled(void) {
145 static void ask_password_agent_open_if_enabled(void) {
147 /* Open the password agent as a child process if necessary */
149 if (!arg_ask_password)
152 if (arg_scope != UNIT_FILE_SYSTEM)
155 ask_password_agent_open();
159 static void polkit_agent_open_if_enabled(void) {
161 /* Open the polkit agent as a child process if necessary */
163 if (!arg_ask_password)
166 if (arg_scope != UNIT_FILE_SYSTEM)
173 static const char *ansi_highlight(bool b) {
178 return b ? ANSI_HIGHLIGHT_ON : ANSI_HIGHLIGHT_OFF;
181 static const char *ansi_highlight_red(bool b) {
186 return b ? ANSI_HIGHLIGHT_RED_ON : ANSI_HIGHLIGHT_OFF;
189 static const char *ansi_highlight_green(bool b) {
194 return b ? ANSI_HIGHLIGHT_GREEN_ON : ANSI_HIGHLIGHT_OFF;
197 static int translate_bus_error_to_exit_status(int r, const DBusError *error) {
200 if (!dbus_error_is_set(error))
203 if (dbus_error_has_name(error, DBUS_ERROR_ACCESS_DENIED) ||
204 dbus_error_has_name(error, BUS_ERROR_ONLY_BY_DEPENDENCY) ||
205 dbus_error_has_name(error, BUS_ERROR_NO_ISOLATION) ||
206 dbus_error_has_name(error, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE))
207 return EXIT_NOPERMISSION;
209 if (dbus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT))
210 return EXIT_NOTINSTALLED;
212 if (dbus_error_has_name(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE) ||
213 dbus_error_has_name(error, BUS_ERROR_NOT_SUPPORTED))
214 return EXIT_NOTIMPLEMENTED;
216 if (dbus_error_has_name(error, BUS_ERROR_LOAD_FAILED))
217 return EXIT_NOTCONFIGURED;
225 static void warn_wall(enum action a) {
226 static const char *table[_ACTION_MAX] = {
227 [ACTION_HALT] = "The system is going down for system halt NOW!",
228 [ACTION_REBOOT] = "The system is going down for reboot NOW!",
229 [ACTION_POWEROFF] = "The system is going down for power-off NOW!",
230 [ACTION_KEXEC] = "The system is going down for kexec reboot NOW!",
231 [ACTION_RESCUE] = "The system is going down to rescue mode NOW!",
232 [ACTION_EMERGENCY] = "The system is going down to emergency mode NOW!",
233 [ACTION_CANCEL_SHUTDOWN] = "The system shutdown has been cancelled NOW!"
240 _cleanup_free_ char *p;
242 p = strv_join(arg_wall, " ");
257 utmp_wall(table[a], NULL);
260 static bool avoid_bus(void) {
262 if (running_in_chroot() > 0)
265 if (sd_booted() <= 0)
268 if (!isempty(arg_root))
271 if (arg_scope == UNIT_FILE_GLOBAL)
279 const char *description;
280 const char *load_state;
281 const char *active_state;
282 const char *sub_state;
283 const char *following;
284 const char *unit_path;
286 const char *job_type;
287 const char *job_path;
290 static int compare_unit_info(const void *a, const void *b) {
292 const struct unit_info *u = a, *v = b;
294 d1 = strrchr(u->id, '.');
295 d2 = strrchr(v->id, '.');
300 r = strcasecmp(d1, d2);
305 return strcasecmp(u->id, v->id);
308 static bool output_show_unit(const struct unit_info *u) {
312 return streq(u->active_state, "failed");
314 return (!arg_type || ((dot = strrchr(u->id, '.')) &&
315 streq(dot+1, arg_type))) &&
316 (!arg_load_state || streq(u->load_state, arg_load_state)) &&
317 (arg_all || !(streq(u->active_state, "inactive")
318 || u->following[0]) || u->job_id > 0);
321 static void output_units_list(const struct unit_info *unit_infos, unsigned c) {
322 unsigned id_len, max_id_len, active_len, sub_len, job_len, desc_len, n_shown = 0;
323 const struct unit_info *u;
326 max_id_len = sizeof("UNIT")-1;
327 active_len = sizeof("ACTIVE")-1;
328 sub_len = sizeof("SUB")-1;
329 job_len = sizeof("JOB")-1;
332 for (u = unit_infos; u < unit_infos + c; u++) {
333 if (!output_show_unit(u))
336 max_id_len = MAX(max_id_len, strlen(u->id));
337 active_len = MAX(active_len, strlen(u->active_state));
338 sub_len = MAX(sub_len, strlen(u->sub_state));
339 if (u->job_id != 0) {
340 job_len = MAX(job_len, strlen(u->job_type));
347 id_len = MIN(max_id_len, 25);
348 basic_len = 5 + id_len + 5 + active_len + sub_len;
350 basic_len += job_len + 1;
351 if (basic_len < (unsigned) columns()) {
352 unsigned extra_len, incr;
353 extra_len = columns() - basic_len;
354 /* Either UNIT already got 25, or is fully satisfied.
355 * Grant up to 25 to DESC now. */
356 incr = MIN(extra_len, 25);
359 /* split the remaining space between UNIT and DESC,
360 * but do not give UNIT more than it needs. */
362 incr = MIN(extra_len / 2, max_id_len - id_len);
364 desc_len += extra_len - incr;
370 for (u = unit_infos; u < unit_infos + c; u++) {
372 const char *on_loaded, *off_loaded;
373 const char *on_active, *off_active;
375 if (!output_show_unit(u))
378 if (!n_shown && !arg_no_legend) {
379 printf("%-*s %-6s %-*s %-*s ", id_len, "UNIT", "LOAD",
380 active_len, "ACTIVE", sub_len, "SUB");
382 printf("%-*s ", job_len, "JOB");
383 if (!arg_full && arg_no_pager)
384 printf("%.*s\n", desc_len, "DESCRIPTION");
386 printf("%s\n", "DESCRIPTION");
391 if (streq(u->load_state, "error")) {
392 on_loaded = ansi_highlight_red(true);
393 off_loaded = ansi_highlight_red(false);
395 on_loaded = off_loaded = "";
397 if (streq(u->active_state, "failed")) {
398 on_active = ansi_highlight_red(true);
399 off_active = ansi_highlight_red(false);
401 on_active = off_active = "";
403 e = arg_full ? NULL : ellipsize(u->id, id_len, 33);
405 printf("%-*s %s%-6s%s %s%-*s %-*s%s %-*s",
406 id_len, e ? e : u->id,
407 on_loaded, u->load_state, off_loaded,
408 on_active, active_len, u->active_state,
409 sub_len, u->sub_state, off_active,
410 job_count ? job_len + 1 : 0, u->job_id ? u->job_type : "");
411 if (!arg_full && arg_no_pager)
412 printf("%.*s\n", desc_len, u->description);
414 printf("%s\n", u->description);
419 if (!arg_no_legend) {
420 const char *on, *off;
423 printf("\nLOAD = Reflects whether the unit definition was properly loaded.\n"
424 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
425 "SUB = The low-level unit activation state, values depend on unit type.\n");
427 printf("JOB = Pending job for the unit.\n");
429 on = ansi_highlight(true);
430 off = ansi_highlight(false);
432 on = ansi_highlight_red(true);
433 off = ansi_highlight_red(false);
437 printf("%s%u loaded units listed.%s\n"
438 "To show all installed unit files use 'systemctl list-unit-files'.\n",
441 printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
442 "To show all installed unit files use 'systemctl list-unit-files'.\n",
447 static int list_units(DBusConnection *bus, char **args) {
448 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
449 _cleanup_free_ struct unit_info *unit_infos = NULL;
450 DBusMessageIter iter, sub, sub2;
451 unsigned c = 0, n_units = 0;
454 pager_open_if_enabled();
456 r = bus_method_call_with_reply(
458 "org.freedesktop.systemd1",
459 "/org/freedesktop/systemd1",
460 "org.freedesktop.systemd1.Manager",
468 if (!dbus_message_iter_init(reply, &iter) ||
469 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
470 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
471 log_error("Failed to parse reply.");
475 dbus_message_iter_recurse(&iter, &sub);
477 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
480 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT);
485 n_units = MAX(2*c, 16);
486 w = realloc(unit_infos, sizeof(struct unit_info) * n_units);
495 dbus_message_iter_recurse(&sub, &sub2);
497 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->id, true) < 0 ||
498 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->description, true) < 0 ||
499 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->load_state, true) < 0 ||
500 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->active_state, true) < 0 ||
501 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->sub_state, true) < 0 ||
502 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->following, true) < 0 ||
503 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &u->unit_path, true) < 0 ||
504 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &u->job_id, true) < 0 ||
505 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->job_type, true) < 0 ||
506 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &u->job_path, false) < 0) {
507 log_error("Failed to parse reply.");
511 dbus_message_iter_next(&sub);
516 qsort(unit_infos, c, sizeof(struct unit_info), compare_unit_info);
517 output_units_list(unit_infos, c);
523 static int compare_unit_file_list(const void *a, const void *b) {
525 const UnitFileList *u = a, *v = b;
527 d1 = strrchr(u->path, '.');
528 d2 = strrchr(v->path, '.');
533 r = strcasecmp(d1, d2);
538 return strcasecmp(path_get_file_name(u->path), path_get_file_name(v->path));
541 static bool output_show_unit_file(const UnitFileList *u) {
544 return !arg_type || ((dot = strrchr(u->path, '.')) && streq(dot+1, arg_type));
547 static void output_unit_file_list(const UnitFileList *units, unsigned c) {
548 unsigned max_id_len, id_cols, state_cols, n_shown = 0;
549 const UnitFileList *u;
551 max_id_len = sizeof("UNIT FILE")-1;
552 state_cols = sizeof("STATE")-1;
553 for (u = units; u < units + c; u++) {
554 if (!output_show_unit_file(u))
557 max_id_len = MAX(max_id_len, strlen(path_get_file_name(u->path)));
558 state_cols = MAX(state_cols, strlen(unit_file_state_to_string(u->state)));
563 id_cols = MIN(max_id_len, 25);
564 basic_cols = 1 + id_cols + state_cols;
565 if (basic_cols < (unsigned) columns())
566 id_cols += MIN(columns() - basic_cols, max_id_len - id_cols);
568 id_cols = max_id_len;
571 printf("%-*s %-*s\n", id_cols, "UNIT FILE", state_cols, "STATE");
573 for (u = units; u < units + c; u++) {
575 const char *on, *off;
578 if (!output_show_unit_file(u))
583 if (u->state == UNIT_FILE_MASKED ||
584 u->state == UNIT_FILE_MASKED_RUNTIME ||
585 u->state == UNIT_FILE_DISABLED ||
586 u->state == UNIT_FILE_INVALID) {
587 on = ansi_highlight_red(true);
588 off = ansi_highlight_red(false);
589 } else if (u->state == UNIT_FILE_ENABLED) {
590 on = ansi_highlight_green(true);
591 off = ansi_highlight_green(false);
595 id = path_get_file_name(u->path);
597 e = arg_full ? NULL : ellipsize(id, id_cols, 33);
599 printf("%-*s %s%-*s%s\n",
601 on, state_cols, unit_file_state_to_string(u->state), off);
607 printf("\n%u unit files listed.\n", n_shown);
610 static int list_unit_files(DBusConnection *bus, char **args) {
611 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
612 _cleanup_free_ UnitFileList *units = NULL;
613 DBusMessageIter iter, sub, sub2;
614 unsigned c = 0, n_units = 0;
617 pager_open_if_enabled();
624 h = hashmap_new(string_hash_func, string_compare_func);
628 r = unit_file_get_list(arg_scope, arg_root, h);
630 unit_file_list_free(h);
631 log_error("Failed to get unit file list: %s", strerror(-r));
635 n_units = hashmap_size(h);
636 units = new(UnitFileList, n_units);
638 unit_file_list_free(h);
642 HASHMAP_FOREACH(u, h, i) {
643 memcpy(units + c++, u, sizeof(UnitFileList));
649 r = bus_method_call_with_reply(
651 "org.freedesktop.systemd1",
652 "/org/freedesktop/systemd1",
653 "org.freedesktop.systemd1.Manager",
661 if (!dbus_message_iter_init(reply, &iter) ||
662 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
663 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
664 log_error("Failed to parse reply.");
668 dbus_message_iter_recurse(&iter, &sub);
670 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
674 assert(dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT);
679 n_units = MAX(2*c, 16);
680 w = realloc(units, sizeof(struct UnitFileList) * n_units);
689 dbus_message_iter_recurse(&sub, &sub2);
691 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->path, true) < 0 ||
692 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, false) < 0) {
693 log_error("Failed to parse reply.");
697 u->state = unit_file_state_from_string(state);
699 dbus_message_iter_next(&sub);
705 qsort(units, c, sizeof(UnitFileList), compare_unit_file_list);
706 output_unit_file_list(units, c);
712 static int dot_one_property(const char *name, const char *prop, DBusMessageIter *iter) {
714 static const char * const colors[] = {
715 "Requires", "[color=\"black\"]",
716 "RequiresOverridable", "[color=\"black\"]",
717 "Requisite", "[color=\"darkblue\"]",
718 "RequisiteOverridable", "[color=\"darkblue\"]",
719 "Wants", "[color=\"grey66\"]",
720 "Conflicts", "[color=\"red\"]",
721 "ConflictedBy", "[color=\"red\"]",
722 "After", "[color=\"green\"]"
725 const char *c = NULL;
732 for (i = 0; i < ELEMENTSOF(colors); i += 2)
733 if (streq(colors[i], prop)) {
741 if (arg_dot != DOT_ALL)
742 if ((arg_dot == DOT_ORDER) != streq(prop, "After"))
745 switch (dbus_message_iter_get_arg_type(iter)) {
747 case DBUS_TYPE_ARRAY:
749 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING) {
752 dbus_message_iter_recurse(iter, &sub);
754 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
757 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING);
758 dbus_message_iter_get_basic(&sub, &s);
759 printf("\t\"%s\"->\"%s\" %s;\n", name, s, c);
761 dbus_message_iter_next(&sub);
771 static int dot_one(DBusConnection *bus, const char *name, const char *path) {
772 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
773 const char *interface = "org.freedesktop.systemd1.Unit";
775 DBusMessageIter iter, sub, sub2, sub3;
780 r = bus_method_call_with_reply(
782 "org.freedesktop.systemd1",
784 "org.freedesktop.DBus.Properties",
788 DBUS_TYPE_STRING, &interface,
793 if (!dbus_message_iter_init(reply, &iter) ||
794 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
795 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
796 log_error("Failed to parse reply.");
800 dbus_message_iter_recurse(&iter, &sub);
802 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
805 assert(dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_DICT_ENTRY);
806 dbus_message_iter_recurse(&sub, &sub2);
808 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &prop, true) < 0 ||
809 dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
810 log_error("Failed to parse reply.");
814 dbus_message_iter_recurse(&sub2, &sub3);
815 r = dot_one_property(name, prop, &sub3);
819 dbus_message_iter_next(&sub);
825 static int dot(DBusConnection *bus, char **args) {
826 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
827 DBusMessageIter iter, sub, sub2;
830 r = bus_method_call_with_reply(
832 "org.freedesktop.systemd1",
833 "/org/freedesktop/systemd1",
834 "org.freedesktop.systemd1.Manager",
842 if (!dbus_message_iter_init(reply, &iter) ||
843 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
844 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
845 log_error("Failed to parse reply.");
849 printf("digraph systemd {\n");
851 dbus_message_iter_recurse(&iter, &sub);
852 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
853 const char *id, *description, *load_state, *active_state, *sub_state, *following, *unit_path;
855 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
856 log_error("Failed to parse reply.");
860 dbus_message_iter_recurse(&sub, &sub2);
862 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &id, true) < 0 ||
863 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &description, true) < 0 ||
864 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &load_state, true) < 0 ||
865 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &active_state, true) < 0 ||
866 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &sub_state, true) < 0 ||
867 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &following, true) < 0 ||
868 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, true) < 0) {
869 log_error("Failed to parse reply.");
873 r = dot_one(bus, id, unit_path);
877 /* printf("\t\"%s\";\n", id); */
878 dbus_message_iter_next(&sub);
883 log_info(" Color legend: black = Requires\n"
884 " dark blue = Requisite\n"
885 " dark grey = Wants\n"
890 log_notice("-- You probably want to process this output with graphviz' dot tool.\n"
891 "-- Try a shell pipeline like 'systemctl dot | dot -Tsvg > systemd.svg'!\n");
896 static int list_jobs(DBusConnection *bus, char **args) {
897 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
898 DBusMessageIter iter, sub, sub2;
902 pager_open_if_enabled();
904 r = bus_method_call_with_reply(
906 "org.freedesktop.systemd1",
907 "/org/freedesktop/systemd1",
908 "org.freedesktop.systemd1.Manager",
916 if (!dbus_message_iter_init(reply, &iter) ||
917 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
918 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
919 log_error("Failed to parse reply.");
923 dbus_message_iter_recurse(&iter, &sub);
926 printf("%4s %-25s %-15s %-7s\n", "JOB", "UNIT", "TYPE", "STATE");
928 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
929 const char *name, *type, *state, *job_path, *unit_path;
933 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
934 log_error("Failed to parse reply.");
938 dbus_message_iter_recurse(&sub, &sub2);
940 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &id, true) < 0 ||
941 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
942 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
943 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, true) < 0 ||
944 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &job_path, true) < 0 ||
945 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, false) < 0) {
946 log_error("Failed to parse reply.");
950 e = arg_full ? NULL : ellipsize(name, 25, 33);
951 printf("%4u %-25s %-15s %-7s\n", id, e ? e : name, type, state);
956 dbus_message_iter_next(&sub);
960 printf("\n%u jobs listed.\n", k);
965 static int load_unit(DBusConnection *bus, char **args) {
970 STRV_FOREACH(name, args+1) {
971 _cleanup_free_ char *n = NULL;
974 n = unit_name_mangle(*name);
978 r = bus_method_call_with_reply(
980 "org.freedesktop.systemd1",
981 "/org/freedesktop/systemd1",
982 "org.freedesktop.systemd1.Manager",
986 DBUS_TYPE_STRING, &n,
995 static int cancel_job(DBusConnection *bus, char **args) {
1000 if (strv_length(args) <= 1)
1001 return daemon_reload(bus, args);
1003 STRV_FOREACH(name, args+1) {
1007 r = safe_atou32(*name, &id);
1009 log_error("Failed to parse job id: %s", strerror(-r));
1013 r = bus_method_call_with_reply(
1015 "org.freedesktop.systemd1",
1016 "/org/freedesktop/systemd1",
1017 "org.freedesktop.systemd1.Manager",
1021 DBUS_TYPE_UINT32, &id,
1030 static bool need_daemon_reload(DBusConnection *bus, const char *unit) {
1031 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1032 dbus_bool_t b = FALSE;
1033 DBusMessageIter iter, sub;
1035 *interface = "org.freedesktop.systemd1.Unit",
1036 *property = "NeedDaemonReload",
1038 _cleanup_free_ char *n = NULL;
1041 /* We ignore all errors here, since this is used to show a warning only */
1043 n = unit_name_mangle(unit);
1047 r = bus_method_call_with_reply (
1049 "org.freedesktop.systemd1",
1050 "/org/freedesktop/systemd1",
1051 "org.freedesktop.systemd1.Manager",
1055 DBUS_TYPE_STRING, &n,
1060 if (!dbus_message_get_args(reply, NULL,
1061 DBUS_TYPE_OBJECT_PATH, &path,
1065 dbus_message_unref(reply);
1068 r = bus_method_call_with_reply(
1070 "org.freedesktop.systemd1",
1072 "org.freedesktop.DBus.Properties",
1076 DBUS_TYPE_STRING, &interface,
1077 DBUS_TYPE_STRING, &property,
1082 if (!dbus_message_iter_init(reply, &iter) ||
1083 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
1086 dbus_message_iter_recurse(&iter, &sub);
1087 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_BOOLEAN)
1090 dbus_message_iter_get_basic(&sub, &b);
1094 typedef struct WaitData {
1101 static DBusHandlerResult wait_filter(DBusConnection *connection, DBusMessage *message, void *data) {
1109 dbus_error_init(&error);
1111 log_debug("Got D-Bus request: %s.%s() on %s",
1112 dbus_message_get_interface(message),
1113 dbus_message_get_member(message),
1114 dbus_message_get_path(message));
1116 if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
1117 log_error("Warning! D-Bus connection terminated.");
1118 dbus_connection_close(connection);
1120 } else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
1122 const char *path, *result, *unit;
1124 if (dbus_message_get_args(message, &error,
1125 DBUS_TYPE_UINT32, &id,
1126 DBUS_TYPE_OBJECT_PATH, &path,
1127 DBUS_TYPE_STRING, &unit,
1128 DBUS_TYPE_STRING, &result,
1129 DBUS_TYPE_INVALID)) {
1131 free(set_remove(d->set, (char*) path));
1133 if (!isempty(result))
1134 d->result = strdup(result);
1137 d->name = strdup(unit);
1142 dbus_error_free(&error);
1143 if (dbus_message_get_args(message, &error,
1144 DBUS_TYPE_UINT32, &id,
1145 DBUS_TYPE_OBJECT_PATH, &path,
1146 DBUS_TYPE_STRING, &result,
1147 DBUS_TYPE_INVALID)) {
1148 /* Compatibility with older systemd versions <
1149 * 183 during upgrades. This should be dropped
1151 free(set_remove(d->set, (char*) path));
1154 d->result = strdup(result);
1160 log_error("Failed to parse message: %s", bus_error_message(&error));
1164 dbus_error_free(&error);
1165 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1168 static int enable_wait_for_jobs(DBusConnection *bus) {
1176 dbus_error_init(&error);
1177 dbus_bus_add_match(bus,
1179 "sender='org.freedesktop.systemd1',"
1180 "interface='org.freedesktop.systemd1.Manager',"
1181 "member='JobRemoved',"
1182 "path='/org/freedesktop/systemd1'",
1185 if (dbus_error_is_set(&error)) {
1186 log_error("Failed to add match: %s", bus_error_message(&error));
1187 dbus_error_free(&error);
1191 /* This is slightly dirty, since we don't undo the match registrations. */
1195 static int wait_for_jobs(DBusConnection *bus, Set *s) {
1205 if (!dbus_connection_add_filter(bus, wait_filter, &d, NULL))
1208 while (!set_isempty(s)) {
1210 if (!dbus_connection_read_write_dispatch(bus, -1)) {
1211 log_error("Disconnected from bus.");
1212 return -ECONNREFUSED;
1219 if (streq(d.result, "timeout"))
1220 log_error("Job for %s timed out.", strna(d.name));
1221 else if (streq(d.result, "canceled"))
1222 log_error("Job for %s canceled.", strna(d.name));
1223 else if (streq(d.result, "dependency"))
1224 log_error("A dependency job for %s failed. See 'journalctl -xn' for details.", strna(d.name));
1225 else if (!streq(d.result, "done") && !streq(d.result, "skipped"))
1226 log_error("Job for %s failed. See 'systemctl status %s' and 'journalctl -xn' for details.", strna(d.name), strna(d.name));
1229 if (streq_ptr(d.result, "timeout"))
1231 else if (streq_ptr(d.result, "canceled"))
1233 else if (!streq_ptr(d.result, "done") && !streq_ptr(d.result, "skipped"))
1244 dbus_connection_remove_filter(bus, wait_filter, &d);
1248 static int check_one_unit(DBusConnection *bus, const char *name, char **check_states, bool quiet) {
1249 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1250 _cleanup_free_ char *n = NULL;
1251 DBusMessageIter iter, sub;
1253 *interface = "org.freedesktop.systemd1.Unit",
1254 *property = "ActiveState";
1255 const char *state, *path;
1261 dbus_error_init(&error);
1263 n = unit_name_mangle(name);
1267 r = bus_method_call_with_reply (
1269 "org.freedesktop.systemd1",
1270 "/org/freedesktop/systemd1",
1271 "org.freedesktop.systemd1.Manager",
1275 DBUS_TYPE_STRING, &n,
1278 dbus_error_free(&error);
1285 if (!dbus_message_get_args(reply, NULL,
1286 DBUS_TYPE_OBJECT_PATH, &path,
1287 DBUS_TYPE_INVALID)) {
1288 log_error("Failed to parse reply.");
1292 dbus_message_unref(reply);
1295 r = bus_method_call_with_reply(
1297 "org.freedesktop.systemd1",
1299 "org.freedesktop.DBus.Properties",
1303 DBUS_TYPE_STRING, &interface,
1304 DBUS_TYPE_STRING, &property,
1312 if (!dbus_message_iter_init(reply, &iter) ||
1313 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1314 log_error("Failed to parse reply.");
1318 dbus_message_iter_recurse(&iter, &sub);
1320 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1321 log_error("Failed to parse reply.");
1325 dbus_message_iter_get_basic(&sub, &state);
1330 return strv_find(check_states, state) ? 1 : 0;
1333 static void check_triggering_units(
1334 DBusConnection *bus,
1335 const char *unit_name) {
1337 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1338 DBusMessageIter iter, sub;
1339 const char *interface = "org.freedesktop.systemd1.Unit",
1340 *triggered_by_property = "TriggeredBy";
1341 char _cleanup_free_ *unit_path = NULL, *n = NULL;
1342 bool print_warning_label = true;
1345 n = unit_name_mangle(unit_name);
1351 unit_path = unit_dbus_path_from_name(n);
1357 r = bus_method_call_with_reply(
1359 "org.freedesktop.systemd1",
1361 "org.freedesktop.DBus.Properties",
1365 DBUS_TYPE_STRING, &interface,
1366 DBUS_TYPE_STRING, &triggered_by_property,
1371 if (!dbus_message_iter_init(reply, &iter) ||
1372 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1373 log_error("Failed to parse reply.");
1377 dbus_message_iter_recurse(&iter, &sub);
1378 dbus_message_iter_recurse(&sub, &iter);
1381 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1382 const char * const check_states[] = {
1387 const char *service_trigger;
1389 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1390 log_error("Failed to parse reply.");
1394 dbus_message_iter_get_basic(&sub, &service_trigger);
1396 r = check_one_unit(bus, service_trigger, (char**) check_states, true);
1400 if (print_warning_label) {
1401 log_warning("Warning: Stopping %s, but it can still be activated by:", unit_name);
1402 print_warning_label = false;
1405 log_warning(" %s", service_trigger);
1408 dbus_message_iter_next(&sub);
1412 static int start_unit_one(
1413 DBusConnection *bus,
1420 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1421 _cleanup_free_ char *n;
1430 n = unit_name_mangle(name);
1434 r = bus_method_call_with_reply(
1436 "org.freedesktop.systemd1",
1437 "/org/freedesktop/systemd1",
1438 "org.freedesktop.systemd1.Manager",
1442 DBUS_TYPE_STRING, &n,
1443 DBUS_TYPE_STRING, &mode,
1446 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
1447 /* There's always a fallback possible for
1448 * legacy actions. */
1451 log_error("Failed to issue method call: %s", bus_error_message(error));
1456 if (!dbus_message_get_args(reply, error,
1457 DBUS_TYPE_OBJECT_PATH, &path,
1458 DBUS_TYPE_INVALID)) {
1459 log_error("Failed to parse reply: %s", bus_error_message(error));
1463 if (need_daemon_reload(bus, n))
1464 log_warning("Warning: Unit file of %s changed on disk, 'systemctl %s daemon-reload' recommended.",
1465 n, arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
1477 log_error("Failed to add path to set.");
1485 static enum action verb_to_action(const char *verb) {
1486 if (streq(verb, "halt"))
1488 else if (streq(verb, "poweroff"))
1489 return ACTION_POWEROFF;
1490 else if (streq(verb, "reboot"))
1491 return ACTION_REBOOT;
1492 else if (streq(verb, "kexec"))
1493 return ACTION_KEXEC;
1494 else if (streq(verb, "rescue"))
1495 return ACTION_RESCUE;
1496 else if (streq(verb, "emergency"))
1497 return ACTION_EMERGENCY;
1498 else if (streq(verb, "default"))
1499 return ACTION_DEFAULT;
1500 else if (streq(verb, "exit"))
1502 else if (streq(verb, "suspend"))
1503 return ACTION_SUSPEND;
1504 else if (streq(verb, "hibernate"))
1505 return ACTION_HIBERNATE;
1506 else if (streq(verb, "hybrid-sleep"))
1507 return ACTION_HYBRID_SLEEP;
1509 return ACTION_INVALID;
1512 static int start_unit(DBusConnection *bus, char **args) {
1514 static const char * const table[_ACTION_MAX] = {
1515 [ACTION_HALT] = SPECIAL_HALT_TARGET,
1516 [ACTION_POWEROFF] = SPECIAL_POWEROFF_TARGET,
1517 [ACTION_REBOOT] = SPECIAL_REBOOT_TARGET,
1518 [ACTION_KEXEC] = SPECIAL_KEXEC_TARGET,
1519 [ACTION_RUNLEVEL2] = SPECIAL_RUNLEVEL2_TARGET,
1520 [ACTION_RUNLEVEL3] = SPECIAL_RUNLEVEL3_TARGET,
1521 [ACTION_RUNLEVEL4] = SPECIAL_RUNLEVEL4_TARGET,
1522 [ACTION_RUNLEVEL5] = SPECIAL_RUNLEVEL5_TARGET,
1523 [ACTION_RESCUE] = SPECIAL_RESCUE_TARGET,
1524 [ACTION_EMERGENCY] = SPECIAL_EMERGENCY_TARGET,
1525 [ACTION_DEFAULT] = SPECIAL_DEFAULT_TARGET,
1526 [ACTION_EXIT] = SPECIAL_EXIT_TARGET,
1527 [ACTION_SUSPEND] = SPECIAL_SUSPEND_TARGET,
1528 [ACTION_HIBERNATE] = SPECIAL_HIBERNATE_TARGET,
1529 [ACTION_HYBRID_SLEEP] = SPECIAL_HYBRID_SLEEP_TARGET
1533 const char *method, *mode, *one_name;
1538 dbus_error_init(&error);
1542 ask_password_agent_open_if_enabled();
1544 if (arg_action == ACTION_SYSTEMCTL) {
1546 streq(args[0], "stop") ||
1547 streq(args[0], "condstop") ? "StopUnit" :
1548 streq(args[0], "reload") ? "ReloadUnit" :
1549 streq(args[0], "restart") ? "RestartUnit" :
1551 streq(args[0], "try-restart") ||
1552 streq(args[0], "condrestart") ? "TryRestartUnit" :
1554 streq(args[0], "reload-or-restart") ? "ReloadOrRestartUnit" :
1556 streq(args[0], "reload-or-try-restart") ||
1557 streq(args[0], "condreload") ||
1559 streq(args[0], "force-reload") ? "ReloadOrTryRestartUnit" :
1563 (streq(args[0], "isolate") ||
1564 streq(args[0], "rescue") ||
1565 streq(args[0], "emergency")) ? "isolate" : arg_job_mode;
1567 one_name = table[verb_to_action(args[0])];
1570 assert(arg_action < ELEMENTSOF(table));
1571 assert(table[arg_action]);
1573 method = "StartUnit";
1575 mode = (arg_action == ACTION_EMERGENCY ||
1576 arg_action == ACTION_RESCUE ||
1577 arg_action == ACTION_RUNLEVEL2 ||
1578 arg_action == ACTION_RUNLEVEL3 ||
1579 arg_action == ACTION_RUNLEVEL4 ||
1580 arg_action == ACTION_RUNLEVEL5) ? "isolate" : "replace";
1582 one_name = table[arg_action];
1585 if (!arg_no_block) {
1586 ret = enable_wait_for_jobs(bus);
1588 log_error("Could not watch jobs: %s", strerror(-ret));
1592 s = set_new(string_hash_func, string_compare_func);
1600 ret = start_unit_one(bus, method, one_name, mode, &error, s);
1602 ret = translate_bus_error_to_exit_status(ret, &error);
1604 STRV_FOREACH(name, args+1) {
1605 r = start_unit_one(bus, method, *name, mode, &error, s);
1607 ret = translate_bus_error_to_exit_status(r, &error);
1608 dbus_error_free(&error);
1613 if (!arg_no_block) {
1614 r = wait_for_jobs(bus, s);
1620 /* When stopping units, warn if they can still be triggered by
1621 * another active unit (socket, path, timer) */
1622 if (!arg_quiet && streq(method, "StopUnit")) {
1624 check_triggering_units(bus, one_name);
1626 STRV_FOREACH(name, args+1)
1627 check_triggering_units(bus, *name);
1633 dbus_error_free(&error);
1638 /* Ask systemd-logind, which might grant access to unprivileged users
1639 * through PolicyKit */
1640 static int reboot_with_logind(DBusConnection *bus, enum action a) {
1643 dbus_bool_t interactive = true;
1648 polkit_agent_open_if_enabled();
1656 case ACTION_POWEROFF:
1657 method = "PowerOff";
1660 case ACTION_SUSPEND:
1664 case ACTION_HIBERNATE:
1665 method = "Hibernate";
1668 case ACTION_HYBRID_SLEEP:
1669 method = "HybridSleep";
1676 return bus_method_call_with_reply(
1678 "org.freedesktop.login1",
1679 "/org/freedesktop/login1",
1680 "org.freedesktop.login1.Manager",
1684 DBUS_TYPE_BOOLEAN, &interactive,
1691 static int check_inhibitors(DBusConnection *bus, enum action a) {
1693 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1694 DBusMessageIter iter, sub, sub2;
1701 if (arg_ignore_inhibitors || arg_force > 0)
1713 r = bus_method_call_with_reply(
1715 "org.freedesktop.login1",
1716 "/org/freedesktop/login1",
1717 "org.freedesktop.login1.Manager",
1723 /* If logind is not around, then there are no inhibitors... */
1726 if (!dbus_message_iter_init(reply, &iter) ||
1727 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
1728 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
1729 log_error("Failed to parse reply.");
1733 dbus_message_iter_recurse(&iter, &sub);
1734 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1735 const char *what, *who, *why, *mode;
1737 _cleanup_strv_free_ char **sv = NULL;
1738 _cleanup_free_ char *comm = NULL;
1740 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
1741 log_error("Failed to parse reply.");
1745 dbus_message_iter_recurse(&sub, &sub2);
1747 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &what, true) < 0 ||
1748 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &who, true) < 0 ||
1749 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &why, true) < 0 ||
1750 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &mode, true) < 0 ||
1751 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &uid, true) < 0 ||
1752 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, false) < 0) {
1753 log_error("Failed to parse reply.");
1757 if (!streq(mode, "block"))
1760 sv = strv_split(what, ":");
1764 if (!strv_contains(sv,
1766 a == ACTION_POWEROFF ||
1767 a == ACTION_REBOOT ||
1768 a == ACTION_KEXEC ? "shutdown" : "sleep"))
1771 get_process_comm(pid, &comm);
1772 log_warning("Operation inhibited by \"%s\" (PID %lu \"%s\", UID %lu), reason is \"%s\".", who, (unsigned long) pid, strna(comm), (unsigned long) uid, why);
1776 dbus_message_iter_next(&sub);
1779 dbus_message_iter_recurse(&iter, &sub);
1784 log_error("Please try again after closing inhibitors or ignore them with 'systemctl %s -i'.",
1785 a == ACTION_HALT ? "halt" :
1786 a == ACTION_POWEROFF ? "poweroff" :
1787 a == ACTION_REBOOT ? "reboot" :
1788 a == ACTION_KEXEC ? "kexec" :
1789 a == ACTION_SUSPEND ? "suspend" :
1790 a == ACTION_HIBERNATE ? "hibernate" : "hybrid-sleep");
1798 static int start_special(DBusConnection *bus, char **args) {
1804 a = verb_to_action(args[0]);
1806 r = check_inhibitors(bus, a);
1810 if (arg_force >= 2 && geteuid() != 0) {
1811 log_error("Must be root.");
1815 if (arg_force >= 2 &&
1816 (a == ACTION_HALT ||
1817 a == ACTION_POWEROFF ||
1818 a == ACTION_REBOOT))
1821 if (arg_force >= 1 &&
1822 (a == ACTION_HALT ||
1823 a == ACTION_POWEROFF ||
1824 a == ACTION_REBOOT ||
1825 a == ACTION_KEXEC ||
1827 return daemon_reload(bus, args);
1829 /* first try logind, to allow authentication with polkit */
1830 if (geteuid() != 0 &&
1831 (a == ACTION_POWEROFF ||
1832 a == ACTION_REBOOT ||
1833 a == ACTION_SUSPEND ||
1834 a == ACTION_HIBERNATE ||
1835 a == ACTION_HYBRID_SLEEP)) {
1836 r = reboot_with_logind(bus, a);
1841 r = start_unit(bus, args);
1848 static int check_unit_active(DBusConnection *bus, char **args) {
1849 const char * const check_states[] = {
1856 int r = 3; /* According to LSB: "program is not running" */
1861 STRV_FOREACH(name, args+1) {
1864 state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
1874 static int check_unit_failed(DBusConnection *bus, char **args) {
1875 const char * const check_states[] = {
1886 STRV_FOREACH(name, args+1) {
1889 state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
1899 static int kill_unit(DBusConnection *bus, char **args) {
1907 arg_kill_who = "all";
1909 STRV_FOREACH(name, args+1) {
1910 _cleanup_free_ char *n = NULL;
1912 n = unit_name_mangle(*name);
1916 r = bus_method_call_with_reply(
1918 "org.freedesktop.systemd1",
1919 "/org/freedesktop/systemd1",
1920 "org.freedesktop.systemd1.Manager",
1924 DBUS_TYPE_STRING, &n,
1925 DBUS_TYPE_STRING, &arg_kill_who,
1926 DBUS_TYPE_INT32, &arg_signal,
1934 static int set_cgroup(DBusConnection *bus, char **args) {
1935 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
1938 DBusMessageIter iter;
1940 _cleanup_free_ char *n = NULL;
1945 dbus_error_init(&error);
1948 streq(args[0], "set-cgroup") ? "SetUnitControlGroups" :
1949 streq(args[0], "unset-group") ? "UnsetUnitControlGroups"
1950 : "UnsetUnitControlGroupAttributes";
1952 n = unit_name_mangle(args[1]);
1956 m = dbus_message_new_method_call(
1957 "org.freedesktop.systemd1",
1958 "/org/freedesktop/systemd1",
1959 "org.freedesktop.systemd1.Manager",
1964 dbus_message_iter_init_append(m, &iter);
1965 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &n))
1968 r = bus_append_strv_iter(&iter, args + 2);
1972 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
1974 log_error("Failed to issue method call: %s", bus_error_message(&error));
1975 dbus_error_free(&error);
1982 static int set_cgroup_attr(DBusConnection *bus, char **args) {
1983 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
1985 DBusMessageIter iter, sub, sub2;
1987 _cleanup_free_ char *n = NULL;
1992 dbus_error_init(&error);
1994 if (strv_length(args) % 2 != 0) {
1995 log_error("Expecting an uneven number of arguments!");
1999 n = unit_name_mangle(args[1]);
2003 m = dbus_message_new_method_call(
2004 "org.freedesktop.systemd1",
2005 "/org/freedesktop/systemd1",
2006 "org.freedesktop.systemd1.Manager",
2007 "SetUnitControlGroupAttributes");
2011 dbus_message_iter_init_append(m, &iter);
2012 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &n) ||
2013 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ss)", &sub))
2016 STRV_FOREACH_PAIR(x, y, args + 2) {
2017 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
2018 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, x) ||
2019 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, y) ||
2020 !dbus_message_iter_close_container(&sub, &sub2))
2024 if (!dbus_message_iter_close_container(&iter, &sub))
2027 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
2029 log_error("Failed to issue method call: %s", bus_error_message(&error));
2030 dbus_error_free(&error);
2037 typedef struct ExecStatusInfo {
2045 usec_t start_timestamp;
2046 usec_t exit_timestamp;
2051 LIST_FIELDS(struct ExecStatusInfo, exec);
2054 static void exec_status_info_free(ExecStatusInfo *i) {
2063 static int exec_status_info_deserialize(DBusMessageIter *sub, ExecStatusInfo *i) {
2064 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
2065 DBusMessageIter sub2, sub3;
2069 int32_t code, status;
2075 if (dbus_message_iter_get_arg_type(sub) != DBUS_TYPE_STRUCT)
2078 dbus_message_iter_recurse(sub, &sub2);
2080 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0)
2083 i->path = strdup(path);
2087 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_ARRAY ||
2088 dbus_message_iter_get_element_type(&sub2) != DBUS_TYPE_STRING)
2092 dbus_message_iter_recurse(&sub2, &sub3);
2093 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2094 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2095 dbus_message_iter_next(&sub3);
2099 i->argv = new0(char*, n+1);
2104 dbus_message_iter_recurse(&sub2, &sub3);
2105 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2108 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2109 dbus_message_iter_get_basic(&sub3, &s);
2110 dbus_message_iter_next(&sub3);
2112 i->argv[n] = strdup(s);
2119 if (!dbus_message_iter_next(&sub2) ||
2120 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, true) < 0 ||
2121 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp, true) < 0 ||
2122 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp_monotonic, true) < 0 ||
2123 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp, true) < 0 ||
2124 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp_monotonic, true) < 0 ||
2125 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, true) < 0 ||
2126 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &code, true) < 0 ||
2127 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &status, false) < 0)
2131 i->start_timestamp = (usec_t) start_timestamp;
2132 i->exit_timestamp = (usec_t) exit_timestamp;
2133 i->pid = (pid_t) pid;
2140 typedef struct UnitStatusInfo {
2142 const char *load_state;
2143 const char *active_state;
2144 const char *sub_state;
2145 const char *unit_file_state;
2147 const char *description;
2148 const char *following;
2150 char **documentation;
2152 const char *fragment_path;
2153 const char *source_path;
2154 const char *default_control_group;
2156 const char *load_error;
2159 usec_t inactive_exit_timestamp;
2160 usec_t inactive_exit_timestamp_monotonic;
2161 usec_t active_enter_timestamp;
2162 usec_t active_exit_timestamp;
2163 usec_t inactive_enter_timestamp;
2165 bool need_daemon_reload;
2170 const char *status_text;
2173 usec_t start_timestamp;
2174 usec_t exit_timestamp;
2176 int exit_code, exit_status;
2178 usec_t condition_timestamp;
2179 bool condition_result;
2182 unsigned n_accepted;
2183 unsigned n_connections;
2187 const char *sysfs_path;
2189 /* Mount, Automount */
2195 LIST_HEAD(ExecStatusInfo, exec);
2198 static void print_status_info(UnitStatusInfo *i) {
2200 const char *on, *off, *ss;
2202 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
2203 char since2[FORMAT_TIMESTAMP_MAX], *s2;
2208 /* This shows pretty information about a unit. See
2209 * print_property() for a low-level property printer */
2211 printf("%s", strna(i->id));
2213 if (i->description && !streq_ptr(i->id, i->description))
2214 printf(" - %s", i->description);
2219 printf("\t Follow: unit currently follows state of %s\n", i->following);
2221 if (streq_ptr(i->load_state, "error")) {
2222 on = ansi_highlight_red(true);
2223 off = ansi_highlight_red(false);
2227 path = i->source_path ? i->source_path : i->fragment_path;
2230 printf("\t Loaded: %s%s%s (Reason: %s)\n", on, strna(i->load_state), off, i->load_error);
2231 else if (path && i->unit_file_state)
2232 printf("\t Loaded: %s%s%s (%s; %s)\n", on, strna(i->load_state), off, path, i->unit_file_state);
2234 printf("\t Loaded: %s%s%s (%s)\n", on, strna(i->load_state), off, path);
2236 printf("\t Loaded: %s%s%s\n", on, strna(i->load_state), off);
2238 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
2240 if (streq_ptr(i->active_state, "failed")) {
2241 on = ansi_highlight_red(true);
2242 off = ansi_highlight_red(false);
2243 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
2244 on = ansi_highlight_green(true);
2245 off = ansi_highlight_green(false);
2250 printf("\t Active: %s%s (%s)%s",
2252 strna(i->active_state),
2256 printf("\t Active: %s%s%s",
2258 strna(i->active_state),
2261 if (!isempty(i->result) && !streq(i->result, "success"))
2262 printf(" (Result: %s)", i->result);
2264 timestamp = (streq_ptr(i->active_state, "active") ||
2265 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
2266 (streq_ptr(i->active_state, "inactive") ||
2267 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
2268 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
2269 i->active_exit_timestamp;
2271 s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
2272 s2 = format_timestamp(since2, sizeof(since2), timestamp);
2275 printf(" since %s; %s\n", s2, s1);
2277 printf(" since %s\n", s2);
2281 if (!i->condition_result && i->condition_timestamp > 0) {
2282 s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
2283 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
2286 printf("\t start condition failed at %s; %s\n", s2, s1);
2288 printf("\t start condition failed at %s\n", s2);
2292 printf("\t Device: %s\n", i->sysfs_path);
2294 printf("\t Where: %s\n", i->where);
2296 printf("\t What: %s\n", i->what);
2298 if (!strv_isempty(i->documentation)) {
2302 STRV_FOREACH(t, i->documentation) {
2304 printf("\t Docs: %s\n", *t);
2307 printf("\t %s\n", *t);
2312 printf("\tAccepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
2314 LIST_FOREACH(exec, p, i->exec) {
2315 _cleanup_free_ char *t = NULL;
2318 /* Only show exited processes here */
2322 t = strv_join(p->argv, " ");
2323 printf("\t Process: %u %s=%s ", p->pid, p->name, strna(t));
2325 good = is_clean_exit_lsb(p->code, p->status, NULL);
2327 on = ansi_highlight_red(true);
2328 off = ansi_highlight_red(false);
2332 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
2334 if (p->code == CLD_EXITED) {
2337 printf("status=%i", p->status);
2339 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
2344 printf("signal=%s", signal_to_string(p->status));
2346 printf(")%s\n", off);
2348 if (i->main_pid == p->pid &&
2349 i->start_timestamp == p->start_timestamp &&
2350 i->exit_timestamp == p->start_timestamp)
2351 /* Let's not show this twice */
2354 if (p->pid == i->control_pid)
2358 if (i->main_pid > 0 || i->control_pid > 0) {
2361 if (i->main_pid > 0) {
2362 printf("Main PID: %u", (unsigned) i->main_pid);
2365 _cleanup_free_ char *t = NULL;
2366 get_process_comm(i->main_pid, &t);
2369 } else if (i->exit_code > 0) {
2370 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
2372 if (i->exit_code == CLD_EXITED) {
2375 printf("status=%i", i->exit_status);
2377 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
2382 printf("signal=%s", signal_to_string(i->exit_status));
2387 if (i->main_pid > 0 && i->control_pid > 0)
2390 if (i->control_pid > 0) {
2391 _cleanup_free_ char *t = NULL;
2393 printf(" Control: %u", (unsigned) i->control_pid);
2395 get_process_comm(i->control_pid, &t);
2404 printf("\t Status: \"%s\"\n", i->status_text);
2406 if (i->default_control_group &&
2407 (i->main_pid > 0 || i->control_pid > 0 || cg_is_empty_by_spec(i->default_control_group, false) == 0)) {
2410 printf("\t CGroup: %s\n", i->default_control_group);
2412 if (arg_transport != TRANSPORT_SSH) {
2422 if (i->main_pid > 0)
2423 extra[k++] = i->main_pid;
2425 if (i->control_pid > 0)
2426 extra[k++] = i->control_pid;
2428 show_cgroup_and_extra_by_spec(i->default_control_group, "\t\t ", c, false, arg_all, extra, k);
2432 if (i->id && arg_transport != TRANSPORT_SSH) {
2434 arg_all * OUTPUT_SHOW_ALL |
2435 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
2436 on_tty() * OUTPUT_COLOR |
2437 !arg_quiet * OUTPUT_WARN_CUTOFF;
2440 show_journal_by_unit(stdout,
2444 i->inactive_exit_timestamp_monotonic,
2449 if (i->need_daemon_reload)
2450 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %s daemon-reload' recommended.\n",
2451 ansi_highlight_red(true),
2452 ansi_highlight_red(false),
2453 arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
2456 static void show_unit_help(UnitStatusInfo *i) {
2461 if (!i->documentation) {
2462 log_info("Documentation for %s not known.", i->id);
2466 STRV_FOREACH(p, i->documentation) {
2468 if (startswith(*p, "man:")) {
2471 char *page = NULL, *section = NULL;
2472 const char *args[4] = { "man", NULL, NULL, NULL };
2477 if ((*p)[k-1] == ')')
2478 e = strrchr(*p, '(');
2481 page = strndup((*p) + 4, e - *p - 4);
2487 section = strndup(e + 1, *p + k - e - 2);
2501 log_error("Failed to fork: %m");
2509 execvp(args[0], (char**) args);
2510 log_error("Failed to execute man: %m");
2511 _exit(EXIT_FAILURE);
2517 wait_for_terminate(pid, NULL);
2519 log_info("Can't show: %s", *p);
2523 static int status_property(const char *name, DBusMessageIter *iter, UnitStatusInfo *i) {
2529 switch (dbus_message_iter_get_arg_type(iter)) {
2531 case DBUS_TYPE_STRING: {
2534 dbus_message_iter_get_basic(iter, &s);
2537 if (streq(name, "Id"))
2539 else if (streq(name, "LoadState"))
2541 else if (streq(name, "ActiveState"))
2542 i->active_state = s;
2543 else if (streq(name, "SubState"))
2545 else if (streq(name, "Description"))
2547 else if (streq(name, "FragmentPath"))
2548 i->fragment_path = s;
2549 else if (streq(name, "SourcePath"))
2551 else if (streq(name, "DefaultControlGroup"))
2552 i->default_control_group = s;
2553 else if (streq(name, "StatusText"))
2555 else if (streq(name, "SysFSPath"))
2557 else if (streq(name, "Where"))
2559 else if (streq(name, "What"))
2561 else if (streq(name, "Following"))
2563 else if (streq(name, "UnitFileState"))
2564 i->unit_file_state = s;
2565 else if (streq(name, "Result"))
2572 case DBUS_TYPE_BOOLEAN: {
2575 dbus_message_iter_get_basic(iter, &b);
2577 if (streq(name, "Accept"))
2579 else if (streq(name, "NeedDaemonReload"))
2580 i->need_daemon_reload = b;
2581 else if (streq(name, "ConditionResult"))
2582 i->condition_result = b;
2587 case DBUS_TYPE_UINT32: {
2590 dbus_message_iter_get_basic(iter, &u);
2592 if (streq(name, "MainPID")) {
2594 i->main_pid = (pid_t) u;
2597 } else if (streq(name, "ControlPID"))
2598 i->control_pid = (pid_t) u;
2599 else if (streq(name, "ExecMainPID")) {
2601 i->main_pid = (pid_t) u;
2602 } else if (streq(name, "NAccepted"))
2604 else if (streq(name, "NConnections"))
2605 i->n_connections = u;
2610 case DBUS_TYPE_INT32: {
2613 dbus_message_iter_get_basic(iter, &j);
2615 if (streq(name, "ExecMainCode"))
2616 i->exit_code = (int) j;
2617 else if (streq(name, "ExecMainStatus"))
2618 i->exit_status = (int) j;
2623 case DBUS_TYPE_UINT64: {
2626 dbus_message_iter_get_basic(iter, &u);
2628 if (streq(name, "ExecMainStartTimestamp"))
2629 i->start_timestamp = (usec_t) u;
2630 else if (streq(name, "ExecMainExitTimestamp"))
2631 i->exit_timestamp = (usec_t) u;
2632 else if (streq(name, "ActiveEnterTimestamp"))
2633 i->active_enter_timestamp = (usec_t) u;
2634 else if (streq(name, "InactiveEnterTimestamp"))
2635 i->inactive_enter_timestamp = (usec_t) u;
2636 else if (streq(name, "InactiveExitTimestamp"))
2637 i->inactive_exit_timestamp = (usec_t) u;
2638 else if (streq(name, "InactiveExitTimestampMonotonic"))
2639 i->inactive_exit_timestamp_monotonic = (usec_t) u;
2640 else if (streq(name, "ActiveExitTimestamp"))
2641 i->active_exit_timestamp = (usec_t) u;
2642 else if (streq(name, "ConditionTimestamp"))
2643 i->condition_timestamp = (usec_t) u;
2648 case DBUS_TYPE_ARRAY: {
2650 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
2651 startswith(name, "Exec")) {
2652 DBusMessageIter sub;
2654 dbus_message_iter_recurse(iter, &sub);
2655 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2656 ExecStatusInfo *info;
2659 if (!(info = new0(ExecStatusInfo, 1)))
2662 if (!(info->name = strdup(name))) {
2667 if ((r = exec_status_info_deserialize(&sub, info)) < 0) {
2672 LIST_PREPEND(ExecStatusInfo, exec, i->exec, info);
2674 dbus_message_iter_next(&sub);
2676 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
2677 streq(name, "Documentation")) {
2679 DBusMessageIter sub;
2681 dbus_message_iter_recurse(iter, &sub);
2682 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING) {
2686 dbus_message_iter_get_basic(&sub, &s);
2688 l = strv_append(i->documentation, s);
2692 strv_free(i->documentation);
2693 i->documentation = l;
2695 dbus_message_iter_next(&sub);
2702 case DBUS_TYPE_STRUCT: {
2704 if (streq(name, "LoadError")) {
2705 DBusMessageIter sub;
2706 const char *n, *message;
2709 dbus_message_iter_recurse(iter, &sub);
2711 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &n, true);
2715 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &message, false);
2719 if (!isempty(message))
2720 i->load_error = message;
2730 static int print_property(const char *name, DBusMessageIter *iter) {
2734 /* This is a low-level property printer, see
2735 * print_status_info() for the nicer output */
2737 if (arg_property && !strv_find(arg_property, name))
2740 switch (dbus_message_iter_get_arg_type(iter)) {
2742 case DBUS_TYPE_STRUCT: {
2743 DBusMessageIter sub;
2744 dbus_message_iter_recurse(iter, &sub);
2746 if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32 && streq(name, "Job")) {
2749 dbus_message_iter_get_basic(&sub, &u);
2752 printf("%s=%u\n", name, (unsigned) u);
2754 printf("%s=\n", name);
2757 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "Unit")) {
2760 dbus_message_iter_get_basic(&sub, &s);
2762 if (arg_all || s[0])
2763 printf("%s=%s\n", name, s);
2766 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "LoadError")) {
2767 const char *a = NULL, *b = NULL;
2769 if (bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &a, true) >= 0)
2770 bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &b, false);
2772 if (arg_all || !isempty(a) || !isempty(b))
2773 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
2781 case DBUS_TYPE_ARRAY:
2783 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "EnvironmentFiles")) {
2784 DBusMessageIter sub, sub2;
2786 dbus_message_iter_recurse(iter, &sub);
2787 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2791 dbus_message_iter_recurse(&sub, &sub2);
2793 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
2794 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) >= 0)
2795 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
2797 dbus_message_iter_next(&sub);
2802 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Paths")) {
2803 DBusMessageIter sub, sub2;
2805 dbus_message_iter_recurse(iter, &sub);
2806 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2807 const char *type, *path;
2809 dbus_message_iter_recurse(&sub, &sub2);
2811 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
2812 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
2813 printf("%s=%s\n", type, path);
2815 dbus_message_iter_next(&sub);
2820 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Timers")) {
2821 DBusMessageIter sub, sub2;
2823 dbus_message_iter_recurse(iter, &sub);
2824 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2826 uint64_t value, next_elapse;
2828 dbus_message_iter_recurse(&sub, &sub2);
2830 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &base, true) >= 0 &&
2831 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &value, true) >= 0 &&
2832 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &next_elapse, false) >= 0) {
2833 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
2835 printf("%s={ value=%s ; next_elapse=%s }\n",
2837 format_timespan(timespan1, sizeof(timespan1), value),
2838 format_timespan(timespan2, sizeof(timespan2), next_elapse));
2841 dbus_message_iter_next(&sub);
2846 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "ControlGroupAttributes")) {
2847 DBusMessageIter sub, sub2;
2849 dbus_message_iter_recurse(iter, &sub);
2850 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2851 const char *controller, *attr, *value;
2853 dbus_message_iter_recurse(&sub, &sub2);
2855 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &controller, true) >= 0 &&
2856 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &attr, true) >= 0 &&
2857 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &value, false) >= 0) {
2859 printf("ControlGroupAttribute={ controller=%s ; attribute=%s ; value=\"%s\" }\n",
2865 dbus_message_iter_next(&sub);
2870 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && startswith(name, "Exec")) {
2871 DBusMessageIter sub;
2873 dbus_message_iter_recurse(iter, &sub);
2874 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2875 ExecStatusInfo info;
2878 if (exec_status_info_deserialize(&sub, &info) >= 0) {
2879 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
2882 t = strv_join(info.argv, " ");
2884 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
2888 yes_no(info.ignore),
2889 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
2890 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
2891 (unsigned) info. pid,
2892 sigchld_code_to_string(info.code),
2894 info.code == CLD_EXITED ? "" : "/",
2895 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
2901 strv_free(info.argv);
2903 dbus_message_iter_next(&sub);
2912 if (generic_print_property(name, iter, arg_all) > 0)
2916 printf("%s=[unprintable]\n", name);
2921 static int show_one(const char *verb, DBusConnection *bus, const char *path, bool show_properties, bool *new_line) {
2922 _cleanup_free_ DBusMessage *reply = NULL;
2923 const char *interface = "";
2925 DBusMessageIter iter, sub, sub2, sub3;
2926 UnitStatusInfo info;
2934 r = bus_method_call_with_reply(
2936 "org.freedesktop.systemd1",
2938 "org.freedesktop.DBus.Properties",
2942 DBUS_TYPE_STRING, &interface,
2947 if (!dbus_message_iter_init(reply, &iter) ||
2948 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
2949 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
2950 log_error("Failed to parse reply.");
2954 dbus_message_iter_recurse(&iter, &sub);
2961 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
2964 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_DICT_ENTRY);
2965 dbus_message_iter_recurse(&sub, &sub2);
2967 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
2968 dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
2969 log_error("Failed to parse reply.");
2973 dbus_message_iter_recurse(&sub2, &sub3);
2975 if (show_properties)
2976 r = print_property(name, &sub3);
2978 r = status_property(name, &sub3, &info);
2980 log_error("Failed to parse reply.");
2984 dbus_message_iter_next(&sub);
2989 if (!show_properties) {
2990 if (streq(verb, "help"))
2991 show_unit_help(&info);
2993 print_status_info(&info);
2996 strv_free(info.documentation);
2998 if (!streq_ptr(info.active_state, "active") &&
2999 !streq_ptr(info.active_state, "reloading") &&
3000 streq(verb, "status"))
3001 /* According to LSB: "program not running" */
3004 while ((p = info.exec)) {
3005 LIST_REMOVE(ExecStatusInfo, exec, info.exec, p);
3006 exec_status_info_free(p);
3012 static int show_one_by_pid(const char *verb, DBusConnection *bus, uint32_t pid, bool *new_line) {
3013 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3014 const char *path = NULL;
3018 dbus_error_init(&error);
3020 r = bus_method_call_with_reply(
3022 "org.freedesktop.systemd1",
3023 "/org/freedesktop/systemd1",
3024 "org.freedesktop.systemd1.Manager",
3028 DBUS_TYPE_UINT32, &pid,
3033 if (!dbus_message_get_args(reply, &error,
3034 DBUS_TYPE_OBJECT_PATH, &path,
3035 DBUS_TYPE_INVALID)) {
3036 log_error("Failed to parse reply: %s", bus_error_message(&error));
3041 r = show_one(verb, bus, path, false, new_line);
3044 dbus_error_free(&error);
3049 static int show(DBusConnection *bus, char **args) {
3051 bool show_properties, new_line = false;
3057 show_properties = streq(args[0], "show");
3059 if (show_properties)
3060 pager_open_if_enabled();
3062 /* If no argument is specified inspect the manager itself */
3064 if (show_properties && strv_length(args) <= 1)
3065 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line);
3067 STRV_FOREACH(name, args+1) {
3070 if (safe_atou32(*name, &id) < 0) {
3071 _cleanup_free_ char *p = NULL, *n = NULL;
3072 /* Interpret as unit name */
3074 n = unit_name_mangle(*name);
3078 p = unit_dbus_path_from_name(n);
3082 r = show_one(args[0], bus, p, show_properties, &new_line);
3086 } else if (show_properties) {
3087 _cleanup_free_ char *p = NULL;
3089 /* Interpret as job id */
3090 if (asprintf(&p, "/org/freedesktop/systemd1/job/%u", id) < 0)
3093 r = show_one(args[0], bus, p, show_properties, &new_line);
3098 /* Interpret as PID */
3099 r = show_one_by_pid(args[0], bus, id, &new_line);
3108 static int dump(DBusConnection *bus, char **args) {
3109 _cleanup_free_ DBusMessage *reply = NULL;
3114 dbus_error_init(&error);
3116 pager_open_if_enabled();
3118 r = bus_method_call_with_reply(
3120 "org.freedesktop.systemd1",
3121 "/org/freedesktop/systemd1",
3122 "org.freedesktop.systemd1.Manager",
3130 if (!dbus_message_get_args(reply, &error,
3131 DBUS_TYPE_STRING, &text,
3132 DBUS_TYPE_INVALID)) {
3133 log_error("Failed to parse reply: %s", bus_error_message(&error));
3134 dbus_error_free(&error);
3138 fputs(text, stdout);
3142 static int snapshot(DBusConnection *bus, char **args) {
3143 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3146 dbus_bool_t cleanup = FALSE;
3147 DBusMessageIter iter, sub;
3150 *interface = "org.freedesktop.systemd1.Unit",
3152 _cleanup_free_ char *n = NULL;
3154 dbus_error_init(&error);
3156 if (strv_length(args) > 1)
3157 n = snapshot_name_mangle(args[1]);
3163 r = bus_method_call_with_reply (
3165 "org.freedesktop.systemd1",
3166 "/org/freedesktop/systemd1",
3167 "org.freedesktop.systemd1.Manager",
3171 DBUS_TYPE_STRING, &n,
3172 DBUS_TYPE_BOOLEAN, &cleanup,
3177 if (!dbus_message_get_args(reply, &error,
3178 DBUS_TYPE_OBJECT_PATH, &path,
3179 DBUS_TYPE_INVALID)) {
3180 log_error("Failed to parse reply: %s", bus_error_message(&error));
3181 dbus_error_free(&error);
3185 dbus_message_unref(reply);
3188 r = bus_method_call_with_reply (
3190 "org.freedesktop.systemd1",
3192 "org.freedesktop.DBus.Properties",
3196 DBUS_TYPE_STRING, &interface,
3197 DBUS_TYPE_STRING, &property,
3202 if (!dbus_message_iter_init(reply, &iter) ||
3203 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3204 log_error("Failed to parse reply.");
3208 dbus_message_iter_recurse(&iter, &sub);
3210 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
3211 log_error("Failed to parse reply.");
3215 dbus_message_iter_get_basic(&sub, &id);
3223 static int delete_snapshot(DBusConnection *bus, char **args) {
3228 STRV_FOREACH(name, args+1) {
3229 _cleanup_free_ char *n = NULL;
3232 n = snapshot_name_mangle(*name);
3236 r = bus_method_call_with_reply(
3238 "org.freedesktop.systemd1",
3239 "/org/freedesktop/systemd1",
3240 "org.freedesktop.systemd1.Manager",
3244 DBUS_TYPE_STRING, &n,
3253 static int daemon_reload(DBusConnection *bus, char **args) {
3258 if (arg_action == ACTION_RELOAD)
3260 else if (arg_action == ACTION_REEXEC)
3261 method = "Reexecute";
3263 assert(arg_action == ACTION_SYSTEMCTL);
3266 streq(args[0], "clear-jobs") ||
3267 streq(args[0], "cancel") ? "ClearJobs" :
3268 streq(args[0], "daemon-reexec") ? "Reexecute" :
3269 streq(args[0], "reset-failed") ? "ResetFailed" :
3270 streq(args[0], "halt") ? "Halt" :
3271 streq(args[0], "poweroff") ? "PowerOff" :
3272 streq(args[0], "reboot") ? "Reboot" :
3273 streq(args[0], "kexec") ? "KExec" :
3274 streq(args[0], "exit") ? "Exit" :
3275 /* "daemon-reload" */ "Reload";
3278 r = bus_method_call_with_reply(
3280 "org.freedesktop.systemd1",
3281 "/org/freedesktop/systemd1",
3282 "org.freedesktop.systemd1.Manager",
3288 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
3289 /* There's always a fallback possible for
3290 * legacy actions. */
3292 else if (r == -ETIMEDOUT && streq(method, "Reexecute"))
3293 /* On reexecution, we expect a disconnect, not
3297 log_error("Failed to issue method call: %s", bus_error_message(&error));
3299 dbus_error_free(&error);
3303 static int reset_failed(DBusConnection *bus, char **args) {
3307 if (strv_length(args) <= 1)
3308 return daemon_reload(bus, args);
3310 STRV_FOREACH(name, args+1) {
3311 _cleanup_free_ char *n;
3313 n = unit_name_mangle(*name);
3317 r = bus_method_call_with_reply(
3319 "org.freedesktop.systemd1",
3320 "/org/freedesktop/systemd1",
3321 "org.freedesktop.systemd1.Manager",
3325 DBUS_TYPE_STRING, &n,
3334 static int show_enviroment(DBusConnection *bus, char **args) {
3335 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3336 DBusMessageIter iter, sub, sub2;
3339 *interface = "org.freedesktop.systemd1.Manager",
3340 *property = "Environment";
3342 pager_open_if_enabled();
3344 r = bus_method_call_with_reply(
3346 "org.freedesktop.systemd1",
3347 "/org/freedesktop/systemd1",
3348 "org.freedesktop.DBus.Properties",
3352 DBUS_TYPE_STRING, &interface,
3353 DBUS_TYPE_STRING, &property,
3358 if (!dbus_message_iter_init(reply, &iter) ||
3359 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3360 log_error("Failed to parse reply.");
3364 dbus_message_iter_recurse(&iter, &sub);
3366 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_ARRAY ||
3367 dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_STRING) {
3368 log_error("Failed to parse reply.");
3372 dbus_message_iter_recurse(&sub, &sub2);
3374 while (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_INVALID) {
3377 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
3378 log_error("Failed to parse reply.");
3382 dbus_message_iter_get_basic(&sub2, &text);
3385 dbus_message_iter_next(&sub2);
3391 static int switch_root(DBusConnection *bus, char **args) {
3394 _cleanup_free_ char *init = NULL;
3396 l = strv_length(args);
3397 if (l < 2 || l > 3) {
3398 log_error("Wrong number of arguments.");
3405 init = strdup(args[2]);
3407 parse_env_file("/proc/cmdline", WHITESPACE,
3417 log_debug("switching root - root: %s; init: %s", root, init);
3419 return bus_method_call_with_reply(
3421 "org.freedesktop.systemd1",
3422 "/org/freedesktop/systemd1",
3423 "org.freedesktop.systemd1.Manager",
3427 DBUS_TYPE_STRING, &root,
3428 DBUS_TYPE_STRING, &init,
3432 static int set_environment(DBusConnection *bus, char **args) {
3433 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
3436 DBusMessageIter iter;
3442 dbus_error_init(&error);
3444 method = streq(args[0], "set-environment")
3446 : "UnsetEnvironment";
3448 m = dbus_message_new_method_call(
3449 "org.freedesktop.systemd1",
3450 "/org/freedesktop/systemd1",
3451 "org.freedesktop.systemd1.Manager",
3456 dbus_message_iter_init_append(m, &iter);
3458 r = bus_append_strv_iter(&iter, args + 1);
3462 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3464 log_error("Failed to issue method call: %s", bus_error_message(&error));
3465 dbus_error_free(&error);
3472 static int enable_sysv_units(char **args) {
3475 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
3476 const char *verb = args[0];
3477 unsigned f = 1, t = 1;
3480 if (arg_scope != UNIT_FILE_SYSTEM)
3483 if (!streq(verb, "enable") &&
3484 !streq(verb, "disable") &&
3485 !streq(verb, "is-enabled"))
3488 /* Processes all SysV units, and reshuffles the array so that
3489 * afterwards only the native units remain */
3492 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, NULL, NULL, NULL);
3497 for (f = 1; args[f]; f++) {
3500 bool found_native = false, found_sysv;
3502 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
3503 char **k, *l, *q = NULL;
3510 if (!endswith(name, ".service"))
3513 if (path_is_absolute(name))
3516 STRV_FOREACH(k, paths.unit_path) {
3519 if (!isempty(arg_root))
3520 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
3522 asprintf(&p, "%s/%s", *k, name);
3529 found_native = access(p, F_OK) >= 0;
3540 if (!isempty(arg_root))
3541 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
3543 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
3549 p[strlen(p) - sizeof(".service") + 1] = 0;
3550 found_sysv = access(p, F_OK) >= 0;
3557 /* Mark this entry, so that we don't try enabling it as native unit */
3558 args[f] = (char*) "";
3560 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
3562 if (!isempty(arg_root))
3563 argv[c++] = q = strappend("--root=", arg_root);
3565 argv[c++] = path_get_file_name(p);
3567 streq(verb, "enable") ? "on" :
3568 streq(verb, "disable") ? "off" : "--level=5";
3571 l = strv_join((char**)argv, " ");
3579 log_info("Executing %s", l);
3584 log_error("Failed to fork: %m");
3589 } else if (pid == 0) {
3592 execv(argv[0], (char**) argv);
3593 _exit(EXIT_FAILURE);
3599 j = wait_for_terminate(pid, &status);
3601 log_error("Failed to wait for child: %s", strerror(-r));
3606 if (status.si_code == CLD_EXITED) {
3607 if (streq(verb, "is-enabled")) {
3608 if (status.si_status == 0) {
3617 } else if (status.si_status != 0) {
3628 lookup_paths_free(&paths);
3630 /* Drop all SysV units */
3631 for (f = 1, t = 1; args[f]; f++) {
3633 if (isempty(args[f]))
3636 args[t++] = args[f];
3645 static int mangle_names(char **original_names, char ***mangled_names) {
3646 char **i, **l, **name;
3648 l = new(char*, strv_length(original_names) + 1);
3653 STRV_FOREACH(name, original_names) {
3655 /* When enabling units qualified path names are OK,
3656 * too, hence allow them explicitly. */
3661 *i = unit_name_mangle(*name);
3677 static int enable_unit(DBusConnection *bus, char **args) {
3678 const char *verb = args[0];
3679 UnitFileChange *changes = NULL;
3680 unsigned n_changes = 0, i;
3681 int carries_install_info = -1;
3682 DBusMessage *m = NULL, *reply = NULL;
3685 char **mangled_names = NULL;
3687 r = enable_sysv_units(args);
3694 dbus_error_init(&error);
3696 if (!bus || avoid_bus()) {
3697 if (streq(verb, "enable")) {
3698 r = unit_file_enable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3699 carries_install_info = r;
3700 } else if (streq(verb, "disable"))
3701 r = unit_file_disable(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3702 else if (streq(verb, "reenable")) {
3703 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3704 carries_install_info = r;
3705 } else if (streq(verb, "link"))
3706 r = unit_file_link(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3707 else if (streq(verb, "preset")) {
3708 r = unit_file_preset(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3709 carries_install_info = r;
3710 } else if (streq(verb, "mask"))
3711 r = unit_file_mask(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3712 else if (streq(verb, "unmask"))
3713 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3715 assert_not_reached("Unknown verb");
3718 log_error("Operation failed: %s", strerror(-r));
3723 for (i = 0; i < n_changes; i++) {
3724 if (changes[i].type == UNIT_FILE_SYMLINK)
3725 log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
3727 log_info("rm '%s'", changes[i].path);
3734 bool send_force = true, expect_carries_install_info = false;
3736 DBusMessageIter iter, sub, sub2;
3738 if (streq(verb, "enable")) {
3739 method = "EnableUnitFiles";
3740 expect_carries_install_info = true;
3741 } else if (streq(verb, "disable")) {
3742 method = "DisableUnitFiles";
3744 } else if (streq(verb, "reenable")) {
3745 method = "ReenableUnitFiles";
3746 expect_carries_install_info = true;
3747 } else if (streq(verb, "link"))
3748 method = "LinkUnitFiles";
3749 else if (streq(verb, "preset")) {
3750 method = "PresetUnitFiles";
3751 expect_carries_install_info = true;
3752 } else if (streq(verb, "mask"))
3753 method = "MaskUnitFiles";
3754 else if (streq(verb, "unmask")) {
3755 method = "UnmaskUnitFiles";
3758 assert_not_reached("Unknown verb");
3760 m = dbus_message_new_method_call(
3761 "org.freedesktop.systemd1",
3762 "/org/freedesktop/systemd1",
3763 "org.freedesktop.systemd1.Manager",
3770 dbus_message_iter_init_append(m, &iter);
3772 r = mangle_names(args+1, &mangled_names);
3776 r = bus_append_strv_iter(&iter, mangled_names);
3778 log_error("Failed to append unit files.");
3783 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &a)) {
3784 log_error("Failed to append runtime boolean.");
3792 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b)) {
3793 log_error("Failed to append force boolean.");
3799 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3801 log_error("Failed to issue method call: %s", bus_error_message(&error));
3806 if (!dbus_message_iter_init(reply, &iter)) {
3807 log_error("Failed to initialize iterator.");
3811 if (expect_carries_install_info) {
3812 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &b, true);
3814 log_error("Failed to parse reply.");
3818 carries_install_info = b;
3821 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3822 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
3823 log_error("Failed to parse reply.");
3828 dbus_message_iter_recurse(&iter, &sub);
3829 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
3830 const char *type, *path, *source;
3832 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
3833 log_error("Failed to parse reply.");
3838 dbus_message_iter_recurse(&sub, &sub2);
3840 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
3841 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
3842 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &source, false) < 0) {
3843 log_error("Failed to parse reply.");
3849 if (streq(type, "symlink"))
3850 log_info("ln -s '%s' '%s'", source, path);
3852 log_info("rm '%s'", path);
3855 dbus_message_iter_next(&sub);
3858 /* Try to reload if enabeld */
3860 r = daemon_reload(bus, args);
3863 if (carries_install_info == 0)
3865 "The unit files have no [Install] section. They are not meant to be enabled\n"
3866 "using systemctl.\n"
3867 "Possible reasons for having this kind of units are:\n"
3868 "1) A unit may be statically enabled by being symlinked from another unit's\n"
3869 " .wants/ or .requires/ directory.\n"
3870 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
3871 " a requirement dependency on it.\n"
3872 "3) A unit may be started when needed via activation (socket, path, timer,\n"
3873 " D-Bus, udev, scripted systemctl call, ...).\n");
3877 dbus_message_unref(m);
3880 dbus_message_unref(reply);
3882 unit_file_changes_free(changes, n_changes);
3884 dbus_error_free(&error);
3886 strv_free(mangled_names);
3891 static int unit_is_enabled(DBusConnection *bus, char **args) {
3894 DBusMessage *reply = NULL;
3898 dbus_error_init(&error);
3900 r = enable_sysv_units(args);
3906 if (!bus || avoid_bus()) {
3908 STRV_FOREACH(name, args+1) {
3909 UnitFileState state;
3911 state = unit_file_get_state(arg_scope, arg_root, *name);
3917 if (state == UNIT_FILE_ENABLED ||
3918 state == UNIT_FILE_ENABLED_RUNTIME ||
3919 state == UNIT_FILE_STATIC)
3923 puts(unit_file_state_to_string(state));
3927 STRV_FOREACH(name, args+1) {
3930 r = bus_method_call_with_reply (
3932 "org.freedesktop.systemd1",
3933 "/org/freedesktop/systemd1",
3934 "org.freedesktop.systemd1.Manager",
3938 DBUS_TYPE_STRING, name,
3943 if (!dbus_message_get_args(reply, &error,
3944 DBUS_TYPE_STRING, &s,
3945 DBUS_TYPE_INVALID)) {
3946 log_error("Failed to parse reply: %s", bus_error_message(&error));
3951 dbus_message_unref(reply);
3954 if (streq(s, "enabled") ||
3955 streq(s, "enabled-runtime") ||
3964 r = enabled ? 0 : 1;
3968 dbus_message_unref(reply);
3970 dbus_error_free(&error);
3974 static int systemctl_help(void) {
3976 pager_open_if_enabled();
3978 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
3979 "Query or send control commands to the systemd manager.\n\n"
3980 " -h --help Show this help\n"
3981 " --version Show package version\n"
3982 " -t --type=TYPE List only units of a particular type\n"
3983 " -p --property=NAME Show only properties by this name\n"
3984 " -a --all Show all units/properties, including dead/empty ones\n"
3985 " --failed Show only failed units\n"
3986 " --full Don't ellipsize unit names on output\n"
3987 " --fail When queueing a new job, fail if conflicting jobs are\n"
3989 " --ignore-dependencies\n"
3990 " When queueing a new job, ignore all its dependencies\n"
3991 " -i --ignore-inhibitors\n"
3992 " When shutting down or sleeping, ignore inhibitors\n"
3993 " --kill-who=WHO Who to send signal to\n"
3994 " -s --signal=SIGNAL Which signal to send\n"
3995 " -H --host=[USER@]HOST\n"
3996 " Show information for remote host\n"
3997 " -P --privileged Acquire privileges before execution\n"
3998 " -q --quiet Suppress output\n"
3999 " --no-block Do not wait until operation finished\n"
4000 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4001 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
4003 " --no-legend Do not print a legend (column headers and hints)\n"
4004 " --no-pager Do not pipe output into a pager\n"
4005 " --no-ask-password\n"
4006 " Do not ask for system passwords\n"
4007 " --order When generating graph for dot, show only order\n"
4008 " --require When generating graph for dot, show only requirement\n"
4009 " --system Connect to system manager\n"
4010 " --user Connect to user service manager\n"
4011 " --global Enable/disable unit files globally\n"
4012 " -f --force When enabling unit files, override existing symlinks\n"
4013 " When shutting down, execute action immediately\n"
4014 " --root=PATH Enable unit files in the specified root directory\n"
4015 " --runtime Enable unit files only temporarily until next reboot\n"
4016 " -n --lines=INTEGER Journal entries to show\n"
4017 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
4018 " verbose, export, json, json-pretty, json-sse, cat)\n\n"
4020 " list-units List loaded units\n"
4021 " start [NAME...] Start (activate) one or more units\n"
4022 " stop [NAME...] Stop (deactivate) one or more units\n"
4023 " reload [NAME...] Reload one or more units\n"
4024 " restart [NAME...] Start or restart one or more units\n"
4025 " try-restart [NAME...] Restart one or more units if active\n"
4026 " reload-or-restart [NAME...] Reload one or more units if possible,\n"
4027 " otherwise start or restart\n"
4028 " reload-or-try-restart [NAME...] Reload one or more units if possible,\n"
4029 " otherwise restart if active\n"
4030 " isolate [NAME] Start one unit and stop all others\n"
4031 " kill [NAME...] Send signal to processes of a unit\n"
4032 " is-active [NAME...] Check whether units are active\n"
4033 " is-failed [NAME...] Check whether units are failed\n"
4034 " status [NAME...|PID...] Show runtime status of one or more units\n"
4035 " show [NAME...|JOB...] Show properties of one or more\n"
4036 " units/jobs or the manager\n"
4037 " help [NAME...|PID...] Show manual for one or more units\n"
4038 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
4040 " set-cgroup [NAME] [CGROUP...] Add unit to a control group\n"
4041 " unset-cgroup [NAME] [CGROUP...] Remove unit from a control group\n"
4042 " set-cgroup-attr [NAME] [ATTR] [VALUE] ...\n"
4043 " Set control group attribute\n"
4044 " unset-cgroup-attr [NAME] [ATTR...]\n"
4045 " Unset control group attribute\n"
4046 " load [NAME...] Load one or more units\n\n"
4047 "Unit File Commands:\n"
4048 " list-unit-files List installed unit files\n"
4049 " enable [NAME...] Enable one or more unit files\n"
4050 " disable [NAME...] Disable one or more unit files\n"
4051 " reenable [NAME...] Reenable one or more unit files\n"
4052 " preset [NAME...] Enable/disable one or more unit files\n"
4053 " based on preset configuration\n"
4054 " mask [NAME...] Mask one or more units\n"
4055 " unmask [NAME...] Unmask one or more units\n"
4056 " link [PATH...] Link one or more units files into\n"
4057 " the search path\n"
4058 " is-enabled [NAME...] Check whether unit files are enabled\n\n"
4060 " list-jobs List jobs\n"
4061 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
4062 "Status Commands:\n"
4063 " dump Dump server status\n"
4064 " dot Dump dependency graph for dot(1)\n\n"
4065 "Snapshot Commands:\n"
4066 " snapshot [NAME] Create a snapshot\n"
4067 " delete [NAME...] Remove one or more snapshots\n\n"
4068 "Environment Commands:\n"
4069 " show-environment Dump environment\n"
4070 " set-environment [NAME=VALUE...] Set one or more environment variables\n"
4071 " unset-environment [NAME...] Unset one or more environment variables\n\n"
4072 "Manager Lifecycle Commands:\n"
4073 " daemon-reload Reload systemd manager configuration\n"
4074 " daemon-reexec Reexecute systemd manager\n\n"
4075 "System Commands:\n"
4076 " default Enter system default mode\n"
4077 " rescue Enter system rescue mode\n"
4078 " emergency Enter system emergency mode\n"
4079 " halt Shut down and halt the system\n"
4080 " poweroff Shut down and power-off the system\n"
4081 " reboot Shut down and reboot the system\n"
4082 " kexec Shut down and reboot the system with kexec\n"
4083 " exit Request user instance exit\n"
4084 " switch-root [ROOT] [INIT] Change to a different root file system\n"
4085 " suspend Suspend the system\n"
4086 " hibernate Hibernate the system\n"
4087 " hybrid-sleep Hibernate and suspend the system\n",
4088 program_invocation_short_name);
4093 static int halt_help(void) {
4095 printf("%s [OPTIONS...]\n\n"
4096 "%s the system.\n\n"
4097 " --help Show this help\n"
4098 " --halt Halt the machine\n"
4099 " -p --poweroff Switch off the machine\n"
4100 " --reboot Reboot the machine\n"
4101 " -f --force Force immediate halt/power-off/reboot\n"
4102 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
4103 " -d --no-wtmp Don't write wtmp record\n"
4104 " --no-wall Don't send wall message before halt/power-off/reboot\n",
4105 program_invocation_short_name,
4106 arg_action == ACTION_REBOOT ? "Reboot" :
4107 arg_action == ACTION_POWEROFF ? "Power off" :
4113 static int shutdown_help(void) {
4115 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
4116 "Shut down the system.\n\n"
4117 " --help Show this help\n"
4118 " -H --halt Halt the machine\n"
4119 " -P --poweroff Power-off the machine\n"
4120 " -r --reboot Reboot the machine\n"
4121 " -h Equivalent to --poweroff, overridden by --halt\n"
4122 " -k Don't halt/power-off/reboot, just send warnings\n"
4123 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4124 " -c Cancel a pending shutdown\n",
4125 program_invocation_short_name);
4130 static int telinit_help(void) {
4132 printf("%s [OPTIONS...] {COMMAND}\n\n"
4133 "Send control commands to the init daemon.\n\n"
4134 " --help Show this help\n"
4135 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
4137 " 0 Power-off the machine\n"
4138 " 6 Reboot the machine\n"
4139 " 2, 3, 4, 5 Start runlevelX.target unit\n"
4140 " 1, s, S Enter rescue mode\n"
4141 " q, Q Reload init daemon configuration\n"
4142 " u, U Reexecute init daemon\n",
4143 program_invocation_short_name);
4148 static int runlevel_help(void) {
4150 printf("%s [OPTIONS...]\n\n"
4151 "Prints the previous and current runlevel of the init system.\n\n"
4152 " --help Show this help\n",
4153 program_invocation_short_name);
4158 static int help_types(void) {
4161 puts("Available unit types:");
4162 for(i = UNIT_SERVICE; i < _UNIT_TYPE_MAX; i++)
4163 if (unit_type_table[i])
4164 puts(unit_type_table[i]);
4166 puts("\nAvailable unit load states: ");
4167 for(i = UNIT_STUB; i < _UNIT_LOAD_STATE_MAX; i++)
4168 if (unit_type_table[i])
4169 puts(unit_load_state_table[i]);
4174 static int systemctl_parse_argv(int argc, char *argv[]) {
4178 ARG_IGNORE_DEPENDENCIES,
4193 ARG_NO_ASK_PASSWORD,
4199 static const struct option options[] = {
4200 { "help", no_argument, NULL, 'h' },
4201 { "version", no_argument, NULL, ARG_VERSION },
4202 { "type", required_argument, NULL, 't' },
4203 { "property", required_argument, NULL, 'p' },
4204 { "all", no_argument, NULL, 'a' },
4205 { "failed", no_argument, NULL, ARG_FAILED },
4206 { "full", no_argument, NULL, ARG_FULL },
4207 { "fail", no_argument, NULL, ARG_FAIL },
4208 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
4209 { "ignore-inhibitors", no_argument, NULL, 'i' },
4210 { "user", no_argument, NULL, ARG_USER },
4211 { "system", no_argument, NULL, ARG_SYSTEM },
4212 { "global", no_argument, NULL, ARG_GLOBAL },
4213 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
4214 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
4215 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
4216 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4217 { "quiet", no_argument, NULL, 'q' },
4218 { "order", no_argument, NULL, ARG_ORDER },
4219 { "require", no_argument, NULL, ARG_REQUIRE },
4220 { "root", required_argument, NULL, ARG_ROOT },
4221 { "force", no_argument, NULL, ARG_FORCE },
4222 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
4223 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
4224 { "signal", required_argument, NULL, 's' },
4225 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
4226 { "host", required_argument, NULL, 'H' },
4227 { "privileged",no_argument, NULL, 'P' },
4228 { "runtime", no_argument, NULL, ARG_RUNTIME },
4229 { "lines", required_argument, NULL, 'n' },
4230 { "output", required_argument, NULL, 'o' },
4231 { NULL, 0, NULL, 0 }
4239 while ((c = getopt_long(argc, argv, "ht:p:aqfs:H:Pn:o:i", options, NULL)) >= 0) {
4248 puts(PACKAGE_STRING);
4249 puts(SYSTEMD_FEATURES);
4253 if (streq(optarg, "help")) {
4258 if (unit_type_from_string(optarg) >= 0) {
4262 if (unit_load_state_from_string(optarg) >= 0) {
4263 arg_load_state = optarg;
4266 log_error("Unkown unit type or load state '%s'.",
4268 log_info("Use -t help to see a list of allowed values.");
4273 if (!(l = strv_append(arg_property, optarg)))
4276 strv_free(arg_property);
4279 /* If the user asked for a particular
4280 * property, show it to him, even if it is
4291 arg_job_mode = "fail";
4294 case ARG_IGNORE_DEPENDENCIES:
4295 arg_job_mode = "ignore-dependencies";
4299 arg_scope = UNIT_FILE_USER;
4303 arg_scope = UNIT_FILE_SYSTEM;
4307 arg_scope = UNIT_FILE_GLOBAL;
4311 arg_no_block = true;
4315 arg_no_legend = true;
4319 arg_no_pager = true;
4327 arg_dot = DOT_ORDER;
4331 arg_dot = DOT_REQUIRE;
4359 arg_no_reload = true;
4363 arg_kill_who = optarg;
4367 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
4368 log_error("Failed to parse signal string %s.", optarg);
4373 case ARG_NO_ASK_PASSWORD:
4374 arg_ask_password = false;
4378 arg_transport = TRANSPORT_POLKIT;
4382 arg_transport = TRANSPORT_SSH;
4391 if (safe_atou(optarg, &arg_lines) < 0) {
4392 log_error("Failed to parse lines '%s'", optarg);
4398 arg_output = output_mode_from_string(optarg);
4399 if (arg_output < 0) {
4400 log_error("Unknown output '%s'.", optarg);
4406 arg_ignore_inhibitors = true;
4413 log_error("Unknown option code '%c'.", c);
4418 if (arg_transport != TRANSPORT_NORMAL && arg_scope != UNIT_FILE_SYSTEM) {
4419 log_error("Cannot access user instance remotely.");
4426 static int halt_parse_argv(int argc, char *argv[]) {
4435 static const struct option options[] = {
4436 { "help", no_argument, NULL, ARG_HELP },
4437 { "halt", no_argument, NULL, ARG_HALT },
4438 { "poweroff", no_argument, NULL, 'p' },
4439 { "reboot", no_argument, NULL, ARG_REBOOT },
4440 { "force", no_argument, NULL, 'f' },
4441 { "wtmp-only", no_argument, NULL, 'w' },
4442 { "no-wtmp", no_argument, NULL, 'd' },
4443 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4444 { NULL, 0, NULL, 0 }
4452 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
4453 if (runlevel == '0' || runlevel == '6')
4456 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
4464 arg_action = ACTION_HALT;
4468 if (arg_action != ACTION_REBOOT)
4469 arg_action = ACTION_POWEROFF;
4473 arg_action = ACTION_REBOOT;
4495 /* Compatibility nops */
4502 log_error("Unknown option code '%c'.", c);
4507 if (optind < argc) {
4508 log_error("Too many arguments.");
4515 static int parse_time_spec(const char *t, usec_t *_u) {
4519 if (streq(t, "now"))
4521 else if (!strchr(t, ':')) {
4524 if (safe_atou64(t, &u) < 0)
4527 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
4536 hour = strtol(t, &e, 10);
4537 if (errno != 0 || *e != ':' || hour < 0 || hour > 23)
4540 minute = strtol(e+1, &e, 10);
4541 if (errno != 0 || *e != 0 || minute < 0 || minute > 59)
4544 n = now(CLOCK_REALTIME);
4545 s = (time_t) (n / USEC_PER_SEC);
4548 assert_se(localtime_r(&s, &tm));
4550 tm.tm_hour = (int) hour;
4551 tm.tm_min = (int) minute;
4554 assert_se(s = mktime(&tm));
4556 *_u = (usec_t) s * USEC_PER_SEC;
4559 *_u += USEC_PER_DAY;
4565 static int shutdown_parse_argv(int argc, char *argv[]) {
4572 static const struct option options[] = {
4573 { "help", no_argument, NULL, ARG_HELP },
4574 { "halt", no_argument, NULL, 'H' },
4575 { "poweroff", no_argument, NULL, 'P' },
4576 { "reboot", no_argument, NULL, 'r' },
4577 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
4578 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4579 { NULL, 0, NULL, 0 }
4587 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
4595 arg_action = ACTION_HALT;
4599 arg_action = ACTION_POWEROFF;
4604 arg_action = ACTION_KEXEC;
4606 arg_action = ACTION_REBOOT;
4610 arg_action = ACTION_KEXEC;
4614 if (arg_action != ACTION_HALT)
4615 arg_action = ACTION_POWEROFF;
4628 /* Compatibility nops */
4632 arg_action = ACTION_CANCEL_SHUTDOWN;
4639 log_error("Unknown option code '%c'.", c);
4644 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
4645 r = parse_time_spec(argv[optind], &arg_when);
4647 log_error("Failed to parse time specification: %s", argv[optind]);
4651 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
4653 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
4654 /* No time argument for shutdown cancel */
4655 arg_wall = argv + optind;
4656 else if (argc > optind + 1)
4657 /* We skip the time argument */
4658 arg_wall = argv + optind + 1;
4665 static int telinit_parse_argv(int argc, char *argv[]) {
4672 static const struct option options[] = {
4673 { "help", no_argument, NULL, ARG_HELP },
4674 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4675 { NULL, 0, NULL, 0 }
4678 static const struct {
4682 { '0', ACTION_POWEROFF },
4683 { '6', ACTION_REBOOT },
4684 { '1', ACTION_RESCUE },
4685 { '2', ACTION_RUNLEVEL2 },
4686 { '3', ACTION_RUNLEVEL3 },
4687 { '4', ACTION_RUNLEVEL4 },
4688 { '5', ACTION_RUNLEVEL5 },
4689 { 's', ACTION_RESCUE },
4690 { 'S', ACTION_RESCUE },
4691 { 'q', ACTION_RELOAD },
4692 { 'Q', ACTION_RELOAD },
4693 { 'u', ACTION_REEXEC },
4694 { 'U', ACTION_REEXEC }
4703 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4718 log_error("Unknown option code '%c'.", c);
4723 if (optind >= argc) {
4728 if (optind + 1 < argc) {
4729 log_error("Too many arguments.");
4733 if (strlen(argv[optind]) != 1) {
4734 log_error("Expected single character argument.");
4738 for (i = 0; i < ELEMENTSOF(table); i++)
4739 if (table[i].from == argv[optind][0])
4742 if (i >= ELEMENTSOF(table)) {
4743 log_error("Unknown command '%s'.", argv[optind]);
4747 arg_action = table[i].to;
4754 static int runlevel_parse_argv(int argc, char *argv[]) {
4760 static const struct option options[] = {
4761 { "help", no_argument, NULL, ARG_HELP },
4762 { NULL, 0, NULL, 0 }
4770 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4781 log_error("Unknown option code '%c'.", c);
4786 if (optind < argc) {
4787 log_error("Too many arguments.");
4794 static int parse_argv(int argc, char *argv[]) {
4798 if (program_invocation_short_name) {
4800 if (strstr(program_invocation_short_name, "halt")) {
4801 arg_action = ACTION_HALT;
4802 return halt_parse_argv(argc, argv);
4803 } else if (strstr(program_invocation_short_name, "poweroff")) {
4804 arg_action = ACTION_POWEROFF;
4805 return halt_parse_argv(argc, argv);
4806 } else if (strstr(program_invocation_short_name, "reboot")) {
4808 arg_action = ACTION_KEXEC;
4810 arg_action = ACTION_REBOOT;
4811 return halt_parse_argv(argc, argv);
4812 } else if (strstr(program_invocation_short_name, "shutdown")) {
4813 arg_action = ACTION_POWEROFF;
4814 return shutdown_parse_argv(argc, argv);
4815 } else if (strstr(program_invocation_short_name, "init")) {
4817 if (sd_booted() > 0) {
4818 arg_action = ACTION_INVALID;
4819 return telinit_parse_argv(argc, argv);
4821 /* Hmm, so some other init system is
4822 * running, we need to forward this
4823 * request to it. For now we simply
4824 * guess that it is Upstart. */
4826 execv("/lib/upstart/telinit", argv);
4828 log_error("Couldn't find an alternative telinit implementation to spawn.");
4832 } else if (strstr(program_invocation_short_name, "runlevel")) {
4833 arg_action = ACTION_RUNLEVEL;
4834 return runlevel_parse_argv(argc, argv);
4838 arg_action = ACTION_SYSTEMCTL;
4839 return systemctl_parse_argv(argc, argv);
4842 static int action_to_runlevel(void) {
4844 static const char table[_ACTION_MAX] = {
4845 [ACTION_HALT] = '0',
4846 [ACTION_POWEROFF] = '0',
4847 [ACTION_REBOOT] = '6',
4848 [ACTION_RUNLEVEL2] = '2',
4849 [ACTION_RUNLEVEL3] = '3',
4850 [ACTION_RUNLEVEL4] = '4',
4851 [ACTION_RUNLEVEL5] = '5',
4852 [ACTION_RESCUE] = '1'
4855 assert(arg_action < _ACTION_MAX);
4857 return table[arg_action];
4860 static int talk_upstart(void) {
4861 DBusMessage *m = NULL, *reply = NULL;
4863 int previous, rl, r;
4865 env1_buf[] = "RUNLEVEL=X",
4866 env2_buf[] = "PREVLEVEL=X";
4867 char *env1 = env1_buf, *env2 = env2_buf;
4868 const char *emit = "runlevel";
4869 dbus_bool_t b_false = FALSE;
4870 DBusMessageIter iter, sub;
4871 DBusConnection *bus;
4873 dbus_error_init(&error);
4875 if (!(rl = action_to_runlevel()))
4878 if (utmp_get_runlevel(&previous, NULL) < 0)
4881 if (!(bus = dbus_connection_open_private("unix:abstract=/com/ubuntu/upstart", &error))) {
4882 if (dbus_error_has_name(&error, DBUS_ERROR_NO_SERVER)) {
4887 log_error("Failed to connect to Upstart bus: %s", bus_error_message(&error));
4892 if ((r = bus_check_peercred(bus)) < 0) {
4893 log_error("Failed to verify owner of bus.");
4897 if (!(m = dbus_message_new_method_call(
4898 "com.ubuntu.Upstart",
4899 "/com/ubuntu/Upstart",
4900 "com.ubuntu.Upstart0_6",
4903 log_error("Could not allocate message.");
4908 dbus_message_iter_init_append(m, &iter);
4910 env1_buf[sizeof(env1_buf)-2] = rl;
4911 env2_buf[sizeof(env2_buf)-2] = previous;
4913 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &emit) ||
4914 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub) ||
4915 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env1) ||
4916 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env2) ||
4917 !dbus_message_iter_close_container(&iter, &sub) ||
4918 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b_false)) {
4919 log_error("Could not append arguments to message.");
4924 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
4926 if (bus_error_is_no_service(&error)) {
4931 log_error("Failed to issue method call: %s", bus_error_message(&error));
4940 dbus_message_unref(m);
4943 dbus_message_unref(reply);
4946 dbus_connection_flush(bus);
4947 dbus_connection_close(bus);
4948 dbus_connection_unref(bus);
4951 dbus_error_free(&error);
4956 static int talk_initctl(void) {
4957 struct init_request request;
4961 if (!(rl = action_to_runlevel()))
4965 request.magic = INIT_MAGIC;
4966 request.sleeptime = 0;
4967 request.cmd = INIT_CMD_RUNLVL;
4968 request.runlevel = rl;
4970 if ((fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY)) < 0) {
4972 if (errno == ENOENT)
4975 log_error("Failed to open "INIT_FIFO": %m");
4980 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
4981 close_nointr_nofail(fd);
4984 log_error("Failed to write to "INIT_FIFO": %m");
4985 return errno ? -errno : -EIO;
4991 static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
4993 static const struct {
5001 int (* const dispatch)(DBusConnection *bus, char **args);
5003 { "list-units", LESS, 1, list_units },
5004 { "list-unit-files", EQUAL, 1, list_unit_files },
5005 { "list-jobs", EQUAL, 1, list_jobs },
5006 { "clear-jobs", EQUAL, 1, daemon_reload },
5007 { "load", MORE, 2, load_unit },
5008 { "cancel", MORE, 2, cancel_job },
5009 { "start", MORE, 2, start_unit },
5010 { "stop", MORE, 2, start_unit },
5011 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5012 { "reload", MORE, 2, start_unit },
5013 { "restart", MORE, 2, start_unit },
5014 { "try-restart", MORE, 2, start_unit },
5015 { "reload-or-restart", MORE, 2, start_unit },
5016 { "reload-or-try-restart", MORE, 2, start_unit },
5017 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
5018 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5019 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
5020 { "isolate", EQUAL, 2, start_unit },
5021 { "set-cgroup", MORE, 2, set_cgroup },
5022 { "unset-cgroup", MORE, 2, set_cgroup },
5023 { "set-cgroup-attr", MORE, 2, set_cgroup_attr },
5024 { "unset-cgroup-attr", MORE, 2, set_cgroup },
5025 { "kill", MORE, 2, kill_unit },
5026 { "is-active", MORE, 2, check_unit_active },
5027 { "check", MORE, 2, check_unit_active },
5028 { "is-failed", MORE, 2, check_unit_failed },
5029 { "show", MORE, 1, show },
5030 { "status", MORE, 2, show },
5031 { "help", MORE, 2, show },
5032 { "dump", EQUAL, 1, dump },
5033 { "dot", EQUAL, 1, dot },
5034 { "snapshot", LESS, 2, snapshot },
5035 { "delete", MORE, 2, delete_snapshot },
5036 { "daemon-reload", EQUAL, 1, daemon_reload },
5037 { "daemon-reexec", EQUAL, 1, daemon_reload },
5038 { "show-environment", EQUAL, 1, show_enviroment },
5039 { "set-environment", MORE, 2, set_environment },
5040 { "unset-environment", MORE, 2, set_environment },
5041 { "halt", EQUAL, 1, start_special },
5042 { "poweroff", EQUAL, 1, start_special },
5043 { "reboot", EQUAL, 1, start_special },
5044 { "kexec", EQUAL, 1, start_special },
5045 { "suspend", EQUAL, 1, start_special },
5046 { "hibernate", EQUAL, 1, start_special },
5047 { "hybrid-sleep", EQUAL, 1, start_special },
5048 { "default", EQUAL, 1, start_special },
5049 { "rescue", EQUAL, 1, start_special },
5050 { "emergency", EQUAL, 1, start_special },
5051 { "exit", EQUAL, 1, start_special },
5052 { "reset-failed", MORE, 1, reset_failed },
5053 { "enable", MORE, 2, enable_unit },
5054 { "disable", MORE, 2, enable_unit },
5055 { "is-enabled", MORE, 2, unit_is_enabled },
5056 { "reenable", MORE, 2, enable_unit },
5057 { "preset", MORE, 2, enable_unit },
5058 { "mask", MORE, 2, enable_unit },
5059 { "unmask", MORE, 2, enable_unit },
5060 { "link", MORE, 2, enable_unit },
5061 { "switch-root", MORE, 2, switch_root },
5071 left = argc - optind;
5074 /* Special rule: no arguments means "list-units" */
5077 if (streq(argv[optind], "help") && !argv[optind+1]) {
5078 log_error("This command expects one or more "
5079 "unit names. Did you mean --help?");
5083 for (i = 0; i < ELEMENTSOF(verbs); i++)
5084 if (streq(argv[optind], verbs[i].verb))
5087 if (i >= ELEMENTSOF(verbs)) {
5088 log_error("Unknown operation '%s'.", argv[optind]);
5093 switch (verbs[i].argc_cmp) {
5096 if (left != verbs[i].argc) {
5097 log_error("Invalid number of arguments.");
5104 if (left < verbs[i].argc) {
5105 log_error("Too few arguments.");
5112 if (left > verbs[i].argc) {
5113 log_error("Too many arguments.");
5120 assert_not_reached("Unknown comparison operator.");
5123 /* Require a bus connection for all operations but
5125 if (!streq(verbs[i].verb, "enable") &&
5126 !streq(verbs[i].verb, "disable") &&
5127 !streq(verbs[i].verb, "is-enabled") &&
5128 !streq(verbs[i].verb, "list-unit-files") &&
5129 !streq(verbs[i].verb, "reenable") &&
5130 !streq(verbs[i].verb, "preset") &&
5131 !streq(verbs[i].verb, "mask") &&
5132 !streq(verbs[i].verb, "unmask") &&
5133 !streq(verbs[i].verb, "link")) {
5135 if (running_in_chroot() > 0) {
5136 log_info("Running in chroot, ignoring request.");
5140 if (((!streq(verbs[i].verb, "reboot") &&
5141 !streq(verbs[i].verb, "halt") &&
5142 !streq(verbs[i].verb, "poweroff")) || arg_force <= 0) && !bus) {
5143 log_error("Failed to get D-Bus connection: %s",
5144 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5150 if (!bus && !avoid_bus()) {
5151 log_error("Failed to get D-Bus connection: %s",
5152 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5157 return verbs[i].dispatch(bus, argv + optind);
5160 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
5162 struct msghdr msghdr;
5163 struct iovec iovec[2];
5164 union sockaddr_union sockaddr;
5165 struct sd_shutdown_command c;
5167 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
5174 c.dry_run = dry_run;
5178 sockaddr.sa.sa_family = AF_UNIX;
5179 strncpy(sockaddr.un.sun_path, "/run/systemd/shutdownd", sizeof(sockaddr.un.sun_path));
5182 msghdr.msg_name = &sockaddr;
5183 msghdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + sizeof("/run/systemd/shutdownd") - 1;
5186 iovec[0].iov_base = (char*) &c;
5187 iovec[0].iov_len = offsetof(struct sd_shutdown_command, wall_message);
5189 if (isempty(message))
5190 msghdr.msg_iovlen = 1;
5192 iovec[1].iov_base = (char*) message;
5193 iovec[1].iov_len = strlen(message);
5194 msghdr.msg_iovlen = 2;
5196 msghdr.msg_iov = iovec;
5198 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0) {
5199 close_nointr_nofail(fd);
5203 close_nointr_nofail(fd);
5207 static int reload_with_fallback(DBusConnection *bus) {
5210 /* First, try systemd via D-Bus. */
5211 if (daemon_reload(bus, NULL) >= 0)
5215 /* Nothing else worked, so let's try signals */
5216 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
5218 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
5219 log_error("kill() failed: %m");
5226 static int start_with_fallback(DBusConnection *bus) {
5229 /* First, try systemd via D-Bus. */
5230 if (start_unit(bus, NULL) >= 0)
5234 /* Hmm, talking to systemd via D-Bus didn't work. Then
5235 * let's try to talk to Upstart via D-Bus. */
5236 if (talk_upstart() > 0)
5239 /* Nothing else worked, so let's try
5241 if (talk_initctl() > 0)
5244 log_error("Failed to talk to init daemon.");
5248 warn_wall(arg_action);
5252 static _noreturn_ void halt_now(enum action a) {
5254 /* Make sure C-A-D is handled by the kernel from this
5256 reboot(RB_ENABLE_CAD);
5261 log_info("Halting.");
5262 reboot(RB_HALT_SYSTEM);
5265 case ACTION_POWEROFF:
5266 log_info("Powering off.");
5267 reboot(RB_POWER_OFF);
5271 log_info("Rebooting.");
5272 reboot(RB_AUTOBOOT);
5276 assert_not_reached("Unknown halt action.");
5279 assert_not_reached("Uh? This shouldn't happen.");
5282 static int halt_main(DBusConnection *bus) {
5285 r = check_inhibitors(bus, arg_action);
5289 if (geteuid() != 0) {
5290 /* Try logind if we are a normal user and no special
5291 * mode applies. Maybe PolicyKit allows us to shutdown
5294 if (arg_when <= 0 &&
5297 (arg_action == ACTION_POWEROFF ||
5298 arg_action == ACTION_REBOOT)) {
5299 r = reboot_with_logind(bus, arg_action);
5304 log_error("Must be root.");
5311 m = strv_join(arg_wall, " ");
5312 r = send_shutdownd(arg_when,
5313 arg_action == ACTION_HALT ? 'H' :
5314 arg_action == ACTION_POWEROFF ? 'P' :
5315 arg_action == ACTION_KEXEC ? 'K' :
5323 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
5325 char date[FORMAT_TIMESTAMP_MAX];
5327 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
5328 format_timestamp(date, sizeof(date), arg_when));
5333 if (!arg_dry && !arg_force)
5334 return start_with_fallback(bus);
5337 if (sd_booted() > 0)
5338 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
5340 r = utmp_put_shutdown();
5342 log_warning("Failed to write utmp record: %s", strerror(-r));
5349 halt_now(arg_action);
5350 /* We should never reach this. */
5354 static int runlevel_main(void) {
5355 int r, runlevel, previous;
5357 r = utmp_get_runlevel(&runlevel, &previous);
5364 previous <= 0 ? 'N' : previous,
5365 runlevel <= 0 ? 'N' : runlevel);
5370 int main(int argc, char*argv[]) {
5371 int r, retval = EXIT_FAILURE;
5372 DBusConnection *bus = NULL;
5375 dbus_error_init(&error);
5377 setlocale(LC_ALL, "");
5378 log_parse_environment();
5381 r = parse_argv(argc, argv);
5385 retval = EXIT_SUCCESS;
5389 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
5390 * let's shortcut this */
5391 if (arg_action == ACTION_RUNLEVEL) {
5392 r = runlevel_main();
5393 retval = r < 0 ? EXIT_FAILURE : r;
5397 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
5398 log_info("Running in chroot, ignoring request.");
5404 if (arg_transport == TRANSPORT_NORMAL)
5405 bus_connect(arg_scope == UNIT_FILE_SYSTEM ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &bus, &private_bus, &error);
5406 else if (arg_transport == TRANSPORT_POLKIT) {
5407 bus_connect_system_polkit(&bus, &error);
5408 private_bus = false;
5409 } else if (arg_transport == TRANSPORT_SSH) {
5410 bus_connect_system_ssh(NULL, arg_host, &bus, &error);
5411 private_bus = false;
5413 assert_not_reached("Uh, invalid transport...");
5416 switch (arg_action) {
5418 case ACTION_SYSTEMCTL:
5419 r = systemctl_main(bus, argc, argv, &error);
5423 case ACTION_POWEROFF:
5429 case ACTION_RUNLEVEL2:
5430 case ACTION_RUNLEVEL3:
5431 case ACTION_RUNLEVEL4:
5432 case ACTION_RUNLEVEL5:
5434 case ACTION_EMERGENCY:
5435 case ACTION_DEFAULT:
5436 r = start_with_fallback(bus);
5441 r = reload_with_fallback(bus);
5444 case ACTION_CANCEL_SHUTDOWN: {
5448 m = strv_join(arg_wall, " ");
5450 retval = EXIT_FAILURE;
5454 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
5456 log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r));
5461 case ACTION_INVALID:
5462 case ACTION_RUNLEVEL:
5464 assert_not_reached("Unknown action");
5467 retval = r < 0 ? EXIT_FAILURE : r;
5471 dbus_connection_flush(bus);
5472 dbus_connection_close(bus);
5473 dbus_connection_unref(bus);
5476 dbus_error_free(&error);
5480 strv_free(arg_property);
5483 ask_password_agent_close();
5484 polkit_agent_close();