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_states = NULL;
73 static char **arg_properties = NULL;
74 static bool arg_all = false;
75 static enum dependency {
80 } arg_dependency = DEPENDENCY_FORWARD;
81 static const char *arg_job_mode = "replace";
82 static UnitFileScope arg_scope = UNIT_FILE_SYSTEM;
83 static bool arg_no_block = false;
84 static bool arg_no_legend = false;
85 static bool arg_no_pager = false;
86 static bool arg_no_wtmp = false;
87 static bool arg_no_wall = false;
88 static bool arg_no_reload = false;
89 static bool arg_show_types = false;
90 static bool arg_ignore_inhibitors = false;
91 static bool arg_dry = false;
92 static bool arg_quiet = false;
93 static bool arg_full = false;
94 static int arg_force = 0;
95 static bool arg_ask_password = true;
96 static bool arg_runtime = false;
97 static char **arg_wall = NULL;
98 static const char *arg_kill_who = NULL;
99 static int arg_signal = SIGTERM;
100 static const char *arg_root = NULL;
101 static usec_t arg_when = 0;
123 ACTION_CANCEL_SHUTDOWN,
125 } arg_action = ACTION_SYSTEMCTL;
126 static enum transport {
130 } arg_transport = TRANSPORT_NORMAL;
131 static char *arg_host = NULL;
132 static char *arg_user = NULL;
133 static unsigned arg_lines = 10;
134 static OutputMode arg_output = OUTPUT_SHORT;
135 static bool arg_plain = false;
137 static bool private_bus = false;
139 static int daemon_reload(DBusConnection *bus, char **args);
140 static void halt_now(enum action a);
142 static void pager_open_if_enabled(void) {
150 static void ask_password_agent_open_if_enabled(void) {
152 /* Open the password agent as a child process if necessary */
154 if (!arg_ask_password)
157 if (arg_scope != UNIT_FILE_SYSTEM)
160 ask_password_agent_open();
164 static void polkit_agent_open_if_enabled(void) {
166 /* Open the polkit agent as a child process if necessary */
168 if (!arg_ask_password)
171 if (arg_scope != UNIT_FILE_SYSTEM)
178 static int translate_bus_error_to_exit_status(int r, const DBusError *error) {
181 if (!dbus_error_is_set(error))
184 if (dbus_error_has_name(error, DBUS_ERROR_ACCESS_DENIED) ||
185 dbus_error_has_name(error, BUS_ERROR_ONLY_BY_DEPENDENCY) ||
186 dbus_error_has_name(error, BUS_ERROR_NO_ISOLATION) ||
187 dbus_error_has_name(error, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE))
188 return EXIT_NOPERMISSION;
190 if (dbus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT))
191 return EXIT_NOTINSTALLED;
193 if (dbus_error_has_name(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE) ||
194 dbus_error_has_name(error, BUS_ERROR_NOT_SUPPORTED))
195 return EXIT_NOTIMPLEMENTED;
197 if (dbus_error_has_name(error, BUS_ERROR_LOAD_FAILED))
198 return EXIT_NOTCONFIGURED;
206 static void warn_wall(enum action a) {
207 static const char *table[_ACTION_MAX] = {
208 [ACTION_HALT] = "The system is going down for system halt NOW!",
209 [ACTION_REBOOT] = "The system is going down for reboot NOW!",
210 [ACTION_POWEROFF] = "The system is going down for power-off NOW!",
211 [ACTION_KEXEC] = "The system is going down for kexec reboot NOW!",
212 [ACTION_RESCUE] = "The system is going down to rescue mode NOW!",
213 [ACTION_EMERGENCY] = "The system is going down to emergency mode NOW!",
214 [ACTION_CANCEL_SHUTDOWN] = "The system shutdown has been cancelled NOW!"
221 _cleanup_free_ char *p;
223 p = strv_join(arg_wall, " ");
238 utmp_wall(table[a], NULL);
241 static bool avoid_bus(void) {
243 if (running_in_chroot() > 0)
246 if (sd_booted() <= 0)
249 if (!isempty(arg_root))
252 if (arg_scope == UNIT_FILE_GLOBAL)
258 static int compare_unit_info(const void *a, const void *b) {
260 const struct unit_info *u = a, *v = b;
262 d1 = strrchr(u->id, '.');
263 d2 = strrchr(v->id, '.');
268 r = strcasecmp(d1, d2);
273 return strcasecmp(u->id, v->id);
276 static bool output_show_unit(const struct unit_info *u) {
279 if (!strv_isempty(arg_states))
280 return strv_contains(arg_states, u->load_state) || strv_contains(arg_states, u->sub_state) || strv_contains(arg_states, u->active_state);
282 return (!arg_types || ((dot = strrchr(u->id, '.')) &&
283 strv_find(arg_types, dot+1))) &&
284 (arg_all || !(streq(u->active_state, "inactive")
285 || u->following[0]) || u->job_id > 0);
288 static void output_units_list(const struct unit_info *unit_infos, unsigned c) {
289 unsigned id_len, max_id_len, active_len, sub_len, job_len, desc_len, n_shown = 0;
290 const struct unit_info *u;
293 max_id_len = sizeof("UNIT")-1;
294 active_len = sizeof("ACTIVE")-1;
295 sub_len = sizeof("SUB")-1;
296 job_len = sizeof("JOB")-1;
299 for (u = unit_infos; u < unit_infos + c; u++) {
300 if (!output_show_unit(u))
303 max_id_len = MAX(max_id_len, strlen(u->id));
304 active_len = MAX(active_len, strlen(u->active_state));
305 sub_len = MAX(sub_len, strlen(u->sub_state));
306 if (u->job_id != 0) {
307 job_len = MAX(job_len, strlen(u->job_type));
314 id_len = MIN(max_id_len, 25u);
315 basic_len = 5 + id_len + 5 + active_len + sub_len;
317 basic_len += job_len + 1;
318 if (basic_len < (unsigned) columns()) {
319 unsigned extra_len, incr;
320 extra_len = columns() - basic_len;
321 /* Either UNIT already got 25, or is fully satisfied.
322 * Grant up to 25 to DESC now. */
323 incr = MIN(extra_len, 25u);
326 /* split the remaining space between UNIT and DESC,
327 * but do not give UNIT more than it needs. */
329 incr = MIN(extra_len / 2, max_id_len - id_len);
331 desc_len += extra_len - incr;
337 for (u = unit_infos; u < unit_infos + c; u++) {
338 _cleanup_free_ char *e = NULL;
339 const char *on_loaded, *off_loaded, *on = "";
340 const char *on_active, *off_active, *off = "";
342 if (!output_show_unit(u))
345 if (!n_shown && !arg_no_legend) {
346 printf("%-*s %-6s %-*s %-*s ", id_len, "UNIT", "LOAD",
347 active_len, "ACTIVE", sub_len, "SUB");
349 printf("%-*s ", job_len, "JOB");
350 if (!arg_full && arg_no_pager)
351 printf("%.*s\n", desc_len, "DESCRIPTION");
353 printf("%s\n", "DESCRIPTION");
358 if (streq(u->load_state, "error") ||
359 streq(u->load_state, "not-found")) {
360 on_loaded = on = ansi_highlight_red();
361 off_loaded = off = ansi_highlight_off();
363 on_loaded = off_loaded = "";
365 if (streq(u->active_state, "failed")) {
366 on_active = on = ansi_highlight_red();
367 off_active = off = ansi_highlight_off();
369 on_active = off_active = "";
371 e = arg_full ? NULL : ellipsize(u->id, id_len, 33);
373 printf("%s%-*s%s %s%-6s%s %s%-*s %-*s%s %-*s",
374 on, id_len, e ? e : u->id, off,
375 on_loaded, u->load_state, off_loaded,
376 on_active, active_len, u->active_state,
377 sub_len, u->sub_state, off_active,
378 job_count ? job_len + 1 : 0, u->job_id ? u->job_type : "");
379 if (!arg_full && arg_no_pager)
380 printf("%.*s\n", desc_len, u->description);
382 printf("%s\n", u->description);
385 if (!arg_no_legend) {
386 const char *on, *off;
389 printf("\nLOAD = Reflects whether the unit definition was properly loaded.\n"
390 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
391 "SUB = The low-level unit activation state, values depend on unit type.\n");
393 printf("JOB = Pending job for the unit.\n");
395 on = ansi_highlight();
396 off = ansi_highlight_off();
398 on = ansi_highlight_red();
399 off = ansi_highlight_off();
403 printf("%s%u loaded units listed.%s\n"
404 "To show all installed unit files use 'systemctl list-unit-files'.\n",
407 printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
408 "To show all installed unit files use 'systemctl list-unit-files'.\n",
413 static int get_unit_list(
416 struct unit_info **unit_infos,
419 DBusMessageIter iter, sub;
427 r = bus_method_call_with_reply(
429 "org.freedesktop.systemd1",
430 "/org/freedesktop/systemd1",
431 "org.freedesktop.systemd1.Manager",
439 if (!dbus_message_iter_init(*reply, &iter) ||
440 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
441 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
442 log_error("Failed to parse reply.");
446 dbus_message_iter_recurse(&iter, &sub);
448 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
449 if (!GREEDY_REALLOC(*unit_infos, size, *c + 1))
452 bus_parse_unit_info(&sub, *unit_infos + *c);
455 dbus_message_iter_next(&sub);
461 static int list_units(DBusConnection *bus, char **args) {
462 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
463 _cleanup_free_ struct unit_info *unit_infos = NULL;
467 pager_open_if_enabled();
469 r = get_unit_list(bus, &reply, &unit_infos, &c);
473 qsort(unit_infos, c, sizeof(struct unit_info), compare_unit_info);
475 output_units_list(unit_infos, c);
480 static int get_triggered_units(
482 const char* unit_path,
485 const char *interface = "org.freedesktop.systemd1.Unit",
486 *triggers_property = "Triggers";
487 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
488 DBusMessageIter iter, sub;
491 r = bus_method_call_with_reply(bus,
492 "org.freedesktop.systemd1",
494 "org.freedesktop.DBus.Properties",
498 DBUS_TYPE_STRING, &interface,
499 DBUS_TYPE_STRING, &triggers_property,
504 if (!dbus_message_iter_init(reply, &iter) ||
505 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
506 log_error("Failed to parse reply.");
510 dbus_message_iter_recurse(&iter, &sub);
511 dbus_message_iter_recurse(&sub, &iter);
514 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
517 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
518 log_error("Failed to parse reply.");
522 dbus_message_iter_get_basic(&sub, &unit);
523 r = strv_extend(triggered, unit);
527 dbus_message_iter_next(&sub);
533 static int get_listening(DBusConnection *bus, const char* unit_path,
534 char*** listen, unsigned *c)
536 const char *interface = "org.freedesktop.systemd1.Socket",
537 *listen_property = "Listen";
538 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
539 DBusMessageIter iter, sub;
542 r = bus_method_call_with_reply(bus,
543 "org.freedesktop.systemd1",
545 "org.freedesktop.DBus.Properties",
549 DBUS_TYPE_STRING, &interface,
550 DBUS_TYPE_STRING, &listen_property,
555 if (!dbus_message_iter_init(reply, &iter) ||
556 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
557 log_error("Failed to parse reply.");
561 dbus_message_iter_recurse(&iter, &sub);
562 dbus_message_iter_recurse(&sub, &iter);
565 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
566 DBusMessageIter sub2;
567 const char *type, *path;
569 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
570 log_error("Failed to parse reply.");
574 dbus_message_iter_recurse(&sub, &sub2);
576 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
577 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0) {
578 r = strv_extend(listen, type);
582 r = strv_extend(listen, path);
589 dbus_message_iter_next(&sub);
601 /* Note: triggered is a list here, although it almost certainly
602 * will always be one unit. Nevertheless, dbus API allows for multiple
603 * values, so let's follow that.*/
606 /* The strv above is shared. free is set only in the first one. */
610 static int socket_info_compare(struct socket_info *a, struct socket_info *b) {
611 int o = strcmp(a->path, b->path);
613 o = strcmp(a->type, b->type);
617 static int output_sockets_list(struct socket_info *socket_infos, unsigned cs) {
618 struct socket_info *s;
619 unsigned pathlen = sizeof("LISTEN") - 1,
620 typelen = (sizeof("TYPE") - 1) * arg_show_types,
621 socklen = sizeof("UNIT") - 1,
622 servlen = sizeof("ACTIVATES") - 1;
623 const char *on, *off;
625 for (s = socket_infos; s < socket_infos + cs; s++) {
629 socklen = MAX(socklen, strlen(s->id));
631 typelen = MAX(typelen, strlen(s->type));
632 pathlen = MAX(pathlen, strlen(s->path));
634 STRV_FOREACH(a, s->triggered)
635 tmp += strlen(*a) + 2*(a != s->triggered);
636 servlen = MAX(servlen, tmp);
641 printf("%-*s %-*.*s%-*s %s\n",
643 typelen + arg_show_types, typelen + arg_show_types, "TYPE ",
647 for (s = socket_infos; s < socket_infos + cs; s++) {
651 printf("%-*s %-*s %-*s",
652 pathlen, s->path, typelen, s->type, socklen, s->id);
655 pathlen, s->path, socklen, s->id);
656 STRV_FOREACH(a, s->triggered)
658 a == s->triggered ? "" : ",", *a);
662 on = ansi_highlight();
663 off = ansi_highlight_off();
667 on = ansi_highlight_red();
668 off = ansi_highlight_off();
671 if (!arg_no_legend) {
672 printf("%s%u sockets listed.%s\n", on, cs, off);
674 printf("Pass --all to see loaded but inactive sockets, too.\n");
680 static int list_sockets(DBusConnection *bus, char **args) {
681 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
682 _cleanup_free_ struct unit_info *unit_infos = NULL;
683 struct socket_info *socket_infos = NULL;
684 const struct unit_info *u;
685 struct socket_info *s;
686 unsigned cu = 0, cs = 0;
690 pager_open_if_enabled();
692 r = get_unit_list(bus, &reply, &unit_infos, &cu);
696 for (u = unit_infos; u < unit_infos + cu; u++) {
698 _cleanup_strv_free_ char **listen = NULL, **triggered = NULL;
701 if (!output_show_unit(u))
704 if ((dot = strrchr(u->id, '.')) && !streq(dot+1, "socket"))
707 r = get_triggered_units(bus, u->unit_path, &triggered);
711 r = get_listening(bus, u->unit_path, &listen, &c);
715 if (!GREEDY_REALLOC(socket_infos, size, cs + c)) {
720 for (i = 0; i < c; i++)
721 socket_infos[cs + i] = (struct socket_info) {
724 .path = listen[i*2 + 1],
725 .triggered = triggered,
726 .own_triggered = i==0,
729 /* from this point on we will cleanup those socket_infos */
732 listen = triggered = NULL; /* avoid cleanup */
735 qsort(socket_infos, cs, sizeof(struct socket_info),
736 (__compar_fn_t) socket_info_compare);
738 output_sockets_list(socket_infos, cs);
741 assert(cs == 0 || socket_infos);
742 for (s = socket_infos; s < socket_infos + cs; s++) {
745 if (s->own_triggered)
746 strv_free(s->triggered);
753 static int compare_unit_file_list(const void *a, const void *b) {
755 const UnitFileList *u = a, *v = b;
757 d1 = strrchr(u->path, '.');
758 d2 = strrchr(v->path, '.');
763 r = strcasecmp(d1, d2);
768 return strcasecmp(path_get_file_name(u->path), path_get_file_name(v->path));
771 static bool output_show_unit_file(const UnitFileList *u) {
774 return !arg_types || ((dot = strrchr(u->path, '.')) && strv_find(arg_types, dot+1));
777 static void output_unit_file_list(const UnitFileList *units, unsigned c) {
778 unsigned max_id_len, id_cols, state_cols, n_shown = 0;
779 const UnitFileList *u;
781 max_id_len = sizeof("UNIT FILE")-1;
782 state_cols = sizeof("STATE")-1;
783 for (u = units; u < units + c; u++) {
784 if (!output_show_unit_file(u))
787 max_id_len = MAX(max_id_len, strlen(path_get_file_name(u->path)));
788 state_cols = MAX(state_cols, strlen(unit_file_state_to_string(u->state)));
793 id_cols = MIN(max_id_len, 25u);
794 basic_cols = 1 + id_cols + state_cols;
795 if (basic_cols < (unsigned) columns())
796 id_cols += MIN(columns() - basic_cols, max_id_len - id_cols);
798 id_cols = max_id_len;
801 printf("%-*s %-*s\n", id_cols, "UNIT FILE", state_cols, "STATE");
803 for (u = units; u < units + c; u++) {
804 _cleanup_free_ char *e = NULL;
805 const char *on, *off;
808 if (!output_show_unit_file(u))
813 if (u->state == UNIT_FILE_MASKED ||
814 u->state == UNIT_FILE_MASKED_RUNTIME ||
815 u->state == UNIT_FILE_DISABLED ||
816 u->state == UNIT_FILE_INVALID) {
817 on = ansi_highlight_red();
818 off = ansi_highlight_off();
819 } else if (u->state == UNIT_FILE_ENABLED) {
820 on = ansi_highlight_green();
821 off = ansi_highlight_off();
825 id = path_get_file_name(u->path);
827 e = arg_full ? NULL : ellipsize(id, id_cols, 33);
829 printf("%-*s %s%-*s%s\n",
831 on, state_cols, unit_file_state_to_string(u->state), off);
835 printf("\n%u unit files listed.\n", n_shown);
838 static int list_unit_files(DBusConnection *bus, char **args) {
839 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
840 _cleanup_free_ UnitFileList *units = NULL;
841 DBusMessageIter iter, sub, sub2;
842 unsigned c = 0, n_units = 0;
845 pager_open_if_enabled();
852 h = hashmap_new(string_hash_func, string_compare_func);
856 r = unit_file_get_list(arg_scope, arg_root, h);
858 unit_file_list_free(h);
859 log_error("Failed to get unit file list: %s", strerror(-r));
863 n_units = hashmap_size(h);
864 units = new(UnitFileList, n_units);
866 unit_file_list_free(h);
870 HASHMAP_FOREACH(u, h, i) {
871 memcpy(units + c++, u, sizeof(UnitFileList));
877 r = bus_method_call_with_reply(
879 "org.freedesktop.systemd1",
880 "/org/freedesktop/systemd1",
881 "org.freedesktop.systemd1.Manager",
889 if (!dbus_message_iter_init(reply, &iter) ||
890 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
891 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
892 log_error("Failed to parse reply.");
896 dbus_message_iter_recurse(&iter, &sub);
898 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
902 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT);
907 n_units = MAX(2*c, 16u);
908 w = realloc(units, sizeof(struct UnitFileList) * n_units);
917 dbus_message_iter_recurse(&sub, &sub2);
919 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->path, true) < 0 ||
920 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, false) < 0) {
921 log_error("Failed to parse reply.");
925 u->state = unit_file_state_from_string(state);
927 dbus_message_iter_next(&sub);
933 qsort(units, c, sizeof(UnitFileList), compare_unit_file_list);
934 output_unit_file_list(units, c);
940 static int list_dependencies_print(const char *name, int level, unsigned int branches, bool last) {
942 _cleanup_free_ char *n = NULL;
944 size_t max_len = MAX(columns(),20u);
947 for (i = level - 1; i >= 0; i--) {
949 if(len > max_len - 3 && !arg_full) {
950 printf("%s...\n",max_len % 2 ? "" : " ");
953 printf("%s", draw_special_char(branches & (1 << i) ? DRAW_TREE_VERT : DRAW_TREE_SPACE));
956 if(len > max_len - 3 && !arg_full) {
957 printf("%s...\n",max_len % 2 ? "" : " ");
960 printf("%s", draw_special_char(last ? DRAW_TREE_RIGHT : DRAW_TREE_BRANCH));
964 printf("%s\n", name);
968 n = ellipsize(name, max_len-len, 100);
976 static int list_dependencies_get_dependencies(DBusConnection *bus, const char *name, char ***deps) {
977 static const char *dependencies[] = {
978 [DEPENDENCY_FORWARD] = "Requires\0"
979 "RequiresOverridable\0"
981 "RequisiteOverridable\0"
983 [DEPENDENCY_REVERSE] = "RequiredBy\0"
984 "RequiredByOverridable\0"
987 [DEPENDENCY_AFTER] = "After\0",
988 [DEPENDENCY_BEFORE] = "Before\0",
991 _cleanup_free_ char *path;
992 const char *interface = "org.freedesktop.systemd1.Unit";
994 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
995 DBusMessageIter iter, sub, sub2, sub3;
1004 path = unit_dbus_path_from_name(name);
1010 r = bus_method_call_with_reply(
1012 "org.freedesktop.systemd1",
1014 "org.freedesktop.DBus.Properties",
1018 DBUS_TYPE_STRING, &interface,
1023 if (!dbus_message_iter_init(reply, &iter) ||
1024 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
1025 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
1026 log_error("Failed to parse reply.");
1031 dbus_message_iter_recurse(&iter, &sub);
1033 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1036 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_DICT_ENTRY);
1037 dbus_message_iter_recurse(&sub, &sub2);
1039 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &prop, true) < 0) {
1040 log_error("Failed to parse reply.");
1045 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
1046 log_error("Failed to parse reply.");
1051 dbus_message_iter_recurse(&sub2, &sub3);
1052 dbus_message_iter_next(&sub);
1054 assert(arg_dependency < ELEMENTSOF(dependencies));
1055 if (!nulstr_contains(dependencies[arg_dependency], prop))
1058 if (dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_ARRAY) {
1059 if (dbus_message_iter_get_element_type(&sub3) == DBUS_TYPE_STRING) {
1060 DBusMessageIter sub4;
1061 dbus_message_iter_recurse(&sub3, &sub4);
1063 while (dbus_message_iter_get_arg_type(&sub4) != DBUS_TYPE_INVALID) {
1066 assert(dbus_message_iter_get_arg_type(&sub4) == DBUS_TYPE_STRING);
1067 dbus_message_iter_get_basic(&sub4, &s);
1069 r = strv_extend(&ret, s);
1075 dbus_message_iter_next(&sub4);
1088 static int list_dependencies_compare(const void *_a, const void *_b) {
1089 const char **a = (const char**) _a, **b = (const char**) _b;
1090 if (unit_name_to_type(*a) == UNIT_TARGET && unit_name_to_type(*b) != UNIT_TARGET)
1092 if (unit_name_to_type(*a) != UNIT_TARGET && unit_name_to_type(*b) == UNIT_TARGET)
1094 return strcasecmp(*a, *b);
1097 static int list_dependencies_one(DBusConnection *bus, const char *name, int level, char ***units, unsigned int branches) {
1098 _cleanup_strv_free_ char **deps = NULL, **u;
1102 u = strv_append(*units, name);
1106 r = list_dependencies_get_dependencies(bus, name, &deps);
1110 qsort(deps, strv_length(deps), sizeof (char*), list_dependencies_compare);
1112 STRV_FOREACH(c, deps) {
1113 if (strv_contains(u, *c)) {
1115 r = list_dependencies_print("...", level + 1, (branches << 1) | (c[1] == NULL ? 0 : 1), 1);
1122 r = list_dependencies_print(*c, level, branches, c[1] == NULL);
1126 if (arg_all || unit_name_to_type(*c) == UNIT_TARGET) {
1127 r = list_dependencies_one(bus, *c, level + 1, &u, (branches << 1) | (c[1] == NULL ? 0 : 1));
1140 static int list_dependencies(DBusConnection *bus, char **args) {
1141 _cleanup_free_ char *unit = NULL;
1142 _cleanup_strv_free_ char **units = NULL;
1148 unit = unit_name_mangle(args[1]);
1153 u = SPECIAL_DEFAULT_TARGET;
1155 pager_open_if_enabled();
1159 return list_dependencies_one(bus, u, 0, &units, 0);
1162 static int get_default(DBusConnection *bus, char **args) {
1164 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1166 _cleanup_dbus_error_free_ DBusError error;
1168 dbus_error_init(&error);
1170 if (!bus || avoid_bus()) {
1171 r = unit_file_get_default(arg_scope, arg_root, &path);
1174 log_error("Operation failed: %s", strerror(-r));
1180 r = bus_method_call_with_reply(
1182 "org.freedesktop.systemd1",
1183 "/org/freedesktop/systemd1",
1184 "org.freedesktop.systemd1.Manager",
1191 log_error("Operation failed: %s", strerror(-r));
1195 if (!dbus_message_get_args(reply, &error,
1196 DBUS_TYPE_STRING, &path,
1197 DBUS_TYPE_INVALID)) {
1198 log_error("Failed to parse reply: %s", bus_error_message(&error));
1199 dbus_error_free(&error);
1205 printf("%s\n", path);
1208 if ((!bus || avoid_bus()) && path)
1217 char *name, *type, *state;
1220 static void list_jobs_print(struct job_info* jobs, size_t n) {
1223 const char *on, *off;
1224 bool shorten = false;
1226 assert(n == 0 || jobs);
1229 on = ansi_highlight_green();
1230 off = ansi_highlight_off();
1232 printf("%sNo jobs running.%s\n", on, off);
1236 pager_open_if_enabled();
1239 /* JOB UNIT TYPE STATE */
1240 unsigned l0 = 3, l1 = 4, l2 = 4, l3 = 5;
1242 for (i = 0, j = jobs; i < n; i++, j++) {
1243 assert(j->name && j->type && j->state);
1244 l0 = MAX(l0, DECIMAL_STR_WIDTH(j->id));
1245 l1 = MAX(l1, strlen(j->name));
1246 l2 = MAX(l2, strlen(j->type));
1247 l3 = MAX(l3, strlen(j->state));
1250 if (!arg_full && l0 + 1 + l1 + l2 + 1 + l3 > columns()) {
1251 l1 = MAX(33u, columns() - l0 - l2 - l3 - 3);
1256 printf("%*s %-*s %-*s %-*s\n",
1262 for (i = 0, j = jobs; i < n; i++, j++) {
1263 _cleanup_free_ char *e = NULL;
1265 if (streq(j->state, "running")) {
1266 on = ansi_highlight();
1267 off = ansi_highlight_off();
1271 e = shorten ? ellipsize(j->name, l1, 33) : NULL;
1272 printf("%*u %s%-*s%s %-*s %s%-*s%s\n",
1274 on, l1, e ? e : j->name, off,
1276 on, l3, j->state, off);
1280 on = ansi_highlight();
1281 off = ansi_highlight_off();
1284 printf("\n%s%zu jobs listed%s.\n", on, n, off);
1287 static int list_jobs(DBusConnection *bus, char **args) {
1288 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1289 DBusMessageIter iter, sub, sub2;
1291 struct job_info *jobs = NULL;
1292 size_t size = 0, used = 0;
1294 r = bus_method_call_with_reply(
1296 "org.freedesktop.systemd1",
1297 "/org/freedesktop/systemd1",
1298 "org.freedesktop.systemd1.Manager",
1306 if (!dbus_message_iter_init(reply, &iter) ||
1307 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
1308 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
1309 log_error("Failed to parse reply.");
1313 dbus_message_iter_recurse(&iter, &sub);
1315 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1316 const char *name, *type, *state, *job_path, *unit_path;
1319 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
1320 log_error("Failed to parse reply.");
1324 dbus_message_iter_recurse(&sub, &sub2);
1326 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &id, true) < 0 ||
1327 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
1328 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
1329 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, true) < 0 ||
1330 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &job_path, true) < 0 ||
1331 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, false) < 0) {
1332 log_error("Failed to parse reply.");
1337 if (!GREEDY_REALLOC(jobs, size, used + 1)) {
1342 jobs[used++] = (struct job_info) { id,
1346 if (!jobs[used-1].name || !jobs[used-1].type || !jobs[used-1].state) {
1351 dbus_message_iter_next(&sub);
1354 list_jobs_print(jobs, used);
1358 free(jobs[used].name);
1359 free(jobs[used].type);
1360 free(jobs[used].state);
1367 static int cancel_job(DBusConnection *bus, char **args) {
1372 if (strv_length(args) <= 1)
1373 return daemon_reload(bus, args);
1375 STRV_FOREACH(name, args+1) {
1379 r = safe_atou32(*name, &id);
1381 log_error("Failed to parse job id: %s", strerror(-r));
1385 r = bus_method_call_with_reply(
1387 "org.freedesktop.systemd1",
1388 "/org/freedesktop/systemd1",
1389 "org.freedesktop.systemd1.Manager",
1393 DBUS_TYPE_UINT32, &id,
1402 static int need_daemon_reload(DBusConnection *bus, const char *unit) {
1403 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1404 _cleanup_dbus_error_free_ DBusError error;
1405 dbus_bool_t b = FALSE;
1406 DBusMessageIter iter, sub;
1408 *interface = "org.freedesktop.systemd1.Unit",
1409 *property = "NeedDaemonReload",
1411 _cleanup_free_ char *n = NULL;
1414 dbus_error_init(&error);
1416 /* We ignore all errors here, since this is used to show a warning only */
1418 n = unit_name_mangle(unit);
1422 r = bus_method_call_with_reply(
1424 "org.freedesktop.systemd1",
1425 "/org/freedesktop/systemd1",
1426 "org.freedesktop.systemd1.Manager",
1430 DBUS_TYPE_STRING, &n,
1435 if (!dbus_message_get_args(reply, NULL,
1436 DBUS_TYPE_OBJECT_PATH, &path,
1440 dbus_message_unref(reply);
1443 r = bus_method_call_with_reply(
1445 "org.freedesktop.systemd1",
1447 "org.freedesktop.DBus.Properties",
1451 DBUS_TYPE_STRING, &interface,
1452 DBUS_TYPE_STRING, &property,
1457 if (!dbus_message_iter_init(reply, &iter) ||
1458 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
1461 dbus_message_iter_recurse(&iter, &sub);
1462 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_BOOLEAN)
1465 dbus_message_iter_get_basic(&sub, &b);
1469 typedef struct WaitData {
1476 static DBusHandlerResult wait_filter(DBusConnection *connection, DBusMessage *message, void *data) {
1477 _cleanup_dbus_error_free_ DBusError error;
1480 dbus_error_init(&error);
1486 log_debug("Got D-Bus request: %s.%s() on %s",
1487 dbus_message_get_interface(message),
1488 dbus_message_get_member(message),
1489 dbus_message_get_path(message));
1491 if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
1492 log_error("Warning! D-Bus connection terminated.");
1493 dbus_connection_close(connection);
1495 } else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
1497 const char *path, *result, *unit;
1499 if (dbus_message_get_args(message, &error,
1500 DBUS_TYPE_UINT32, &id,
1501 DBUS_TYPE_OBJECT_PATH, &path,
1502 DBUS_TYPE_STRING, &unit,
1503 DBUS_TYPE_STRING, &result,
1504 DBUS_TYPE_INVALID)) {
1506 free(set_remove(d->set, (char*) path));
1508 if (!isempty(result))
1509 d->result = strdup(result);
1512 d->name = strdup(unit);
1514 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1517 dbus_error_free(&error);
1518 if (dbus_message_get_args(message, &error,
1519 DBUS_TYPE_UINT32, &id,
1520 DBUS_TYPE_OBJECT_PATH, &path,
1521 DBUS_TYPE_STRING, &result,
1522 DBUS_TYPE_INVALID)) {
1523 /* Compatibility with older systemd versions <
1524 * 183 during upgrades. This should be dropped
1526 free(set_remove(d->set, (char*) path));
1529 d->result = strdup(result);
1531 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1535 log_error("Failed to parse message: %s", bus_error_message(&error));
1538 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1541 static int enable_wait_for_jobs(DBusConnection *bus) {
1549 dbus_error_init(&error);
1550 dbus_bus_add_match(bus,
1552 "sender='org.freedesktop.systemd1',"
1553 "interface='org.freedesktop.systemd1.Manager',"
1554 "member='JobRemoved',"
1555 "path='/org/freedesktop/systemd1'",
1558 if (dbus_error_is_set(&error)) {
1559 log_error("Failed to add match: %s", bus_error_message(&error));
1560 dbus_error_free(&error);
1564 /* This is slightly dirty, since we don't undo the match registrations. */
1568 static int wait_for_jobs(DBusConnection *bus, Set *s) {
1570 WaitData d = { .set = s };
1575 if (!dbus_connection_add_filter(bus, wait_filter, &d, NULL))
1578 while (!set_isempty(s)) {
1580 if (!dbus_connection_read_write_dispatch(bus, -1)) {
1581 log_error("Disconnected from bus.");
1582 return -ECONNREFUSED;
1589 if (streq(d.result, "timeout"))
1590 log_error("Job for %s timed out.", strna(d.name));
1591 else if (streq(d.result, "canceled"))
1592 log_error("Job for %s canceled.", strna(d.name));
1593 else if (streq(d.result, "dependency"))
1594 log_error("A dependency job for %s failed. See 'journalctl -xn' for details.", strna(d.name));
1595 else if (!streq(d.result, "done") && !streq(d.result, "skipped"))
1596 log_error("Job for %s failed. See 'systemctl status %s' and 'journalctl -xn' for details.", strna(d.name), strna(d.name));
1599 if (streq_ptr(d.result, "timeout"))
1601 else if (streq_ptr(d.result, "canceled"))
1603 else if (!streq_ptr(d.result, "done") && !streq_ptr(d.result, "skipped"))
1614 dbus_connection_remove_filter(bus, wait_filter, &d);
1618 static int check_one_unit(DBusConnection *bus, const char *name, char **check_states, bool quiet) {
1619 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1620 _cleanup_free_ char *n = NULL;
1621 DBusMessageIter iter, sub;
1623 *interface = "org.freedesktop.systemd1.Unit",
1624 *property = "ActiveState";
1625 const char *state, *path;
1631 dbus_error_init(&error);
1633 n = unit_name_mangle(name);
1637 r = bus_method_call_with_reply (
1639 "org.freedesktop.systemd1",
1640 "/org/freedesktop/systemd1",
1641 "org.freedesktop.systemd1.Manager",
1645 DBUS_TYPE_STRING, &n,
1648 dbus_error_free(&error);
1655 if (!dbus_message_get_args(reply, NULL,
1656 DBUS_TYPE_OBJECT_PATH, &path,
1657 DBUS_TYPE_INVALID)) {
1658 log_error("Failed to parse reply.");
1662 dbus_message_unref(reply);
1665 r = bus_method_call_with_reply(
1667 "org.freedesktop.systemd1",
1669 "org.freedesktop.DBus.Properties",
1673 DBUS_TYPE_STRING, &interface,
1674 DBUS_TYPE_STRING, &property,
1682 if (!dbus_message_iter_init(reply, &iter) ||
1683 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1684 log_error("Failed to parse reply.");
1688 dbus_message_iter_recurse(&iter, &sub);
1690 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1691 log_error("Failed to parse reply.");
1695 dbus_message_iter_get_basic(&sub, &state);
1700 return strv_find(check_states, state) ? 1 : 0;
1703 static void check_triggering_units(
1704 DBusConnection *bus,
1705 const char *unit_name) {
1707 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1708 DBusMessageIter iter, sub;
1709 const char *interface = "org.freedesktop.systemd1.Unit",
1710 *load_state_property = "LoadState",
1711 *triggered_by_property = "TriggeredBy",
1713 _cleanup_free_ char *unit_path = NULL, *n = NULL;
1714 bool print_warning_label = true;
1717 n = unit_name_mangle(unit_name);
1723 unit_path = unit_dbus_path_from_name(n);
1729 r = bus_method_call_with_reply(
1731 "org.freedesktop.systemd1",
1733 "org.freedesktop.DBus.Properties",
1737 DBUS_TYPE_STRING, &interface,
1738 DBUS_TYPE_STRING, &load_state_property,
1743 if (!dbus_message_iter_init(reply, &iter) ||
1744 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1745 log_error("Failed to parse reply.");
1749 dbus_message_iter_recurse(&iter, &sub);
1751 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1752 log_error("Failed to parse reply.");
1756 dbus_message_iter_get_basic(&sub, &state);
1758 if (streq(state, "masked"))
1761 dbus_message_unref(reply);
1764 r = bus_method_call_with_reply(
1766 "org.freedesktop.systemd1",
1768 "org.freedesktop.DBus.Properties",
1772 DBUS_TYPE_STRING, &interface,
1773 DBUS_TYPE_STRING, &triggered_by_property,
1778 if (!dbus_message_iter_init(reply, &iter) ||
1779 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1780 log_error("Failed to parse reply.");
1784 dbus_message_iter_recurse(&iter, &sub);
1785 dbus_message_iter_recurse(&sub, &iter);
1788 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1789 const char * const check_states[] = {
1794 const char *service_trigger;
1796 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1797 log_error("Failed to parse reply.");
1801 dbus_message_iter_get_basic(&sub, &service_trigger);
1803 r = check_one_unit(bus, service_trigger, (char**) check_states, true);
1807 if (print_warning_label) {
1808 log_warning("Warning: Stopping %s, but it can still be activated by:", unit_name);
1809 print_warning_label = false;
1812 log_warning(" %s", service_trigger);
1815 dbus_message_iter_next(&sub);
1819 static int start_unit_one(
1820 DBusConnection *bus,
1827 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1828 _cleanup_free_ char *n;
1837 n = unit_name_mangle(name);
1841 r = bus_method_call_with_reply(
1843 "org.freedesktop.systemd1",
1844 "/org/freedesktop/systemd1",
1845 "org.freedesktop.systemd1.Manager",
1849 DBUS_TYPE_STRING, &n,
1850 DBUS_TYPE_STRING, &mode,
1853 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
1854 /* There's always a fallback possible for
1855 * legacy actions. */
1858 log_error("Failed to issue method call: %s", bus_error_message(error));
1863 if (!dbus_message_get_args(reply, error,
1864 DBUS_TYPE_OBJECT_PATH, &path,
1865 DBUS_TYPE_INVALID)) {
1866 log_error("Failed to parse reply: %s", bus_error_message(error));
1870 if (need_daemon_reload(bus, n) > 0)
1871 log_warning("Warning: Unit file of %s changed on disk, 'systemctl %sdaemon-reload' recommended.",
1872 n, arg_scope == UNIT_FILE_SYSTEM ? "" : "--user ");
1881 r = set_consume(s, p);
1883 log_error("Failed to add path to set.");
1891 static const struct {
1895 } action_table[_ACTION_MAX] = {
1896 [ACTION_HALT] = { SPECIAL_HALT_TARGET, "halt", "replace-irreversibly" },
1897 [ACTION_POWEROFF] = { SPECIAL_POWEROFF_TARGET, "poweroff", "replace-irreversibly" },
1898 [ACTION_REBOOT] = { SPECIAL_REBOOT_TARGET, "reboot", "replace-irreversibly" },
1899 [ACTION_KEXEC] = { SPECIAL_KEXEC_TARGET, "kexec", "replace-irreversibly" },
1900 [ACTION_RUNLEVEL2] = { SPECIAL_RUNLEVEL2_TARGET, NULL, "isolate" },
1901 [ACTION_RUNLEVEL3] = { SPECIAL_RUNLEVEL3_TARGET, NULL, "isolate" },
1902 [ACTION_RUNLEVEL4] = { SPECIAL_RUNLEVEL4_TARGET, NULL, "isolate" },
1903 [ACTION_RUNLEVEL5] = { SPECIAL_RUNLEVEL5_TARGET, NULL, "isolate" },
1904 [ACTION_RESCUE] = { SPECIAL_RESCUE_TARGET, "rescue", "isolate" },
1905 [ACTION_EMERGENCY] = { SPECIAL_EMERGENCY_TARGET, "emergency", "isolate" },
1906 [ACTION_DEFAULT] = { SPECIAL_DEFAULT_TARGET, "default", "isolate" },
1907 [ACTION_EXIT] = { SPECIAL_EXIT_TARGET, "exit", "replace-irreversibly" },
1908 [ACTION_SUSPEND] = { SPECIAL_SUSPEND_TARGET, "suspend", "replace-irreversibly" },
1909 [ACTION_HIBERNATE] = { SPECIAL_HIBERNATE_TARGET, "hibernate", "replace-irreversibly" },
1910 [ACTION_HYBRID_SLEEP] = { SPECIAL_HYBRID_SLEEP_TARGET, "hybrid-sleep", "replace-irreversibly" },
1913 static enum action verb_to_action(const char *verb) {
1916 for (i = ACTION_INVALID; i < _ACTION_MAX; i++)
1917 if (action_table[i].verb && streq(verb, action_table[i].verb))
1919 return ACTION_INVALID;
1922 static int start_unit(DBusConnection *bus, char **args) {
1925 const char *method, *mode, *one_name;
1926 _cleanup_set_free_free_ Set *s = NULL;
1927 _cleanup_dbus_error_free_ DBusError error;
1930 dbus_error_init(&error);
1934 ask_password_agent_open_if_enabled();
1936 if (arg_action == ACTION_SYSTEMCTL) {
1939 streq(args[0], "stop") ||
1940 streq(args[0], "condstop") ? "StopUnit" :
1941 streq(args[0], "reload") ? "ReloadUnit" :
1942 streq(args[0], "restart") ? "RestartUnit" :
1944 streq(args[0], "try-restart") ||
1945 streq(args[0], "condrestart") ? "TryRestartUnit" :
1947 streq(args[0], "reload-or-restart") ? "ReloadOrRestartUnit" :
1949 streq(args[0], "reload-or-try-restart") ||
1950 streq(args[0], "condreload") ||
1952 streq(args[0], "force-reload") ? "ReloadOrTryRestartUnit" :
1954 action = verb_to_action(args[0]);
1956 mode = streq(args[0], "isolate") ? "isolate" :
1957 action_table[action].mode ?: arg_job_mode;
1959 one_name = action_table[action].target;
1962 assert(arg_action < ELEMENTSOF(action_table));
1963 assert(action_table[arg_action].target);
1965 method = "StartUnit";
1967 mode = action_table[arg_action].mode;
1968 one_name = action_table[arg_action].target;
1971 if (!arg_no_block) {
1972 ret = enable_wait_for_jobs(bus);
1974 log_error("Could not watch jobs: %s", strerror(-ret));
1978 s = set_new(string_hash_func, string_compare_func);
1984 ret = start_unit_one(bus, method, one_name, mode, &error, s);
1986 ret = translate_bus_error_to_exit_status(ret, &error);
1988 STRV_FOREACH(name, args+1) {
1989 r = start_unit_one(bus, method, *name, mode, &error, s);
1991 ret = translate_bus_error_to_exit_status(r, &error);
1992 dbus_error_free(&error);
1997 if (!arg_no_block) {
1998 r = wait_for_jobs(bus, s);
2002 /* When stopping units, warn if they can still be triggered by
2003 * another active unit (socket, path, timer) */
2004 if (!arg_quiet && streq(method, "StopUnit")) {
2006 check_triggering_units(bus, one_name);
2008 STRV_FOREACH(name, args+1)
2009 check_triggering_units(bus, *name);
2016 /* Ask systemd-logind, which might grant access to unprivileged users
2017 * through PolicyKit */
2018 static int reboot_with_logind(DBusConnection *bus, enum action a) {
2021 dbus_bool_t interactive = true;
2026 polkit_agent_open_if_enabled();
2034 case ACTION_POWEROFF:
2035 method = "PowerOff";
2038 case ACTION_SUSPEND:
2042 case ACTION_HIBERNATE:
2043 method = "Hibernate";
2046 case ACTION_HYBRID_SLEEP:
2047 method = "HybridSleep";
2054 return bus_method_call_with_reply(
2056 "org.freedesktop.login1",
2057 "/org/freedesktop/login1",
2058 "org.freedesktop.login1.Manager",
2062 DBUS_TYPE_BOOLEAN, &interactive,
2069 static int check_inhibitors(DBusConnection *bus, enum action a) {
2071 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
2072 DBusMessageIter iter, sub, sub2;
2075 _cleanup_strv_free_ char **sessions = NULL;
2081 if (arg_ignore_inhibitors || arg_force > 0)
2093 r = bus_method_call_with_reply(
2095 "org.freedesktop.login1",
2096 "/org/freedesktop/login1",
2097 "org.freedesktop.login1.Manager",
2103 /* If logind is not around, then there are no inhibitors... */
2106 if (!dbus_message_iter_init(reply, &iter) ||
2107 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
2108 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
2109 log_error("Failed to parse reply.");
2113 dbus_message_iter_recurse(&iter, &sub);
2114 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
2115 const char *what, *who, *why, *mode;
2117 _cleanup_strv_free_ char **sv = NULL;
2118 _cleanup_free_ char *comm = NULL, *user = NULL;
2120 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
2121 log_error("Failed to parse reply.");
2125 dbus_message_iter_recurse(&sub, &sub2);
2127 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &what, true) < 0 ||
2128 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &who, true) < 0 ||
2129 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &why, true) < 0 ||
2130 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &mode, true) < 0 ||
2131 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &uid, true) < 0 ||
2132 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, false) < 0) {
2133 log_error("Failed to parse reply.");
2137 if (!streq(mode, "block"))
2140 sv = strv_split(what, ":");
2144 if (!strv_contains(sv,
2146 a == ACTION_POWEROFF ||
2147 a == ACTION_REBOOT ||
2148 a == ACTION_KEXEC ? "shutdown" : "sleep"))
2151 get_process_comm(pid, &comm);
2152 user = uid_to_name(uid);
2153 log_warning("Operation inhibited by \"%s\" (PID %lu \"%s\", user %s), reason is \"%s\".",
2154 who, (unsigned long) pid, strna(comm), strna(user), why);
2158 dbus_message_iter_next(&sub);
2161 dbus_message_iter_recurse(&iter, &sub);
2163 /* Check for current sessions */
2164 sd_get_sessions(&sessions);
2165 STRV_FOREACH(s, sessions) {
2167 _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL;
2169 if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid())
2172 if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
2175 if (sd_session_get_type(*s, &type) < 0 || (!streq(type, "x11") && !streq(type, "tty")))
2178 sd_session_get_tty(*s, &tty);
2179 sd_session_get_seat(*s, &seat);
2180 sd_session_get_service(*s, &service);
2181 user = uid_to_name(uid);
2183 log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty);
2190 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
2191 action_table[a].verb);
2199 static int start_special(DBusConnection *bus, char **args) {
2205 a = verb_to_action(args[0]);
2207 r = check_inhibitors(bus, a);
2211 if (arg_force >= 2 && geteuid() != 0) {
2212 log_error("Must be root.");
2216 if (arg_force >= 2 &&
2217 (a == ACTION_HALT ||
2218 a == ACTION_POWEROFF ||
2219 a == ACTION_REBOOT))
2222 if (arg_force >= 1 &&
2223 (a == ACTION_HALT ||
2224 a == ACTION_POWEROFF ||
2225 a == ACTION_REBOOT ||
2226 a == ACTION_KEXEC ||
2228 return daemon_reload(bus, args);
2230 /* first try logind, to allow authentication with polkit */
2231 if (geteuid() != 0 &&
2232 (a == ACTION_POWEROFF ||
2233 a == ACTION_REBOOT ||
2234 a == ACTION_SUSPEND ||
2235 a == ACTION_HIBERNATE ||
2236 a == ACTION_HYBRID_SLEEP)) {
2237 r = reboot_with_logind(bus, a);
2242 r = start_unit(bus, args);
2243 if (r == EXIT_SUCCESS)
2249 static int check_unit_active(DBusConnection *bus, char **args) {
2250 const char * const check_states[] = {
2257 int r = 3; /* According to LSB: "program is not running" */
2262 STRV_FOREACH(name, args+1) {
2265 state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
2275 static int check_unit_failed(DBusConnection *bus, char **args) {
2276 const char * const check_states[] = {
2287 STRV_FOREACH(name, args+1) {
2290 state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
2300 static int kill_unit(DBusConnection *bus, char **args) {
2308 arg_kill_who = "all";
2310 STRV_FOREACH(name, args+1) {
2311 _cleanup_free_ char *n = NULL;
2313 n = unit_name_mangle(*name);
2317 r = bus_method_call_with_reply(
2319 "org.freedesktop.systemd1",
2320 "/org/freedesktop/systemd1",
2321 "org.freedesktop.systemd1.Manager",
2325 DBUS_TYPE_STRING, &n,
2326 DBUS_TYPE_STRING, &arg_kill_who,
2327 DBUS_TYPE_INT32, &arg_signal,
2335 typedef struct ExecStatusInfo {
2343 usec_t start_timestamp;
2344 usec_t exit_timestamp;
2349 LIST_FIELDS(struct ExecStatusInfo, exec);
2352 static void exec_status_info_free(ExecStatusInfo *i) {
2361 static int exec_status_info_deserialize(DBusMessageIter *sub, ExecStatusInfo *i) {
2362 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
2363 DBusMessageIter sub2, sub3;
2367 int32_t code, status;
2373 if (dbus_message_iter_get_arg_type(sub) != DBUS_TYPE_STRUCT)
2376 dbus_message_iter_recurse(sub, &sub2);
2378 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0)
2381 i->path = strdup(path);
2385 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_ARRAY ||
2386 dbus_message_iter_get_element_type(&sub2) != DBUS_TYPE_STRING)
2390 dbus_message_iter_recurse(&sub2, &sub3);
2391 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2392 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2393 dbus_message_iter_next(&sub3);
2397 i->argv = new0(char*, n+1);
2402 dbus_message_iter_recurse(&sub2, &sub3);
2403 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2406 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2407 dbus_message_iter_get_basic(&sub3, &s);
2408 dbus_message_iter_next(&sub3);
2410 i->argv[n] = strdup(s);
2417 if (!dbus_message_iter_next(&sub2) ||
2418 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, true) < 0 ||
2419 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp, true) < 0 ||
2420 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp_monotonic, true) < 0 ||
2421 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp, true) < 0 ||
2422 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp_monotonic, true) < 0 ||
2423 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, true) < 0 ||
2424 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &code, true) < 0 ||
2425 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &status, false) < 0)
2429 i->start_timestamp = (usec_t) start_timestamp;
2430 i->exit_timestamp = (usec_t) exit_timestamp;
2431 i->pid = (pid_t) pid;
2438 typedef struct UnitStatusInfo {
2440 const char *load_state;
2441 const char *active_state;
2442 const char *sub_state;
2443 const char *unit_file_state;
2445 const char *description;
2446 const char *following;
2448 char **documentation;
2450 const char *fragment_path;
2451 const char *source_path;
2452 const char *control_group;
2454 char **dropin_paths;
2456 const char *load_error;
2459 usec_t inactive_exit_timestamp;
2460 usec_t inactive_exit_timestamp_monotonic;
2461 usec_t active_enter_timestamp;
2462 usec_t active_exit_timestamp;
2463 usec_t inactive_enter_timestamp;
2465 bool need_daemon_reload;
2470 const char *status_text;
2471 const char *pid_file;
2474 usec_t start_timestamp;
2475 usec_t exit_timestamp;
2477 int exit_code, exit_status;
2479 usec_t condition_timestamp;
2480 bool condition_result;
2481 bool failed_condition_trigger;
2482 bool failed_condition_negate;
2483 const char *failed_condition;
2484 const char *failed_condition_param;
2487 unsigned n_accepted;
2488 unsigned n_connections;
2491 /* Pairs of type, path */
2495 const char *sysfs_path;
2497 /* Mount, Automount */
2503 LIST_HEAD(ExecStatusInfo, exec);
2506 static void print_status_info(UnitStatusInfo *i,
2509 const char *on, *off, *ss;
2511 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
2512 char since2[FORMAT_TIMESTAMP_MAX], *s2;
2515 arg_all * OUTPUT_SHOW_ALL |
2516 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
2517 on_tty() * OUTPUT_COLOR |
2518 !arg_quiet * OUTPUT_WARN_CUTOFF |
2519 arg_full * OUTPUT_FULL_WIDTH;
2524 /* This shows pretty information about a unit. See
2525 * print_property() for a low-level property printer */
2527 printf("%s", strna(i->id));
2529 if (i->description && !streq_ptr(i->id, i->description))
2530 printf(" - %s", i->description);
2535 printf(" Follow: unit currently follows state of %s\n", i->following);
2537 if (streq_ptr(i->load_state, "error")) {
2538 on = ansi_highlight_red();
2539 off = ansi_highlight_off();
2543 path = i->source_path ? i->source_path : i->fragment_path;
2546 printf(" Loaded: %s%s%s (Reason: %s)\n",
2547 on, strna(i->load_state), off, i->load_error);
2548 else if (path && i->unit_file_state)
2549 printf(" Loaded: %s%s%s (%s; %s)\n",
2550 on, strna(i->load_state), off, path, i->unit_file_state);
2552 printf(" Loaded: %s%s%s (%s)\n",
2553 on, strna(i->load_state), off, path);
2555 printf(" Loaded: %s%s%s\n",
2556 on, strna(i->load_state), off);
2558 if (!strv_isempty(i->dropin_paths)) {
2563 STRV_FOREACH(dropin, i->dropin_paths) {
2564 if (! dir || last) {
2565 printf(dir ? " " : " Drop-In: ");
2569 if (path_get_parent(*dropin, &dir) < 0) {
2574 printf("%s\n %s", dir,
2575 draw_special_char(DRAW_TREE_RIGHT));
2578 last = ! (*(dropin + 1) && startswith(*(dropin + 1), dir));
2580 printf("%s%s", path_get_file_name(*dropin), last ? "\n" : ", ");
2586 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
2588 if (streq_ptr(i->active_state, "failed")) {
2589 on = ansi_highlight_red();
2590 off = ansi_highlight_off();
2591 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
2592 on = ansi_highlight_green();
2593 off = ansi_highlight_off();
2598 printf(" Active: %s%s (%s)%s",
2599 on, strna(i->active_state), ss, off);
2601 printf(" Active: %s%s%s",
2602 on, strna(i->active_state), off);
2604 if (!isempty(i->result) && !streq(i->result, "success"))
2605 printf(" (Result: %s)", i->result);
2607 timestamp = (streq_ptr(i->active_state, "active") ||
2608 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
2609 (streq_ptr(i->active_state, "inactive") ||
2610 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
2611 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
2612 i->active_exit_timestamp;
2614 s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
2615 s2 = format_timestamp(since2, sizeof(since2), timestamp);
2618 printf(" since %s; %s\n", s2, s1);
2620 printf(" since %s\n", s2);
2624 if (!i->condition_result && i->condition_timestamp > 0) {
2625 s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
2626 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
2628 printf(" start condition failed at %s%s%s\n",
2629 s2, s1 ? "; " : "", s1 ? s1 : "");
2630 if (i->failed_condition_trigger)
2631 printf(" none of the trigger conditions were met\n");
2632 else if (i->failed_condition)
2633 printf(" %s=%s%s was not met\n",
2634 i->failed_condition,
2635 i->failed_condition_negate ? "!" : "",
2636 i->failed_condition_param);
2640 printf(" Device: %s\n", i->sysfs_path);
2642 printf(" Where: %s\n", i->where);
2644 printf(" What: %s\n", i->what);
2646 STRV_FOREACH(t, i->documentation)
2647 printf(" %*s %s\n", 9, t == i->documentation ? "Docs:" : "", *t);
2649 STRV_FOREACH_PAIR(t, t2, i->listen)
2650 printf(" %*s %s (%s)\n", 9, t == i->listen ? "Listen:" : "", *t2, *t);
2653 printf(" Accepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
2655 LIST_FOREACH(exec, p, i->exec) {
2656 _cleanup_free_ char *argv = NULL;
2659 /* Only show exited processes here */
2663 argv = strv_join(p->argv, " ");
2664 printf(" Process: %u %s=%s ", p->pid, p->name, strna(argv));
2666 good = is_clean_exit_lsb(p->code, p->status, NULL);
2668 on = ansi_highlight_red();
2669 off = ansi_highlight_off();
2673 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
2675 if (p->code == CLD_EXITED) {
2678 printf("status=%i", p->status);
2680 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
2685 printf("signal=%s", signal_to_string(p->status));
2687 printf(")%s\n", off);
2689 if (i->main_pid == p->pid &&
2690 i->start_timestamp == p->start_timestamp &&
2691 i->exit_timestamp == p->start_timestamp)
2692 /* Let's not show this twice */
2695 if (p->pid == i->control_pid)
2699 if (i->main_pid > 0 || i->control_pid > 0) {
2700 if (i->main_pid > 0) {
2701 printf(" Main PID: %u", (unsigned) i->main_pid);
2704 _cleanup_free_ char *comm = NULL;
2705 get_process_comm(i->main_pid, &comm);
2707 printf(" (%s)", comm);
2708 } else if (i->exit_code > 0) {
2709 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
2711 if (i->exit_code == CLD_EXITED) {
2714 printf("status=%i", i->exit_status);
2716 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
2721 printf("signal=%s", signal_to_string(i->exit_status));
2725 if (i->control_pid > 0)
2729 if (i->control_pid > 0) {
2730 _cleanup_free_ char *c = NULL;
2732 printf(" %8s: %u", i->main_pid ? "" : " Control", (unsigned) i->control_pid);
2734 get_process_comm(i->control_pid, &c);
2743 printf(" Status: \"%s\"\n", i->status_text);
2745 if (i->control_group &&
2746 (i->main_pid > 0 || i->control_pid > 0 || cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, i->control_group, false) == 0)) {
2749 printf(" CGroup: %s\n", i->control_group);
2751 if (arg_transport != TRANSPORT_SSH) {
2754 char prefix[] = " ";
2757 if (c > sizeof(prefix) - 1)
2758 c -= sizeof(prefix) - 1;
2762 if (i->main_pid > 0)
2763 extra[k++] = i->main_pid;
2765 if (i->control_pid > 0)
2766 extra[k++] = i->control_pid;
2768 show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, i->control_group, prefix,
2769 c, false, extra, k, flags);
2773 if (i->id && arg_transport != TRANSPORT_SSH) {
2775 show_journal_by_unit(stdout,
2779 i->inactive_exit_timestamp_monotonic,
2783 arg_scope == UNIT_FILE_SYSTEM,
2787 if (i->need_daemon_reload)
2788 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %sdaemon-reload' recommended.\n",
2789 ansi_highlight_red(),
2790 ansi_highlight_off(),
2791 arg_scope == UNIT_FILE_SYSTEM ? "" : "--user ");
2794 static void show_unit_help(UnitStatusInfo *i) {
2799 if (!i->documentation) {
2800 log_info("Documentation for %s not known.", i->id);
2804 STRV_FOREACH(p, i->documentation) {
2806 if (startswith(*p, "man:")) {
2809 _cleanup_free_ char *page = NULL, *section = NULL;
2810 const char *args[4] = { "man", NULL, NULL, NULL };
2815 if ((*p)[k-1] == ')')
2816 e = strrchr(*p, '(');
2819 page = strndup((*p) + 4, e - *p - 4);
2820 section = strndup(e + 1, *p + k - e - 2);
2821 if (!page || !section) {
2833 log_error("Failed to fork: %m");
2839 execvp(args[0], (char**) args);
2840 log_error("Failed to execute man: %m");
2841 _exit(EXIT_FAILURE);
2844 wait_for_terminate(pid, NULL);
2846 log_info("Can't show: %s", *p);
2850 static int status_property(const char *name, DBusMessageIter *iter, UnitStatusInfo *i) {
2856 switch (dbus_message_iter_get_arg_type(iter)) {
2858 case DBUS_TYPE_STRING: {
2861 dbus_message_iter_get_basic(iter, &s);
2864 if (streq(name, "Id"))
2866 else if (streq(name, "LoadState"))
2868 else if (streq(name, "ActiveState"))
2869 i->active_state = s;
2870 else if (streq(name, "SubState"))
2872 else if (streq(name, "Description"))
2874 else if (streq(name, "FragmentPath"))
2875 i->fragment_path = s;
2876 else if (streq(name, "SourcePath"))
2879 else if (streq(name, "DefaultControlGroup")) {
2881 e = startswith(s, SYSTEMD_CGROUP_CONTROLLER ":");
2883 i->control_group = e;
2886 else if (streq(name, "ControlGroup"))
2887 i->control_group = s;
2888 else if (streq(name, "StatusText"))
2890 else if (streq(name, "PIDFile"))
2892 else if (streq(name, "SysFSPath"))
2894 else if (streq(name, "Where"))
2896 else if (streq(name, "What"))
2898 else if (streq(name, "Following"))
2900 else if (streq(name, "UnitFileState"))
2901 i->unit_file_state = s;
2902 else if (streq(name, "Result"))
2909 case DBUS_TYPE_BOOLEAN: {
2912 dbus_message_iter_get_basic(iter, &b);
2914 if (streq(name, "Accept"))
2916 else if (streq(name, "NeedDaemonReload"))
2917 i->need_daemon_reload = b;
2918 else if (streq(name, "ConditionResult"))
2919 i->condition_result = b;
2924 case DBUS_TYPE_UINT32: {
2927 dbus_message_iter_get_basic(iter, &u);
2929 if (streq(name, "MainPID")) {
2931 i->main_pid = (pid_t) u;
2934 } else if (streq(name, "ControlPID"))
2935 i->control_pid = (pid_t) u;
2936 else if (streq(name, "ExecMainPID")) {
2938 i->main_pid = (pid_t) u;
2939 } else if (streq(name, "NAccepted"))
2941 else if (streq(name, "NConnections"))
2942 i->n_connections = u;
2947 case DBUS_TYPE_INT32: {
2950 dbus_message_iter_get_basic(iter, &j);
2952 if (streq(name, "ExecMainCode"))
2953 i->exit_code = (int) j;
2954 else if (streq(name, "ExecMainStatus"))
2955 i->exit_status = (int) j;
2960 case DBUS_TYPE_UINT64: {
2963 dbus_message_iter_get_basic(iter, &u);
2965 if (streq(name, "ExecMainStartTimestamp"))
2966 i->start_timestamp = (usec_t) u;
2967 else if (streq(name, "ExecMainExitTimestamp"))
2968 i->exit_timestamp = (usec_t) u;
2969 else if (streq(name, "ActiveEnterTimestamp"))
2970 i->active_enter_timestamp = (usec_t) u;
2971 else if (streq(name, "InactiveEnterTimestamp"))
2972 i->inactive_enter_timestamp = (usec_t) u;
2973 else if (streq(name, "InactiveExitTimestamp"))
2974 i->inactive_exit_timestamp = (usec_t) u;
2975 else if (streq(name, "InactiveExitTimestampMonotonic"))
2976 i->inactive_exit_timestamp_monotonic = (usec_t) u;
2977 else if (streq(name, "ActiveExitTimestamp"))
2978 i->active_exit_timestamp = (usec_t) u;
2979 else if (streq(name, "ConditionTimestamp"))
2980 i->condition_timestamp = (usec_t) u;
2985 case DBUS_TYPE_ARRAY: {
2987 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
2988 startswith(name, "Exec")) {
2989 DBusMessageIter sub;
2991 dbus_message_iter_recurse(iter, &sub);
2992 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2993 ExecStatusInfo *info;
2996 info = new0(ExecStatusInfo, 1);
3000 info->name = strdup(name);
3006 r = exec_status_info_deserialize(&sub, info);
3012 LIST_PREPEND(ExecStatusInfo, exec, i->exec, info);
3014 dbus_message_iter_next(&sub);
3017 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
3018 streq(name, "Listen")) {
3019 DBusMessageIter sub, sub2;
3021 dbus_message_iter_recurse(iter, &sub);
3022 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3023 const char *type, *path;
3025 dbus_message_iter_recurse(&sub, &sub2);
3027 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
3028 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0) {
3031 r = strv_extend(&i->listen, type);
3034 r = strv_extend(&i->listen, path);
3039 dbus_message_iter_next(&sub);
3044 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
3045 streq(name, "DropInPaths")) {
3046 int r = bus_parse_strv_iter(iter, &i->dropin_paths);
3050 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
3051 streq(name, "Documentation")) {
3053 DBusMessageIter sub;
3055 dbus_message_iter_recurse(iter, &sub);
3056 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING) {
3060 dbus_message_iter_get_basic(&sub, &s);
3062 r = strv_extend(&i->documentation, s);
3066 dbus_message_iter_next(&sub);
3069 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
3070 streq(name, "Conditions")) {
3071 DBusMessageIter sub, sub2;
3073 dbus_message_iter_recurse(iter, &sub);
3074 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3075 const char *cond, *param;
3076 dbus_bool_t trigger, negate;
3079 dbus_message_iter_recurse(&sub, &sub2);
3082 if(bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &cond, true) >= 0 &&
3083 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &trigger, true) >= 0 &&
3084 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &negate, true) >= 0 &&
3085 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, ¶m, true) >= 0 &&
3086 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &state, false) >= 0) {
3087 log_debug("%s %d %d %s %d", cond, trigger, negate, param, state);
3088 if (state < 0 && (!trigger || !i->failed_condition)) {
3089 i->failed_condition = cond;
3090 i->failed_condition_trigger = trigger;
3091 i->failed_condition_negate = negate;
3092 i->failed_condition_param = param;
3096 dbus_message_iter_next(&sub);
3103 case DBUS_TYPE_STRUCT: {
3105 if (streq(name, "LoadError")) {
3106 DBusMessageIter sub;
3107 const char *n, *message;
3110 dbus_message_iter_recurse(iter, &sub);
3112 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &n, true);
3116 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &message, false);
3120 if (!isempty(message))
3121 i->load_error = message;
3131 static int print_property(const char *name, DBusMessageIter *iter) {
3135 /* This is a low-level property printer, see
3136 * print_status_info() for the nicer output */
3138 if (arg_properties && !strv_find(arg_properties, name))
3141 switch (dbus_message_iter_get_arg_type(iter)) {
3143 case DBUS_TYPE_STRUCT: {
3144 DBusMessageIter sub;
3145 dbus_message_iter_recurse(iter, &sub);
3147 if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32 && streq(name, "Job")) {
3150 dbus_message_iter_get_basic(&sub, &u);
3153 printf("%s=%u\n", name, (unsigned) u);
3155 printf("%s=\n", name);
3158 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "Unit")) {
3161 dbus_message_iter_get_basic(&sub, &s);
3163 if (arg_all || s[0])
3164 printf("%s=%s\n", name, s);
3167 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "LoadError")) {
3168 const char *a = NULL, *b = NULL;
3170 if (bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &a, true) >= 0)
3171 bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &b, false);
3173 if (arg_all || !isempty(a) || !isempty(b))
3174 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
3182 case DBUS_TYPE_ARRAY:
3184 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "EnvironmentFiles")) {
3185 DBusMessageIter sub, sub2;
3187 dbus_message_iter_recurse(iter, &sub);
3188 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3192 dbus_message_iter_recurse(&sub, &sub2);
3194 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
3195 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) >= 0)
3196 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
3198 dbus_message_iter_next(&sub);
3203 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Paths")) {
3204 DBusMessageIter sub, sub2;
3206 dbus_message_iter_recurse(iter, &sub);
3208 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3209 const char *type, *path;
3211 dbus_message_iter_recurse(&sub, &sub2);
3213 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
3214 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
3215 printf("%s=%s\n", type, path);
3217 dbus_message_iter_next(&sub);
3222 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Listen")) {
3223 DBusMessageIter sub, sub2;
3225 dbus_message_iter_recurse(iter, &sub);
3226 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3227 const char *type, *path;
3229 dbus_message_iter_recurse(&sub, &sub2);
3231 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
3232 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
3233 printf("Listen%s=%s\n", type, path);
3235 dbus_message_iter_next(&sub);
3240 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Timers")) {
3241 DBusMessageIter sub, sub2;
3243 dbus_message_iter_recurse(iter, &sub);
3244 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3246 uint64_t value, next_elapse;
3248 dbus_message_iter_recurse(&sub, &sub2);
3250 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &base, true) >= 0 &&
3251 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &value, true) >= 0 &&
3252 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &next_elapse, false) >= 0) {
3253 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
3255 printf("%s={ value=%s ; next_elapse=%s }\n",
3257 format_timespan(timespan1, sizeof(timespan1), value, 0),
3258 format_timespan(timespan2, sizeof(timespan2), next_elapse, 0));
3261 dbus_message_iter_next(&sub);
3266 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && startswith(name, "Exec")) {
3267 DBusMessageIter sub;
3269 dbus_message_iter_recurse(iter, &sub);
3270 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3271 ExecStatusInfo info = {};
3273 if (exec_status_info_deserialize(&sub, &info) >= 0) {
3274 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
3275 _cleanup_free_ char *t;
3277 t = strv_join(info.argv, " ");
3279 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
3283 yes_no(info.ignore),
3284 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
3285 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
3286 (unsigned) info. pid,
3287 sigchld_code_to_string(info.code),
3289 info.code == CLD_EXITED ? "" : "/",
3290 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
3294 strv_free(info.argv);
3296 dbus_message_iter_next(&sub);
3301 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "DeviceAllow")) {
3302 DBusMessageIter sub, sub2;
3304 dbus_message_iter_recurse(iter, &sub);
3305 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3306 const char *path, *rwm;
3308 dbus_message_iter_recurse(&sub, &sub2);
3310 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
3311 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &rwm, false) >= 0)
3312 printf("%s=%s %s\n", name, strna(path), strna(rwm));
3314 dbus_message_iter_next(&sub);
3318 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "BlockIODeviceWeight")) {
3319 DBusMessageIter sub, sub2;
3321 dbus_message_iter_recurse(iter, &sub);
3322 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3326 dbus_message_iter_recurse(&sub, &sub2);
3328 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
3329 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &weight, false) >= 0)
3330 printf("%s=%s %" PRIu64 "\n", name, strna(path), weight);
3332 dbus_message_iter_next(&sub);
3336 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && (streq(name, "BlockIOReadBandwidth") || streq(name, "BlockIOWriteBandwidth"))) {
3337 DBusMessageIter sub, sub2;
3339 dbus_message_iter_recurse(iter, &sub);
3340 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3344 dbus_message_iter_recurse(&sub, &sub2);
3346 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
3347 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &bandwidth, false) >= 0)
3348 printf("%s=%s %" PRIu64 "\n", name, strna(path), bandwidth);
3350 dbus_message_iter_next(&sub);
3359 if (generic_print_property(name, iter, arg_all) > 0)
3363 printf("%s=[unprintable]\n", name);
3368 static int show_one(const char *verb,
3369 DBusConnection *bus,
3371 bool show_properties,
3374 _cleanup_free_ DBusMessage *reply = NULL;
3375 const char *interface = "";
3377 DBusMessageIter iter, sub, sub2, sub3;
3378 UnitStatusInfo info = {};
3384 r = bus_method_call_with_reply(
3386 "org.freedesktop.systemd1",
3388 "org.freedesktop.DBus.Properties",
3392 DBUS_TYPE_STRING, &interface,
3397 if (!dbus_message_iter_init(reply, &iter) ||
3398 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3399 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
3400 log_error("Failed to parse reply.");
3404 dbus_message_iter_recurse(&iter, &sub);
3411 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
3414 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_DICT_ENTRY);
3415 dbus_message_iter_recurse(&sub, &sub2);
3417 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
3418 dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
3419 log_error("Failed to parse reply.");
3423 dbus_message_iter_recurse(&sub2, &sub3);
3425 if (show_properties)
3426 r = print_property(name, &sub3);
3428 r = status_property(name, &sub3, &info);
3430 log_error("Failed to parse reply.");
3434 dbus_message_iter_next(&sub);
3439 if (!show_properties) {
3440 if (streq(verb, "help"))
3441 show_unit_help(&info);
3443 print_status_info(&info, ellipsized);
3446 strv_free(info.documentation);
3447 strv_free(info.dropin_paths);
3448 strv_free(info.listen);
3450 if (!streq_ptr(info.active_state, "active") &&
3451 !streq_ptr(info.active_state, "reloading") &&
3452 streq(verb, "status")) {
3453 /* According to LSB: "program not running" */
3454 /* 0: program is running or service is OK
3455 * 1: program is dead and /var/run pid file exists
3456 * 2: program is dead and /var/lock lock file exists
3457 * 3: program is not running
3458 * 4: program or service status is unknown
3460 if (info.pid_file && access(info.pid_file, F_OK) == 0)
3466 while ((p = info.exec)) {
3467 LIST_REMOVE(ExecStatusInfo, exec, info.exec, p);
3468 exec_status_info_free(p);
3474 static int show_one_by_pid(const char *verb,
3475 DBusConnection *bus,
3479 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3480 const char *path = NULL;
3481 _cleanup_dbus_error_free_ DBusError error;
3484 dbus_error_init(&error);
3486 r = bus_method_call_with_reply(
3488 "org.freedesktop.systemd1",
3489 "/org/freedesktop/systemd1",
3490 "org.freedesktop.systemd1.Manager",
3494 DBUS_TYPE_UINT32, &pid,
3499 if (!dbus_message_get_args(reply, &error,
3500 DBUS_TYPE_OBJECT_PATH, &path,
3501 DBUS_TYPE_INVALID)) {
3502 log_error("Failed to parse reply: %s", bus_error_message(&error));
3506 r = show_one(verb, bus, path, false, new_line, ellipsized);
3510 static int show_all(const char* verb,
3511 DBusConnection *bus,
3512 bool show_properties,
3515 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3516 _cleanup_free_ struct unit_info *unit_infos = NULL;
3518 const struct unit_info *u;
3521 r = get_unit_list(bus, &reply, &unit_infos, &c);
3525 qsort(unit_infos, c, sizeof(struct unit_info), compare_unit_info);
3527 for (u = unit_infos; u < unit_infos + c; u++) {
3528 _cleanup_free_ char *p = NULL;
3530 if (!output_show_unit(u))
3533 p = unit_dbus_path_from_name(u->id);
3537 printf("%s -> '%s'\n", u->id, p);
3539 r = show_one(verb, bus, p, show_properties, new_line, ellipsized);
3547 static int show(DBusConnection *bus, char **args) {
3549 bool show_properties, show_status, new_line = false;
3551 bool ellipsized = false;
3556 show_properties = streq(args[0], "show");
3557 show_status = streq(args[0], "status");
3559 if (show_properties)
3560 pager_open_if_enabled();
3562 /* If no argument is specified inspect the manager itself */
3564 if (show_properties && strv_length(args) <= 1)
3565 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line, &ellipsized);
3567 if (show_status && strv_length(args) <= 1)
3568 ret = show_all(args[0], bus, false, &new_line, &ellipsized);
3570 STRV_FOREACH(name, args+1) {
3573 if (safe_atou32(*name, &id) < 0) {
3574 _cleanup_free_ char *p = NULL, *n = NULL;
3575 /* Interpret as unit name */
3577 n = unit_name_mangle(*name);
3581 p = unit_dbus_path_from_name(n);
3585 r = show_one(args[0], bus, p, show_properties, &new_line, &ellipsized);
3589 } else if (show_properties) {
3590 _cleanup_free_ char *p = NULL;
3592 /* Interpret as job id */
3593 if (asprintf(&p, "/org/freedesktop/systemd1/job/%u", id) < 0)
3596 r = show_one(args[0], bus, p, show_properties, &new_line, &ellipsized);
3601 /* Interpret as PID */
3602 r = show_one_by_pid(args[0], bus, id, &new_line, &ellipsized);
3608 if (ellipsized && !arg_quiet)
3609 printf("Hint: Some lines were ellipsized, use -l to show in full.\n");
3614 static int append_assignment(DBusMessageIter *iter, const char *assignment) {
3617 DBusMessageIter sub;
3623 eq = strchr(assignment, '=');
3625 log_error("Not an assignment: %s", assignment);
3629 field = strndupa(assignment, eq - assignment);
3632 if (!dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &field))
3635 if (streq(field, "CPUAccounting") ||
3636 streq(field, "MemoryAccounting") ||
3637 streq(field, "BlockIOAccounting")) {
3640 r = parse_boolean(eq);
3642 log_error("Failed to parse boolean assignment %s.", assignment);
3647 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "b", &sub) ||
3648 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_BOOLEAN, &b))
3651 } else if (streq(field, "MemoryLimit") || streq(field, "MemorySoftLimit")) {
3655 r = parse_bytes(eq, &bytes);
3657 log_error("Failed to parse bytes specification %s", assignment);
3662 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "t", &sub) ||
3663 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_UINT64, &u))
3666 } else if (streq(field, "CPUShares") || streq(field, "BlockIOWeight")) {
3669 r = safe_atou64(eq, &u);
3671 log_error("Failed to parse %s value %s.", field, eq);
3675 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "t", &sub) ||
3676 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_UINT64, &u))
3679 } else if (streq(field, "DevicePolicy")) {
3681 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "s", &sub) ||
3682 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &eq))
3685 } else if (streq(field, "DeviceAllow")) {
3686 DBusMessageIter sub2;
3688 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "a(ss)", &sub) ||
3689 !dbus_message_iter_open_container(&sub, DBUS_TYPE_ARRAY, "(ss)", &sub2))
3693 const char *path, *rwm;
3694 DBusMessageIter sub3;
3697 e = strchr(eq, ' ');
3699 path = strndupa(eq, e - eq);
3706 if (!path_startswith(path, "/dev")) {
3707 log_error("%s is not a device file in /dev.", path);
3711 if (!dbus_message_iter_open_container(&sub2, DBUS_TYPE_STRUCT, NULL, &sub3) ||
3712 !dbus_message_iter_append_basic(&sub3, DBUS_TYPE_STRING, &path) ||
3713 !dbus_message_iter_append_basic(&sub3, DBUS_TYPE_STRING, &rwm) ||
3714 !dbus_message_iter_close_container(&sub2, &sub3))
3718 if (!dbus_message_iter_close_container(&sub, &sub2))
3721 } else if (streq(field, "BlockIOReadBandwidth") || streq(field, "BlockIOWriteBandwidth")) {
3722 DBusMessageIter sub2;
3724 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "a(st)", &sub) ||
3725 !dbus_message_iter_open_container(&sub, DBUS_TYPE_ARRAY, "(st)", &sub2))
3729 const char *path, *bandwidth;
3730 DBusMessageIter sub3;
3735 e = strchr(eq, ' ');
3737 path = strndupa(eq, e - eq);
3740 log_error("Failed to parse %s value %s.", field, eq);
3744 if (!path_startswith(path, "/dev")) {
3745 log_error("%s is not a device file in /dev.", path);
3749 r = parse_bytes(bandwidth, &bytes);
3751 log_error("Failed to parse byte value %s.", bandwidth);
3755 u = (uint64_t) bytes;
3757 if (!dbus_message_iter_open_container(&sub2, DBUS_TYPE_STRUCT, NULL, &sub3) ||
3758 !dbus_message_iter_append_basic(&sub3, DBUS_TYPE_STRING, &path) ||
3759 !dbus_message_iter_append_basic(&sub3, DBUS_TYPE_UINT64, &u) ||
3760 !dbus_message_iter_close_container(&sub2, &sub3))
3764 if (!dbus_message_iter_close_container(&sub, &sub2))
3767 } else if (streq(field, "BlockIODeviceWeight")) {
3768 DBusMessageIter sub2;
3770 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "a(st)", &sub) ||
3771 !dbus_message_iter_open_container(&sub, DBUS_TYPE_ARRAY, "(st)", &sub2))
3775 const char *path, *weight;
3776 DBusMessageIter sub3;
3780 e = strchr(eq, ' ');
3782 path = strndupa(eq, e - eq);
3785 log_error("Failed to parse %s value %s.", field, eq);
3789 if (!path_startswith(path, "/dev")) {
3790 log_error("%s is not a device file in /dev.", path);
3794 r = safe_atou64(weight, &u);
3796 log_error("Failed to parse %s value %s.", field, weight);
3799 if (!dbus_message_iter_open_container(&sub2, DBUS_TYPE_STRUCT, NULL, &sub3) ||
3800 !dbus_message_iter_append_basic(&sub3, DBUS_TYPE_STRING, &path) ||
3801 !dbus_message_iter_append_basic(&sub3, DBUS_TYPE_UINT64, &u) ||
3802 !dbus_message_iter_close_container(&sub2, &sub3))
3806 if (!dbus_message_iter_close_container(&sub, &sub2))
3810 log_error("Unknown assignment %s.", assignment);
3814 if (!dbus_message_iter_close_container(iter, &sub))
3820 static int set_property(DBusConnection *bus, char **args) {
3822 _cleanup_free_ DBusMessage *m = NULL, *reply = NULL;
3823 DBusMessageIter iter, sub;
3824 dbus_bool_t runtime;
3829 dbus_error_init(&error);
3831 m = dbus_message_new_method_call(
3832 "org.freedesktop.systemd1",
3833 "/org/freedesktop/systemd1",
3834 "org.freedesktop.systemd1.Manager",
3835 "SetUnitProperties");
3839 dbus_message_iter_init_append(m, &iter);
3841 runtime = arg_runtime;
3843 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &args[1]) ||
3844 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &runtime) ||
3845 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(sv)", &sub))
3848 STRV_FOREACH(i, args + 2) {
3849 DBusMessageIter sub2;
3851 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
3854 r = append_assignment(&sub2, *i);
3858 if (!dbus_message_iter_close_container(&sub, &sub2))
3863 if (!dbus_message_iter_close_container(&iter, &sub))
3866 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3868 log_error("Failed to issue method call: %s", bus_error_message(&error));
3869 dbus_error_free(&error);
3876 static int snapshot(DBusConnection *bus, char **args) {
3877 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3880 dbus_bool_t cleanup = FALSE;
3881 DBusMessageIter iter, sub;
3884 *interface = "org.freedesktop.systemd1.Unit",
3886 _cleanup_free_ char *n = NULL;
3888 dbus_error_init(&error);
3890 if (strv_length(args) > 1)
3891 n = unit_name_mangle_with_suffix(args[1], ".snapshot");
3897 r = bus_method_call_with_reply(
3899 "org.freedesktop.systemd1",
3900 "/org/freedesktop/systemd1",
3901 "org.freedesktop.systemd1.Manager",
3905 DBUS_TYPE_STRING, &n,
3906 DBUS_TYPE_BOOLEAN, &cleanup,
3911 if (!dbus_message_get_args(reply, &error,
3912 DBUS_TYPE_OBJECT_PATH, &path,
3913 DBUS_TYPE_INVALID)) {
3914 log_error("Failed to parse reply: %s", bus_error_message(&error));
3915 dbus_error_free(&error);
3919 dbus_message_unref(reply);
3922 r = bus_method_call_with_reply (
3924 "org.freedesktop.systemd1",
3926 "org.freedesktop.DBus.Properties",
3930 DBUS_TYPE_STRING, &interface,
3931 DBUS_TYPE_STRING, &property,
3936 if (!dbus_message_iter_init(reply, &iter) ||
3937 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3938 log_error("Failed to parse reply.");
3942 dbus_message_iter_recurse(&iter, &sub);
3944 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
3945 log_error("Failed to parse reply.");
3949 dbus_message_iter_get_basic(&sub, &id);
3957 static int delete_snapshot(DBusConnection *bus, char **args) {
3962 STRV_FOREACH(name, args+1) {
3963 _cleanup_free_ char *n = NULL;
3966 n = unit_name_mangle_with_suffix(*name, ".snapshot");
3970 r = bus_method_call_with_reply(
3972 "org.freedesktop.systemd1",
3973 "/org/freedesktop/systemd1",
3974 "org.freedesktop.systemd1.Manager",
3978 DBUS_TYPE_STRING, &n,
3987 static int daemon_reload(DBusConnection *bus, char **args) {
3992 if (arg_action == ACTION_RELOAD)
3994 else if (arg_action == ACTION_REEXEC)
3995 method = "Reexecute";
3997 assert(arg_action == ACTION_SYSTEMCTL);
4000 streq(args[0], "clear-jobs") ||
4001 streq(args[0], "cancel") ? "ClearJobs" :
4002 streq(args[0], "daemon-reexec") ? "Reexecute" :
4003 streq(args[0], "reset-failed") ? "ResetFailed" :
4004 streq(args[0], "halt") ? "Halt" :
4005 streq(args[0], "poweroff") ? "PowerOff" :
4006 streq(args[0], "reboot") ? "Reboot" :
4007 streq(args[0], "kexec") ? "KExec" :
4008 streq(args[0], "exit") ? "Exit" :
4009 /* "daemon-reload" */ "Reload";
4012 r = bus_method_call_with_reply(
4014 "org.freedesktop.systemd1",
4015 "/org/freedesktop/systemd1",
4016 "org.freedesktop.systemd1.Manager",
4022 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
4023 /* There's always a fallback possible for
4024 * legacy actions. */
4026 else if ((r == -ETIMEDOUT || r == -ECONNRESET) && streq(method, "Reexecute"))
4027 /* On reexecution, we expect a disconnect, not a
4031 log_error("Failed to issue method call: %s", bus_error_message(&error));
4033 dbus_error_free(&error);
4037 static int reset_failed(DBusConnection *bus, char **args) {
4041 if (strv_length(args) <= 1)
4042 return daemon_reload(bus, args);
4044 STRV_FOREACH(name, args+1) {
4045 _cleanup_free_ char *n;
4047 n = unit_name_mangle(*name);
4051 r = bus_method_call_with_reply(
4053 "org.freedesktop.systemd1",
4054 "/org/freedesktop/systemd1",
4055 "org.freedesktop.systemd1.Manager",
4059 DBUS_TYPE_STRING, &n,
4068 static int show_enviroment(DBusConnection *bus, char **args) {
4069 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
4070 DBusMessageIter iter, sub, sub2;
4073 *interface = "org.freedesktop.systemd1.Manager",
4074 *property = "Environment";
4076 pager_open_if_enabled();
4078 r = bus_method_call_with_reply(
4080 "org.freedesktop.systemd1",
4081 "/org/freedesktop/systemd1",
4082 "org.freedesktop.DBus.Properties",
4086 DBUS_TYPE_STRING, &interface,
4087 DBUS_TYPE_STRING, &property,
4092 if (!dbus_message_iter_init(reply, &iter) ||
4093 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
4094 log_error("Failed to parse reply.");
4098 dbus_message_iter_recurse(&iter, &sub);
4100 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_ARRAY ||
4101 dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_STRING) {
4102 log_error("Failed to parse reply.");
4106 dbus_message_iter_recurse(&sub, &sub2);
4108 while (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_INVALID) {
4111 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
4112 log_error("Failed to parse reply.");
4116 dbus_message_iter_get_basic(&sub2, &text);
4119 dbus_message_iter_next(&sub2);
4125 static int switch_root(DBusConnection *bus, char **args) {
4128 _cleanup_free_ char *init = NULL;
4130 l = strv_length(args);
4131 if (l < 2 || l > 3) {
4132 log_error("Wrong number of arguments.");
4139 init = strdup(args[2]);
4141 parse_env_file("/proc/cmdline", WHITESPACE,
4151 log_debug("switching root - root: %s; init: %s", root, init);
4153 return bus_method_call_with_reply(
4155 "org.freedesktop.systemd1",
4156 "/org/freedesktop/systemd1",
4157 "org.freedesktop.systemd1.Manager",
4161 DBUS_TYPE_STRING, &root,
4162 DBUS_TYPE_STRING, &init,
4166 static int set_environment(DBusConnection *bus, char **args) {
4167 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
4170 DBusMessageIter iter;
4176 dbus_error_init(&error);
4178 method = streq(args[0], "set-environment")
4180 : "UnsetEnvironment";
4182 m = dbus_message_new_method_call(
4183 "org.freedesktop.systemd1",
4184 "/org/freedesktop/systemd1",
4185 "org.freedesktop.systemd1.Manager",
4190 dbus_message_iter_init_append(m, &iter);
4192 r = bus_append_strv_iter(&iter, args + 1);
4196 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
4198 log_error("Failed to issue method call: %s", bus_error_message(&error));
4199 dbus_error_free(&error);
4206 static int enable_sysv_units(char **args) {
4209 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
4210 const char *verb = args[0];
4211 unsigned f = 1, t = 1;
4212 LookupPaths paths = {};
4214 if (arg_scope != UNIT_FILE_SYSTEM)
4217 if (!streq(verb, "enable") &&
4218 !streq(verb, "disable") &&
4219 !streq(verb, "is-enabled"))
4222 /* Processes all SysV units, and reshuffles the array so that
4223 * afterwards only the native units remain */
4225 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, NULL, NULL, NULL);
4230 for (f = 1; args[f]; f++) {
4232 _cleanup_free_ char *p = NULL, *q = NULL;
4233 bool found_native = false, found_sysv;
4235 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
4243 if (!endswith(name, ".service"))
4246 if (path_is_absolute(name))
4249 STRV_FOREACH(k, paths.unit_path) {
4250 if (!isempty(arg_root))
4251 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
4253 asprintf(&p, "%s/%s", *k, name);
4260 found_native = access(p, F_OK) >= 0;
4271 if (!isempty(arg_root))
4272 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
4274 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
4280 p[strlen(p) - sizeof(".service") + 1] = 0;
4281 found_sysv = access(p, F_OK) >= 0;
4286 /* Mark this entry, so that we don't try enabling it as native unit */
4287 args[f] = (char*) "";
4289 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
4291 if (!isempty(arg_root))
4292 argv[c++] = q = strappend("--root=", arg_root);
4294 argv[c++] = path_get_file_name(p);
4296 streq(verb, "enable") ? "on" :
4297 streq(verb, "disable") ? "off" : "--level=5";
4300 l = strv_join((char**)argv, " ");
4306 log_info("Executing %s", l);
4311 log_error("Failed to fork: %m");
4314 } else if (pid == 0) {
4317 execv(argv[0], (char**) argv);
4318 _exit(EXIT_FAILURE);
4321 j = wait_for_terminate(pid, &status);
4323 log_error("Failed to wait for child: %s", strerror(-r));
4328 if (status.si_code == CLD_EXITED) {
4329 if (streq(verb, "is-enabled")) {
4330 if (status.si_status == 0) {
4339 } else if (status.si_status != 0) {
4350 lookup_paths_free(&paths);
4352 /* Drop all SysV units */
4353 for (f = 1, t = 1; args[f]; f++) {
4355 if (isempty(args[f]))
4358 args[t++] = args[f];
4367 static int mangle_names(char **original_names, char ***mangled_names) {
4368 char **i, **l, **name;
4370 l = new(char*, strv_length(original_names) + 1);
4375 STRV_FOREACH(name, original_names) {
4377 /* When enabling units qualified path names are OK,
4378 * too, hence allow them explicitly. */
4383 *i = unit_name_mangle(*name);
4399 static int enable_unit(DBusConnection *bus, char **args) {
4400 const char *verb = args[0];
4401 UnitFileChange *changes = NULL;
4402 unsigned n_changes = 0, i;
4403 int carries_install_info = -1;
4404 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
4406 _cleanup_dbus_error_free_ DBusError error;
4407 _cleanup_strv_free_ char **mangled_names = NULL;
4409 dbus_error_init(&error);
4411 r = enable_sysv_units(args);
4418 r = mangle_names(args+1, &mangled_names);
4422 if (!bus || avoid_bus()) {
4423 if (streq(verb, "enable")) {
4424 r = unit_file_enable(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4425 carries_install_info = r;
4426 } else if (streq(verb, "disable"))
4427 r = unit_file_disable(arg_scope, arg_runtime, arg_root, mangled_names, &changes, &n_changes);
4428 else if (streq(verb, "reenable")) {
4429 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4430 carries_install_info = r;
4431 } else if (streq(verb, "link"))
4432 r = unit_file_link(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4433 else if (streq(verb, "preset")) {
4434 r = unit_file_preset(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4435 carries_install_info = r;
4436 } else if (streq(verb, "mask"))
4437 r = unit_file_mask(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4438 else if (streq(verb, "unmask"))
4439 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, mangled_names, &changes, &n_changes);
4440 else if (streq(verb, "set-default"))
4441 r = unit_file_set_default(arg_scope, arg_root, args[1], &changes, &n_changes);
4443 assert_not_reached("Unknown verb");
4446 log_error("Operation failed: %s", strerror(-r));
4451 for (i = 0; i < n_changes; i++) {
4452 if (changes[i].type == UNIT_FILE_SYMLINK)
4453 log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
4455 log_info("rm '%s'", changes[i].path);
4462 bool send_force = true, expect_carries_install_info = false;
4464 DBusMessageIter iter, sub, sub2;
4466 if (streq(verb, "enable")) {
4467 method = "EnableUnitFiles";
4468 expect_carries_install_info = true;
4469 } else if (streq(verb, "disable")) {
4470 method = "DisableUnitFiles";
4472 } else if (streq(verb, "reenable")) {
4473 method = "ReenableUnitFiles";
4474 expect_carries_install_info = true;
4475 } else if (streq(verb, "link"))
4476 method = "LinkUnitFiles";
4477 else if (streq(verb, "preset")) {
4478 method = "PresetUnitFiles";
4479 expect_carries_install_info = true;
4480 } else if (streq(verb, "mask"))
4481 method = "MaskUnitFiles";
4482 else if (streq(verb, "unmask")) {
4483 method = "UnmaskUnitFiles";
4485 } else if (streq(verb, "set-default")) {
4486 method = "SetDefaultTarget";
4488 assert_not_reached("Unknown verb");
4490 m = dbus_message_new_method_call(
4491 "org.freedesktop.systemd1",
4492 "/org/freedesktop/systemd1",
4493 "org.freedesktop.systemd1.Manager",
4500 dbus_message_iter_init_append(m, &iter);
4502 r = bus_append_strv_iter(&iter, mangled_names);
4504 log_error("Failed to append unit files.");
4509 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &a)) {
4510 log_error("Failed to append runtime boolean.");
4518 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b)) {
4519 log_error("Failed to append force boolean.");
4525 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
4527 log_error("Failed to issue method call: %s", bus_error_message(&error));
4532 if (!dbus_message_iter_init(reply, &iter)) {
4533 log_error("Failed to initialize iterator.");
4537 if (expect_carries_install_info) {
4538 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &b, true);
4540 log_error("Failed to parse reply.");
4544 carries_install_info = b;
4547 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
4548 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
4549 log_error("Failed to parse reply.");
4554 dbus_message_iter_recurse(&iter, &sub);
4555 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
4556 const char *type, *path, *source;
4558 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
4559 log_error("Failed to parse reply.");
4564 dbus_message_iter_recurse(&sub, &sub2);
4566 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
4567 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
4568 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &source, false) < 0) {
4569 log_error("Failed to parse reply.");
4575 if (streq(type, "symlink"))
4576 log_info("ln -s '%s' '%s'", source, path);
4578 log_info("rm '%s'", path);
4581 dbus_message_iter_next(&sub);
4584 /* Try to reload if enabeld */
4586 r = daemon_reload(bus, args);
4589 if (carries_install_info == 0)
4590 log_warning("The unit files have no [Install] section. They are not meant to be enabled\n"
4591 "using systemctl.\n"
4592 "Possible reasons for having this kind of units are:\n"
4593 "1) A unit may be statically enabled by being symlinked from another unit's\n"
4594 " .wants/ or .requires/ directory.\n"
4595 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
4596 " a requirement dependency on it.\n"
4597 "3) A unit may be started when needed via activation (socket, path, timer,\n"
4598 " D-Bus, udev, scripted systemctl call, ...).\n");
4601 unit_file_changes_free(changes, n_changes);
4606 static int unit_is_enabled(DBusConnection *bus, char **args) {
4607 _cleanup_dbus_error_free_ DBusError error;
4609 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
4614 dbus_error_init(&error);
4616 r = enable_sysv_units(args);
4622 if (!bus || avoid_bus()) {
4624 STRV_FOREACH(name, args+1) {
4625 UnitFileState state;
4627 n = unit_name_mangle(*name);
4631 state = unit_file_get_state(arg_scope, arg_root, n);
4638 if (state == UNIT_FILE_ENABLED ||
4639 state == UNIT_FILE_ENABLED_RUNTIME ||
4640 state == UNIT_FILE_STATIC)
4644 puts(unit_file_state_to_string(state));
4648 STRV_FOREACH(name, args+1) {
4651 n = unit_name_mangle(*name);
4655 r = bus_method_call_with_reply (
4657 "org.freedesktop.systemd1",
4658 "/org/freedesktop/systemd1",
4659 "org.freedesktop.systemd1.Manager",
4663 DBUS_TYPE_STRING, &n,
4671 if (!dbus_message_get_args(reply, &error,
4672 DBUS_TYPE_STRING, &s,
4673 DBUS_TYPE_INVALID)) {
4674 log_error("Failed to parse reply: %s", bus_error_message(&error));
4678 dbus_message_unref(reply);
4681 if (streq(s, "enabled") ||
4682 streq(s, "enabled-runtime") ||
4691 return enabled ? 0 : 1;
4694 static int systemctl_help(void) {
4696 pager_open_if_enabled();
4698 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
4699 "Query or send control commands to the systemd manager.\n\n"
4700 " -h --help Show this help\n"
4701 " --version Show package version\n"
4702 " -t --type=TYPE List only units of a particular type\n"
4703 " --state=STATE List only units with particular LOAD or SUB or ACTIVE state\n"
4704 " -p --property=NAME Show only properties by this name\n"
4705 " -a --all Show all loaded units/properties, including dead/empty\n"
4706 " ones. To list all units installed on the system, use\n"
4707 " the 'list-unit-files' command instead.\n"
4708 " --reverse Show reverse dependencies with 'list-dependencies'\n"
4709 " -l --full Don't ellipsize unit names on output\n"
4710 " --fail When queueing a new job, fail if conflicting jobs are\n"
4712 " --irreversible When queueing a new job, make sure it cannot be implicitly\n"
4714 " --ignore-dependencies\n"
4715 " When queueing a new job, ignore all its dependencies\n"
4716 " --show-types When showing sockets, explicitly show their type\n"
4717 " -i --ignore-inhibitors\n"
4718 " When shutting down or sleeping, ignore inhibitors\n"
4719 " --kill-who=WHO Who to send signal to\n"
4720 " -s --signal=SIGNAL Which signal to send\n"
4721 " -H --host=[USER@]HOST\n"
4722 " Show information for remote host\n"
4723 " -P --privileged Acquire privileges before execution\n"
4724 " -q --quiet Suppress output\n"
4725 " --no-block Do not wait until operation finished\n"
4726 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4727 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
4729 " --no-legend Do not print a legend (column headers and hints)\n"
4730 " --no-pager Do not pipe output into a pager\n"
4731 " --no-ask-password\n"
4732 " Do not ask for system passwords\n"
4733 " --system Connect to system manager\n"
4734 " --user Connect to user service manager\n"
4735 " --global Enable/disable unit files globally\n"
4736 " --runtime Enable unit files only temporarily until next reboot\n"
4737 " -f --force When enabling unit files, override existing symlinks\n"
4738 " When shutting down, execute action immediately\n"
4739 " --root=PATH Enable unit files in the specified root directory\n"
4740 " -n --lines=INTEGER Numer of journal entries to show\n"
4741 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
4742 " verbose, export, json, json-pretty, json-sse, cat)\n\n"
4744 " list-units List loaded units\n"
4745 " list-sockets List loaded sockets ordered by address\n"
4746 " start [NAME...] Start (activate) one or more units\n"
4747 " stop [NAME...] Stop (deactivate) one or more units\n"
4748 " reload [NAME...] Reload one or more units\n"
4749 " restart [NAME...] Start or restart one or more units\n"
4750 " try-restart [NAME...] Restart one or more units if active\n"
4751 " reload-or-restart [NAME...] Reload one or more units if possible,\n"
4752 " otherwise start or restart\n"
4753 " reload-or-try-restart [NAME...] Reload one or more units if possible,\n"
4754 " otherwise restart if active\n"
4755 " isolate [NAME] Start one unit and stop all others\n"
4756 " kill [NAME...] Send signal to processes of a unit\n"
4757 " is-active [NAME...] Check whether units are active\n"
4758 " is-failed [NAME...] Check whether units are failed\n"
4759 " status [NAME...|PID...] Show runtime status of one or more units\n"
4760 " show [NAME...|JOB...] Show properties of one or more\n"
4761 " units/jobs or the manager\n"
4762 " set-property [NAME] [ASSIGNMENT...]\n"
4763 " Sets one or more properties of a unit\n"
4764 " help [NAME...|PID...] Show manual for one or more units\n"
4765 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
4767 " list-dependencies [NAME] Recursively show units which are required\n"
4768 " or wanted by this unit or by which this\n"
4769 " unit is required or wanted\n\n"
4770 "Unit File Commands:\n"
4771 " list-unit-files List installed unit files\n"
4772 " enable [NAME...] Enable one or more unit files\n"
4773 " disable [NAME...] Disable one or more unit files\n"
4774 " reenable [NAME...] Reenable one or more unit files\n"
4775 " preset [NAME...] Enable/disable one or more unit files\n"
4776 " based on preset configuration\n"
4777 " is-enabled [NAME...] Check whether unit files are enabled\n\n"
4778 " mask [NAME...] Mask one or more units\n"
4779 " unmask [NAME...] Unmask one or more units\n"
4780 " link [PATH...] Link one or more units files into\n"
4781 " the search path\n"
4782 " get-default Get the name of the default target\n"
4783 " set-default NAME Set the default target\n\n"
4785 " list-jobs List jobs\n"
4786 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
4787 "Snapshot Commands:\n"
4788 " snapshot [NAME] Create a snapshot\n"
4789 " delete [NAME...] Remove one or more snapshots\n\n"
4790 "Environment Commands:\n"
4791 " show-environment Dump environment\n"
4792 " set-environment [NAME=VALUE...] Set one or more environment variables\n"
4793 " unset-environment [NAME...] Unset one or more environment variables\n\n"
4794 "Manager Lifecycle Commands:\n"
4795 " daemon-reload Reload systemd manager configuration\n"
4796 " daemon-reexec Reexecute systemd manager\n\n"
4797 "System Commands:\n"
4798 " default Enter system default mode\n"
4799 " rescue Enter system rescue mode\n"
4800 " emergency Enter system emergency mode\n"
4801 " halt Shut down and halt the system\n"
4802 " poweroff Shut down and power-off the system\n"
4803 " reboot Shut down and reboot the system\n"
4804 " kexec Shut down and reboot the system with kexec\n"
4805 " exit Request user instance exit\n"
4806 " switch-root [ROOT] [INIT] Change to a different root file system\n"
4807 " suspend Suspend the system\n"
4808 " hibernate Hibernate the system\n"
4809 " hybrid-sleep Hibernate and suspend the system\n",
4810 program_invocation_short_name);
4815 static int halt_help(void) {
4817 printf("%s [OPTIONS...]\n\n"
4818 "%s the system.\n\n"
4819 " --help Show this help\n"
4820 " --halt Halt the machine\n"
4821 " -p --poweroff Switch off the machine\n"
4822 " --reboot Reboot the machine\n"
4823 " -f --force Force immediate halt/power-off/reboot\n"
4824 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
4825 " -d --no-wtmp Don't write wtmp record\n"
4826 " --no-wall Don't send wall message before halt/power-off/reboot\n",
4827 program_invocation_short_name,
4828 arg_action == ACTION_REBOOT ? "Reboot" :
4829 arg_action == ACTION_POWEROFF ? "Power off" :
4835 static int shutdown_help(void) {
4837 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
4838 "Shut down the system.\n\n"
4839 " --help Show this help\n"
4840 " -H --halt Halt the machine\n"
4841 " -P --poweroff Power-off the machine\n"
4842 " -r --reboot Reboot the machine\n"
4843 " -h Equivalent to --poweroff, overridden by --halt\n"
4844 " -k Don't halt/power-off/reboot, just send warnings\n"
4845 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4846 " -c Cancel a pending shutdown\n",
4847 program_invocation_short_name);
4852 static int telinit_help(void) {
4854 printf("%s [OPTIONS...] {COMMAND}\n\n"
4855 "Send control commands to the init daemon.\n\n"
4856 " --help Show this help\n"
4857 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
4859 " 0 Power-off the machine\n"
4860 " 6 Reboot the machine\n"
4861 " 2, 3, 4, 5 Start runlevelX.target unit\n"
4862 " 1, s, S Enter rescue mode\n"
4863 " q, Q Reload init daemon configuration\n"
4864 " u, U Reexecute init daemon\n",
4865 program_invocation_short_name);
4870 static int runlevel_help(void) {
4872 printf("%s [OPTIONS...]\n\n"
4873 "Prints the previous and current runlevel of the init system.\n\n"
4874 " --help Show this help\n",
4875 program_invocation_short_name);
4880 static int help_types(void) {
4884 puts("Available unit types:");
4885 for(i = 0; i < _UNIT_TYPE_MAX; i++) {
4886 t = unit_type_to_string(i);
4894 static int systemctl_parse_argv(int argc, char *argv[]) {
4903 ARG_IGNORE_DEPENDENCIES,
4915 ARG_NO_ASK_PASSWORD,
4923 static const struct option options[] = {
4924 { "help", no_argument, NULL, 'h' },
4925 { "version", no_argument, NULL, ARG_VERSION },
4926 { "type", required_argument, NULL, 't' },
4927 { "property", required_argument, NULL, 'p' },
4928 { "all", no_argument, NULL, 'a' },
4929 { "reverse", no_argument, NULL, ARG_REVERSE },
4930 { "after", no_argument, NULL, ARG_AFTER },
4931 { "before", no_argument, NULL, ARG_BEFORE },
4932 { "show-types", no_argument, NULL, ARG_SHOW_TYPES },
4933 { "failed", no_argument, NULL, ARG_FAILED }, /* compatibility only */
4934 { "full", no_argument, NULL, 'l' },
4935 { "fail", no_argument, NULL, ARG_FAIL },
4936 { "irreversible", no_argument, NULL, ARG_IRREVERSIBLE },
4937 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
4938 { "ignore-inhibitors", no_argument, NULL, 'i' },
4939 { "user", no_argument, NULL, ARG_USER },
4940 { "system", no_argument, NULL, ARG_SYSTEM },
4941 { "global", no_argument, NULL, ARG_GLOBAL },
4942 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
4943 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
4944 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
4945 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4946 { "quiet", no_argument, NULL, 'q' },
4947 { "root", required_argument, NULL, ARG_ROOT },
4948 { "force", no_argument, NULL, ARG_FORCE },
4949 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
4950 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
4951 { "signal", required_argument, NULL, 's' },
4952 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
4953 { "host", required_argument, NULL, 'H' },
4954 { "privileged", no_argument, NULL, 'P' },
4955 { "runtime", no_argument, NULL, ARG_RUNTIME },
4956 { "lines", required_argument, NULL, 'n' },
4957 { "output", required_argument, NULL, 'o' },
4958 { "plain", no_argument, NULL, ARG_PLAIN },
4959 { "state", required_argument, NULL, ARG_STATE },
4960 { NULL, 0, NULL, 0 }
4968 while ((c = getopt_long(argc, argv, "ht:p:alqfs:H:Pn:o:i", options, NULL)) >= 0) {
4977 puts(PACKAGE_STRING);
4978 puts(SYSTEMD_FEATURES);
4985 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
4986 _cleanup_free_ char *type;
4988 type = strndup(word, size);
4992 if (streq(type, "help")) {
4997 if (unit_type_from_string(type) >= 0) {
4998 if (strv_push(&arg_types, type))
5004 /* It's much nicer to use --state= for
5005 * load states, but let's support this
5006 * in --types= too for compatibility
5007 * with old versions */
5008 if (unit_load_state_from_string(optarg) >= 0) {
5009 if (strv_push(&arg_states, type) < 0)
5015 log_error("Unknown unit type or load state '%s'.", type);
5016 log_info("Use -t help to see a list of allowed values.");
5024 /* Make sure that if the empty property list
5025 was specified, we won't show any properties. */
5026 if (isempty(optarg) && !arg_properties) {
5027 arg_properties = strv_new(NULL, NULL);
5028 if (!arg_properties)
5034 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
5037 prop = strndup(word, size);
5041 if (strv_push(&arg_properties, prop) < 0) {
5048 /* If the user asked for a particular
5049 * property, show it to him, even if it is
5061 arg_dependency = DEPENDENCY_REVERSE;
5065 arg_dependency = DEPENDENCY_AFTER;
5069 arg_dependency = DEPENDENCY_BEFORE;
5072 case ARG_SHOW_TYPES:
5073 arg_show_types = true;
5077 arg_job_mode = "fail";
5080 case ARG_IRREVERSIBLE:
5081 arg_job_mode = "replace-irreversibly";
5084 case ARG_IGNORE_DEPENDENCIES:
5085 arg_job_mode = "ignore-dependencies";
5089 arg_scope = UNIT_FILE_USER;
5093 arg_scope = UNIT_FILE_SYSTEM;
5097 arg_scope = UNIT_FILE_GLOBAL;
5101 arg_no_block = true;
5105 arg_no_legend = true;
5109 arg_no_pager = true;
5125 if (strv_extend(&arg_states, "failed") < 0)
5143 arg_no_reload = true;
5147 arg_kill_who = optarg;
5151 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
5152 log_error("Failed to parse signal string %s.", optarg);
5157 case ARG_NO_ASK_PASSWORD:
5158 arg_ask_password = false;
5162 arg_transport = TRANSPORT_POLKIT;
5166 arg_transport = TRANSPORT_SSH;
5167 parse_user_at_host(optarg, &arg_user, &arg_host);
5175 if (safe_atou(optarg, &arg_lines) < 0) {
5176 log_error("Failed to parse lines '%s'", optarg);
5182 arg_output = output_mode_from_string(optarg);
5183 if (arg_output < 0) {
5184 log_error("Unknown output '%s'.", optarg);
5190 arg_ignore_inhibitors = true;
5201 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
5204 s = strndup(word, size);
5208 if (strv_push(&arg_states, s) < 0) {
5220 log_error("Unknown option code '%c'.", c);
5225 if (arg_transport != TRANSPORT_NORMAL && arg_scope != UNIT_FILE_SYSTEM) {
5226 log_error("Cannot access user instance remotely.");
5233 static int halt_parse_argv(int argc, char *argv[]) {
5242 static const struct option options[] = {
5243 { "help", no_argument, NULL, ARG_HELP },
5244 { "halt", no_argument, NULL, ARG_HALT },
5245 { "poweroff", no_argument, NULL, 'p' },
5246 { "reboot", no_argument, NULL, ARG_REBOOT },
5247 { "force", no_argument, NULL, 'f' },
5248 { "wtmp-only", no_argument, NULL, 'w' },
5249 { "no-wtmp", no_argument, NULL, 'd' },
5250 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5251 { NULL, 0, NULL, 0 }
5259 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
5260 if (runlevel == '0' || runlevel == '6')
5263 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
5271 arg_action = ACTION_HALT;
5275 if (arg_action != ACTION_REBOOT)
5276 arg_action = ACTION_POWEROFF;
5280 arg_action = ACTION_REBOOT;
5302 /* Compatibility nops */
5309 log_error("Unknown option code '%c'.", c);
5314 if (optind < argc) {
5315 log_error("Too many arguments.");
5322 static int parse_time_spec(const char *t, usec_t *_u) {
5326 if (streq(t, "now"))
5328 else if (!strchr(t, ':')) {
5331 if (safe_atou64(t, &u) < 0)
5334 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
5343 hour = strtol(t, &e, 10);
5344 if (errno > 0 || *e != ':' || hour < 0 || hour > 23)
5347 minute = strtol(e+1, &e, 10);
5348 if (errno > 0 || *e != 0 || minute < 0 || minute > 59)
5351 n = now(CLOCK_REALTIME);
5352 s = (time_t) (n / USEC_PER_SEC);
5354 assert_se(localtime_r(&s, &tm));
5356 tm.tm_hour = (int) hour;
5357 tm.tm_min = (int) minute;
5360 assert_se(s = mktime(&tm));
5362 *_u = (usec_t) s * USEC_PER_SEC;
5365 *_u += USEC_PER_DAY;
5371 static int shutdown_parse_argv(int argc, char *argv[]) {
5378 static const struct option options[] = {
5379 { "help", no_argument, NULL, ARG_HELP },
5380 { "halt", no_argument, NULL, 'H' },
5381 { "poweroff", no_argument, NULL, 'P' },
5382 { "reboot", no_argument, NULL, 'r' },
5383 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
5384 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5385 { NULL, 0, NULL, 0 }
5393 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
5401 arg_action = ACTION_HALT;
5405 arg_action = ACTION_POWEROFF;
5410 arg_action = ACTION_KEXEC;
5412 arg_action = ACTION_REBOOT;
5416 arg_action = ACTION_KEXEC;
5420 if (arg_action != ACTION_HALT)
5421 arg_action = ACTION_POWEROFF;
5434 /* Compatibility nops */
5438 arg_action = ACTION_CANCEL_SHUTDOWN;
5445 log_error("Unknown option code '%c'.", c);
5450 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
5451 r = parse_time_spec(argv[optind], &arg_when);
5453 log_error("Failed to parse time specification: %s", argv[optind]);
5457 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
5459 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
5460 /* No time argument for shutdown cancel */
5461 arg_wall = argv + optind;
5462 else if (argc > optind + 1)
5463 /* We skip the time argument */
5464 arg_wall = argv + optind + 1;
5471 static int telinit_parse_argv(int argc, char *argv[]) {
5478 static const struct option options[] = {
5479 { "help", no_argument, NULL, ARG_HELP },
5480 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5481 { NULL, 0, NULL, 0 }
5484 static const struct {
5488 { '0', ACTION_POWEROFF },
5489 { '6', ACTION_REBOOT },
5490 { '1', ACTION_RESCUE },
5491 { '2', ACTION_RUNLEVEL2 },
5492 { '3', ACTION_RUNLEVEL3 },
5493 { '4', ACTION_RUNLEVEL4 },
5494 { '5', ACTION_RUNLEVEL5 },
5495 { 's', ACTION_RESCUE },
5496 { 'S', ACTION_RESCUE },
5497 { 'q', ACTION_RELOAD },
5498 { 'Q', ACTION_RELOAD },
5499 { 'u', ACTION_REEXEC },
5500 { 'U', ACTION_REEXEC }
5509 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
5524 log_error("Unknown option code '%c'.", c);
5529 if (optind >= argc) {
5534 if (optind + 1 < argc) {
5535 log_error("Too many arguments.");
5539 if (strlen(argv[optind]) != 1) {
5540 log_error("Expected single character argument.");
5544 for (i = 0; i < ELEMENTSOF(table); i++)
5545 if (table[i].from == argv[optind][0])
5548 if (i >= ELEMENTSOF(table)) {
5549 log_error("Unknown command '%s'.", argv[optind]);
5553 arg_action = table[i].to;
5560 static int runlevel_parse_argv(int argc, char *argv[]) {
5566 static const struct option options[] = {
5567 { "help", no_argument, NULL, ARG_HELP },
5568 { NULL, 0, NULL, 0 }
5576 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
5587 log_error("Unknown option code '%c'.", c);
5592 if (optind < argc) {
5593 log_error("Too many arguments.");
5600 static int parse_argv(int argc, char *argv[]) {
5604 if (program_invocation_short_name) {
5606 if (strstr(program_invocation_short_name, "halt")) {
5607 arg_action = ACTION_HALT;
5608 return halt_parse_argv(argc, argv);
5609 } else if (strstr(program_invocation_short_name, "poweroff")) {
5610 arg_action = ACTION_POWEROFF;
5611 return halt_parse_argv(argc, argv);
5612 } else if (strstr(program_invocation_short_name, "reboot")) {
5614 arg_action = ACTION_KEXEC;
5616 arg_action = ACTION_REBOOT;
5617 return halt_parse_argv(argc, argv);
5618 } else if (strstr(program_invocation_short_name, "shutdown")) {
5619 arg_action = ACTION_POWEROFF;
5620 return shutdown_parse_argv(argc, argv);
5621 } else if (strstr(program_invocation_short_name, "init")) {
5623 if (sd_booted() > 0) {
5624 arg_action = ACTION_INVALID;
5625 return telinit_parse_argv(argc, argv);
5627 /* Hmm, so some other init system is
5628 * running, we need to forward this
5629 * request to it. For now we simply
5630 * guess that it is Upstart. */
5632 execv(TELINIT, argv);
5634 log_error("Couldn't find an alternative telinit implementation to spawn.");
5638 } else if (strstr(program_invocation_short_name, "runlevel")) {
5639 arg_action = ACTION_RUNLEVEL;
5640 return runlevel_parse_argv(argc, argv);
5644 arg_action = ACTION_SYSTEMCTL;
5645 return systemctl_parse_argv(argc, argv);
5648 _pure_ static int action_to_runlevel(void) {
5650 static const char table[_ACTION_MAX] = {
5651 [ACTION_HALT] = '0',
5652 [ACTION_POWEROFF] = '0',
5653 [ACTION_REBOOT] = '6',
5654 [ACTION_RUNLEVEL2] = '2',
5655 [ACTION_RUNLEVEL3] = '3',
5656 [ACTION_RUNLEVEL4] = '4',
5657 [ACTION_RUNLEVEL5] = '5',
5658 [ACTION_RESCUE] = '1'
5661 assert(arg_action < _ACTION_MAX);
5663 return table[arg_action];
5666 static int talk_upstart(void) {
5667 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
5668 _cleanup_dbus_error_free_ DBusError error;
5669 int previous, rl, r;
5671 env1_buf[] = "RUNLEVEL=X",
5672 env2_buf[] = "PREVLEVEL=X";
5673 char *env1 = env1_buf, *env2 = env2_buf;
5674 const char *emit = "runlevel";
5675 dbus_bool_t b_false = FALSE;
5676 DBusMessageIter iter, sub;
5677 DBusConnection *bus;
5679 dbus_error_init(&error);
5681 if (!(rl = action_to_runlevel()))
5684 if (utmp_get_runlevel(&previous, NULL) < 0)
5687 if (!(bus = dbus_connection_open_private("unix:abstract=/com/ubuntu/upstart", &error))) {
5688 if (dbus_error_has_name(&error, DBUS_ERROR_NO_SERVER)) {
5693 log_error("Failed to connect to Upstart bus: %s", bus_error_message(&error));
5698 if ((r = bus_check_peercred(bus)) < 0) {
5699 log_error("Failed to verify owner of bus.");
5703 if (!(m = dbus_message_new_method_call(
5704 "com.ubuntu.Upstart",
5705 "/com/ubuntu/Upstart",
5706 "com.ubuntu.Upstart0_6",
5709 log_error("Could not allocate message.");
5714 dbus_message_iter_init_append(m, &iter);
5716 env1_buf[sizeof(env1_buf)-2] = rl;
5717 env2_buf[sizeof(env2_buf)-2] = previous;
5719 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &emit) ||
5720 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub) ||
5721 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env1) ||
5722 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env2) ||
5723 !dbus_message_iter_close_container(&iter, &sub) ||
5724 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b_false)) {
5725 log_error("Could not append arguments to message.");
5730 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
5732 if (bus_error_is_no_service(&error)) {
5737 log_error("Failed to issue method call: %s", bus_error_message(&error));
5746 dbus_connection_flush(bus);
5747 dbus_connection_close(bus);
5748 dbus_connection_unref(bus);
5754 static int talk_initctl(void) {
5755 struct init_request request = {};
5757 _cleanup_close_ int fd = -1;
5760 rl = action_to_runlevel();
5764 request.magic = INIT_MAGIC;
5765 request.sleeptime = 0;
5766 request.cmd = INIT_CMD_RUNLVL;
5767 request.runlevel = rl;
5769 fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY);
5771 if (errno == ENOENT)
5774 log_error("Failed to open "INIT_FIFO": %m");
5779 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
5781 log_error("Failed to write to "INIT_FIFO": %m");
5782 return errno > 0 ? -errno : -EIO;
5788 static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
5790 static const struct {
5798 int (* const dispatch)(DBusConnection *bus, char **args);
5800 { "list-units", LESS, 1, list_units },
5801 { "list-unit-files", EQUAL, 1, list_unit_files },
5802 { "list-sockets", LESS, 1, list_sockets },
5803 { "list-jobs", EQUAL, 1, list_jobs },
5804 { "clear-jobs", EQUAL, 1, daemon_reload },
5805 { "cancel", MORE, 2, cancel_job },
5806 { "start", MORE, 2, start_unit },
5807 { "stop", MORE, 2, start_unit },
5808 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5809 { "reload", MORE, 2, start_unit },
5810 { "restart", MORE, 2, start_unit },
5811 { "try-restart", MORE, 2, start_unit },
5812 { "reload-or-restart", MORE, 2, start_unit },
5813 { "reload-or-try-restart", MORE, 2, start_unit },
5814 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
5815 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5816 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
5817 { "isolate", EQUAL, 2, start_unit },
5818 { "kill", MORE, 2, kill_unit },
5819 { "is-active", MORE, 2, check_unit_active },
5820 { "check", MORE, 2, check_unit_active },
5821 { "is-failed", MORE, 2, check_unit_failed },
5822 { "show", MORE, 1, show },
5823 { "status", MORE, 1, show },
5824 { "help", MORE, 2, show },
5825 { "snapshot", LESS, 2, snapshot },
5826 { "delete", MORE, 2, delete_snapshot },
5827 { "daemon-reload", EQUAL, 1, daemon_reload },
5828 { "daemon-reexec", EQUAL, 1, daemon_reload },
5829 { "show-environment", EQUAL, 1, show_enviroment },
5830 { "set-environment", MORE, 2, set_environment },
5831 { "unset-environment", MORE, 2, set_environment },
5832 { "halt", EQUAL, 1, start_special },
5833 { "poweroff", EQUAL, 1, start_special },
5834 { "reboot", EQUAL, 1, start_special },
5835 { "kexec", EQUAL, 1, start_special },
5836 { "suspend", EQUAL, 1, start_special },
5837 { "hibernate", EQUAL, 1, start_special },
5838 { "hybrid-sleep", EQUAL, 1, start_special },
5839 { "default", EQUAL, 1, start_special },
5840 { "rescue", EQUAL, 1, start_special },
5841 { "emergency", EQUAL, 1, start_special },
5842 { "exit", EQUAL, 1, start_special },
5843 { "reset-failed", MORE, 1, reset_failed },
5844 { "enable", MORE, 2, enable_unit },
5845 { "disable", MORE, 2, enable_unit },
5846 { "is-enabled", MORE, 2, unit_is_enabled },
5847 { "reenable", MORE, 2, enable_unit },
5848 { "preset", MORE, 2, enable_unit },
5849 { "mask", MORE, 2, enable_unit },
5850 { "unmask", MORE, 2, enable_unit },
5851 { "link", MORE, 2, enable_unit },
5852 { "switch-root", MORE, 2, switch_root },
5853 { "list-dependencies", LESS, 2, list_dependencies },
5854 { "set-default", EQUAL, 2, enable_unit },
5855 { "get-default", LESS, 1, get_default },
5856 { "set-property", MORE, 3, set_property },
5866 left = argc - optind;
5869 /* Special rule: no arguments means "list-units" */
5872 if (streq(argv[optind], "help") && !argv[optind+1]) {
5873 log_error("This command expects one or more "
5874 "unit names. Did you mean --help?");
5878 for (i = 0; i < ELEMENTSOF(verbs); i++)
5879 if (streq(argv[optind], verbs[i].verb))
5882 if (i >= ELEMENTSOF(verbs)) {
5883 log_error("Unknown operation '%s'.", argv[optind]);
5888 switch (verbs[i].argc_cmp) {
5891 if (left != verbs[i].argc) {
5892 log_error("Invalid number of arguments.");
5899 if (left < verbs[i].argc) {
5900 log_error("Too few arguments.");
5907 if (left > verbs[i].argc) {
5908 log_error("Too many arguments.");
5915 assert_not_reached("Unknown comparison operator.");
5918 /* Require a bus connection for all operations but
5920 if (!streq(verbs[i].verb, "enable") &&
5921 !streq(verbs[i].verb, "disable") &&
5922 !streq(verbs[i].verb, "is-enabled") &&
5923 !streq(verbs[i].verb, "list-unit-files") &&
5924 !streq(verbs[i].verb, "reenable") &&
5925 !streq(verbs[i].verb, "preset") &&
5926 !streq(verbs[i].verb, "mask") &&
5927 !streq(verbs[i].verb, "unmask") &&
5928 !streq(verbs[i].verb, "link") &&
5929 !streq(verbs[i].verb, "set-default") &&
5930 !streq(verbs[i].verb, "get-default")) {
5932 if (running_in_chroot() > 0) {
5933 log_info("Running in chroot, ignoring request.");
5937 if (((!streq(verbs[i].verb, "reboot") &&
5938 !streq(verbs[i].verb, "halt") &&
5939 !streq(verbs[i].verb, "poweroff")) || arg_force <= 0) && !bus) {
5940 log_error("Failed to get D-Bus connection: %s",
5941 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5947 if (!bus && !avoid_bus()) {
5948 log_error("Failed to get D-Bus connection: %s",
5949 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5954 return verbs[i].dispatch(bus, argv + optind);
5957 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
5958 _cleanup_close_ int fd;
5959 struct sd_shutdown_command c = {
5965 union sockaddr_union sockaddr = {
5966 .un.sun_family = AF_UNIX,
5967 .un.sun_path = "/run/systemd/shutdownd",
5969 struct iovec iovec[2] = {
5970 {.iov_base = (char*) &c,
5971 .iov_len = offsetof(struct sd_shutdown_command, wall_message),
5974 struct msghdr msghdr = {
5975 .msg_name = &sockaddr,
5976 .msg_namelen = offsetof(struct sockaddr_un, sun_path)
5977 + sizeof("/run/systemd/shutdownd") - 1,
5982 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
5986 if (!isempty(message)) {
5987 iovec[1].iov_base = (char*) message;
5988 iovec[1].iov_len = strlen(message);
5989 msghdr.msg_iovlen++;
5992 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0)
5998 static int reload_with_fallback(DBusConnection *bus) {
6001 /* First, try systemd via D-Bus. */
6002 if (daemon_reload(bus, NULL) >= 0)
6006 /* Nothing else worked, so let's try signals */
6007 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
6009 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
6010 log_error("kill() failed: %m");
6017 static int start_with_fallback(DBusConnection *bus) {
6020 /* First, try systemd via D-Bus. */
6021 if (start_unit(bus, NULL) >= 0)
6025 /* Hmm, talking to systemd via D-Bus didn't work. Then
6026 * let's try to talk to Upstart via D-Bus. */
6027 if (talk_upstart() > 0)
6030 /* Nothing else worked, so let's try
6032 if (talk_initctl() > 0)
6035 log_error("Failed to talk to init daemon.");
6039 warn_wall(arg_action);
6043 static _noreturn_ void halt_now(enum action a) {
6045 /* Make sure C-A-D is handled by the kernel from this
6047 reboot(RB_ENABLE_CAD);
6052 log_info("Halting.");
6053 reboot(RB_HALT_SYSTEM);
6056 case ACTION_POWEROFF:
6057 log_info("Powering off.");
6058 reboot(RB_POWER_OFF);
6062 log_info("Rebooting.");
6063 reboot(RB_AUTOBOOT);
6067 assert_not_reached("Unknown halt action.");
6070 assert_not_reached("Uh? This shouldn't happen.");
6073 static int halt_main(DBusConnection *bus) {
6076 r = check_inhibitors(bus, arg_action);
6080 if (geteuid() != 0) {
6081 /* Try logind if we are a normal user and no special
6082 * mode applies. Maybe PolicyKit allows us to shutdown
6085 if (arg_when <= 0 &&
6088 (arg_action == ACTION_POWEROFF ||
6089 arg_action == ACTION_REBOOT)) {
6090 r = reboot_with_logind(bus, arg_action);
6095 log_error("Must be root.");
6100 _cleanup_free_ char *m;
6102 m = strv_join(arg_wall, " ");
6103 r = send_shutdownd(arg_when,
6104 arg_action == ACTION_HALT ? 'H' :
6105 arg_action == ACTION_POWEROFF ? 'P' :
6106 arg_action == ACTION_KEXEC ? 'K' :
6113 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
6115 char date[FORMAT_TIMESTAMP_MAX];
6117 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
6118 format_timestamp(date, sizeof(date), arg_when));
6123 if (!arg_dry && !arg_force)
6124 return start_with_fallback(bus);
6127 if (sd_booted() > 0)
6128 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
6130 r = utmp_put_shutdown();
6132 log_warning("Failed to write utmp record: %s", strerror(-r));
6139 halt_now(arg_action);
6140 /* We should never reach this. */
6144 static int runlevel_main(void) {
6145 int r, runlevel, previous;
6147 r = utmp_get_runlevel(&runlevel, &previous);
6154 previous <= 0 ? 'N' : previous,
6155 runlevel <= 0 ? 'N' : runlevel);
6160 int main(int argc, char*argv[]) {
6161 int r, retval = EXIT_FAILURE;
6162 DBusConnection *bus = NULL;
6163 _cleanup_dbus_error_free_ DBusError error;
6165 dbus_error_init(&error);
6167 setlocale(LC_ALL, "");
6168 log_parse_environment();
6171 r = parse_argv(argc, argv);
6175 retval = EXIT_SUCCESS;
6179 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
6180 * let's shortcut this */
6181 if (arg_action == ACTION_RUNLEVEL) {
6182 r = runlevel_main();
6183 retval = r < 0 ? EXIT_FAILURE : r;
6187 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
6188 log_info("Running in chroot, ignoring request.");
6194 if (arg_transport == TRANSPORT_NORMAL)
6195 bus_connect(arg_scope == UNIT_FILE_SYSTEM ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &bus, &private_bus, &error);
6196 else if (arg_transport == TRANSPORT_POLKIT) {
6197 bus_connect_system_polkit(&bus, &error);
6198 private_bus = false;
6199 } else if (arg_transport == TRANSPORT_SSH) {
6200 bus_connect_system_ssh(arg_user, arg_host, &bus, &error);
6201 private_bus = false;
6203 assert_not_reached("Uh, invalid transport...");
6206 switch (arg_action) {
6208 case ACTION_SYSTEMCTL:
6209 r = systemctl_main(bus, argc, argv, &error);
6213 case ACTION_POWEROFF:
6219 case ACTION_RUNLEVEL2:
6220 case ACTION_RUNLEVEL3:
6221 case ACTION_RUNLEVEL4:
6222 case ACTION_RUNLEVEL5:
6224 case ACTION_EMERGENCY:
6225 case ACTION_DEFAULT:
6226 r = start_with_fallback(bus);
6231 r = reload_with_fallback(bus);
6234 case ACTION_CANCEL_SHUTDOWN: {
6238 m = strv_join(arg_wall, " ");
6240 retval = EXIT_FAILURE;
6244 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
6246 log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r));
6251 case ACTION_INVALID:
6252 case ACTION_RUNLEVEL:
6254 assert_not_reached("Unknown action");
6257 retval = r < 0 ? EXIT_FAILURE : r;
6261 dbus_connection_flush(bus);
6262 dbus_connection_close(bus);
6263 dbus_connection_unref(bus);
6268 strv_free(arg_types);
6269 strv_free(arg_states);
6270 strv_free(arg_properties);
6273 ask_password_agent_close();
6274 polkit_agent_close();