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;
1123 dbus_bool_t success = true;
1125 if (dbus_message_get_args(message, &error,
1126 DBUS_TYPE_UINT32, &id,
1127 DBUS_TYPE_OBJECT_PATH, &path,
1128 DBUS_TYPE_STRING, &unit,
1129 DBUS_TYPE_STRING, &result,
1130 DBUS_TYPE_INVALID)) {
1133 p = set_remove(d->set, (char*) path);
1136 if (!isempty(result))
1137 d->result = strdup(result);
1140 d->name = strdup(unit);
1145 dbus_error_free(&error);
1146 if (dbus_message_get_args(message, &error,
1147 DBUS_TYPE_UINT32, &id,
1148 DBUS_TYPE_OBJECT_PATH, &path,
1149 DBUS_TYPE_STRING, &result,
1150 DBUS_TYPE_INVALID)) {
1153 /* Compatibility with older systemd versions <
1154 * 183 during upgrades. This should be dropped
1156 p = set_remove(d->set, (char*) path);
1160 d->result = strdup(result);
1165 dbus_error_free(&error);
1166 if (dbus_message_get_args(message, &error,
1167 DBUS_TYPE_UINT32, &id,
1168 DBUS_TYPE_OBJECT_PATH, &path,
1169 DBUS_TYPE_BOOLEAN, &success,
1170 DBUS_TYPE_INVALID)) {
1173 /* Compatibility with older systemd versions <
1174 * 19 during upgrades. This should be dropped
1177 p = set_remove(d->set, (char*) path);
1181 d->result = strdup("failed");
1187 log_error("Failed to parse message: %s", bus_error_message(&error));
1191 dbus_error_free(&error);
1192 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1195 static int enable_wait_for_jobs(DBusConnection *bus) {
1203 dbus_error_init(&error);
1204 dbus_bus_add_match(bus,
1206 "sender='org.freedesktop.systemd1',"
1207 "interface='org.freedesktop.systemd1.Manager',"
1208 "member='JobRemoved',"
1209 "path='/org/freedesktop/systemd1'",
1212 if (dbus_error_is_set(&error)) {
1213 log_error("Failed to add match: %s", bus_error_message(&error));
1214 dbus_error_free(&error);
1218 /* This is slightly dirty, since we don't undo the match registrations. */
1222 static int wait_for_jobs(DBusConnection *bus, Set *s) {
1232 if (!dbus_connection_add_filter(bus, wait_filter, &d, NULL))
1235 while (!set_isempty(s)) {
1237 if (!dbus_connection_read_write_dispatch(bus, -1)) {
1238 log_error("Disconnected from bus.");
1239 return -ECONNREFUSED;
1246 if (streq(d.result, "timeout"))
1247 log_error("Job for %s timed out.", strna(d.name));
1248 else if (streq(d.result, "canceled"))
1249 log_error("Job for %s canceled.", strna(d.name));
1250 else if (streq(d.result, "dependency"))
1251 log_error("A dependency job for %s failed. See 'journalctl -xn' for details.", strna(d.name));
1252 else if (!streq(d.result, "done") && !streq(d.result, "skipped"))
1253 log_error("Job for %s failed. See 'systemctl status %s' and 'journalctl -xn' for details.", strna(d.name), strna(d.name));
1256 if (streq_ptr(d.result, "timeout"))
1258 else if (streq_ptr(d.result, "canceled"))
1260 else if (!streq_ptr(d.result, "done") && !streq_ptr(d.result, "skipped"))
1271 dbus_connection_remove_filter(bus, wait_filter, &d);
1275 static int check_one_unit(DBusConnection *bus, const char *name, char **check_states, bool quiet) {
1276 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1277 _cleanup_free_ char *n = NULL;
1278 DBusMessageIter iter, sub;
1280 *interface = "org.freedesktop.systemd1.Unit",
1281 *property = "ActiveState";
1282 const char *state, *path;
1288 dbus_error_init(&error);
1290 n = unit_name_mangle(name);
1294 r = bus_method_call_with_reply (
1296 "org.freedesktop.systemd1",
1297 "/org/freedesktop/systemd1",
1298 "org.freedesktop.systemd1.Manager",
1302 DBUS_TYPE_STRING, &n,
1305 dbus_error_free(&error);
1312 if (!dbus_message_get_args(reply, NULL,
1313 DBUS_TYPE_OBJECT_PATH, &path,
1314 DBUS_TYPE_INVALID)) {
1315 log_error("Failed to parse reply.");
1319 dbus_message_unref(reply);
1322 r = bus_method_call_with_reply(
1324 "org.freedesktop.systemd1",
1326 "org.freedesktop.DBus.Properties",
1330 DBUS_TYPE_STRING, &interface,
1331 DBUS_TYPE_STRING, &property,
1339 if (!dbus_message_iter_init(reply, &iter) ||
1340 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1341 log_error("Failed to parse reply.");
1345 dbus_message_iter_recurse(&iter, &sub);
1347 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1348 log_error("Failed to parse reply.");
1352 dbus_message_iter_get_basic(&sub, &state);
1357 return strv_find(check_states, state) ? 1 : 0;
1360 static void check_triggering_units(
1361 DBusConnection *bus,
1362 const char *unit_name) {
1364 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1365 DBusMessageIter iter, sub;
1366 const char *interface = "org.freedesktop.systemd1.Unit",
1367 *triggered_by_property = "TriggeredBy";
1368 char _cleanup_free_ *unit_path = NULL, *n = NULL;
1369 bool print_warning_label = true;
1372 n = unit_name_mangle(unit_name);
1378 unit_path = unit_dbus_path_from_name(n);
1384 r = bus_method_call_with_reply(
1386 "org.freedesktop.systemd1",
1388 "org.freedesktop.DBus.Properties",
1392 DBUS_TYPE_STRING, &interface,
1393 DBUS_TYPE_STRING, &triggered_by_property,
1398 if (!dbus_message_iter_init(reply, &iter) ||
1399 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1400 log_error("Failed to parse reply.");
1404 dbus_message_iter_recurse(&iter, &sub);
1405 dbus_message_iter_recurse(&sub, &iter);
1408 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1409 const char * const check_states[] = {
1414 const char *service_trigger;
1416 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1417 log_error("Failed to parse reply.");
1421 dbus_message_iter_get_basic(&sub, &service_trigger);
1423 r = check_one_unit(bus, service_trigger, (char**) check_states, true);
1427 if (print_warning_label) {
1428 log_warning("Warning: Stopping %s, but it can still be activated by:", unit_name);
1429 print_warning_label = false;
1432 log_warning(" %s", service_trigger);
1435 dbus_message_iter_next(&sub);
1439 static int start_unit_one(
1440 DBusConnection *bus,
1447 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1448 _cleanup_free_ char *n;
1457 n = unit_name_mangle(name);
1461 r = bus_method_call_with_reply(
1463 "org.freedesktop.systemd1",
1464 "/org/freedesktop/systemd1",
1465 "org.freedesktop.systemd1.Manager",
1469 DBUS_TYPE_STRING, &n,
1470 DBUS_TYPE_STRING, &mode,
1473 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
1474 /* There's always a fallback possible for
1475 * legacy actions. */
1478 log_error("Failed to issue method call: %s", bus_error_message(error));
1483 if (!dbus_message_get_args(reply, error,
1484 DBUS_TYPE_OBJECT_PATH, &path,
1485 DBUS_TYPE_INVALID)) {
1486 log_error("Failed to parse reply: %s", bus_error_message(error));
1490 if (need_daemon_reload(bus, n))
1491 log_warning("Warning: Unit file of %s changed on disk, 'systemctl %s daemon-reload' recommended.",
1492 n, arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
1504 log_error("Failed to add path to set.");
1512 static enum action verb_to_action(const char *verb) {
1513 if (streq(verb, "halt"))
1515 else if (streq(verb, "poweroff"))
1516 return ACTION_POWEROFF;
1517 else if (streq(verb, "reboot"))
1518 return ACTION_REBOOT;
1519 else if (streq(verb, "kexec"))
1520 return ACTION_KEXEC;
1521 else if (streq(verb, "rescue"))
1522 return ACTION_RESCUE;
1523 else if (streq(verb, "emergency"))
1524 return ACTION_EMERGENCY;
1525 else if (streq(verb, "default"))
1526 return ACTION_DEFAULT;
1527 else if (streq(verb, "exit"))
1529 else if (streq(verb, "suspend"))
1530 return ACTION_SUSPEND;
1531 else if (streq(verb, "hibernate"))
1532 return ACTION_HIBERNATE;
1533 else if (streq(verb, "hybrid-sleep"))
1534 return ACTION_HYBRID_SLEEP;
1536 return ACTION_INVALID;
1539 static int start_unit(DBusConnection *bus, char **args) {
1541 static const char * const table[_ACTION_MAX] = {
1542 [ACTION_HALT] = SPECIAL_HALT_TARGET,
1543 [ACTION_POWEROFF] = SPECIAL_POWEROFF_TARGET,
1544 [ACTION_REBOOT] = SPECIAL_REBOOT_TARGET,
1545 [ACTION_KEXEC] = SPECIAL_KEXEC_TARGET,
1546 [ACTION_RUNLEVEL2] = SPECIAL_RUNLEVEL2_TARGET,
1547 [ACTION_RUNLEVEL3] = SPECIAL_RUNLEVEL3_TARGET,
1548 [ACTION_RUNLEVEL4] = SPECIAL_RUNLEVEL4_TARGET,
1549 [ACTION_RUNLEVEL5] = SPECIAL_RUNLEVEL5_TARGET,
1550 [ACTION_RESCUE] = SPECIAL_RESCUE_TARGET,
1551 [ACTION_EMERGENCY] = SPECIAL_EMERGENCY_TARGET,
1552 [ACTION_DEFAULT] = SPECIAL_DEFAULT_TARGET,
1553 [ACTION_EXIT] = SPECIAL_EXIT_TARGET,
1554 [ACTION_SUSPEND] = SPECIAL_SUSPEND_TARGET,
1555 [ACTION_HIBERNATE] = SPECIAL_HIBERNATE_TARGET,
1556 [ACTION_HYBRID_SLEEP] = SPECIAL_HYBRID_SLEEP_TARGET
1560 const char *method, *mode, *one_name;
1565 dbus_error_init(&error);
1569 ask_password_agent_open_if_enabled();
1571 if (arg_action == ACTION_SYSTEMCTL) {
1573 streq(args[0], "stop") ||
1574 streq(args[0], "condstop") ? "StopUnit" :
1575 streq(args[0], "reload") ? "ReloadUnit" :
1576 streq(args[0], "restart") ? "RestartUnit" :
1578 streq(args[0], "try-restart") ||
1579 streq(args[0], "condrestart") ? "TryRestartUnit" :
1581 streq(args[0], "reload-or-restart") ? "ReloadOrRestartUnit" :
1583 streq(args[0], "reload-or-try-restart") ||
1584 streq(args[0], "condreload") ||
1586 streq(args[0], "force-reload") ? "ReloadOrTryRestartUnit" :
1590 (streq(args[0], "isolate") ||
1591 streq(args[0], "rescue") ||
1592 streq(args[0], "emergency")) ? "isolate" : arg_job_mode;
1594 one_name = table[verb_to_action(args[0])];
1597 assert(arg_action < ELEMENTSOF(table));
1598 assert(table[arg_action]);
1600 method = "StartUnit";
1602 mode = (arg_action == ACTION_EMERGENCY ||
1603 arg_action == ACTION_RESCUE ||
1604 arg_action == ACTION_RUNLEVEL2 ||
1605 arg_action == ACTION_RUNLEVEL3 ||
1606 arg_action == ACTION_RUNLEVEL4 ||
1607 arg_action == ACTION_RUNLEVEL5) ? "isolate" : "replace";
1609 one_name = table[arg_action];
1612 if (!arg_no_block) {
1613 ret = enable_wait_for_jobs(bus);
1615 log_error("Could not watch jobs: %s", strerror(-ret));
1619 s = set_new(string_hash_func, string_compare_func);
1627 ret = start_unit_one(bus, method, one_name, mode, &error, s);
1629 ret = translate_bus_error_to_exit_status(ret, &error);
1631 STRV_FOREACH(name, args+1) {
1632 r = start_unit_one(bus, method, *name, mode, &error, s);
1634 ret = translate_bus_error_to_exit_status(r, &error);
1635 dbus_error_free(&error);
1640 if (!arg_no_block) {
1641 r = wait_for_jobs(bus, s);
1647 /* When stopping units, warn if they can still be triggered by
1648 * another active unit (socket, path, timer) */
1649 if (!arg_quiet && streq(method, "StopUnit")) {
1651 check_triggering_units(bus, one_name);
1653 STRV_FOREACH(name, args+1)
1654 check_triggering_units(bus, *name);
1660 dbus_error_free(&error);
1665 /* Ask systemd-logind, which might grant access to unprivileged users
1666 * through PolicyKit */
1667 static int reboot_with_logind(DBusConnection *bus, enum action a) {
1670 dbus_bool_t interactive = true;
1675 polkit_agent_open_if_enabled();
1683 case ACTION_POWEROFF:
1684 method = "PowerOff";
1687 case ACTION_SUSPEND:
1691 case ACTION_HIBERNATE:
1692 method = "Hibernate";
1695 case ACTION_HYBRID_SLEEP:
1696 method = "HybridSleep";
1703 return bus_method_call_with_reply(
1705 "org.freedesktop.login1",
1706 "/org/freedesktop/login1",
1707 "org.freedesktop.login1.Manager",
1711 DBUS_TYPE_BOOLEAN, &interactive,
1718 static int check_inhibitors(DBusConnection *bus, enum action a) {
1720 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1721 DBusMessageIter iter, sub, sub2;
1728 if (arg_ignore_inhibitors || arg_force > 0)
1740 r = bus_method_call_with_reply(
1742 "org.freedesktop.login1",
1743 "/org/freedesktop/login1",
1744 "org.freedesktop.login1.Manager",
1750 /* If logind is not around, then there are no inhibitors... */
1753 if (!dbus_message_iter_init(reply, &iter) ||
1754 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
1755 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
1756 log_error("Failed to parse reply.");
1760 dbus_message_iter_recurse(&iter, &sub);
1761 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1762 const char *what, *who, *why, *mode;
1764 _cleanup_strv_free_ char **sv = NULL;
1765 _cleanup_free_ char *comm = NULL;
1767 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
1768 log_error("Failed to parse reply.");
1772 dbus_message_iter_recurse(&sub, &sub2);
1774 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &what, true) < 0 ||
1775 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &who, true) < 0 ||
1776 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &why, true) < 0 ||
1777 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &mode, true) < 0 ||
1778 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &uid, true) < 0 ||
1779 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, false) < 0) {
1780 log_error("Failed to parse reply.");
1784 if (!streq(mode, "block"))
1787 sv = strv_split(what, ":");
1791 if (!strv_contains(sv,
1793 a == ACTION_POWEROFF ||
1794 a == ACTION_REBOOT ||
1795 a == ACTION_KEXEC ? "shutdown" : "sleep"))
1798 get_process_comm(pid, &comm);
1799 log_warning("Operation inhibited by \"%s\" (PID %lu \"%s\", UID %lu), reason is \"%s\".", who, (unsigned long) pid, strna(comm), (unsigned long) uid, why);
1803 dbus_message_iter_next(&sub);
1806 dbus_message_iter_recurse(&iter, &sub);
1811 log_error("Please try again after closing inhibitors or ignore them with 'systemctl %s -i'.",
1812 a == ACTION_HALT ? "halt" :
1813 a == ACTION_POWEROFF ? "poweroff" :
1814 a == ACTION_REBOOT ? "reboot" :
1815 a == ACTION_KEXEC ? "kexec" :
1816 a == ACTION_SUSPEND ? "suspend" :
1817 a == ACTION_HIBERNATE ? "hibernate" : "hybrid-sleep");
1825 static int start_special(DBusConnection *bus, char **args) {
1831 a = verb_to_action(args[0]);
1833 r = check_inhibitors(bus, a);
1837 if (arg_force >= 2 && geteuid() != 0) {
1838 log_error("Must be root.");
1842 if (arg_force >= 2 &&
1843 (a == ACTION_HALT ||
1844 a == ACTION_POWEROFF ||
1845 a == ACTION_REBOOT))
1848 if (arg_force >= 1 &&
1849 (a == ACTION_HALT ||
1850 a == ACTION_POWEROFF ||
1851 a == ACTION_REBOOT ||
1852 a == ACTION_KEXEC ||
1854 return daemon_reload(bus, args);
1856 /* first try logind, to allow authentication with polkit */
1857 if (geteuid() != 0 &&
1858 (a == ACTION_POWEROFF ||
1859 a == ACTION_REBOOT ||
1860 a == ACTION_SUSPEND ||
1861 a == ACTION_HIBERNATE ||
1862 a == ACTION_HYBRID_SLEEP)) {
1863 r = reboot_with_logind(bus, a);
1868 r = start_unit(bus, args);
1875 static int check_unit_active(DBusConnection *bus, char **args) {
1876 const char * const check_states[] = {
1883 int r = 3; /* According to LSB: "program is not running" */
1888 STRV_FOREACH(name, args+1) {
1891 state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
1901 static int check_unit_failed(DBusConnection *bus, char **args) {
1902 const char * const check_states[] = {
1913 STRV_FOREACH(name, args+1) {
1916 state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
1926 static int kill_unit(DBusConnection *bus, char **args) {
1934 arg_kill_who = "all";
1936 STRV_FOREACH(name, args+1) {
1937 _cleanup_free_ char *n = NULL;
1939 n = unit_name_mangle(*name);
1943 r = bus_method_call_with_reply(
1945 "org.freedesktop.systemd1",
1946 "/org/freedesktop/systemd1",
1947 "org.freedesktop.systemd1.Manager",
1951 DBUS_TYPE_STRING, &n,
1952 DBUS_TYPE_STRING, &arg_kill_who,
1953 DBUS_TYPE_INT32, &arg_signal,
1961 static int set_cgroup(DBusConnection *bus, char **args) {
1962 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
1965 DBusMessageIter iter;
1967 _cleanup_free_ char *n = NULL;
1972 dbus_error_init(&error);
1975 streq(args[0], "set-cgroup") ? "SetUnitControlGroups" :
1976 streq(args[0], "unset-group") ? "UnsetUnitControlGroups"
1977 : "UnsetUnitControlGroupAttributes";
1979 n = unit_name_mangle(args[1]);
1983 m = dbus_message_new_method_call(
1984 "org.freedesktop.systemd1",
1985 "/org/freedesktop/systemd1",
1986 "org.freedesktop.systemd1.Manager",
1991 dbus_message_iter_init_append(m, &iter);
1992 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &n))
1995 r = bus_append_strv_iter(&iter, args + 2);
1999 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
2001 log_error("Failed to issue method call: %s", bus_error_message(&error));
2002 dbus_error_free(&error);
2009 static int set_cgroup_attr(DBusConnection *bus, char **args) {
2010 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
2012 DBusMessageIter iter, sub, sub2;
2014 _cleanup_free_ char *n = NULL;
2019 dbus_error_init(&error);
2021 if (strv_length(args) % 2 != 0) {
2022 log_error("Expecting an uneven number of arguments!");
2026 n = unit_name_mangle(args[1]);
2030 m = dbus_message_new_method_call(
2031 "org.freedesktop.systemd1",
2032 "/org/freedesktop/systemd1",
2033 "org.freedesktop.systemd1.Manager",
2034 "SetUnitControlGroupAttributes");
2038 dbus_message_iter_init_append(m, &iter);
2039 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &n) ||
2040 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ss)", &sub))
2043 STRV_FOREACH_PAIR(x, y, args + 2) {
2044 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
2045 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, x) ||
2046 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, y) ||
2047 !dbus_message_iter_close_container(&sub, &sub2))
2051 if (!dbus_message_iter_close_container(&iter, &sub))
2054 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
2056 log_error("Failed to issue method call: %s", bus_error_message(&error));
2057 dbus_error_free(&error);
2064 typedef struct ExecStatusInfo {
2072 usec_t start_timestamp;
2073 usec_t exit_timestamp;
2078 LIST_FIELDS(struct ExecStatusInfo, exec);
2081 static void exec_status_info_free(ExecStatusInfo *i) {
2090 static int exec_status_info_deserialize(DBusMessageIter *sub, ExecStatusInfo *i) {
2091 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
2092 DBusMessageIter sub2, sub3;
2096 int32_t code, status;
2102 if (dbus_message_iter_get_arg_type(sub) != DBUS_TYPE_STRUCT)
2105 dbus_message_iter_recurse(sub, &sub2);
2107 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0)
2110 i->path = strdup(path);
2114 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_ARRAY ||
2115 dbus_message_iter_get_element_type(&sub2) != DBUS_TYPE_STRING)
2119 dbus_message_iter_recurse(&sub2, &sub3);
2120 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2121 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2122 dbus_message_iter_next(&sub3);
2126 i->argv = new0(char*, n+1);
2131 dbus_message_iter_recurse(&sub2, &sub3);
2132 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2135 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2136 dbus_message_iter_get_basic(&sub3, &s);
2137 dbus_message_iter_next(&sub3);
2139 i->argv[n] = strdup(s);
2146 if (!dbus_message_iter_next(&sub2) ||
2147 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, true) < 0 ||
2148 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp, true) < 0 ||
2149 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp_monotonic, true) < 0 ||
2150 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp, true) < 0 ||
2151 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp_monotonic, true) < 0 ||
2152 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, true) < 0 ||
2153 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &code, true) < 0 ||
2154 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &status, false) < 0)
2158 i->start_timestamp = (usec_t) start_timestamp;
2159 i->exit_timestamp = (usec_t) exit_timestamp;
2160 i->pid = (pid_t) pid;
2167 typedef struct UnitStatusInfo {
2169 const char *load_state;
2170 const char *active_state;
2171 const char *sub_state;
2172 const char *unit_file_state;
2174 const char *description;
2175 const char *following;
2177 char **documentation;
2179 const char *fragment_path;
2180 const char *source_path;
2181 const char *default_control_group;
2183 const char *load_error;
2186 usec_t inactive_exit_timestamp;
2187 usec_t inactive_exit_timestamp_monotonic;
2188 usec_t active_enter_timestamp;
2189 usec_t active_exit_timestamp;
2190 usec_t inactive_enter_timestamp;
2192 bool need_daemon_reload;
2197 const char *status_text;
2200 usec_t start_timestamp;
2201 usec_t exit_timestamp;
2203 int exit_code, exit_status;
2205 usec_t condition_timestamp;
2206 bool condition_result;
2209 unsigned n_accepted;
2210 unsigned n_connections;
2214 const char *sysfs_path;
2216 /* Mount, Automount */
2222 LIST_HEAD(ExecStatusInfo, exec);
2225 static void print_status_info(UnitStatusInfo *i) {
2227 const char *on, *off, *ss;
2229 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
2230 char since2[FORMAT_TIMESTAMP_MAX], *s2;
2235 /* This shows pretty information about a unit. See
2236 * print_property() for a low-level property printer */
2238 printf("%s", strna(i->id));
2240 if (i->description && !streq_ptr(i->id, i->description))
2241 printf(" - %s", i->description);
2246 printf("\t Follow: unit currently follows state of %s\n", i->following);
2248 if (streq_ptr(i->load_state, "error")) {
2249 on = ansi_highlight_red(true);
2250 off = ansi_highlight_red(false);
2254 path = i->source_path ? i->source_path : i->fragment_path;
2257 printf("\t Loaded: %s%s%s (Reason: %s)\n", on, strna(i->load_state), off, i->load_error);
2258 else if (path && i->unit_file_state)
2259 printf("\t Loaded: %s%s%s (%s; %s)\n", on, strna(i->load_state), off, path, i->unit_file_state);
2261 printf("\t Loaded: %s%s%s (%s)\n", on, strna(i->load_state), off, path);
2263 printf("\t Loaded: %s%s%s\n", on, strna(i->load_state), off);
2265 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
2267 if (streq_ptr(i->active_state, "failed")) {
2268 on = ansi_highlight_red(true);
2269 off = ansi_highlight_red(false);
2270 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
2271 on = ansi_highlight_green(true);
2272 off = ansi_highlight_green(false);
2277 printf("\t Active: %s%s (%s)%s",
2279 strna(i->active_state),
2283 printf("\t Active: %s%s%s",
2285 strna(i->active_state),
2288 if (!isempty(i->result) && !streq(i->result, "success"))
2289 printf(" (Result: %s)", i->result);
2291 timestamp = (streq_ptr(i->active_state, "active") ||
2292 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
2293 (streq_ptr(i->active_state, "inactive") ||
2294 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
2295 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
2296 i->active_exit_timestamp;
2298 s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
2299 s2 = format_timestamp(since2, sizeof(since2), timestamp);
2302 printf(" since %s; %s\n", s2, s1);
2304 printf(" since %s\n", s2);
2308 if (!i->condition_result && i->condition_timestamp > 0) {
2309 s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
2310 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
2313 printf("\t start condition failed at %s; %s\n", s2, s1);
2315 printf("\t start condition failed at %s\n", s2);
2319 printf("\t Device: %s\n", i->sysfs_path);
2321 printf("\t Where: %s\n", i->where);
2323 printf("\t What: %s\n", i->what);
2325 if (!strv_isempty(i->documentation)) {
2329 STRV_FOREACH(t, i->documentation) {
2331 printf("\t Docs: %s\n", *t);
2334 printf("\t %s\n", *t);
2339 printf("\tAccepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
2341 LIST_FOREACH(exec, p, i->exec) {
2342 _cleanup_free_ char *t = NULL;
2345 /* Only show exited processes here */
2349 t = strv_join(p->argv, " ");
2350 printf("\t Process: %u %s=%s ", p->pid, p->name, strna(t));
2352 good = is_clean_exit_lsb(p->code, p->status, NULL);
2354 on = ansi_highlight_red(true);
2355 off = ansi_highlight_red(false);
2359 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
2361 if (p->code == CLD_EXITED) {
2364 printf("status=%i", p->status);
2366 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
2371 printf("signal=%s", signal_to_string(p->status));
2373 printf(")%s\n", off);
2375 if (i->main_pid == p->pid &&
2376 i->start_timestamp == p->start_timestamp &&
2377 i->exit_timestamp == p->start_timestamp)
2378 /* Let's not show this twice */
2381 if (p->pid == i->control_pid)
2385 if (i->main_pid > 0 || i->control_pid > 0) {
2388 if (i->main_pid > 0) {
2389 printf("Main PID: %u", (unsigned) i->main_pid);
2392 _cleanup_free_ char *t = NULL;
2393 get_process_comm(i->main_pid, &t);
2396 } else if (i->exit_code > 0) {
2397 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
2399 if (i->exit_code == CLD_EXITED) {
2402 printf("status=%i", i->exit_status);
2404 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
2409 printf("signal=%s", signal_to_string(i->exit_status));
2414 if (i->main_pid > 0 && i->control_pid > 0)
2417 if (i->control_pid > 0) {
2418 _cleanup_free_ char *t = NULL;
2420 printf(" Control: %u", (unsigned) i->control_pid);
2422 get_process_comm(i->control_pid, &t);
2431 printf("\t Status: \"%s\"\n", i->status_text);
2433 if (i->default_control_group &&
2434 (i->main_pid > 0 || i->control_pid > 0 || cg_is_empty_by_spec(i->default_control_group, false) == 0)) {
2437 printf("\t CGroup: %s\n", i->default_control_group);
2439 if (arg_transport != TRANSPORT_SSH) {
2449 if (i->main_pid > 0)
2450 extra[k++] = i->main_pid;
2452 if (i->control_pid > 0)
2453 extra[k++] = i->control_pid;
2455 show_cgroup_and_extra_by_spec(i->default_control_group, "\t\t ", c, false, arg_all, extra, k);
2459 if (i->id && arg_transport != TRANSPORT_SSH) {
2461 arg_all * OUTPUT_SHOW_ALL |
2462 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
2463 on_tty() * OUTPUT_COLOR |
2464 !arg_quiet * OUTPUT_WARN_CUTOFF;
2467 show_journal_by_unit(stdout,
2471 i->inactive_exit_timestamp_monotonic,
2476 if (i->need_daemon_reload)
2477 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %s daemon-reload' recommended.\n",
2478 ansi_highlight_red(true),
2479 ansi_highlight_red(false),
2480 arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
2483 static void show_unit_help(UnitStatusInfo *i) {
2488 if (!i->documentation) {
2489 log_info("Documentation for %s not known.", i->id);
2493 STRV_FOREACH(p, i->documentation) {
2495 if (startswith(*p, "man:")) {
2498 char *page = NULL, *section = NULL;
2499 const char *args[4] = { "man", NULL, NULL, NULL };
2504 if ((*p)[k-1] == ')')
2505 e = strrchr(*p, '(');
2508 page = strndup((*p) + 4, e - *p - 4);
2514 section = strndup(e + 1, *p + k - e - 2);
2528 log_error("Failed to fork: %m");
2536 execvp(args[0], (char**) args);
2537 log_error("Failed to execute man: %m");
2538 _exit(EXIT_FAILURE);
2544 wait_for_terminate(pid, NULL);
2546 log_info("Can't show: %s", *p);
2550 static int status_property(const char *name, DBusMessageIter *iter, UnitStatusInfo *i) {
2556 switch (dbus_message_iter_get_arg_type(iter)) {
2558 case DBUS_TYPE_STRING: {
2561 dbus_message_iter_get_basic(iter, &s);
2564 if (streq(name, "Id"))
2566 else if (streq(name, "LoadState"))
2568 else if (streq(name, "ActiveState"))
2569 i->active_state = s;
2570 else if (streq(name, "SubState"))
2572 else if (streq(name, "Description"))
2574 else if (streq(name, "FragmentPath"))
2575 i->fragment_path = s;
2576 else if (streq(name, "SourcePath"))
2578 else if (streq(name, "DefaultControlGroup"))
2579 i->default_control_group = s;
2580 else if (streq(name, "StatusText"))
2582 else if (streq(name, "SysFSPath"))
2584 else if (streq(name, "Where"))
2586 else if (streq(name, "What"))
2588 else if (streq(name, "Following"))
2590 else if (streq(name, "UnitFileState"))
2591 i->unit_file_state = s;
2592 else if (streq(name, "Result"))
2599 case DBUS_TYPE_BOOLEAN: {
2602 dbus_message_iter_get_basic(iter, &b);
2604 if (streq(name, "Accept"))
2606 else if (streq(name, "NeedDaemonReload"))
2607 i->need_daemon_reload = b;
2608 else if (streq(name, "ConditionResult"))
2609 i->condition_result = b;
2614 case DBUS_TYPE_UINT32: {
2617 dbus_message_iter_get_basic(iter, &u);
2619 if (streq(name, "MainPID")) {
2621 i->main_pid = (pid_t) u;
2624 } else if (streq(name, "ControlPID"))
2625 i->control_pid = (pid_t) u;
2626 else if (streq(name, "ExecMainPID")) {
2628 i->main_pid = (pid_t) u;
2629 } else if (streq(name, "NAccepted"))
2631 else if (streq(name, "NConnections"))
2632 i->n_connections = u;
2637 case DBUS_TYPE_INT32: {
2640 dbus_message_iter_get_basic(iter, &j);
2642 if (streq(name, "ExecMainCode"))
2643 i->exit_code = (int) j;
2644 else if (streq(name, "ExecMainStatus"))
2645 i->exit_status = (int) j;
2650 case DBUS_TYPE_UINT64: {
2653 dbus_message_iter_get_basic(iter, &u);
2655 if (streq(name, "ExecMainStartTimestamp"))
2656 i->start_timestamp = (usec_t) u;
2657 else if (streq(name, "ExecMainExitTimestamp"))
2658 i->exit_timestamp = (usec_t) u;
2659 else if (streq(name, "ActiveEnterTimestamp"))
2660 i->active_enter_timestamp = (usec_t) u;
2661 else if (streq(name, "InactiveEnterTimestamp"))
2662 i->inactive_enter_timestamp = (usec_t) u;
2663 else if (streq(name, "InactiveExitTimestamp"))
2664 i->inactive_exit_timestamp = (usec_t) u;
2665 else if (streq(name, "InactiveExitTimestampMonotonic"))
2666 i->inactive_exit_timestamp_monotonic = (usec_t) u;
2667 else if (streq(name, "ActiveExitTimestamp"))
2668 i->active_exit_timestamp = (usec_t) u;
2669 else if (streq(name, "ConditionTimestamp"))
2670 i->condition_timestamp = (usec_t) u;
2675 case DBUS_TYPE_ARRAY: {
2677 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
2678 startswith(name, "Exec")) {
2679 DBusMessageIter sub;
2681 dbus_message_iter_recurse(iter, &sub);
2682 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2683 ExecStatusInfo *info;
2686 if (!(info = new0(ExecStatusInfo, 1)))
2689 if (!(info->name = strdup(name))) {
2694 if ((r = exec_status_info_deserialize(&sub, info)) < 0) {
2699 LIST_PREPEND(ExecStatusInfo, exec, i->exec, info);
2701 dbus_message_iter_next(&sub);
2703 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
2704 streq(name, "Documentation")) {
2706 DBusMessageIter sub;
2708 dbus_message_iter_recurse(iter, &sub);
2709 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING) {
2713 dbus_message_iter_get_basic(&sub, &s);
2715 l = strv_append(i->documentation, s);
2719 strv_free(i->documentation);
2720 i->documentation = l;
2722 dbus_message_iter_next(&sub);
2729 case DBUS_TYPE_STRUCT: {
2731 if (streq(name, "LoadError")) {
2732 DBusMessageIter sub;
2733 const char *n, *message;
2736 dbus_message_iter_recurse(iter, &sub);
2738 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &n, true);
2742 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &message, false);
2746 if (!isempty(message))
2747 i->load_error = message;
2757 static int print_property(const char *name, DBusMessageIter *iter) {
2761 /* This is a low-level property printer, see
2762 * print_status_info() for the nicer output */
2764 if (arg_property && !strv_find(arg_property, name))
2767 switch (dbus_message_iter_get_arg_type(iter)) {
2769 case DBUS_TYPE_STRUCT: {
2770 DBusMessageIter sub;
2771 dbus_message_iter_recurse(iter, &sub);
2773 if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32 && streq(name, "Job")) {
2776 dbus_message_iter_get_basic(&sub, &u);
2779 printf("%s=%u\n", name, (unsigned) u);
2781 printf("%s=\n", name);
2784 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "Unit")) {
2787 dbus_message_iter_get_basic(&sub, &s);
2789 if (arg_all || s[0])
2790 printf("%s=%s\n", name, s);
2793 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "LoadError")) {
2794 const char *a = NULL, *b = NULL;
2796 if (bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &a, true) >= 0)
2797 bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &b, false);
2799 if (arg_all || !isempty(a) || !isempty(b))
2800 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
2808 case DBUS_TYPE_ARRAY:
2810 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "EnvironmentFiles")) {
2811 DBusMessageIter sub, sub2;
2813 dbus_message_iter_recurse(iter, &sub);
2814 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2818 dbus_message_iter_recurse(&sub, &sub2);
2820 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
2821 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) >= 0)
2822 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
2824 dbus_message_iter_next(&sub);
2829 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Paths")) {
2830 DBusMessageIter sub, sub2;
2832 dbus_message_iter_recurse(iter, &sub);
2833 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2834 const char *type, *path;
2836 dbus_message_iter_recurse(&sub, &sub2);
2838 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
2839 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
2840 printf("%s=%s\n", type, path);
2842 dbus_message_iter_next(&sub);
2847 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Timers")) {
2848 DBusMessageIter sub, sub2;
2850 dbus_message_iter_recurse(iter, &sub);
2851 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2853 uint64_t value, next_elapse;
2855 dbus_message_iter_recurse(&sub, &sub2);
2857 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &base, true) >= 0 &&
2858 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &value, true) >= 0 &&
2859 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &next_elapse, false) >= 0) {
2860 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
2862 printf("%s={ value=%s ; next_elapse=%s }\n",
2864 format_timespan(timespan1, sizeof(timespan1), value),
2865 format_timespan(timespan2, sizeof(timespan2), next_elapse));
2868 dbus_message_iter_next(&sub);
2873 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "ControlGroupAttributes")) {
2874 DBusMessageIter sub, sub2;
2876 dbus_message_iter_recurse(iter, &sub);
2877 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2878 const char *controller, *attr, *value;
2880 dbus_message_iter_recurse(&sub, &sub2);
2882 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &controller, true) >= 0 &&
2883 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &attr, true) >= 0 &&
2884 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &value, false) >= 0) {
2886 printf("ControlGroupAttribute={ controller=%s ; attribute=%s ; value=\"%s\" }\n",
2892 dbus_message_iter_next(&sub);
2897 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && startswith(name, "Exec")) {
2898 DBusMessageIter sub;
2900 dbus_message_iter_recurse(iter, &sub);
2901 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2902 ExecStatusInfo info;
2905 if (exec_status_info_deserialize(&sub, &info) >= 0) {
2906 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
2909 t = strv_join(info.argv, " ");
2911 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
2915 yes_no(info.ignore),
2916 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
2917 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
2918 (unsigned) info. pid,
2919 sigchld_code_to_string(info.code),
2921 info.code == CLD_EXITED ? "" : "/",
2922 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
2928 strv_free(info.argv);
2930 dbus_message_iter_next(&sub);
2939 if (generic_print_property(name, iter, arg_all) > 0)
2943 printf("%s=[unprintable]\n", name);
2948 static int show_one(const char *verb, DBusConnection *bus, const char *path, bool show_properties, bool *new_line) {
2949 _cleanup_free_ DBusMessage *reply = NULL;
2950 const char *interface = "";
2952 DBusMessageIter iter, sub, sub2, sub3;
2953 UnitStatusInfo info;
2961 r = bus_method_call_with_reply(
2963 "org.freedesktop.systemd1",
2965 "org.freedesktop.DBus.Properties",
2969 DBUS_TYPE_STRING, &interface,
2974 if (!dbus_message_iter_init(reply, &iter) ||
2975 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
2976 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
2977 log_error("Failed to parse reply.");
2981 dbus_message_iter_recurse(&iter, &sub);
2988 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
2991 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_DICT_ENTRY);
2992 dbus_message_iter_recurse(&sub, &sub2);
2994 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
2995 dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
2996 log_error("Failed to parse reply.");
3000 dbus_message_iter_recurse(&sub2, &sub3);
3002 if (show_properties)
3003 r = print_property(name, &sub3);
3005 r = status_property(name, &sub3, &info);
3007 log_error("Failed to parse reply.");
3011 dbus_message_iter_next(&sub);
3016 if (!show_properties) {
3017 if (streq(verb, "help"))
3018 show_unit_help(&info);
3020 print_status_info(&info);
3023 strv_free(info.documentation);
3025 if (!streq_ptr(info.active_state, "active") &&
3026 !streq_ptr(info.active_state, "reloading") &&
3027 streq(verb, "status"))
3028 /* According to LSB: "program not running" */
3031 while ((p = info.exec)) {
3032 LIST_REMOVE(ExecStatusInfo, exec, info.exec, p);
3033 exec_status_info_free(p);
3039 static int show_one_by_pid(const char *verb, DBusConnection *bus, uint32_t pid, bool *new_line) {
3040 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3041 const char *path = NULL;
3045 dbus_error_init(&error);
3047 r = bus_method_call_with_reply(
3049 "org.freedesktop.systemd1",
3050 "/org/freedesktop/systemd1",
3051 "org.freedesktop.systemd1.Manager",
3055 DBUS_TYPE_UINT32, &pid,
3060 if (!dbus_message_get_args(reply, &error,
3061 DBUS_TYPE_OBJECT_PATH, &path,
3062 DBUS_TYPE_INVALID)) {
3063 log_error("Failed to parse reply: %s", bus_error_message(&error));
3068 r = show_one(verb, bus, path, false, new_line);
3071 dbus_error_free(&error);
3076 static int show(DBusConnection *bus, char **args) {
3078 bool show_properties, new_line = false;
3084 show_properties = streq(args[0], "show");
3086 if (show_properties)
3087 pager_open_if_enabled();
3089 /* If no argument is specified inspect the manager itself */
3091 if (show_properties && strv_length(args) <= 1)
3092 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line);
3094 STRV_FOREACH(name, args+1) {
3097 if (safe_atou32(*name, &id) < 0) {
3098 _cleanup_free_ char *p = NULL, *n = NULL;
3099 /* Interpret as unit name */
3101 n = unit_name_mangle(*name);
3105 p = unit_dbus_path_from_name(n);
3109 r = show_one(args[0], bus, p, show_properties, &new_line);
3113 } else if (show_properties) {
3114 _cleanup_free_ char *p = NULL;
3116 /* Interpret as job id */
3117 if (asprintf(&p, "/org/freedesktop/systemd1/job/%u", id) < 0)
3120 r = show_one(args[0], bus, p, show_properties, &new_line);
3125 /* Interpret as PID */
3126 r = show_one_by_pid(args[0], bus, id, &new_line);
3135 static int dump(DBusConnection *bus, char **args) {
3136 _cleanup_free_ DBusMessage *reply = NULL;
3141 dbus_error_init(&error);
3143 pager_open_if_enabled();
3145 r = bus_method_call_with_reply(
3147 "org.freedesktop.systemd1",
3148 "/org/freedesktop/systemd1",
3149 "org.freedesktop.systemd1.Manager",
3157 if (!dbus_message_get_args(reply, &error,
3158 DBUS_TYPE_STRING, &text,
3159 DBUS_TYPE_INVALID)) {
3160 log_error("Failed to parse reply: %s", bus_error_message(&error));
3161 dbus_error_free(&error);
3165 fputs(text, stdout);
3169 static int snapshot(DBusConnection *bus, char **args) {
3170 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3173 dbus_bool_t cleanup = FALSE;
3174 DBusMessageIter iter, sub;
3176 *name = "", *path, *id,
3177 *interface = "org.freedesktop.systemd1.Unit",
3179 _cleanup_free_ char *n = NULL;
3181 dbus_error_init(&error);
3183 if (strv_length(args) > 1) {
3185 n = unit_name_mangle(name);
3188 r = bus_method_call_with_reply (
3190 "org.freedesktop.systemd1",
3191 "/org/freedesktop/systemd1",
3192 "org.freedesktop.systemd1.Manager",
3196 DBUS_TYPE_STRING, n ? (const char**) &n : &name,
3197 DBUS_TYPE_BOOLEAN, &cleanup,
3202 if (!dbus_message_get_args(reply, &error,
3203 DBUS_TYPE_OBJECT_PATH, &path,
3204 DBUS_TYPE_INVALID)) {
3205 log_error("Failed to parse reply: %s", bus_error_message(&error));
3210 dbus_message_unref(reply);
3213 r = bus_method_call_with_reply (
3215 "org.freedesktop.systemd1",
3217 "org.freedesktop.DBus.Properties",
3221 DBUS_TYPE_STRING, &interface,
3222 DBUS_TYPE_STRING, &property,
3227 if (!dbus_message_iter_init(reply, &iter) ||
3228 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3229 log_error("Failed to parse reply.");
3234 dbus_message_iter_recurse(&iter, &sub);
3236 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
3237 log_error("Failed to parse reply.");
3242 dbus_message_iter_get_basic(&sub, &id);
3248 dbus_error_free(&error);
3253 static int delete_snapshot(DBusConnection *bus, char **args) {
3258 STRV_FOREACH(name, args+1) {
3259 _cleanup_free_ char *n = NULL;
3262 n = unit_name_mangle(*name);
3263 r = bus_method_call_with_reply(
3265 "org.freedesktop.systemd1",
3266 "/org/freedesktop/systemd1",
3267 "org.freedesktop.systemd1.Manager",
3271 DBUS_TYPE_STRING, n ? &n : name,
3280 static int daemon_reload(DBusConnection *bus, char **args) {
3285 if (arg_action == ACTION_RELOAD)
3287 else if (arg_action == ACTION_REEXEC)
3288 method = "Reexecute";
3290 assert(arg_action == ACTION_SYSTEMCTL);
3293 streq(args[0], "clear-jobs") ||
3294 streq(args[0], "cancel") ? "ClearJobs" :
3295 streq(args[0], "daemon-reexec") ? "Reexecute" :
3296 streq(args[0], "reset-failed") ? "ResetFailed" :
3297 streq(args[0], "halt") ? "Halt" :
3298 streq(args[0], "poweroff") ? "PowerOff" :
3299 streq(args[0], "reboot") ? "Reboot" :
3300 streq(args[0], "kexec") ? "KExec" :
3301 streq(args[0], "exit") ? "Exit" :
3302 /* "daemon-reload" */ "Reload";
3305 r = bus_method_call_with_reply (
3307 "org.freedesktop.systemd1",
3308 "/org/freedesktop/systemd1",
3309 "org.freedesktop.systemd1.Manager",
3315 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
3316 /* There's always a fallback possible for
3317 * legacy actions. */
3319 else if (r == -ETIMEDOUT && streq(method, "Reexecute"))
3320 /* On reexecution, we expect a disconnect, not
3324 log_error("Failed to issue method call: %s", bus_error_message(&error));
3325 dbus_error_free(&error);
3330 static int reset_failed(DBusConnection *bus, char **args) {
3334 if (strv_length(args) <= 1)
3335 return daemon_reload(bus, args);
3337 STRV_FOREACH(name, args+1) {
3338 _cleanup_free_ char *n;
3340 n = unit_name_mangle(*name);
3344 r = bus_method_call_with_reply(
3346 "org.freedesktop.systemd1",
3347 "/org/freedesktop/systemd1",
3348 "org.freedesktop.systemd1.Manager",
3352 DBUS_TYPE_STRING, &n,
3361 static int show_enviroment(DBusConnection *bus, char **args) {
3362 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3363 DBusMessageIter iter, sub, sub2;
3366 *interface = "org.freedesktop.systemd1.Manager",
3367 *property = "Environment";
3369 pager_open_if_enabled();
3371 r = bus_method_call_with_reply(
3373 "org.freedesktop.systemd1",
3374 "/org/freedesktop/systemd1",
3375 "org.freedesktop.DBus.Properties",
3379 DBUS_TYPE_STRING, &interface,
3380 DBUS_TYPE_STRING, &property,
3385 if (!dbus_message_iter_init(reply, &iter) ||
3386 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3387 log_error("Failed to parse reply.");
3391 dbus_message_iter_recurse(&iter, &sub);
3393 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_ARRAY ||
3394 dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_STRING) {
3395 log_error("Failed to parse reply.");
3399 dbus_message_iter_recurse(&sub, &sub2);
3401 while (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_INVALID) {
3404 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
3405 log_error("Failed to parse reply.");
3409 dbus_message_iter_get_basic(&sub2, &text);
3412 dbus_message_iter_next(&sub2);
3418 static int switch_root(DBusConnection *bus, char **args) {
3421 _cleanup_free_ char *init = NULL;
3423 l = strv_length(args);
3424 if (l < 2 || l > 3) {
3425 log_error("Wrong number of arguments.");
3432 init = strdup(args[2]);
3434 parse_env_file("/proc/cmdline", WHITESPACE,
3444 log_debug("switching root - root: %s; init: %s", root, init);
3446 return bus_method_call_with_reply(
3448 "org.freedesktop.systemd1",
3449 "/org/freedesktop/systemd1",
3450 "org.freedesktop.systemd1.Manager",
3454 DBUS_TYPE_STRING, &root,
3455 DBUS_TYPE_STRING, &init,
3459 static int set_environment(DBusConnection *bus, char **args) {
3460 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
3463 DBusMessageIter iter;
3469 dbus_error_init(&error);
3471 method = streq(args[0], "set-environment")
3473 : "UnsetEnvironment";
3475 m = dbus_message_new_method_call(
3476 "org.freedesktop.systemd1",
3477 "/org/freedesktop/systemd1",
3478 "org.freedesktop.systemd1.Manager",
3483 dbus_message_iter_init_append(m, &iter);
3485 r = bus_append_strv_iter(&iter, args + 1);
3489 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3491 log_error("Failed to issue method call: %s", bus_error_message(&error));
3492 dbus_error_free(&error);
3499 static int enable_sysv_units(char **args) {
3502 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
3503 const char *verb = args[0];
3504 unsigned f = 1, t = 1;
3507 if (arg_scope != UNIT_FILE_SYSTEM)
3510 if (!streq(verb, "enable") &&
3511 !streq(verb, "disable") &&
3512 !streq(verb, "is-enabled"))
3515 /* Processes all SysV units, and reshuffles the array so that
3516 * afterwards only the native units remain */
3519 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, NULL, NULL, NULL);
3524 for (f = 1; args[f]; f++) {
3527 bool found_native = false, found_sysv;
3529 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
3530 char **k, *l, *q = NULL;
3537 if (!endswith(name, ".service"))
3540 if (path_is_absolute(name))
3543 STRV_FOREACH(k, paths.unit_path) {
3546 if (!isempty(arg_root))
3547 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
3549 asprintf(&p, "%s/%s", *k, name);
3556 found_native = access(p, F_OK) >= 0;
3567 if (!isempty(arg_root))
3568 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
3570 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
3576 p[strlen(p) - sizeof(".service") + 1] = 0;
3577 found_sysv = access(p, F_OK) >= 0;
3584 /* Mark this entry, so that we don't try enabling it as native unit */
3585 args[f] = (char*) "";
3587 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
3589 if (!isempty(arg_root))
3590 argv[c++] = q = strappend("--root=", arg_root);
3592 argv[c++] = path_get_file_name(p);
3594 streq(verb, "enable") ? "on" :
3595 streq(verb, "disable") ? "off" : "--level=5";
3598 l = strv_join((char**)argv, " ");
3606 log_info("Executing %s", l);
3611 log_error("Failed to fork: %m");
3616 } else if (pid == 0) {
3619 execv(argv[0], (char**) argv);
3620 _exit(EXIT_FAILURE);
3626 j = wait_for_terminate(pid, &status);
3628 log_error("Failed to wait for child: %s", strerror(-r));
3633 if (status.si_code == CLD_EXITED) {
3634 if (streq(verb, "is-enabled")) {
3635 if (status.si_status == 0) {
3644 } else if (status.si_status != 0) {
3655 lookup_paths_free(&paths);
3657 /* Drop all SysV units */
3658 for (f = 1, t = 1; args[f]; f++) {
3660 if (isempty(args[f]))
3663 args[t++] = args[f];
3672 static int mangle_names(char **original_names, char ***mangled_names) {
3673 char **i, **l, **name;
3675 l = new(char*, strv_length(original_names) + 1);
3680 STRV_FOREACH(name, original_names) {
3682 /* When enabling units qualified path names are OK,
3683 * too, hence allow them explicitly. */
3688 *i = unit_name_mangle(*name);
3704 static int enable_unit(DBusConnection *bus, char **args) {
3705 const char *verb = args[0];
3706 UnitFileChange *changes = NULL;
3707 unsigned n_changes = 0, i;
3708 int carries_install_info = -1;
3709 DBusMessage *m = NULL, *reply = NULL;
3712 char **mangled_names = NULL;
3714 r = enable_sysv_units(args);
3721 dbus_error_init(&error);
3723 if (!bus || avoid_bus()) {
3724 if (streq(verb, "enable")) {
3725 r = unit_file_enable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3726 carries_install_info = r;
3727 } else if (streq(verb, "disable"))
3728 r = unit_file_disable(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3729 else if (streq(verb, "reenable")) {
3730 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3731 carries_install_info = r;
3732 } else if (streq(verb, "link"))
3733 r = unit_file_link(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3734 else if (streq(verb, "preset")) {
3735 r = unit_file_preset(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3736 carries_install_info = r;
3737 } else if (streq(verb, "mask"))
3738 r = unit_file_mask(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3739 else if (streq(verb, "unmask"))
3740 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3742 assert_not_reached("Unknown verb");
3745 log_error("Operation failed: %s", strerror(-r));
3750 for (i = 0; i < n_changes; i++) {
3751 if (changes[i].type == UNIT_FILE_SYMLINK)
3752 log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
3754 log_info("rm '%s'", changes[i].path);
3761 bool send_force = true, expect_carries_install_info = false;
3763 DBusMessageIter iter, sub, sub2;
3765 if (streq(verb, "enable")) {
3766 method = "EnableUnitFiles";
3767 expect_carries_install_info = true;
3768 } else if (streq(verb, "disable")) {
3769 method = "DisableUnitFiles";
3771 } else if (streq(verb, "reenable")) {
3772 method = "ReenableUnitFiles";
3773 expect_carries_install_info = true;
3774 } else if (streq(verb, "link"))
3775 method = "LinkUnitFiles";
3776 else if (streq(verb, "preset")) {
3777 method = "PresetUnitFiles";
3778 expect_carries_install_info = true;
3779 } else if (streq(verb, "mask"))
3780 method = "MaskUnitFiles";
3781 else if (streq(verb, "unmask")) {
3782 method = "UnmaskUnitFiles";
3785 assert_not_reached("Unknown verb");
3787 m = dbus_message_new_method_call(
3788 "org.freedesktop.systemd1",
3789 "/org/freedesktop/systemd1",
3790 "org.freedesktop.systemd1.Manager",
3797 dbus_message_iter_init_append(m, &iter);
3799 r = mangle_names(args+1, &mangled_names);
3803 r = bus_append_strv_iter(&iter, mangled_names);
3805 log_error("Failed to append unit files.");
3810 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &a)) {
3811 log_error("Failed to append runtime boolean.");
3819 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b)) {
3820 log_error("Failed to append force boolean.");
3826 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3828 log_error("Failed to issue method call: %s", bus_error_message(&error));
3833 if (!dbus_message_iter_init(reply, &iter)) {
3834 log_error("Failed to initialize iterator.");
3838 if (expect_carries_install_info) {
3839 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &b, true);
3841 log_error("Failed to parse reply.");
3845 carries_install_info = b;
3848 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3849 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
3850 log_error("Failed to parse reply.");
3855 dbus_message_iter_recurse(&iter, &sub);
3856 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
3857 const char *type, *path, *source;
3859 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
3860 log_error("Failed to parse reply.");
3865 dbus_message_iter_recurse(&sub, &sub2);
3867 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
3868 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
3869 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &source, false) < 0) {
3870 log_error("Failed to parse reply.");
3876 if (streq(type, "symlink"))
3877 log_info("ln -s '%s' '%s'", source, path);
3879 log_info("rm '%s'", path);
3882 dbus_message_iter_next(&sub);
3885 /* Try to reload if enabeld */
3887 r = daemon_reload(bus, args);
3890 if (carries_install_info == 0)
3892 "The unit files have no [Install] section. They are not meant to be enabled\n"
3893 "using systemctl.\n"
3894 "Possible reasons for having this kind of units are:\n"
3895 "1) A unit may be statically enabled by being symlinked from another unit's\n"
3896 " .wants/ or .requires/ directory.\n"
3897 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
3898 " a requirement dependency on it.\n"
3899 "3) A unit may be started when needed via activation (socket, path, timer,\n"
3900 " D-Bus, udev, scripted systemctl call, ...).\n");
3904 dbus_message_unref(m);
3907 dbus_message_unref(reply);
3909 unit_file_changes_free(changes, n_changes);
3911 dbus_error_free(&error);
3913 strv_free(mangled_names);
3918 static int unit_is_enabled(DBusConnection *bus, char **args) {
3921 DBusMessage *reply = NULL;
3925 dbus_error_init(&error);
3927 r = enable_sysv_units(args);
3933 if (!bus || avoid_bus()) {
3935 STRV_FOREACH(name, args+1) {
3936 UnitFileState state;
3938 state = unit_file_get_state(arg_scope, arg_root, *name);
3944 if (state == UNIT_FILE_ENABLED ||
3945 state == UNIT_FILE_ENABLED_RUNTIME ||
3946 state == UNIT_FILE_STATIC)
3950 puts(unit_file_state_to_string(state));
3954 STRV_FOREACH(name, args+1) {
3957 r = bus_method_call_with_reply (
3959 "org.freedesktop.systemd1",
3960 "/org/freedesktop/systemd1",
3961 "org.freedesktop.systemd1.Manager",
3965 DBUS_TYPE_STRING, name,
3970 if (!dbus_message_get_args(reply, &error,
3971 DBUS_TYPE_STRING, &s,
3972 DBUS_TYPE_INVALID)) {
3973 log_error("Failed to parse reply: %s", bus_error_message(&error));
3978 dbus_message_unref(reply);
3981 if (streq(s, "enabled") ||
3982 streq(s, "enabled-runtime") ||
3991 r = enabled ? 0 : 1;
3995 dbus_message_unref(reply);
3997 dbus_error_free(&error);
4001 static int systemctl_help(void) {
4003 pager_open_if_enabled();
4005 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
4006 "Query or send control commands to the systemd manager.\n\n"
4007 " -h --help Show this help\n"
4008 " --version Show package version\n"
4009 " -t --type=TYPE List only units of a particular type\n"
4010 " -p --property=NAME Show only properties by this name\n"
4011 " -a --all Show all units/properties, including dead/empty ones\n"
4012 " --failed Show only failed units\n"
4013 " --full Don't ellipsize unit names on output\n"
4014 " --fail When queueing a new job, fail if conflicting jobs are\n"
4016 " --ignore-dependencies\n"
4017 " When queueing a new job, ignore all its dependencies\n"
4018 " -i --ignore-inhibitors\n"
4019 " When shutting down or sleeping, ignore inhibitors\n"
4020 " --kill-who=WHO Who to send signal to\n"
4021 " -s --signal=SIGNAL Which signal to send\n"
4022 " -H --host=[USER@]HOST\n"
4023 " Show information for remote host\n"
4024 " -P --privileged Acquire privileges before execution\n"
4025 " -q --quiet Suppress output\n"
4026 " --no-block Do not wait until operation finished\n"
4027 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4028 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
4030 " --no-legend Do not print a legend (column headers and hints)\n"
4031 " --no-pager Do not pipe output into a pager\n"
4032 " --no-ask-password\n"
4033 " Do not ask for system passwords\n"
4034 " --order When generating graph for dot, show only order\n"
4035 " --require When generating graph for dot, show only requirement\n"
4036 " --system Connect to system manager\n"
4037 " --user Connect to user service manager\n"
4038 " --global Enable/disable unit files globally\n"
4039 " -f --force When enabling unit files, override existing symlinks\n"
4040 " When shutting down, execute action immediately\n"
4041 " --root=PATH Enable unit files in the specified root directory\n"
4042 " --runtime Enable unit files only temporarily until next reboot\n"
4043 " -n --lines=INTEGER Journal entries to show\n"
4044 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
4045 " verbose, export, json, json-pretty, json-sse, cat)\n\n"
4047 " list-units List loaded units\n"
4048 " start [NAME...] Start (activate) one or more units\n"
4049 " stop [NAME...] Stop (deactivate) one or more units\n"
4050 " reload [NAME...] Reload one or more units\n"
4051 " restart [NAME...] Start or restart one or more units\n"
4052 " try-restart [NAME...] Restart one or more units if active\n"
4053 " reload-or-restart [NAME...] Reload one or more units if possible,\n"
4054 " otherwise start or restart\n"
4055 " reload-or-try-restart [NAME...] Reload one or more units if possible,\n"
4056 " otherwise restart if active\n"
4057 " isolate [NAME] Start one unit and stop all others\n"
4058 " kill [NAME...] Send signal to processes of a unit\n"
4059 " is-active [NAME...] Check whether units are active\n"
4060 " is-failed [NAME...] Check whether units are failed\n"
4061 " status [NAME...|PID...] Show runtime status of one or more units\n"
4062 " show [NAME...|JOB...] Show properties of one or more\n"
4063 " units/jobs or the manager\n"
4064 " help [NAME...|PID...] Show manual for one or more units\n"
4065 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
4067 " set-cgroup [NAME] [CGROUP...] Add unit to a control group\n"
4068 " unset-cgroup [NAME] [CGROUP...] Remove unit from a control group\n"
4069 " set-cgroup-attr [NAME] [ATTR] [VALUE] ...\n"
4070 " Set control group attribute\n"
4071 " unset-cgroup-attr [NAME] [ATTR...]\n"
4072 " Unset control group attribute\n"
4073 " load [NAME...] Load one or more units\n\n"
4074 "Unit File Commands:\n"
4075 " list-unit-files List installed unit files\n"
4076 " enable [NAME...] Enable one or more unit files\n"
4077 " disable [NAME...] Disable one or more unit files\n"
4078 " reenable [NAME...] Reenable one or more unit files\n"
4079 " preset [NAME...] Enable/disable one or more unit files\n"
4080 " based on preset configuration\n"
4081 " mask [NAME...] Mask one or more units\n"
4082 " unmask [NAME...] Unmask one or more units\n"
4083 " link [PATH...] Link one or more units files into\n"
4084 " the search path\n"
4085 " is-enabled [NAME...] Check whether unit files are enabled\n\n"
4087 " list-jobs List jobs\n"
4088 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
4089 "Status Commands:\n"
4090 " dump Dump server status\n"
4091 " dot Dump dependency graph for dot(1)\n\n"
4092 "Snapshot Commands:\n"
4093 " snapshot [NAME] Create a snapshot\n"
4094 " delete [NAME...] Remove one or more snapshots\n\n"
4095 "Environment Commands:\n"
4096 " show-environment Dump environment\n"
4097 " set-environment [NAME=VALUE...] Set one or more environment variables\n"
4098 " unset-environment [NAME...] Unset one or more environment variables\n\n"
4099 "Manager Lifecycle Commands:\n"
4100 " daemon-reload Reload systemd manager configuration\n"
4101 " daemon-reexec Reexecute systemd manager\n\n"
4102 "System Commands:\n"
4103 " default Enter system default mode\n"
4104 " rescue Enter system rescue mode\n"
4105 " emergency Enter system emergency mode\n"
4106 " halt Shut down and halt the system\n"
4107 " poweroff Shut down and power-off the system\n"
4108 " reboot Shut down and reboot the system\n"
4109 " kexec Shut down and reboot the system with kexec\n"
4110 " exit Request user instance exit\n"
4111 " switch-root [ROOT] [INIT] Change to a different root file system\n"
4112 " suspend Suspend the system\n"
4113 " hibernate Hibernate the system\n"
4114 " hybrid-sleep Hibernate and suspend the system\n",
4115 program_invocation_short_name);
4120 static int halt_help(void) {
4122 printf("%s [OPTIONS...]\n\n"
4123 "%s the system.\n\n"
4124 " --help Show this help\n"
4125 " --halt Halt the machine\n"
4126 " -p --poweroff Switch off the machine\n"
4127 " --reboot Reboot the machine\n"
4128 " -f --force Force immediate halt/power-off/reboot\n"
4129 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
4130 " -d --no-wtmp Don't write wtmp record\n"
4131 " --no-wall Don't send wall message before halt/power-off/reboot\n",
4132 program_invocation_short_name,
4133 arg_action == ACTION_REBOOT ? "Reboot" :
4134 arg_action == ACTION_POWEROFF ? "Power off" :
4140 static int shutdown_help(void) {
4142 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
4143 "Shut down the system.\n\n"
4144 " --help Show this help\n"
4145 " -H --halt Halt the machine\n"
4146 " -P --poweroff Power-off the machine\n"
4147 " -r --reboot Reboot the machine\n"
4148 " -h Equivalent to --poweroff, overridden by --halt\n"
4149 " -k Don't halt/power-off/reboot, just send warnings\n"
4150 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4151 " -c Cancel a pending shutdown\n",
4152 program_invocation_short_name);
4157 static int telinit_help(void) {
4159 printf("%s [OPTIONS...] {COMMAND}\n\n"
4160 "Send control commands to the init daemon.\n\n"
4161 " --help Show this help\n"
4162 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
4164 " 0 Power-off the machine\n"
4165 " 6 Reboot the machine\n"
4166 " 2, 3, 4, 5 Start runlevelX.target unit\n"
4167 " 1, s, S Enter rescue mode\n"
4168 " q, Q Reload init daemon configuration\n"
4169 " u, U Reexecute init daemon\n",
4170 program_invocation_short_name);
4175 static int runlevel_help(void) {
4177 printf("%s [OPTIONS...]\n\n"
4178 "Prints the previous and current runlevel of the init system.\n\n"
4179 " --help Show this help\n",
4180 program_invocation_short_name);
4185 static int help_types(void) {
4188 puts("Available unit types:");
4189 for(i = UNIT_SERVICE; i < _UNIT_TYPE_MAX; i++)
4190 if (unit_type_table[i])
4191 puts(unit_type_table[i]);
4193 puts("\nAvailable unit load states: ");
4194 for(i = UNIT_STUB; i < _UNIT_LOAD_STATE_MAX; i++)
4195 if (unit_type_table[i])
4196 puts(unit_load_state_table[i]);
4201 static int systemctl_parse_argv(int argc, char *argv[]) {
4205 ARG_IGNORE_DEPENDENCIES,
4220 ARG_NO_ASK_PASSWORD,
4226 static const struct option options[] = {
4227 { "help", no_argument, NULL, 'h' },
4228 { "version", no_argument, NULL, ARG_VERSION },
4229 { "type", required_argument, NULL, 't' },
4230 { "property", required_argument, NULL, 'p' },
4231 { "all", no_argument, NULL, 'a' },
4232 { "failed", no_argument, NULL, ARG_FAILED },
4233 { "full", no_argument, NULL, ARG_FULL },
4234 { "fail", no_argument, NULL, ARG_FAIL },
4235 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
4236 { "ignore-inhibitors", no_argument, NULL, 'i' },
4237 { "user", no_argument, NULL, ARG_USER },
4238 { "system", no_argument, NULL, ARG_SYSTEM },
4239 { "global", no_argument, NULL, ARG_GLOBAL },
4240 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
4241 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
4242 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
4243 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4244 { "quiet", no_argument, NULL, 'q' },
4245 { "order", no_argument, NULL, ARG_ORDER },
4246 { "require", no_argument, NULL, ARG_REQUIRE },
4247 { "root", required_argument, NULL, ARG_ROOT },
4248 { "force", no_argument, NULL, ARG_FORCE },
4249 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
4250 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
4251 { "signal", required_argument, NULL, 's' },
4252 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
4253 { "host", required_argument, NULL, 'H' },
4254 { "privileged",no_argument, NULL, 'P' },
4255 { "runtime", no_argument, NULL, ARG_RUNTIME },
4256 { "lines", required_argument, NULL, 'n' },
4257 { "output", required_argument, NULL, 'o' },
4258 { NULL, 0, NULL, 0 }
4266 while ((c = getopt_long(argc, argv, "ht:p:aqfs:H:Pn:o:i", options, NULL)) >= 0) {
4275 puts(PACKAGE_STRING);
4276 puts(SYSTEMD_FEATURES);
4280 if (streq(optarg, "help")) {
4285 if (unit_type_from_string(optarg) >= 0) {
4289 if (unit_load_state_from_string(optarg) >= 0) {
4290 arg_load_state = optarg;
4293 log_error("Unkown unit type or load state '%s'.",
4295 log_info("Use -t help to see a list of allowed values.");
4300 if (!(l = strv_append(arg_property, optarg)))
4303 strv_free(arg_property);
4306 /* If the user asked for a particular
4307 * property, show it to him, even if it is
4318 arg_job_mode = "fail";
4321 case ARG_IGNORE_DEPENDENCIES:
4322 arg_job_mode = "ignore-dependencies";
4326 arg_scope = UNIT_FILE_USER;
4330 arg_scope = UNIT_FILE_SYSTEM;
4334 arg_scope = UNIT_FILE_GLOBAL;
4338 arg_no_block = true;
4342 arg_no_legend = true;
4346 arg_no_pager = true;
4354 arg_dot = DOT_ORDER;
4358 arg_dot = DOT_REQUIRE;
4386 arg_no_reload = true;
4390 arg_kill_who = optarg;
4394 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
4395 log_error("Failed to parse signal string %s.", optarg);
4400 case ARG_NO_ASK_PASSWORD:
4401 arg_ask_password = false;
4405 arg_transport = TRANSPORT_POLKIT;
4409 arg_transport = TRANSPORT_SSH;
4418 if (safe_atou(optarg, &arg_lines) < 0) {
4419 log_error("Failed to parse lines '%s'", optarg);
4425 arg_output = output_mode_from_string(optarg);
4426 if (arg_output < 0) {
4427 log_error("Unknown output '%s'.", optarg);
4433 arg_ignore_inhibitors = true;
4440 log_error("Unknown option code '%c'.", c);
4445 if (arg_transport != TRANSPORT_NORMAL && arg_scope != UNIT_FILE_SYSTEM) {
4446 log_error("Cannot access user instance remotely.");
4453 static int halt_parse_argv(int argc, char *argv[]) {
4462 static const struct option options[] = {
4463 { "help", no_argument, NULL, ARG_HELP },
4464 { "halt", no_argument, NULL, ARG_HALT },
4465 { "poweroff", no_argument, NULL, 'p' },
4466 { "reboot", no_argument, NULL, ARG_REBOOT },
4467 { "force", no_argument, NULL, 'f' },
4468 { "wtmp-only", no_argument, NULL, 'w' },
4469 { "no-wtmp", no_argument, NULL, 'd' },
4470 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4471 { NULL, 0, NULL, 0 }
4479 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
4480 if (runlevel == '0' || runlevel == '6')
4483 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
4491 arg_action = ACTION_HALT;
4495 if (arg_action != ACTION_REBOOT)
4496 arg_action = ACTION_POWEROFF;
4500 arg_action = ACTION_REBOOT;
4522 /* Compatibility nops */
4529 log_error("Unknown option code '%c'.", c);
4534 if (optind < argc) {
4535 log_error("Too many arguments.");
4542 static int parse_time_spec(const char *t, usec_t *_u) {
4546 if (streq(t, "now"))
4548 else if (!strchr(t, ':')) {
4551 if (safe_atou64(t, &u) < 0)
4554 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
4563 hour = strtol(t, &e, 10);
4564 if (errno != 0 || *e != ':' || hour < 0 || hour > 23)
4567 minute = strtol(e+1, &e, 10);
4568 if (errno != 0 || *e != 0 || minute < 0 || minute > 59)
4571 n = now(CLOCK_REALTIME);
4572 s = (time_t) (n / USEC_PER_SEC);
4575 assert_se(localtime_r(&s, &tm));
4577 tm.tm_hour = (int) hour;
4578 tm.tm_min = (int) minute;
4581 assert_se(s = mktime(&tm));
4583 *_u = (usec_t) s * USEC_PER_SEC;
4586 *_u += USEC_PER_DAY;
4592 static int shutdown_parse_argv(int argc, char *argv[]) {
4599 static const struct option options[] = {
4600 { "help", no_argument, NULL, ARG_HELP },
4601 { "halt", no_argument, NULL, 'H' },
4602 { "poweroff", no_argument, NULL, 'P' },
4603 { "reboot", no_argument, NULL, 'r' },
4604 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
4605 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4606 { NULL, 0, NULL, 0 }
4614 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
4622 arg_action = ACTION_HALT;
4626 arg_action = ACTION_POWEROFF;
4631 arg_action = ACTION_KEXEC;
4633 arg_action = ACTION_REBOOT;
4637 arg_action = ACTION_KEXEC;
4641 if (arg_action != ACTION_HALT)
4642 arg_action = ACTION_POWEROFF;
4655 /* Compatibility nops */
4659 arg_action = ACTION_CANCEL_SHUTDOWN;
4666 log_error("Unknown option code '%c'.", c);
4671 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
4672 r = parse_time_spec(argv[optind], &arg_when);
4674 log_error("Failed to parse time specification: %s", argv[optind]);
4678 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
4680 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
4681 /* No time argument for shutdown cancel */
4682 arg_wall = argv + optind;
4683 else if (argc > optind + 1)
4684 /* We skip the time argument */
4685 arg_wall = argv + optind + 1;
4692 static int telinit_parse_argv(int argc, char *argv[]) {
4699 static const struct option options[] = {
4700 { "help", no_argument, NULL, ARG_HELP },
4701 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4702 { NULL, 0, NULL, 0 }
4705 static const struct {
4709 { '0', ACTION_POWEROFF },
4710 { '6', ACTION_REBOOT },
4711 { '1', ACTION_RESCUE },
4712 { '2', ACTION_RUNLEVEL2 },
4713 { '3', ACTION_RUNLEVEL3 },
4714 { '4', ACTION_RUNLEVEL4 },
4715 { '5', ACTION_RUNLEVEL5 },
4716 { 's', ACTION_RESCUE },
4717 { 'S', ACTION_RESCUE },
4718 { 'q', ACTION_RELOAD },
4719 { 'Q', ACTION_RELOAD },
4720 { 'u', ACTION_REEXEC },
4721 { 'U', ACTION_REEXEC }
4730 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4745 log_error("Unknown option code '%c'.", c);
4750 if (optind >= argc) {
4755 if (optind + 1 < argc) {
4756 log_error("Too many arguments.");
4760 if (strlen(argv[optind]) != 1) {
4761 log_error("Expected single character argument.");
4765 for (i = 0; i < ELEMENTSOF(table); i++)
4766 if (table[i].from == argv[optind][0])
4769 if (i >= ELEMENTSOF(table)) {
4770 log_error("Unknown command '%s'.", argv[optind]);
4774 arg_action = table[i].to;
4781 static int runlevel_parse_argv(int argc, char *argv[]) {
4787 static const struct option options[] = {
4788 { "help", no_argument, NULL, ARG_HELP },
4789 { NULL, 0, NULL, 0 }
4797 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4808 log_error("Unknown option code '%c'.", c);
4813 if (optind < argc) {
4814 log_error("Too many arguments.");
4821 static int parse_argv(int argc, char *argv[]) {
4825 if (program_invocation_short_name) {
4827 if (strstr(program_invocation_short_name, "halt")) {
4828 arg_action = ACTION_HALT;
4829 return halt_parse_argv(argc, argv);
4830 } else if (strstr(program_invocation_short_name, "poweroff")) {
4831 arg_action = ACTION_POWEROFF;
4832 return halt_parse_argv(argc, argv);
4833 } else if (strstr(program_invocation_short_name, "reboot")) {
4835 arg_action = ACTION_KEXEC;
4837 arg_action = ACTION_REBOOT;
4838 return halt_parse_argv(argc, argv);
4839 } else if (strstr(program_invocation_short_name, "shutdown")) {
4840 arg_action = ACTION_POWEROFF;
4841 return shutdown_parse_argv(argc, argv);
4842 } else if (strstr(program_invocation_short_name, "init")) {
4844 if (sd_booted() > 0) {
4845 arg_action = ACTION_INVALID;
4846 return telinit_parse_argv(argc, argv);
4848 /* Hmm, so some other init system is
4849 * running, we need to forward this
4850 * request to it. For now we simply
4851 * guess that it is Upstart. */
4853 execv("/lib/upstart/telinit", argv);
4855 log_error("Couldn't find an alternative telinit implementation to spawn.");
4859 } else if (strstr(program_invocation_short_name, "runlevel")) {
4860 arg_action = ACTION_RUNLEVEL;
4861 return runlevel_parse_argv(argc, argv);
4865 arg_action = ACTION_SYSTEMCTL;
4866 return systemctl_parse_argv(argc, argv);
4869 static int action_to_runlevel(void) {
4871 static const char table[_ACTION_MAX] = {
4872 [ACTION_HALT] = '0',
4873 [ACTION_POWEROFF] = '0',
4874 [ACTION_REBOOT] = '6',
4875 [ACTION_RUNLEVEL2] = '2',
4876 [ACTION_RUNLEVEL3] = '3',
4877 [ACTION_RUNLEVEL4] = '4',
4878 [ACTION_RUNLEVEL5] = '5',
4879 [ACTION_RESCUE] = '1'
4882 assert(arg_action < _ACTION_MAX);
4884 return table[arg_action];
4887 static int talk_upstart(void) {
4888 DBusMessage *m = NULL, *reply = NULL;
4890 int previous, rl, r;
4892 env1_buf[] = "RUNLEVEL=X",
4893 env2_buf[] = "PREVLEVEL=X";
4894 char *env1 = env1_buf, *env2 = env2_buf;
4895 const char *emit = "runlevel";
4896 dbus_bool_t b_false = FALSE;
4897 DBusMessageIter iter, sub;
4898 DBusConnection *bus;
4900 dbus_error_init(&error);
4902 if (!(rl = action_to_runlevel()))
4905 if (utmp_get_runlevel(&previous, NULL) < 0)
4908 if (!(bus = dbus_connection_open_private("unix:abstract=/com/ubuntu/upstart", &error))) {
4909 if (dbus_error_has_name(&error, DBUS_ERROR_NO_SERVER)) {
4914 log_error("Failed to connect to Upstart bus: %s", bus_error_message(&error));
4919 if ((r = bus_check_peercred(bus)) < 0) {
4920 log_error("Failed to verify owner of bus.");
4924 if (!(m = dbus_message_new_method_call(
4925 "com.ubuntu.Upstart",
4926 "/com/ubuntu/Upstart",
4927 "com.ubuntu.Upstart0_6",
4930 log_error("Could not allocate message.");
4935 dbus_message_iter_init_append(m, &iter);
4937 env1_buf[sizeof(env1_buf)-2] = rl;
4938 env2_buf[sizeof(env2_buf)-2] = previous;
4940 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &emit) ||
4941 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub) ||
4942 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env1) ||
4943 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env2) ||
4944 !dbus_message_iter_close_container(&iter, &sub) ||
4945 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b_false)) {
4946 log_error("Could not append arguments to message.");
4951 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
4953 if (bus_error_is_no_service(&error)) {
4958 log_error("Failed to issue method call: %s", bus_error_message(&error));
4967 dbus_message_unref(m);
4970 dbus_message_unref(reply);
4973 dbus_connection_flush(bus);
4974 dbus_connection_close(bus);
4975 dbus_connection_unref(bus);
4978 dbus_error_free(&error);
4983 static int talk_initctl(void) {
4984 struct init_request request;
4988 if (!(rl = action_to_runlevel()))
4992 request.magic = INIT_MAGIC;
4993 request.sleeptime = 0;
4994 request.cmd = INIT_CMD_RUNLVL;
4995 request.runlevel = rl;
4997 if ((fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY)) < 0) {
4999 if (errno == ENOENT)
5002 log_error("Failed to open "INIT_FIFO": %m");
5007 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
5008 close_nointr_nofail(fd);
5011 log_error("Failed to write to "INIT_FIFO": %m");
5012 return errno ? -errno : -EIO;
5018 static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
5020 static const struct {
5028 int (* const dispatch)(DBusConnection *bus, char **args);
5030 { "list-units", LESS, 1, list_units },
5031 { "list-unit-files", EQUAL, 1, list_unit_files },
5032 { "list-jobs", EQUAL, 1, list_jobs },
5033 { "clear-jobs", EQUAL, 1, daemon_reload },
5034 { "load", MORE, 2, load_unit },
5035 { "cancel", MORE, 2, cancel_job },
5036 { "start", MORE, 2, start_unit },
5037 { "stop", MORE, 2, start_unit },
5038 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5039 { "reload", MORE, 2, start_unit },
5040 { "restart", MORE, 2, start_unit },
5041 { "try-restart", MORE, 2, start_unit },
5042 { "reload-or-restart", MORE, 2, start_unit },
5043 { "reload-or-try-restart", MORE, 2, start_unit },
5044 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
5045 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5046 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
5047 { "isolate", EQUAL, 2, start_unit },
5048 { "set-cgroup", MORE, 2, set_cgroup },
5049 { "unset-cgroup", MORE, 2, set_cgroup },
5050 { "set-cgroup-attr", MORE, 2, set_cgroup_attr },
5051 { "unset-cgroup-attr", MORE, 2, set_cgroup },
5052 { "kill", MORE, 2, kill_unit },
5053 { "is-active", MORE, 2, check_unit_active },
5054 { "check", MORE, 2, check_unit_active },
5055 { "is-failed", MORE, 2, check_unit_failed },
5056 { "show", MORE, 1, show },
5057 { "status", MORE, 2, show },
5058 { "help", MORE, 2, show },
5059 { "dump", EQUAL, 1, dump },
5060 { "dot", EQUAL, 1, dot },
5061 { "snapshot", LESS, 2, snapshot },
5062 { "delete", MORE, 2, delete_snapshot },
5063 { "daemon-reload", EQUAL, 1, daemon_reload },
5064 { "daemon-reexec", EQUAL, 1, daemon_reload },
5065 { "show-environment", EQUAL, 1, show_enviroment },
5066 { "set-environment", MORE, 2, set_environment },
5067 { "unset-environment", MORE, 2, set_environment },
5068 { "halt", EQUAL, 1, start_special },
5069 { "poweroff", EQUAL, 1, start_special },
5070 { "reboot", EQUAL, 1, start_special },
5071 { "kexec", EQUAL, 1, start_special },
5072 { "suspend", EQUAL, 1, start_special },
5073 { "hibernate", EQUAL, 1, start_special },
5074 { "hybrid-sleep", EQUAL, 1, start_special },
5075 { "default", EQUAL, 1, start_special },
5076 { "rescue", EQUAL, 1, start_special },
5077 { "emergency", EQUAL, 1, start_special },
5078 { "exit", EQUAL, 1, start_special },
5079 { "reset-failed", MORE, 1, reset_failed },
5080 { "enable", MORE, 2, enable_unit },
5081 { "disable", MORE, 2, enable_unit },
5082 { "is-enabled", MORE, 2, unit_is_enabled },
5083 { "reenable", MORE, 2, enable_unit },
5084 { "preset", MORE, 2, enable_unit },
5085 { "mask", MORE, 2, enable_unit },
5086 { "unmask", MORE, 2, enable_unit },
5087 { "link", MORE, 2, enable_unit },
5088 { "switch-root", MORE, 2, switch_root },
5098 left = argc - optind;
5101 /* Special rule: no arguments means "list-units" */
5104 if (streq(argv[optind], "help") && !argv[optind+1]) {
5105 log_error("This command expects one or more "
5106 "unit names. Did you mean --help?");
5110 for (i = 0; i < ELEMENTSOF(verbs); i++)
5111 if (streq(argv[optind], verbs[i].verb))
5114 if (i >= ELEMENTSOF(verbs)) {
5115 log_error("Unknown operation '%s'.", argv[optind]);
5120 switch (verbs[i].argc_cmp) {
5123 if (left != verbs[i].argc) {
5124 log_error("Invalid number of arguments.");
5131 if (left < verbs[i].argc) {
5132 log_error("Too few arguments.");
5139 if (left > verbs[i].argc) {
5140 log_error("Too many arguments.");
5147 assert_not_reached("Unknown comparison operator.");
5150 /* Require a bus connection for all operations but
5152 if (!streq(verbs[i].verb, "enable") &&
5153 !streq(verbs[i].verb, "disable") &&
5154 !streq(verbs[i].verb, "is-enabled") &&
5155 !streq(verbs[i].verb, "list-unit-files") &&
5156 !streq(verbs[i].verb, "reenable") &&
5157 !streq(verbs[i].verb, "preset") &&
5158 !streq(verbs[i].verb, "mask") &&
5159 !streq(verbs[i].verb, "unmask") &&
5160 !streq(verbs[i].verb, "link")) {
5162 if (running_in_chroot() > 0) {
5163 log_info("Running in chroot, ignoring request.");
5167 if (((!streq(verbs[i].verb, "reboot") &&
5168 !streq(verbs[i].verb, "halt") &&
5169 !streq(verbs[i].verb, "poweroff")) || arg_force <= 0) && !bus) {
5170 log_error("Failed to get D-Bus connection: %s",
5171 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5177 if (!bus && !avoid_bus()) {
5178 log_error("Failed to get D-Bus connection: %s",
5179 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5184 return verbs[i].dispatch(bus, argv + optind);
5187 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
5189 struct msghdr msghdr;
5190 struct iovec iovec[2];
5191 union sockaddr_union sockaddr;
5192 struct sd_shutdown_command c;
5194 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
5201 c.dry_run = dry_run;
5205 sockaddr.sa.sa_family = AF_UNIX;
5206 strncpy(sockaddr.un.sun_path, "/run/systemd/shutdownd", sizeof(sockaddr.un.sun_path));
5209 msghdr.msg_name = &sockaddr;
5210 msghdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + sizeof("/run/systemd/shutdownd") - 1;
5213 iovec[0].iov_base = (char*) &c;
5214 iovec[0].iov_len = offsetof(struct sd_shutdown_command, wall_message);
5216 if (isempty(message))
5217 msghdr.msg_iovlen = 1;
5219 iovec[1].iov_base = (char*) message;
5220 iovec[1].iov_len = strlen(message);
5221 msghdr.msg_iovlen = 2;
5223 msghdr.msg_iov = iovec;
5225 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0) {
5226 close_nointr_nofail(fd);
5230 close_nointr_nofail(fd);
5234 static int reload_with_fallback(DBusConnection *bus) {
5237 /* First, try systemd via D-Bus. */
5238 if (daemon_reload(bus, NULL) >= 0)
5242 /* Nothing else worked, so let's try signals */
5243 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
5245 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
5246 log_error("kill() failed: %m");
5253 static int start_with_fallback(DBusConnection *bus) {
5256 /* First, try systemd via D-Bus. */
5257 if (start_unit(bus, NULL) >= 0)
5261 /* Hmm, talking to systemd via D-Bus didn't work. Then
5262 * let's try to talk to Upstart via D-Bus. */
5263 if (talk_upstart() > 0)
5266 /* Nothing else worked, so let's try
5268 if (talk_initctl() > 0)
5271 log_error("Failed to talk to init daemon.");
5275 warn_wall(arg_action);
5279 static _noreturn_ void halt_now(enum action a) {
5281 /* Make sure C-A-D is handled by the kernel from this
5283 reboot(RB_ENABLE_CAD);
5288 log_info("Halting.");
5289 reboot(RB_HALT_SYSTEM);
5292 case ACTION_POWEROFF:
5293 log_info("Powering off.");
5294 reboot(RB_POWER_OFF);
5298 log_info("Rebooting.");
5299 reboot(RB_AUTOBOOT);
5303 assert_not_reached("Unknown halt action.");
5306 assert_not_reached("Uh? This shouldn't happen.");
5309 static int halt_main(DBusConnection *bus) {
5312 r = check_inhibitors(bus, arg_action);
5316 if (geteuid() != 0) {
5317 /* Try logind if we are a normal user and no special
5318 * mode applies. Maybe PolicyKit allows us to shutdown
5321 if (arg_when <= 0 &&
5324 (arg_action == ACTION_POWEROFF ||
5325 arg_action == ACTION_REBOOT)) {
5326 r = reboot_with_logind(bus, arg_action);
5331 log_error("Must be root.");
5338 m = strv_join(arg_wall, " ");
5339 r = send_shutdownd(arg_when,
5340 arg_action == ACTION_HALT ? 'H' :
5341 arg_action == ACTION_POWEROFF ? 'P' :
5342 arg_action == ACTION_KEXEC ? 'K' :
5350 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
5352 char date[FORMAT_TIMESTAMP_MAX];
5354 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
5355 format_timestamp(date, sizeof(date), arg_when));
5360 if (!arg_dry && !arg_force)
5361 return start_with_fallback(bus);
5364 if (sd_booted() > 0)
5365 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
5367 r = utmp_put_shutdown();
5369 log_warning("Failed to write utmp record: %s", strerror(-r));
5376 halt_now(arg_action);
5377 /* We should never reach this. */
5381 static int runlevel_main(void) {
5382 int r, runlevel, previous;
5384 r = utmp_get_runlevel(&runlevel, &previous);
5391 previous <= 0 ? 'N' : previous,
5392 runlevel <= 0 ? 'N' : runlevel);
5397 int main(int argc, char*argv[]) {
5398 int r, retval = EXIT_FAILURE;
5399 DBusConnection *bus = NULL;
5402 dbus_error_init(&error);
5404 setlocale(LC_ALL, "");
5405 log_parse_environment();
5408 r = parse_argv(argc, argv);
5412 retval = EXIT_SUCCESS;
5416 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
5417 * let's shortcut this */
5418 if (arg_action == ACTION_RUNLEVEL) {
5419 r = runlevel_main();
5420 retval = r < 0 ? EXIT_FAILURE : r;
5424 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
5425 log_info("Running in chroot, ignoring request.");
5431 if (arg_transport == TRANSPORT_NORMAL)
5432 bus_connect(arg_scope == UNIT_FILE_SYSTEM ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &bus, &private_bus, &error);
5433 else if (arg_transport == TRANSPORT_POLKIT) {
5434 bus_connect_system_polkit(&bus, &error);
5435 private_bus = false;
5436 } else if (arg_transport == TRANSPORT_SSH) {
5437 bus_connect_system_ssh(NULL, arg_host, &bus, &error);
5438 private_bus = false;
5440 assert_not_reached("Uh, invalid transport...");
5443 switch (arg_action) {
5445 case ACTION_SYSTEMCTL:
5446 r = systemctl_main(bus, argc, argv, &error);
5450 case ACTION_POWEROFF:
5456 case ACTION_RUNLEVEL2:
5457 case ACTION_RUNLEVEL3:
5458 case ACTION_RUNLEVEL4:
5459 case ACTION_RUNLEVEL5:
5461 case ACTION_EMERGENCY:
5462 case ACTION_DEFAULT:
5463 r = start_with_fallback(bus);
5468 r = reload_with_fallback(bus);
5471 case ACTION_CANCEL_SHUTDOWN: {
5475 m = strv_join(arg_wall, " ");
5477 retval = EXIT_FAILURE;
5481 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
5483 log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r));
5488 case ACTION_INVALID:
5489 case ACTION_RUNLEVEL:
5491 assert_not_reached("Unknown action");
5494 retval = r < 0 ? EXIT_FAILURE : r;
5498 dbus_connection_flush(bus);
5499 dbus_connection_close(bus);
5500 dbus_connection_unref(bus);
5503 dbus_error_free(&error);
5507 strv_free(arg_property);
5510 ask_password_agent_close();
5511 polkit_agent_close();