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;
1500 if (dbus_message_get_args(message, &error,
1501 DBUS_TYPE_UINT32, &id,
1502 DBUS_TYPE_OBJECT_PATH, &path,
1503 DBUS_TYPE_STRING, &unit,
1504 DBUS_TYPE_STRING, &result,
1505 DBUS_TYPE_INVALID)) {
1507 r = set_remove(d->set, (char*) path);
1509 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1513 if (!isempty(result))
1514 d->result = strdup(result);
1517 d->name = strdup(unit);
1519 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1522 dbus_error_free(&error);
1523 if (dbus_message_get_args(message, &error,
1524 DBUS_TYPE_UINT32, &id,
1525 DBUS_TYPE_OBJECT_PATH, &path,
1526 DBUS_TYPE_STRING, &result,
1527 DBUS_TYPE_INVALID)) {
1528 /* Compatibility with older systemd versions <
1529 * 183 during upgrades. This should be dropped
1531 r = set_remove(d->set, (char*) path);
1533 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1538 d->result = strdup(result);
1540 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1544 log_error("Failed to parse message: %s", bus_error_message(&error));
1547 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1550 static int enable_wait_for_jobs(DBusConnection *bus) {
1558 dbus_error_init(&error);
1559 dbus_bus_add_match(bus,
1561 "sender='org.freedesktop.systemd1',"
1562 "interface='org.freedesktop.systemd1.Manager',"
1563 "member='JobRemoved',"
1564 "path='/org/freedesktop/systemd1'",
1567 if (dbus_error_is_set(&error)) {
1568 log_error("Failed to add match: %s", bus_error_message(&error));
1569 dbus_error_free(&error);
1573 /* This is slightly dirty, since we don't undo the match registrations. */
1577 static int wait_for_jobs(DBusConnection *bus, Set *s) {
1579 WaitData d = { .set = s };
1584 if (!dbus_connection_add_filter(bus, wait_filter, &d, NULL))
1587 while (!set_isempty(s)) {
1589 if (!dbus_connection_read_write_dispatch(bus, -1)) {
1590 log_error("Disconnected from bus.");
1591 return -ECONNREFUSED;
1598 if (streq(d.result, "timeout"))
1599 log_error("Job for %s timed out.", strna(d.name));
1600 else if (streq(d.result, "canceled"))
1601 log_error("Job for %s canceled.", strna(d.name));
1602 else if (streq(d.result, "dependency"))
1603 log_error("A dependency job for %s failed. See 'journalctl -xn' for details.", strna(d.name));
1604 else if (!streq(d.result, "done") && !streq(d.result, "skipped"))
1605 log_error("Job for %s failed. See 'systemctl status %s' and 'journalctl -xn' for details.", strna(d.name), strna(d.name));
1608 if (streq_ptr(d.result, "timeout"))
1610 else if (streq_ptr(d.result, "canceled"))
1612 else if (!streq_ptr(d.result, "done") && !streq_ptr(d.result, "skipped"))
1623 dbus_connection_remove_filter(bus, wait_filter, &d);
1627 static int check_one_unit(DBusConnection *bus, const char *name, char **check_states, bool quiet) {
1628 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1629 _cleanup_free_ char *n = NULL;
1630 DBusMessageIter iter, sub;
1632 *interface = "org.freedesktop.systemd1.Unit",
1633 *property = "ActiveState";
1634 const char *state, *path;
1640 dbus_error_init(&error);
1642 n = unit_name_mangle(name);
1646 r = bus_method_call_with_reply (
1648 "org.freedesktop.systemd1",
1649 "/org/freedesktop/systemd1",
1650 "org.freedesktop.systemd1.Manager",
1654 DBUS_TYPE_STRING, &n,
1657 dbus_error_free(&error);
1664 if (!dbus_message_get_args(reply, NULL,
1665 DBUS_TYPE_OBJECT_PATH, &path,
1666 DBUS_TYPE_INVALID)) {
1667 log_error("Failed to parse reply.");
1671 dbus_message_unref(reply);
1674 r = bus_method_call_with_reply(
1676 "org.freedesktop.systemd1",
1678 "org.freedesktop.DBus.Properties",
1682 DBUS_TYPE_STRING, &interface,
1683 DBUS_TYPE_STRING, &property,
1691 if (!dbus_message_iter_init(reply, &iter) ||
1692 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1693 log_error("Failed to parse reply.");
1697 dbus_message_iter_recurse(&iter, &sub);
1699 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1700 log_error("Failed to parse reply.");
1704 dbus_message_iter_get_basic(&sub, &state);
1709 return strv_find(check_states, state) ? 1 : 0;
1712 static void check_triggering_units(
1713 DBusConnection *bus,
1714 const char *unit_name) {
1716 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1717 DBusMessageIter iter, sub;
1718 const char *interface = "org.freedesktop.systemd1.Unit",
1719 *load_state_property = "LoadState",
1720 *triggered_by_property = "TriggeredBy",
1722 _cleanup_free_ char *unit_path = NULL, *n = NULL;
1723 bool print_warning_label = true;
1726 n = unit_name_mangle(unit_name);
1732 unit_path = unit_dbus_path_from_name(n);
1738 r = bus_method_call_with_reply(
1740 "org.freedesktop.systemd1",
1742 "org.freedesktop.DBus.Properties",
1746 DBUS_TYPE_STRING, &interface,
1747 DBUS_TYPE_STRING, &load_state_property,
1752 if (!dbus_message_iter_init(reply, &iter) ||
1753 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1754 log_error("Failed to parse reply.");
1758 dbus_message_iter_recurse(&iter, &sub);
1760 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1761 log_error("Failed to parse reply.");
1765 dbus_message_iter_get_basic(&sub, &state);
1767 if (streq(state, "masked"))
1770 dbus_message_unref(reply);
1773 r = bus_method_call_with_reply(
1775 "org.freedesktop.systemd1",
1777 "org.freedesktop.DBus.Properties",
1781 DBUS_TYPE_STRING, &interface,
1782 DBUS_TYPE_STRING, &triggered_by_property,
1787 if (!dbus_message_iter_init(reply, &iter) ||
1788 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1789 log_error("Failed to parse reply.");
1793 dbus_message_iter_recurse(&iter, &sub);
1794 dbus_message_iter_recurse(&sub, &iter);
1797 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1798 const char * const check_states[] = {
1803 const char *service_trigger;
1805 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1806 log_error("Failed to parse reply.");
1810 dbus_message_iter_get_basic(&sub, &service_trigger);
1812 r = check_one_unit(bus, service_trigger, (char**) check_states, true);
1816 if (print_warning_label) {
1817 log_warning("Warning: Stopping %s, but it can still be activated by:", unit_name);
1818 print_warning_label = false;
1821 log_warning(" %s", service_trigger);
1824 dbus_message_iter_next(&sub);
1828 static int start_unit_one(
1829 DBusConnection *bus,
1836 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1837 _cleanup_free_ char *n;
1846 n = unit_name_mangle(name);
1850 r = bus_method_call_with_reply(
1852 "org.freedesktop.systemd1",
1853 "/org/freedesktop/systemd1",
1854 "org.freedesktop.systemd1.Manager",
1858 DBUS_TYPE_STRING, &n,
1859 DBUS_TYPE_STRING, &mode,
1862 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
1863 /* There's always a fallback possible for
1864 * legacy actions. */
1867 log_error("Failed to issue method call: %s", bus_error_message(error));
1872 if (!dbus_message_get_args(reply, error,
1873 DBUS_TYPE_OBJECT_PATH, &path,
1874 DBUS_TYPE_INVALID)) {
1875 log_error("Failed to parse reply: %s", bus_error_message(error));
1879 if (need_daemon_reload(bus, n) > 0)
1880 log_warning("Warning: Unit file of %s changed on disk, 'systemctl %sdaemon-reload' recommended.",
1881 n, arg_scope == UNIT_FILE_SYSTEM ? "" : "--user ");
1890 r = set_consume(s, p);
1892 log_error("Failed to add path to set.");
1900 static const struct {
1904 } action_table[_ACTION_MAX] = {
1905 [ACTION_HALT] = { SPECIAL_HALT_TARGET, "halt", "replace-irreversibly" },
1906 [ACTION_POWEROFF] = { SPECIAL_POWEROFF_TARGET, "poweroff", "replace-irreversibly" },
1907 [ACTION_REBOOT] = { SPECIAL_REBOOT_TARGET, "reboot", "replace-irreversibly" },
1908 [ACTION_KEXEC] = { SPECIAL_KEXEC_TARGET, "kexec", "replace-irreversibly" },
1909 [ACTION_RUNLEVEL2] = { SPECIAL_RUNLEVEL2_TARGET, NULL, "isolate" },
1910 [ACTION_RUNLEVEL3] = { SPECIAL_RUNLEVEL3_TARGET, NULL, "isolate" },
1911 [ACTION_RUNLEVEL4] = { SPECIAL_RUNLEVEL4_TARGET, NULL, "isolate" },
1912 [ACTION_RUNLEVEL5] = { SPECIAL_RUNLEVEL5_TARGET, NULL, "isolate" },
1913 [ACTION_RESCUE] = { SPECIAL_RESCUE_TARGET, "rescue", "isolate" },
1914 [ACTION_EMERGENCY] = { SPECIAL_EMERGENCY_TARGET, "emergency", "isolate" },
1915 [ACTION_DEFAULT] = { SPECIAL_DEFAULT_TARGET, "default", "isolate" },
1916 [ACTION_EXIT] = { SPECIAL_EXIT_TARGET, "exit", "replace-irreversibly" },
1917 [ACTION_SUSPEND] = { SPECIAL_SUSPEND_TARGET, "suspend", "replace-irreversibly" },
1918 [ACTION_HIBERNATE] = { SPECIAL_HIBERNATE_TARGET, "hibernate", "replace-irreversibly" },
1919 [ACTION_HYBRID_SLEEP] = { SPECIAL_HYBRID_SLEEP_TARGET, "hybrid-sleep", "replace-irreversibly" },
1922 static enum action verb_to_action(const char *verb) {
1925 for (i = ACTION_INVALID; i < _ACTION_MAX; i++)
1926 if (action_table[i].verb && streq(verb, action_table[i].verb))
1928 return ACTION_INVALID;
1931 static int start_unit(DBusConnection *bus, char **args) {
1934 const char *method, *mode, *one_name;
1935 _cleanup_set_free_free_ Set *s = NULL;
1936 _cleanup_dbus_error_free_ DBusError error;
1939 dbus_error_init(&error);
1943 ask_password_agent_open_if_enabled();
1945 if (arg_action == ACTION_SYSTEMCTL) {
1948 streq(args[0], "stop") ||
1949 streq(args[0], "condstop") ? "StopUnit" :
1950 streq(args[0], "reload") ? "ReloadUnit" :
1951 streq(args[0], "restart") ? "RestartUnit" :
1953 streq(args[0], "try-restart") ||
1954 streq(args[0], "condrestart") ? "TryRestartUnit" :
1956 streq(args[0], "reload-or-restart") ? "ReloadOrRestartUnit" :
1958 streq(args[0], "reload-or-try-restart") ||
1959 streq(args[0], "condreload") ||
1961 streq(args[0], "force-reload") ? "ReloadOrTryRestartUnit" :
1963 action = verb_to_action(args[0]);
1965 mode = streq(args[0], "isolate") ? "isolate" :
1966 action_table[action].mode ?: arg_job_mode;
1968 one_name = action_table[action].target;
1971 assert(arg_action < ELEMENTSOF(action_table));
1972 assert(action_table[arg_action].target);
1974 method = "StartUnit";
1976 mode = action_table[arg_action].mode;
1977 one_name = action_table[arg_action].target;
1980 if (!arg_no_block) {
1981 ret = enable_wait_for_jobs(bus);
1983 log_error("Could not watch jobs: %s", strerror(-ret));
1987 s = set_new(string_hash_func, string_compare_func);
1993 ret = start_unit_one(bus, method, one_name, mode, &error, s);
1995 ret = translate_bus_error_to_exit_status(ret, &error);
1997 STRV_FOREACH(name, args+1) {
1998 r = start_unit_one(bus, method, *name, mode, &error, s);
2000 ret = translate_bus_error_to_exit_status(r, &error);
2001 dbus_error_free(&error);
2006 if (!arg_no_block) {
2007 r = wait_for_jobs(bus, s);
2011 /* When stopping units, warn if they can still be triggered by
2012 * another active unit (socket, path, timer) */
2013 if (!arg_quiet && streq(method, "StopUnit")) {
2015 check_triggering_units(bus, one_name);
2017 STRV_FOREACH(name, args+1)
2018 check_triggering_units(bus, *name);
2025 /* Ask systemd-logind, which might grant access to unprivileged users
2026 * through PolicyKit */
2027 static int reboot_with_logind(DBusConnection *bus, enum action a) {
2030 dbus_bool_t interactive = true;
2035 polkit_agent_open_if_enabled();
2043 case ACTION_POWEROFF:
2044 method = "PowerOff";
2047 case ACTION_SUSPEND:
2051 case ACTION_HIBERNATE:
2052 method = "Hibernate";
2055 case ACTION_HYBRID_SLEEP:
2056 method = "HybridSleep";
2063 return bus_method_call_with_reply(
2065 "org.freedesktop.login1",
2066 "/org/freedesktop/login1",
2067 "org.freedesktop.login1.Manager",
2071 DBUS_TYPE_BOOLEAN, &interactive,
2078 static int check_inhibitors(DBusConnection *bus, enum action a) {
2080 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
2081 DBusMessageIter iter, sub, sub2;
2084 _cleanup_strv_free_ char **sessions = NULL;
2090 if (arg_ignore_inhibitors || arg_force > 0)
2102 r = bus_method_call_with_reply(
2104 "org.freedesktop.login1",
2105 "/org/freedesktop/login1",
2106 "org.freedesktop.login1.Manager",
2112 /* If logind is not around, then there are no inhibitors... */
2115 if (!dbus_message_iter_init(reply, &iter) ||
2116 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
2117 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
2118 log_error("Failed to parse reply.");
2122 dbus_message_iter_recurse(&iter, &sub);
2123 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
2124 const char *what, *who, *why, *mode;
2126 _cleanup_strv_free_ char **sv = NULL;
2127 _cleanup_free_ char *comm = NULL, *user = NULL;
2129 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
2130 log_error("Failed to parse reply.");
2134 dbus_message_iter_recurse(&sub, &sub2);
2136 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &what, true) < 0 ||
2137 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &who, true) < 0 ||
2138 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &why, true) < 0 ||
2139 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &mode, true) < 0 ||
2140 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &uid, true) < 0 ||
2141 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, false) < 0) {
2142 log_error("Failed to parse reply.");
2146 if (!streq(mode, "block"))
2149 sv = strv_split(what, ":");
2153 if (!strv_contains(sv,
2155 a == ACTION_POWEROFF ||
2156 a == ACTION_REBOOT ||
2157 a == ACTION_KEXEC ? "shutdown" : "sleep"))
2160 get_process_comm(pid, &comm);
2161 user = uid_to_name(uid);
2162 log_warning("Operation inhibited by \"%s\" (PID %lu \"%s\", user %s), reason is \"%s\".",
2163 who, (unsigned long) pid, strna(comm), strna(user), why);
2167 dbus_message_iter_next(&sub);
2170 dbus_message_iter_recurse(&iter, &sub);
2172 /* Check for current sessions */
2173 sd_get_sessions(&sessions);
2174 STRV_FOREACH(s, sessions) {
2176 _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL;
2178 if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid())
2181 if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
2184 if (sd_session_get_type(*s, &type) < 0 || (!streq(type, "x11") && !streq(type, "tty")))
2187 sd_session_get_tty(*s, &tty);
2188 sd_session_get_seat(*s, &seat);
2189 sd_session_get_service(*s, &service);
2190 user = uid_to_name(uid);
2192 log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty);
2199 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
2200 action_table[a].verb);
2208 static int start_special(DBusConnection *bus, char **args) {
2214 a = verb_to_action(args[0]);
2216 r = check_inhibitors(bus, a);
2220 if (arg_force >= 2 && geteuid() != 0) {
2221 log_error("Must be root.");
2225 if (arg_force >= 2 &&
2226 (a == ACTION_HALT ||
2227 a == ACTION_POWEROFF ||
2228 a == ACTION_REBOOT))
2231 if (arg_force >= 1 &&
2232 (a == ACTION_HALT ||
2233 a == ACTION_POWEROFF ||
2234 a == ACTION_REBOOT ||
2235 a == ACTION_KEXEC ||
2237 return daemon_reload(bus, args);
2239 /* first try logind, to allow authentication with polkit */
2240 if (geteuid() != 0 &&
2241 (a == ACTION_POWEROFF ||
2242 a == ACTION_REBOOT ||
2243 a == ACTION_SUSPEND ||
2244 a == ACTION_HIBERNATE ||
2245 a == ACTION_HYBRID_SLEEP)) {
2246 r = reboot_with_logind(bus, a);
2251 r = start_unit(bus, args);
2252 if (r == EXIT_SUCCESS)
2258 static int check_unit_active(DBusConnection *bus, char **args) {
2259 const char * const check_states[] = {
2266 int r = 3; /* According to LSB: "program is not running" */
2271 STRV_FOREACH(name, args+1) {
2274 state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
2284 static int check_unit_failed(DBusConnection *bus, char **args) {
2285 const char * const check_states[] = {
2296 STRV_FOREACH(name, args+1) {
2299 state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
2309 static int kill_unit(DBusConnection *bus, char **args) {
2317 arg_kill_who = "all";
2319 STRV_FOREACH(name, args+1) {
2320 _cleanup_free_ char *n = NULL;
2322 n = unit_name_mangle(*name);
2326 r = bus_method_call_with_reply(
2328 "org.freedesktop.systemd1",
2329 "/org/freedesktop/systemd1",
2330 "org.freedesktop.systemd1.Manager",
2334 DBUS_TYPE_STRING, &n,
2335 DBUS_TYPE_STRING, &arg_kill_who,
2336 DBUS_TYPE_INT32, &arg_signal,
2344 typedef struct ExecStatusInfo {
2352 usec_t start_timestamp;
2353 usec_t exit_timestamp;
2358 LIST_FIELDS(struct ExecStatusInfo, exec);
2361 static void exec_status_info_free(ExecStatusInfo *i) {
2370 static int exec_status_info_deserialize(DBusMessageIter *sub, ExecStatusInfo *i) {
2371 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
2372 DBusMessageIter sub2, sub3;
2376 int32_t code, status;
2382 if (dbus_message_iter_get_arg_type(sub) != DBUS_TYPE_STRUCT)
2385 dbus_message_iter_recurse(sub, &sub2);
2387 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0)
2390 i->path = strdup(path);
2394 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_ARRAY ||
2395 dbus_message_iter_get_element_type(&sub2) != DBUS_TYPE_STRING)
2399 dbus_message_iter_recurse(&sub2, &sub3);
2400 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2401 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2402 dbus_message_iter_next(&sub3);
2406 i->argv = new0(char*, n+1);
2411 dbus_message_iter_recurse(&sub2, &sub3);
2412 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2415 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2416 dbus_message_iter_get_basic(&sub3, &s);
2417 dbus_message_iter_next(&sub3);
2419 i->argv[n] = strdup(s);
2426 if (!dbus_message_iter_next(&sub2) ||
2427 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, true) < 0 ||
2428 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp, true) < 0 ||
2429 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp_monotonic, true) < 0 ||
2430 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp, true) < 0 ||
2431 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp_monotonic, true) < 0 ||
2432 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, true) < 0 ||
2433 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &code, true) < 0 ||
2434 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &status, false) < 0)
2438 i->start_timestamp = (usec_t) start_timestamp;
2439 i->exit_timestamp = (usec_t) exit_timestamp;
2440 i->pid = (pid_t) pid;
2447 typedef struct UnitStatusInfo {
2449 const char *load_state;
2450 const char *active_state;
2451 const char *sub_state;
2452 const char *unit_file_state;
2454 const char *description;
2455 const char *following;
2457 char **documentation;
2459 const char *fragment_path;
2460 const char *source_path;
2461 const char *control_group;
2463 char **dropin_paths;
2465 const char *load_error;
2468 usec_t inactive_exit_timestamp;
2469 usec_t inactive_exit_timestamp_monotonic;
2470 usec_t active_enter_timestamp;
2471 usec_t active_exit_timestamp;
2472 usec_t inactive_enter_timestamp;
2474 bool need_daemon_reload;
2479 const char *status_text;
2480 const char *pid_file;
2483 usec_t start_timestamp;
2484 usec_t exit_timestamp;
2486 int exit_code, exit_status;
2488 usec_t condition_timestamp;
2489 bool condition_result;
2490 bool failed_condition_trigger;
2491 bool failed_condition_negate;
2492 const char *failed_condition;
2493 const char *failed_condition_param;
2496 unsigned n_accepted;
2497 unsigned n_connections;
2500 /* Pairs of type, path */
2504 const char *sysfs_path;
2506 /* Mount, Automount */
2512 LIST_HEAD(ExecStatusInfo, exec);
2515 static void print_status_info(UnitStatusInfo *i,
2518 const char *on, *off, *ss;
2520 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
2521 char since2[FORMAT_TIMESTAMP_MAX], *s2;
2524 arg_all * OUTPUT_SHOW_ALL |
2525 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
2526 on_tty() * OUTPUT_COLOR |
2527 !arg_quiet * OUTPUT_WARN_CUTOFF |
2528 arg_full * OUTPUT_FULL_WIDTH;
2533 /* This shows pretty information about a unit. See
2534 * print_property() for a low-level property printer */
2536 printf("%s", strna(i->id));
2538 if (i->description && !streq_ptr(i->id, i->description))
2539 printf(" - %s", i->description);
2544 printf(" Follow: unit currently follows state of %s\n", i->following);
2546 if (streq_ptr(i->load_state, "error")) {
2547 on = ansi_highlight_red();
2548 off = ansi_highlight_off();
2552 path = i->source_path ? i->source_path : i->fragment_path;
2555 printf(" Loaded: %s%s%s (Reason: %s)\n",
2556 on, strna(i->load_state), off, i->load_error);
2557 else if (path && i->unit_file_state)
2558 printf(" Loaded: %s%s%s (%s; %s)\n",
2559 on, strna(i->load_state), off, path, i->unit_file_state);
2561 printf(" Loaded: %s%s%s (%s)\n",
2562 on, strna(i->load_state), off, path);
2564 printf(" Loaded: %s%s%s\n",
2565 on, strna(i->load_state), off);
2567 if (!strv_isempty(i->dropin_paths)) {
2572 STRV_FOREACH(dropin, i->dropin_paths) {
2573 if (! dir || last) {
2574 printf(dir ? " " : " Drop-In: ");
2578 if (path_get_parent(*dropin, &dir) < 0) {
2583 printf("%s\n %s", dir,
2584 draw_special_char(DRAW_TREE_RIGHT));
2587 last = ! (*(dropin + 1) && startswith(*(dropin + 1), dir));
2589 printf("%s%s", path_get_file_name(*dropin), last ? "\n" : ", ");
2595 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
2597 if (streq_ptr(i->active_state, "failed")) {
2598 on = ansi_highlight_red();
2599 off = ansi_highlight_off();
2600 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
2601 on = ansi_highlight_green();
2602 off = ansi_highlight_off();
2607 printf(" Active: %s%s (%s)%s",
2608 on, strna(i->active_state), ss, off);
2610 printf(" Active: %s%s%s",
2611 on, strna(i->active_state), off);
2613 if (!isempty(i->result) && !streq(i->result, "success"))
2614 printf(" (Result: %s)", i->result);
2616 timestamp = (streq_ptr(i->active_state, "active") ||
2617 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
2618 (streq_ptr(i->active_state, "inactive") ||
2619 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
2620 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
2621 i->active_exit_timestamp;
2623 s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
2624 s2 = format_timestamp(since2, sizeof(since2), timestamp);
2627 printf(" since %s; %s\n", s2, s1);
2629 printf(" since %s\n", s2);
2633 if (!i->condition_result && i->condition_timestamp > 0) {
2634 s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
2635 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
2637 printf(" start condition failed at %s%s%s\n",
2638 s2, s1 ? "; " : "", s1 ? s1 : "");
2639 if (i->failed_condition_trigger)
2640 printf(" none of the trigger conditions were met\n");
2641 else if (i->failed_condition)
2642 printf(" %s=%s%s was not met\n",
2643 i->failed_condition,
2644 i->failed_condition_negate ? "!" : "",
2645 i->failed_condition_param);
2649 printf(" Device: %s\n", i->sysfs_path);
2651 printf(" Where: %s\n", i->where);
2653 printf(" What: %s\n", i->what);
2655 STRV_FOREACH(t, i->documentation)
2656 printf(" %*s %s\n", 9, t == i->documentation ? "Docs:" : "", *t);
2658 STRV_FOREACH_PAIR(t, t2, i->listen)
2659 printf(" %*s %s (%s)\n", 9, t == i->listen ? "Listen:" : "", *t2, *t);
2662 printf(" Accepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
2664 LIST_FOREACH(exec, p, i->exec) {
2665 _cleanup_free_ char *argv = NULL;
2668 /* Only show exited processes here */
2672 argv = strv_join(p->argv, " ");
2673 printf(" Process: %u %s=%s ", p->pid, p->name, strna(argv));
2675 good = is_clean_exit_lsb(p->code, p->status, NULL);
2677 on = ansi_highlight_red();
2678 off = ansi_highlight_off();
2682 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
2684 if (p->code == CLD_EXITED) {
2687 printf("status=%i", p->status);
2689 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
2694 printf("signal=%s", signal_to_string(p->status));
2696 printf(")%s\n", off);
2698 if (i->main_pid == p->pid &&
2699 i->start_timestamp == p->start_timestamp &&
2700 i->exit_timestamp == p->start_timestamp)
2701 /* Let's not show this twice */
2704 if (p->pid == i->control_pid)
2708 if (i->main_pid > 0 || i->control_pid > 0) {
2709 if (i->main_pid > 0) {
2710 printf(" Main PID: %u", (unsigned) i->main_pid);
2713 _cleanup_free_ char *comm = NULL;
2714 get_process_comm(i->main_pid, &comm);
2716 printf(" (%s)", comm);
2717 } else if (i->exit_code > 0) {
2718 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
2720 if (i->exit_code == CLD_EXITED) {
2723 printf("status=%i", i->exit_status);
2725 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
2730 printf("signal=%s", signal_to_string(i->exit_status));
2734 if (i->control_pid > 0)
2738 if (i->control_pid > 0) {
2739 _cleanup_free_ char *c = NULL;
2741 printf(" %8s: %u", i->main_pid ? "" : " Control", (unsigned) i->control_pid);
2743 get_process_comm(i->control_pid, &c);
2752 printf(" Status: \"%s\"\n", i->status_text);
2754 if (i->control_group &&
2755 (i->main_pid > 0 || i->control_pid > 0 || cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, i->control_group, false) == 0)) {
2758 printf(" CGroup: %s\n", i->control_group);
2760 if (arg_transport != TRANSPORT_SSH) {
2763 char prefix[] = " ";
2766 if (c > sizeof(prefix) - 1)
2767 c -= sizeof(prefix) - 1;
2771 if (i->main_pid > 0)
2772 extra[k++] = i->main_pid;
2774 if (i->control_pid > 0)
2775 extra[k++] = i->control_pid;
2777 show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, i->control_group, prefix,
2778 c, false, extra, k, flags);
2782 if (i->id && arg_transport != TRANSPORT_SSH) {
2784 show_journal_by_unit(stdout,
2788 i->inactive_exit_timestamp_monotonic,
2792 arg_scope == UNIT_FILE_SYSTEM,
2796 if (i->need_daemon_reload)
2797 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %sdaemon-reload' recommended.\n",
2798 ansi_highlight_red(),
2799 ansi_highlight_off(),
2800 arg_scope == UNIT_FILE_SYSTEM ? "" : "--user ");
2803 static void show_unit_help(UnitStatusInfo *i) {
2808 if (!i->documentation) {
2809 log_info("Documentation for %s not known.", i->id);
2813 STRV_FOREACH(p, i->documentation) {
2815 if (startswith(*p, "man:")) {
2818 _cleanup_free_ char *page = NULL, *section = NULL;
2819 const char *args[4] = { "man", NULL, NULL, NULL };
2824 if ((*p)[k-1] == ')')
2825 e = strrchr(*p, '(');
2828 page = strndup((*p) + 4, e - *p - 4);
2829 section = strndup(e + 1, *p + k - e - 2);
2830 if (!page || !section) {
2842 log_error("Failed to fork: %m");
2848 execvp(args[0], (char**) args);
2849 log_error("Failed to execute man: %m");
2850 _exit(EXIT_FAILURE);
2853 wait_for_terminate(pid, NULL);
2855 log_info("Can't show: %s", *p);
2859 static int status_property(const char *name, DBusMessageIter *iter, UnitStatusInfo *i) {
2865 switch (dbus_message_iter_get_arg_type(iter)) {
2867 case DBUS_TYPE_STRING: {
2870 dbus_message_iter_get_basic(iter, &s);
2873 if (streq(name, "Id"))
2875 else if (streq(name, "LoadState"))
2877 else if (streq(name, "ActiveState"))
2878 i->active_state = s;
2879 else if (streq(name, "SubState"))
2881 else if (streq(name, "Description"))
2883 else if (streq(name, "FragmentPath"))
2884 i->fragment_path = s;
2885 else if (streq(name, "SourcePath"))
2888 else if (streq(name, "DefaultControlGroup")) {
2890 e = startswith(s, SYSTEMD_CGROUP_CONTROLLER ":");
2892 i->control_group = e;
2895 else if (streq(name, "ControlGroup"))
2896 i->control_group = s;
2897 else if (streq(name, "StatusText"))
2899 else if (streq(name, "PIDFile"))
2901 else if (streq(name, "SysFSPath"))
2903 else if (streq(name, "Where"))
2905 else if (streq(name, "What"))
2907 else if (streq(name, "Following"))
2909 else if (streq(name, "UnitFileState"))
2910 i->unit_file_state = s;
2911 else if (streq(name, "Result"))
2918 case DBUS_TYPE_BOOLEAN: {
2921 dbus_message_iter_get_basic(iter, &b);
2923 if (streq(name, "Accept"))
2925 else if (streq(name, "NeedDaemonReload"))
2926 i->need_daemon_reload = b;
2927 else if (streq(name, "ConditionResult"))
2928 i->condition_result = b;
2933 case DBUS_TYPE_UINT32: {
2936 dbus_message_iter_get_basic(iter, &u);
2938 if (streq(name, "MainPID")) {
2940 i->main_pid = (pid_t) u;
2943 } else if (streq(name, "ControlPID"))
2944 i->control_pid = (pid_t) u;
2945 else if (streq(name, "ExecMainPID")) {
2947 i->main_pid = (pid_t) u;
2948 } else if (streq(name, "NAccepted"))
2950 else if (streq(name, "NConnections"))
2951 i->n_connections = u;
2956 case DBUS_TYPE_INT32: {
2959 dbus_message_iter_get_basic(iter, &j);
2961 if (streq(name, "ExecMainCode"))
2962 i->exit_code = (int) j;
2963 else if (streq(name, "ExecMainStatus"))
2964 i->exit_status = (int) j;
2969 case DBUS_TYPE_UINT64: {
2972 dbus_message_iter_get_basic(iter, &u);
2974 if (streq(name, "ExecMainStartTimestamp"))
2975 i->start_timestamp = (usec_t) u;
2976 else if (streq(name, "ExecMainExitTimestamp"))
2977 i->exit_timestamp = (usec_t) u;
2978 else if (streq(name, "ActiveEnterTimestamp"))
2979 i->active_enter_timestamp = (usec_t) u;
2980 else if (streq(name, "InactiveEnterTimestamp"))
2981 i->inactive_enter_timestamp = (usec_t) u;
2982 else if (streq(name, "InactiveExitTimestamp"))
2983 i->inactive_exit_timestamp = (usec_t) u;
2984 else if (streq(name, "InactiveExitTimestampMonotonic"))
2985 i->inactive_exit_timestamp_monotonic = (usec_t) u;
2986 else if (streq(name, "ActiveExitTimestamp"))
2987 i->active_exit_timestamp = (usec_t) u;
2988 else if (streq(name, "ConditionTimestamp"))
2989 i->condition_timestamp = (usec_t) u;
2994 case DBUS_TYPE_ARRAY: {
2996 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
2997 startswith(name, "Exec")) {
2998 DBusMessageIter sub;
3000 dbus_message_iter_recurse(iter, &sub);
3001 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3002 ExecStatusInfo *info;
3005 info = new0(ExecStatusInfo, 1);
3009 info->name = strdup(name);
3015 r = exec_status_info_deserialize(&sub, info);
3021 LIST_PREPEND(ExecStatusInfo, exec, i->exec, info);
3023 dbus_message_iter_next(&sub);
3026 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
3027 streq(name, "Listen")) {
3028 DBusMessageIter sub, sub2;
3030 dbus_message_iter_recurse(iter, &sub);
3031 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3032 const char *type, *path;
3034 dbus_message_iter_recurse(&sub, &sub2);
3036 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
3037 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0) {
3040 r = strv_extend(&i->listen, type);
3043 r = strv_extend(&i->listen, path);
3048 dbus_message_iter_next(&sub);
3053 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
3054 streq(name, "DropInPaths")) {
3055 int r = bus_parse_strv_iter(iter, &i->dropin_paths);
3059 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
3060 streq(name, "Documentation")) {
3062 DBusMessageIter sub;
3064 dbus_message_iter_recurse(iter, &sub);
3065 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING) {
3069 dbus_message_iter_get_basic(&sub, &s);
3071 r = strv_extend(&i->documentation, s);
3075 dbus_message_iter_next(&sub);
3078 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
3079 streq(name, "Conditions")) {
3080 DBusMessageIter sub, sub2;
3082 dbus_message_iter_recurse(iter, &sub);
3083 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3084 const char *cond, *param;
3085 dbus_bool_t trigger, negate;
3088 dbus_message_iter_recurse(&sub, &sub2);
3091 if(bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &cond, true) >= 0 &&
3092 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &trigger, true) >= 0 &&
3093 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &negate, true) >= 0 &&
3094 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, ¶m, true) >= 0 &&
3095 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &state, false) >= 0) {
3096 log_debug("%s %d %d %s %d", cond, trigger, negate, param, state);
3097 if (state < 0 && (!trigger || !i->failed_condition)) {
3098 i->failed_condition = cond;
3099 i->failed_condition_trigger = trigger;
3100 i->failed_condition_negate = negate;
3101 i->failed_condition_param = param;
3105 dbus_message_iter_next(&sub);
3112 case DBUS_TYPE_STRUCT: {
3114 if (streq(name, "LoadError")) {
3115 DBusMessageIter sub;
3116 const char *n, *message;
3119 dbus_message_iter_recurse(iter, &sub);
3121 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &n, true);
3125 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &message, false);
3129 if (!isempty(message))
3130 i->load_error = message;
3140 static int print_property(const char *name, DBusMessageIter *iter) {
3144 /* This is a low-level property printer, see
3145 * print_status_info() for the nicer output */
3147 if (arg_properties && !strv_find(arg_properties, name))
3150 switch (dbus_message_iter_get_arg_type(iter)) {
3152 case DBUS_TYPE_STRUCT: {
3153 DBusMessageIter sub;
3154 dbus_message_iter_recurse(iter, &sub);
3156 if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32 && streq(name, "Job")) {
3159 dbus_message_iter_get_basic(&sub, &u);
3162 printf("%s=%u\n", name, (unsigned) u);
3164 printf("%s=\n", name);
3167 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "Unit")) {
3170 dbus_message_iter_get_basic(&sub, &s);
3172 if (arg_all || s[0])
3173 printf("%s=%s\n", name, s);
3176 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "LoadError")) {
3177 const char *a = NULL, *b = NULL;
3179 if (bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &a, true) >= 0)
3180 bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &b, false);
3182 if (arg_all || !isempty(a) || !isempty(b))
3183 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
3191 case DBUS_TYPE_ARRAY:
3193 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "EnvironmentFiles")) {
3194 DBusMessageIter sub, sub2;
3196 dbus_message_iter_recurse(iter, &sub);
3197 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3201 dbus_message_iter_recurse(&sub, &sub2);
3203 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
3204 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) >= 0)
3205 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
3207 dbus_message_iter_next(&sub);
3212 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Paths")) {
3213 DBusMessageIter sub, sub2;
3215 dbus_message_iter_recurse(iter, &sub);
3217 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3218 const char *type, *path;
3220 dbus_message_iter_recurse(&sub, &sub2);
3222 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
3223 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
3224 printf("%s=%s\n", type, path);
3226 dbus_message_iter_next(&sub);
3231 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Listen")) {
3232 DBusMessageIter sub, sub2;
3234 dbus_message_iter_recurse(iter, &sub);
3235 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3236 const char *type, *path;
3238 dbus_message_iter_recurse(&sub, &sub2);
3240 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
3241 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
3242 printf("Listen%s=%s\n", type, path);
3244 dbus_message_iter_next(&sub);
3249 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Timers")) {
3250 DBusMessageIter sub, sub2;
3252 dbus_message_iter_recurse(iter, &sub);
3253 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3255 uint64_t value, next_elapse;
3257 dbus_message_iter_recurse(&sub, &sub2);
3259 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &base, true) >= 0 &&
3260 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &value, true) >= 0 &&
3261 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &next_elapse, false) >= 0) {
3262 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
3264 printf("%s={ value=%s ; next_elapse=%s }\n",
3266 format_timespan(timespan1, sizeof(timespan1), value, 0),
3267 format_timespan(timespan2, sizeof(timespan2), next_elapse, 0));
3270 dbus_message_iter_next(&sub);
3275 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && startswith(name, "Exec")) {
3276 DBusMessageIter sub;
3278 dbus_message_iter_recurse(iter, &sub);
3279 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3280 ExecStatusInfo info = {};
3282 if (exec_status_info_deserialize(&sub, &info) >= 0) {
3283 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
3284 _cleanup_free_ char *t;
3286 t = strv_join(info.argv, " ");
3288 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
3292 yes_no(info.ignore),
3293 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
3294 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
3295 (unsigned) info. pid,
3296 sigchld_code_to_string(info.code),
3298 info.code == CLD_EXITED ? "" : "/",
3299 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
3303 strv_free(info.argv);
3305 dbus_message_iter_next(&sub);
3310 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "DeviceAllow")) {
3311 DBusMessageIter sub, sub2;
3313 dbus_message_iter_recurse(iter, &sub);
3314 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3315 const char *path, *rwm;
3317 dbus_message_iter_recurse(&sub, &sub2);
3319 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
3320 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &rwm, false) >= 0)
3321 printf("%s=%s %s\n", name, strna(path), strna(rwm));
3323 dbus_message_iter_next(&sub);
3327 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "BlockIODeviceWeight")) {
3328 DBusMessageIter sub, sub2;
3330 dbus_message_iter_recurse(iter, &sub);
3331 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3335 dbus_message_iter_recurse(&sub, &sub2);
3337 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
3338 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &weight, false) >= 0)
3339 printf("%s=%s %" PRIu64 "\n", name, strna(path), weight);
3341 dbus_message_iter_next(&sub);
3345 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && (streq(name, "BlockIOReadBandwidth") || streq(name, "BlockIOWriteBandwidth"))) {
3346 DBusMessageIter sub, sub2;
3348 dbus_message_iter_recurse(iter, &sub);
3349 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3353 dbus_message_iter_recurse(&sub, &sub2);
3355 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
3356 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &bandwidth, false) >= 0)
3357 printf("%s=%s %" PRIu64 "\n", name, strna(path), bandwidth);
3359 dbus_message_iter_next(&sub);
3368 if (generic_print_property(name, iter, arg_all) > 0)
3372 printf("%s=[unprintable]\n", name);
3377 static int show_one(const char *verb,
3378 DBusConnection *bus,
3380 bool show_properties,
3383 _cleanup_free_ DBusMessage *reply = NULL;
3384 const char *interface = "";
3386 DBusMessageIter iter, sub, sub2, sub3;
3387 UnitStatusInfo info = {};
3393 r = bus_method_call_with_reply(
3395 "org.freedesktop.systemd1",
3397 "org.freedesktop.DBus.Properties",
3401 DBUS_TYPE_STRING, &interface,
3406 if (!dbus_message_iter_init(reply, &iter) ||
3407 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3408 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
3409 log_error("Failed to parse reply.");
3413 dbus_message_iter_recurse(&iter, &sub);
3420 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
3423 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_DICT_ENTRY);
3424 dbus_message_iter_recurse(&sub, &sub2);
3426 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
3427 dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
3428 log_error("Failed to parse reply.");
3432 dbus_message_iter_recurse(&sub2, &sub3);
3434 if (show_properties)
3435 r = print_property(name, &sub3);
3437 r = status_property(name, &sub3, &info);
3439 log_error("Failed to parse reply.");
3443 dbus_message_iter_next(&sub);
3448 if (!show_properties) {
3449 if (streq(verb, "help"))
3450 show_unit_help(&info);
3452 print_status_info(&info, ellipsized);
3455 strv_free(info.documentation);
3456 strv_free(info.dropin_paths);
3457 strv_free(info.listen);
3459 if (!streq_ptr(info.active_state, "active") &&
3460 !streq_ptr(info.active_state, "reloading") &&
3461 streq(verb, "status")) {
3462 /* According to LSB: "program not running" */
3463 /* 0: program is running or service is OK
3464 * 1: program is dead and /var/run pid file exists
3465 * 2: program is dead and /var/lock lock file exists
3466 * 3: program is not running
3467 * 4: program or service status is unknown
3469 if (info.pid_file && access(info.pid_file, F_OK) == 0)
3475 while ((p = info.exec)) {
3476 LIST_REMOVE(ExecStatusInfo, exec, info.exec, p);
3477 exec_status_info_free(p);
3483 static int show_one_by_pid(const char *verb,
3484 DBusConnection *bus,
3488 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3489 const char *path = NULL;
3490 _cleanup_dbus_error_free_ DBusError error;
3493 dbus_error_init(&error);
3495 r = bus_method_call_with_reply(
3497 "org.freedesktop.systemd1",
3498 "/org/freedesktop/systemd1",
3499 "org.freedesktop.systemd1.Manager",
3503 DBUS_TYPE_UINT32, &pid,
3508 if (!dbus_message_get_args(reply, &error,
3509 DBUS_TYPE_OBJECT_PATH, &path,
3510 DBUS_TYPE_INVALID)) {
3511 log_error("Failed to parse reply: %s", bus_error_message(&error));
3515 r = show_one(verb, bus, path, false, new_line, ellipsized);
3519 static int show_all(const char* verb,
3520 DBusConnection *bus,
3521 bool show_properties,
3524 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3525 _cleanup_free_ struct unit_info *unit_infos = NULL;
3527 const struct unit_info *u;
3530 r = get_unit_list(bus, &reply, &unit_infos, &c);
3534 qsort(unit_infos, c, sizeof(struct unit_info), compare_unit_info);
3536 for (u = unit_infos; u < unit_infos + c; u++) {
3537 _cleanup_free_ char *p = NULL;
3539 if (!output_show_unit(u))
3542 p = unit_dbus_path_from_name(u->id);
3546 printf("%s -> '%s'\n", u->id, p);
3548 r = show_one(verb, bus, p, show_properties, new_line, ellipsized);
3556 static int show(DBusConnection *bus, char **args) {
3558 bool show_properties, show_status, new_line = false;
3560 bool ellipsized = false;
3565 show_properties = streq(args[0], "show");
3566 show_status = streq(args[0], "status");
3568 if (show_properties)
3569 pager_open_if_enabled();
3571 /* If no argument is specified inspect the manager itself */
3573 if (show_properties && strv_length(args) <= 1)
3574 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line, &ellipsized);
3576 if (show_status && strv_length(args) <= 1)
3577 ret = show_all(args[0], bus, false, &new_line, &ellipsized);
3579 STRV_FOREACH(name, args+1) {
3582 if (safe_atou32(*name, &id) < 0) {
3583 _cleanup_free_ char *p = NULL, *n = NULL;
3584 /* Interpret as unit name */
3586 n = unit_name_mangle(*name);
3590 p = unit_dbus_path_from_name(n);
3594 r = show_one(args[0], bus, p, show_properties, &new_line, &ellipsized);
3598 } else if (show_properties) {
3599 _cleanup_free_ char *p = NULL;
3601 /* Interpret as job id */
3602 if (asprintf(&p, "/org/freedesktop/systemd1/job/%u", id) < 0)
3605 r = show_one(args[0], bus, p, show_properties, &new_line, &ellipsized);
3610 /* Interpret as PID */
3611 r = show_one_by_pid(args[0], bus, id, &new_line, &ellipsized);
3617 if (ellipsized && !arg_quiet)
3618 printf("Hint: Some lines were ellipsized, use -l to show in full.\n");
3623 static int append_assignment(DBusMessageIter *iter, const char *assignment) {
3626 DBusMessageIter sub;
3632 eq = strchr(assignment, '=');
3634 log_error("Not an assignment: %s", assignment);
3638 field = strndupa(assignment, eq - assignment);
3641 if (!dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &field))
3644 if (streq(field, "CPUAccounting") ||
3645 streq(field, "MemoryAccounting") ||
3646 streq(field, "BlockIOAccounting")) {
3649 r = parse_boolean(eq);
3651 log_error("Failed to parse boolean assignment %s.", assignment);
3656 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "b", &sub) ||
3657 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_BOOLEAN, &b))
3660 } else if (streq(field, "MemoryLimit") || streq(field, "MemorySoftLimit")) {
3664 r = parse_bytes(eq, &bytes);
3666 log_error("Failed to parse bytes specification %s", assignment);
3671 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "t", &sub) ||
3672 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_UINT64, &u))
3675 } else if (streq(field, "CPUShares") || streq(field, "BlockIOWeight")) {
3678 r = safe_atou64(eq, &u);
3680 log_error("Failed to parse %s value %s.", field, eq);
3684 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "t", &sub) ||
3685 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_UINT64, &u))
3688 } else if (streq(field, "DevicePolicy")) {
3690 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "s", &sub) ||
3691 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &eq))
3694 } else if (streq(field, "DeviceAllow")) {
3695 DBusMessageIter sub2;
3697 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "a(ss)", &sub) ||
3698 !dbus_message_iter_open_container(&sub, DBUS_TYPE_ARRAY, "(ss)", &sub2))
3702 const char *path, *rwm;
3703 DBusMessageIter sub3;
3706 e = strchr(eq, ' ');
3708 path = strndupa(eq, e - eq);
3715 if (!path_startswith(path, "/dev")) {
3716 log_error("%s is not a device file in /dev.", path);
3720 if (!dbus_message_iter_open_container(&sub2, DBUS_TYPE_STRUCT, NULL, &sub3) ||
3721 !dbus_message_iter_append_basic(&sub3, DBUS_TYPE_STRING, &path) ||
3722 !dbus_message_iter_append_basic(&sub3, DBUS_TYPE_STRING, &rwm) ||
3723 !dbus_message_iter_close_container(&sub2, &sub3))
3727 if (!dbus_message_iter_close_container(&sub, &sub2))
3730 } else if (streq(field, "BlockIOReadBandwidth") || streq(field, "BlockIOWriteBandwidth")) {
3731 DBusMessageIter sub2;
3733 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "a(st)", &sub) ||
3734 !dbus_message_iter_open_container(&sub, DBUS_TYPE_ARRAY, "(st)", &sub2))
3738 const char *path, *bandwidth;
3739 DBusMessageIter sub3;
3744 e = strchr(eq, ' ');
3746 path = strndupa(eq, e - eq);
3749 log_error("Failed to parse %s value %s.", field, eq);
3753 if (!path_startswith(path, "/dev")) {
3754 log_error("%s is not a device file in /dev.", path);
3758 r = parse_bytes(bandwidth, &bytes);
3760 log_error("Failed to parse byte value %s.", bandwidth);
3764 u = (uint64_t) bytes;
3766 if (!dbus_message_iter_open_container(&sub2, DBUS_TYPE_STRUCT, NULL, &sub3) ||
3767 !dbus_message_iter_append_basic(&sub3, DBUS_TYPE_STRING, &path) ||
3768 !dbus_message_iter_append_basic(&sub3, DBUS_TYPE_UINT64, &u) ||
3769 !dbus_message_iter_close_container(&sub2, &sub3))
3773 if (!dbus_message_iter_close_container(&sub, &sub2))
3776 } else if (streq(field, "BlockIODeviceWeight")) {
3777 DBusMessageIter sub2;
3779 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "a(st)", &sub) ||
3780 !dbus_message_iter_open_container(&sub, DBUS_TYPE_ARRAY, "(st)", &sub2))
3784 const char *path, *weight;
3785 DBusMessageIter sub3;
3789 e = strchr(eq, ' ');
3791 path = strndupa(eq, e - eq);
3794 log_error("Failed to parse %s value %s.", field, eq);
3798 if (!path_startswith(path, "/dev")) {
3799 log_error("%s is not a device file in /dev.", path);
3803 r = safe_atou64(weight, &u);
3805 log_error("Failed to parse %s value %s.", field, weight);
3808 if (!dbus_message_iter_open_container(&sub2, DBUS_TYPE_STRUCT, NULL, &sub3) ||
3809 !dbus_message_iter_append_basic(&sub3, DBUS_TYPE_STRING, &path) ||
3810 !dbus_message_iter_append_basic(&sub3, DBUS_TYPE_UINT64, &u) ||
3811 !dbus_message_iter_close_container(&sub2, &sub3))
3815 if (!dbus_message_iter_close_container(&sub, &sub2))
3819 log_error("Unknown assignment %s.", assignment);
3823 if (!dbus_message_iter_close_container(iter, &sub))
3829 static int set_property(DBusConnection *bus, char **args) {
3831 _cleanup_free_ DBusMessage *m = NULL, *reply = NULL;
3832 DBusMessageIter iter, sub;
3833 dbus_bool_t runtime;
3838 dbus_error_init(&error);
3840 m = dbus_message_new_method_call(
3841 "org.freedesktop.systemd1",
3842 "/org/freedesktop/systemd1",
3843 "org.freedesktop.systemd1.Manager",
3844 "SetUnitProperties");
3848 dbus_message_iter_init_append(m, &iter);
3850 runtime = arg_runtime;
3852 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &args[1]) ||
3853 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &runtime) ||
3854 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(sv)", &sub))
3857 STRV_FOREACH(i, args + 2) {
3858 DBusMessageIter sub2;
3860 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
3863 r = append_assignment(&sub2, *i);
3867 if (!dbus_message_iter_close_container(&sub, &sub2))
3872 if (!dbus_message_iter_close_container(&iter, &sub))
3875 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3877 log_error("Failed to issue method call: %s", bus_error_message(&error));
3878 dbus_error_free(&error);
3885 static int snapshot(DBusConnection *bus, char **args) {
3886 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3889 dbus_bool_t cleanup = FALSE;
3890 DBusMessageIter iter, sub;
3893 *interface = "org.freedesktop.systemd1.Unit",
3895 _cleanup_free_ char *n = NULL;
3897 dbus_error_init(&error);
3899 if (strv_length(args) > 1)
3900 n = unit_name_mangle_with_suffix(args[1], ".snapshot");
3906 r = bus_method_call_with_reply(
3908 "org.freedesktop.systemd1",
3909 "/org/freedesktop/systemd1",
3910 "org.freedesktop.systemd1.Manager",
3914 DBUS_TYPE_STRING, &n,
3915 DBUS_TYPE_BOOLEAN, &cleanup,
3920 if (!dbus_message_get_args(reply, &error,
3921 DBUS_TYPE_OBJECT_PATH, &path,
3922 DBUS_TYPE_INVALID)) {
3923 log_error("Failed to parse reply: %s", bus_error_message(&error));
3924 dbus_error_free(&error);
3928 dbus_message_unref(reply);
3931 r = bus_method_call_with_reply (
3933 "org.freedesktop.systemd1",
3935 "org.freedesktop.DBus.Properties",
3939 DBUS_TYPE_STRING, &interface,
3940 DBUS_TYPE_STRING, &property,
3945 if (!dbus_message_iter_init(reply, &iter) ||
3946 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3947 log_error("Failed to parse reply.");
3951 dbus_message_iter_recurse(&iter, &sub);
3953 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
3954 log_error("Failed to parse reply.");
3958 dbus_message_iter_get_basic(&sub, &id);
3966 static int delete_snapshot(DBusConnection *bus, char **args) {
3971 STRV_FOREACH(name, args+1) {
3972 _cleanup_free_ char *n = NULL;
3975 n = unit_name_mangle_with_suffix(*name, ".snapshot");
3979 r = bus_method_call_with_reply(
3981 "org.freedesktop.systemd1",
3982 "/org/freedesktop/systemd1",
3983 "org.freedesktop.systemd1.Manager",
3987 DBUS_TYPE_STRING, &n,
3996 static int daemon_reload(DBusConnection *bus, char **args) {
4001 if (arg_action == ACTION_RELOAD)
4003 else if (arg_action == ACTION_REEXEC)
4004 method = "Reexecute";
4006 assert(arg_action == ACTION_SYSTEMCTL);
4009 streq(args[0], "clear-jobs") ||
4010 streq(args[0], "cancel") ? "ClearJobs" :
4011 streq(args[0], "daemon-reexec") ? "Reexecute" :
4012 streq(args[0], "reset-failed") ? "ResetFailed" :
4013 streq(args[0], "halt") ? "Halt" :
4014 streq(args[0], "poweroff") ? "PowerOff" :
4015 streq(args[0], "reboot") ? "Reboot" :
4016 streq(args[0], "kexec") ? "KExec" :
4017 streq(args[0], "exit") ? "Exit" :
4018 /* "daemon-reload" */ "Reload";
4021 r = bus_method_call_with_reply(
4023 "org.freedesktop.systemd1",
4024 "/org/freedesktop/systemd1",
4025 "org.freedesktop.systemd1.Manager",
4031 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
4032 /* There's always a fallback possible for
4033 * legacy actions. */
4035 else if ((r == -ETIMEDOUT || r == -ECONNRESET) && streq(method, "Reexecute"))
4036 /* On reexecution, we expect a disconnect, not a
4040 log_error("Failed to issue method call: %s", bus_error_message(&error));
4042 dbus_error_free(&error);
4046 static int reset_failed(DBusConnection *bus, char **args) {
4050 if (strv_length(args) <= 1)
4051 return daemon_reload(bus, args);
4053 STRV_FOREACH(name, args+1) {
4054 _cleanup_free_ char *n;
4056 n = unit_name_mangle(*name);
4060 r = bus_method_call_with_reply(
4062 "org.freedesktop.systemd1",
4063 "/org/freedesktop/systemd1",
4064 "org.freedesktop.systemd1.Manager",
4068 DBUS_TYPE_STRING, &n,
4077 static int show_enviroment(DBusConnection *bus, char **args) {
4078 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
4079 DBusMessageIter iter, sub, sub2;
4082 *interface = "org.freedesktop.systemd1.Manager",
4083 *property = "Environment";
4085 pager_open_if_enabled();
4087 r = bus_method_call_with_reply(
4089 "org.freedesktop.systemd1",
4090 "/org/freedesktop/systemd1",
4091 "org.freedesktop.DBus.Properties",
4095 DBUS_TYPE_STRING, &interface,
4096 DBUS_TYPE_STRING, &property,
4101 if (!dbus_message_iter_init(reply, &iter) ||
4102 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
4103 log_error("Failed to parse reply.");
4107 dbus_message_iter_recurse(&iter, &sub);
4109 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_ARRAY ||
4110 dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_STRING) {
4111 log_error("Failed to parse reply.");
4115 dbus_message_iter_recurse(&sub, &sub2);
4117 while (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_INVALID) {
4120 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
4121 log_error("Failed to parse reply.");
4125 dbus_message_iter_get_basic(&sub2, &text);
4128 dbus_message_iter_next(&sub2);
4134 static int switch_root(DBusConnection *bus, char **args) {
4137 _cleanup_free_ char *init = NULL;
4139 l = strv_length(args);
4140 if (l < 2 || l > 3) {
4141 log_error("Wrong number of arguments.");
4148 init = strdup(args[2]);
4150 parse_env_file("/proc/cmdline", WHITESPACE,
4160 log_debug("switching root - root: %s; init: %s", root, init);
4162 return bus_method_call_with_reply(
4164 "org.freedesktop.systemd1",
4165 "/org/freedesktop/systemd1",
4166 "org.freedesktop.systemd1.Manager",
4170 DBUS_TYPE_STRING, &root,
4171 DBUS_TYPE_STRING, &init,
4175 static int set_environment(DBusConnection *bus, char **args) {
4176 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
4179 DBusMessageIter iter;
4185 dbus_error_init(&error);
4187 method = streq(args[0], "set-environment")
4189 : "UnsetEnvironment";
4191 m = dbus_message_new_method_call(
4192 "org.freedesktop.systemd1",
4193 "/org/freedesktop/systemd1",
4194 "org.freedesktop.systemd1.Manager",
4199 dbus_message_iter_init_append(m, &iter);
4201 r = bus_append_strv_iter(&iter, args + 1);
4205 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
4207 log_error("Failed to issue method call: %s", bus_error_message(&error));
4208 dbus_error_free(&error);
4215 static int enable_sysv_units(char **args) {
4218 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
4219 const char *verb = args[0];
4220 unsigned f = 1, t = 1;
4221 LookupPaths paths = {};
4223 if (arg_scope != UNIT_FILE_SYSTEM)
4226 if (!streq(verb, "enable") &&
4227 !streq(verb, "disable") &&
4228 !streq(verb, "is-enabled"))
4231 /* Processes all SysV units, and reshuffles the array so that
4232 * afterwards only the native units remain */
4234 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, NULL, NULL, NULL);
4239 for (f = 1; args[f]; f++) {
4241 _cleanup_free_ char *p = NULL, *q = NULL;
4242 bool found_native = false, found_sysv;
4244 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
4252 if (!endswith(name, ".service"))
4255 if (path_is_absolute(name))
4258 STRV_FOREACH(k, paths.unit_path) {
4259 if (!isempty(arg_root))
4260 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
4262 asprintf(&p, "%s/%s", *k, name);
4269 found_native = access(p, F_OK) >= 0;
4280 if (!isempty(arg_root))
4281 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
4283 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
4289 p[strlen(p) - sizeof(".service") + 1] = 0;
4290 found_sysv = access(p, F_OK) >= 0;
4295 /* Mark this entry, so that we don't try enabling it as native unit */
4296 args[f] = (char*) "";
4298 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
4300 if (!isempty(arg_root))
4301 argv[c++] = q = strappend("--root=", arg_root);
4303 argv[c++] = path_get_file_name(p);
4305 streq(verb, "enable") ? "on" :
4306 streq(verb, "disable") ? "off" : "--level=5";
4309 l = strv_join((char**)argv, " ");
4315 log_info("Executing %s", l);
4320 log_error("Failed to fork: %m");
4323 } else if (pid == 0) {
4326 execv(argv[0], (char**) argv);
4327 _exit(EXIT_FAILURE);
4330 j = wait_for_terminate(pid, &status);
4332 log_error("Failed to wait for child: %s", strerror(-r));
4337 if (status.si_code == CLD_EXITED) {
4338 if (streq(verb, "is-enabled")) {
4339 if (status.si_status == 0) {
4348 } else if (status.si_status != 0) {
4359 lookup_paths_free(&paths);
4361 /* Drop all SysV units */
4362 for (f = 1, t = 1; args[f]; f++) {
4364 if (isempty(args[f]))
4367 args[t++] = args[f];
4376 static int mangle_names(char **original_names, char ***mangled_names) {
4377 char **i, **l, **name;
4379 l = new(char*, strv_length(original_names) + 1);
4384 STRV_FOREACH(name, original_names) {
4386 /* When enabling units qualified path names are OK,
4387 * too, hence allow them explicitly. */
4392 *i = unit_name_mangle(*name);
4408 static int enable_unit(DBusConnection *bus, char **args) {
4409 const char *verb = args[0];
4410 UnitFileChange *changes = NULL;
4411 unsigned n_changes = 0, i;
4412 int carries_install_info = -1;
4413 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
4415 _cleanup_dbus_error_free_ DBusError error;
4416 _cleanup_strv_free_ char **mangled_names = NULL;
4418 dbus_error_init(&error);
4420 r = enable_sysv_units(args);
4427 r = mangle_names(args+1, &mangled_names);
4431 if (!bus || avoid_bus()) {
4432 if (streq(verb, "enable")) {
4433 r = unit_file_enable(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4434 carries_install_info = r;
4435 } else if (streq(verb, "disable"))
4436 r = unit_file_disable(arg_scope, arg_runtime, arg_root, mangled_names, &changes, &n_changes);
4437 else if (streq(verb, "reenable")) {
4438 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4439 carries_install_info = r;
4440 } else if (streq(verb, "link"))
4441 r = unit_file_link(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4442 else if (streq(verb, "preset")) {
4443 r = unit_file_preset(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4444 carries_install_info = r;
4445 } else if (streq(verb, "mask"))
4446 r = unit_file_mask(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4447 else if (streq(verb, "unmask"))
4448 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, mangled_names, &changes, &n_changes);
4449 else if (streq(verb, "set-default"))
4450 r = unit_file_set_default(arg_scope, arg_root, args[1], &changes, &n_changes);
4452 assert_not_reached("Unknown verb");
4455 log_error("Operation failed: %s", strerror(-r));
4460 for (i = 0; i < n_changes; i++) {
4461 if (changes[i].type == UNIT_FILE_SYMLINK)
4462 log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
4464 log_info("rm '%s'", changes[i].path);
4471 bool send_force = true, expect_carries_install_info = false;
4473 DBusMessageIter iter, sub, sub2;
4475 if (streq(verb, "enable")) {
4476 method = "EnableUnitFiles";
4477 expect_carries_install_info = true;
4478 } else if (streq(verb, "disable")) {
4479 method = "DisableUnitFiles";
4481 } else if (streq(verb, "reenable")) {
4482 method = "ReenableUnitFiles";
4483 expect_carries_install_info = true;
4484 } else if (streq(verb, "link"))
4485 method = "LinkUnitFiles";
4486 else if (streq(verb, "preset")) {
4487 method = "PresetUnitFiles";
4488 expect_carries_install_info = true;
4489 } else if (streq(verb, "mask"))
4490 method = "MaskUnitFiles";
4491 else if (streq(verb, "unmask")) {
4492 method = "UnmaskUnitFiles";
4494 } else if (streq(verb, "set-default")) {
4495 method = "SetDefaultTarget";
4497 assert_not_reached("Unknown verb");
4499 m = dbus_message_new_method_call(
4500 "org.freedesktop.systemd1",
4501 "/org/freedesktop/systemd1",
4502 "org.freedesktop.systemd1.Manager",
4509 dbus_message_iter_init_append(m, &iter);
4511 r = bus_append_strv_iter(&iter, mangled_names);
4513 log_error("Failed to append unit files.");
4518 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &a)) {
4519 log_error("Failed to append runtime boolean.");
4527 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b)) {
4528 log_error("Failed to append force boolean.");
4534 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
4536 log_error("Failed to issue method call: %s", bus_error_message(&error));
4541 if (!dbus_message_iter_init(reply, &iter)) {
4542 log_error("Failed to initialize iterator.");
4546 if (expect_carries_install_info) {
4547 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &b, true);
4549 log_error("Failed to parse reply.");
4553 carries_install_info = b;
4556 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
4557 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
4558 log_error("Failed to parse reply.");
4563 dbus_message_iter_recurse(&iter, &sub);
4564 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
4565 const char *type, *path, *source;
4567 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
4568 log_error("Failed to parse reply.");
4573 dbus_message_iter_recurse(&sub, &sub2);
4575 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
4576 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
4577 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &source, false) < 0) {
4578 log_error("Failed to parse reply.");
4584 if (streq(type, "symlink"))
4585 log_info("ln -s '%s' '%s'", source, path);
4587 log_info("rm '%s'", path);
4590 dbus_message_iter_next(&sub);
4593 /* Try to reload if enabeld */
4595 r = daemon_reload(bus, args);
4598 if (carries_install_info == 0)
4599 log_warning("The unit files have no [Install] section. They are not meant to be enabled\n"
4600 "using systemctl.\n"
4601 "Possible reasons for having this kind of units are:\n"
4602 "1) A unit may be statically enabled by being symlinked from another unit's\n"
4603 " .wants/ or .requires/ directory.\n"
4604 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
4605 " a requirement dependency on it.\n"
4606 "3) A unit may be started when needed via activation (socket, path, timer,\n"
4607 " D-Bus, udev, scripted systemctl call, ...).\n");
4610 unit_file_changes_free(changes, n_changes);
4615 static int unit_is_enabled(DBusConnection *bus, char **args) {
4616 _cleanup_dbus_error_free_ DBusError error;
4618 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
4623 dbus_error_init(&error);
4625 r = enable_sysv_units(args);
4631 if (!bus || avoid_bus()) {
4633 STRV_FOREACH(name, args+1) {
4634 UnitFileState state;
4636 n = unit_name_mangle(*name);
4640 state = unit_file_get_state(arg_scope, arg_root, n);
4647 if (state == UNIT_FILE_ENABLED ||
4648 state == UNIT_FILE_ENABLED_RUNTIME ||
4649 state == UNIT_FILE_STATIC)
4653 puts(unit_file_state_to_string(state));
4657 STRV_FOREACH(name, args+1) {
4660 n = unit_name_mangle(*name);
4664 r = bus_method_call_with_reply (
4666 "org.freedesktop.systemd1",
4667 "/org/freedesktop/systemd1",
4668 "org.freedesktop.systemd1.Manager",
4672 DBUS_TYPE_STRING, &n,
4680 if (!dbus_message_get_args(reply, &error,
4681 DBUS_TYPE_STRING, &s,
4682 DBUS_TYPE_INVALID)) {
4683 log_error("Failed to parse reply: %s", bus_error_message(&error));
4687 dbus_message_unref(reply);
4690 if (streq(s, "enabled") ||
4691 streq(s, "enabled-runtime") ||
4700 return enabled ? 0 : 1;
4703 static int systemctl_help(void) {
4705 pager_open_if_enabled();
4707 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
4708 "Query or send control commands to the systemd manager.\n\n"
4709 " -h --help Show this help\n"
4710 " --version Show package version\n"
4711 " -t --type=TYPE List only units of a particular type\n"
4712 " --state=STATE List only units with particular LOAD or SUB or ACTIVE state\n"
4713 " -p --property=NAME Show only properties by this name\n"
4714 " -a --all Show all loaded units/properties, including dead/empty\n"
4715 " ones. To list all units installed on the system, use\n"
4716 " the 'list-unit-files' command instead.\n"
4717 " --reverse Show reverse dependencies with 'list-dependencies'\n"
4718 " -l --full Don't ellipsize unit names on output\n"
4719 " --fail When queueing a new job, fail if conflicting jobs are\n"
4721 " --irreversible When queueing a new job, make sure it cannot be implicitly\n"
4723 " --ignore-dependencies\n"
4724 " When queueing a new job, ignore all its dependencies\n"
4725 " --show-types When showing sockets, explicitly show their type\n"
4726 " -i --ignore-inhibitors\n"
4727 " When shutting down or sleeping, ignore inhibitors\n"
4728 " --kill-who=WHO Who to send signal to\n"
4729 " -s --signal=SIGNAL Which signal to send\n"
4730 " -H --host=[USER@]HOST\n"
4731 " Show information for remote host\n"
4732 " -P --privileged Acquire privileges before execution\n"
4733 " -q --quiet Suppress output\n"
4734 " --no-block Do not wait until operation finished\n"
4735 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4736 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
4738 " --no-legend Do not print a legend (column headers and hints)\n"
4739 " --no-pager Do not pipe output into a pager\n"
4740 " --no-ask-password\n"
4741 " Do not ask for system passwords\n"
4742 " --system Connect to system manager\n"
4743 " --user Connect to user service manager\n"
4744 " --global Enable/disable unit files globally\n"
4745 " --runtime Enable unit files only temporarily until next reboot\n"
4746 " -f --force When enabling unit files, override existing symlinks\n"
4747 " When shutting down, execute action immediately\n"
4748 " --root=PATH Enable unit files in the specified root directory\n"
4749 " -n --lines=INTEGER Numer of journal entries to show\n"
4750 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
4751 " verbose, export, json, json-pretty, json-sse, cat)\n\n"
4753 " list-units List loaded units\n"
4754 " list-sockets List loaded sockets ordered by address\n"
4755 " start [NAME...] Start (activate) one or more units\n"
4756 " stop [NAME...] Stop (deactivate) one or more units\n"
4757 " reload [NAME...] Reload one or more units\n"
4758 " restart [NAME...] Start or restart one or more units\n"
4759 " try-restart [NAME...] Restart one or more units if active\n"
4760 " reload-or-restart [NAME...] Reload one or more units if possible,\n"
4761 " otherwise start or restart\n"
4762 " reload-or-try-restart [NAME...] Reload one or more units if possible,\n"
4763 " otherwise restart if active\n"
4764 " isolate [NAME] Start one unit and stop all others\n"
4765 " kill [NAME...] Send signal to processes of a unit\n"
4766 " is-active [NAME...] Check whether units are active\n"
4767 " is-failed [NAME...] Check whether units are failed\n"
4768 " status [NAME...|PID...] Show runtime status of one or more units\n"
4769 " show [NAME...|JOB...] Show properties of one or more\n"
4770 " units/jobs or the manager\n"
4771 " set-property [NAME] [ASSIGNMENT...]\n"
4772 " Sets one or more properties of a unit\n"
4773 " help [NAME...|PID...] Show manual for one or more units\n"
4774 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
4776 " list-dependencies [NAME] Recursively show units which are required\n"
4777 " or wanted by this unit or by which this\n"
4778 " unit is required or wanted\n\n"
4779 "Unit File Commands:\n"
4780 " list-unit-files List installed unit files\n"
4781 " enable [NAME...] Enable one or more unit files\n"
4782 " disable [NAME...] Disable one or more unit files\n"
4783 " reenable [NAME...] Reenable one or more unit files\n"
4784 " preset [NAME...] Enable/disable one or more unit files\n"
4785 " based on preset configuration\n"
4786 " is-enabled [NAME...] Check whether unit files are enabled\n\n"
4787 " mask [NAME...] Mask one or more units\n"
4788 " unmask [NAME...] Unmask one or more units\n"
4789 " link [PATH...] Link one or more units files into\n"
4790 " the search path\n"
4791 " get-default Get the name of the default target\n"
4792 " set-default NAME Set the default target\n\n"
4794 " list-jobs List jobs\n"
4795 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
4796 "Snapshot Commands:\n"
4797 " snapshot [NAME] Create a snapshot\n"
4798 " delete [NAME...] Remove one or more snapshots\n\n"
4799 "Environment Commands:\n"
4800 " show-environment Dump environment\n"
4801 " set-environment [NAME=VALUE...] Set one or more environment variables\n"
4802 " unset-environment [NAME...] Unset one or more environment variables\n\n"
4803 "Manager Lifecycle Commands:\n"
4804 " daemon-reload Reload systemd manager configuration\n"
4805 " daemon-reexec Reexecute systemd manager\n\n"
4806 "System Commands:\n"
4807 " default Enter system default mode\n"
4808 " rescue Enter system rescue mode\n"
4809 " emergency Enter system emergency mode\n"
4810 " halt Shut down and halt the system\n"
4811 " poweroff Shut down and power-off the system\n"
4812 " reboot Shut down and reboot the system\n"
4813 " kexec Shut down and reboot the system with kexec\n"
4814 " exit Request user instance exit\n"
4815 " switch-root [ROOT] [INIT] Change to a different root file system\n"
4816 " suspend Suspend the system\n"
4817 " hibernate Hibernate the system\n"
4818 " hybrid-sleep Hibernate and suspend the system\n",
4819 program_invocation_short_name);
4824 static int halt_help(void) {
4826 printf("%s [OPTIONS...]\n\n"
4827 "%s the system.\n\n"
4828 " --help Show this help\n"
4829 " --halt Halt the machine\n"
4830 " -p --poweroff Switch off the machine\n"
4831 " --reboot Reboot the machine\n"
4832 " -f --force Force immediate halt/power-off/reboot\n"
4833 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
4834 " -d --no-wtmp Don't write wtmp record\n"
4835 " --no-wall Don't send wall message before halt/power-off/reboot\n",
4836 program_invocation_short_name,
4837 arg_action == ACTION_REBOOT ? "Reboot" :
4838 arg_action == ACTION_POWEROFF ? "Power off" :
4844 static int shutdown_help(void) {
4846 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
4847 "Shut down the system.\n\n"
4848 " --help Show this help\n"
4849 " -H --halt Halt the machine\n"
4850 " -P --poweroff Power-off the machine\n"
4851 " -r --reboot Reboot the machine\n"
4852 " -h Equivalent to --poweroff, overridden by --halt\n"
4853 " -k Don't halt/power-off/reboot, just send warnings\n"
4854 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4855 " -c Cancel a pending shutdown\n",
4856 program_invocation_short_name);
4861 static int telinit_help(void) {
4863 printf("%s [OPTIONS...] {COMMAND}\n\n"
4864 "Send control commands to the init daemon.\n\n"
4865 " --help Show this help\n"
4866 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
4868 " 0 Power-off the machine\n"
4869 " 6 Reboot the machine\n"
4870 " 2, 3, 4, 5 Start runlevelX.target unit\n"
4871 " 1, s, S Enter rescue mode\n"
4872 " q, Q Reload init daemon configuration\n"
4873 " u, U Reexecute init daemon\n",
4874 program_invocation_short_name);
4879 static int runlevel_help(void) {
4881 printf("%s [OPTIONS...]\n\n"
4882 "Prints the previous and current runlevel of the init system.\n\n"
4883 " --help Show this help\n",
4884 program_invocation_short_name);
4889 static int help_types(void) {
4893 puts("Available unit types:");
4894 for(i = 0; i < _UNIT_TYPE_MAX; i++) {
4895 t = unit_type_to_string(i);
4903 static int systemctl_parse_argv(int argc, char *argv[]) {
4912 ARG_IGNORE_DEPENDENCIES,
4924 ARG_NO_ASK_PASSWORD,
4932 static const struct option options[] = {
4933 { "help", no_argument, NULL, 'h' },
4934 { "version", no_argument, NULL, ARG_VERSION },
4935 { "type", required_argument, NULL, 't' },
4936 { "property", required_argument, NULL, 'p' },
4937 { "all", no_argument, NULL, 'a' },
4938 { "reverse", no_argument, NULL, ARG_REVERSE },
4939 { "after", no_argument, NULL, ARG_AFTER },
4940 { "before", no_argument, NULL, ARG_BEFORE },
4941 { "show-types", no_argument, NULL, ARG_SHOW_TYPES },
4942 { "failed", no_argument, NULL, ARG_FAILED }, /* compatibility only */
4943 { "full", no_argument, NULL, 'l' },
4944 { "fail", no_argument, NULL, ARG_FAIL },
4945 { "irreversible", no_argument, NULL, ARG_IRREVERSIBLE },
4946 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
4947 { "ignore-inhibitors", no_argument, NULL, 'i' },
4948 { "user", no_argument, NULL, ARG_USER },
4949 { "system", no_argument, NULL, ARG_SYSTEM },
4950 { "global", no_argument, NULL, ARG_GLOBAL },
4951 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
4952 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
4953 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
4954 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4955 { "quiet", no_argument, NULL, 'q' },
4956 { "root", required_argument, NULL, ARG_ROOT },
4957 { "force", no_argument, NULL, ARG_FORCE },
4958 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
4959 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
4960 { "signal", required_argument, NULL, 's' },
4961 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
4962 { "host", required_argument, NULL, 'H' },
4963 { "privileged", no_argument, NULL, 'P' },
4964 { "runtime", no_argument, NULL, ARG_RUNTIME },
4965 { "lines", required_argument, NULL, 'n' },
4966 { "output", required_argument, NULL, 'o' },
4967 { "plain", no_argument, NULL, ARG_PLAIN },
4968 { "state", required_argument, NULL, ARG_STATE },
4969 { NULL, 0, NULL, 0 }
4977 while ((c = getopt_long(argc, argv, "ht:p:alqfs:H:Pn:o:i", options, NULL)) >= 0) {
4986 puts(PACKAGE_STRING);
4987 puts(SYSTEMD_FEATURES);
4994 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
4995 _cleanup_free_ char *type;
4997 type = strndup(word, size);
5001 if (streq(type, "help")) {
5006 if (unit_type_from_string(type) >= 0) {
5007 if (strv_push(&arg_types, type))
5013 /* It's much nicer to use --state= for
5014 * load states, but let's support this
5015 * in --types= too for compatibility
5016 * with old versions */
5017 if (unit_load_state_from_string(optarg) >= 0) {
5018 if (strv_push(&arg_states, type) < 0)
5024 log_error("Unknown unit type or load state '%s'.", type);
5025 log_info("Use -t help to see a list of allowed values.");
5033 /* Make sure that if the empty property list
5034 was specified, we won't show any properties. */
5035 if (isempty(optarg) && !arg_properties) {
5036 arg_properties = strv_new(NULL, NULL);
5037 if (!arg_properties)
5043 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
5046 prop = strndup(word, size);
5050 if (strv_push(&arg_properties, prop) < 0) {
5057 /* If the user asked for a particular
5058 * property, show it to him, even if it is
5070 arg_dependency = DEPENDENCY_REVERSE;
5074 arg_dependency = DEPENDENCY_AFTER;
5078 arg_dependency = DEPENDENCY_BEFORE;
5081 case ARG_SHOW_TYPES:
5082 arg_show_types = true;
5086 arg_job_mode = "fail";
5089 case ARG_IRREVERSIBLE:
5090 arg_job_mode = "replace-irreversibly";
5093 case ARG_IGNORE_DEPENDENCIES:
5094 arg_job_mode = "ignore-dependencies";
5098 arg_scope = UNIT_FILE_USER;
5102 arg_scope = UNIT_FILE_SYSTEM;
5106 arg_scope = UNIT_FILE_GLOBAL;
5110 arg_no_block = true;
5114 arg_no_legend = true;
5118 arg_no_pager = true;
5134 if (strv_extend(&arg_states, "failed") < 0)
5152 arg_no_reload = true;
5156 arg_kill_who = optarg;
5160 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
5161 log_error("Failed to parse signal string %s.", optarg);
5166 case ARG_NO_ASK_PASSWORD:
5167 arg_ask_password = false;
5171 arg_transport = TRANSPORT_POLKIT;
5175 arg_transport = TRANSPORT_SSH;
5176 parse_user_at_host(optarg, &arg_user, &arg_host);
5184 if (safe_atou(optarg, &arg_lines) < 0) {
5185 log_error("Failed to parse lines '%s'", optarg);
5191 arg_output = output_mode_from_string(optarg);
5192 if (arg_output < 0) {
5193 log_error("Unknown output '%s'.", optarg);
5199 arg_ignore_inhibitors = true;
5210 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
5213 s = strndup(word, size);
5217 if (strv_push(&arg_states, s) < 0) {
5229 log_error("Unknown option code '%c'.", c);
5234 if (arg_transport != TRANSPORT_NORMAL && arg_scope != UNIT_FILE_SYSTEM) {
5235 log_error("Cannot access user instance remotely.");
5242 static int halt_parse_argv(int argc, char *argv[]) {
5251 static const struct option options[] = {
5252 { "help", no_argument, NULL, ARG_HELP },
5253 { "halt", no_argument, NULL, ARG_HALT },
5254 { "poweroff", no_argument, NULL, 'p' },
5255 { "reboot", no_argument, NULL, ARG_REBOOT },
5256 { "force", no_argument, NULL, 'f' },
5257 { "wtmp-only", no_argument, NULL, 'w' },
5258 { "no-wtmp", no_argument, NULL, 'd' },
5259 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5260 { NULL, 0, NULL, 0 }
5268 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
5269 if (runlevel == '0' || runlevel == '6')
5272 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
5280 arg_action = ACTION_HALT;
5284 if (arg_action != ACTION_REBOOT)
5285 arg_action = ACTION_POWEROFF;
5289 arg_action = ACTION_REBOOT;
5311 /* Compatibility nops */
5318 log_error("Unknown option code '%c'.", c);
5323 if (optind < argc) {
5324 log_error("Too many arguments.");
5331 static int parse_time_spec(const char *t, usec_t *_u) {
5335 if (streq(t, "now"))
5337 else if (!strchr(t, ':')) {
5340 if (safe_atou64(t, &u) < 0)
5343 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
5352 hour = strtol(t, &e, 10);
5353 if (errno > 0 || *e != ':' || hour < 0 || hour > 23)
5356 minute = strtol(e+1, &e, 10);
5357 if (errno > 0 || *e != 0 || minute < 0 || minute > 59)
5360 n = now(CLOCK_REALTIME);
5361 s = (time_t) (n / USEC_PER_SEC);
5363 assert_se(localtime_r(&s, &tm));
5365 tm.tm_hour = (int) hour;
5366 tm.tm_min = (int) minute;
5369 assert_se(s = mktime(&tm));
5371 *_u = (usec_t) s * USEC_PER_SEC;
5374 *_u += USEC_PER_DAY;
5380 static int shutdown_parse_argv(int argc, char *argv[]) {
5387 static const struct option options[] = {
5388 { "help", no_argument, NULL, ARG_HELP },
5389 { "halt", no_argument, NULL, 'H' },
5390 { "poweroff", no_argument, NULL, 'P' },
5391 { "reboot", no_argument, NULL, 'r' },
5392 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
5393 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5394 { NULL, 0, NULL, 0 }
5402 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
5410 arg_action = ACTION_HALT;
5414 arg_action = ACTION_POWEROFF;
5419 arg_action = ACTION_KEXEC;
5421 arg_action = ACTION_REBOOT;
5425 arg_action = ACTION_KEXEC;
5429 if (arg_action != ACTION_HALT)
5430 arg_action = ACTION_POWEROFF;
5443 /* Compatibility nops */
5447 arg_action = ACTION_CANCEL_SHUTDOWN;
5454 log_error("Unknown option code '%c'.", c);
5459 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
5460 r = parse_time_spec(argv[optind], &arg_when);
5462 log_error("Failed to parse time specification: %s", argv[optind]);
5466 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
5468 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
5469 /* No time argument for shutdown cancel */
5470 arg_wall = argv + optind;
5471 else if (argc > optind + 1)
5472 /* We skip the time argument */
5473 arg_wall = argv + optind + 1;
5480 static int telinit_parse_argv(int argc, char *argv[]) {
5487 static const struct option options[] = {
5488 { "help", no_argument, NULL, ARG_HELP },
5489 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5490 { NULL, 0, NULL, 0 }
5493 static const struct {
5497 { '0', ACTION_POWEROFF },
5498 { '6', ACTION_REBOOT },
5499 { '1', ACTION_RESCUE },
5500 { '2', ACTION_RUNLEVEL2 },
5501 { '3', ACTION_RUNLEVEL3 },
5502 { '4', ACTION_RUNLEVEL4 },
5503 { '5', ACTION_RUNLEVEL5 },
5504 { 's', ACTION_RESCUE },
5505 { 'S', ACTION_RESCUE },
5506 { 'q', ACTION_RELOAD },
5507 { 'Q', ACTION_RELOAD },
5508 { 'u', ACTION_REEXEC },
5509 { 'U', ACTION_REEXEC }
5518 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
5533 log_error("Unknown option code '%c'.", c);
5538 if (optind >= argc) {
5543 if (optind + 1 < argc) {
5544 log_error("Too many arguments.");
5548 if (strlen(argv[optind]) != 1) {
5549 log_error("Expected single character argument.");
5553 for (i = 0; i < ELEMENTSOF(table); i++)
5554 if (table[i].from == argv[optind][0])
5557 if (i >= ELEMENTSOF(table)) {
5558 log_error("Unknown command '%s'.", argv[optind]);
5562 arg_action = table[i].to;
5569 static int runlevel_parse_argv(int argc, char *argv[]) {
5575 static const struct option options[] = {
5576 { "help", no_argument, NULL, ARG_HELP },
5577 { NULL, 0, NULL, 0 }
5585 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
5596 log_error("Unknown option code '%c'.", c);
5601 if (optind < argc) {
5602 log_error("Too many arguments.");
5609 static int parse_argv(int argc, char *argv[]) {
5613 if (program_invocation_short_name) {
5615 if (strstr(program_invocation_short_name, "halt")) {
5616 arg_action = ACTION_HALT;
5617 return halt_parse_argv(argc, argv);
5618 } else if (strstr(program_invocation_short_name, "poweroff")) {
5619 arg_action = ACTION_POWEROFF;
5620 return halt_parse_argv(argc, argv);
5621 } else if (strstr(program_invocation_short_name, "reboot")) {
5623 arg_action = ACTION_KEXEC;
5625 arg_action = ACTION_REBOOT;
5626 return halt_parse_argv(argc, argv);
5627 } else if (strstr(program_invocation_short_name, "shutdown")) {
5628 arg_action = ACTION_POWEROFF;
5629 return shutdown_parse_argv(argc, argv);
5630 } else if (strstr(program_invocation_short_name, "init")) {
5632 if (sd_booted() > 0) {
5633 arg_action = ACTION_INVALID;
5634 return telinit_parse_argv(argc, argv);
5636 /* Hmm, so some other init system is
5637 * running, we need to forward this
5638 * request to it. For now we simply
5639 * guess that it is Upstart. */
5641 execv(TELINIT, argv);
5643 log_error("Couldn't find an alternative telinit implementation to spawn.");
5647 } else if (strstr(program_invocation_short_name, "runlevel")) {
5648 arg_action = ACTION_RUNLEVEL;
5649 return runlevel_parse_argv(argc, argv);
5653 arg_action = ACTION_SYSTEMCTL;
5654 return systemctl_parse_argv(argc, argv);
5657 _pure_ static int action_to_runlevel(void) {
5659 static const char table[_ACTION_MAX] = {
5660 [ACTION_HALT] = '0',
5661 [ACTION_POWEROFF] = '0',
5662 [ACTION_REBOOT] = '6',
5663 [ACTION_RUNLEVEL2] = '2',
5664 [ACTION_RUNLEVEL3] = '3',
5665 [ACTION_RUNLEVEL4] = '4',
5666 [ACTION_RUNLEVEL5] = '5',
5667 [ACTION_RESCUE] = '1'
5670 assert(arg_action < _ACTION_MAX);
5672 return table[arg_action];
5675 static int talk_upstart(void) {
5676 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
5677 _cleanup_dbus_error_free_ DBusError error;
5678 int previous, rl, r;
5680 env1_buf[] = "RUNLEVEL=X",
5681 env2_buf[] = "PREVLEVEL=X";
5682 char *env1 = env1_buf, *env2 = env2_buf;
5683 const char *emit = "runlevel";
5684 dbus_bool_t b_false = FALSE;
5685 DBusMessageIter iter, sub;
5686 DBusConnection *bus;
5688 dbus_error_init(&error);
5690 if (!(rl = action_to_runlevel()))
5693 if (utmp_get_runlevel(&previous, NULL) < 0)
5696 if (!(bus = dbus_connection_open_private("unix:abstract=/com/ubuntu/upstart", &error))) {
5697 if (dbus_error_has_name(&error, DBUS_ERROR_NO_SERVER)) {
5702 log_error("Failed to connect to Upstart bus: %s", bus_error_message(&error));
5707 if ((r = bus_check_peercred(bus)) < 0) {
5708 log_error("Failed to verify owner of bus.");
5712 if (!(m = dbus_message_new_method_call(
5713 "com.ubuntu.Upstart",
5714 "/com/ubuntu/Upstart",
5715 "com.ubuntu.Upstart0_6",
5718 log_error("Could not allocate message.");
5723 dbus_message_iter_init_append(m, &iter);
5725 env1_buf[sizeof(env1_buf)-2] = rl;
5726 env2_buf[sizeof(env2_buf)-2] = previous;
5728 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &emit) ||
5729 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub) ||
5730 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env1) ||
5731 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env2) ||
5732 !dbus_message_iter_close_container(&iter, &sub) ||
5733 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b_false)) {
5734 log_error("Could not append arguments to message.");
5739 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
5741 if (bus_error_is_no_service(&error)) {
5746 log_error("Failed to issue method call: %s", bus_error_message(&error));
5755 dbus_connection_flush(bus);
5756 dbus_connection_close(bus);
5757 dbus_connection_unref(bus);
5763 static int talk_initctl(void) {
5764 struct init_request request = {};
5766 _cleanup_close_ int fd = -1;
5769 rl = action_to_runlevel();
5773 request.magic = INIT_MAGIC;
5774 request.sleeptime = 0;
5775 request.cmd = INIT_CMD_RUNLVL;
5776 request.runlevel = rl;
5778 fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY);
5780 if (errno == ENOENT)
5783 log_error("Failed to open "INIT_FIFO": %m");
5788 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
5790 log_error("Failed to write to "INIT_FIFO": %m");
5791 return errno > 0 ? -errno : -EIO;
5797 static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
5799 static const struct {
5807 int (* const dispatch)(DBusConnection *bus, char **args);
5809 { "list-units", LESS, 1, list_units },
5810 { "list-unit-files", EQUAL, 1, list_unit_files },
5811 { "list-sockets", LESS, 1, list_sockets },
5812 { "list-jobs", EQUAL, 1, list_jobs },
5813 { "clear-jobs", EQUAL, 1, daemon_reload },
5814 { "cancel", MORE, 2, cancel_job },
5815 { "start", MORE, 2, start_unit },
5816 { "stop", MORE, 2, start_unit },
5817 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5818 { "reload", MORE, 2, start_unit },
5819 { "restart", MORE, 2, start_unit },
5820 { "try-restart", MORE, 2, start_unit },
5821 { "reload-or-restart", MORE, 2, start_unit },
5822 { "reload-or-try-restart", MORE, 2, start_unit },
5823 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
5824 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5825 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
5826 { "isolate", EQUAL, 2, start_unit },
5827 { "kill", MORE, 2, kill_unit },
5828 { "is-active", MORE, 2, check_unit_active },
5829 { "check", MORE, 2, check_unit_active },
5830 { "is-failed", MORE, 2, check_unit_failed },
5831 { "show", MORE, 1, show },
5832 { "status", MORE, 1, show },
5833 { "help", MORE, 2, show },
5834 { "snapshot", LESS, 2, snapshot },
5835 { "delete", MORE, 2, delete_snapshot },
5836 { "daemon-reload", EQUAL, 1, daemon_reload },
5837 { "daemon-reexec", EQUAL, 1, daemon_reload },
5838 { "show-environment", EQUAL, 1, show_enviroment },
5839 { "set-environment", MORE, 2, set_environment },
5840 { "unset-environment", MORE, 2, set_environment },
5841 { "halt", EQUAL, 1, start_special },
5842 { "poweroff", EQUAL, 1, start_special },
5843 { "reboot", EQUAL, 1, start_special },
5844 { "kexec", EQUAL, 1, start_special },
5845 { "suspend", EQUAL, 1, start_special },
5846 { "hibernate", EQUAL, 1, start_special },
5847 { "hybrid-sleep", EQUAL, 1, start_special },
5848 { "default", EQUAL, 1, start_special },
5849 { "rescue", EQUAL, 1, start_special },
5850 { "emergency", EQUAL, 1, start_special },
5851 { "exit", EQUAL, 1, start_special },
5852 { "reset-failed", MORE, 1, reset_failed },
5853 { "enable", MORE, 2, enable_unit },
5854 { "disable", MORE, 2, enable_unit },
5855 { "is-enabled", MORE, 2, unit_is_enabled },
5856 { "reenable", MORE, 2, enable_unit },
5857 { "preset", MORE, 2, enable_unit },
5858 { "mask", MORE, 2, enable_unit },
5859 { "unmask", MORE, 2, enable_unit },
5860 { "link", MORE, 2, enable_unit },
5861 { "switch-root", MORE, 2, switch_root },
5862 { "list-dependencies", LESS, 2, list_dependencies },
5863 { "set-default", EQUAL, 2, enable_unit },
5864 { "get-default", LESS, 1, get_default },
5865 { "set-property", MORE, 3, set_property },
5875 left = argc - optind;
5878 /* Special rule: no arguments means "list-units" */
5881 if (streq(argv[optind], "help") && !argv[optind+1]) {
5882 log_error("This command expects one or more "
5883 "unit names. Did you mean --help?");
5887 for (i = 0; i < ELEMENTSOF(verbs); i++)
5888 if (streq(argv[optind], verbs[i].verb))
5891 if (i >= ELEMENTSOF(verbs)) {
5892 log_error("Unknown operation '%s'.", argv[optind]);
5897 switch (verbs[i].argc_cmp) {
5900 if (left != verbs[i].argc) {
5901 log_error("Invalid number of arguments.");
5908 if (left < verbs[i].argc) {
5909 log_error("Too few arguments.");
5916 if (left > verbs[i].argc) {
5917 log_error("Too many arguments.");
5924 assert_not_reached("Unknown comparison operator.");
5927 /* Require a bus connection for all operations but
5929 if (!streq(verbs[i].verb, "enable") &&
5930 !streq(verbs[i].verb, "disable") &&
5931 !streq(verbs[i].verb, "is-enabled") &&
5932 !streq(verbs[i].verb, "list-unit-files") &&
5933 !streq(verbs[i].verb, "reenable") &&
5934 !streq(verbs[i].verb, "preset") &&
5935 !streq(verbs[i].verb, "mask") &&
5936 !streq(verbs[i].verb, "unmask") &&
5937 !streq(verbs[i].verb, "link") &&
5938 !streq(verbs[i].verb, "set-default") &&
5939 !streq(verbs[i].verb, "get-default")) {
5941 if (running_in_chroot() > 0) {
5942 log_info("Running in chroot, ignoring request.");
5946 if (((!streq(verbs[i].verb, "reboot") &&
5947 !streq(verbs[i].verb, "halt") &&
5948 !streq(verbs[i].verb, "poweroff")) || arg_force <= 0) && !bus) {
5949 log_error("Failed to get D-Bus connection: %s",
5950 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5956 if (!bus && !avoid_bus()) {
5957 log_error("Failed to get D-Bus connection: %s",
5958 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5963 return verbs[i].dispatch(bus, argv + optind);
5966 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
5967 _cleanup_close_ int fd;
5968 struct sd_shutdown_command c = {
5974 union sockaddr_union sockaddr = {
5975 .un.sun_family = AF_UNIX,
5976 .un.sun_path = "/run/systemd/shutdownd",
5978 struct iovec iovec[2] = {
5979 {.iov_base = (char*) &c,
5980 .iov_len = offsetof(struct sd_shutdown_command, wall_message),
5983 struct msghdr msghdr = {
5984 .msg_name = &sockaddr,
5985 .msg_namelen = offsetof(struct sockaddr_un, sun_path)
5986 + sizeof("/run/systemd/shutdownd") - 1,
5991 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
5995 if (!isempty(message)) {
5996 iovec[1].iov_base = (char*) message;
5997 iovec[1].iov_len = strlen(message);
5998 msghdr.msg_iovlen++;
6001 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0)
6007 static int reload_with_fallback(DBusConnection *bus) {
6010 /* First, try systemd via D-Bus. */
6011 if (daemon_reload(bus, NULL) >= 0)
6015 /* Nothing else worked, so let's try signals */
6016 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
6018 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
6019 log_error("kill() failed: %m");
6026 static int start_with_fallback(DBusConnection *bus) {
6029 /* First, try systemd via D-Bus. */
6030 if (start_unit(bus, NULL) >= 0)
6034 /* Hmm, talking to systemd via D-Bus didn't work. Then
6035 * let's try to talk to Upstart via D-Bus. */
6036 if (talk_upstart() > 0)
6039 /* Nothing else worked, so let's try
6041 if (talk_initctl() > 0)
6044 log_error("Failed to talk to init daemon.");
6048 warn_wall(arg_action);
6052 static _noreturn_ void halt_now(enum action a) {
6054 /* Make sure C-A-D is handled by the kernel from this
6056 reboot(RB_ENABLE_CAD);
6061 log_info("Halting.");
6062 reboot(RB_HALT_SYSTEM);
6065 case ACTION_POWEROFF:
6066 log_info("Powering off.");
6067 reboot(RB_POWER_OFF);
6071 log_info("Rebooting.");
6072 reboot(RB_AUTOBOOT);
6076 assert_not_reached("Unknown halt action.");
6079 assert_not_reached("Uh? This shouldn't happen.");
6082 static int halt_main(DBusConnection *bus) {
6085 r = check_inhibitors(bus, arg_action);
6089 if (geteuid() != 0) {
6090 /* Try logind if we are a normal user and no special
6091 * mode applies. Maybe PolicyKit allows us to shutdown
6094 if (arg_when <= 0 &&
6097 (arg_action == ACTION_POWEROFF ||
6098 arg_action == ACTION_REBOOT)) {
6099 r = reboot_with_logind(bus, arg_action);
6104 log_error("Must be root.");
6109 _cleanup_free_ char *m;
6111 m = strv_join(arg_wall, " ");
6112 r = send_shutdownd(arg_when,
6113 arg_action == ACTION_HALT ? 'H' :
6114 arg_action == ACTION_POWEROFF ? 'P' :
6115 arg_action == ACTION_KEXEC ? 'K' :
6122 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
6124 char date[FORMAT_TIMESTAMP_MAX];
6126 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
6127 format_timestamp(date, sizeof(date), arg_when));
6132 if (!arg_dry && !arg_force)
6133 return start_with_fallback(bus);
6136 if (sd_booted() > 0)
6137 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
6139 r = utmp_put_shutdown();
6141 log_warning("Failed to write utmp record: %s", strerror(-r));
6148 halt_now(arg_action);
6149 /* We should never reach this. */
6153 static int runlevel_main(void) {
6154 int r, runlevel, previous;
6156 r = utmp_get_runlevel(&runlevel, &previous);
6163 previous <= 0 ? 'N' : previous,
6164 runlevel <= 0 ? 'N' : runlevel);
6169 int main(int argc, char*argv[]) {
6170 int r, retval = EXIT_FAILURE;
6171 DBusConnection *bus = NULL;
6172 _cleanup_dbus_error_free_ DBusError error;
6174 dbus_error_init(&error);
6176 setlocale(LC_ALL, "");
6177 log_parse_environment();
6180 r = parse_argv(argc, argv);
6184 retval = EXIT_SUCCESS;
6188 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
6189 * let's shortcut this */
6190 if (arg_action == ACTION_RUNLEVEL) {
6191 r = runlevel_main();
6192 retval = r < 0 ? EXIT_FAILURE : r;
6196 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
6197 log_info("Running in chroot, ignoring request.");
6203 if (arg_transport == TRANSPORT_NORMAL)
6204 bus_connect(arg_scope == UNIT_FILE_SYSTEM ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &bus, &private_bus, &error);
6205 else if (arg_transport == TRANSPORT_POLKIT) {
6206 bus_connect_system_polkit(&bus, &error);
6207 private_bus = false;
6208 } else if (arg_transport == TRANSPORT_SSH) {
6209 bus_connect_system_ssh(arg_user, arg_host, &bus, &error);
6210 private_bus = false;
6212 assert_not_reached("Uh, invalid transport...");
6215 switch (arg_action) {
6217 case ACTION_SYSTEMCTL:
6218 r = systemctl_main(bus, argc, argv, &error);
6222 case ACTION_POWEROFF:
6228 case ACTION_RUNLEVEL2:
6229 case ACTION_RUNLEVEL3:
6230 case ACTION_RUNLEVEL4:
6231 case ACTION_RUNLEVEL5:
6233 case ACTION_EMERGENCY:
6234 case ACTION_DEFAULT:
6235 r = start_with_fallback(bus);
6240 r = reload_with_fallback(bus);
6243 case ACTION_CANCEL_SHUTDOWN: {
6247 m = strv_join(arg_wall, " ");
6249 retval = EXIT_FAILURE;
6253 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
6255 log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r));
6260 case ACTION_INVALID:
6261 case ACTION_RUNLEVEL:
6263 assert_not_reached("Unknown action");
6266 retval = r < 0 ? EXIT_FAILURE : r;
6270 dbus_connection_flush(bus);
6271 dbus_connection_close(bus);
6272 dbus_connection_unref(bus);
6277 strv_free(arg_types);
6278 strv_free(arg_states);
6279 strv_free(arg_properties);
6282 ask_password_agent_close();
6283 polkit_agent_close();