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 char **arg_types = NULL;
72 static char **arg_load_states = NULL;
73 static char **arg_properties = 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_types || ((dot = strrchr(u->id, '.')) &&
299 strv_find(arg_types, dot+1))) &&
300 (!arg_load_states || strv_find(arg_load_states, u->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, 25u);
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, 25u);
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, *on = "";
357 const char *on_active, *off_active, *off = "";
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 = on = ansi_highlight_red(true);
377 off_loaded = off = ansi_highlight_red(false);
379 on_loaded = off_loaded = "";
381 if (streq(u->active_state, "failed")) {
382 on_active = on = ansi_highlight_red(true);
383 off_active = off = ansi_highlight_red(false);
385 on_active = off_active = "";
387 e = arg_full ? NULL : ellipsize(u->id, id_len, 33);
389 printf("%s%-*s%s %s%-6s%s %s%-*s %-*s%s %-*s",
390 on, id_len, e ? e : u->id, off,
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, 16u);
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_types || ((dot = strrchr(u->path, '.')) && strv_find(arg_types, dot+1));
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, 25u);
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, 16u);
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(),20u);
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);
900 char *name, *type, *state;
903 static void list_jobs_print(struct job_info* jobs, size_t n) {
906 const char *on, *off;
907 bool shorten = false;
909 assert(n == 0 || jobs);
912 on = ansi_highlight_green(true);
913 off = ansi_highlight_green(false);
915 printf("%sNo jobs running.%s\n", on, off);
919 pager_open_if_enabled();
922 /* JOB UNIT TYPE STATE */
923 unsigned l0 = 3, l1 = 4, l2 = 4, l3 = 5;
925 for (i = 0, j = jobs; i < n; i++, j++) {
926 assert(j->name && j->type && j->state);
927 l0 = MAX(l0, decimal_str_max(j->id));
928 l1 = MAX(l1, strlen(j->name));
929 l2 = MAX(l2, strlen(j->type));
930 l3 = MAX(l3, strlen(j->state));
933 if (!arg_full && l0 + 1 + l1 + l2 + 1 + l3 > columns()) {
934 l1 = MAX(33u, columns() - l0 - l2 - l3 - 3);
939 printf("%*s %-*s %-*s %-*s\n",
945 for (i = 0, j = jobs; i < n; i++, j++) {
946 char _cleanup_free_ *e = NULL;
948 if (streq(j->state, "running")) {
949 on = ansi_highlight(true);
950 off = ansi_highlight(false);
954 e = shorten ? ellipsize(j->name, l1, 33) : NULL;
955 printf("%*u %s%-*s%s %-*s %s%-*s%s\n",
957 on, l1, e ? e : j->name, off,
959 on, l3, j->state, off);
963 on = ansi_highlight(true);
964 off = ansi_highlight(false);
967 printf("\n%s%zu jobs listed%s.\n", on, n, off);
970 static int list_jobs(DBusConnection *bus, char **args) {
971 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
972 DBusMessageIter iter, sub, sub2;
974 struct job_info *jobs = NULL;
975 size_t size = 0, used = 0;
977 r = bus_method_call_with_reply(
979 "org.freedesktop.systemd1",
980 "/org/freedesktop/systemd1",
981 "org.freedesktop.systemd1.Manager",
989 if (!dbus_message_iter_init(reply, &iter) ||
990 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
991 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
992 log_error("Failed to parse reply.");
996 dbus_message_iter_recurse(&iter, &sub);
998 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
999 const char *name, *type, *state, *job_path, *unit_path;
1002 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
1003 log_error("Failed to parse reply.");
1007 dbus_message_iter_recurse(&sub, &sub2);
1009 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &id, true) < 0 ||
1010 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
1011 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
1012 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, true) < 0 ||
1013 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &job_path, true) < 0 ||
1014 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, false) < 0) {
1015 log_error("Failed to parse reply.");
1020 if (!greedy_realloc((void**) &jobs, &size,
1021 sizeof(struct job_info) * (used + 1))) {
1026 jobs[used++] = (struct job_info) { id,
1030 if (!jobs[used-1].name || !jobs[used-1].type || !jobs[used-1].state) {
1035 dbus_message_iter_next(&sub);
1038 list_jobs_print(jobs, used);
1042 free(jobs[used].name);
1043 free(jobs[used].type);
1044 free(jobs[used].state);
1051 static int load_unit(DBusConnection *bus, char **args) {
1056 STRV_FOREACH(name, args+1) {
1057 _cleanup_free_ char *n = NULL;
1060 n = unit_name_mangle(*name);
1064 r = bus_method_call_with_reply(
1066 "org.freedesktop.systemd1",
1067 "/org/freedesktop/systemd1",
1068 "org.freedesktop.systemd1.Manager",
1072 DBUS_TYPE_STRING, &n,
1081 static int cancel_job(DBusConnection *bus, char **args) {
1086 if (strv_length(args) <= 1)
1087 return daemon_reload(bus, args);
1089 STRV_FOREACH(name, args+1) {
1093 r = safe_atou32(*name, &id);
1095 log_error("Failed to parse job id: %s", strerror(-r));
1099 r = bus_method_call_with_reply(
1101 "org.freedesktop.systemd1",
1102 "/org/freedesktop/systemd1",
1103 "org.freedesktop.systemd1.Manager",
1107 DBUS_TYPE_UINT32, &id,
1116 static bool need_daemon_reload(DBusConnection *bus, const char *unit) {
1117 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1118 dbus_bool_t b = FALSE;
1119 DBusMessageIter iter, sub;
1121 *interface = "org.freedesktop.systemd1.Unit",
1122 *property = "NeedDaemonReload",
1124 _cleanup_free_ char *n = NULL;
1127 /* We ignore all errors here, since this is used to show a warning only */
1129 n = unit_name_mangle(unit);
1133 r = bus_method_call_with_reply(
1135 "org.freedesktop.systemd1",
1136 "/org/freedesktop/systemd1",
1137 "org.freedesktop.systemd1.Manager",
1141 DBUS_TYPE_STRING, &n,
1146 if (!dbus_message_get_args(reply, NULL,
1147 DBUS_TYPE_OBJECT_PATH, &path,
1151 dbus_message_unref(reply);
1154 r = bus_method_call_with_reply(
1156 "org.freedesktop.systemd1",
1158 "org.freedesktop.DBus.Properties",
1162 DBUS_TYPE_STRING, &interface,
1163 DBUS_TYPE_STRING, &property,
1168 if (!dbus_message_iter_init(reply, &iter) ||
1169 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
1172 dbus_message_iter_recurse(&iter, &sub);
1173 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_BOOLEAN)
1176 dbus_message_iter_get_basic(&sub, &b);
1180 typedef struct WaitData {
1187 static DBusHandlerResult wait_filter(DBusConnection *connection, DBusMessage *message, void *data) {
1188 DBusError _cleanup_dbus_error_free_ error;
1191 dbus_error_init(&error);
1197 log_debug("Got D-Bus request: %s.%s() on %s",
1198 dbus_message_get_interface(message),
1199 dbus_message_get_member(message),
1200 dbus_message_get_path(message));
1202 if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
1203 log_error("Warning! D-Bus connection terminated.");
1204 dbus_connection_close(connection);
1206 } else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
1208 const char *path, *result, *unit;
1210 if (dbus_message_get_args(message, &error,
1211 DBUS_TYPE_UINT32, &id,
1212 DBUS_TYPE_OBJECT_PATH, &path,
1213 DBUS_TYPE_STRING, &unit,
1214 DBUS_TYPE_STRING, &result,
1215 DBUS_TYPE_INVALID)) {
1217 free(set_remove(d->set, (char*) path));
1219 if (!isempty(result))
1220 d->result = strdup(result);
1223 d->name = strdup(unit);
1225 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1228 dbus_error_free(&error);
1229 if (dbus_message_get_args(message, &error,
1230 DBUS_TYPE_UINT32, &id,
1231 DBUS_TYPE_OBJECT_PATH, &path,
1232 DBUS_TYPE_STRING, &result,
1233 DBUS_TYPE_INVALID)) {
1234 /* Compatibility with older systemd versions <
1235 * 183 during upgrades. This should be dropped
1237 free(set_remove(d->set, (char*) path));
1240 d->result = strdup(result);
1242 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1246 log_error("Failed to parse message: %s", bus_error_message(&error));
1249 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1252 static int enable_wait_for_jobs(DBusConnection *bus) {
1260 dbus_error_init(&error);
1261 dbus_bus_add_match(bus,
1263 "sender='org.freedesktop.systemd1',"
1264 "interface='org.freedesktop.systemd1.Manager',"
1265 "member='JobRemoved',"
1266 "path='/org/freedesktop/systemd1'",
1269 if (dbus_error_is_set(&error)) {
1270 log_error("Failed to add match: %s", bus_error_message(&error));
1271 dbus_error_free(&error);
1275 /* This is slightly dirty, since we don't undo the match registrations. */
1279 static int wait_for_jobs(DBusConnection *bus, Set *s) {
1281 WaitData d = { .set = s };
1286 if (!dbus_connection_add_filter(bus, wait_filter, &d, NULL))
1289 while (!set_isempty(s)) {
1291 if (!dbus_connection_read_write_dispatch(bus, -1)) {
1292 log_error("Disconnected from bus.");
1293 return -ECONNREFUSED;
1300 if (streq(d.result, "timeout"))
1301 log_error("Job for %s timed out.", strna(d.name));
1302 else if (streq(d.result, "canceled"))
1303 log_error("Job for %s canceled.", strna(d.name));
1304 else if (streq(d.result, "dependency"))
1305 log_error("A dependency job for %s failed. See 'journalctl -xn' for details.", strna(d.name));
1306 else if (!streq(d.result, "done") && !streq(d.result, "skipped"))
1307 log_error("Job for %s failed. See 'systemctl status %s' and 'journalctl -xn' for details.", strna(d.name), strna(d.name));
1310 if (streq_ptr(d.result, "timeout"))
1312 else if (streq_ptr(d.result, "canceled"))
1314 else if (!streq_ptr(d.result, "done") && !streq_ptr(d.result, "skipped"))
1325 dbus_connection_remove_filter(bus, wait_filter, &d);
1329 static int check_one_unit(DBusConnection *bus, const char *name, char **check_states, bool quiet) {
1330 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1331 _cleanup_free_ char *n = NULL;
1332 DBusMessageIter iter, sub;
1334 *interface = "org.freedesktop.systemd1.Unit",
1335 *property = "ActiveState";
1336 const char *state, *path;
1342 dbus_error_init(&error);
1344 n = unit_name_mangle(name);
1348 r = bus_method_call_with_reply (
1350 "org.freedesktop.systemd1",
1351 "/org/freedesktop/systemd1",
1352 "org.freedesktop.systemd1.Manager",
1356 DBUS_TYPE_STRING, &n,
1359 dbus_error_free(&error);
1366 if (!dbus_message_get_args(reply, NULL,
1367 DBUS_TYPE_OBJECT_PATH, &path,
1368 DBUS_TYPE_INVALID)) {
1369 log_error("Failed to parse reply.");
1373 dbus_message_unref(reply);
1376 r = bus_method_call_with_reply(
1378 "org.freedesktop.systemd1",
1380 "org.freedesktop.DBus.Properties",
1384 DBUS_TYPE_STRING, &interface,
1385 DBUS_TYPE_STRING, &property,
1393 if (!dbus_message_iter_init(reply, &iter) ||
1394 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1395 log_error("Failed to parse reply.");
1399 dbus_message_iter_recurse(&iter, &sub);
1401 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1402 log_error("Failed to parse reply.");
1406 dbus_message_iter_get_basic(&sub, &state);
1411 return strv_find(check_states, state) ? 1 : 0;
1414 static void check_triggering_units(
1415 DBusConnection *bus,
1416 const char *unit_name) {
1418 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1419 DBusMessageIter iter, sub;
1420 const char *interface = "org.freedesktop.systemd1.Unit",
1421 *load_state_property = "LoadState",
1422 *triggered_by_property = "TriggeredBy",
1424 char _cleanup_free_ *unit_path = NULL, *n = NULL;
1425 bool print_warning_label = true;
1428 n = unit_name_mangle(unit_name);
1434 unit_path = unit_dbus_path_from_name(n);
1440 r = bus_method_call_with_reply(
1442 "org.freedesktop.systemd1",
1444 "org.freedesktop.DBus.Properties",
1448 DBUS_TYPE_STRING, &interface,
1449 DBUS_TYPE_STRING, &load_state_property,
1454 if (!dbus_message_iter_init(reply, &iter) ||
1455 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1456 log_error("Failed to parse reply.");
1460 dbus_message_iter_recurse(&iter, &sub);
1462 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1463 log_error("Failed to parse reply.");
1467 dbus_message_iter_get_basic(&sub, &state);
1469 if (streq(state, "masked"))
1472 dbus_message_unref(reply);
1475 r = bus_method_call_with_reply(
1477 "org.freedesktop.systemd1",
1479 "org.freedesktop.DBus.Properties",
1483 DBUS_TYPE_STRING, &interface,
1484 DBUS_TYPE_STRING, &triggered_by_property,
1489 if (!dbus_message_iter_init(reply, &iter) ||
1490 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1491 log_error("Failed to parse reply.");
1495 dbus_message_iter_recurse(&iter, &sub);
1496 dbus_message_iter_recurse(&sub, &iter);
1499 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1500 const char * const check_states[] = {
1505 const char *service_trigger;
1507 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1508 log_error("Failed to parse reply.");
1512 dbus_message_iter_get_basic(&sub, &service_trigger);
1514 r = check_one_unit(bus, service_trigger, (char**) check_states, true);
1518 if (print_warning_label) {
1519 log_warning("Warning: Stopping %s, but it can still be activated by:", unit_name);
1520 print_warning_label = false;
1523 log_warning(" %s", service_trigger);
1526 dbus_message_iter_next(&sub);
1530 static int start_unit_one(
1531 DBusConnection *bus,
1538 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1539 _cleanup_free_ char *n;
1548 n = unit_name_mangle(name);
1552 r = bus_method_call_with_reply(
1554 "org.freedesktop.systemd1",
1555 "/org/freedesktop/systemd1",
1556 "org.freedesktop.systemd1.Manager",
1560 DBUS_TYPE_STRING, &n,
1561 DBUS_TYPE_STRING, &mode,
1564 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
1565 /* There's always a fallback possible for
1566 * legacy actions. */
1569 log_error("Failed to issue method call: %s", bus_error_message(error));
1574 if (!dbus_message_get_args(reply, error,
1575 DBUS_TYPE_OBJECT_PATH, &path,
1576 DBUS_TYPE_INVALID)) {
1577 log_error("Failed to parse reply: %s", bus_error_message(error));
1581 if (need_daemon_reload(bus, n))
1582 log_warning("Warning: Unit file of %s changed on disk, 'systemctl %s daemon-reload' recommended.",
1583 n, arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
1595 log_error("Failed to add path to set.");
1603 static const struct {
1607 } action_table[_ACTION_MAX] = {
1608 [ACTION_HALT] = { SPECIAL_HALT_TARGET, "halt", "replace-irreversibly" },
1609 [ACTION_POWEROFF] = { SPECIAL_POWEROFF_TARGET, "poweroff", "replace-irreversibly" },
1610 [ACTION_REBOOT] = { SPECIAL_REBOOT_TARGET, "reboot", "replace-irreversibly" },
1611 [ACTION_KEXEC] = { SPECIAL_KEXEC_TARGET, "kexec", "replace-irreversibly" },
1612 [ACTION_RUNLEVEL2] = { SPECIAL_RUNLEVEL2_TARGET, NULL, "isolate" },
1613 [ACTION_RUNLEVEL3] = { SPECIAL_RUNLEVEL3_TARGET, NULL, "isolate" },
1614 [ACTION_RUNLEVEL4] = { SPECIAL_RUNLEVEL4_TARGET, NULL, "isolate" },
1615 [ACTION_RUNLEVEL5] = { SPECIAL_RUNLEVEL5_TARGET, NULL, "isolate" },
1616 [ACTION_RESCUE] = { SPECIAL_RESCUE_TARGET, "rescue", "isolate" },
1617 [ACTION_EMERGENCY] = { SPECIAL_EMERGENCY_TARGET, "emergency", "isolate" },
1618 [ACTION_DEFAULT] = { SPECIAL_DEFAULT_TARGET, "default", "isolate" },
1619 [ACTION_EXIT] = { SPECIAL_EXIT_TARGET, "exit", "replace-irreversibly" },
1620 [ACTION_SUSPEND] = { SPECIAL_SUSPEND_TARGET, "suspend", "replace-irreversibly" },
1621 [ACTION_HIBERNATE] = { SPECIAL_HIBERNATE_TARGET, "hibernate", "replace-irreversibly" },
1622 [ACTION_HYBRID_SLEEP] = { SPECIAL_HYBRID_SLEEP_TARGET, "hybrid-sleep", "replace-irreversibly" },
1625 static enum action verb_to_action(const char *verb) {
1628 for (i = ACTION_INVALID; i < _ACTION_MAX; i++)
1629 if (action_table[i].verb && streq(verb, action_table[i].verb))
1631 return ACTION_INVALID;
1634 static int start_unit(DBusConnection *bus, char **args) {
1637 const char *method, *mode, *one_name;
1638 Set _cleanup_set_free_free_ *s = NULL;
1639 DBusError _cleanup_dbus_error_free_ error;
1642 dbus_error_init(&error);
1646 ask_password_agent_open_if_enabled();
1648 if (arg_action == ACTION_SYSTEMCTL) {
1651 streq(args[0], "stop") ||
1652 streq(args[0], "condstop") ? "StopUnit" :
1653 streq(args[0], "reload") ? "ReloadUnit" :
1654 streq(args[0], "restart") ? "RestartUnit" :
1656 streq(args[0], "try-restart") ||
1657 streq(args[0], "condrestart") ? "TryRestartUnit" :
1659 streq(args[0], "reload-or-restart") ? "ReloadOrRestartUnit" :
1661 streq(args[0], "reload-or-try-restart") ||
1662 streq(args[0], "condreload") ||
1664 streq(args[0], "force-reload") ? "ReloadOrTryRestartUnit" :
1666 action = verb_to_action(args[0]);
1668 mode = streq(args[0], "isolate") ? "isolate" :
1669 action_table[action].mode ?: arg_job_mode;
1671 one_name = action_table[action].target;
1674 assert(arg_action < ELEMENTSOF(action_table));
1675 assert(action_table[arg_action].target);
1677 method = "StartUnit";
1679 mode = action_table[arg_action].mode;
1680 one_name = action_table[arg_action].target;
1683 if (!arg_no_block) {
1684 ret = enable_wait_for_jobs(bus);
1686 log_error("Could not watch jobs: %s", strerror(-ret));
1690 s = set_new(string_hash_func, string_compare_func);
1696 ret = start_unit_one(bus, method, one_name, mode, &error, s);
1698 ret = translate_bus_error_to_exit_status(ret, &error);
1700 STRV_FOREACH(name, args+1) {
1701 r = start_unit_one(bus, method, *name, mode, &error, s);
1703 ret = translate_bus_error_to_exit_status(r, &error);
1704 dbus_error_free(&error);
1709 if (!arg_no_block) {
1710 r = wait_for_jobs(bus, s);
1714 /* When stopping units, warn if they can still be triggered by
1715 * another active unit (socket, path, timer) */
1716 if (!arg_quiet && streq(method, "StopUnit")) {
1718 check_triggering_units(bus, one_name);
1720 STRV_FOREACH(name, args+1)
1721 check_triggering_units(bus, *name);
1728 /* Ask systemd-logind, which might grant access to unprivileged users
1729 * through PolicyKit */
1730 static int reboot_with_logind(DBusConnection *bus, enum action a) {
1733 dbus_bool_t interactive = true;
1738 polkit_agent_open_if_enabled();
1746 case ACTION_POWEROFF:
1747 method = "PowerOff";
1750 case ACTION_SUSPEND:
1754 case ACTION_HIBERNATE:
1755 method = "Hibernate";
1758 case ACTION_HYBRID_SLEEP:
1759 method = "HybridSleep";
1766 return bus_method_call_with_reply(
1768 "org.freedesktop.login1",
1769 "/org/freedesktop/login1",
1770 "org.freedesktop.login1.Manager",
1774 DBUS_TYPE_BOOLEAN, &interactive,
1781 static int check_inhibitors(DBusConnection *bus, enum action a) {
1783 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1784 DBusMessageIter iter, sub, sub2;
1787 _cleanup_strv_free_ char **sessions = NULL;
1793 if (arg_ignore_inhibitors || arg_force > 0)
1805 r = bus_method_call_with_reply(
1807 "org.freedesktop.login1",
1808 "/org/freedesktop/login1",
1809 "org.freedesktop.login1.Manager",
1815 /* If logind is not around, then there are no inhibitors... */
1818 if (!dbus_message_iter_init(reply, &iter) ||
1819 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
1820 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
1821 log_error("Failed to parse reply.");
1825 dbus_message_iter_recurse(&iter, &sub);
1826 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1827 const char *what, *who, *why, *mode;
1829 _cleanup_strv_free_ char **sv = NULL;
1830 _cleanup_free_ char *comm = NULL, *user = NULL;
1832 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
1833 log_error("Failed to parse reply.");
1837 dbus_message_iter_recurse(&sub, &sub2);
1839 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &what, true) < 0 ||
1840 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &who, true) < 0 ||
1841 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &why, true) < 0 ||
1842 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &mode, true) < 0 ||
1843 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &uid, true) < 0 ||
1844 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, false) < 0) {
1845 log_error("Failed to parse reply.");
1849 if (!streq(mode, "block"))
1852 sv = strv_split(what, ":");
1856 if (!strv_contains(sv,
1858 a == ACTION_POWEROFF ||
1859 a == ACTION_REBOOT ||
1860 a == ACTION_KEXEC ? "shutdown" : "sleep"))
1863 get_process_comm(pid, &comm);
1864 user = uid_to_name(uid);
1865 log_warning("Operation inhibited by \"%s\" (PID %lu \"%s\", user %s), reason is \"%s\".",
1866 who, (unsigned long) pid, strna(comm), strna(user), why);
1870 dbus_message_iter_next(&sub);
1873 dbus_message_iter_recurse(&iter, &sub);
1875 /* Check for current sessions */
1876 sd_get_sessions(&sessions);
1877 STRV_FOREACH(s, sessions) {
1879 _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL;
1881 if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid())
1884 if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
1887 if (sd_session_get_type(*s, &type) < 0 || (!streq(type, "x11") && !streq(type, "tty")))
1890 sd_session_get_tty(*s, &tty);
1891 sd_session_get_seat(*s, &seat);
1892 sd_session_get_service(*s, &service);
1893 user = uid_to_name(uid);
1895 log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty);
1902 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
1903 action_table[a].verb);
1911 static int start_special(DBusConnection *bus, char **args) {
1917 a = verb_to_action(args[0]);
1919 r = check_inhibitors(bus, a);
1923 if (arg_force >= 2 && geteuid() != 0) {
1924 log_error("Must be root.");
1928 if (arg_force >= 2 &&
1929 (a == ACTION_HALT ||
1930 a == ACTION_POWEROFF ||
1931 a == ACTION_REBOOT))
1934 if (arg_force >= 1 &&
1935 (a == ACTION_HALT ||
1936 a == ACTION_POWEROFF ||
1937 a == ACTION_REBOOT ||
1938 a == ACTION_KEXEC ||
1940 return daemon_reload(bus, args);
1942 /* first try logind, to allow authentication with polkit */
1943 if (geteuid() != 0 &&
1944 (a == ACTION_POWEROFF ||
1945 a == ACTION_REBOOT ||
1946 a == ACTION_SUSPEND ||
1947 a == ACTION_HIBERNATE ||
1948 a == ACTION_HYBRID_SLEEP)) {
1949 r = reboot_with_logind(bus, a);
1954 r = start_unit(bus, args);
1955 if (r == EXIT_SUCCESS)
1961 static int check_unit_active(DBusConnection *bus, char **args) {
1962 const char * const check_states[] = {
1969 int r = 3; /* According to LSB: "program is not running" */
1974 STRV_FOREACH(name, args+1) {
1977 state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
1987 static int check_unit_failed(DBusConnection *bus, char **args) {
1988 const char * const check_states[] = {
1999 STRV_FOREACH(name, args+1) {
2002 state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
2012 static int kill_unit(DBusConnection *bus, char **args) {
2020 arg_kill_who = "all";
2022 STRV_FOREACH(name, args+1) {
2023 _cleanup_free_ char *n = NULL;
2025 n = unit_name_mangle(*name);
2029 r = bus_method_call_with_reply(
2031 "org.freedesktop.systemd1",
2032 "/org/freedesktop/systemd1",
2033 "org.freedesktop.systemd1.Manager",
2037 DBUS_TYPE_STRING, &n,
2038 DBUS_TYPE_STRING, &arg_kill_who,
2039 DBUS_TYPE_INT32, &arg_signal,
2047 static int set_cgroup(DBusConnection *bus, char **args) {
2048 _cleanup_free_ char *n = NULL;
2049 const char *method, *runtime;
2057 streq(args[0], "set-cgroup") ? "SetUnitControlGroup" :
2058 streq(args[0], "unset-cgroup") ? "UnsetUnitControlGroup"
2059 : "UnsetUnitControlGroupAttribute";
2061 runtime = arg_runtime ? "runtime" : "persistent";
2063 n = unit_name_mangle(args[1]);
2067 STRV_FOREACH(argument, args + 2) {
2069 r = bus_method_call_with_reply(
2071 "org.freedesktop.systemd1",
2072 "/org/freedesktop/systemd1",
2073 "org.freedesktop.systemd1.Manager",
2077 DBUS_TYPE_STRING, &n,
2078 DBUS_TYPE_STRING, argument,
2079 DBUS_TYPE_STRING, &runtime,
2088 static int set_cgroup_attr(DBusConnection *bus, char **args) {
2089 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
2091 DBusMessageIter iter;
2092 _cleanup_free_ char *n = NULL;
2093 const char *runtime;
2099 dbus_error_init(&error);
2101 runtime = arg_runtime ? "runtime" : "persistent";
2103 n = unit_name_mangle(args[1]);
2107 m = dbus_message_new_method_call(
2108 "org.freedesktop.systemd1",
2109 "/org/freedesktop/systemd1",
2110 "org.freedesktop.systemd1.Manager",
2111 "SetUnitControlGroupAttribute");
2115 dbus_message_iter_init_append(m, &iter);
2116 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &n) ||
2117 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &args[2]))
2120 r = bus_append_strv_iter(&iter, args + 3);
2124 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &runtime))
2127 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
2129 log_error("Failed to issue method call: %s", bus_error_message(&error));
2130 dbus_error_free(&error);
2137 static int get_cgroup_attr(DBusConnection *bus, char **args) {
2138 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
2139 _cleanup_free_ char *n = NULL;
2146 n = unit_name_mangle(args[1]);
2150 STRV_FOREACH(argument, args + 2) {
2151 _cleanup_strv_free_ char **list = NULL;
2152 DBusMessageIter iter;
2155 r = bus_method_call_with_reply(
2157 "org.freedesktop.systemd1",
2158 "/org/freedesktop/systemd1",
2159 "org.freedesktop.systemd1.Manager",
2160 "GetUnitControlGroupAttribute",
2163 DBUS_TYPE_STRING, &n,
2164 DBUS_TYPE_STRING, argument,
2169 if (!dbus_message_iter_init(reply, &iter)) {
2170 log_error("Failed to initialize iterator.");
2174 r = bus_parse_strv_iter(&iter, &list);
2176 log_error("Failed to parse value list.");
2180 STRV_FOREACH(a, list) {
2181 if (endswith(*a, "\n"))
2191 typedef struct ExecStatusInfo {
2199 usec_t start_timestamp;
2200 usec_t exit_timestamp;
2205 LIST_FIELDS(struct ExecStatusInfo, exec);
2208 static void exec_status_info_free(ExecStatusInfo *i) {
2217 static int exec_status_info_deserialize(DBusMessageIter *sub, ExecStatusInfo *i) {
2218 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
2219 DBusMessageIter sub2, sub3;
2223 int32_t code, status;
2229 if (dbus_message_iter_get_arg_type(sub) != DBUS_TYPE_STRUCT)
2232 dbus_message_iter_recurse(sub, &sub2);
2234 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0)
2237 i->path = strdup(path);
2241 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_ARRAY ||
2242 dbus_message_iter_get_element_type(&sub2) != DBUS_TYPE_STRING)
2246 dbus_message_iter_recurse(&sub2, &sub3);
2247 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2248 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2249 dbus_message_iter_next(&sub3);
2253 i->argv = new0(char*, n+1);
2258 dbus_message_iter_recurse(&sub2, &sub3);
2259 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2262 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2263 dbus_message_iter_get_basic(&sub3, &s);
2264 dbus_message_iter_next(&sub3);
2266 i->argv[n] = strdup(s);
2273 if (!dbus_message_iter_next(&sub2) ||
2274 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, true) < 0 ||
2275 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp, true) < 0 ||
2276 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp_monotonic, true) < 0 ||
2277 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp, true) < 0 ||
2278 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp_monotonic, true) < 0 ||
2279 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, true) < 0 ||
2280 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &code, true) < 0 ||
2281 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &status, false) < 0)
2285 i->start_timestamp = (usec_t) start_timestamp;
2286 i->exit_timestamp = (usec_t) exit_timestamp;
2287 i->pid = (pid_t) pid;
2294 typedef struct UnitStatusInfo {
2296 const char *load_state;
2297 const char *active_state;
2298 const char *sub_state;
2299 const char *unit_file_state;
2301 const char *description;
2302 const char *following;
2304 char **documentation;
2306 const char *fragment_path;
2307 const char *source_path;
2308 const char *default_control_group;
2310 char **dropin_paths;
2312 const char *load_error;
2315 usec_t inactive_exit_timestamp;
2316 usec_t inactive_exit_timestamp_monotonic;
2317 usec_t active_enter_timestamp;
2318 usec_t active_exit_timestamp;
2319 usec_t inactive_enter_timestamp;
2321 bool need_daemon_reload;
2326 const char *status_text;
2329 usec_t start_timestamp;
2330 usec_t exit_timestamp;
2332 int exit_code, exit_status;
2334 usec_t condition_timestamp;
2335 bool condition_result;
2338 unsigned n_accepted;
2339 unsigned n_connections;
2342 /* Pairs of type, path */
2346 const char *sysfs_path;
2348 /* Mount, Automount */
2354 LIST_HEAD(ExecStatusInfo, exec);
2357 static void print_status_info(UnitStatusInfo *i) {
2359 const char *on, *off, *ss;
2361 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
2362 char since2[FORMAT_TIMESTAMP_MAX], *s2;
2365 arg_all * OUTPUT_SHOW_ALL |
2366 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
2367 on_tty() * OUTPUT_COLOR |
2368 !arg_quiet * OUTPUT_WARN_CUTOFF |
2369 arg_full * OUTPUT_FULL_WIDTH;
2370 int maxlen = 8; /* a value that'll suffice most of the time */
2375 STRV_FOREACH_PAIR(t, t2, i->listen)
2376 maxlen = MAX(maxlen, (int)(sizeof("Listen") - 1 + strlen(*t)));
2378 maxlen = MAX(maxlen, (int)sizeof("Accept") - 1);
2379 if (i->main_pid > 0)
2380 maxlen = MAX(maxlen, (int)sizeof("Main PID") - 1);
2381 else if (i->control_pid > 0)
2382 maxlen = MAX(maxlen, (int)sizeof("Control") - 1);
2384 /* This shows pretty information about a unit. See
2385 * print_property() for a low-level property printer */
2387 printf("%s", strna(i->id));
2389 if (i->description && !streq_ptr(i->id, i->description))
2390 printf(" - %s", i->description);
2395 printf(" %*s: unit currently follows state of %s\n", maxlen, "Follow", i->following);
2397 if (streq_ptr(i->load_state, "error")) {
2398 on = ansi_highlight_red(true);
2399 off = ansi_highlight_red(false);
2403 path = i->source_path ? i->source_path : i->fragment_path;
2406 printf(" %*s: %s%s%s (Reason: %s)\n",
2407 maxlen, "Loaded", on, strna(i->load_state), off, i->load_error);
2408 else if (path && i->unit_file_state)
2409 printf(" %*s: %s%s%s (%s; %s)\n",
2410 maxlen, "Loaded", on, strna(i->load_state), off, path, i->unit_file_state);
2412 printf(" %*s: %s%s%s (%s)\n",
2413 maxlen, "Loaded", on, strna(i->load_state), off, path);
2415 printf(" %*s: %s%s%s\n",
2416 maxlen, "Loaded", on, strna(i->load_state), off);
2418 if (!strv_isempty(i->dropin_paths)) {
2423 STRV_FOREACH(dropin, i->dropin_paths) {
2424 if (! dir || last) {
2425 printf(" %*s ", maxlen, dir ? "" : "Drop-In:");
2429 if (path_get_parent(*dropin, &dir) < 0) {
2434 printf("%s\n %*s %s", dir, maxlen, "",
2435 draw_special_char(DRAW_TREE_RIGHT));
2438 last = ! (*(dropin + 1) && startswith(*(dropin + 1), dir));
2440 printf("%s%s", path_get_file_name(*dropin), last ? "\n" : ", ");
2446 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
2448 if (streq_ptr(i->active_state, "failed")) {
2449 on = ansi_highlight_red(true);
2450 off = ansi_highlight_red(false);
2451 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
2452 on = ansi_highlight_green(true);
2453 off = ansi_highlight_green(false);
2458 printf(" %*s: %s%s (%s)%s",
2459 maxlen, "Active", on, strna(i->active_state), ss, off);
2461 printf(" %*s: %s%s%s",
2462 maxlen, "Active", on, strna(i->active_state), off);
2464 if (!isempty(i->result) && !streq(i->result, "success"))
2465 printf(" (Result: %s)", i->result);
2467 timestamp = (streq_ptr(i->active_state, "active") ||
2468 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
2469 (streq_ptr(i->active_state, "inactive") ||
2470 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
2471 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
2472 i->active_exit_timestamp;
2474 s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
2475 s2 = format_timestamp(since2, sizeof(since2), timestamp);
2478 printf(" since %s; %s\n", s2, s1);
2480 printf(" since %s\n", s2);
2484 if (!i->condition_result && i->condition_timestamp > 0) {
2485 s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
2486 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
2489 printf(" %*s start condition failed at %s; %s\n", maxlen, "", s2, s1);
2491 printf(" %*s start condition failed at %s\n", maxlen, "", s2);
2495 printf(" %*s: %s\n", maxlen, "Device", i->sysfs_path);
2497 printf(" %*s: %s\n", maxlen, "Where", i->where);
2499 printf(" %*s: %s\n", maxlen, "What", i->what);
2501 STRV_FOREACH(t, i->documentation)
2502 printf(" %*s %s\n", maxlen+1, t == i->documentation ? "Docs:" : "", *t);
2504 STRV_FOREACH_PAIR(t, t2, i->listen)
2505 printf(" %*s %s (%s)\n", maxlen+1, t == i->listen ? "Listen:" : "", *t2, *t);
2508 printf(" %*s: %u; Connected: %u\n", maxlen, "Accepted", i->n_accepted, i->n_connections);
2510 LIST_FOREACH(exec, p, i->exec) {
2511 _cleanup_free_ char *argv = NULL;
2514 /* Only show exited processes here */
2518 argv = strv_join(p->argv, " ");
2519 printf(" %*s: %u %s=%s ", maxlen, "Process", p->pid, p->name, strna(argv));
2521 good = is_clean_exit_lsb(p->code, p->status, NULL);
2523 on = ansi_highlight_red(true);
2524 off = ansi_highlight_red(false);
2528 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
2530 if (p->code == CLD_EXITED) {
2533 printf("status=%i", p->status);
2535 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
2540 printf("signal=%s", signal_to_string(p->status));
2542 printf(")%s\n", off);
2544 if (i->main_pid == p->pid &&
2545 i->start_timestamp == p->start_timestamp &&
2546 i->exit_timestamp == p->start_timestamp)
2547 /* Let's not show this twice */
2550 if (p->pid == i->control_pid)
2554 if (i->main_pid > 0 || i->control_pid > 0) {
2555 if (i->main_pid > 0) {
2556 printf(" %*s: %u", maxlen, "Main PID", (unsigned) i->main_pid);
2559 _cleanup_free_ char *comm = NULL;
2560 get_process_comm(i->main_pid, &comm);
2562 printf(" (%s)", comm);
2563 } else if (i->exit_code > 0) {
2564 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
2566 if (i->exit_code == CLD_EXITED) {
2569 printf("status=%i", i->exit_status);
2571 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
2576 printf("signal=%s", signal_to_string(i->exit_status));
2580 if (i->control_pid > 0)
2584 if (i->control_pid > 0) {
2585 _cleanup_free_ char *c = NULL;
2587 printf(" %*s: %u", i->main_pid ? 0 : maxlen, "Control", (unsigned) i->control_pid);
2589 get_process_comm(i->control_pid, &c);
2598 printf(" %*s: \"%s\"\n", maxlen, "Status", i->status_text);
2600 if (i->default_control_group &&
2601 (i->main_pid > 0 || i->control_pid > 0 || cg_is_empty_by_spec(i->default_control_group, false) == 0)) {
2604 printf(" %*s: %s\n", maxlen, "CGroup", i->default_control_group);
2606 if (arg_transport != TRANSPORT_SSH) {
2609 char prefix[maxlen + 4];
2610 memset(prefix, ' ', sizeof(prefix) - 1);
2611 prefix[sizeof(prefix) - 1] = '\0';
2614 if (c > sizeof(prefix) - 1)
2615 c -= sizeof(prefix) - 1;
2619 if (i->main_pid > 0)
2620 extra[k++] = i->main_pid;
2622 if (i->control_pid > 0)
2623 extra[k++] = i->control_pid;
2625 show_cgroup_and_extra_by_spec(i->default_control_group, prefix,
2626 c, false, extra, k, flags);
2630 if (i->id && arg_transport != TRANSPORT_SSH) {
2632 show_journal_by_unit(stdout,
2636 i->inactive_exit_timestamp_monotonic,
2640 arg_scope == UNIT_FILE_SYSTEM);
2643 if (i->need_daemon_reload)
2644 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %s daemon-reload' recommended.\n",
2645 ansi_highlight_red(true),
2646 ansi_highlight_red(false),
2647 arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
2650 static void show_unit_help(UnitStatusInfo *i) {
2655 if (!i->documentation) {
2656 log_info("Documentation for %s not known.", i->id);
2660 STRV_FOREACH(p, i->documentation) {
2662 if (startswith(*p, "man:")) {
2665 char _cleanup_free_ *page = NULL, *section = NULL;
2666 const char *args[4] = { "man", NULL, NULL, NULL };
2671 if ((*p)[k-1] == ')')
2672 e = strrchr(*p, '(');
2675 page = strndup((*p) + 4, e - *p - 4);
2676 section = strndup(e + 1, *p + k - e - 2);
2677 if (!page || !section) {
2689 log_error("Failed to fork: %m");
2695 execvp(args[0], (char**) args);
2696 log_error("Failed to execute man: %m");
2697 _exit(EXIT_FAILURE);
2700 wait_for_terminate(pid, NULL);
2702 log_info("Can't show: %s", *p);
2706 static int status_property(const char *name, DBusMessageIter *iter, UnitStatusInfo *i) {
2712 switch (dbus_message_iter_get_arg_type(iter)) {
2714 case DBUS_TYPE_STRING: {
2717 dbus_message_iter_get_basic(iter, &s);
2720 if (streq(name, "Id"))
2722 else if (streq(name, "LoadState"))
2724 else if (streq(name, "ActiveState"))
2725 i->active_state = s;
2726 else if (streq(name, "SubState"))
2728 else if (streq(name, "Description"))
2730 else if (streq(name, "FragmentPath"))
2731 i->fragment_path = s;
2732 else if (streq(name, "SourcePath"))
2734 else if (streq(name, "DefaultControlGroup"))
2735 i->default_control_group = s;
2736 else if (streq(name, "StatusText"))
2738 else if (streq(name, "SysFSPath"))
2740 else if (streq(name, "Where"))
2742 else if (streq(name, "What"))
2744 else if (streq(name, "Following"))
2746 else if (streq(name, "UnitFileState"))
2747 i->unit_file_state = s;
2748 else if (streq(name, "Result"))
2755 case DBUS_TYPE_BOOLEAN: {
2758 dbus_message_iter_get_basic(iter, &b);
2760 if (streq(name, "Accept"))
2762 else if (streq(name, "NeedDaemonReload"))
2763 i->need_daemon_reload = b;
2764 else if (streq(name, "ConditionResult"))
2765 i->condition_result = b;
2770 case DBUS_TYPE_UINT32: {
2773 dbus_message_iter_get_basic(iter, &u);
2775 if (streq(name, "MainPID")) {
2777 i->main_pid = (pid_t) u;
2780 } else if (streq(name, "ControlPID"))
2781 i->control_pid = (pid_t) u;
2782 else if (streq(name, "ExecMainPID")) {
2784 i->main_pid = (pid_t) u;
2785 } else if (streq(name, "NAccepted"))
2787 else if (streq(name, "NConnections"))
2788 i->n_connections = u;
2793 case DBUS_TYPE_INT32: {
2796 dbus_message_iter_get_basic(iter, &j);
2798 if (streq(name, "ExecMainCode"))
2799 i->exit_code = (int) j;
2800 else if (streq(name, "ExecMainStatus"))
2801 i->exit_status = (int) j;
2806 case DBUS_TYPE_UINT64: {
2809 dbus_message_iter_get_basic(iter, &u);
2811 if (streq(name, "ExecMainStartTimestamp"))
2812 i->start_timestamp = (usec_t) u;
2813 else if (streq(name, "ExecMainExitTimestamp"))
2814 i->exit_timestamp = (usec_t) u;
2815 else if (streq(name, "ActiveEnterTimestamp"))
2816 i->active_enter_timestamp = (usec_t) u;
2817 else if (streq(name, "InactiveEnterTimestamp"))
2818 i->inactive_enter_timestamp = (usec_t) u;
2819 else if (streq(name, "InactiveExitTimestamp"))
2820 i->inactive_exit_timestamp = (usec_t) u;
2821 else if (streq(name, "InactiveExitTimestampMonotonic"))
2822 i->inactive_exit_timestamp_monotonic = (usec_t) u;
2823 else if (streq(name, "ActiveExitTimestamp"))
2824 i->active_exit_timestamp = (usec_t) u;
2825 else if (streq(name, "ConditionTimestamp"))
2826 i->condition_timestamp = (usec_t) u;
2831 case DBUS_TYPE_ARRAY: {
2833 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
2834 startswith(name, "Exec")) {
2835 DBusMessageIter sub;
2837 dbus_message_iter_recurse(iter, &sub);
2838 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2839 ExecStatusInfo *info;
2842 if (!(info = new0(ExecStatusInfo, 1)))
2845 if (!(info->name = strdup(name))) {
2850 if ((r = exec_status_info_deserialize(&sub, info)) < 0) {
2855 LIST_PREPEND(ExecStatusInfo, exec, i->exec, info);
2857 dbus_message_iter_next(&sub);
2860 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Listen")) {
2861 DBusMessageIter sub, sub2;
2863 dbus_message_iter_recurse(iter, &sub);
2864 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2865 const char *type, *path;
2867 dbus_message_iter_recurse(&sub, &sub2);
2869 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
2870 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0) {
2873 r = strv_extend(&i->listen, type);
2876 r = strv_extend(&i->listen, path);
2881 dbus_message_iter_next(&sub);
2886 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING && streq(name, "DropInPaths")) {
2887 int r = bus_parse_strv_iter(iter, &i->dropin_paths);
2891 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
2892 streq(name, "Documentation")) {
2894 DBusMessageIter sub;
2896 dbus_message_iter_recurse(iter, &sub);
2897 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING) {
2901 dbus_message_iter_get_basic(&sub, &s);
2903 r = strv_extend(&i->documentation, s);
2907 dbus_message_iter_next(&sub);
2914 case DBUS_TYPE_STRUCT: {
2916 if (streq(name, "LoadError")) {
2917 DBusMessageIter sub;
2918 const char *n, *message;
2921 dbus_message_iter_recurse(iter, &sub);
2923 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &n, true);
2927 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &message, false);
2931 if (!isempty(message))
2932 i->load_error = message;
2942 static int print_property(const char *name, DBusMessageIter *iter) {
2946 /* This is a low-level property printer, see
2947 * print_status_info() for the nicer output */
2949 if (arg_properties && !strv_find(arg_properties, name))
2952 switch (dbus_message_iter_get_arg_type(iter)) {
2954 case DBUS_TYPE_STRUCT: {
2955 DBusMessageIter sub;
2956 dbus_message_iter_recurse(iter, &sub);
2958 if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32 && streq(name, "Job")) {
2961 dbus_message_iter_get_basic(&sub, &u);
2964 printf("%s=%u\n", name, (unsigned) u);
2966 printf("%s=\n", name);
2969 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "Unit")) {
2972 dbus_message_iter_get_basic(&sub, &s);
2974 if (arg_all || s[0])
2975 printf("%s=%s\n", name, s);
2978 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "LoadError")) {
2979 const char *a = NULL, *b = NULL;
2981 if (bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &a, true) >= 0)
2982 bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &b, false);
2984 if (arg_all || !isempty(a) || !isempty(b))
2985 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
2993 case DBUS_TYPE_ARRAY:
2995 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "EnvironmentFiles")) {
2996 DBusMessageIter sub, sub2;
2998 dbus_message_iter_recurse(iter, &sub);
2999 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3003 dbus_message_iter_recurse(&sub, &sub2);
3005 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
3006 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) >= 0)
3007 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
3009 dbus_message_iter_next(&sub);
3014 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Paths")) {
3015 DBusMessageIter sub, sub2;
3017 dbus_message_iter_recurse(iter, &sub);
3019 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3020 const char *type, *path;
3022 dbus_message_iter_recurse(&sub, &sub2);
3024 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
3025 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
3026 printf("%s=%s\n", type, path);
3028 dbus_message_iter_next(&sub);
3033 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Listen")) {
3034 DBusMessageIter sub, sub2;
3036 dbus_message_iter_recurse(iter, &sub);
3037 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3038 const char *type, *path;
3040 dbus_message_iter_recurse(&sub, &sub2);
3042 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
3043 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
3044 printf("Listen%s=%s\n", type, path);
3046 dbus_message_iter_next(&sub);
3051 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Timers")) {
3052 DBusMessageIter sub, sub2;
3054 dbus_message_iter_recurse(iter, &sub);
3055 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3057 uint64_t value, next_elapse;
3059 dbus_message_iter_recurse(&sub, &sub2);
3061 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &base, true) >= 0 &&
3062 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &value, true) >= 0 &&
3063 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &next_elapse, false) >= 0) {
3064 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
3066 printf("%s={ value=%s ; next_elapse=%s }\n",
3068 format_timespan(timespan1, sizeof(timespan1), value, 0),
3069 format_timespan(timespan2, sizeof(timespan2), next_elapse, 0));
3072 dbus_message_iter_next(&sub);
3077 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "ControlGroupAttributes")) {
3078 DBusMessageIter sub, sub2;
3080 dbus_message_iter_recurse(iter, &sub);
3081 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3082 const char *controller, *attr, *value;
3084 dbus_message_iter_recurse(&sub, &sub2);
3086 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &controller, true) >= 0 &&
3087 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &attr, true) >= 0 &&
3088 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &value, false) >= 0) {
3090 printf("ControlGroupAttributes={ controller=%s ; attribute=%s ; value=\"%s\" }\n",
3096 dbus_message_iter_next(&sub);
3101 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && startswith(name, "Exec")) {
3102 DBusMessageIter sub;
3104 dbus_message_iter_recurse(iter, &sub);
3105 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3106 ExecStatusInfo info = {};
3108 if (exec_status_info_deserialize(&sub, &info) >= 0) {
3109 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
3110 char _cleanup_free_ *t;
3112 t = strv_join(info.argv, " ");
3114 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
3118 yes_no(info.ignore),
3119 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
3120 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
3121 (unsigned) info. pid,
3122 sigchld_code_to_string(info.code),
3124 info.code == CLD_EXITED ? "" : "/",
3125 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
3129 strv_free(info.argv);
3131 dbus_message_iter_next(&sub);
3140 if (generic_print_property(name, iter, arg_all) > 0)
3144 printf("%s=[unprintable]\n", name);
3149 static int show_one(const char *verb, DBusConnection *bus, const char *path, bool show_properties, bool *new_line) {
3150 DBusMessage _cleanup_free_ *reply = NULL;
3151 const char *interface = "";
3153 DBusMessageIter iter, sub, sub2, sub3;
3154 UnitStatusInfo info = {};
3160 r = bus_method_call_with_reply(
3162 "org.freedesktop.systemd1",
3164 "org.freedesktop.DBus.Properties",
3168 DBUS_TYPE_STRING, &interface,
3173 if (!dbus_message_iter_init(reply, &iter) ||
3174 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3175 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
3176 log_error("Failed to parse reply.");
3180 dbus_message_iter_recurse(&iter, &sub);
3187 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
3190 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_DICT_ENTRY);
3191 dbus_message_iter_recurse(&sub, &sub2);
3193 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
3194 dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
3195 log_error("Failed to parse reply.");
3199 dbus_message_iter_recurse(&sub2, &sub3);
3201 if (show_properties)
3202 r = print_property(name, &sub3);
3204 r = status_property(name, &sub3, &info);
3206 log_error("Failed to parse reply.");
3210 dbus_message_iter_next(&sub);
3215 if (!show_properties) {
3216 if (streq(verb, "help"))
3217 show_unit_help(&info);
3219 print_status_info(&info);
3222 strv_free(info.documentation);
3223 strv_free(info.dropin_paths);
3224 strv_free(info.listen);
3226 if (!streq_ptr(info.active_state, "active") &&
3227 !streq_ptr(info.active_state, "reloading") &&
3228 streq(verb, "status"))
3229 /* According to LSB: "program not running" */
3232 while ((p = info.exec)) {
3233 LIST_REMOVE(ExecStatusInfo, exec, info.exec, p);
3234 exec_status_info_free(p);
3240 static int show_one_by_pid(const char *verb, DBusConnection *bus, uint32_t pid, bool *new_line) {
3241 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3242 const char *path = NULL;
3243 DBusError _cleanup_dbus_error_free_ error;
3246 dbus_error_init(&error);
3248 r = bus_method_call_with_reply(
3250 "org.freedesktop.systemd1",
3251 "/org/freedesktop/systemd1",
3252 "org.freedesktop.systemd1.Manager",
3256 DBUS_TYPE_UINT32, &pid,
3261 if (!dbus_message_get_args(reply, &error,
3262 DBUS_TYPE_OBJECT_PATH, &path,
3263 DBUS_TYPE_INVALID)) {
3264 log_error("Failed to parse reply: %s", bus_error_message(&error));
3268 r = show_one(verb, bus, path, false, new_line);
3272 static int show_all(const char* verb, DBusConnection *bus, bool show_properties, bool *new_line) {
3273 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3274 _cleanup_free_ struct unit_info *unit_infos = NULL;
3276 const struct unit_info *u;
3279 r = get_unit_list(bus, &reply, &unit_infos, &c);
3283 for (u = unit_infos; u < unit_infos + c; u++) {
3284 char _cleanup_free_ *p = NULL;
3286 if (!output_show_unit(u))
3289 p = unit_dbus_path_from_name(u->id);
3293 printf("%s -> '%s'\n", u->id, p);
3295 r = show_one(verb, bus, p, show_properties, new_line);
3303 static int show(DBusConnection *bus, char **args) {
3305 bool show_properties, show_status, new_line = false;
3311 show_properties = streq(args[0], "show");
3312 show_status = streq(args[0], "status");
3314 if (show_properties)
3315 pager_open_if_enabled();
3317 /* If no argument is specified inspect the manager itself */
3319 if (show_properties && strv_length(args) <= 1)
3320 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line);
3322 if (show_status && strv_length(args) <= 1)
3323 return show_all(args[0], bus, false, &new_line);
3325 STRV_FOREACH(name, args+1) {
3328 if (safe_atou32(*name, &id) < 0) {
3329 _cleanup_free_ char *p = NULL, *n = NULL;
3330 /* Interpret as unit name */
3332 n = unit_name_mangle(*name);
3336 p = unit_dbus_path_from_name(n);
3340 r = show_one(args[0], bus, p, show_properties, &new_line);
3344 } else if (show_properties) {
3345 _cleanup_free_ char *p = NULL;
3347 /* Interpret as job id */
3348 if (asprintf(&p, "/org/freedesktop/systemd1/job/%u", id) < 0)
3351 r = show_one(args[0], bus, p, show_properties, &new_line);
3356 /* Interpret as PID */
3357 r = show_one_by_pid(args[0], bus, id, &new_line);
3366 static int dump(DBusConnection *bus, char **args) {
3367 _cleanup_free_ DBusMessage *reply = NULL;
3372 dbus_error_init(&error);
3374 pager_open_if_enabled();
3376 r = bus_method_call_with_reply(
3378 "org.freedesktop.systemd1",
3379 "/org/freedesktop/systemd1",
3380 "org.freedesktop.systemd1.Manager",
3388 if (!dbus_message_get_args(reply, &error,
3389 DBUS_TYPE_STRING, &text,
3390 DBUS_TYPE_INVALID)) {
3391 log_error("Failed to parse reply: %s", bus_error_message(&error));
3392 dbus_error_free(&error);
3396 fputs(text, stdout);
3400 static int snapshot(DBusConnection *bus, char **args) {
3401 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3404 dbus_bool_t cleanup = FALSE;
3405 DBusMessageIter iter, sub;
3408 *interface = "org.freedesktop.systemd1.Unit",
3410 _cleanup_free_ char *n = NULL;
3412 dbus_error_init(&error);
3414 if (strv_length(args) > 1)
3415 n = snapshot_name_mangle(args[1]);
3421 r = bus_method_call_with_reply (
3423 "org.freedesktop.systemd1",
3424 "/org/freedesktop/systemd1",
3425 "org.freedesktop.systemd1.Manager",
3429 DBUS_TYPE_STRING, &n,
3430 DBUS_TYPE_BOOLEAN, &cleanup,
3435 if (!dbus_message_get_args(reply, &error,
3436 DBUS_TYPE_OBJECT_PATH, &path,
3437 DBUS_TYPE_INVALID)) {
3438 log_error("Failed to parse reply: %s", bus_error_message(&error));
3439 dbus_error_free(&error);
3443 dbus_message_unref(reply);
3446 r = bus_method_call_with_reply (
3448 "org.freedesktop.systemd1",
3450 "org.freedesktop.DBus.Properties",
3454 DBUS_TYPE_STRING, &interface,
3455 DBUS_TYPE_STRING, &property,
3460 if (!dbus_message_iter_init(reply, &iter) ||
3461 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3462 log_error("Failed to parse reply.");
3466 dbus_message_iter_recurse(&iter, &sub);
3468 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
3469 log_error("Failed to parse reply.");
3473 dbus_message_iter_get_basic(&sub, &id);
3481 static int delete_snapshot(DBusConnection *bus, char **args) {
3486 STRV_FOREACH(name, args+1) {
3487 _cleanup_free_ char *n = NULL;
3490 n = snapshot_name_mangle(*name);
3494 r = bus_method_call_with_reply(
3496 "org.freedesktop.systemd1",
3497 "/org/freedesktop/systemd1",
3498 "org.freedesktop.systemd1.Manager",
3502 DBUS_TYPE_STRING, &n,
3511 static int daemon_reload(DBusConnection *bus, char **args) {
3516 if (arg_action == ACTION_RELOAD)
3518 else if (arg_action == ACTION_REEXEC)
3519 method = "Reexecute";
3521 assert(arg_action == ACTION_SYSTEMCTL);
3524 streq(args[0], "clear-jobs") ||
3525 streq(args[0], "cancel") ? "ClearJobs" :
3526 streq(args[0], "daemon-reexec") ? "Reexecute" :
3527 streq(args[0], "reset-failed") ? "ResetFailed" :
3528 streq(args[0], "halt") ? "Halt" :
3529 streq(args[0], "poweroff") ? "PowerOff" :
3530 streq(args[0], "reboot") ? "Reboot" :
3531 streq(args[0], "kexec") ? "KExec" :
3532 streq(args[0], "exit") ? "Exit" :
3533 /* "daemon-reload" */ "Reload";
3536 r = bus_method_call_with_reply(
3538 "org.freedesktop.systemd1",
3539 "/org/freedesktop/systemd1",
3540 "org.freedesktop.systemd1.Manager",
3546 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
3547 /* There's always a fallback possible for
3548 * legacy actions. */
3550 else if (r == -ETIMEDOUT && streq(method, "Reexecute"))
3551 /* On reexecution, we expect a disconnect, not
3555 log_error("Failed to issue method call: %s", bus_error_message(&error));
3557 dbus_error_free(&error);
3561 static int reset_failed(DBusConnection *bus, char **args) {
3565 if (strv_length(args) <= 1)
3566 return daemon_reload(bus, args);
3568 STRV_FOREACH(name, args+1) {
3569 _cleanup_free_ char *n;
3571 n = unit_name_mangle(*name);
3575 r = bus_method_call_with_reply(
3577 "org.freedesktop.systemd1",
3578 "/org/freedesktop/systemd1",
3579 "org.freedesktop.systemd1.Manager",
3583 DBUS_TYPE_STRING, &n,
3592 static int show_enviroment(DBusConnection *bus, char **args) {
3593 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3594 DBusMessageIter iter, sub, sub2;
3597 *interface = "org.freedesktop.systemd1.Manager",
3598 *property = "Environment";
3600 pager_open_if_enabled();
3602 r = bus_method_call_with_reply(
3604 "org.freedesktop.systemd1",
3605 "/org/freedesktop/systemd1",
3606 "org.freedesktop.DBus.Properties",
3610 DBUS_TYPE_STRING, &interface,
3611 DBUS_TYPE_STRING, &property,
3616 if (!dbus_message_iter_init(reply, &iter) ||
3617 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3618 log_error("Failed to parse reply.");
3622 dbus_message_iter_recurse(&iter, &sub);
3624 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_ARRAY ||
3625 dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_STRING) {
3626 log_error("Failed to parse reply.");
3630 dbus_message_iter_recurse(&sub, &sub2);
3632 while (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_INVALID) {
3635 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
3636 log_error("Failed to parse reply.");
3640 dbus_message_iter_get_basic(&sub2, &text);
3643 dbus_message_iter_next(&sub2);
3649 static int switch_root(DBusConnection *bus, char **args) {
3652 _cleanup_free_ char *init = NULL;
3654 l = strv_length(args);
3655 if (l < 2 || l > 3) {
3656 log_error("Wrong number of arguments.");
3663 init = strdup(args[2]);
3665 parse_env_file("/proc/cmdline", WHITESPACE,
3675 log_debug("switching root - root: %s; init: %s", root, init);
3677 return bus_method_call_with_reply(
3679 "org.freedesktop.systemd1",
3680 "/org/freedesktop/systemd1",
3681 "org.freedesktop.systemd1.Manager",
3685 DBUS_TYPE_STRING, &root,
3686 DBUS_TYPE_STRING, &init,
3690 static int set_environment(DBusConnection *bus, char **args) {
3691 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
3694 DBusMessageIter iter;
3700 dbus_error_init(&error);
3702 method = streq(args[0], "set-environment")
3704 : "UnsetEnvironment";
3706 m = dbus_message_new_method_call(
3707 "org.freedesktop.systemd1",
3708 "/org/freedesktop/systemd1",
3709 "org.freedesktop.systemd1.Manager",
3714 dbus_message_iter_init_append(m, &iter);
3716 r = bus_append_strv_iter(&iter, args + 1);
3720 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3722 log_error("Failed to issue method call: %s", bus_error_message(&error));
3723 dbus_error_free(&error);
3730 static int enable_sysv_units(char **args) {
3733 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
3734 const char *verb = args[0];
3735 unsigned f = 1, t = 1;
3736 LookupPaths paths = {};
3738 if (arg_scope != UNIT_FILE_SYSTEM)
3741 if (!streq(verb, "enable") &&
3742 !streq(verb, "disable") &&
3743 !streq(verb, "is-enabled"))
3746 /* Processes all SysV units, and reshuffles the array so that
3747 * afterwards only the native units remain */
3749 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, NULL, NULL, NULL);
3754 for (f = 1; args[f]; f++) {
3757 bool found_native = false, found_sysv;
3759 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
3760 char **k, *l, *q = NULL;
3767 if (!endswith(name, ".service"))
3770 if (path_is_absolute(name))
3773 STRV_FOREACH(k, paths.unit_path) {
3776 if (!isempty(arg_root))
3777 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
3779 asprintf(&p, "%s/%s", *k, name);
3786 found_native = access(p, F_OK) >= 0;
3797 if (!isempty(arg_root))
3798 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
3800 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
3806 p[strlen(p) - sizeof(".service") + 1] = 0;
3807 found_sysv = access(p, F_OK) >= 0;
3814 /* Mark this entry, so that we don't try enabling it as native unit */
3815 args[f] = (char*) "";
3817 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
3819 if (!isempty(arg_root))
3820 argv[c++] = q = strappend("--root=", arg_root);
3822 argv[c++] = path_get_file_name(p);
3824 streq(verb, "enable") ? "on" :
3825 streq(verb, "disable") ? "off" : "--level=5";
3828 l = strv_join((char**)argv, " ");
3836 log_info("Executing %s", l);
3841 log_error("Failed to fork: %m");
3846 } else if (pid == 0) {
3849 execv(argv[0], (char**) argv);
3850 _exit(EXIT_FAILURE);
3856 j = wait_for_terminate(pid, &status);
3858 log_error("Failed to wait for child: %s", strerror(-r));
3863 if (status.si_code == CLD_EXITED) {
3864 if (streq(verb, "is-enabled")) {
3865 if (status.si_status == 0) {
3874 } else if (status.si_status != 0) {
3885 lookup_paths_free(&paths);
3887 /* Drop all SysV units */
3888 for (f = 1, t = 1; args[f]; f++) {
3890 if (isempty(args[f]))
3893 args[t++] = args[f];
3902 static int mangle_names(char **original_names, char ***mangled_names) {
3903 char **i, **l, **name;
3905 l = new(char*, strv_length(original_names) + 1);
3910 STRV_FOREACH(name, original_names) {
3912 /* When enabling units qualified path names are OK,
3913 * too, hence allow them explicitly. */
3918 *i = unit_name_mangle(*name);
3934 static int enable_unit(DBusConnection *bus, char **args) {
3935 const char *verb = args[0];
3936 UnitFileChange *changes = NULL;
3937 unsigned n_changes = 0, i;
3938 int carries_install_info = -1;
3939 DBusMessage _cleanup_dbus_message_unref_ *m = NULL, *reply = NULL;
3941 DBusError _cleanup_dbus_error_free_ error;
3942 char _cleanup_strv_free_ **mangled_names = NULL;
3944 dbus_error_init(&error);
3946 r = enable_sysv_units(args);
3953 if (!bus || avoid_bus()) {
3954 if (streq(verb, "enable")) {
3955 r = unit_file_enable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3956 carries_install_info = r;
3957 } else if (streq(verb, "disable"))
3958 r = unit_file_disable(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3959 else if (streq(verb, "reenable")) {
3960 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3961 carries_install_info = r;
3962 } else if (streq(verb, "link"))
3963 r = unit_file_link(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3964 else if (streq(verb, "preset")) {
3965 r = unit_file_preset(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3966 carries_install_info = r;
3967 } else if (streq(verb, "mask"))
3968 r = unit_file_mask(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3969 else if (streq(verb, "unmask"))
3970 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3972 assert_not_reached("Unknown verb");
3975 log_error("Operation failed: %s", strerror(-r));
3980 for (i = 0; i < n_changes; i++) {
3981 if (changes[i].type == UNIT_FILE_SYMLINK)
3982 log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
3984 log_info("rm '%s'", changes[i].path);
3991 bool send_force = true, expect_carries_install_info = false;
3993 DBusMessageIter iter, sub, sub2;
3995 if (streq(verb, "enable")) {
3996 method = "EnableUnitFiles";
3997 expect_carries_install_info = true;
3998 } else if (streq(verb, "disable")) {
3999 method = "DisableUnitFiles";
4001 } else if (streq(verb, "reenable")) {
4002 method = "ReenableUnitFiles";
4003 expect_carries_install_info = true;
4004 } else if (streq(verb, "link"))
4005 method = "LinkUnitFiles";
4006 else if (streq(verb, "preset")) {
4007 method = "PresetUnitFiles";
4008 expect_carries_install_info = true;
4009 } else if (streq(verb, "mask"))
4010 method = "MaskUnitFiles";
4011 else if (streq(verb, "unmask")) {
4012 method = "UnmaskUnitFiles";
4015 assert_not_reached("Unknown verb");
4017 m = dbus_message_new_method_call(
4018 "org.freedesktop.systemd1",
4019 "/org/freedesktop/systemd1",
4020 "org.freedesktop.systemd1.Manager",
4027 dbus_message_iter_init_append(m, &iter);
4029 r = mangle_names(args+1, &mangled_names);
4033 r = bus_append_strv_iter(&iter, mangled_names);
4035 log_error("Failed to append unit files.");
4040 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &a)) {
4041 log_error("Failed to append runtime boolean.");
4049 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b)) {
4050 log_error("Failed to append force boolean.");
4056 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
4058 log_error("Failed to issue method call: %s", bus_error_message(&error));
4063 if (!dbus_message_iter_init(reply, &iter)) {
4064 log_error("Failed to initialize iterator.");
4068 if (expect_carries_install_info) {
4069 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &b, true);
4071 log_error("Failed to parse reply.");
4075 carries_install_info = b;
4078 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
4079 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
4080 log_error("Failed to parse reply.");
4085 dbus_message_iter_recurse(&iter, &sub);
4086 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
4087 const char *type, *path, *source;
4089 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
4090 log_error("Failed to parse reply.");
4095 dbus_message_iter_recurse(&sub, &sub2);
4097 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
4098 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
4099 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &source, false) < 0) {
4100 log_error("Failed to parse reply.");
4106 if (streq(type, "symlink"))
4107 log_info("ln -s '%s' '%s'", source, path);
4109 log_info("rm '%s'", path);
4112 dbus_message_iter_next(&sub);
4115 /* Try to reload if enabeld */
4117 r = daemon_reload(bus, args);
4120 if (carries_install_info == 0)
4121 log_warning("The unit files have no [Install] section. They are not meant to be enabled\n"
4122 "using systemctl.\n"
4123 "Possible reasons for having this kind of units are:\n"
4124 "1) A unit may be statically enabled by being symlinked from another unit's\n"
4125 " .wants/ or .requires/ directory.\n"
4126 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
4127 " a requirement dependency on it.\n"
4128 "3) A unit may be started when needed via activation (socket, path, timer,\n"
4129 " D-Bus, udev, scripted systemctl call, ...).\n");
4132 unit_file_changes_free(changes, n_changes);
4137 static int unit_is_enabled(DBusConnection *bus, char **args) {
4138 DBusError _cleanup_dbus_error_free_ error;
4140 DBusMessage _cleanup_dbus_message_unref_ *reply = NULL;
4145 dbus_error_init(&error);
4147 r = enable_sysv_units(args);
4153 if (!bus || avoid_bus()) {
4155 STRV_FOREACH(name, args+1) {
4156 UnitFileState state;
4158 n = unit_name_mangle(*name);
4162 state = unit_file_get_state(arg_scope, arg_root, n);
4169 if (state == UNIT_FILE_ENABLED ||
4170 state == UNIT_FILE_ENABLED_RUNTIME ||
4171 state == UNIT_FILE_STATIC)
4175 puts(unit_file_state_to_string(state));
4179 STRV_FOREACH(name, args+1) {
4182 n = unit_name_mangle(*name);
4186 r = bus_method_call_with_reply (
4188 "org.freedesktop.systemd1",
4189 "/org/freedesktop/systemd1",
4190 "org.freedesktop.systemd1.Manager",
4194 DBUS_TYPE_STRING, &n,
4202 if (!dbus_message_get_args(reply, &error,
4203 DBUS_TYPE_STRING, &s,
4204 DBUS_TYPE_INVALID)) {
4205 log_error("Failed to parse reply: %s", bus_error_message(&error));
4209 dbus_message_unref(reply);
4212 if (streq(s, "enabled") ||
4213 streq(s, "enabled-runtime") ||
4222 return enabled ? 0 : 1;
4225 static int systemctl_help(void) {
4227 pager_open_if_enabled();
4229 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
4230 "Query or send control commands to the systemd manager.\n\n"
4231 " -h --help Show this help\n"
4232 " --version Show package version\n"
4233 " -t --type=TYPE List only units of a particular type\n"
4234 " -p --property=NAME Show only properties by this name\n"
4235 " -a --all Show all units/properties, including dead/empty ones\n"
4236 " --failed Show only failed units\n"
4237 " --full Don't ellipsize unit names on output\n"
4238 " --fail When queueing a new job, fail if conflicting jobs are\n"
4240 " --ignore-dependencies\n"
4241 " When queueing a new job, ignore all its dependencies\n"
4242 " -i --ignore-inhibitors\n"
4243 " When shutting down or sleeping, ignore inhibitors\n"
4244 " --kill-who=WHO Who to send signal to\n"
4245 " -s --signal=SIGNAL Which signal to send\n"
4246 " -H --host=[USER@]HOST\n"
4247 " Show information for remote host\n"
4248 " -P --privileged Acquire privileges before execution\n"
4249 " -q --quiet Suppress output\n"
4250 " --no-block Do not wait until operation finished\n"
4251 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4252 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
4254 " --no-legend Do not print a legend (column headers and hints)\n"
4255 " --no-pager Do not pipe output into a pager\n"
4256 " --no-ask-password\n"
4257 " Do not ask for system passwords\n"
4258 " --system Connect to system manager\n"
4259 " --user Connect to user service manager\n"
4260 " --global Enable/disable unit files globally\n"
4261 " -f --force When enabling unit files, override existing symlinks\n"
4262 " When shutting down, execute action immediately\n"
4263 " --root=PATH Enable unit files in the specified root directory\n"
4264 " --runtime Enable unit files only temporarily until next reboot\n"
4265 " -n --lines=INTEGER Journal entries to show\n"
4266 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
4267 " verbose, export, json, json-pretty, json-sse, cat)\n\n"
4269 " list-units List loaded units\n"
4270 " start [NAME...] Start (activate) one or more units\n"
4271 " stop [NAME...] Stop (deactivate) one or more units\n"
4272 " reload [NAME...] Reload one or more units\n"
4273 " restart [NAME...] Start or restart one or more units\n"
4274 " try-restart [NAME...] Restart one or more units if active\n"
4275 " reload-or-restart [NAME...] Reload one or more units if possible,\n"
4276 " otherwise start or restart\n"
4277 " reload-or-try-restart [NAME...] Reload one or more units if possible,\n"
4278 " otherwise restart if active\n"
4279 " isolate [NAME] Start one unit and stop all others\n"
4280 " kill [NAME...] Send signal to processes of a unit\n"
4281 " is-active [NAME...] Check whether units are active\n"
4282 " is-failed [NAME...] Check whether units are failed\n"
4283 " status [NAME...|PID...] Show runtime status of one or more units\n"
4284 " show [NAME...|JOB...] Show properties of one or more\n"
4285 " units/jobs or the manager\n"
4286 " help [NAME...|PID...] Show manual for one or more units\n"
4287 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
4289 " get-cgroup-attr [NAME] [ATTR] ...\n"
4290 " Get control group attrubute\n"
4291 " set-cgroup-attr [NAME] [ATTR] [VALUE] ...\n"
4292 " Set control group attribute\n"
4293 " unset-cgroup-attr [NAME] [ATTR...]\n"
4294 " Unset control group attribute\n"
4295 " set-cgroup [NAME] [CGROUP...] Add unit to a control group\n"
4296 " unset-cgroup [NAME] [CGROUP...] Remove unit from a control group\n"
4297 " load [NAME...] Load one or more units\n"
4298 " list-dependencies [NAME] Recursively show units which are required\n"
4299 " or wanted by this unit\n\n"
4300 "Unit File Commands:\n"
4301 " list-unit-files List installed unit files\n"
4302 " enable [NAME...] Enable one or more unit files\n"
4303 " disable [NAME...] Disable one or more unit files\n"
4304 " reenable [NAME...] Reenable one or more unit files\n"
4305 " preset [NAME...] Enable/disable one or more unit files\n"
4306 " based on preset configuration\n"
4307 " mask [NAME...] Mask one or more units\n"
4308 " unmask [NAME...] Unmask one or more units\n"
4309 " link [PATH...] Link one or more units files into\n"
4310 " the search path\n"
4311 " is-enabled [NAME...] Check whether unit files are enabled\n\n"
4313 " list-jobs List jobs\n"
4314 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
4315 "Status Commands:\n"
4316 " dump Dump server status\n"
4317 "Snapshot Commands:\n"
4318 " snapshot [NAME] Create a snapshot\n"
4319 " delete [NAME...] Remove one or more snapshots\n\n"
4320 "Environment Commands:\n"
4321 " show-environment Dump environment\n"
4322 " set-environment [NAME=VALUE...] Set one or more environment variables\n"
4323 " unset-environment [NAME...] Unset one or more environment variables\n\n"
4324 "Manager Lifecycle Commands:\n"
4325 " daemon-reload Reload systemd manager configuration\n"
4326 " daemon-reexec Reexecute systemd manager\n\n"
4327 "System Commands:\n"
4328 " default Enter system default mode\n"
4329 " rescue Enter system rescue mode\n"
4330 " emergency Enter system emergency mode\n"
4331 " halt Shut down and halt the system\n"
4332 " poweroff Shut down and power-off the system\n"
4333 " reboot Shut down and reboot the system\n"
4334 " kexec Shut down and reboot the system with kexec\n"
4335 " exit Request user instance exit\n"
4336 " switch-root [ROOT] [INIT] Change to a different root file system\n"
4337 " suspend Suspend the system\n"
4338 " hibernate Hibernate the system\n"
4339 " hybrid-sleep Hibernate and suspend the system\n",
4340 program_invocation_short_name);
4345 static int halt_help(void) {
4347 printf("%s [OPTIONS...]\n\n"
4348 "%s the system.\n\n"
4349 " --help Show this help\n"
4350 " --halt Halt the machine\n"
4351 " -p --poweroff Switch off the machine\n"
4352 " --reboot Reboot the machine\n"
4353 " -f --force Force immediate halt/power-off/reboot\n"
4354 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
4355 " -d --no-wtmp Don't write wtmp record\n"
4356 " --no-wall Don't send wall message before halt/power-off/reboot\n",
4357 program_invocation_short_name,
4358 arg_action == ACTION_REBOOT ? "Reboot" :
4359 arg_action == ACTION_POWEROFF ? "Power off" :
4365 static int shutdown_help(void) {
4367 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
4368 "Shut down the system.\n\n"
4369 " --help Show this help\n"
4370 " -H --halt Halt the machine\n"
4371 " -P --poweroff Power-off the machine\n"
4372 " -r --reboot Reboot the machine\n"
4373 " -h Equivalent to --poweroff, overridden by --halt\n"
4374 " -k Don't halt/power-off/reboot, just send warnings\n"
4375 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4376 " -c Cancel a pending shutdown\n",
4377 program_invocation_short_name);
4382 static int telinit_help(void) {
4384 printf("%s [OPTIONS...] {COMMAND}\n\n"
4385 "Send control commands to the init daemon.\n\n"
4386 " --help Show this help\n"
4387 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
4389 " 0 Power-off the machine\n"
4390 " 6 Reboot the machine\n"
4391 " 2, 3, 4, 5 Start runlevelX.target unit\n"
4392 " 1, s, S Enter rescue mode\n"
4393 " q, Q Reload init daemon configuration\n"
4394 " u, U Reexecute init daemon\n",
4395 program_invocation_short_name);
4400 static int runlevel_help(void) {
4402 printf("%s [OPTIONS...]\n\n"
4403 "Prints the previous and current runlevel of the init system.\n\n"
4404 " --help Show this help\n",
4405 program_invocation_short_name);
4410 static int help_types(void) {
4414 puts("Available unit types:");
4415 for(i = 0; i < _UNIT_TYPE_MAX; i++) {
4416 t = unit_type_to_string(i);
4421 puts("\nAvailable unit load states: ");
4422 for(i = 0; i < _UNIT_LOAD_STATE_MAX; i++) {
4423 t = unit_load_state_to_string(i);
4431 static int systemctl_parse_argv(int argc, char *argv[]) {
4436 ARG_IGNORE_DEPENDENCIES,
4449 ARG_NO_ASK_PASSWORD,
4455 static const struct option options[] = {
4456 { "help", no_argument, NULL, 'h' },
4457 { "version", no_argument, NULL, ARG_VERSION },
4458 { "type", required_argument, NULL, 't' },
4459 { "property", required_argument, NULL, 'p' },
4460 { "all", no_argument, NULL, 'a' },
4461 { "failed", no_argument, NULL, ARG_FAILED },
4462 { "full", no_argument, NULL, ARG_FULL },
4463 { "fail", no_argument, NULL, ARG_FAIL },
4464 { "irreversible", no_argument, NULL, ARG_IRREVERSIBLE },
4465 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
4466 { "ignore-inhibitors", no_argument, NULL, 'i' },
4467 { "user", no_argument, NULL, ARG_USER },
4468 { "system", no_argument, NULL, ARG_SYSTEM },
4469 { "global", no_argument, NULL, ARG_GLOBAL },
4470 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
4471 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
4472 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
4473 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4474 { "quiet", no_argument, NULL, 'q' },
4475 { "root", required_argument, NULL, ARG_ROOT },
4476 { "force", no_argument, NULL, ARG_FORCE },
4477 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
4478 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
4479 { "signal", required_argument, NULL, 's' },
4480 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
4481 { "host", required_argument, NULL, 'H' },
4482 { "privileged",no_argument, NULL, 'P' },
4483 { "runtime", no_argument, NULL, ARG_RUNTIME },
4484 { "lines", required_argument, NULL, 'n' },
4485 { "output", required_argument, NULL, 'o' },
4486 { NULL, 0, NULL, 0 }
4494 while ((c = getopt_long(argc, argv, "ht:p:aqfs:H:Pn:o:i", options, NULL)) >= 0) {
4503 puts(PACKAGE_STRING);
4504 puts(SYSTEMD_FEATURES);
4511 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
4512 char _cleanup_free_ *type;
4514 type = strndup(word, size);
4518 if (streq(type, "help")) {
4523 if (unit_type_from_string(type) >= 0) {
4524 if (strv_push(&arg_types, type))
4530 if (unit_load_state_from_string(optarg) >= 0) {
4531 if (strv_push(&arg_load_states, type))
4537 log_error("Unkown unit type or load state '%s'.", type);
4538 log_info("Use -t help to see a list of allowed values.");
4546 /* Make sure that if the empty property list
4547 was specified, we won't show any properties. */
4548 if (isempty(optarg) && !arg_properties) {
4549 arg_properties = strv_new(NULL, NULL);
4550 if (!arg_properties)
4556 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
4559 prop = strndup(word, size);
4563 if (strv_push(&arg_properties, prop)) {
4570 /* If the user asked for a particular
4571 * property, show it to him, even if it is
4583 arg_job_mode = "fail";
4586 case ARG_IRREVERSIBLE:
4587 arg_job_mode = "replace-irreversibly";
4590 case ARG_IGNORE_DEPENDENCIES:
4591 arg_job_mode = "ignore-dependencies";
4595 arg_scope = UNIT_FILE_USER;
4599 arg_scope = UNIT_FILE_SYSTEM;
4603 arg_scope = UNIT_FILE_GLOBAL;
4607 arg_no_block = true;
4611 arg_no_legend = true;
4615 arg_no_pager = true;
4647 arg_no_reload = true;
4651 arg_kill_who = optarg;
4655 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
4656 log_error("Failed to parse signal string %s.", optarg);
4661 case ARG_NO_ASK_PASSWORD:
4662 arg_ask_password = false;
4666 arg_transport = TRANSPORT_POLKIT;
4670 arg_transport = TRANSPORT_SSH;
4679 if (safe_atou(optarg, &arg_lines) < 0) {
4680 log_error("Failed to parse lines '%s'", optarg);
4686 arg_output = output_mode_from_string(optarg);
4687 if (arg_output < 0) {
4688 log_error("Unknown output '%s'.", optarg);
4694 arg_ignore_inhibitors = true;
4701 log_error("Unknown option code '%c'.", c);
4706 if (arg_transport != TRANSPORT_NORMAL && arg_scope != UNIT_FILE_SYSTEM) {
4707 log_error("Cannot access user instance remotely.");
4714 static int halt_parse_argv(int argc, char *argv[]) {
4723 static const struct option options[] = {
4724 { "help", no_argument, NULL, ARG_HELP },
4725 { "halt", no_argument, NULL, ARG_HALT },
4726 { "poweroff", no_argument, NULL, 'p' },
4727 { "reboot", no_argument, NULL, ARG_REBOOT },
4728 { "force", no_argument, NULL, 'f' },
4729 { "wtmp-only", no_argument, NULL, 'w' },
4730 { "no-wtmp", no_argument, NULL, 'd' },
4731 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4732 { NULL, 0, NULL, 0 }
4740 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
4741 if (runlevel == '0' || runlevel == '6')
4744 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
4752 arg_action = ACTION_HALT;
4756 if (arg_action != ACTION_REBOOT)
4757 arg_action = ACTION_POWEROFF;
4761 arg_action = ACTION_REBOOT;
4783 /* Compatibility nops */
4790 log_error("Unknown option code '%c'.", c);
4795 if (optind < argc) {
4796 log_error("Too many arguments.");
4803 static int parse_time_spec(const char *t, usec_t *_u) {
4807 if (streq(t, "now"))
4809 else if (!strchr(t, ':')) {
4812 if (safe_atou64(t, &u) < 0)
4815 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
4824 hour = strtol(t, &e, 10);
4825 if (errno > 0 || *e != ':' || hour < 0 || hour > 23)
4828 minute = strtol(e+1, &e, 10);
4829 if (errno > 0 || *e != 0 || minute < 0 || minute > 59)
4832 n = now(CLOCK_REALTIME);
4833 s = (time_t) (n / USEC_PER_SEC);
4835 assert_se(localtime_r(&s, &tm));
4837 tm.tm_hour = (int) hour;
4838 tm.tm_min = (int) minute;
4841 assert_se(s = mktime(&tm));
4843 *_u = (usec_t) s * USEC_PER_SEC;
4846 *_u += USEC_PER_DAY;
4852 static int shutdown_parse_argv(int argc, char *argv[]) {
4859 static const struct option options[] = {
4860 { "help", no_argument, NULL, ARG_HELP },
4861 { "halt", no_argument, NULL, 'H' },
4862 { "poweroff", no_argument, NULL, 'P' },
4863 { "reboot", no_argument, NULL, 'r' },
4864 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
4865 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4866 { NULL, 0, NULL, 0 }
4874 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
4882 arg_action = ACTION_HALT;
4886 arg_action = ACTION_POWEROFF;
4891 arg_action = ACTION_KEXEC;
4893 arg_action = ACTION_REBOOT;
4897 arg_action = ACTION_KEXEC;
4901 if (arg_action != ACTION_HALT)
4902 arg_action = ACTION_POWEROFF;
4915 /* Compatibility nops */
4919 arg_action = ACTION_CANCEL_SHUTDOWN;
4926 log_error("Unknown option code '%c'.", c);
4931 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
4932 r = parse_time_spec(argv[optind], &arg_when);
4934 log_error("Failed to parse time specification: %s", argv[optind]);
4938 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
4940 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
4941 /* No time argument for shutdown cancel */
4942 arg_wall = argv + optind;
4943 else if (argc > optind + 1)
4944 /* We skip the time argument */
4945 arg_wall = argv + optind + 1;
4952 static int telinit_parse_argv(int argc, char *argv[]) {
4959 static const struct option options[] = {
4960 { "help", no_argument, NULL, ARG_HELP },
4961 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4962 { NULL, 0, NULL, 0 }
4965 static const struct {
4969 { '0', ACTION_POWEROFF },
4970 { '6', ACTION_REBOOT },
4971 { '1', ACTION_RESCUE },
4972 { '2', ACTION_RUNLEVEL2 },
4973 { '3', ACTION_RUNLEVEL3 },
4974 { '4', ACTION_RUNLEVEL4 },
4975 { '5', ACTION_RUNLEVEL5 },
4976 { 's', ACTION_RESCUE },
4977 { 'S', ACTION_RESCUE },
4978 { 'q', ACTION_RELOAD },
4979 { 'Q', ACTION_RELOAD },
4980 { 'u', ACTION_REEXEC },
4981 { 'U', ACTION_REEXEC }
4990 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
5005 log_error("Unknown option code '%c'.", c);
5010 if (optind >= argc) {
5015 if (optind + 1 < argc) {
5016 log_error("Too many arguments.");
5020 if (strlen(argv[optind]) != 1) {
5021 log_error("Expected single character argument.");
5025 for (i = 0; i < ELEMENTSOF(table); i++)
5026 if (table[i].from == argv[optind][0])
5029 if (i >= ELEMENTSOF(table)) {
5030 log_error("Unknown command '%s'.", argv[optind]);
5034 arg_action = table[i].to;
5041 static int runlevel_parse_argv(int argc, char *argv[]) {
5047 static const struct option options[] = {
5048 { "help", no_argument, NULL, ARG_HELP },
5049 { NULL, 0, NULL, 0 }
5057 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
5068 log_error("Unknown option code '%c'.", c);
5073 if (optind < argc) {
5074 log_error("Too many arguments.");
5081 static int parse_argv(int argc, char *argv[]) {
5085 if (program_invocation_short_name) {
5087 if (strstr(program_invocation_short_name, "halt")) {
5088 arg_action = ACTION_HALT;
5089 return halt_parse_argv(argc, argv);
5090 } else if (strstr(program_invocation_short_name, "poweroff")) {
5091 arg_action = ACTION_POWEROFF;
5092 return halt_parse_argv(argc, argv);
5093 } else if (strstr(program_invocation_short_name, "reboot")) {
5095 arg_action = ACTION_KEXEC;
5097 arg_action = ACTION_REBOOT;
5098 return halt_parse_argv(argc, argv);
5099 } else if (strstr(program_invocation_short_name, "shutdown")) {
5100 arg_action = ACTION_POWEROFF;
5101 return shutdown_parse_argv(argc, argv);
5102 } else if (strstr(program_invocation_short_name, "init")) {
5104 if (sd_booted() > 0) {
5105 arg_action = ACTION_INVALID;
5106 return telinit_parse_argv(argc, argv);
5108 /* Hmm, so some other init system is
5109 * running, we need to forward this
5110 * request to it. For now we simply
5111 * guess that it is Upstart. */
5113 execv(TELINIT, argv);
5115 log_error("Couldn't find an alternative telinit implementation to spawn.");
5119 } else if (strstr(program_invocation_short_name, "runlevel")) {
5120 arg_action = ACTION_RUNLEVEL;
5121 return runlevel_parse_argv(argc, argv);
5125 arg_action = ACTION_SYSTEMCTL;
5126 return systemctl_parse_argv(argc, argv);
5129 static int action_to_runlevel(void) {
5131 static const char table[_ACTION_MAX] = {
5132 [ACTION_HALT] = '0',
5133 [ACTION_POWEROFF] = '0',
5134 [ACTION_REBOOT] = '6',
5135 [ACTION_RUNLEVEL2] = '2',
5136 [ACTION_RUNLEVEL3] = '3',
5137 [ACTION_RUNLEVEL4] = '4',
5138 [ACTION_RUNLEVEL5] = '5',
5139 [ACTION_RESCUE] = '1'
5142 assert(arg_action < _ACTION_MAX);
5144 return table[arg_action];
5147 static int talk_upstart(void) {
5148 DBusMessage _cleanup_dbus_message_unref_ *m = NULL, *reply = NULL;
5149 DBusError _cleanup_dbus_error_free_ error;
5150 int previous, rl, r;
5152 env1_buf[] = "RUNLEVEL=X",
5153 env2_buf[] = "PREVLEVEL=X";
5154 char *env1 = env1_buf, *env2 = env2_buf;
5155 const char *emit = "runlevel";
5156 dbus_bool_t b_false = FALSE;
5157 DBusMessageIter iter, sub;
5158 DBusConnection *bus;
5160 dbus_error_init(&error);
5162 if (!(rl = action_to_runlevel()))
5165 if (utmp_get_runlevel(&previous, NULL) < 0)
5168 if (!(bus = dbus_connection_open_private("unix:abstract=/com/ubuntu/upstart", &error))) {
5169 if (dbus_error_has_name(&error, DBUS_ERROR_NO_SERVER)) {
5174 log_error("Failed to connect to Upstart bus: %s", bus_error_message(&error));
5179 if ((r = bus_check_peercred(bus)) < 0) {
5180 log_error("Failed to verify owner of bus.");
5184 if (!(m = dbus_message_new_method_call(
5185 "com.ubuntu.Upstart",
5186 "/com/ubuntu/Upstart",
5187 "com.ubuntu.Upstart0_6",
5190 log_error("Could not allocate message.");
5195 dbus_message_iter_init_append(m, &iter);
5197 env1_buf[sizeof(env1_buf)-2] = rl;
5198 env2_buf[sizeof(env2_buf)-2] = previous;
5200 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &emit) ||
5201 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub) ||
5202 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env1) ||
5203 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env2) ||
5204 !dbus_message_iter_close_container(&iter, &sub) ||
5205 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b_false)) {
5206 log_error("Could not append arguments to message.");
5211 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
5213 if (bus_error_is_no_service(&error)) {
5218 log_error("Failed to issue method call: %s", bus_error_message(&error));
5227 dbus_connection_flush(bus);
5228 dbus_connection_close(bus);
5229 dbus_connection_unref(bus);
5235 static int talk_initctl(void) {
5236 struct init_request request = {};
5238 int _cleanup_close_ fd = -1;
5241 rl = action_to_runlevel();
5245 request.magic = INIT_MAGIC;
5246 request.sleeptime = 0;
5247 request.cmd = INIT_CMD_RUNLVL;
5248 request.runlevel = rl;
5250 fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY);
5252 if (errno == ENOENT)
5255 log_error("Failed to open "INIT_FIFO": %m");
5260 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
5262 log_error("Failed to write to "INIT_FIFO": %m");
5263 return errno > 0 ? -errno : -EIO;
5269 static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
5271 static const struct {
5279 int (* const dispatch)(DBusConnection *bus, char **args);
5281 { "list-units", LESS, 1, list_units },
5282 { "list-unit-files", EQUAL, 1, list_unit_files },
5283 { "list-jobs", EQUAL, 1, list_jobs },
5284 { "clear-jobs", EQUAL, 1, daemon_reload },
5285 { "load", MORE, 2, load_unit },
5286 { "cancel", MORE, 2, cancel_job },
5287 { "start", MORE, 2, start_unit },
5288 { "stop", MORE, 2, start_unit },
5289 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5290 { "reload", MORE, 2, start_unit },
5291 { "restart", MORE, 2, start_unit },
5292 { "try-restart", MORE, 2, start_unit },
5293 { "reload-or-restart", MORE, 2, start_unit },
5294 { "reload-or-try-restart", MORE, 2, start_unit },
5295 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
5296 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5297 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
5298 { "isolate", EQUAL, 2, start_unit },
5299 { "set-cgroup", MORE, 3, set_cgroup },
5300 { "unset-cgroup", MORE, 3, set_cgroup },
5301 { "get-cgroup-attr", MORE, 3, get_cgroup_attr },
5302 { "set-cgroup-attr", MORE, 4, set_cgroup_attr },
5303 { "unset-cgroup-attr", MORE, 3, set_cgroup },
5304 { "kill", MORE, 2, kill_unit },
5305 { "is-active", MORE, 2, check_unit_active },
5306 { "check", MORE, 2, check_unit_active },
5307 { "is-failed", MORE, 2, check_unit_failed },
5308 { "show", MORE, 1, show },
5309 { "status", MORE, 1, show },
5310 { "help", MORE, 2, show },
5311 { "dump", EQUAL, 1, dump },
5312 { "snapshot", LESS, 2, snapshot },
5313 { "delete", MORE, 2, delete_snapshot },
5314 { "daemon-reload", EQUAL, 1, daemon_reload },
5315 { "daemon-reexec", EQUAL, 1, daemon_reload },
5316 { "show-environment", EQUAL, 1, show_enviroment },
5317 { "set-environment", MORE, 2, set_environment },
5318 { "unset-environment", MORE, 2, set_environment },
5319 { "halt", EQUAL, 1, start_special },
5320 { "poweroff", EQUAL, 1, start_special },
5321 { "reboot", EQUAL, 1, start_special },
5322 { "kexec", EQUAL, 1, start_special },
5323 { "suspend", EQUAL, 1, start_special },
5324 { "hibernate", EQUAL, 1, start_special },
5325 { "hybrid-sleep", EQUAL, 1, start_special },
5326 { "default", EQUAL, 1, start_special },
5327 { "rescue", EQUAL, 1, start_special },
5328 { "emergency", EQUAL, 1, start_special },
5329 { "exit", EQUAL, 1, start_special },
5330 { "reset-failed", MORE, 1, reset_failed },
5331 { "enable", MORE, 2, enable_unit },
5332 { "disable", MORE, 2, enable_unit },
5333 { "is-enabled", MORE, 2, unit_is_enabled },
5334 { "reenable", MORE, 2, enable_unit },
5335 { "preset", MORE, 2, enable_unit },
5336 { "mask", MORE, 2, enable_unit },
5337 { "unmask", MORE, 2, enable_unit },
5338 { "link", MORE, 2, enable_unit },
5339 { "switch-root", MORE, 2, switch_root },
5340 { "list-dependencies", LESS, 2, list_dependencies },
5350 left = argc - optind;
5353 /* Special rule: no arguments means "list-units" */
5356 if (streq(argv[optind], "help") && !argv[optind+1]) {
5357 log_error("This command expects one or more "
5358 "unit names. Did you mean --help?");
5362 for (i = 0; i < ELEMENTSOF(verbs); i++)
5363 if (streq(argv[optind], verbs[i].verb))
5366 if (i >= ELEMENTSOF(verbs)) {
5367 log_error("Unknown operation '%s'.", argv[optind]);
5372 switch (verbs[i].argc_cmp) {
5375 if (left != verbs[i].argc) {
5376 log_error("Invalid number of arguments.");
5383 if (left < verbs[i].argc) {
5384 log_error("Too few arguments.");
5391 if (left > verbs[i].argc) {
5392 log_error("Too many arguments.");
5399 assert_not_reached("Unknown comparison operator.");
5402 /* Require a bus connection for all operations but
5404 if (!streq(verbs[i].verb, "enable") &&
5405 !streq(verbs[i].verb, "disable") &&
5406 !streq(verbs[i].verb, "is-enabled") &&
5407 !streq(verbs[i].verb, "list-unit-files") &&
5408 !streq(verbs[i].verb, "reenable") &&
5409 !streq(verbs[i].verb, "preset") &&
5410 !streq(verbs[i].verb, "mask") &&
5411 !streq(verbs[i].verb, "unmask") &&
5412 !streq(verbs[i].verb, "link")) {
5414 if (running_in_chroot() > 0) {
5415 log_info("Running in chroot, ignoring request.");
5419 if (((!streq(verbs[i].verb, "reboot") &&
5420 !streq(verbs[i].verb, "halt") &&
5421 !streq(verbs[i].verb, "poweroff")) || arg_force <= 0) && !bus) {
5422 log_error("Failed to get D-Bus connection: %s",
5423 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5429 if (!bus && !avoid_bus()) {
5430 log_error("Failed to get D-Bus connection: %s",
5431 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5436 return verbs[i].dispatch(bus, argv + optind);
5439 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
5440 int _cleanup_close_ fd;
5441 struct sd_shutdown_command c = {
5447 union sockaddr_union sockaddr = {
5448 .un.sun_family = AF_UNIX,
5449 .un.sun_path = "/run/systemd/shutdownd",
5451 struct iovec iovec[2] = {
5452 {.iov_base = (char*) &c,
5453 .iov_len = offsetof(struct sd_shutdown_command, wall_message),
5456 struct msghdr msghdr = {
5457 .msg_name = &sockaddr,
5458 .msg_namelen = offsetof(struct sockaddr_un, sun_path)
5459 + sizeof("/run/systemd/shutdownd") - 1,
5464 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
5468 if (!isempty(message)) {
5469 iovec[1].iov_base = (char*) message;
5470 iovec[1].iov_len = strlen(message);
5471 msghdr.msg_iovlen++;
5474 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0)
5480 static int reload_with_fallback(DBusConnection *bus) {
5483 /* First, try systemd via D-Bus. */
5484 if (daemon_reload(bus, NULL) >= 0)
5488 /* Nothing else worked, so let's try signals */
5489 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
5491 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
5492 log_error("kill() failed: %m");
5499 static int start_with_fallback(DBusConnection *bus) {
5502 /* First, try systemd via D-Bus. */
5503 if (start_unit(bus, NULL) >= 0)
5507 /* Hmm, talking to systemd via D-Bus didn't work. Then
5508 * let's try to talk to Upstart via D-Bus. */
5509 if (talk_upstart() > 0)
5512 /* Nothing else worked, so let's try
5514 if (talk_initctl() > 0)
5517 log_error("Failed to talk to init daemon.");
5521 warn_wall(arg_action);
5525 static _noreturn_ void halt_now(enum action a) {
5527 /* Make sure C-A-D is handled by the kernel from this
5529 reboot(RB_ENABLE_CAD);
5534 log_info("Halting.");
5535 reboot(RB_HALT_SYSTEM);
5538 case ACTION_POWEROFF:
5539 log_info("Powering off.");
5540 reboot(RB_POWER_OFF);
5544 log_info("Rebooting.");
5545 reboot(RB_AUTOBOOT);
5549 assert_not_reached("Unknown halt action.");
5552 assert_not_reached("Uh? This shouldn't happen.");
5555 static int halt_main(DBusConnection *bus) {
5558 r = check_inhibitors(bus, arg_action);
5562 if (geteuid() != 0) {
5563 /* Try logind if we are a normal user and no special
5564 * mode applies. Maybe PolicyKit allows us to shutdown
5567 if (arg_when <= 0 &&
5570 (arg_action == ACTION_POWEROFF ||
5571 arg_action == ACTION_REBOOT)) {
5572 r = reboot_with_logind(bus, arg_action);
5577 log_error("Must be root.");
5582 char _cleanup_free_ *m;
5584 m = strv_join(arg_wall, " ");
5585 r = send_shutdownd(arg_when,
5586 arg_action == ACTION_HALT ? 'H' :
5587 arg_action == ACTION_POWEROFF ? 'P' :
5588 arg_action == ACTION_KEXEC ? 'K' :
5595 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
5597 char date[FORMAT_TIMESTAMP_MAX];
5599 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
5600 format_timestamp(date, sizeof(date), arg_when));
5605 if (!arg_dry && !arg_force)
5606 return start_with_fallback(bus);
5609 if (sd_booted() > 0)
5610 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
5612 r = utmp_put_shutdown();
5614 log_warning("Failed to write utmp record: %s", strerror(-r));
5621 halt_now(arg_action);
5622 /* We should never reach this. */
5626 static int runlevel_main(void) {
5627 int r, runlevel, previous;
5629 r = utmp_get_runlevel(&runlevel, &previous);
5636 previous <= 0 ? 'N' : previous,
5637 runlevel <= 0 ? 'N' : runlevel);
5642 int main(int argc, char*argv[]) {
5643 int r, retval = EXIT_FAILURE;
5644 DBusConnection *bus = NULL;
5645 DBusError _cleanup_dbus_error_free_ error;
5647 dbus_error_init(&error);
5649 setlocale(LC_ALL, "");
5650 log_parse_environment();
5653 r = parse_argv(argc, argv);
5657 retval = EXIT_SUCCESS;
5661 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
5662 * let's shortcut this */
5663 if (arg_action == ACTION_RUNLEVEL) {
5664 r = runlevel_main();
5665 retval = r < 0 ? EXIT_FAILURE : r;
5669 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
5670 log_info("Running in chroot, ignoring request.");
5676 if (arg_transport == TRANSPORT_NORMAL)
5677 bus_connect(arg_scope == UNIT_FILE_SYSTEM ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &bus, &private_bus, &error);
5678 else if (arg_transport == TRANSPORT_POLKIT) {
5679 bus_connect_system_polkit(&bus, &error);
5680 private_bus = false;
5681 } else if (arg_transport == TRANSPORT_SSH) {
5682 bus_connect_system_ssh(NULL, arg_host, &bus, &error);
5683 private_bus = false;
5685 assert_not_reached("Uh, invalid transport...");
5688 switch (arg_action) {
5690 case ACTION_SYSTEMCTL:
5691 r = systemctl_main(bus, argc, argv, &error);
5695 case ACTION_POWEROFF:
5701 case ACTION_RUNLEVEL2:
5702 case ACTION_RUNLEVEL3:
5703 case ACTION_RUNLEVEL4:
5704 case ACTION_RUNLEVEL5:
5706 case ACTION_EMERGENCY:
5707 case ACTION_DEFAULT:
5708 r = start_with_fallback(bus);
5713 r = reload_with_fallback(bus);
5716 case ACTION_CANCEL_SHUTDOWN: {
5720 m = strv_join(arg_wall, " ");
5722 retval = EXIT_FAILURE;
5726 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
5728 log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r));
5733 case ACTION_INVALID:
5734 case ACTION_RUNLEVEL:
5736 assert_not_reached("Unknown action");
5739 retval = r < 0 ? EXIT_FAILURE : r;
5743 dbus_connection_flush(bus);
5744 dbus_connection_close(bus);
5745 dbus_connection_unref(bus);
5750 strv_free(arg_types);
5751 strv_free(arg_load_states);
5752 strv_free(arg_properties);
5755 ask_password_agent_close();
5756 polkit_agent_close();