1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
22 #include <sys/reboot.h>
29 #include <sys/ioctl.h>
33 #include <sys/socket.h>
36 #include <sys/prctl.h>
37 #include <dbus/dbus.h>
39 #include <systemd/sd-daemon.h>
40 #include <systemd/sd-shutdown.h>
41 #include <systemd/sd-login.h>
47 #include "utmp-wtmp.h"
50 #include "path-util.h"
52 #include "dbus-common.h"
53 #include "cgroup-show.h"
54 #include "cgroup-util.h"
56 #include "path-lookup.h"
57 #include "conf-parser.h"
58 #include "exit-status.h"
59 #include "bus-errors.h"
61 #include "unit-name.h"
63 #include "spawn-ask-password-agent.h"
64 #include "spawn-polkit-agent.h"
66 #include "logs-show.h"
67 #include "path-util.h"
68 #include "socket-util.h"
71 static const char *arg_type = NULL;
72 static const char *arg_load_state = NULL;
73 static char **arg_property = NULL;
74 static bool arg_all = false;
75 static const char *arg_job_mode = "replace";
76 static UnitFileScope arg_scope = UNIT_FILE_SYSTEM;
77 static bool arg_no_block = false;
78 static bool arg_no_legend = false;
79 static bool arg_no_pager = false;
80 static bool arg_no_wtmp = false;
81 static bool arg_no_wall = false;
82 static bool arg_no_reload = false;
83 static bool arg_ignore_inhibitors = false;
84 static bool arg_dry = false;
85 static bool arg_quiet = false;
86 static bool arg_full = false;
87 static int arg_force = 0;
88 static bool arg_ask_password = true;
89 static bool arg_failed = false;
90 static bool arg_runtime = false;
91 static char **arg_wall = NULL;
92 static const char *arg_kill_who = NULL;
93 static int arg_signal = SIGTERM;
94 static const char *arg_root = NULL;
95 static usec_t arg_when = 0;
117 ACTION_CANCEL_SHUTDOWN,
119 } arg_action = ACTION_SYSTEMCTL;
120 static enum transport {
124 } arg_transport = TRANSPORT_NORMAL;
125 static const char *arg_host = NULL;
126 static unsigned arg_lines = 10;
127 static OutputMode arg_output = OUTPUT_SHORT;
129 static bool private_bus = false;
131 static int daemon_reload(DBusConnection *bus, char **args);
132 static void halt_now(enum action a);
134 static void pager_open_if_enabled(void) {
142 static void ask_password_agent_open_if_enabled(void) {
144 /* Open the password agent as a child process if necessary */
146 if (!arg_ask_password)
149 if (arg_scope != UNIT_FILE_SYSTEM)
152 ask_password_agent_open();
156 static void polkit_agent_open_if_enabled(void) {
158 /* Open the polkit agent as a child process if necessary */
160 if (!arg_ask_password)
163 if (arg_scope != UNIT_FILE_SYSTEM)
170 static const char *ansi_highlight(bool b) {
175 return b ? ANSI_HIGHLIGHT_ON : ANSI_HIGHLIGHT_OFF;
178 static const char *ansi_highlight_red(bool b) {
183 return b ? ANSI_HIGHLIGHT_RED_ON : ANSI_HIGHLIGHT_OFF;
186 static const char *ansi_highlight_green(bool b) {
191 return b ? ANSI_HIGHLIGHT_GREEN_ON : ANSI_HIGHLIGHT_OFF;
194 static int translate_bus_error_to_exit_status(int r, const DBusError *error) {
197 if (!dbus_error_is_set(error))
200 if (dbus_error_has_name(error, DBUS_ERROR_ACCESS_DENIED) ||
201 dbus_error_has_name(error, BUS_ERROR_ONLY_BY_DEPENDENCY) ||
202 dbus_error_has_name(error, BUS_ERROR_NO_ISOLATION) ||
203 dbus_error_has_name(error, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE))
204 return EXIT_NOPERMISSION;
206 if (dbus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT))
207 return EXIT_NOTINSTALLED;
209 if (dbus_error_has_name(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE) ||
210 dbus_error_has_name(error, BUS_ERROR_NOT_SUPPORTED))
211 return EXIT_NOTIMPLEMENTED;
213 if (dbus_error_has_name(error, BUS_ERROR_LOAD_FAILED))
214 return EXIT_NOTCONFIGURED;
222 static void warn_wall(enum action a) {
223 static const char *table[_ACTION_MAX] = {
224 [ACTION_HALT] = "The system is going down for system halt NOW!",
225 [ACTION_REBOOT] = "The system is going down for reboot NOW!",
226 [ACTION_POWEROFF] = "The system is going down for power-off NOW!",
227 [ACTION_KEXEC] = "The system is going down for kexec reboot NOW!",
228 [ACTION_RESCUE] = "The system is going down to rescue mode NOW!",
229 [ACTION_EMERGENCY] = "The system is going down to emergency mode NOW!",
230 [ACTION_CANCEL_SHUTDOWN] = "The system shutdown has been cancelled NOW!"
237 _cleanup_free_ char *p;
239 p = strv_join(arg_wall, " ");
254 utmp_wall(table[a], NULL);
257 static bool avoid_bus(void) {
259 if (running_in_chroot() > 0)
262 if (sd_booted() <= 0)
265 if (!isempty(arg_root))
268 if (arg_scope == UNIT_FILE_GLOBAL)
274 static int compare_unit_info(const void *a, const void *b) {
276 const struct unit_info *u = a, *v = b;
278 d1 = strrchr(u->id, '.');
279 d2 = strrchr(v->id, '.');
284 r = strcasecmp(d1, d2);
289 return strcasecmp(u->id, v->id);
292 static bool output_show_unit(const struct unit_info *u) {
296 return streq(u->active_state, "failed");
298 return (!arg_type || ((dot = strrchr(u->id, '.')) &&
299 streq(dot+1, arg_type))) &&
300 (!arg_load_state || streq(u->load_state, arg_load_state)) &&
301 (arg_all || !(streq(u->active_state, "inactive")
302 || u->following[0]) || u->job_id > 0);
305 static void output_units_list(const struct unit_info *unit_infos, unsigned c) {
306 unsigned id_len, max_id_len, active_len, sub_len, job_len, desc_len, n_shown = 0;
307 const struct unit_info *u;
310 max_id_len = sizeof("UNIT")-1;
311 active_len = sizeof("ACTIVE")-1;
312 sub_len = sizeof("SUB")-1;
313 job_len = sizeof("JOB")-1;
316 for (u = unit_infos; u < unit_infos + c; u++) {
317 if (!output_show_unit(u))
320 max_id_len = MAX(max_id_len, strlen(u->id));
321 active_len = MAX(active_len, strlen(u->active_state));
322 sub_len = MAX(sub_len, strlen(u->sub_state));
323 if (u->job_id != 0) {
324 job_len = MAX(job_len, strlen(u->job_type));
331 id_len = MIN(max_id_len, 25);
332 basic_len = 5 + id_len + 5 + active_len + sub_len;
334 basic_len += job_len + 1;
335 if (basic_len < (unsigned) columns()) {
336 unsigned extra_len, incr;
337 extra_len = columns() - basic_len;
338 /* Either UNIT already got 25, or is fully satisfied.
339 * Grant up to 25 to DESC now. */
340 incr = MIN(extra_len, 25);
343 /* split the remaining space between UNIT and DESC,
344 * but do not give UNIT more than it needs. */
346 incr = MIN(extra_len / 2, max_id_len - id_len);
348 desc_len += extra_len - incr;
354 for (u = unit_infos; u < unit_infos + c; u++) {
355 char _cleanup_free_ *e = NULL;
356 const char *on_loaded, *off_loaded;
357 const char *on_active, *off_active;
359 if (!output_show_unit(u))
362 if (!n_shown && !arg_no_legend) {
363 printf("%-*s %-6s %-*s %-*s ", id_len, "UNIT", "LOAD",
364 active_len, "ACTIVE", sub_len, "SUB");
366 printf("%-*s ", job_len, "JOB");
367 if (!arg_full && arg_no_pager)
368 printf("%.*s\n", desc_len, "DESCRIPTION");
370 printf("%s\n", "DESCRIPTION");
375 if (streq(u->load_state, "error")) {
376 on_loaded = ansi_highlight_red(true);
377 off_loaded = ansi_highlight_red(false);
379 on_loaded = off_loaded = "";
381 if (streq(u->active_state, "failed")) {
382 on_active = ansi_highlight_red(true);
383 off_active = ansi_highlight_red(false);
385 on_active = off_active = "";
387 e = arg_full ? NULL : ellipsize(u->id, id_len, 33);
389 printf("%-*s %s%-6s%s %s%-*s %-*s%s %-*s",
390 id_len, e ? e : u->id,
391 on_loaded, u->load_state, off_loaded,
392 on_active, active_len, u->active_state,
393 sub_len, u->sub_state, off_active,
394 job_count ? job_len + 1 : 0, u->job_id ? u->job_type : "");
395 if (!arg_full && arg_no_pager)
396 printf("%.*s\n", desc_len, u->description);
398 printf("%s\n", u->description);
401 if (!arg_no_legend) {
402 const char *on, *off;
405 printf("\nLOAD = Reflects whether the unit definition was properly loaded.\n"
406 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
407 "SUB = The low-level unit activation state, values depend on unit type.\n");
409 printf("JOB = Pending job for the unit.\n");
411 on = ansi_highlight(true);
412 off = ansi_highlight(false);
414 on = ansi_highlight_red(true);
415 off = ansi_highlight_red(false);
419 printf("%s%u loaded units listed.%s\n"
420 "To show all installed unit files use 'systemctl list-unit-files'.\n",
423 printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
424 "To show all installed unit files use 'systemctl list-unit-files'.\n",
429 static int get_unit_list(DBusConnection *bus, DBusMessage **reply,
430 struct unit_info **unit_infos, unsigned *c) {
431 DBusMessageIter iter, sub;
432 unsigned n_units = 0;
439 r = bus_method_call_with_reply(
441 "org.freedesktop.systemd1",
442 "/org/freedesktop/systemd1",
443 "org.freedesktop.systemd1.Manager",
451 if (!dbus_message_iter_init(*reply, &iter) ||
452 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
453 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
454 log_error("Failed to parse reply.");
458 dbus_message_iter_recurse(&iter, &sub);
460 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
466 n_units = MAX(2 * *c, 16);
467 w = realloc(*unit_infos, sizeof(struct unit_info) * n_units);
474 u = *unit_infos + *c;
476 bus_parse_unit_info(&sub, u);
478 dbus_message_iter_next(&sub);
483 qsort(*unit_infos, *c, sizeof(struct unit_info), compare_unit_info);
488 static int list_units(DBusConnection *bus, char **args) {
489 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
490 _cleanup_free_ struct unit_info *unit_infos = NULL;
494 pager_open_if_enabled();
496 r = get_unit_list(bus, &reply, &unit_infos, &c);
501 output_units_list(unit_infos, c);
506 static int compare_unit_file_list(const void *a, const void *b) {
508 const UnitFileList *u = a, *v = b;
510 d1 = strrchr(u->path, '.');
511 d2 = strrchr(v->path, '.');
516 r = strcasecmp(d1, d2);
521 return strcasecmp(path_get_file_name(u->path), path_get_file_name(v->path));
524 static bool output_show_unit_file(const UnitFileList *u) {
527 return !arg_type || ((dot = strrchr(u->path, '.')) && streq(dot+1, arg_type));
530 static void output_unit_file_list(const UnitFileList *units, unsigned c) {
531 unsigned max_id_len, id_cols, state_cols, n_shown = 0;
532 const UnitFileList *u;
534 max_id_len = sizeof("UNIT FILE")-1;
535 state_cols = sizeof("STATE")-1;
536 for (u = units; u < units + c; u++) {
537 if (!output_show_unit_file(u))
540 max_id_len = MAX(max_id_len, strlen(path_get_file_name(u->path)));
541 state_cols = MAX(state_cols, strlen(unit_file_state_to_string(u->state)));
546 id_cols = MIN(max_id_len, 25);
547 basic_cols = 1 + id_cols + state_cols;
548 if (basic_cols < (unsigned) columns())
549 id_cols += MIN(columns() - basic_cols, max_id_len - id_cols);
551 id_cols = max_id_len;
554 printf("%-*s %-*s\n", id_cols, "UNIT FILE", state_cols, "STATE");
556 for (u = units; u < units + c; u++) {
557 char _cleanup_free_ *e = NULL;
558 const char *on, *off;
561 if (!output_show_unit_file(u))
566 if (u->state == UNIT_FILE_MASKED ||
567 u->state == UNIT_FILE_MASKED_RUNTIME ||
568 u->state == UNIT_FILE_DISABLED ||
569 u->state == UNIT_FILE_INVALID) {
570 on = ansi_highlight_red(true);
571 off = ansi_highlight_red(false);
572 } else if (u->state == UNIT_FILE_ENABLED) {
573 on = ansi_highlight_green(true);
574 off = ansi_highlight_green(false);
578 id = path_get_file_name(u->path);
580 e = arg_full ? NULL : ellipsize(id, id_cols, 33);
582 printf("%-*s %s%-*s%s\n",
584 on, state_cols, unit_file_state_to_string(u->state), off);
588 printf("\n%u unit files listed.\n", n_shown);
591 static int list_unit_files(DBusConnection *bus, char **args) {
592 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
593 _cleanup_free_ UnitFileList *units = NULL;
594 DBusMessageIter iter, sub, sub2;
595 unsigned c = 0, n_units = 0;
598 pager_open_if_enabled();
605 h = hashmap_new(string_hash_func, string_compare_func);
609 r = unit_file_get_list(arg_scope, arg_root, h);
611 unit_file_list_free(h);
612 log_error("Failed to get unit file list: %s", strerror(-r));
616 n_units = hashmap_size(h);
617 units = new(UnitFileList, n_units);
619 unit_file_list_free(h);
623 HASHMAP_FOREACH(u, h, i) {
624 memcpy(units + c++, u, sizeof(UnitFileList));
630 r = bus_method_call_with_reply(
632 "org.freedesktop.systemd1",
633 "/org/freedesktop/systemd1",
634 "org.freedesktop.systemd1.Manager",
642 if (!dbus_message_iter_init(reply, &iter) ||
643 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
644 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
645 log_error("Failed to parse reply.");
649 dbus_message_iter_recurse(&iter, &sub);
651 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
655 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT);
660 n_units = MAX(2*c, 16);
661 w = realloc(units, sizeof(struct UnitFileList) * n_units);
670 dbus_message_iter_recurse(&sub, &sub2);
672 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->path, true) < 0 ||
673 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, false) < 0) {
674 log_error("Failed to parse reply.");
678 u->state = unit_file_state_from_string(state);
680 dbus_message_iter_next(&sub);
686 qsort(units, c, sizeof(UnitFileList), compare_unit_file_list);
687 output_unit_file_list(units, c);
693 static int list_dependencies_print(const char *name, int level, unsigned int branches, bool last) {
695 _cleanup_free_ char *n = NULL;
697 size_t max_len = MAX(columns(),20);
699 for (i = level - 1; i >= 0; i--) {
701 if(len > max_len - 3 && !arg_full) {
702 printf("%s...\n",max_len % 2 ? "" : " ");
705 printf("%s", draw_special_char(branches & (1 << i) ? DRAW_TREE_VERT : DRAW_TREE_SPACE));
708 if(len > max_len - 3 && !arg_full) {
709 printf("%s...\n",max_len % 2 ? "" : " ");
712 printf("%s", draw_special_char(last ? DRAW_TREE_RIGHT : DRAW_TREE_BRANCH));
715 printf("%s\n", name);
719 n = ellipsize(name, max_len-len, 100);
727 static int list_dependencies_get_dependencies(DBusConnection *bus, const char *name, char ***deps) {
728 static const char dependencies[] =
730 "RequiresOverridable\0"
732 "RequisiteOverridable\0"
735 _cleanup_free_ char *path;
736 const char *interface = "org.freedesktop.systemd1.Unit";
738 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
739 DBusMessageIter iter, sub, sub2, sub3;
748 path = unit_dbus_path_from_name(name);
754 r = bus_method_call_with_reply(
756 "org.freedesktop.systemd1",
758 "org.freedesktop.DBus.Properties",
762 DBUS_TYPE_STRING, &interface,
767 if (!dbus_message_iter_init(reply, &iter) ||
768 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
769 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
770 log_error("Failed to parse reply.");
775 dbus_message_iter_recurse(&iter, &sub);
777 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
780 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_DICT_ENTRY);
781 dbus_message_iter_recurse(&sub, &sub2);
783 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &prop, true) < 0) {
784 log_error("Failed to parse reply.");
789 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
790 log_error("Failed to parse reply.");
795 dbus_message_iter_recurse(&sub2, &sub3);
796 dbus_message_iter_next(&sub);
798 if (!nulstr_contains(dependencies, prop))
801 if (dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_ARRAY) {
802 if (dbus_message_iter_get_element_type(&sub3) == DBUS_TYPE_STRING) {
803 DBusMessageIter sub4;
804 dbus_message_iter_recurse(&sub3, &sub4);
806 while (dbus_message_iter_get_arg_type(&sub4) != DBUS_TYPE_INVALID) {
809 assert(dbus_message_iter_get_arg_type(&sub4) == DBUS_TYPE_STRING);
810 dbus_message_iter_get_basic(&sub4, &s);
812 r = strv_extend(&ret, s);
818 dbus_message_iter_next(&sub4);
831 static int list_dependencies_compare(const void *_a, const void *_b) {
832 const char **a = (const char**) _a, **b = (const char**) _b;
833 if (unit_name_to_type(*a) == UNIT_TARGET && unit_name_to_type(*b) != UNIT_TARGET)
835 if (unit_name_to_type(*a) != UNIT_TARGET && unit_name_to_type(*b) == UNIT_TARGET)
837 return strcasecmp(*a, *b);
840 static int list_dependencies_one(DBusConnection *bus, const char *name, int level, char **units, unsigned int branches) {
841 char _cleanup_strv_free_ **deps = NULL, **u;
845 u = strv_append(units, name);
849 r = list_dependencies_get_dependencies(bus, name, &deps);
853 qsort(deps, strv_length(deps), sizeof (char*), list_dependencies_compare);
855 STRV_FOREACH(c, deps) {
856 if (strv_contains(u, *c)) {
857 r = list_dependencies_print("...", level + 1, (branches << 1) | (c[1] == NULL ? 0 : 1), 1);
863 r = list_dependencies_print(*c, level, branches, c[1] == NULL);
867 if (arg_all || unit_name_to_type(*c) == UNIT_TARGET) {
868 r = list_dependencies_one(bus, *c, level + 1, u, (branches << 1) | (c[1] == NULL ? 0 : 1));
877 static int list_dependencies(DBusConnection *bus, char **args) {
878 _cleanup_free_ char *unit = NULL;
884 unit = unit_name_mangle(args[1]);
889 u = SPECIAL_DEFAULT_TARGET;
891 pager_open_if_enabled();
895 return list_dependencies_one(bus, u, 0, NULL, 0);
898 static int list_jobs(DBusConnection *bus, char **args) {
899 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
900 DBusMessageIter iter, sub, sub2;
904 pager_open_if_enabled();
906 r = bus_method_call_with_reply(
908 "org.freedesktop.systemd1",
909 "/org/freedesktop/systemd1",
910 "org.freedesktop.systemd1.Manager",
918 if (!dbus_message_iter_init(reply, &iter) ||
919 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
920 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
921 log_error("Failed to parse reply.");
925 dbus_message_iter_recurse(&iter, &sub);
928 printf("%4s %-25s %-15s %-7s\n", "JOB", "UNIT", "TYPE", "STATE");
930 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
931 const char *name, *type, *state, *job_path, *unit_path;
933 char _cleanup_free_ *e = NULL;
935 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
936 log_error("Failed to parse reply.");
940 dbus_message_iter_recurse(&sub, &sub2);
942 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &id, true) < 0 ||
943 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
944 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
945 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, true) < 0 ||
946 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &job_path, true) < 0 ||
947 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, false) < 0) {
948 log_error("Failed to parse reply.");
952 e = arg_full ? NULL : ellipsize(name, 25, 33);
953 printf("%4u %-25s %-15s %-7s\n", id, e ? e : name, type, state);
957 dbus_message_iter_next(&sub);
961 printf("\n%u jobs listed.\n", k);
966 static int load_unit(DBusConnection *bus, char **args) {
971 STRV_FOREACH(name, args+1) {
972 _cleanup_free_ char *n = NULL;
975 n = unit_name_mangle(*name);
979 r = bus_method_call_with_reply(
981 "org.freedesktop.systemd1",
982 "/org/freedesktop/systemd1",
983 "org.freedesktop.systemd1.Manager",
987 DBUS_TYPE_STRING, &n,
996 static int cancel_job(DBusConnection *bus, char **args) {
1001 if (strv_length(args) <= 1)
1002 return daemon_reload(bus, args);
1004 STRV_FOREACH(name, args+1) {
1008 r = safe_atou32(*name, &id);
1010 log_error("Failed to parse job id: %s", strerror(-r));
1014 r = bus_method_call_with_reply(
1016 "org.freedesktop.systemd1",
1017 "/org/freedesktop/systemd1",
1018 "org.freedesktop.systemd1.Manager",
1022 DBUS_TYPE_UINT32, &id,
1031 static bool need_daemon_reload(DBusConnection *bus, const char *unit) {
1032 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1033 dbus_bool_t b = FALSE;
1034 DBusMessageIter iter, sub;
1036 *interface = "org.freedesktop.systemd1.Unit",
1037 *property = "NeedDaemonReload",
1039 _cleanup_free_ char *n = NULL;
1042 /* We ignore all errors here, since this is used to show a warning only */
1044 n = unit_name_mangle(unit);
1048 r = bus_method_call_with_reply (
1050 "org.freedesktop.systemd1",
1051 "/org/freedesktop/systemd1",
1052 "org.freedesktop.systemd1.Manager",
1056 DBUS_TYPE_STRING, &n,
1061 if (!dbus_message_get_args(reply, NULL,
1062 DBUS_TYPE_OBJECT_PATH, &path,
1066 dbus_message_unref(reply);
1069 r = bus_method_call_with_reply(
1071 "org.freedesktop.systemd1",
1073 "org.freedesktop.DBus.Properties",
1077 DBUS_TYPE_STRING, &interface,
1078 DBUS_TYPE_STRING, &property,
1083 if (!dbus_message_iter_init(reply, &iter) ||
1084 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
1087 dbus_message_iter_recurse(&iter, &sub);
1088 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_BOOLEAN)
1091 dbus_message_iter_get_basic(&sub, &b);
1095 typedef struct WaitData {
1102 static DBusHandlerResult wait_filter(DBusConnection *connection, DBusMessage *message, void *data) {
1103 DBusError _cleanup_dbus_error_free_ error;
1106 dbus_error_init(&error);
1112 log_debug("Got D-Bus request: %s.%s() on %s",
1113 dbus_message_get_interface(message),
1114 dbus_message_get_member(message),
1115 dbus_message_get_path(message));
1117 if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
1118 log_error("Warning! D-Bus connection terminated.");
1119 dbus_connection_close(connection);
1121 } else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
1123 const char *path, *result, *unit;
1125 if (dbus_message_get_args(message, &error,
1126 DBUS_TYPE_UINT32, &id,
1127 DBUS_TYPE_OBJECT_PATH, &path,
1128 DBUS_TYPE_STRING, &unit,
1129 DBUS_TYPE_STRING, &result,
1130 DBUS_TYPE_INVALID)) {
1132 free(set_remove(d->set, (char*) path));
1134 if (!isempty(result))
1135 d->result = strdup(result);
1138 d->name = strdup(unit);
1140 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1143 dbus_error_free(&error);
1144 if (dbus_message_get_args(message, &error,
1145 DBUS_TYPE_UINT32, &id,
1146 DBUS_TYPE_OBJECT_PATH, &path,
1147 DBUS_TYPE_STRING, &result,
1148 DBUS_TYPE_INVALID)) {
1149 /* Compatibility with older systemd versions <
1150 * 183 during upgrades. This should be dropped
1152 free(set_remove(d->set, (char*) path));
1155 d->result = strdup(result);
1157 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1161 log_error("Failed to parse message: %s", bus_error_message(&error));
1164 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1167 static int enable_wait_for_jobs(DBusConnection *bus) {
1175 dbus_error_init(&error);
1176 dbus_bus_add_match(bus,
1178 "sender='org.freedesktop.systemd1',"
1179 "interface='org.freedesktop.systemd1.Manager',"
1180 "member='JobRemoved',"
1181 "path='/org/freedesktop/systemd1'",
1184 if (dbus_error_is_set(&error)) {
1185 log_error("Failed to add match: %s", bus_error_message(&error));
1186 dbus_error_free(&error);
1190 /* This is slightly dirty, since we don't undo the match registrations. */
1194 static int wait_for_jobs(DBusConnection *bus, Set *s) {
1204 if (!dbus_connection_add_filter(bus, wait_filter, &d, NULL))
1207 while (!set_isempty(s)) {
1209 if (!dbus_connection_read_write_dispatch(bus, -1)) {
1210 log_error("Disconnected from bus.");
1211 return -ECONNREFUSED;
1218 if (streq(d.result, "timeout"))
1219 log_error("Job for %s timed out.", strna(d.name));
1220 else if (streq(d.result, "canceled"))
1221 log_error("Job for %s canceled.", strna(d.name));
1222 else if (streq(d.result, "dependency"))
1223 log_error("A dependency job for %s failed. See 'journalctl -xn' for details.", strna(d.name));
1224 else if (!streq(d.result, "done") && !streq(d.result, "skipped"))
1225 log_error("Job for %s failed. See 'systemctl status %s' and 'journalctl -xn' for details.", strna(d.name), strna(d.name));
1228 if (streq_ptr(d.result, "timeout"))
1230 else if (streq_ptr(d.result, "canceled"))
1232 else if (!streq_ptr(d.result, "done") && !streq_ptr(d.result, "skipped"))
1243 dbus_connection_remove_filter(bus, wait_filter, &d);
1247 static int check_one_unit(DBusConnection *bus, const char *name, char **check_states, bool quiet) {
1248 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1249 _cleanup_free_ char *n = NULL;
1250 DBusMessageIter iter, sub;
1252 *interface = "org.freedesktop.systemd1.Unit",
1253 *property = "ActiveState";
1254 const char *state, *path;
1260 dbus_error_init(&error);
1262 n = unit_name_mangle(name);
1266 r = bus_method_call_with_reply (
1268 "org.freedesktop.systemd1",
1269 "/org/freedesktop/systemd1",
1270 "org.freedesktop.systemd1.Manager",
1274 DBUS_TYPE_STRING, &n,
1277 dbus_error_free(&error);
1284 if (!dbus_message_get_args(reply, NULL,
1285 DBUS_TYPE_OBJECT_PATH, &path,
1286 DBUS_TYPE_INVALID)) {
1287 log_error("Failed to parse reply.");
1291 dbus_message_unref(reply);
1294 r = bus_method_call_with_reply(
1296 "org.freedesktop.systemd1",
1298 "org.freedesktop.DBus.Properties",
1302 DBUS_TYPE_STRING, &interface,
1303 DBUS_TYPE_STRING, &property,
1311 if (!dbus_message_iter_init(reply, &iter) ||
1312 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1313 log_error("Failed to parse reply.");
1317 dbus_message_iter_recurse(&iter, &sub);
1319 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1320 log_error("Failed to parse reply.");
1324 dbus_message_iter_get_basic(&sub, &state);
1329 return strv_find(check_states, state) ? 1 : 0;
1332 static void check_triggering_units(
1333 DBusConnection *bus,
1334 const char *unit_name) {
1336 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1337 DBusMessageIter iter, sub;
1338 const char *interface = "org.freedesktop.systemd1.Unit",
1339 *load_state_property = "LoadState",
1340 *triggered_by_property = "TriggeredBy",
1342 char _cleanup_free_ *unit_path = NULL, *n = NULL;
1343 bool print_warning_label = true;
1346 n = unit_name_mangle(unit_name);
1352 unit_path = unit_dbus_path_from_name(n);
1358 r = bus_method_call_with_reply(
1360 "org.freedesktop.systemd1",
1362 "org.freedesktop.DBus.Properties",
1366 DBUS_TYPE_STRING, &interface,
1367 DBUS_TYPE_STRING, &load_state_property,
1372 if (!dbus_message_iter_init(reply, &iter) ||
1373 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1374 log_error("Failed to parse reply.");
1378 dbus_message_iter_recurse(&iter, &sub);
1380 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1381 log_error("Failed to parse reply.");
1385 dbus_message_iter_get_basic(&sub, &state);
1387 if (streq(state, "masked"))
1390 dbus_message_unref(reply);
1393 r = bus_method_call_with_reply(
1395 "org.freedesktop.systemd1",
1397 "org.freedesktop.DBus.Properties",
1401 DBUS_TYPE_STRING, &interface,
1402 DBUS_TYPE_STRING, &triggered_by_property,
1407 if (!dbus_message_iter_init(reply, &iter) ||
1408 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1409 log_error("Failed to parse reply.");
1413 dbus_message_iter_recurse(&iter, &sub);
1414 dbus_message_iter_recurse(&sub, &iter);
1417 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1418 const char * const check_states[] = {
1423 const char *service_trigger;
1425 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1426 log_error("Failed to parse reply.");
1430 dbus_message_iter_get_basic(&sub, &service_trigger);
1432 r = check_one_unit(bus, service_trigger, (char**) check_states, true);
1436 if (print_warning_label) {
1437 log_warning("Warning: Stopping %s, but it can still be activated by:", unit_name);
1438 print_warning_label = false;
1441 log_warning(" %s", service_trigger);
1444 dbus_message_iter_next(&sub);
1448 static int start_unit_one(
1449 DBusConnection *bus,
1456 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1457 _cleanup_free_ char *n;
1466 n = unit_name_mangle(name);
1470 r = bus_method_call_with_reply(
1472 "org.freedesktop.systemd1",
1473 "/org/freedesktop/systemd1",
1474 "org.freedesktop.systemd1.Manager",
1478 DBUS_TYPE_STRING, &n,
1479 DBUS_TYPE_STRING, &mode,
1482 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
1483 /* There's always a fallback possible for
1484 * legacy actions. */
1487 log_error("Failed to issue method call: %s", bus_error_message(error));
1492 if (!dbus_message_get_args(reply, error,
1493 DBUS_TYPE_OBJECT_PATH, &path,
1494 DBUS_TYPE_INVALID)) {
1495 log_error("Failed to parse reply: %s", bus_error_message(error));
1499 if (need_daemon_reload(bus, n))
1500 log_warning("Warning: Unit file of %s changed on disk, 'systemctl %s daemon-reload' recommended.",
1501 n, arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
1513 log_error("Failed to add path to set.");
1521 static enum action verb_to_action(const char *verb) {
1522 if (streq(verb, "halt"))
1524 else if (streq(verb, "poweroff"))
1525 return ACTION_POWEROFF;
1526 else if (streq(verb, "reboot"))
1527 return ACTION_REBOOT;
1528 else if (streq(verb, "kexec"))
1529 return ACTION_KEXEC;
1530 else if (streq(verb, "rescue"))
1531 return ACTION_RESCUE;
1532 else if (streq(verb, "emergency"))
1533 return ACTION_EMERGENCY;
1534 else if (streq(verb, "default"))
1535 return ACTION_DEFAULT;
1536 else if (streq(verb, "exit"))
1538 else if (streq(verb, "suspend"))
1539 return ACTION_SUSPEND;
1540 else if (streq(verb, "hibernate"))
1541 return ACTION_HIBERNATE;
1542 else if (streq(verb, "hybrid-sleep"))
1543 return ACTION_HYBRID_SLEEP;
1545 return ACTION_INVALID;
1548 static int start_unit(DBusConnection *bus, char **args) {
1550 static const char * const table[_ACTION_MAX] = {
1551 [ACTION_HALT] = SPECIAL_HALT_TARGET,
1552 [ACTION_POWEROFF] = SPECIAL_POWEROFF_TARGET,
1553 [ACTION_REBOOT] = SPECIAL_REBOOT_TARGET,
1554 [ACTION_KEXEC] = SPECIAL_KEXEC_TARGET,
1555 [ACTION_RUNLEVEL2] = SPECIAL_RUNLEVEL2_TARGET,
1556 [ACTION_RUNLEVEL3] = SPECIAL_RUNLEVEL3_TARGET,
1557 [ACTION_RUNLEVEL4] = SPECIAL_RUNLEVEL4_TARGET,
1558 [ACTION_RUNLEVEL5] = SPECIAL_RUNLEVEL5_TARGET,
1559 [ACTION_RESCUE] = SPECIAL_RESCUE_TARGET,
1560 [ACTION_EMERGENCY] = SPECIAL_EMERGENCY_TARGET,
1561 [ACTION_DEFAULT] = SPECIAL_DEFAULT_TARGET,
1562 [ACTION_EXIT] = SPECIAL_EXIT_TARGET,
1563 [ACTION_SUSPEND] = SPECIAL_SUSPEND_TARGET,
1564 [ACTION_HIBERNATE] = SPECIAL_HIBERNATE_TARGET,
1565 [ACTION_HYBRID_SLEEP] = SPECIAL_HYBRID_SLEEP_TARGET
1569 const char *method, *mode, *one_name;
1570 Set _cleanup_set_free_free_ *s = NULL;
1571 DBusError _cleanup_dbus_error_free_ error;
1574 dbus_error_init(&error);
1578 ask_password_agent_open_if_enabled();
1580 if (arg_action == ACTION_SYSTEMCTL) {
1582 streq(args[0], "stop") ||
1583 streq(args[0], "condstop") ? "StopUnit" :
1584 streq(args[0], "reload") ? "ReloadUnit" :
1585 streq(args[0], "restart") ? "RestartUnit" :
1587 streq(args[0], "try-restart") ||
1588 streq(args[0], "condrestart") ? "TryRestartUnit" :
1590 streq(args[0], "reload-or-restart") ? "ReloadOrRestartUnit" :
1592 streq(args[0], "reload-or-try-restart") ||
1593 streq(args[0], "condreload") ||
1595 streq(args[0], "force-reload") ? "ReloadOrTryRestartUnit" :
1599 (streq(args[0], "isolate") ||
1600 streq(args[0], "rescue") ||
1601 streq(args[0], "emergency")) ? "isolate" : arg_job_mode;
1603 one_name = table[verb_to_action(args[0])];
1606 assert(arg_action < ELEMENTSOF(table));
1607 assert(table[arg_action]);
1609 method = "StartUnit";
1611 mode = (arg_action == ACTION_EMERGENCY ||
1612 arg_action == ACTION_RESCUE ||
1613 arg_action == ACTION_RUNLEVEL2 ||
1614 arg_action == ACTION_RUNLEVEL3 ||
1615 arg_action == ACTION_RUNLEVEL4 ||
1616 arg_action == ACTION_RUNLEVEL5) ? "isolate" : "replace";
1618 one_name = table[arg_action];
1621 if (!arg_no_block) {
1622 ret = enable_wait_for_jobs(bus);
1624 log_error("Could not watch jobs: %s", strerror(-ret));
1628 s = set_new(string_hash_func, string_compare_func);
1634 ret = start_unit_one(bus, method, one_name, mode, &error, s);
1636 ret = translate_bus_error_to_exit_status(ret, &error);
1638 STRV_FOREACH(name, args+1) {
1639 r = start_unit_one(bus, method, *name, mode, &error, s);
1641 ret = translate_bus_error_to_exit_status(r, &error);
1642 dbus_error_free(&error);
1647 if (!arg_no_block) {
1648 r = wait_for_jobs(bus, s);
1652 /* When stopping units, warn if they can still be triggered by
1653 * another active unit (socket, path, timer) */
1654 if (!arg_quiet && streq(method, "StopUnit")) {
1656 check_triggering_units(bus, one_name);
1658 STRV_FOREACH(name, args+1)
1659 check_triggering_units(bus, *name);
1666 /* Ask systemd-logind, which might grant access to unprivileged users
1667 * through PolicyKit */
1668 static int reboot_with_logind(DBusConnection *bus, enum action a) {
1671 dbus_bool_t interactive = true;
1676 polkit_agent_open_if_enabled();
1684 case ACTION_POWEROFF:
1685 method = "PowerOff";
1688 case ACTION_SUSPEND:
1692 case ACTION_HIBERNATE:
1693 method = "Hibernate";
1696 case ACTION_HYBRID_SLEEP:
1697 method = "HybridSleep";
1704 return bus_method_call_with_reply(
1706 "org.freedesktop.login1",
1707 "/org/freedesktop/login1",
1708 "org.freedesktop.login1.Manager",
1712 DBUS_TYPE_BOOLEAN, &interactive,
1719 static int check_inhibitors(DBusConnection *bus, enum action a) {
1721 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1722 DBusMessageIter iter, sub, sub2;
1725 _cleanup_strv_free_ char **sessions = NULL;
1731 if (arg_ignore_inhibitors || arg_force > 0)
1743 r = bus_method_call_with_reply(
1745 "org.freedesktop.login1",
1746 "/org/freedesktop/login1",
1747 "org.freedesktop.login1.Manager",
1753 /* If logind is not around, then there are no inhibitors... */
1756 if (!dbus_message_iter_init(reply, &iter) ||
1757 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
1758 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
1759 log_error("Failed to parse reply.");
1763 dbus_message_iter_recurse(&iter, &sub);
1764 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1765 const char *what, *who, *why, *mode;
1767 _cleanup_strv_free_ char **sv = NULL;
1768 _cleanup_free_ char *comm = NULL, *user = NULL;
1770 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
1771 log_error("Failed to parse reply.");
1775 dbus_message_iter_recurse(&sub, &sub2);
1777 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &what, true) < 0 ||
1778 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &who, true) < 0 ||
1779 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &why, true) < 0 ||
1780 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &mode, true) < 0 ||
1781 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &uid, true) < 0 ||
1782 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, false) < 0) {
1783 log_error("Failed to parse reply.");
1787 if (!streq(mode, "block"))
1790 sv = strv_split(what, ":");
1794 if (!strv_contains(sv,
1796 a == ACTION_POWEROFF ||
1797 a == ACTION_REBOOT ||
1798 a == ACTION_KEXEC ? "shutdown" : "sleep"))
1801 get_process_comm(pid, &comm);
1802 user = uid_to_name(uid);
1803 log_warning("Operation inhibited by \"%s\" (PID %lu \"%s\", user %s), reason is \"%s\".",
1804 who, (unsigned long) pid, strna(comm), strna(user), why);
1808 dbus_message_iter_next(&sub);
1811 dbus_message_iter_recurse(&iter, &sub);
1813 /* Check for current sessions */
1814 sd_get_sessions(&sessions);
1815 STRV_FOREACH(s, sessions) {
1817 _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL;
1819 if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid())
1822 if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
1825 if (sd_session_get_type(*s, &type) < 0 || (!streq(type, "x11") && !streq(type, "tty")))
1828 sd_session_get_tty(*s, &tty);
1829 sd_session_get_seat(*s, &seat);
1830 sd_session_get_service(*s, &service);
1831 user = uid_to_name(uid);
1833 log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty);
1840 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
1841 a == ACTION_HALT ? "halt" :
1842 a == ACTION_POWEROFF ? "poweroff" :
1843 a == ACTION_REBOOT ? "reboot" :
1844 a == ACTION_KEXEC ? "kexec" :
1845 a == ACTION_SUSPEND ? "suspend" :
1846 a == ACTION_HIBERNATE ? "hibernate" : "hybrid-sleep");
1854 static int start_special(DBusConnection *bus, char **args) {
1860 a = verb_to_action(args[0]);
1862 r = check_inhibitors(bus, a);
1866 if (arg_force >= 2 && geteuid() != 0) {
1867 log_error("Must be root.");
1871 if (arg_force >= 2 &&
1872 (a == ACTION_HALT ||
1873 a == ACTION_POWEROFF ||
1874 a == ACTION_REBOOT))
1877 if (arg_force >= 1 &&
1878 (a == ACTION_HALT ||
1879 a == ACTION_POWEROFF ||
1880 a == ACTION_REBOOT ||
1881 a == ACTION_KEXEC ||
1883 return daemon_reload(bus, args);
1885 /* first try logind, to allow authentication with polkit */
1886 if (geteuid() != 0 &&
1887 (a == ACTION_POWEROFF ||
1888 a == ACTION_REBOOT ||
1889 a == ACTION_SUSPEND ||
1890 a == ACTION_HIBERNATE ||
1891 a == ACTION_HYBRID_SLEEP)) {
1892 r = reboot_with_logind(bus, a);
1897 r = start_unit(bus, args);
1898 if (r == EXIT_SUCCESS)
1904 static int check_unit_active(DBusConnection *bus, char **args) {
1905 const char * const check_states[] = {
1912 int r = 3; /* According to LSB: "program is not running" */
1917 STRV_FOREACH(name, args+1) {
1920 state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
1930 static int check_unit_failed(DBusConnection *bus, char **args) {
1931 const char * const check_states[] = {
1942 STRV_FOREACH(name, args+1) {
1945 state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
1955 static int kill_unit(DBusConnection *bus, char **args) {
1963 arg_kill_who = "all";
1965 STRV_FOREACH(name, args+1) {
1966 _cleanup_free_ char *n = NULL;
1968 n = unit_name_mangle(*name);
1972 r = bus_method_call_with_reply(
1974 "org.freedesktop.systemd1",
1975 "/org/freedesktop/systemd1",
1976 "org.freedesktop.systemd1.Manager",
1980 DBUS_TYPE_STRING, &n,
1981 DBUS_TYPE_STRING, &arg_kill_who,
1982 DBUS_TYPE_INT32, &arg_signal,
1990 static int set_cgroup(DBusConnection *bus, char **args) {
1991 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
1994 DBusMessageIter iter;
1996 _cleanup_free_ char *n = NULL;
1997 const char *runtime;
2002 dbus_error_init(&error);
2005 streq(args[0], "set-cgroup") ? "SetUnitControlGroups" :
2006 streq(args[0], "unset-group") ? "UnsetUnitControlGroups"
2007 : "UnsetUnitControlGroupAttributes";
2009 n = unit_name_mangle(args[1]);
2013 m = dbus_message_new_method_call(
2014 "org.freedesktop.systemd1",
2015 "/org/freedesktop/systemd1",
2016 "org.freedesktop.systemd1.Manager",
2021 dbus_message_iter_init_append(m, &iter);
2022 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &n))
2025 r = bus_append_strv_iter(&iter, args + 2);
2029 runtime = arg_runtime ? "runtime" : "persistent";
2030 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &runtime))
2033 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
2035 log_error("Failed to issue method call: %s", bus_error_message(&error));
2036 dbus_error_free(&error);
2043 static int set_cgroup_attr(DBusConnection *bus, char **args) {
2044 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
2046 DBusMessageIter iter, sub, sub2;
2048 _cleanup_free_ char *n = NULL;
2049 const char *runtime;
2054 dbus_error_init(&error);
2056 if (strv_length(args) % 2 != 0) {
2057 log_error("Expecting an uneven number of arguments!");
2061 n = unit_name_mangle(args[1]);
2065 m = dbus_message_new_method_call(
2066 "org.freedesktop.systemd1",
2067 "/org/freedesktop/systemd1",
2068 "org.freedesktop.systemd1.Manager",
2069 "SetUnitControlGroupAttributes");
2073 dbus_message_iter_init_append(m, &iter);
2074 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &n) ||
2075 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ss)", &sub))
2078 STRV_FOREACH_PAIR(x, y, args + 2) {
2079 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
2080 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, x) ||
2081 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, y) ||
2082 !dbus_message_iter_close_container(&sub, &sub2))
2086 runtime = arg_runtime ? "runtime" : "persistent";
2087 if (!dbus_message_iter_close_container(&iter, &sub) ||
2088 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &runtime))
2091 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
2093 log_error("Failed to issue method call: %s", bus_error_message(&error));
2094 dbus_error_free(&error);
2101 static int get_cgroup_attr(DBusConnection *bus, char **args) {
2102 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
2104 DBusMessageIter iter;
2106 _cleanup_free_ char *n = NULL;
2107 _cleanup_strv_free_ char **list = NULL;
2113 dbus_error_init(&error);
2115 n = unit_name_mangle(args[1]);
2119 m = dbus_message_new_method_call(
2120 "org.freedesktop.systemd1",
2121 "/org/freedesktop/systemd1",
2122 "org.freedesktop.systemd1.Manager",
2123 "GetUnitControlGroupAttributes");
2127 dbus_message_iter_init_append(m, &iter);
2128 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &n))
2131 r = bus_append_strv_iter(&iter, args + 2);
2135 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
2137 log_error("Failed to issue method call: %s", bus_error_message(&error));
2138 dbus_error_free(&error);
2142 dbus_message_iter_init(reply, &iter);
2143 r = bus_parse_strv_iter(&iter, &list);
2145 log_error("Failed to parse value list.");
2149 STRV_FOREACH(a, list) {
2150 if (endswith(*a, "\n"))
2159 typedef struct ExecStatusInfo {
2167 usec_t start_timestamp;
2168 usec_t exit_timestamp;
2173 LIST_FIELDS(struct ExecStatusInfo, exec);
2176 static void exec_status_info_free(ExecStatusInfo *i) {
2185 static int exec_status_info_deserialize(DBusMessageIter *sub, ExecStatusInfo *i) {
2186 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
2187 DBusMessageIter sub2, sub3;
2191 int32_t code, status;
2197 if (dbus_message_iter_get_arg_type(sub) != DBUS_TYPE_STRUCT)
2200 dbus_message_iter_recurse(sub, &sub2);
2202 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0)
2205 i->path = strdup(path);
2209 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_ARRAY ||
2210 dbus_message_iter_get_element_type(&sub2) != DBUS_TYPE_STRING)
2214 dbus_message_iter_recurse(&sub2, &sub3);
2215 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2216 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2217 dbus_message_iter_next(&sub3);
2221 i->argv = new0(char*, n+1);
2226 dbus_message_iter_recurse(&sub2, &sub3);
2227 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2230 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2231 dbus_message_iter_get_basic(&sub3, &s);
2232 dbus_message_iter_next(&sub3);
2234 i->argv[n] = strdup(s);
2241 if (!dbus_message_iter_next(&sub2) ||
2242 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, true) < 0 ||
2243 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp, true) < 0 ||
2244 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp_monotonic, true) < 0 ||
2245 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp, true) < 0 ||
2246 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp_monotonic, true) < 0 ||
2247 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, true) < 0 ||
2248 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &code, true) < 0 ||
2249 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &status, false) < 0)
2253 i->start_timestamp = (usec_t) start_timestamp;
2254 i->exit_timestamp = (usec_t) exit_timestamp;
2255 i->pid = (pid_t) pid;
2262 typedef struct UnitStatusInfo {
2264 const char *load_state;
2265 const char *active_state;
2266 const char *sub_state;
2267 const char *unit_file_state;
2269 const char *description;
2270 const char *following;
2272 char **documentation;
2274 const char *fragment_path;
2275 const char *source_path;
2276 const char *default_control_group;
2278 const char *load_error;
2281 usec_t inactive_exit_timestamp;
2282 usec_t inactive_exit_timestamp_monotonic;
2283 usec_t active_enter_timestamp;
2284 usec_t active_exit_timestamp;
2285 usec_t inactive_enter_timestamp;
2287 bool need_daemon_reload;
2292 const char *status_text;
2295 usec_t start_timestamp;
2296 usec_t exit_timestamp;
2298 int exit_code, exit_status;
2300 usec_t condition_timestamp;
2301 bool condition_result;
2304 unsigned n_accepted;
2305 unsigned n_connections;
2309 const char *sysfs_path;
2311 /* Mount, Automount */
2317 LIST_HEAD(ExecStatusInfo, exec);
2320 static void print_status_info(UnitStatusInfo *i) {
2322 const char *on, *off, *ss;
2324 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
2325 char since2[FORMAT_TIMESTAMP_MAX], *s2;
2328 arg_all * OUTPUT_SHOW_ALL |
2329 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
2330 on_tty() * OUTPUT_COLOR |
2331 !arg_quiet * OUTPUT_WARN_CUTOFF |
2332 arg_full * OUTPUT_FULL_WIDTH;
2336 /* This shows pretty information about a unit. See
2337 * print_property() for a low-level property printer */
2339 printf("%s", strna(i->id));
2341 if (i->description && !streq_ptr(i->id, i->description))
2342 printf(" - %s", i->description);
2347 printf("\t Follow: unit currently follows state of %s\n", i->following);
2349 if (streq_ptr(i->load_state, "error")) {
2350 on = ansi_highlight_red(true);
2351 off = ansi_highlight_red(false);
2355 path = i->source_path ? i->source_path : i->fragment_path;
2358 printf("\t Loaded: %s%s%s (Reason: %s)\n", on, strna(i->load_state), off, i->load_error);
2359 else if (path && i->unit_file_state)
2360 printf("\t Loaded: %s%s%s (%s; %s)\n", on, strna(i->load_state), off, path, i->unit_file_state);
2362 printf("\t Loaded: %s%s%s (%s)\n", on, strna(i->load_state), off, path);
2364 printf("\t Loaded: %s%s%s\n", on, strna(i->load_state), off);
2366 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
2368 if (streq_ptr(i->active_state, "failed")) {
2369 on = ansi_highlight_red(true);
2370 off = ansi_highlight_red(false);
2371 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
2372 on = ansi_highlight_green(true);
2373 off = ansi_highlight_green(false);
2378 printf("\t Active: %s%s (%s)%s",
2380 strna(i->active_state),
2384 printf("\t Active: %s%s%s",
2386 strna(i->active_state),
2389 if (!isempty(i->result) && !streq(i->result, "success"))
2390 printf(" (Result: %s)", i->result);
2392 timestamp = (streq_ptr(i->active_state, "active") ||
2393 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
2394 (streq_ptr(i->active_state, "inactive") ||
2395 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
2396 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
2397 i->active_exit_timestamp;
2399 s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
2400 s2 = format_timestamp(since2, sizeof(since2), timestamp);
2403 printf(" since %s; %s\n", s2, s1);
2405 printf(" since %s\n", s2);
2409 if (!i->condition_result && i->condition_timestamp > 0) {
2410 s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
2411 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
2414 printf("\t start condition failed at %s; %s\n", s2, s1);
2416 printf("\t start condition failed at %s\n", s2);
2420 printf("\t Device: %s\n", i->sysfs_path);
2422 printf("\t Where: %s\n", i->where);
2424 printf("\t What: %s\n", i->what);
2426 if (!strv_isempty(i->documentation)) {
2430 STRV_FOREACH(t, i->documentation) {
2432 printf("\t Docs: %s\n", *t);
2435 printf("\t %s\n", *t);
2440 printf("\tAccepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
2442 LIST_FOREACH(exec, p, i->exec) {
2443 _cleanup_free_ char *t = NULL;
2446 /* Only show exited processes here */
2450 t = strv_join(p->argv, " ");
2451 printf("\t Process: %u %s=%s ", p->pid, p->name, strna(t));
2453 good = is_clean_exit_lsb(p->code, p->status, NULL);
2455 on = ansi_highlight_red(true);
2456 off = ansi_highlight_red(false);
2460 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
2462 if (p->code == CLD_EXITED) {
2465 printf("status=%i", p->status);
2467 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
2472 printf("signal=%s", signal_to_string(p->status));
2474 printf(")%s\n", off);
2476 if (i->main_pid == p->pid &&
2477 i->start_timestamp == p->start_timestamp &&
2478 i->exit_timestamp == p->start_timestamp)
2479 /* Let's not show this twice */
2482 if (p->pid == i->control_pid)
2486 if (i->main_pid > 0 || i->control_pid > 0) {
2489 if (i->main_pid > 0) {
2490 printf("Main PID: %u", (unsigned) i->main_pid);
2493 _cleanup_free_ char *t = NULL;
2494 get_process_comm(i->main_pid, &t);
2497 } else if (i->exit_code > 0) {
2498 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
2500 if (i->exit_code == CLD_EXITED) {
2503 printf("status=%i", i->exit_status);
2505 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
2510 printf("signal=%s", signal_to_string(i->exit_status));
2515 if (i->main_pid > 0 && i->control_pid > 0)
2518 if (i->control_pid > 0) {
2519 _cleanup_free_ char *t = NULL;
2521 printf(" Control: %u", (unsigned) i->control_pid);
2523 get_process_comm(i->control_pid, &t);
2532 printf("\t Status: \"%s\"\n", i->status_text);
2534 if (i->default_control_group &&
2535 (i->main_pid > 0 || i->control_pid > 0 || cg_is_empty_by_spec(i->default_control_group, false) == 0)) {
2538 printf("\t CGroup: %s\n", i->default_control_group);
2540 if (arg_transport != TRANSPORT_SSH) {
2550 if (i->main_pid > 0)
2551 extra[k++] = i->main_pid;
2553 if (i->control_pid > 0)
2554 extra[k++] = i->control_pid;
2556 show_cgroup_and_extra_by_spec(i->default_control_group, "\t\t ", c, false, extra, k, flags);
2560 if (i->id && arg_transport != TRANSPORT_SSH) {
2562 if(arg_scope == UNIT_FILE_SYSTEM)
2563 show_journal_by_unit(stdout,
2567 i->inactive_exit_timestamp_monotonic,
2571 show_journal_by_user_unit(stdout,
2575 i->inactive_exit_timestamp_monotonic,
2581 if (i->need_daemon_reload)
2582 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %s daemon-reload' recommended.\n",
2583 ansi_highlight_red(true),
2584 ansi_highlight_red(false),
2585 arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
2588 static void show_unit_help(UnitStatusInfo *i) {
2593 if (!i->documentation) {
2594 log_info("Documentation for %s not known.", i->id);
2598 STRV_FOREACH(p, i->documentation) {
2600 if (startswith(*p, "man:")) {
2603 char _cleanup_free_ *page = NULL, *section = NULL;
2604 const char *args[4] = { "man", NULL, NULL, NULL };
2609 if ((*p)[k-1] == ')')
2610 e = strrchr(*p, '(');
2613 page = strndup((*p) + 4, e - *p - 4);
2614 section = strndup(e + 1, *p + k - e - 2);
2615 if (!page || !section) {
2627 log_error("Failed to fork: %m");
2633 execvp(args[0], (char**) args);
2634 log_error("Failed to execute man: %m");
2635 _exit(EXIT_FAILURE);
2638 wait_for_terminate(pid, NULL);
2640 log_info("Can't show: %s", *p);
2644 static int status_property(const char *name, DBusMessageIter *iter, UnitStatusInfo *i) {
2650 switch (dbus_message_iter_get_arg_type(iter)) {
2652 case DBUS_TYPE_STRING: {
2655 dbus_message_iter_get_basic(iter, &s);
2658 if (streq(name, "Id"))
2660 else if (streq(name, "LoadState"))
2662 else if (streq(name, "ActiveState"))
2663 i->active_state = s;
2664 else if (streq(name, "SubState"))
2666 else if (streq(name, "Description"))
2668 else if (streq(name, "FragmentPath"))
2669 i->fragment_path = s;
2670 else if (streq(name, "SourcePath"))
2672 else if (streq(name, "DefaultControlGroup"))
2673 i->default_control_group = s;
2674 else if (streq(name, "StatusText"))
2676 else if (streq(name, "SysFSPath"))
2678 else if (streq(name, "Where"))
2680 else if (streq(name, "What"))
2682 else if (streq(name, "Following"))
2684 else if (streq(name, "UnitFileState"))
2685 i->unit_file_state = s;
2686 else if (streq(name, "Result"))
2693 case DBUS_TYPE_BOOLEAN: {
2696 dbus_message_iter_get_basic(iter, &b);
2698 if (streq(name, "Accept"))
2700 else if (streq(name, "NeedDaemonReload"))
2701 i->need_daemon_reload = b;
2702 else if (streq(name, "ConditionResult"))
2703 i->condition_result = b;
2708 case DBUS_TYPE_UINT32: {
2711 dbus_message_iter_get_basic(iter, &u);
2713 if (streq(name, "MainPID")) {
2715 i->main_pid = (pid_t) u;
2718 } else if (streq(name, "ControlPID"))
2719 i->control_pid = (pid_t) u;
2720 else if (streq(name, "ExecMainPID")) {
2722 i->main_pid = (pid_t) u;
2723 } else if (streq(name, "NAccepted"))
2725 else if (streq(name, "NConnections"))
2726 i->n_connections = u;
2731 case DBUS_TYPE_INT32: {
2734 dbus_message_iter_get_basic(iter, &j);
2736 if (streq(name, "ExecMainCode"))
2737 i->exit_code = (int) j;
2738 else if (streq(name, "ExecMainStatus"))
2739 i->exit_status = (int) j;
2744 case DBUS_TYPE_UINT64: {
2747 dbus_message_iter_get_basic(iter, &u);
2749 if (streq(name, "ExecMainStartTimestamp"))
2750 i->start_timestamp = (usec_t) u;
2751 else if (streq(name, "ExecMainExitTimestamp"))
2752 i->exit_timestamp = (usec_t) u;
2753 else if (streq(name, "ActiveEnterTimestamp"))
2754 i->active_enter_timestamp = (usec_t) u;
2755 else if (streq(name, "InactiveEnterTimestamp"))
2756 i->inactive_enter_timestamp = (usec_t) u;
2757 else if (streq(name, "InactiveExitTimestamp"))
2758 i->inactive_exit_timestamp = (usec_t) u;
2759 else if (streq(name, "InactiveExitTimestampMonotonic"))
2760 i->inactive_exit_timestamp_monotonic = (usec_t) u;
2761 else if (streq(name, "ActiveExitTimestamp"))
2762 i->active_exit_timestamp = (usec_t) u;
2763 else if (streq(name, "ConditionTimestamp"))
2764 i->condition_timestamp = (usec_t) u;
2769 case DBUS_TYPE_ARRAY: {
2771 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
2772 startswith(name, "Exec")) {
2773 DBusMessageIter sub;
2775 dbus_message_iter_recurse(iter, &sub);
2776 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2777 ExecStatusInfo *info;
2780 if (!(info = new0(ExecStatusInfo, 1)))
2783 if (!(info->name = strdup(name))) {
2788 if ((r = exec_status_info_deserialize(&sub, info)) < 0) {
2793 LIST_PREPEND(ExecStatusInfo, exec, i->exec, info);
2795 dbus_message_iter_next(&sub);
2797 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
2798 streq(name, "Documentation")) {
2800 DBusMessageIter sub;
2802 dbus_message_iter_recurse(iter, &sub);
2803 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING) {
2807 dbus_message_iter_get_basic(&sub, &s);
2809 l = strv_append(i->documentation, s);
2813 strv_free(i->documentation);
2814 i->documentation = l;
2816 dbus_message_iter_next(&sub);
2823 case DBUS_TYPE_STRUCT: {
2825 if (streq(name, "LoadError")) {
2826 DBusMessageIter sub;
2827 const char *n, *message;
2830 dbus_message_iter_recurse(iter, &sub);
2832 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &n, true);
2836 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &message, false);
2840 if (!isempty(message))
2841 i->load_error = message;
2851 static int print_property(const char *name, DBusMessageIter *iter) {
2855 /* This is a low-level property printer, see
2856 * print_status_info() for the nicer output */
2858 if (arg_property && !strv_find(arg_property, name))
2861 switch (dbus_message_iter_get_arg_type(iter)) {
2863 case DBUS_TYPE_STRUCT: {
2864 DBusMessageIter sub;
2865 dbus_message_iter_recurse(iter, &sub);
2867 if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32 && streq(name, "Job")) {
2870 dbus_message_iter_get_basic(&sub, &u);
2873 printf("%s=%u\n", name, (unsigned) u);
2875 printf("%s=\n", name);
2878 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "Unit")) {
2881 dbus_message_iter_get_basic(&sub, &s);
2883 if (arg_all || s[0])
2884 printf("%s=%s\n", name, s);
2887 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "LoadError")) {
2888 const char *a = NULL, *b = NULL;
2890 if (bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &a, true) >= 0)
2891 bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &b, false);
2893 if (arg_all || !isempty(a) || !isempty(b))
2894 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
2902 case DBUS_TYPE_ARRAY:
2904 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "EnvironmentFiles")) {
2905 DBusMessageIter sub, sub2;
2907 dbus_message_iter_recurse(iter, &sub);
2908 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2912 dbus_message_iter_recurse(&sub, &sub2);
2914 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
2915 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) >= 0)
2916 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
2918 dbus_message_iter_next(&sub);
2923 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Paths")) {
2924 DBusMessageIter sub, sub2;
2926 dbus_message_iter_recurse(iter, &sub);
2927 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2928 const char *type, *path;
2930 dbus_message_iter_recurse(&sub, &sub2);
2932 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
2933 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
2934 printf("%s=%s\n", type, path);
2936 dbus_message_iter_next(&sub);
2941 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Timers")) {
2942 DBusMessageIter sub, sub2;
2944 dbus_message_iter_recurse(iter, &sub);
2945 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2947 uint64_t value, next_elapse;
2949 dbus_message_iter_recurse(&sub, &sub2);
2951 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &base, true) >= 0 &&
2952 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &value, true) >= 0 &&
2953 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &next_elapse, false) >= 0) {
2954 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
2956 printf("%s={ value=%s ; next_elapse=%s }\n",
2958 format_timespan(timespan1, sizeof(timespan1), value),
2959 format_timespan(timespan2, sizeof(timespan2), next_elapse));
2962 dbus_message_iter_next(&sub);
2967 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "ControlGroupAttributes")) {
2968 DBusMessageIter sub, sub2;
2970 dbus_message_iter_recurse(iter, &sub);
2971 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2972 const char *controller, *attr, *value;
2974 dbus_message_iter_recurse(&sub, &sub2);
2976 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &controller, true) >= 0 &&
2977 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &attr, true) >= 0 &&
2978 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &value, false) >= 0) {
2980 printf("ControlGroupAttributes={ controller=%s ; attribute=%s ; value=\"%s\" }\n",
2986 dbus_message_iter_next(&sub);
2991 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && startswith(name, "Exec")) {
2992 DBusMessageIter sub;
2994 dbus_message_iter_recurse(iter, &sub);
2995 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2996 ExecStatusInfo info;
2999 if (exec_status_info_deserialize(&sub, &info) >= 0) {
3000 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
3001 char _cleanup_free_ *t;
3003 t = strv_join(info.argv, " ");
3005 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
3009 yes_no(info.ignore),
3010 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
3011 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
3012 (unsigned) info. pid,
3013 sigchld_code_to_string(info.code),
3015 info.code == CLD_EXITED ? "" : "/",
3016 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
3020 strv_free(info.argv);
3022 dbus_message_iter_next(&sub);
3031 if (generic_print_property(name, iter, arg_all) > 0)
3035 printf("%s=[unprintable]\n", name);
3040 static int show_one(const char *verb, DBusConnection *bus, const char *path, bool show_properties, bool *new_line) {
3041 _cleanup_free_ DBusMessage *reply = NULL;
3042 const char *interface = "";
3044 DBusMessageIter iter, sub, sub2, sub3;
3045 UnitStatusInfo info;
3053 r = bus_method_call_with_reply(
3055 "org.freedesktop.systemd1",
3057 "org.freedesktop.DBus.Properties",
3061 DBUS_TYPE_STRING, &interface,
3066 if (!dbus_message_iter_init(reply, &iter) ||
3067 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3068 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
3069 log_error("Failed to parse reply.");
3073 dbus_message_iter_recurse(&iter, &sub);
3080 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
3083 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_DICT_ENTRY);
3084 dbus_message_iter_recurse(&sub, &sub2);
3086 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
3087 dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
3088 log_error("Failed to parse reply.");
3092 dbus_message_iter_recurse(&sub2, &sub3);
3094 if (show_properties)
3095 r = print_property(name, &sub3);
3097 r = status_property(name, &sub3, &info);
3099 log_error("Failed to parse reply.");
3103 dbus_message_iter_next(&sub);
3108 if (!show_properties) {
3109 if (streq(verb, "help"))
3110 show_unit_help(&info);
3112 print_status_info(&info);
3115 strv_free(info.documentation);
3117 if (!streq_ptr(info.active_state, "active") &&
3118 !streq_ptr(info.active_state, "reloading") &&
3119 streq(verb, "status"))
3120 /* According to LSB: "program not running" */
3123 while ((p = info.exec)) {
3124 LIST_REMOVE(ExecStatusInfo, exec, info.exec, p);
3125 exec_status_info_free(p);
3131 static int show_one_by_pid(const char *verb, DBusConnection *bus, uint32_t pid, bool *new_line) {
3132 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3133 const char *path = NULL;
3134 DBusError _cleanup_dbus_error_free_ error;
3137 dbus_error_init(&error);
3139 r = bus_method_call_with_reply(
3141 "org.freedesktop.systemd1",
3142 "/org/freedesktop/systemd1",
3143 "org.freedesktop.systemd1.Manager",
3147 DBUS_TYPE_UINT32, &pid,
3152 if (!dbus_message_get_args(reply, &error,
3153 DBUS_TYPE_OBJECT_PATH, &path,
3154 DBUS_TYPE_INVALID)) {
3155 log_error("Failed to parse reply: %s", bus_error_message(&error));
3159 r = show_one(verb, bus, path, false, new_line);
3163 static int show_all(const char* verb, DBusConnection *bus, bool show_properties, bool *new_line) {
3164 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3165 _cleanup_free_ struct unit_info *unit_infos = NULL;
3167 const struct unit_info *u;
3170 r = get_unit_list(bus, &reply, &unit_infos, &c);
3174 for (u = unit_infos; u < unit_infos + c; u++) {
3175 char _cleanup_free_ *p = NULL;
3177 if (!output_show_unit(u))
3180 p = unit_dbus_path_from_name(u->id);
3184 printf("%s -> '%s'\n", u->id, p);
3186 r = show_one(verb, bus, p, show_properties, new_line);
3194 static int show(DBusConnection *bus, char **args) {
3196 bool show_properties, show_status, new_line = false;
3202 show_properties = streq(args[0], "show");
3203 show_status = streq(args[0], "status");
3205 if (show_properties)
3206 pager_open_if_enabled();
3208 /* If no argument is specified inspect the manager itself */
3210 if (show_properties && strv_length(args) <= 1)
3211 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line);
3213 if (show_status && strv_length(args) <= 1)
3214 return show_all(args[0], bus, false, &new_line);
3216 STRV_FOREACH(name, args+1) {
3219 if (safe_atou32(*name, &id) < 0) {
3220 _cleanup_free_ char *p = NULL, *n = NULL;
3221 /* Interpret as unit name */
3223 n = unit_name_mangle(*name);
3227 p = unit_dbus_path_from_name(n);
3231 r = show_one(args[0], bus, p, show_properties, &new_line);
3235 } else if (show_properties) {
3236 _cleanup_free_ char *p = NULL;
3238 /* Interpret as job id */
3239 if (asprintf(&p, "/org/freedesktop/systemd1/job/%u", id) < 0)
3242 r = show_one(args[0], bus, p, show_properties, &new_line);
3247 /* Interpret as PID */
3248 r = show_one_by_pid(args[0], bus, id, &new_line);
3257 static int dump(DBusConnection *bus, char **args) {
3258 _cleanup_free_ DBusMessage *reply = NULL;
3263 dbus_error_init(&error);
3265 pager_open_if_enabled();
3267 r = bus_method_call_with_reply(
3269 "org.freedesktop.systemd1",
3270 "/org/freedesktop/systemd1",
3271 "org.freedesktop.systemd1.Manager",
3279 if (!dbus_message_get_args(reply, &error,
3280 DBUS_TYPE_STRING, &text,
3281 DBUS_TYPE_INVALID)) {
3282 log_error("Failed to parse reply: %s", bus_error_message(&error));
3283 dbus_error_free(&error);
3287 fputs(text, stdout);
3291 static int snapshot(DBusConnection *bus, char **args) {
3292 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3295 dbus_bool_t cleanup = FALSE;
3296 DBusMessageIter iter, sub;
3299 *interface = "org.freedesktop.systemd1.Unit",
3301 _cleanup_free_ char *n = NULL;
3303 dbus_error_init(&error);
3305 if (strv_length(args) > 1)
3306 n = snapshot_name_mangle(args[1]);
3312 r = bus_method_call_with_reply (
3314 "org.freedesktop.systemd1",
3315 "/org/freedesktop/systemd1",
3316 "org.freedesktop.systemd1.Manager",
3320 DBUS_TYPE_STRING, &n,
3321 DBUS_TYPE_BOOLEAN, &cleanup,
3326 if (!dbus_message_get_args(reply, &error,
3327 DBUS_TYPE_OBJECT_PATH, &path,
3328 DBUS_TYPE_INVALID)) {
3329 log_error("Failed to parse reply: %s", bus_error_message(&error));
3330 dbus_error_free(&error);
3334 dbus_message_unref(reply);
3337 r = bus_method_call_with_reply (
3339 "org.freedesktop.systemd1",
3341 "org.freedesktop.DBus.Properties",
3345 DBUS_TYPE_STRING, &interface,
3346 DBUS_TYPE_STRING, &property,
3351 if (!dbus_message_iter_init(reply, &iter) ||
3352 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3353 log_error("Failed to parse reply.");
3357 dbus_message_iter_recurse(&iter, &sub);
3359 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
3360 log_error("Failed to parse reply.");
3364 dbus_message_iter_get_basic(&sub, &id);
3372 static int delete_snapshot(DBusConnection *bus, char **args) {
3377 STRV_FOREACH(name, args+1) {
3378 _cleanup_free_ char *n = NULL;
3381 n = snapshot_name_mangle(*name);
3385 r = bus_method_call_with_reply(
3387 "org.freedesktop.systemd1",
3388 "/org/freedesktop/systemd1",
3389 "org.freedesktop.systemd1.Manager",
3393 DBUS_TYPE_STRING, &n,
3402 static int daemon_reload(DBusConnection *bus, char **args) {
3407 if (arg_action == ACTION_RELOAD)
3409 else if (arg_action == ACTION_REEXEC)
3410 method = "Reexecute";
3412 assert(arg_action == ACTION_SYSTEMCTL);
3415 streq(args[0], "clear-jobs") ||
3416 streq(args[0], "cancel") ? "ClearJobs" :
3417 streq(args[0], "daemon-reexec") ? "Reexecute" :
3418 streq(args[0], "reset-failed") ? "ResetFailed" :
3419 streq(args[0], "halt") ? "Halt" :
3420 streq(args[0], "poweroff") ? "PowerOff" :
3421 streq(args[0], "reboot") ? "Reboot" :
3422 streq(args[0], "kexec") ? "KExec" :
3423 streq(args[0], "exit") ? "Exit" :
3424 /* "daemon-reload" */ "Reload";
3427 r = bus_method_call_with_reply(
3429 "org.freedesktop.systemd1",
3430 "/org/freedesktop/systemd1",
3431 "org.freedesktop.systemd1.Manager",
3437 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
3438 /* There's always a fallback possible for
3439 * legacy actions. */
3441 else if (r == -ETIMEDOUT && streq(method, "Reexecute"))
3442 /* On reexecution, we expect a disconnect, not
3446 log_error("Failed to issue method call: %s", bus_error_message(&error));
3448 dbus_error_free(&error);
3452 static int reset_failed(DBusConnection *bus, char **args) {
3456 if (strv_length(args) <= 1)
3457 return daemon_reload(bus, args);
3459 STRV_FOREACH(name, args+1) {
3460 _cleanup_free_ char *n;
3462 n = unit_name_mangle(*name);
3466 r = bus_method_call_with_reply(
3468 "org.freedesktop.systemd1",
3469 "/org/freedesktop/systemd1",
3470 "org.freedesktop.systemd1.Manager",
3474 DBUS_TYPE_STRING, &n,
3483 static int show_enviroment(DBusConnection *bus, char **args) {
3484 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3485 DBusMessageIter iter, sub, sub2;
3488 *interface = "org.freedesktop.systemd1.Manager",
3489 *property = "Environment";
3491 pager_open_if_enabled();
3493 r = bus_method_call_with_reply(
3495 "org.freedesktop.systemd1",
3496 "/org/freedesktop/systemd1",
3497 "org.freedesktop.DBus.Properties",
3501 DBUS_TYPE_STRING, &interface,
3502 DBUS_TYPE_STRING, &property,
3507 if (!dbus_message_iter_init(reply, &iter) ||
3508 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3509 log_error("Failed to parse reply.");
3513 dbus_message_iter_recurse(&iter, &sub);
3515 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_ARRAY ||
3516 dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_STRING) {
3517 log_error("Failed to parse reply.");
3521 dbus_message_iter_recurse(&sub, &sub2);
3523 while (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_INVALID) {
3526 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
3527 log_error("Failed to parse reply.");
3531 dbus_message_iter_get_basic(&sub2, &text);
3534 dbus_message_iter_next(&sub2);
3540 static int switch_root(DBusConnection *bus, char **args) {
3543 _cleanup_free_ char *init = NULL;
3545 l = strv_length(args);
3546 if (l < 2 || l > 3) {
3547 log_error("Wrong number of arguments.");
3554 init = strdup(args[2]);
3556 parse_env_file("/proc/cmdline", WHITESPACE,
3566 log_debug("switching root - root: %s; init: %s", root, init);
3568 return bus_method_call_with_reply(
3570 "org.freedesktop.systemd1",
3571 "/org/freedesktop/systemd1",
3572 "org.freedesktop.systemd1.Manager",
3576 DBUS_TYPE_STRING, &root,
3577 DBUS_TYPE_STRING, &init,
3581 static int set_environment(DBusConnection *bus, char **args) {
3582 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
3585 DBusMessageIter iter;
3591 dbus_error_init(&error);
3593 method = streq(args[0], "set-environment")
3595 : "UnsetEnvironment";
3597 m = dbus_message_new_method_call(
3598 "org.freedesktop.systemd1",
3599 "/org/freedesktop/systemd1",
3600 "org.freedesktop.systemd1.Manager",
3605 dbus_message_iter_init_append(m, &iter);
3607 r = bus_append_strv_iter(&iter, args + 1);
3611 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3613 log_error("Failed to issue method call: %s", bus_error_message(&error));
3614 dbus_error_free(&error);
3621 static int enable_sysv_units(char **args) {
3624 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
3625 const char *verb = args[0];
3626 unsigned f = 1, t = 1;
3629 if (arg_scope != UNIT_FILE_SYSTEM)
3632 if (!streq(verb, "enable") &&
3633 !streq(verb, "disable") &&
3634 !streq(verb, "is-enabled"))
3637 /* Processes all SysV units, and reshuffles the array so that
3638 * afterwards only the native units remain */
3641 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, NULL, NULL, NULL);
3646 for (f = 1; args[f]; f++) {
3649 bool found_native = false, found_sysv;
3651 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
3652 char **k, *l, *q = NULL;
3659 if (!endswith(name, ".service"))
3662 if (path_is_absolute(name))
3665 STRV_FOREACH(k, paths.unit_path) {
3668 if (!isempty(arg_root))
3669 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
3671 asprintf(&p, "%s/%s", *k, name);
3678 found_native = access(p, F_OK) >= 0;
3689 if (!isempty(arg_root))
3690 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
3692 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
3698 p[strlen(p) - sizeof(".service") + 1] = 0;
3699 found_sysv = access(p, F_OK) >= 0;
3706 /* Mark this entry, so that we don't try enabling it as native unit */
3707 args[f] = (char*) "";
3709 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
3711 if (!isempty(arg_root))
3712 argv[c++] = q = strappend("--root=", arg_root);
3714 argv[c++] = path_get_file_name(p);
3716 streq(verb, "enable") ? "on" :
3717 streq(verb, "disable") ? "off" : "--level=5";
3720 l = strv_join((char**)argv, " ");
3728 log_info("Executing %s", l);
3733 log_error("Failed to fork: %m");
3738 } else if (pid == 0) {
3741 execv(argv[0], (char**) argv);
3742 _exit(EXIT_FAILURE);
3748 j = wait_for_terminate(pid, &status);
3750 log_error("Failed to wait for child: %s", strerror(-r));
3755 if (status.si_code == CLD_EXITED) {
3756 if (streq(verb, "is-enabled")) {
3757 if (status.si_status == 0) {
3766 } else if (status.si_status != 0) {
3777 lookup_paths_free(&paths);
3779 /* Drop all SysV units */
3780 for (f = 1, t = 1; args[f]; f++) {
3782 if (isempty(args[f]))
3785 args[t++] = args[f];
3794 static int mangle_names(char **original_names, char ***mangled_names) {
3795 char **i, **l, **name;
3797 l = new(char*, strv_length(original_names) + 1);
3802 STRV_FOREACH(name, original_names) {
3804 /* When enabling units qualified path names are OK,
3805 * too, hence allow them explicitly. */
3810 *i = unit_name_mangle(*name);
3826 static int enable_unit(DBusConnection *bus, char **args) {
3827 const char *verb = args[0];
3828 UnitFileChange *changes = NULL;
3829 unsigned n_changes = 0, i;
3830 int carries_install_info = -1;
3831 DBusMessage _cleanup_dbus_message_unref_ *m = NULL, *reply = NULL;
3833 DBusError _cleanup_dbus_error_free_ error;
3834 char _cleanup_strv_free_ **mangled_names = NULL;
3836 dbus_error_init(&error);
3838 r = enable_sysv_units(args);
3845 if (!bus || avoid_bus()) {
3846 if (streq(verb, "enable")) {
3847 r = unit_file_enable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3848 carries_install_info = r;
3849 } else if (streq(verb, "disable"))
3850 r = unit_file_disable(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3851 else if (streq(verb, "reenable")) {
3852 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3853 carries_install_info = r;
3854 } else if (streq(verb, "link"))
3855 r = unit_file_link(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3856 else if (streq(verb, "preset")) {
3857 r = unit_file_preset(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3858 carries_install_info = r;
3859 } else if (streq(verb, "mask"))
3860 r = unit_file_mask(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3861 else if (streq(verb, "unmask"))
3862 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3864 assert_not_reached("Unknown verb");
3867 log_error("Operation failed: %s", strerror(-r));
3872 for (i = 0; i < n_changes; i++) {
3873 if (changes[i].type == UNIT_FILE_SYMLINK)
3874 log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
3876 log_info("rm '%s'", changes[i].path);
3883 bool send_force = true, expect_carries_install_info = false;
3885 DBusMessageIter iter, sub, sub2;
3887 if (streq(verb, "enable")) {
3888 method = "EnableUnitFiles";
3889 expect_carries_install_info = true;
3890 } else if (streq(verb, "disable")) {
3891 method = "DisableUnitFiles";
3893 } else if (streq(verb, "reenable")) {
3894 method = "ReenableUnitFiles";
3895 expect_carries_install_info = true;
3896 } else if (streq(verb, "link"))
3897 method = "LinkUnitFiles";
3898 else if (streq(verb, "preset")) {
3899 method = "PresetUnitFiles";
3900 expect_carries_install_info = true;
3901 } else if (streq(verb, "mask"))
3902 method = "MaskUnitFiles";
3903 else if (streq(verb, "unmask")) {
3904 method = "UnmaskUnitFiles";
3907 assert_not_reached("Unknown verb");
3909 m = dbus_message_new_method_call(
3910 "org.freedesktop.systemd1",
3911 "/org/freedesktop/systemd1",
3912 "org.freedesktop.systemd1.Manager",
3919 dbus_message_iter_init_append(m, &iter);
3921 r = mangle_names(args+1, &mangled_names);
3925 r = bus_append_strv_iter(&iter, mangled_names);
3927 log_error("Failed to append unit files.");
3932 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &a)) {
3933 log_error("Failed to append runtime boolean.");
3941 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b)) {
3942 log_error("Failed to append force boolean.");
3948 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3950 log_error("Failed to issue method call: %s", bus_error_message(&error));
3955 if (!dbus_message_iter_init(reply, &iter)) {
3956 log_error("Failed to initialize iterator.");
3960 if (expect_carries_install_info) {
3961 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &b, true);
3963 log_error("Failed to parse reply.");
3967 carries_install_info = b;
3970 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3971 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
3972 log_error("Failed to parse reply.");
3977 dbus_message_iter_recurse(&iter, &sub);
3978 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
3979 const char *type, *path, *source;
3981 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
3982 log_error("Failed to parse reply.");
3987 dbus_message_iter_recurse(&sub, &sub2);
3989 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
3990 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
3991 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &source, false) < 0) {
3992 log_error("Failed to parse reply.");
3998 if (streq(type, "symlink"))
3999 log_info("ln -s '%s' '%s'", source, path);
4001 log_info("rm '%s'", path);
4004 dbus_message_iter_next(&sub);
4007 /* Try to reload if enabeld */
4009 r = daemon_reload(bus, args);
4012 if (carries_install_info == 0)
4014 "The unit files have no [Install] section. They are not meant to be enabled\n"
4015 "using systemctl.\n"
4016 "Possible reasons for having this kind of units are:\n"
4017 "1) A unit may be statically enabled by being symlinked from another unit's\n"
4018 " .wants/ or .requires/ directory.\n"
4019 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
4020 " a requirement dependency on it.\n"
4021 "3) A unit may be started when needed via activation (socket, path, timer,\n"
4022 " D-Bus, udev, scripted systemctl call, ...).\n");
4025 unit_file_changes_free(changes, n_changes);
4030 static int unit_is_enabled(DBusConnection *bus, char **args) {
4031 DBusError _cleanup_dbus_error_free_ error;
4033 DBusMessage _cleanup_dbus_message_unref_ *reply = NULL;
4037 dbus_error_init(&error);
4039 r = enable_sysv_units(args);
4045 if (!bus || avoid_bus()) {
4047 STRV_FOREACH(name, args+1) {
4048 UnitFileState state;
4050 state = unit_file_get_state(arg_scope, arg_root, *name);
4054 if (state == UNIT_FILE_ENABLED ||
4055 state == UNIT_FILE_ENABLED_RUNTIME ||
4056 state == UNIT_FILE_STATIC)
4060 puts(unit_file_state_to_string(state));
4064 STRV_FOREACH(name, args+1) {
4067 r = bus_method_call_with_reply (
4069 "org.freedesktop.systemd1",
4070 "/org/freedesktop/systemd1",
4071 "org.freedesktop.systemd1.Manager",
4075 DBUS_TYPE_STRING, name,
4080 if (!dbus_message_get_args(reply, &error,
4081 DBUS_TYPE_STRING, &s,
4082 DBUS_TYPE_INVALID)) {
4083 log_error("Failed to parse reply: %s", bus_error_message(&error));
4087 dbus_message_unref(reply);
4090 if (streq(s, "enabled") ||
4091 streq(s, "enabled-runtime") ||
4100 return enabled ? 0 : 1;
4103 static int systemctl_help(void) {
4105 pager_open_if_enabled();
4107 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
4108 "Query or send control commands to the systemd manager.\n\n"
4109 " -h --help Show this help\n"
4110 " --version Show package version\n"
4111 " -t --type=TYPE List only units of a particular type\n"
4112 " -p --property=NAME Show only properties by this name\n"
4113 " -a --all Show all units/properties, including dead/empty ones\n"
4114 " --failed Show only failed units\n"
4115 " --full Don't ellipsize unit names on output\n"
4116 " --fail When queueing a new job, fail if conflicting jobs are\n"
4118 " --ignore-dependencies\n"
4119 " When queueing a new job, ignore all its dependencies\n"
4120 " -i --ignore-inhibitors\n"
4121 " When shutting down or sleeping, ignore inhibitors\n"
4122 " --kill-who=WHO Who to send signal to\n"
4123 " -s --signal=SIGNAL Which signal to send\n"
4124 " -H --host=[USER@]HOST\n"
4125 " Show information for remote host\n"
4126 " -P --privileged Acquire privileges before execution\n"
4127 " -q --quiet Suppress output\n"
4128 " --no-block Do not wait until operation finished\n"
4129 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4130 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
4132 " --no-legend Do not print a legend (column headers and hints)\n"
4133 " --no-pager Do not pipe output into a pager\n"
4134 " --no-ask-password\n"
4135 " Do not ask for system passwords\n"
4136 " --system Connect to system manager\n"
4137 " --user Connect to user service manager\n"
4138 " --global Enable/disable unit files globally\n"
4139 " -f --force When enabling unit files, override existing symlinks\n"
4140 " When shutting down, execute action immediately\n"
4141 " --root=PATH Enable unit files in the specified root directory\n"
4142 " --runtime Enable unit files only temporarily until next reboot\n"
4143 " -n --lines=INTEGER Journal entries to show\n"
4144 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
4145 " verbose, export, json, json-pretty, json-sse, cat)\n\n"
4147 " list-units List loaded units\n"
4148 " start [NAME...] Start (activate) one or more units\n"
4149 " stop [NAME...] Stop (deactivate) one or more units\n"
4150 " reload [NAME...] Reload one or more units\n"
4151 " restart [NAME...] Start or restart one or more units\n"
4152 " try-restart [NAME...] Restart one or more units if active\n"
4153 " reload-or-restart [NAME...] Reload one or more units if possible,\n"
4154 " otherwise start or restart\n"
4155 " reload-or-try-restart [NAME...] Reload one or more units if possible,\n"
4156 " otherwise restart if active\n"
4157 " isolate [NAME] Start one unit and stop all others\n"
4158 " kill [NAME...] Send signal to processes of a unit\n"
4159 " is-active [NAME...] Check whether units are active\n"
4160 " is-failed [NAME...] Check whether units are failed\n"
4161 " status [NAME...|PID...] Show runtime status of one or more units\n"
4162 " show [NAME...|JOB...] Show properties of one or more\n"
4163 " units/jobs or the manager\n"
4164 " help [NAME...|PID...] Show manual for one or more units\n"
4165 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
4167 " get-cgroup-attr [NAME] [ATTR] ...\n"
4168 " Get control group attrubute\n"
4169 " set-cgroup-attr [NAME] [ATTR] [VALUE] ...\n"
4170 " Set control group attribute\n"
4171 " unset-cgroup-attr [NAME] [ATTR...]\n"
4172 " Unset control group attribute\n"
4173 " set-cgroup [NAME] [CGROUP...] Add unit to a control group\n"
4174 " unset-cgroup [NAME] [CGROUP...] Remove unit from a control group\n"
4175 " load [NAME...] Load one or more units\n"
4176 " list-dependencies [NAME] Recursively show units which are required\n"
4177 " or wanted by this unit\n\n"
4178 "Unit File Commands:\n"
4179 " list-unit-files List installed unit files\n"
4180 " enable [NAME...] Enable one or more unit files\n"
4181 " disable [NAME...] Disable one or more unit files\n"
4182 " reenable [NAME...] Reenable one or more unit files\n"
4183 " preset [NAME...] Enable/disable one or more unit files\n"
4184 " based on preset configuration\n"
4185 " mask [NAME...] Mask one or more units\n"
4186 " unmask [NAME...] Unmask one or more units\n"
4187 " link [PATH...] Link one or more units files into\n"
4188 " the search path\n"
4189 " is-enabled [NAME...] Check whether unit files are enabled\n\n"
4191 " list-jobs List jobs\n"
4192 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
4193 "Status Commands:\n"
4194 " dump Dump server status\n"
4195 "Snapshot Commands:\n"
4196 " snapshot [NAME] Create a snapshot\n"
4197 " delete [NAME...] Remove one or more snapshots\n\n"
4198 "Environment Commands:\n"
4199 " show-environment Dump environment\n"
4200 " set-environment [NAME=VALUE...] Set one or more environment variables\n"
4201 " unset-environment [NAME...] Unset one or more environment variables\n\n"
4202 "Manager Lifecycle Commands:\n"
4203 " daemon-reload Reload systemd manager configuration\n"
4204 " daemon-reexec Reexecute systemd manager\n\n"
4205 "System Commands:\n"
4206 " default Enter system default mode\n"
4207 " rescue Enter system rescue mode\n"
4208 " emergency Enter system emergency mode\n"
4209 " halt Shut down and halt the system\n"
4210 " poweroff Shut down and power-off the system\n"
4211 " reboot Shut down and reboot the system\n"
4212 " kexec Shut down and reboot the system with kexec\n"
4213 " exit Request user instance exit\n"
4214 " switch-root [ROOT] [INIT] Change to a different root file system\n"
4215 " suspend Suspend the system\n"
4216 " hibernate Hibernate the system\n"
4217 " hybrid-sleep Hibernate and suspend the system\n",
4218 program_invocation_short_name);
4223 static int halt_help(void) {
4225 printf("%s [OPTIONS...]\n\n"
4226 "%s the system.\n\n"
4227 " --help Show this help\n"
4228 " --halt Halt the machine\n"
4229 " -p --poweroff Switch off the machine\n"
4230 " --reboot Reboot the machine\n"
4231 " -f --force Force immediate halt/power-off/reboot\n"
4232 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
4233 " -d --no-wtmp Don't write wtmp record\n"
4234 " --no-wall Don't send wall message before halt/power-off/reboot\n",
4235 program_invocation_short_name,
4236 arg_action == ACTION_REBOOT ? "Reboot" :
4237 arg_action == ACTION_POWEROFF ? "Power off" :
4243 static int shutdown_help(void) {
4245 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
4246 "Shut down the system.\n\n"
4247 " --help Show this help\n"
4248 " -H --halt Halt the machine\n"
4249 " -P --poweroff Power-off the machine\n"
4250 " -r --reboot Reboot the machine\n"
4251 " -h Equivalent to --poweroff, overridden by --halt\n"
4252 " -k Don't halt/power-off/reboot, just send warnings\n"
4253 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4254 " -c Cancel a pending shutdown\n",
4255 program_invocation_short_name);
4260 static int telinit_help(void) {
4262 printf("%s [OPTIONS...] {COMMAND}\n\n"
4263 "Send control commands to the init daemon.\n\n"
4264 " --help Show this help\n"
4265 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
4267 " 0 Power-off the machine\n"
4268 " 6 Reboot the machine\n"
4269 " 2, 3, 4, 5 Start runlevelX.target unit\n"
4270 " 1, s, S Enter rescue mode\n"
4271 " q, Q Reload init daemon configuration\n"
4272 " u, U Reexecute init daemon\n",
4273 program_invocation_short_name);
4278 static int runlevel_help(void) {
4280 printf("%s [OPTIONS...]\n\n"
4281 "Prints the previous and current runlevel of the init system.\n\n"
4282 " --help Show this help\n",
4283 program_invocation_short_name);
4288 static int help_types(void) {
4291 puts("Available unit types:");
4292 for(i = UNIT_SERVICE; i < _UNIT_TYPE_MAX; i++)
4293 if (unit_type_table[i])
4294 puts(unit_type_table[i]);
4296 puts("\nAvailable unit load states: ");
4297 for(i = UNIT_STUB; i < _UNIT_LOAD_STATE_MAX; i++)
4298 if (unit_type_table[i])
4299 puts(unit_load_state_table[i]);
4304 static int systemctl_parse_argv(int argc, char *argv[]) {
4308 ARG_IGNORE_DEPENDENCIES,
4321 ARG_NO_ASK_PASSWORD,
4327 static const struct option options[] = {
4328 { "help", no_argument, NULL, 'h' },
4329 { "version", no_argument, NULL, ARG_VERSION },
4330 { "type", required_argument, NULL, 't' },
4331 { "property", required_argument, NULL, 'p' },
4332 { "all", no_argument, NULL, 'a' },
4333 { "failed", no_argument, NULL, ARG_FAILED },
4334 { "full", no_argument, NULL, ARG_FULL },
4335 { "fail", no_argument, NULL, ARG_FAIL },
4336 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
4337 { "ignore-inhibitors", no_argument, NULL, 'i' },
4338 { "user", no_argument, NULL, ARG_USER },
4339 { "system", no_argument, NULL, ARG_SYSTEM },
4340 { "global", no_argument, NULL, ARG_GLOBAL },
4341 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
4342 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
4343 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
4344 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4345 { "quiet", no_argument, NULL, 'q' },
4346 { "root", required_argument, NULL, ARG_ROOT },
4347 { "force", no_argument, NULL, ARG_FORCE },
4348 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
4349 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
4350 { "signal", required_argument, NULL, 's' },
4351 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
4352 { "host", required_argument, NULL, 'H' },
4353 { "privileged",no_argument, NULL, 'P' },
4354 { "runtime", no_argument, NULL, ARG_RUNTIME },
4355 { "lines", required_argument, NULL, 'n' },
4356 { "output", required_argument, NULL, 'o' },
4357 { NULL, 0, NULL, 0 }
4365 while ((c = getopt_long(argc, argv, "ht:p:aqfs:H:Pn:o:i", options, NULL)) >= 0) {
4374 puts(PACKAGE_STRING);
4375 puts(SYSTEMD_FEATURES);
4379 if (streq(optarg, "help")) {
4384 if (unit_type_from_string(optarg) >= 0) {
4388 if (unit_load_state_from_string(optarg) >= 0) {
4389 arg_load_state = optarg;
4392 log_error("Unkown unit type or load state '%s'.",
4394 log_info("Use -t help to see a list of allowed values.");
4399 /* Make sure that if the empty property list
4400 was specified, we won't show any properties. */
4401 const char *source = isempty(optarg) ? " " : optarg;
4403 FOREACH_WORD_SEPARATOR(word, size, source, ",", state) {
4404 char _cleanup_free_ *prop;
4407 prop = strndup(word, size);
4411 tmp = strv_append(arg_property, prop);
4415 strv_free(arg_property);
4419 /* If the user asked for a particular
4420 * property, show it to him, even if it is
4432 arg_job_mode = "fail";
4435 case ARG_IGNORE_DEPENDENCIES:
4436 arg_job_mode = "ignore-dependencies";
4440 arg_scope = UNIT_FILE_USER;
4444 arg_scope = UNIT_FILE_SYSTEM;
4448 arg_scope = UNIT_FILE_GLOBAL;
4452 arg_no_block = true;
4456 arg_no_legend = true;
4460 arg_no_pager = true;
4492 arg_no_reload = true;
4496 arg_kill_who = optarg;
4500 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
4501 log_error("Failed to parse signal string %s.", optarg);
4506 case ARG_NO_ASK_PASSWORD:
4507 arg_ask_password = false;
4511 arg_transport = TRANSPORT_POLKIT;
4515 arg_transport = TRANSPORT_SSH;
4524 if (safe_atou(optarg, &arg_lines) < 0) {
4525 log_error("Failed to parse lines '%s'", optarg);
4531 arg_output = output_mode_from_string(optarg);
4532 if (arg_output < 0) {
4533 log_error("Unknown output '%s'.", optarg);
4539 arg_ignore_inhibitors = true;
4546 log_error("Unknown option code '%c'.", c);
4551 if (arg_transport != TRANSPORT_NORMAL && arg_scope != UNIT_FILE_SYSTEM) {
4552 log_error("Cannot access user instance remotely.");
4559 static int halt_parse_argv(int argc, char *argv[]) {
4568 static const struct option options[] = {
4569 { "help", no_argument, NULL, ARG_HELP },
4570 { "halt", no_argument, NULL, ARG_HALT },
4571 { "poweroff", no_argument, NULL, 'p' },
4572 { "reboot", no_argument, NULL, ARG_REBOOT },
4573 { "force", no_argument, NULL, 'f' },
4574 { "wtmp-only", no_argument, NULL, 'w' },
4575 { "no-wtmp", no_argument, NULL, 'd' },
4576 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4577 { NULL, 0, NULL, 0 }
4585 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
4586 if (runlevel == '0' || runlevel == '6')
4589 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
4597 arg_action = ACTION_HALT;
4601 if (arg_action != ACTION_REBOOT)
4602 arg_action = ACTION_POWEROFF;
4606 arg_action = ACTION_REBOOT;
4628 /* Compatibility nops */
4635 log_error("Unknown option code '%c'.", c);
4640 if (optind < argc) {
4641 log_error("Too many arguments.");
4648 static int parse_time_spec(const char *t, usec_t *_u) {
4652 if (streq(t, "now"))
4654 else if (!strchr(t, ':')) {
4657 if (safe_atou64(t, &u) < 0)
4660 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
4669 hour = strtol(t, &e, 10);
4670 if (errno != 0 || *e != ':' || hour < 0 || hour > 23)
4673 minute = strtol(e+1, &e, 10);
4674 if (errno != 0 || *e != 0 || minute < 0 || minute > 59)
4677 n = now(CLOCK_REALTIME);
4678 s = (time_t) (n / USEC_PER_SEC);
4681 assert_se(localtime_r(&s, &tm));
4683 tm.tm_hour = (int) hour;
4684 tm.tm_min = (int) minute;
4687 assert_se(s = mktime(&tm));
4689 *_u = (usec_t) s * USEC_PER_SEC;
4692 *_u += USEC_PER_DAY;
4698 static int shutdown_parse_argv(int argc, char *argv[]) {
4705 static const struct option options[] = {
4706 { "help", no_argument, NULL, ARG_HELP },
4707 { "halt", no_argument, NULL, 'H' },
4708 { "poweroff", no_argument, NULL, 'P' },
4709 { "reboot", no_argument, NULL, 'r' },
4710 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
4711 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4712 { NULL, 0, NULL, 0 }
4720 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
4728 arg_action = ACTION_HALT;
4732 arg_action = ACTION_POWEROFF;
4737 arg_action = ACTION_KEXEC;
4739 arg_action = ACTION_REBOOT;
4743 arg_action = ACTION_KEXEC;
4747 if (arg_action != ACTION_HALT)
4748 arg_action = ACTION_POWEROFF;
4761 /* Compatibility nops */
4765 arg_action = ACTION_CANCEL_SHUTDOWN;
4772 log_error("Unknown option code '%c'.", c);
4777 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
4778 r = parse_time_spec(argv[optind], &arg_when);
4780 log_error("Failed to parse time specification: %s", argv[optind]);
4784 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
4786 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
4787 /* No time argument for shutdown cancel */
4788 arg_wall = argv + optind;
4789 else if (argc > optind + 1)
4790 /* We skip the time argument */
4791 arg_wall = argv + optind + 1;
4798 static int telinit_parse_argv(int argc, char *argv[]) {
4805 static const struct option options[] = {
4806 { "help", no_argument, NULL, ARG_HELP },
4807 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4808 { NULL, 0, NULL, 0 }
4811 static const struct {
4815 { '0', ACTION_POWEROFF },
4816 { '6', ACTION_REBOOT },
4817 { '1', ACTION_RESCUE },
4818 { '2', ACTION_RUNLEVEL2 },
4819 { '3', ACTION_RUNLEVEL3 },
4820 { '4', ACTION_RUNLEVEL4 },
4821 { '5', ACTION_RUNLEVEL5 },
4822 { 's', ACTION_RESCUE },
4823 { 'S', ACTION_RESCUE },
4824 { 'q', ACTION_RELOAD },
4825 { 'Q', ACTION_RELOAD },
4826 { 'u', ACTION_REEXEC },
4827 { 'U', ACTION_REEXEC }
4836 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4851 log_error("Unknown option code '%c'.", c);
4856 if (optind >= argc) {
4861 if (optind + 1 < argc) {
4862 log_error("Too many arguments.");
4866 if (strlen(argv[optind]) != 1) {
4867 log_error("Expected single character argument.");
4871 for (i = 0; i < ELEMENTSOF(table); i++)
4872 if (table[i].from == argv[optind][0])
4875 if (i >= ELEMENTSOF(table)) {
4876 log_error("Unknown command '%s'.", argv[optind]);
4880 arg_action = table[i].to;
4887 static int runlevel_parse_argv(int argc, char *argv[]) {
4893 static const struct option options[] = {
4894 { "help", no_argument, NULL, ARG_HELP },
4895 { NULL, 0, NULL, 0 }
4903 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4914 log_error("Unknown option code '%c'.", c);
4919 if (optind < argc) {
4920 log_error("Too many arguments.");
4927 static int parse_argv(int argc, char *argv[]) {
4931 if (program_invocation_short_name) {
4933 if (strstr(program_invocation_short_name, "halt")) {
4934 arg_action = ACTION_HALT;
4935 return halt_parse_argv(argc, argv);
4936 } else if (strstr(program_invocation_short_name, "poweroff")) {
4937 arg_action = ACTION_POWEROFF;
4938 return halt_parse_argv(argc, argv);
4939 } else if (strstr(program_invocation_short_name, "reboot")) {
4941 arg_action = ACTION_KEXEC;
4943 arg_action = ACTION_REBOOT;
4944 return halt_parse_argv(argc, argv);
4945 } else if (strstr(program_invocation_short_name, "shutdown")) {
4946 arg_action = ACTION_POWEROFF;
4947 return shutdown_parse_argv(argc, argv);
4948 } else if (strstr(program_invocation_short_name, "init")) {
4950 if (sd_booted() > 0) {
4951 arg_action = ACTION_INVALID;
4952 return telinit_parse_argv(argc, argv);
4954 /* Hmm, so some other init system is
4955 * running, we need to forward this
4956 * request to it. For now we simply
4957 * guess that it is Upstart. */
4959 execv("/lib/upstart/telinit", argv);
4961 log_error("Couldn't find an alternative telinit implementation to spawn.");
4965 } else if (strstr(program_invocation_short_name, "runlevel")) {
4966 arg_action = ACTION_RUNLEVEL;
4967 return runlevel_parse_argv(argc, argv);
4971 arg_action = ACTION_SYSTEMCTL;
4972 return systemctl_parse_argv(argc, argv);
4975 static int action_to_runlevel(void) {
4977 static const char table[_ACTION_MAX] = {
4978 [ACTION_HALT] = '0',
4979 [ACTION_POWEROFF] = '0',
4980 [ACTION_REBOOT] = '6',
4981 [ACTION_RUNLEVEL2] = '2',
4982 [ACTION_RUNLEVEL3] = '3',
4983 [ACTION_RUNLEVEL4] = '4',
4984 [ACTION_RUNLEVEL5] = '5',
4985 [ACTION_RESCUE] = '1'
4988 assert(arg_action < _ACTION_MAX);
4990 return table[arg_action];
4993 static int talk_upstart(void) {
4994 DBusMessage _cleanup_dbus_message_unref_ *m = NULL, *reply = NULL;
4995 DBusError _cleanup_dbus_error_free_ error;
4996 int previous, rl, r;
4998 env1_buf[] = "RUNLEVEL=X",
4999 env2_buf[] = "PREVLEVEL=X";
5000 char *env1 = env1_buf, *env2 = env2_buf;
5001 const char *emit = "runlevel";
5002 dbus_bool_t b_false = FALSE;
5003 DBusMessageIter iter, sub;
5004 DBusConnection *bus;
5006 dbus_error_init(&error);
5008 if (!(rl = action_to_runlevel()))
5011 if (utmp_get_runlevel(&previous, NULL) < 0)
5014 if (!(bus = dbus_connection_open_private("unix:abstract=/com/ubuntu/upstart", &error))) {
5015 if (dbus_error_has_name(&error, DBUS_ERROR_NO_SERVER)) {
5020 log_error("Failed to connect to Upstart bus: %s", bus_error_message(&error));
5025 if ((r = bus_check_peercred(bus)) < 0) {
5026 log_error("Failed to verify owner of bus.");
5030 if (!(m = dbus_message_new_method_call(
5031 "com.ubuntu.Upstart",
5032 "/com/ubuntu/Upstart",
5033 "com.ubuntu.Upstart0_6",
5036 log_error("Could not allocate message.");
5041 dbus_message_iter_init_append(m, &iter);
5043 env1_buf[sizeof(env1_buf)-2] = rl;
5044 env2_buf[sizeof(env2_buf)-2] = previous;
5046 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &emit) ||
5047 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub) ||
5048 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env1) ||
5049 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env2) ||
5050 !dbus_message_iter_close_container(&iter, &sub) ||
5051 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b_false)) {
5052 log_error("Could not append arguments to message.");
5057 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
5059 if (bus_error_is_no_service(&error)) {
5064 log_error("Failed to issue method call: %s", bus_error_message(&error));
5073 dbus_connection_flush(bus);
5074 dbus_connection_close(bus);
5075 dbus_connection_unref(bus);
5081 static int talk_initctl(void) {
5082 struct init_request request;
5086 if (!(rl = action_to_runlevel()))
5090 request.magic = INIT_MAGIC;
5091 request.sleeptime = 0;
5092 request.cmd = INIT_CMD_RUNLVL;
5093 request.runlevel = rl;
5095 if ((fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY)) < 0) {
5097 if (errno == ENOENT)
5100 log_error("Failed to open "INIT_FIFO": %m");
5105 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
5106 close_nointr_nofail(fd);
5109 log_error("Failed to write to "INIT_FIFO": %m");
5110 return errno ? -errno : -EIO;
5116 static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
5118 static const struct {
5126 int (* const dispatch)(DBusConnection *bus, char **args);
5128 { "list-units", LESS, 1, list_units },
5129 { "list-unit-files", EQUAL, 1, list_unit_files },
5130 { "list-jobs", EQUAL, 1, list_jobs },
5131 { "clear-jobs", EQUAL, 1, daemon_reload },
5132 { "load", MORE, 2, load_unit },
5133 { "cancel", MORE, 2, cancel_job },
5134 { "start", MORE, 2, start_unit },
5135 { "stop", MORE, 2, start_unit },
5136 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5137 { "reload", MORE, 2, start_unit },
5138 { "restart", MORE, 2, start_unit },
5139 { "try-restart", MORE, 2, start_unit },
5140 { "reload-or-restart", MORE, 2, start_unit },
5141 { "reload-or-try-restart", MORE, 2, start_unit },
5142 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
5143 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5144 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
5145 { "isolate", EQUAL, 2, start_unit },
5146 { "set-cgroup", MORE, 2, set_cgroup },
5147 { "unset-cgroup", MORE, 2, set_cgroup },
5148 { "get-cgroup-attr", MORE, 2, get_cgroup_attr },
5149 { "set-cgroup-attr", MORE, 2, set_cgroup_attr },
5150 { "unset-cgroup-attr", MORE, 2, set_cgroup },
5151 { "kill", MORE, 2, kill_unit },
5152 { "is-active", MORE, 2, check_unit_active },
5153 { "check", MORE, 2, check_unit_active },
5154 { "is-failed", MORE, 2, check_unit_failed },
5155 { "show", MORE, 1, show },
5156 { "status", MORE, 1, show },
5157 { "help", MORE, 2, show },
5158 { "dump", EQUAL, 1, dump },
5159 { "snapshot", LESS, 2, snapshot },
5160 { "delete", MORE, 2, delete_snapshot },
5161 { "daemon-reload", EQUAL, 1, daemon_reload },
5162 { "daemon-reexec", EQUAL, 1, daemon_reload },
5163 { "show-environment", EQUAL, 1, show_enviroment },
5164 { "set-environment", MORE, 2, set_environment },
5165 { "unset-environment", MORE, 2, set_environment },
5166 { "halt", EQUAL, 1, start_special },
5167 { "poweroff", EQUAL, 1, start_special },
5168 { "reboot", EQUAL, 1, start_special },
5169 { "kexec", EQUAL, 1, start_special },
5170 { "suspend", EQUAL, 1, start_special },
5171 { "hibernate", EQUAL, 1, start_special },
5172 { "hybrid-sleep", EQUAL, 1, start_special },
5173 { "default", EQUAL, 1, start_special },
5174 { "rescue", EQUAL, 1, start_special },
5175 { "emergency", EQUAL, 1, start_special },
5176 { "exit", EQUAL, 1, start_special },
5177 { "reset-failed", MORE, 1, reset_failed },
5178 { "enable", MORE, 2, enable_unit },
5179 { "disable", MORE, 2, enable_unit },
5180 { "is-enabled", MORE, 2, unit_is_enabled },
5181 { "reenable", MORE, 2, enable_unit },
5182 { "preset", MORE, 2, enable_unit },
5183 { "mask", MORE, 2, enable_unit },
5184 { "unmask", MORE, 2, enable_unit },
5185 { "link", MORE, 2, enable_unit },
5186 { "switch-root", MORE, 2, switch_root },
5187 { "list-dependencies", LESS, 2, list_dependencies },
5197 left = argc - optind;
5200 /* Special rule: no arguments means "list-units" */
5203 if (streq(argv[optind], "help") && !argv[optind+1]) {
5204 log_error("This command expects one or more "
5205 "unit names. Did you mean --help?");
5209 for (i = 0; i < ELEMENTSOF(verbs); i++)
5210 if (streq(argv[optind], verbs[i].verb))
5213 if (i >= ELEMENTSOF(verbs)) {
5214 log_error("Unknown operation '%s'.", argv[optind]);
5219 switch (verbs[i].argc_cmp) {
5222 if (left != verbs[i].argc) {
5223 log_error("Invalid number of arguments.");
5230 if (left < verbs[i].argc) {
5231 log_error("Too few arguments.");
5238 if (left > verbs[i].argc) {
5239 log_error("Too many arguments.");
5246 assert_not_reached("Unknown comparison operator.");
5249 /* Require a bus connection for all operations but
5251 if (!streq(verbs[i].verb, "enable") &&
5252 !streq(verbs[i].verb, "disable") &&
5253 !streq(verbs[i].verb, "is-enabled") &&
5254 !streq(verbs[i].verb, "list-unit-files") &&
5255 !streq(verbs[i].verb, "reenable") &&
5256 !streq(verbs[i].verb, "preset") &&
5257 !streq(verbs[i].verb, "mask") &&
5258 !streq(verbs[i].verb, "unmask") &&
5259 !streq(verbs[i].verb, "link")) {
5261 if (running_in_chroot() > 0) {
5262 log_info("Running in chroot, ignoring request.");
5266 if (((!streq(verbs[i].verb, "reboot") &&
5267 !streq(verbs[i].verb, "halt") &&
5268 !streq(verbs[i].verb, "poweroff")) || arg_force <= 0) && !bus) {
5269 log_error("Failed to get D-Bus connection: %s",
5270 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5276 if (!bus && !avoid_bus()) {
5277 log_error("Failed to get D-Bus connection: %s",
5278 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5283 return verbs[i].dispatch(bus, argv + optind);
5286 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
5287 int _cleanup_close_ fd;
5288 struct msghdr msghdr;
5289 struct iovec iovec[2];
5290 union sockaddr_union sockaddr;
5291 struct sd_shutdown_command c;
5293 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
5300 c.dry_run = dry_run;
5304 sockaddr.sa.sa_family = AF_UNIX;
5305 strncpy(sockaddr.un.sun_path, "/run/systemd/shutdownd", sizeof(sockaddr.un.sun_path));
5308 msghdr.msg_name = &sockaddr;
5309 msghdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + sizeof("/run/systemd/shutdownd") - 1;
5312 iovec[0].iov_base = (char*) &c;
5313 iovec[0].iov_len = offsetof(struct sd_shutdown_command, wall_message);
5315 if (isempty(message))
5316 msghdr.msg_iovlen = 1;
5318 iovec[1].iov_base = (char*) message;
5319 iovec[1].iov_len = strlen(message);
5320 msghdr.msg_iovlen = 2;
5322 msghdr.msg_iov = iovec;
5324 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0)
5330 static int reload_with_fallback(DBusConnection *bus) {
5333 /* First, try systemd via D-Bus. */
5334 if (daemon_reload(bus, NULL) >= 0)
5338 /* Nothing else worked, so let's try signals */
5339 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
5341 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
5342 log_error("kill() failed: %m");
5349 static int start_with_fallback(DBusConnection *bus) {
5352 /* First, try systemd via D-Bus. */
5353 if (start_unit(bus, NULL) >= 0)
5357 /* Hmm, talking to systemd via D-Bus didn't work. Then
5358 * let's try to talk to Upstart via D-Bus. */
5359 if (talk_upstart() > 0)
5362 /* Nothing else worked, so let's try
5364 if (talk_initctl() > 0)
5367 log_error("Failed to talk to init daemon.");
5371 warn_wall(arg_action);
5375 static _noreturn_ void halt_now(enum action a) {
5377 /* Make sure C-A-D is handled by the kernel from this
5379 reboot(RB_ENABLE_CAD);
5384 log_info("Halting.");
5385 reboot(RB_HALT_SYSTEM);
5388 case ACTION_POWEROFF:
5389 log_info("Powering off.");
5390 reboot(RB_POWER_OFF);
5394 log_info("Rebooting.");
5395 reboot(RB_AUTOBOOT);
5399 assert_not_reached("Unknown halt action.");
5402 assert_not_reached("Uh? This shouldn't happen.");
5405 static int halt_main(DBusConnection *bus) {
5408 r = check_inhibitors(bus, arg_action);
5412 if (geteuid() != 0) {
5413 /* Try logind if we are a normal user and no special
5414 * mode applies. Maybe PolicyKit allows us to shutdown
5417 if (arg_when <= 0 &&
5420 (arg_action == ACTION_POWEROFF ||
5421 arg_action == ACTION_REBOOT)) {
5422 r = reboot_with_logind(bus, arg_action);
5427 log_error("Must be root.");
5432 char _cleanup_free_ *m;
5434 m = strv_join(arg_wall, " ");
5435 r = send_shutdownd(arg_when,
5436 arg_action == ACTION_HALT ? 'H' :
5437 arg_action == ACTION_POWEROFF ? 'P' :
5438 arg_action == ACTION_KEXEC ? 'K' :
5445 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
5447 char date[FORMAT_TIMESTAMP_MAX];
5449 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
5450 format_timestamp(date, sizeof(date), arg_when));
5455 if (!arg_dry && !arg_force)
5456 return start_with_fallback(bus);
5459 if (sd_booted() > 0)
5460 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
5462 r = utmp_put_shutdown();
5464 log_warning("Failed to write utmp record: %s", strerror(-r));
5471 halt_now(arg_action);
5472 /* We should never reach this. */
5476 static int runlevel_main(void) {
5477 int r, runlevel, previous;
5479 r = utmp_get_runlevel(&runlevel, &previous);
5486 previous <= 0 ? 'N' : previous,
5487 runlevel <= 0 ? 'N' : runlevel);
5492 int main(int argc, char*argv[]) {
5493 int r, retval = EXIT_FAILURE;
5494 DBusConnection *bus = NULL;
5495 DBusError _cleanup_dbus_error_free_ error;
5497 dbus_error_init(&error);
5499 setlocale(LC_ALL, "");
5500 log_parse_environment();
5503 r = parse_argv(argc, argv);
5507 retval = EXIT_SUCCESS;
5511 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
5512 * let's shortcut this */
5513 if (arg_action == ACTION_RUNLEVEL) {
5514 r = runlevel_main();
5515 retval = r < 0 ? EXIT_FAILURE : r;
5519 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
5520 log_info("Running in chroot, ignoring request.");
5526 if (arg_transport == TRANSPORT_NORMAL)
5527 bus_connect(arg_scope == UNIT_FILE_SYSTEM ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &bus, &private_bus, &error);
5528 else if (arg_transport == TRANSPORT_POLKIT) {
5529 bus_connect_system_polkit(&bus, &error);
5530 private_bus = false;
5531 } else if (arg_transport == TRANSPORT_SSH) {
5532 bus_connect_system_ssh(NULL, arg_host, &bus, &error);
5533 private_bus = false;
5535 assert_not_reached("Uh, invalid transport...");
5538 switch (arg_action) {
5540 case ACTION_SYSTEMCTL:
5541 r = systemctl_main(bus, argc, argv, &error);
5545 case ACTION_POWEROFF:
5551 case ACTION_RUNLEVEL2:
5552 case ACTION_RUNLEVEL3:
5553 case ACTION_RUNLEVEL4:
5554 case ACTION_RUNLEVEL5:
5556 case ACTION_EMERGENCY:
5557 case ACTION_DEFAULT:
5558 r = start_with_fallback(bus);
5563 r = reload_with_fallback(bus);
5566 case ACTION_CANCEL_SHUTDOWN: {
5570 m = strv_join(arg_wall, " ");
5572 retval = EXIT_FAILURE;
5576 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
5578 log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r));
5583 case ACTION_INVALID:
5584 case ACTION_RUNLEVEL:
5586 assert_not_reached("Unknown action");
5589 retval = r < 0 ? EXIT_FAILURE : r;
5593 dbus_connection_flush(bus);
5594 dbus_connection_close(bus);
5595 dbus_connection_unref(bus);
5600 strv_free(arg_property);
5603 ask_password_agent_close();
5604 polkit_agent_close();