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) {
2508 const char *on, *off, *ss;
2510 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
2511 char since2[FORMAT_TIMESTAMP_MAX], *s2;
2514 arg_all * OUTPUT_SHOW_ALL |
2515 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
2516 on_tty() * OUTPUT_COLOR |
2517 !arg_quiet * OUTPUT_WARN_CUTOFF |
2518 arg_full * OUTPUT_FULL_WIDTH;
2523 /* This shows pretty information about a unit. See
2524 * print_property() for a low-level property printer */
2526 printf("%s", strna(i->id));
2528 if (i->description && !streq_ptr(i->id, i->description))
2529 printf(" - %s", i->description);
2534 printf(" Follow: unit currently follows state of %s\n", i->following);
2536 if (streq_ptr(i->load_state, "error")) {
2537 on = ansi_highlight_red();
2538 off = ansi_highlight_off();
2542 path = i->source_path ? i->source_path : i->fragment_path;
2545 printf(" Loaded: %s%s%s (Reason: %s)\n",
2546 on, strna(i->load_state), off, i->load_error);
2547 else if (path && i->unit_file_state)
2548 printf(" Loaded: %s%s%s (%s; %s)\n",
2549 on, strna(i->load_state), off, path, i->unit_file_state);
2551 printf(" Loaded: %s%s%s (%s)\n",
2552 on, strna(i->load_state), off, path);
2554 printf(" Loaded: %s%s%s\n",
2555 on, strna(i->load_state), off);
2557 if (!strv_isempty(i->dropin_paths)) {
2562 STRV_FOREACH(dropin, i->dropin_paths) {
2563 if (! dir || last) {
2564 printf(dir ? " " : " Drop-In: ");
2568 if (path_get_parent(*dropin, &dir) < 0) {
2573 printf("%s\n %s", dir,
2574 draw_special_char(DRAW_TREE_RIGHT));
2577 last = ! (*(dropin + 1) && startswith(*(dropin + 1), dir));
2579 printf("%s%s", path_get_file_name(*dropin), last ? "\n" : ", ");
2585 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
2587 if (streq_ptr(i->active_state, "failed")) {
2588 on = ansi_highlight_red();
2589 off = ansi_highlight_off();
2590 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
2591 on = ansi_highlight_green();
2592 off = ansi_highlight_off();
2597 printf(" Active: %s%s (%s)%s",
2598 on, strna(i->active_state), ss, off);
2600 printf(" Active: %s%s%s",
2601 on, strna(i->active_state), off);
2603 if (!isempty(i->result) && !streq(i->result, "success"))
2604 printf(" (Result: %s)", i->result);
2606 timestamp = (streq_ptr(i->active_state, "active") ||
2607 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
2608 (streq_ptr(i->active_state, "inactive") ||
2609 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
2610 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
2611 i->active_exit_timestamp;
2613 s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
2614 s2 = format_timestamp(since2, sizeof(since2), timestamp);
2617 printf(" since %s; %s\n", s2, s1);
2619 printf(" since %s\n", s2);
2623 if (!i->condition_result && i->condition_timestamp > 0) {
2624 s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
2625 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
2627 printf(" start condition failed at %s%s%s\n",
2628 s2, s1 ? "; " : "", s1 ? s1 : "");
2629 if (i->failed_condition_trigger)
2630 printf(" none of the trigger conditions were met\n");
2631 else if (i->failed_condition)
2632 printf(" %s=%s%s was not met\n",
2633 i->failed_condition,
2634 i->failed_condition_negate ? "!" : "",
2635 i->failed_condition_param);
2639 printf(" Device: %s\n", i->sysfs_path);
2641 printf(" Where: %s\n", i->where);
2643 printf(" What: %s\n", i->what);
2645 STRV_FOREACH(t, i->documentation)
2646 printf(" %*s %s\n", 9, t == i->documentation ? "Docs:" : "", *t);
2648 STRV_FOREACH_PAIR(t, t2, i->listen)
2649 printf(" %*s %s (%s)\n", 9, t == i->listen ? "Listen:" : "", *t2, *t);
2652 printf(" Accepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
2654 LIST_FOREACH(exec, p, i->exec) {
2655 _cleanup_free_ char *argv = NULL;
2658 /* Only show exited processes here */
2662 argv = strv_join(p->argv, " ");
2663 printf(" Process: %u %s=%s ", p->pid, p->name, strna(argv));
2665 good = is_clean_exit_lsb(p->code, p->status, NULL);
2667 on = ansi_highlight_red();
2668 off = ansi_highlight_off();
2672 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
2674 if (p->code == CLD_EXITED) {
2677 printf("status=%i", p->status);
2679 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
2684 printf("signal=%s", signal_to_string(p->status));
2686 printf(")%s\n", off);
2688 if (i->main_pid == p->pid &&
2689 i->start_timestamp == p->start_timestamp &&
2690 i->exit_timestamp == p->start_timestamp)
2691 /* Let's not show this twice */
2694 if (p->pid == i->control_pid)
2698 if (i->main_pid > 0 || i->control_pid > 0) {
2699 if (i->main_pid > 0) {
2700 printf(" Main PID: %u", (unsigned) i->main_pid);
2703 _cleanup_free_ char *comm = NULL;
2704 get_process_comm(i->main_pid, &comm);
2706 printf(" (%s)", comm);
2707 } else if (i->exit_code > 0) {
2708 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
2710 if (i->exit_code == CLD_EXITED) {
2713 printf("status=%i", i->exit_status);
2715 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
2720 printf("signal=%s", signal_to_string(i->exit_status));
2724 if (i->control_pid > 0)
2728 if (i->control_pid > 0) {
2729 _cleanup_free_ char *c = NULL;
2731 printf(" %8s: %u", i->main_pid ? "" : " Control", (unsigned) i->control_pid);
2733 get_process_comm(i->control_pid, &c);
2742 printf(" Status: \"%s\"\n", i->status_text);
2744 if (i->control_group &&
2745 (i->main_pid > 0 || i->control_pid > 0 || cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, i->control_group, false) == 0)) {
2748 printf(" CGroup: %s\n", i->control_group);
2750 if (arg_transport != TRANSPORT_SSH) {
2753 char prefix[] = " ";
2756 if (c > sizeof(prefix) - 1)
2757 c -= sizeof(prefix) - 1;
2761 if (i->main_pid > 0)
2762 extra[k++] = i->main_pid;
2764 if (i->control_pid > 0)
2765 extra[k++] = i->control_pid;
2767 show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, i->control_group, prefix,
2768 c, false, extra, k, flags);
2772 if (i->id && arg_transport != TRANSPORT_SSH) {
2774 show_journal_by_unit(stdout,
2778 i->inactive_exit_timestamp_monotonic,
2782 arg_scope == UNIT_FILE_SYSTEM);
2785 if (i->need_daemon_reload)
2786 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %sdaemon-reload' recommended.\n",
2787 ansi_highlight_red(),
2788 ansi_highlight_off(),
2789 arg_scope == UNIT_FILE_SYSTEM ? "" : "--user ");
2792 static void show_unit_help(UnitStatusInfo *i) {
2797 if (!i->documentation) {
2798 log_info("Documentation for %s not known.", i->id);
2802 STRV_FOREACH(p, i->documentation) {
2804 if (startswith(*p, "man:")) {
2807 _cleanup_free_ char *page = NULL, *section = NULL;
2808 const char *args[4] = { "man", NULL, NULL, NULL };
2813 if ((*p)[k-1] == ')')
2814 e = strrchr(*p, '(');
2817 page = strndup((*p) + 4, e - *p - 4);
2818 section = strndup(e + 1, *p + k - e - 2);
2819 if (!page || !section) {
2831 log_error("Failed to fork: %m");
2837 execvp(args[0], (char**) args);
2838 log_error("Failed to execute man: %m");
2839 _exit(EXIT_FAILURE);
2842 wait_for_terminate(pid, NULL);
2844 log_info("Can't show: %s", *p);
2848 static int status_property(const char *name, DBusMessageIter *iter, UnitStatusInfo *i) {
2854 switch (dbus_message_iter_get_arg_type(iter)) {
2856 case DBUS_TYPE_STRING: {
2859 dbus_message_iter_get_basic(iter, &s);
2862 if (streq(name, "Id"))
2864 else if (streq(name, "LoadState"))
2866 else if (streq(name, "ActiveState"))
2867 i->active_state = s;
2868 else if (streq(name, "SubState"))
2870 else if (streq(name, "Description"))
2872 else if (streq(name, "FragmentPath"))
2873 i->fragment_path = s;
2874 else if (streq(name, "SourcePath"))
2877 else if (streq(name, "DefaultControlGroup")) {
2879 e = startswith(s, SYSTEMD_CGROUP_CONTROLLER ":");
2881 i->control_group = e;
2884 else if (streq(name, "ControlGroup"))
2885 i->control_group = s;
2886 else if (streq(name, "StatusText"))
2888 else if (streq(name, "PIDFile"))
2890 else if (streq(name, "SysFSPath"))
2892 else if (streq(name, "Where"))
2894 else if (streq(name, "What"))
2896 else if (streq(name, "Following"))
2898 else if (streq(name, "UnitFileState"))
2899 i->unit_file_state = s;
2900 else if (streq(name, "Result"))
2907 case DBUS_TYPE_BOOLEAN: {
2910 dbus_message_iter_get_basic(iter, &b);
2912 if (streq(name, "Accept"))
2914 else if (streq(name, "NeedDaemonReload"))
2915 i->need_daemon_reload = b;
2916 else if (streq(name, "ConditionResult"))
2917 i->condition_result = b;
2922 case DBUS_TYPE_UINT32: {
2925 dbus_message_iter_get_basic(iter, &u);
2927 if (streq(name, "MainPID")) {
2929 i->main_pid = (pid_t) u;
2932 } else if (streq(name, "ControlPID"))
2933 i->control_pid = (pid_t) u;
2934 else if (streq(name, "ExecMainPID")) {
2936 i->main_pid = (pid_t) u;
2937 } else if (streq(name, "NAccepted"))
2939 else if (streq(name, "NConnections"))
2940 i->n_connections = u;
2945 case DBUS_TYPE_INT32: {
2948 dbus_message_iter_get_basic(iter, &j);
2950 if (streq(name, "ExecMainCode"))
2951 i->exit_code = (int) j;
2952 else if (streq(name, "ExecMainStatus"))
2953 i->exit_status = (int) j;
2958 case DBUS_TYPE_UINT64: {
2961 dbus_message_iter_get_basic(iter, &u);
2963 if (streq(name, "ExecMainStartTimestamp"))
2964 i->start_timestamp = (usec_t) u;
2965 else if (streq(name, "ExecMainExitTimestamp"))
2966 i->exit_timestamp = (usec_t) u;
2967 else if (streq(name, "ActiveEnterTimestamp"))
2968 i->active_enter_timestamp = (usec_t) u;
2969 else if (streq(name, "InactiveEnterTimestamp"))
2970 i->inactive_enter_timestamp = (usec_t) u;
2971 else if (streq(name, "InactiveExitTimestamp"))
2972 i->inactive_exit_timestamp = (usec_t) u;
2973 else if (streq(name, "InactiveExitTimestampMonotonic"))
2974 i->inactive_exit_timestamp_monotonic = (usec_t) u;
2975 else if (streq(name, "ActiveExitTimestamp"))
2976 i->active_exit_timestamp = (usec_t) u;
2977 else if (streq(name, "ConditionTimestamp"))
2978 i->condition_timestamp = (usec_t) u;
2983 case DBUS_TYPE_ARRAY: {
2985 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
2986 startswith(name, "Exec")) {
2987 DBusMessageIter sub;
2989 dbus_message_iter_recurse(iter, &sub);
2990 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2991 ExecStatusInfo *info;
2994 info = new0(ExecStatusInfo, 1);
2998 info->name = strdup(name);
3004 r = exec_status_info_deserialize(&sub, info);
3010 LIST_PREPEND(ExecStatusInfo, exec, i->exec, info);
3012 dbus_message_iter_next(&sub);
3015 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
3016 streq(name, "Listen")) {
3017 DBusMessageIter sub, sub2;
3019 dbus_message_iter_recurse(iter, &sub);
3020 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3021 const char *type, *path;
3023 dbus_message_iter_recurse(&sub, &sub2);
3025 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
3026 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0) {
3029 r = strv_extend(&i->listen, type);
3032 r = strv_extend(&i->listen, path);
3037 dbus_message_iter_next(&sub);
3042 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
3043 streq(name, "DropInPaths")) {
3044 int r = bus_parse_strv_iter(iter, &i->dropin_paths);
3048 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
3049 streq(name, "Documentation")) {
3051 DBusMessageIter sub;
3053 dbus_message_iter_recurse(iter, &sub);
3054 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING) {
3058 dbus_message_iter_get_basic(&sub, &s);
3060 r = strv_extend(&i->documentation, s);
3064 dbus_message_iter_next(&sub);
3067 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
3068 streq(name, "Conditions")) {
3069 DBusMessageIter sub, sub2;
3071 dbus_message_iter_recurse(iter, &sub);
3072 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3073 const char *cond, *param;
3074 dbus_bool_t trigger, negate;
3077 dbus_message_iter_recurse(&sub, &sub2);
3080 if(bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &cond, true) >= 0 &&
3081 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &trigger, true) >= 0 &&
3082 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &negate, true) >= 0 &&
3083 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, ¶m, true) >= 0 &&
3084 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &state, false) >= 0) {
3085 log_debug("%s %d %d %s %d", cond, trigger, negate, param, state);
3086 if (state < 0 && (!trigger || !i->failed_condition)) {
3087 i->failed_condition = cond;
3088 i->failed_condition_trigger = trigger;
3089 i->failed_condition_negate = negate;
3090 i->failed_condition_param = param;
3094 dbus_message_iter_next(&sub);
3101 case DBUS_TYPE_STRUCT: {
3103 if (streq(name, "LoadError")) {
3104 DBusMessageIter sub;
3105 const char *n, *message;
3108 dbus_message_iter_recurse(iter, &sub);
3110 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &n, true);
3114 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &message, false);
3118 if (!isempty(message))
3119 i->load_error = message;
3129 static int print_property(const char *name, DBusMessageIter *iter) {
3133 /* This is a low-level property printer, see
3134 * print_status_info() for the nicer output */
3136 if (arg_properties && !strv_find(arg_properties, name))
3139 switch (dbus_message_iter_get_arg_type(iter)) {
3141 case DBUS_TYPE_STRUCT: {
3142 DBusMessageIter sub;
3143 dbus_message_iter_recurse(iter, &sub);
3145 if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32 && streq(name, "Job")) {
3148 dbus_message_iter_get_basic(&sub, &u);
3151 printf("%s=%u\n", name, (unsigned) u);
3153 printf("%s=\n", name);
3156 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "Unit")) {
3159 dbus_message_iter_get_basic(&sub, &s);
3161 if (arg_all || s[0])
3162 printf("%s=%s\n", name, s);
3165 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "LoadError")) {
3166 const char *a = NULL, *b = NULL;
3168 if (bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &a, true) >= 0)
3169 bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &b, false);
3171 if (arg_all || !isempty(a) || !isempty(b))
3172 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
3180 case DBUS_TYPE_ARRAY:
3182 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "EnvironmentFiles")) {
3183 DBusMessageIter sub, sub2;
3185 dbus_message_iter_recurse(iter, &sub);
3186 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3190 dbus_message_iter_recurse(&sub, &sub2);
3192 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
3193 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) >= 0)
3194 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
3196 dbus_message_iter_next(&sub);
3201 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Paths")) {
3202 DBusMessageIter sub, sub2;
3204 dbus_message_iter_recurse(iter, &sub);
3206 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3207 const char *type, *path;
3209 dbus_message_iter_recurse(&sub, &sub2);
3211 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
3212 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
3213 printf("%s=%s\n", type, path);
3215 dbus_message_iter_next(&sub);
3220 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Listen")) {
3221 DBusMessageIter sub, sub2;
3223 dbus_message_iter_recurse(iter, &sub);
3224 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3225 const char *type, *path;
3227 dbus_message_iter_recurse(&sub, &sub2);
3229 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
3230 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
3231 printf("Listen%s=%s\n", type, path);
3233 dbus_message_iter_next(&sub);
3238 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Timers")) {
3239 DBusMessageIter sub, sub2;
3241 dbus_message_iter_recurse(iter, &sub);
3242 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3244 uint64_t value, next_elapse;
3246 dbus_message_iter_recurse(&sub, &sub2);
3248 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &base, true) >= 0 &&
3249 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &value, true) >= 0 &&
3250 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &next_elapse, false) >= 0) {
3251 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
3253 printf("%s={ value=%s ; next_elapse=%s }\n",
3255 format_timespan(timespan1, sizeof(timespan1), value, 0),
3256 format_timespan(timespan2, sizeof(timespan2), next_elapse, 0));
3259 dbus_message_iter_next(&sub);
3264 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && startswith(name, "Exec")) {
3265 DBusMessageIter sub;
3267 dbus_message_iter_recurse(iter, &sub);
3268 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3269 ExecStatusInfo info = {};
3271 if (exec_status_info_deserialize(&sub, &info) >= 0) {
3272 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
3273 _cleanup_free_ char *t;
3275 t = strv_join(info.argv, " ");
3277 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
3281 yes_no(info.ignore),
3282 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
3283 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
3284 (unsigned) info. pid,
3285 sigchld_code_to_string(info.code),
3287 info.code == CLD_EXITED ? "" : "/",
3288 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
3292 strv_free(info.argv);
3294 dbus_message_iter_next(&sub);
3299 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "DeviceAllow")) {
3300 DBusMessageIter sub, sub2;
3302 dbus_message_iter_recurse(iter, &sub);
3303 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3304 const char *path, *rwm;
3306 dbus_message_iter_recurse(&sub, &sub2);
3308 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
3309 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &rwm, false) >= 0)
3310 printf("%s=%s %s\n", name, strna(path), strna(rwm));
3312 dbus_message_iter_next(&sub);
3316 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && (streq(name, "BlockIOReadBandwidth") || streq(name, "BlockIOWriteBandwidth"))) {
3317 DBusMessageIter sub, sub2;
3319 dbus_message_iter_recurse(iter, &sub);
3320 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3324 dbus_message_iter_recurse(&sub, &sub2);
3326 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
3327 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &bandwidth, false) >= 0)
3328 printf("%s=%s %" PRIu64 "\n", name, strna(path), bandwidth);
3330 dbus_message_iter_next(&sub);
3339 if (generic_print_property(name, iter, arg_all) > 0)
3343 printf("%s=[unprintable]\n", name);
3348 static int show_one(const char *verb, DBusConnection *bus, const char *path, bool show_properties, bool *new_line) {
3349 _cleanup_free_ DBusMessage *reply = NULL;
3350 const char *interface = "";
3352 DBusMessageIter iter, sub, sub2, sub3;
3353 UnitStatusInfo info = {};
3359 r = bus_method_call_with_reply(
3361 "org.freedesktop.systemd1",
3363 "org.freedesktop.DBus.Properties",
3367 DBUS_TYPE_STRING, &interface,
3372 if (!dbus_message_iter_init(reply, &iter) ||
3373 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3374 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
3375 log_error("Failed to parse reply.");
3379 dbus_message_iter_recurse(&iter, &sub);
3386 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
3389 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_DICT_ENTRY);
3390 dbus_message_iter_recurse(&sub, &sub2);
3392 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
3393 dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
3394 log_error("Failed to parse reply.");
3398 dbus_message_iter_recurse(&sub2, &sub3);
3400 if (show_properties)
3401 r = print_property(name, &sub3);
3403 r = status_property(name, &sub3, &info);
3405 log_error("Failed to parse reply.");
3409 dbus_message_iter_next(&sub);
3414 if (!show_properties) {
3415 if (streq(verb, "help"))
3416 show_unit_help(&info);
3418 print_status_info(&info);
3421 strv_free(info.documentation);
3422 strv_free(info.dropin_paths);
3423 strv_free(info.listen);
3425 if (!streq_ptr(info.active_state, "active") &&
3426 !streq_ptr(info.active_state, "reloading") &&
3427 streq(verb, "status")) {
3428 /* According to LSB: "program not running" */
3429 /* 0: program is running or service is OK
3430 * 1: program is dead and /var/run pid file exists
3431 * 2: program is dead and /var/lock lock file exists
3432 * 3: program is not running
3433 * 4: program or service status is unknown
3435 if (info.pid_file && access(info.pid_file, F_OK) == 0)
3441 while ((p = info.exec)) {
3442 LIST_REMOVE(ExecStatusInfo, exec, info.exec, p);
3443 exec_status_info_free(p);
3449 static int show_one_by_pid(const char *verb, DBusConnection *bus, uint32_t pid, bool *new_line) {
3450 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3451 const char *path = NULL;
3452 _cleanup_dbus_error_free_ DBusError error;
3455 dbus_error_init(&error);
3457 r = bus_method_call_with_reply(
3459 "org.freedesktop.systemd1",
3460 "/org/freedesktop/systemd1",
3461 "org.freedesktop.systemd1.Manager",
3465 DBUS_TYPE_UINT32, &pid,
3470 if (!dbus_message_get_args(reply, &error,
3471 DBUS_TYPE_OBJECT_PATH, &path,
3472 DBUS_TYPE_INVALID)) {
3473 log_error("Failed to parse reply: %s", bus_error_message(&error));
3477 r = show_one(verb, bus, path, false, new_line);
3481 static int show_all(const char* verb, DBusConnection *bus, bool show_properties, bool *new_line) {
3482 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3483 _cleanup_free_ struct unit_info *unit_infos = NULL;
3485 const struct unit_info *u;
3488 r = get_unit_list(bus, &reply, &unit_infos, &c);
3492 qsort(unit_infos, c, sizeof(struct unit_info), compare_unit_info);
3494 for (u = unit_infos; u < unit_infos + c; u++) {
3495 _cleanup_free_ char *p = NULL;
3497 if (!output_show_unit(u))
3500 p = unit_dbus_path_from_name(u->id);
3504 printf("%s -> '%s'\n", u->id, p);
3506 r = show_one(verb, bus, p, show_properties, new_line);
3514 static int show(DBusConnection *bus, char **args) {
3516 bool show_properties, show_status, new_line = false;
3522 show_properties = streq(args[0], "show");
3523 show_status = streq(args[0], "status");
3525 if (show_properties)
3526 pager_open_if_enabled();
3528 /* If no argument is specified inspect the manager itself */
3530 if (show_properties && strv_length(args) <= 1)
3531 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line);
3533 if (show_status && strv_length(args) <= 1)
3534 return show_all(args[0], bus, false, &new_line);
3536 STRV_FOREACH(name, args+1) {
3539 if (safe_atou32(*name, &id) < 0) {
3540 _cleanup_free_ char *p = NULL, *n = NULL;
3541 /* Interpret as unit name */
3543 n = unit_name_mangle(*name);
3547 p = unit_dbus_path_from_name(n);
3551 r = show_one(args[0], bus, p, show_properties, &new_line);
3555 } else if (show_properties) {
3556 _cleanup_free_ char *p = NULL;
3558 /* Interpret as job id */
3559 if (asprintf(&p, "/org/freedesktop/systemd1/job/%u", id) < 0)
3562 r = show_one(args[0], bus, p, show_properties, &new_line);
3567 /* Interpret as PID */
3568 r = show_one_by_pid(args[0], bus, id, &new_line);
3577 static int append_assignment(DBusMessageIter *iter, const char *assignment) {
3580 DBusMessageIter sub;
3586 eq = strchr(assignment, '=');
3588 log_error("Not an assignment: %s", assignment);
3592 field = strndupa(assignment, eq - assignment);
3595 if (!dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &field))
3598 if (streq(field, "CPUAccounting") ||
3599 streq(field, "MemoryAccounting") ||
3600 streq(field, "BlockIOAccounting")) {
3603 r = parse_boolean(eq);
3605 log_error("Failed to parse boolean assignment %s.", assignment);
3610 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "b", &sub) ||
3611 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_BOOLEAN, &b))
3614 } else if (streq(field, "MemoryLimit") || streq(field, "MemorySoftLimit")) {
3618 r = parse_bytes(eq, &bytes);
3620 log_error("Failed to parse bytes specification %s", assignment);
3625 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "t", &sub) ||
3626 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_UINT64, &u))
3629 } else if (streq(field, "CPUShares") || streq(field, "BlockIOWeight")) {
3632 r = safe_atou64(eq, &u);
3634 log_error("Failed to parse %s value %s.", field, eq);
3638 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "t", &sub) ||
3639 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_UINT64, &u))
3642 } else if (streq(field, "DevicePolicy")) {
3644 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "s", &sub) ||
3645 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &eq))
3648 } else if (streq(field, "DeviceAllow")) {
3649 DBusMessageIter sub2;
3651 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "a(ss)", &sub) ||
3652 !dbus_message_iter_open_container(&sub, DBUS_TYPE_ARRAY, "(ss)", &sub2))
3656 const char *path, *rwm;
3657 DBusMessageIter sub3;
3660 e = strchr(eq, ' ');
3662 path = strndupa(eq, e - eq);
3669 if (!dbus_message_iter_open_container(&sub2, DBUS_TYPE_STRUCT, NULL, &sub3) ||
3670 !dbus_message_iter_append_basic(&sub3, DBUS_TYPE_STRING, &path) ||
3671 !dbus_message_iter_append_basic(&sub3, DBUS_TYPE_STRING, &rwm) ||
3672 !dbus_message_iter_close_container(&sub2, &sub3))
3676 if (!dbus_message_iter_close_container(&sub, &sub2))
3680 log_error("Unknown assignment %s.", assignment);
3684 if (!dbus_message_iter_close_container(iter, &sub))
3690 static int set_property(DBusConnection *bus, char **args) {
3692 _cleanup_free_ DBusMessage *m = NULL, *reply = NULL;
3693 DBusMessageIter iter, sub;
3694 dbus_bool_t runtime;
3699 dbus_error_init(&error);
3701 m = dbus_message_new_method_call(
3702 "org.freedesktop.systemd1",
3703 "/org/freedesktop/systemd1",
3704 "org.freedesktop.systemd1.Manager",
3705 "SetUnitProperties");
3709 dbus_message_iter_init_append(m, &iter);
3711 runtime = arg_runtime;
3713 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &args[1]) ||
3714 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &runtime) ||
3715 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(sv)", &sub))
3718 STRV_FOREACH(i, args + 2) {
3719 DBusMessageIter sub2;
3721 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
3724 r = append_assignment(&sub2, *i);
3728 if (!dbus_message_iter_close_container(&sub, &sub2))
3733 if (!dbus_message_iter_close_container(&iter, &sub))
3736 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3738 log_error("Failed to issue method call: %s", bus_error_message(&error));
3739 dbus_error_free(&error);
3746 static int snapshot(DBusConnection *bus, char **args) {
3747 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3750 dbus_bool_t cleanup = FALSE;
3751 DBusMessageIter iter, sub;
3754 *interface = "org.freedesktop.systemd1.Unit",
3756 _cleanup_free_ char *n = NULL;
3758 dbus_error_init(&error);
3760 if (strv_length(args) > 1)
3761 n = unit_name_mangle_with_suffix(args[1], ".snapshot");
3767 r = bus_method_call_with_reply(
3769 "org.freedesktop.systemd1",
3770 "/org/freedesktop/systemd1",
3771 "org.freedesktop.systemd1.Manager",
3775 DBUS_TYPE_STRING, &n,
3776 DBUS_TYPE_BOOLEAN, &cleanup,
3781 if (!dbus_message_get_args(reply, &error,
3782 DBUS_TYPE_OBJECT_PATH, &path,
3783 DBUS_TYPE_INVALID)) {
3784 log_error("Failed to parse reply: %s", bus_error_message(&error));
3785 dbus_error_free(&error);
3789 dbus_message_unref(reply);
3792 r = bus_method_call_with_reply (
3794 "org.freedesktop.systemd1",
3796 "org.freedesktop.DBus.Properties",
3800 DBUS_TYPE_STRING, &interface,
3801 DBUS_TYPE_STRING, &property,
3806 if (!dbus_message_iter_init(reply, &iter) ||
3807 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3808 log_error("Failed to parse reply.");
3812 dbus_message_iter_recurse(&iter, &sub);
3814 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
3815 log_error("Failed to parse reply.");
3819 dbus_message_iter_get_basic(&sub, &id);
3827 static int delete_snapshot(DBusConnection *bus, char **args) {
3832 STRV_FOREACH(name, args+1) {
3833 _cleanup_free_ char *n = NULL;
3836 n = unit_name_mangle_with_suffix(*name, ".snapshot");
3840 r = bus_method_call_with_reply(
3842 "org.freedesktop.systemd1",
3843 "/org/freedesktop/systemd1",
3844 "org.freedesktop.systemd1.Manager",
3848 DBUS_TYPE_STRING, &n,
3857 static int daemon_reload(DBusConnection *bus, char **args) {
3862 if (arg_action == ACTION_RELOAD)
3864 else if (arg_action == ACTION_REEXEC)
3865 method = "Reexecute";
3867 assert(arg_action == ACTION_SYSTEMCTL);
3870 streq(args[0], "clear-jobs") ||
3871 streq(args[0], "cancel") ? "ClearJobs" :
3872 streq(args[0], "daemon-reexec") ? "Reexecute" :
3873 streq(args[0], "reset-failed") ? "ResetFailed" :
3874 streq(args[0], "halt") ? "Halt" :
3875 streq(args[0], "poweroff") ? "PowerOff" :
3876 streq(args[0], "reboot") ? "Reboot" :
3877 streq(args[0], "kexec") ? "KExec" :
3878 streq(args[0], "exit") ? "Exit" :
3879 /* "daemon-reload" */ "Reload";
3882 r = bus_method_call_with_reply(
3884 "org.freedesktop.systemd1",
3885 "/org/freedesktop/systemd1",
3886 "org.freedesktop.systemd1.Manager",
3892 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
3893 /* There's always a fallback possible for
3894 * legacy actions. */
3896 else if ((r == -ETIMEDOUT || r == -ECONNRESET) && streq(method, "Reexecute"))
3897 /* On reexecution, we expect a disconnect, not a
3901 log_error("Failed to issue method call: %s", bus_error_message(&error));
3903 dbus_error_free(&error);
3907 static int reset_failed(DBusConnection *bus, char **args) {
3911 if (strv_length(args) <= 1)
3912 return daemon_reload(bus, args);
3914 STRV_FOREACH(name, args+1) {
3915 _cleanup_free_ char *n;
3917 n = unit_name_mangle(*name);
3921 r = bus_method_call_with_reply(
3923 "org.freedesktop.systemd1",
3924 "/org/freedesktop/systemd1",
3925 "org.freedesktop.systemd1.Manager",
3929 DBUS_TYPE_STRING, &n,
3938 static int show_enviroment(DBusConnection *bus, char **args) {
3939 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3940 DBusMessageIter iter, sub, sub2;
3943 *interface = "org.freedesktop.systemd1.Manager",
3944 *property = "Environment";
3946 pager_open_if_enabled();
3948 r = bus_method_call_with_reply(
3950 "org.freedesktop.systemd1",
3951 "/org/freedesktop/systemd1",
3952 "org.freedesktop.DBus.Properties",
3956 DBUS_TYPE_STRING, &interface,
3957 DBUS_TYPE_STRING, &property,
3962 if (!dbus_message_iter_init(reply, &iter) ||
3963 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3964 log_error("Failed to parse reply.");
3968 dbus_message_iter_recurse(&iter, &sub);
3970 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_ARRAY ||
3971 dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_STRING) {
3972 log_error("Failed to parse reply.");
3976 dbus_message_iter_recurse(&sub, &sub2);
3978 while (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_INVALID) {
3981 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
3982 log_error("Failed to parse reply.");
3986 dbus_message_iter_get_basic(&sub2, &text);
3989 dbus_message_iter_next(&sub2);
3995 static int switch_root(DBusConnection *bus, char **args) {
3998 _cleanup_free_ char *init = NULL;
4000 l = strv_length(args);
4001 if (l < 2 || l > 3) {
4002 log_error("Wrong number of arguments.");
4009 init = strdup(args[2]);
4011 parse_env_file("/proc/cmdline", WHITESPACE,
4021 log_debug("switching root - root: %s; init: %s", root, init);
4023 return bus_method_call_with_reply(
4025 "org.freedesktop.systemd1",
4026 "/org/freedesktop/systemd1",
4027 "org.freedesktop.systemd1.Manager",
4031 DBUS_TYPE_STRING, &root,
4032 DBUS_TYPE_STRING, &init,
4036 static int set_environment(DBusConnection *bus, char **args) {
4037 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
4040 DBusMessageIter iter;
4046 dbus_error_init(&error);
4048 method = streq(args[0], "set-environment")
4050 : "UnsetEnvironment";
4052 m = dbus_message_new_method_call(
4053 "org.freedesktop.systemd1",
4054 "/org/freedesktop/systemd1",
4055 "org.freedesktop.systemd1.Manager",
4060 dbus_message_iter_init_append(m, &iter);
4062 r = bus_append_strv_iter(&iter, args + 1);
4066 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
4068 log_error("Failed to issue method call: %s", bus_error_message(&error));
4069 dbus_error_free(&error);
4076 static int enable_sysv_units(char **args) {
4079 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
4080 const char *verb = args[0];
4081 unsigned f = 1, t = 1;
4082 LookupPaths paths = {};
4084 if (arg_scope != UNIT_FILE_SYSTEM)
4087 if (!streq(verb, "enable") &&
4088 !streq(verb, "disable") &&
4089 !streq(verb, "is-enabled"))
4092 /* Processes all SysV units, and reshuffles the array so that
4093 * afterwards only the native units remain */
4095 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, NULL, NULL, NULL);
4100 for (f = 1; args[f]; f++) {
4102 _cleanup_free_ char *p = NULL, *q = NULL;
4103 bool found_native = false, found_sysv;
4105 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
4113 if (!endswith(name, ".service"))
4116 if (path_is_absolute(name))
4119 STRV_FOREACH(k, paths.unit_path) {
4120 if (!isempty(arg_root))
4121 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
4123 asprintf(&p, "%s/%s", *k, name);
4130 found_native = access(p, F_OK) >= 0;
4141 if (!isempty(arg_root))
4142 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
4144 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
4150 p[strlen(p) - sizeof(".service") + 1] = 0;
4151 found_sysv = access(p, F_OK) >= 0;
4156 /* Mark this entry, so that we don't try enabling it as native unit */
4157 args[f] = (char*) "";
4159 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
4161 if (!isempty(arg_root))
4162 argv[c++] = q = strappend("--root=", arg_root);
4164 argv[c++] = path_get_file_name(p);
4166 streq(verb, "enable") ? "on" :
4167 streq(verb, "disable") ? "off" : "--level=5";
4170 l = strv_join((char**)argv, " ");
4176 log_info("Executing %s", l);
4181 log_error("Failed to fork: %m");
4184 } else if (pid == 0) {
4187 execv(argv[0], (char**) argv);
4188 _exit(EXIT_FAILURE);
4191 j = wait_for_terminate(pid, &status);
4193 log_error("Failed to wait for child: %s", strerror(-r));
4198 if (status.si_code == CLD_EXITED) {
4199 if (streq(verb, "is-enabled")) {
4200 if (status.si_status == 0) {
4209 } else if (status.si_status != 0) {
4220 lookup_paths_free(&paths);
4222 /* Drop all SysV units */
4223 for (f = 1, t = 1; args[f]; f++) {
4225 if (isempty(args[f]))
4228 args[t++] = args[f];
4237 static int mangle_names(char **original_names, char ***mangled_names) {
4238 char **i, **l, **name;
4240 l = new(char*, strv_length(original_names) + 1);
4245 STRV_FOREACH(name, original_names) {
4247 /* When enabling units qualified path names are OK,
4248 * too, hence allow them explicitly. */
4253 *i = unit_name_mangle(*name);
4269 static int enable_unit(DBusConnection *bus, char **args) {
4270 const char *verb = args[0];
4271 UnitFileChange *changes = NULL;
4272 unsigned n_changes = 0, i;
4273 int carries_install_info = -1;
4274 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
4276 _cleanup_dbus_error_free_ DBusError error;
4277 _cleanup_strv_free_ char **mangled_names = NULL;
4279 dbus_error_init(&error);
4281 r = enable_sysv_units(args);
4288 r = mangle_names(args+1, &mangled_names);
4292 if (!bus || avoid_bus()) {
4293 if (streq(verb, "enable")) {
4294 r = unit_file_enable(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4295 carries_install_info = r;
4296 } else if (streq(verb, "disable"))
4297 r = unit_file_disable(arg_scope, arg_runtime, arg_root, mangled_names, &changes, &n_changes);
4298 else if (streq(verb, "reenable")) {
4299 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4300 carries_install_info = r;
4301 } else if (streq(verb, "link"))
4302 r = unit_file_link(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4303 else if (streq(verb, "preset")) {
4304 r = unit_file_preset(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4305 carries_install_info = r;
4306 } else if (streq(verb, "mask"))
4307 r = unit_file_mask(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4308 else if (streq(verb, "unmask"))
4309 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, mangled_names, &changes, &n_changes);
4310 else if (streq(verb, "set-default"))
4311 r = unit_file_set_default(arg_scope, arg_root, args[1], &changes, &n_changes);
4313 assert_not_reached("Unknown verb");
4316 log_error("Operation failed: %s", strerror(-r));
4321 for (i = 0; i < n_changes; i++) {
4322 if (changes[i].type == UNIT_FILE_SYMLINK)
4323 log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
4325 log_info("rm '%s'", changes[i].path);
4332 bool send_force = true, expect_carries_install_info = false;
4334 DBusMessageIter iter, sub, sub2;
4336 if (streq(verb, "enable")) {
4337 method = "EnableUnitFiles";
4338 expect_carries_install_info = true;
4339 } else if (streq(verb, "disable")) {
4340 method = "DisableUnitFiles";
4342 } else if (streq(verb, "reenable")) {
4343 method = "ReenableUnitFiles";
4344 expect_carries_install_info = true;
4345 } else if (streq(verb, "link"))
4346 method = "LinkUnitFiles";
4347 else if (streq(verb, "preset")) {
4348 method = "PresetUnitFiles";
4349 expect_carries_install_info = true;
4350 } else if (streq(verb, "mask"))
4351 method = "MaskUnitFiles";
4352 else if (streq(verb, "unmask")) {
4353 method = "UnmaskUnitFiles";
4355 } else if (streq(verb, "set-default")) {
4356 method = "SetDefaultTarget";
4358 assert_not_reached("Unknown verb");
4360 m = dbus_message_new_method_call(
4361 "org.freedesktop.systemd1",
4362 "/org/freedesktop/systemd1",
4363 "org.freedesktop.systemd1.Manager",
4370 dbus_message_iter_init_append(m, &iter);
4372 r = bus_append_strv_iter(&iter, mangled_names);
4374 log_error("Failed to append unit files.");
4379 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &a)) {
4380 log_error("Failed to append runtime boolean.");
4388 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b)) {
4389 log_error("Failed to append force boolean.");
4395 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
4397 log_error("Failed to issue method call: %s", bus_error_message(&error));
4402 if (!dbus_message_iter_init(reply, &iter)) {
4403 log_error("Failed to initialize iterator.");
4407 if (expect_carries_install_info) {
4408 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &b, true);
4410 log_error("Failed to parse reply.");
4414 carries_install_info = b;
4417 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
4418 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
4419 log_error("Failed to parse reply.");
4424 dbus_message_iter_recurse(&iter, &sub);
4425 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
4426 const char *type, *path, *source;
4428 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
4429 log_error("Failed to parse reply.");
4434 dbus_message_iter_recurse(&sub, &sub2);
4436 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
4437 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
4438 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &source, false) < 0) {
4439 log_error("Failed to parse reply.");
4445 if (streq(type, "symlink"))
4446 log_info("ln -s '%s' '%s'", source, path);
4448 log_info("rm '%s'", path);
4451 dbus_message_iter_next(&sub);
4454 /* Try to reload if enabeld */
4456 r = daemon_reload(bus, args);
4459 if (carries_install_info == 0)
4460 log_warning("The unit files have no [Install] section. They are not meant to be enabled\n"
4461 "using systemctl.\n"
4462 "Possible reasons for having this kind of units are:\n"
4463 "1) A unit may be statically enabled by being symlinked from another unit's\n"
4464 " .wants/ or .requires/ directory.\n"
4465 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
4466 " a requirement dependency on it.\n"
4467 "3) A unit may be started when needed via activation (socket, path, timer,\n"
4468 " D-Bus, udev, scripted systemctl call, ...).\n");
4471 unit_file_changes_free(changes, n_changes);
4476 static int unit_is_enabled(DBusConnection *bus, char **args) {
4477 _cleanup_dbus_error_free_ DBusError error;
4479 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
4484 dbus_error_init(&error);
4486 r = enable_sysv_units(args);
4492 if (!bus || avoid_bus()) {
4494 STRV_FOREACH(name, args+1) {
4495 UnitFileState state;
4497 n = unit_name_mangle(*name);
4501 state = unit_file_get_state(arg_scope, arg_root, n);
4508 if (state == UNIT_FILE_ENABLED ||
4509 state == UNIT_FILE_ENABLED_RUNTIME ||
4510 state == UNIT_FILE_STATIC)
4514 puts(unit_file_state_to_string(state));
4518 STRV_FOREACH(name, args+1) {
4521 n = unit_name_mangle(*name);
4525 r = bus_method_call_with_reply (
4527 "org.freedesktop.systemd1",
4528 "/org/freedesktop/systemd1",
4529 "org.freedesktop.systemd1.Manager",
4533 DBUS_TYPE_STRING, &n,
4541 if (!dbus_message_get_args(reply, &error,
4542 DBUS_TYPE_STRING, &s,
4543 DBUS_TYPE_INVALID)) {
4544 log_error("Failed to parse reply: %s", bus_error_message(&error));
4548 dbus_message_unref(reply);
4551 if (streq(s, "enabled") ||
4552 streq(s, "enabled-runtime") ||
4561 return enabled ? 0 : 1;
4564 static int systemctl_help(void) {
4566 pager_open_if_enabled();
4568 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
4569 "Query or send control commands to the systemd manager.\n\n"
4570 " -h --help Show this help\n"
4571 " --version Show package version\n"
4572 " -t --type=TYPE List only units of a particular type\n"
4573 " --state=STATE List only units with particular LOAD or SUB or ACTIVE state\n"
4574 " -p --property=NAME Show only properties by this name\n"
4575 " -a --all Show all loaded units/properties, including dead/empty\n"
4576 " ones. To list all units installed on the system, use\n"
4577 " the 'list-unit-files' command instead.\n"
4578 " --reverse Show reverse dependencies with 'list-dependencies'\n"
4579 " -l --full Don't ellipsize unit names on output\n"
4580 " --fail When queueing a new job, fail if conflicting jobs are\n"
4582 " --irreversible When queueing a new job, make sure it cannot be implicitly\n"
4584 " --ignore-dependencies\n"
4585 " When queueing a new job, ignore all its dependencies\n"
4586 " --show-types When showing sockets, explicitly show their type\n"
4587 " -i --ignore-inhibitors\n"
4588 " When shutting down or sleeping, ignore inhibitors\n"
4589 " --kill-who=WHO Who to send signal to\n"
4590 " -s --signal=SIGNAL Which signal to send\n"
4591 " -H --host=[USER@]HOST\n"
4592 " Show information for remote host\n"
4593 " -P --privileged Acquire privileges before execution\n"
4594 " -q --quiet Suppress output\n"
4595 " --no-block Do not wait until operation finished\n"
4596 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4597 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
4599 " --no-legend Do not print a legend (column headers and hints)\n"
4600 " --no-pager Do not pipe output into a pager\n"
4601 " --no-ask-password\n"
4602 " Do not ask for system passwords\n"
4603 " --system Connect to system manager\n"
4604 " --user Connect to user service manager\n"
4605 " --global Enable/disable unit files globally\n"
4606 " --runtime Enable unit files only temporarily until next reboot\n"
4607 " -f --force When enabling unit files, override existing symlinks\n"
4608 " When shutting down, execute action immediately\n"
4609 " --root=PATH Enable unit files in the specified root directory\n"
4610 " -n --lines=INTEGER Numer of journal entries to show\n"
4611 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
4612 " verbose, export, json, json-pretty, json-sse, cat)\n\n"
4614 " list-units List loaded units\n"
4615 " list-sockets List loaded sockets ordered by address\n"
4616 " start [NAME...] Start (activate) one or more units\n"
4617 " stop [NAME...] Stop (deactivate) one or more units\n"
4618 " reload [NAME...] Reload one or more units\n"
4619 " restart [NAME...] Start or restart one or more units\n"
4620 " try-restart [NAME...] Restart one or more units if active\n"
4621 " reload-or-restart [NAME...] Reload one or more units if possible,\n"
4622 " otherwise start or restart\n"
4623 " reload-or-try-restart [NAME...] Reload one or more units if possible,\n"
4624 " otherwise restart if active\n"
4625 " isolate [NAME] Start one unit and stop all others\n"
4626 " kill [NAME...] Send signal to processes of a unit\n"
4627 " is-active [NAME...] Check whether units are active\n"
4628 " is-failed [NAME...] Check whether units are failed\n"
4629 " status [NAME...|PID...] Show runtime status of one or more units\n"
4630 " show [NAME...|JOB...] Show properties of one or more\n"
4631 " units/jobs or the manager\n"
4632 " set-property [NAME] [ASSIGNMENT...]\n"
4633 " Sets one or more properties of a unit\n"
4634 " help [NAME...|PID...] Show manual for one or more units\n"
4635 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
4637 " list-dependencies [NAME] Recursively show units which are required\n"
4638 " or wanted by this unit or by which this\n"
4639 " unit is required or wanted\n\n"
4640 "Unit File Commands:\n"
4641 " list-unit-files List installed unit files\n"
4642 " enable [NAME...] Enable one or more unit files\n"
4643 " disable [NAME...] Disable one or more unit files\n"
4644 " reenable [NAME...] Reenable one or more unit files\n"
4645 " preset [NAME...] Enable/disable one or more unit files\n"
4646 " based on preset configuration\n"
4647 " is-enabled [NAME...] Check whether unit files are enabled\n\n"
4648 " mask [NAME...] Mask one or more units\n"
4649 " unmask [NAME...] Unmask one or more units\n"
4650 " link [PATH...] Link one or more units files into\n"
4651 " the search path\n"
4652 " get-default Get the name of the default target\n"
4653 " set-default NAME Set the default target\n"
4655 " list-jobs List jobs\n"
4656 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
4657 "Snapshot Commands:\n"
4658 " snapshot [NAME] Create a snapshot\n"
4659 " delete [NAME...] Remove one or more snapshots\n\n"
4660 "Environment Commands:\n"
4661 " show-environment Dump environment\n"
4662 " set-environment [NAME=VALUE...] Set one or more environment variables\n"
4663 " unset-environment [NAME...] Unset one or more environment variables\n\n"
4664 "Manager Lifecycle Commands:\n"
4665 " daemon-reload Reload systemd manager configuration\n"
4666 " daemon-reexec Reexecute systemd manager\n\n"
4667 "System Commands:\n"
4668 " default Enter system default mode\n"
4669 " rescue Enter system rescue mode\n"
4670 " emergency Enter system emergency mode\n"
4671 " halt Shut down and halt the system\n"
4672 " poweroff Shut down and power-off the system\n"
4673 " reboot Shut down and reboot the system\n"
4674 " kexec Shut down and reboot the system with kexec\n"
4675 " exit Request user instance exit\n"
4676 " switch-root [ROOT] [INIT] Change to a different root file system\n"
4677 " suspend Suspend the system\n"
4678 " hibernate Hibernate the system\n"
4679 " hybrid-sleep Hibernate and suspend the system\n",
4680 program_invocation_short_name);
4685 static int halt_help(void) {
4687 printf("%s [OPTIONS...]\n\n"
4688 "%s the system.\n\n"
4689 " --help Show this help\n"
4690 " --halt Halt the machine\n"
4691 " -p --poweroff Switch off the machine\n"
4692 " --reboot Reboot the machine\n"
4693 " -f --force Force immediate halt/power-off/reboot\n"
4694 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
4695 " -d --no-wtmp Don't write wtmp record\n"
4696 " --no-wall Don't send wall message before halt/power-off/reboot\n",
4697 program_invocation_short_name,
4698 arg_action == ACTION_REBOOT ? "Reboot" :
4699 arg_action == ACTION_POWEROFF ? "Power off" :
4705 static int shutdown_help(void) {
4707 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
4708 "Shut down the system.\n\n"
4709 " --help Show this help\n"
4710 " -H --halt Halt the machine\n"
4711 " -P --poweroff Power-off the machine\n"
4712 " -r --reboot Reboot the machine\n"
4713 " -h Equivalent to --poweroff, overridden by --halt\n"
4714 " -k Don't halt/power-off/reboot, just send warnings\n"
4715 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4716 " -c Cancel a pending shutdown\n",
4717 program_invocation_short_name);
4722 static int telinit_help(void) {
4724 printf("%s [OPTIONS...] {COMMAND}\n\n"
4725 "Send control commands to the init daemon.\n\n"
4726 " --help Show this help\n"
4727 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
4729 " 0 Power-off the machine\n"
4730 " 6 Reboot the machine\n"
4731 " 2, 3, 4, 5 Start runlevelX.target unit\n"
4732 " 1, s, S Enter rescue mode\n"
4733 " q, Q Reload init daemon configuration\n"
4734 " u, U Reexecute init daemon\n",
4735 program_invocation_short_name);
4740 static int runlevel_help(void) {
4742 printf("%s [OPTIONS...]\n\n"
4743 "Prints the previous and current runlevel of the init system.\n\n"
4744 " --help Show this help\n",
4745 program_invocation_short_name);
4750 static int help_types(void) {
4754 puts("Available unit types:");
4755 for(i = 0; i < _UNIT_TYPE_MAX; i++) {
4756 t = unit_type_to_string(i);
4764 static int systemctl_parse_argv(int argc, char *argv[]) {
4773 ARG_IGNORE_DEPENDENCIES,
4785 ARG_NO_ASK_PASSWORD,
4793 static const struct option options[] = {
4794 { "help", no_argument, NULL, 'h' },
4795 { "version", no_argument, NULL, ARG_VERSION },
4796 { "type", required_argument, NULL, 't' },
4797 { "property", required_argument, NULL, 'p' },
4798 { "all", no_argument, NULL, 'a' },
4799 { "reverse", no_argument, NULL, ARG_REVERSE },
4800 { "after", no_argument, NULL, ARG_AFTER },
4801 { "before", no_argument, NULL, ARG_BEFORE },
4802 { "show-types", no_argument, NULL, ARG_SHOW_TYPES },
4803 { "failed", no_argument, NULL, ARG_FAILED }, /* compatibility only */
4804 { "full", no_argument, NULL, 'l' },
4805 { "fail", no_argument, NULL, ARG_FAIL },
4806 { "irreversible", no_argument, NULL, ARG_IRREVERSIBLE },
4807 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
4808 { "ignore-inhibitors", no_argument, NULL, 'i' },
4809 { "user", no_argument, NULL, ARG_USER },
4810 { "system", no_argument, NULL, ARG_SYSTEM },
4811 { "global", no_argument, NULL, ARG_GLOBAL },
4812 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
4813 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
4814 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
4815 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4816 { "quiet", no_argument, NULL, 'q' },
4817 { "root", required_argument, NULL, ARG_ROOT },
4818 { "force", no_argument, NULL, ARG_FORCE },
4819 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
4820 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
4821 { "signal", required_argument, NULL, 's' },
4822 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
4823 { "host", required_argument, NULL, 'H' },
4824 { "privileged", no_argument, NULL, 'P' },
4825 { "runtime", no_argument, NULL, ARG_RUNTIME },
4826 { "lines", required_argument, NULL, 'n' },
4827 { "output", required_argument, NULL, 'o' },
4828 { "plain", no_argument, NULL, ARG_PLAIN },
4829 { "state", required_argument, NULL, ARG_STATE },
4830 { NULL, 0, NULL, 0 }
4838 while ((c = getopt_long(argc, argv, "ht:p:alqfs:H:Pn:o:i", options, NULL)) >= 0) {
4847 puts(PACKAGE_STRING);
4848 puts(SYSTEMD_FEATURES);
4855 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
4856 _cleanup_free_ char *type;
4858 type = strndup(word, size);
4862 if (streq(type, "help")) {
4867 if (unit_type_from_string(type) >= 0) {
4868 if (strv_push(&arg_types, type))
4874 /* It's much nicer to use --state= for
4875 * load states, but let's support this
4876 * in --types= too for compatibility
4877 * with old versions */
4878 if (unit_load_state_from_string(optarg) >= 0) {
4879 if (strv_push(&arg_states, type) < 0)
4885 log_error("Unknown unit type or load state '%s'.", type);
4886 log_info("Use -t help to see a list of allowed values.");
4894 /* Make sure that if the empty property list
4895 was specified, we won't show any properties. */
4896 if (isempty(optarg) && !arg_properties) {
4897 arg_properties = strv_new(NULL, NULL);
4898 if (!arg_properties)
4904 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
4907 prop = strndup(word, size);
4911 if (strv_push(&arg_properties, prop) < 0) {
4918 /* If the user asked for a particular
4919 * property, show it to him, even if it is
4931 arg_dependency = DEPENDENCY_REVERSE;
4935 arg_dependency = DEPENDENCY_AFTER;
4939 arg_dependency = DEPENDENCY_BEFORE;
4942 case ARG_SHOW_TYPES:
4943 arg_show_types = true;
4947 arg_job_mode = "fail";
4950 case ARG_IRREVERSIBLE:
4951 arg_job_mode = "replace-irreversibly";
4954 case ARG_IGNORE_DEPENDENCIES:
4955 arg_job_mode = "ignore-dependencies";
4959 arg_scope = UNIT_FILE_USER;
4963 arg_scope = UNIT_FILE_SYSTEM;
4967 arg_scope = UNIT_FILE_GLOBAL;
4971 arg_no_block = true;
4975 arg_no_legend = true;
4979 arg_no_pager = true;
4995 if (strv_extend(&arg_states, "failed") < 0)
5013 arg_no_reload = true;
5017 arg_kill_who = optarg;
5021 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
5022 log_error("Failed to parse signal string %s.", optarg);
5027 case ARG_NO_ASK_PASSWORD:
5028 arg_ask_password = false;
5032 arg_transport = TRANSPORT_POLKIT;
5036 arg_transport = TRANSPORT_SSH;
5037 parse_user_at_host(optarg, &arg_user, &arg_host);
5045 if (safe_atou(optarg, &arg_lines) < 0) {
5046 log_error("Failed to parse lines '%s'", optarg);
5052 arg_output = output_mode_from_string(optarg);
5053 if (arg_output < 0) {
5054 log_error("Unknown output '%s'.", optarg);
5060 arg_ignore_inhibitors = true;
5071 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
5074 s = strndup(word, size);
5078 if (strv_push(&arg_states, s) < 0) {
5090 log_error("Unknown option code '%c'.", c);
5095 if (arg_transport != TRANSPORT_NORMAL && arg_scope != UNIT_FILE_SYSTEM) {
5096 log_error("Cannot access user instance remotely.");
5103 static int halt_parse_argv(int argc, char *argv[]) {
5112 static const struct option options[] = {
5113 { "help", no_argument, NULL, ARG_HELP },
5114 { "halt", no_argument, NULL, ARG_HALT },
5115 { "poweroff", no_argument, NULL, 'p' },
5116 { "reboot", no_argument, NULL, ARG_REBOOT },
5117 { "force", no_argument, NULL, 'f' },
5118 { "wtmp-only", no_argument, NULL, 'w' },
5119 { "no-wtmp", no_argument, NULL, 'd' },
5120 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5121 { NULL, 0, NULL, 0 }
5129 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
5130 if (runlevel == '0' || runlevel == '6')
5133 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
5141 arg_action = ACTION_HALT;
5145 if (arg_action != ACTION_REBOOT)
5146 arg_action = ACTION_POWEROFF;
5150 arg_action = ACTION_REBOOT;
5172 /* Compatibility nops */
5179 log_error("Unknown option code '%c'.", c);
5184 if (optind < argc) {
5185 log_error("Too many arguments.");
5192 static int parse_time_spec(const char *t, usec_t *_u) {
5196 if (streq(t, "now"))
5198 else if (!strchr(t, ':')) {
5201 if (safe_atou64(t, &u) < 0)
5204 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
5213 hour = strtol(t, &e, 10);
5214 if (errno > 0 || *e != ':' || hour < 0 || hour > 23)
5217 minute = strtol(e+1, &e, 10);
5218 if (errno > 0 || *e != 0 || minute < 0 || minute > 59)
5221 n = now(CLOCK_REALTIME);
5222 s = (time_t) (n / USEC_PER_SEC);
5224 assert_se(localtime_r(&s, &tm));
5226 tm.tm_hour = (int) hour;
5227 tm.tm_min = (int) minute;
5230 assert_se(s = mktime(&tm));
5232 *_u = (usec_t) s * USEC_PER_SEC;
5235 *_u += USEC_PER_DAY;
5241 static int shutdown_parse_argv(int argc, char *argv[]) {
5248 static const struct option options[] = {
5249 { "help", no_argument, NULL, ARG_HELP },
5250 { "halt", no_argument, NULL, 'H' },
5251 { "poweroff", no_argument, NULL, 'P' },
5252 { "reboot", no_argument, NULL, 'r' },
5253 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
5254 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5255 { NULL, 0, NULL, 0 }
5263 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
5271 arg_action = ACTION_HALT;
5275 arg_action = ACTION_POWEROFF;
5280 arg_action = ACTION_KEXEC;
5282 arg_action = ACTION_REBOOT;
5286 arg_action = ACTION_KEXEC;
5290 if (arg_action != ACTION_HALT)
5291 arg_action = ACTION_POWEROFF;
5304 /* Compatibility nops */
5308 arg_action = ACTION_CANCEL_SHUTDOWN;
5315 log_error("Unknown option code '%c'.", c);
5320 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
5321 r = parse_time_spec(argv[optind], &arg_when);
5323 log_error("Failed to parse time specification: %s", argv[optind]);
5327 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
5329 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
5330 /* No time argument for shutdown cancel */
5331 arg_wall = argv + optind;
5332 else if (argc > optind + 1)
5333 /* We skip the time argument */
5334 arg_wall = argv + optind + 1;
5341 static int telinit_parse_argv(int argc, char *argv[]) {
5348 static const struct option options[] = {
5349 { "help", no_argument, NULL, ARG_HELP },
5350 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5351 { NULL, 0, NULL, 0 }
5354 static const struct {
5358 { '0', ACTION_POWEROFF },
5359 { '6', ACTION_REBOOT },
5360 { '1', ACTION_RESCUE },
5361 { '2', ACTION_RUNLEVEL2 },
5362 { '3', ACTION_RUNLEVEL3 },
5363 { '4', ACTION_RUNLEVEL4 },
5364 { '5', ACTION_RUNLEVEL5 },
5365 { 's', ACTION_RESCUE },
5366 { 'S', ACTION_RESCUE },
5367 { 'q', ACTION_RELOAD },
5368 { 'Q', ACTION_RELOAD },
5369 { 'u', ACTION_REEXEC },
5370 { 'U', ACTION_REEXEC }
5379 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
5394 log_error("Unknown option code '%c'.", c);
5399 if (optind >= argc) {
5404 if (optind + 1 < argc) {
5405 log_error("Too many arguments.");
5409 if (strlen(argv[optind]) != 1) {
5410 log_error("Expected single character argument.");
5414 for (i = 0; i < ELEMENTSOF(table); i++)
5415 if (table[i].from == argv[optind][0])
5418 if (i >= ELEMENTSOF(table)) {
5419 log_error("Unknown command '%s'.", argv[optind]);
5423 arg_action = table[i].to;
5430 static int runlevel_parse_argv(int argc, char *argv[]) {
5436 static const struct option options[] = {
5437 { "help", no_argument, NULL, ARG_HELP },
5438 { NULL, 0, NULL, 0 }
5446 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
5457 log_error("Unknown option code '%c'.", c);
5462 if (optind < argc) {
5463 log_error("Too many arguments.");
5470 static int parse_argv(int argc, char *argv[]) {
5474 if (program_invocation_short_name) {
5476 if (strstr(program_invocation_short_name, "halt")) {
5477 arg_action = ACTION_HALT;
5478 return halt_parse_argv(argc, argv);
5479 } else if (strstr(program_invocation_short_name, "poweroff")) {
5480 arg_action = ACTION_POWEROFF;
5481 return halt_parse_argv(argc, argv);
5482 } else if (strstr(program_invocation_short_name, "reboot")) {
5484 arg_action = ACTION_KEXEC;
5486 arg_action = ACTION_REBOOT;
5487 return halt_parse_argv(argc, argv);
5488 } else if (strstr(program_invocation_short_name, "shutdown")) {
5489 arg_action = ACTION_POWEROFF;
5490 return shutdown_parse_argv(argc, argv);
5491 } else if (strstr(program_invocation_short_name, "init")) {
5493 if (sd_booted() > 0) {
5494 arg_action = ACTION_INVALID;
5495 return telinit_parse_argv(argc, argv);
5497 /* Hmm, so some other init system is
5498 * running, we need to forward this
5499 * request to it. For now we simply
5500 * guess that it is Upstart. */
5502 execv(TELINIT, argv);
5504 log_error("Couldn't find an alternative telinit implementation to spawn.");
5508 } else if (strstr(program_invocation_short_name, "runlevel")) {
5509 arg_action = ACTION_RUNLEVEL;
5510 return runlevel_parse_argv(argc, argv);
5514 arg_action = ACTION_SYSTEMCTL;
5515 return systemctl_parse_argv(argc, argv);
5518 _pure_ static int action_to_runlevel(void) {
5520 static const char table[_ACTION_MAX] = {
5521 [ACTION_HALT] = '0',
5522 [ACTION_POWEROFF] = '0',
5523 [ACTION_REBOOT] = '6',
5524 [ACTION_RUNLEVEL2] = '2',
5525 [ACTION_RUNLEVEL3] = '3',
5526 [ACTION_RUNLEVEL4] = '4',
5527 [ACTION_RUNLEVEL5] = '5',
5528 [ACTION_RESCUE] = '1'
5531 assert(arg_action < _ACTION_MAX);
5533 return table[arg_action];
5536 static int talk_upstart(void) {
5537 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
5538 _cleanup_dbus_error_free_ DBusError error;
5539 int previous, rl, r;
5541 env1_buf[] = "RUNLEVEL=X",
5542 env2_buf[] = "PREVLEVEL=X";
5543 char *env1 = env1_buf, *env2 = env2_buf;
5544 const char *emit = "runlevel";
5545 dbus_bool_t b_false = FALSE;
5546 DBusMessageIter iter, sub;
5547 DBusConnection *bus;
5549 dbus_error_init(&error);
5551 if (!(rl = action_to_runlevel()))
5554 if (utmp_get_runlevel(&previous, NULL) < 0)
5557 if (!(bus = dbus_connection_open_private("unix:abstract=/com/ubuntu/upstart", &error))) {
5558 if (dbus_error_has_name(&error, DBUS_ERROR_NO_SERVER)) {
5563 log_error("Failed to connect to Upstart bus: %s", bus_error_message(&error));
5568 if ((r = bus_check_peercred(bus)) < 0) {
5569 log_error("Failed to verify owner of bus.");
5573 if (!(m = dbus_message_new_method_call(
5574 "com.ubuntu.Upstart",
5575 "/com/ubuntu/Upstart",
5576 "com.ubuntu.Upstart0_6",
5579 log_error("Could not allocate message.");
5584 dbus_message_iter_init_append(m, &iter);
5586 env1_buf[sizeof(env1_buf)-2] = rl;
5587 env2_buf[sizeof(env2_buf)-2] = previous;
5589 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &emit) ||
5590 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub) ||
5591 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env1) ||
5592 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env2) ||
5593 !dbus_message_iter_close_container(&iter, &sub) ||
5594 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b_false)) {
5595 log_error("Could not append arguments to message.");
5600 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
5602 if (bus_error_is_no_service(&error)) {
5607 log_error("Failed to issue method call: %s", bus_error_message(&error));
5616 dbus_connection_flush(bus);
5617 dbus_connection_close(bus);
5618 dbus_connection_unref(bus);
5624 static int talk_initctl(void) {
5625 struct init_request request = {};
5627 _cleanup_close_ int fd = -1;
5630 rl = action_to_runlevel();
5634 request.magic = INIT_MAGIC;
5635 request.sleeptime = 0;
5636 request.cmd = INIT_CMD_RUNLVL;
5637 request.runlevel = rl;
5639 fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY);
5641 if (errno == ENOENT)
5644 log_error("Failed to open "INIT_FIFO": %m");
5649 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
5651 log_error("Failed to write to "INIT_FIFO": %m");
5652 return errno > 0 ? -errno : -EIO;
5658 static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
5660 static const struct {
5668 int (* const dispatch)(DBusConnection *bus, char **args);
5670 { "list-units", LESS, 1, list_units },
5671 { "list-unit-files", EQUAL, 1, list_unit_files },
5672 { "list-sockets", LESS, 1, list_sockets },
5673 { "list-jobs", EQUAL, 1, list_jobs },
5674 { "clear-jobs", EQUAL, 1, daemon_reload },
5675 { "cancel", MORE, 2, cancel_job },
5676 { "start", MORE, 2, start_unit },
5677 { "stop", MORE, 2, start_unit },
5678 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5679 { "reload", MORE, 2, start_unit },
5680 { "restart", MORE, 2, start_unit },
5681 { "try-restart", MORE, 2, start_unit },
5682 { "reload-or-restart", MORE, 2, start_unit },
5683 { "reload-or-try-restart", MORE, 2, start_unit },
5684 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
5685 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5686 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
5687 { "isolate", EQUAL, 2, start_unit },
5688 { "kill", MORE, 2, kill_unit },
5689 { "is-active", MORE, 2, check_unit_active },
5690 { "check", MORE, 2, check_unit_active },
5691 { "is-failed", MORE, 2, check_unit_failed },
5692 { "show", MORE, 1, show },
5693 { "status", MORE, 1, show },
5694 { "help", MORE, 2, show },
5695 { "snapshot", LESS, 2, snapshot },
5696 { "delete", MORE, 2, delete_snapshot },
5697 { "daemon-reload", EQUAL, 1, daemon_reload },
5698 { "daemon-reexec", EQUAL, 1, daemon_reload },
5699 { "show-environment", EQUAL, 1, show_enviroment },
5700 { "set-environment", MORE, 2, set_environment },
5701 { "unset-environment", MORE, 2, set_environment },
5702 { "halt", EQUAL, 1, start_special },
5703 { "poweroff", EQUAL, 1, start_special },
5704 { "reboot", EQUAL, 1, start_special },
5705 { "kexec", EQUAL, 1, start_special },
5706 { "suspend", EQUAL, 1, start_special },
5707 { "hibernate", EQUAL, 1, start_special },
5708 { "hybrid-sleep", EQUAL, 1, start_special },
5709 { "default", EQUAL, 1, start_special },
5710 { "rescue", EQUAL, 1, start_special },
5711 { "emergency", EQUAL, 1, start_special },
5712 { "exit", EQUAL, 1, start_special },
5713 { "reset-failed", MORE, 1, reset_failed },
5714 { "enable", MORE, 2, enable_unit },
5715 { "disable", MORE, 2, enable_unit },
5716 { "is-enabled", MORE, 2, unit_is_enabled },
5717 { "reenable", MORE, 2, enable_unit },
5718 { "preset", MORE, 2, enable_unit },
5719 { "mask", MORE, 2, enable_unit },
5720 { "unmask", MORE, 2, enable_unit },
5721 { "link", MORE, 2, enable_unit },
5722 { "switch-root", MORE, 2, switch_root },
5723 { "list-dependencies", LESS, 2, list_dependencies },
5724 { "set-default", EQUAL, 2, enable_unit },
5725 { "get-default", LESS, 1, get_default },
5726 { "set-property", MORE, 3, set_property },
5736 left = argc - optind;
5739 /* Special rule: no arguments means "list-units" */
5742 if (streq(argv[optind], "help") && !argv[optind+1]) {
5743 log_error("This command expects one or more "
5744 "unit names. Did you mean --help?");
5748 for (i = 0; i < ELEMENTSOF(verbs); i++)
5749 if (streq(argv[optind], verbs[i].verb))
5752 if (i >= ELEMENTSOF(verbs)) {
5753 log_error("Unknown operation '%s'.", argv[optind]);
5758 switch (verbs[i].argc_cmp) {
5761 if (left != verbs[i].argc) {
5762 log_error("Invalid number of arguments.");
5769 if (left < verbs[i].argc) {
5770 log_error("Too few arguments.");
5777 if (left > verbs[i].argc) {
5778 log_error("Too many arguments.");
5785 assert_not_reached("Unknown comparison operator.");
5788 /* Require a bus connection for all operations but
5790 if (!streq(verbs[i].verb, "enable") &&
5791 !streq(verbs[i].verb, "disable") &&
5792 !streq(verbs[i].verb, "is-enabled") &&
5793 !streq(verbs[i].verb, "list-unit-files") &&
5794 !streq(verbs[i].verb, "reenable") &&
5795 !streq(verbs[i].verb, "preset") &&
5796 !streq(verbs[i].verb, "mask") &&
5797 !streq(verbs[i].verb, "unmask") &&
5798 !streq(verbs[i].verb, "link") &&
5799 !streq(verbs[i].verb, "set-default") &&
5800 !streq(verbs[i].verb, "get-default")) {
5802 if (running_in_chroot() > 0) {
5803 log_info("Running in chroot, ignoring request.");
5807 if (((!streq(verbs[i].verb, "reboot") &&
5808 !streq(verbs[i].verb, "halt") &&
5809 !streq(verbs[i].verb, "poweroff")) || arg_force <= 0) && !bus) {
5810 log_error("Failed to get D-Bus connection: %s",
5811 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5817 if (!bus && !avoid_bus()) {
5818 log_error("Failed to get D-Bus connection: %s",
5819 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5824 return verbs[i].dispatch(bus, argv + optind);
5827 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
5828 _cleanup_close_ int fd;
5829 struct sd_shutdown_command c = {
5835 union sockaddr_union sockaddr = {
5836 .un.sun_family = AF_UNIX,
5837 .un.sun_path = "/run/systemd/shutdownd",
5839 struct iovec iovec[2] = {
5840 {.iov_base = (char*) &c,
5841 .iov_len = offsetof(struct sd_shutdown_command, wall_message),
5844 struct msghdr msghdr = {
5845 .msg_name = &sockaddr,
5846 .msg_namelen = offsetof(struct sockaddr_un, sun_path)
5847 + sizeof("/run/systemd/shutdownd") - 1,
5852 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
5856 if (!isempty(message)) {
5857 iovec[1].iov_base = (char*) message;
5858 iovec[1].iov_len = strlen(message);
5859 msghdr.msg_iovlen++;
5862 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0)
5868 static int reload_with_fallback(DBusConnection *bus) {
5871 /* First, try systemd via D-Bus. */
5872 if (daemon_reload(bus, NULL) >= 0)
5876 /* Nothing else worked, so let's try signals */
5877 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
5879 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
5880 log_error("kill() failed: %m");
5887 static int start_with_fallback(DBusConnection *bus) {
5890 /* First, try systemd via D-Bus. */
5891 if (start_unit(bus, NULL) >= 0)
5895 /* Hmm, talking to systemd via D-Bus didn't work. Then
5896 * let's try to talk to Upstart via D-Bus. */
5897 if (talk_upstart() > 0)
5900 /* Nothing else worked, so let's try
5902 if (talk_initctl() > 0)
5905 log_error("Failed to talk to init daemon.");
5909 warn_wall(arg_action);
5913 static _noreturn_ void halt_now(enum action a) {
5915 /* Make sure C-A-D is handled by the kernel from this
5917 reboot(RB_ENABLE_CAD);
5922 log_info("Halting.");
5923 reboot(RB_HALT_SYSTEM);
5926 case ACTION_POWEROFF:
5927 log_info("Powering off.");
5928 reboot(RB_POWER_OFF);
5932 log_info("Rebooting.");
5933 reboot(RB_AUTOBOOT);
5937 assert_not_reached("Unknown halt action.");
5940 assert_not_reached("Uh? This shouldn't happen.");
5943 static int halt_main(DBusConnection *bus) {
5946 r = check_inhibitors(bus, arg_action);
5950 if (geteuid() != 0) {
5951 /* Try logind if we are a normal user and no special
5952 * mode applies. Maybe PolicyKit allows us to shutdown
5955 if (arg_when <= 0 &&
5958 (arg_action == ACTION_POWEROFF ||
5959 arg_action == ACTION_REBOOT)) {
5960 r = reboot_with_logind(bus, arg_action);
5965 log_error("Must be root.");
5970 _cleanup_free_ char *m;
5972 m = strv_join(arg_wall, " ");
5973 r = send_shutdownd(arg_when,
5974 arg_action == ACTION_HALT ? 'H' :
5975 arg_action == ACTION_POWEROFF ? 'P' :
5976 arg_action == ACTION_KEXEC ? 'K' :
5983 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
5985 char date[FORMAT_TIMESTAMP_MAX];
5987 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
5988 format_timestamp(date, sizeof(date), arg_when));
5993 if (!arg_dry && !arg_force)
5994 return start_with_fallback(bus);
5997 if (sd_booted() > 0)
5998 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
6000 r = utmp_put_shutdown();
6002 log_warning("Failed to write utmp record: %s", strerror(-r));
6009 halt_now(arg_action);
6010 /* We should never reach this. */
6014 static int runlevel_main(void) {
6015 int r, runlevel, previous;
6017 r = utmp_get_runlevel(&runlevel, &previous);
6024 previous <= 0 ? 'N' : previous,
6025 runlevel <= 0 ? 'N' : runlevel);
6030 int main(int argc, char*argv[]) {
6031 int r, retval = EXIT_FAILURE;
6032 DBusConnection *bus = NULL;
6033 _cleanup_dbus_error_free_ DBusError error;
6035 dbus_error_init(&error);
6037 setlocale(LC_ALL, "");
6038 log_parse_environment();
6041 r = parse_argv(argc, argv);
6045 retval = EXIT_SUCCESS;
6049 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
6050 * let's shortcut this */
6051 if (arg_action == ACTION_RUNLEVEL) {
6052 r = runlevel_main();
6053 retval = r < 0 ? EXIT_FAILURE : r;
6057 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
6058 log_info("Running in chroot, ignoring request.");
6064 if (arg_transport == TRANSPORT_NORMAL)
6065 bus_connect(arg_scope == UNIT_FILE_SYSTEM ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &bus, &private_bus, &error);
6066 else if (arg_transport == TRANSPORT_POLKIT) {
6067 bus_connect_system_polkit(&bus, &error);
6068 private_bus = false;
6069 } else if (arg_transport == TRANSPORT_SSH) {
6070 bus_connect_system_ssh(arg_user, arg_host, &bus, &error);
6071 private_bus = false;
6073 assert_not_reached("Uh, invalid transport...");
6076 switch (arg_action) {
6078 case ACTION_SYSTEMCTL:
6079 r = systemctl_main(bus, argc, argv, &error);
6083 case ACTION_POWEROFF:
6089 case ACTION_RUNLEVEL2:
6090 case ACTION_RUNLEVEL3:
6091 case ACTION_RUNLEVEL4:
6092 case ACTION_RUNLEVEL5:
6094 case ACTION_EMERGENCY:
6095 case ACTION_DEFAULT:
6096 r = start_with_fallback(bus);
6101 r = reload_with_fallback(bus);
6104 case ACTION_CANCEL_SHUTDOWN: {
6108 m = strv_join(arg_wall, " ");
6110 retval = EXIT_FAILURE;
6114 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
6116 log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r));
6121 case ACTION_INVALID:
6122 case ACTION_RUNLEVEL:
6124 assert_not_reached("Unknown action");
6127 retval = r < 0 ? EXIT_FAILURE : r;
6131 dbus_connection_flush(bus);
6132 dbus_connection_close(bus);
6133 dbus_connection_unref(bus);
6138 strv_free(arg_types);
6139 strv_free(arg_states);
6140 strv_free(arg_properties);
6143 ask_password_agent_close();
6144 polkit_agent_close();