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, *r;
1499 if (dbus_message_get_args(message, &error,
1500 DBUS_TYPE_UINT32, &id,
1501 DBUS_TYPE_OBJECT_PATH, &path,
1502 DBUS_TYPE_STRING, &unit,
1503 DBUS_TYPE_STRING, &result,
1504 DBUS_TYPE_INVALID)) {
1506 r = set_remove(d->set, (char*) path);
1508 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1512 if (!isempty(result))
1513 d->result = strdup(result);
1516 d->name = strdup(unit);
1518 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1521 dbus_error_free(&error);
1522 if (dbus_message_get_args(message, &error,
1523 DBUS_TYPE_UINT32, &id,
1524 DBUS_TYPE_OBJECT_PATH, &path,
1525 DBUS_TYPE_STRING, &result,
1526 DBUS_TYPE_INVALID)) {
1527 /* Compatibility with older systemd versions <
1528 * 183 during upgrades. This should be dropped
1530 r = set_remove(d->set, (char*) path);
1532 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1537 d->result = strdup(result);
1539 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1543 log_error("Failed to parse message: %s", bus_error_message(&error));
1546 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1549 static int enable_wait_for_jobs(DBusConnection *bus) {
1557 dbus_error_init(&error);
1558 dbus_bus_add_match(bus,
1560 "sender='org.freedesktop.systemd1',"
1561 "interface='org.freedesktop.systemd1.Manager',"
1562 "member='JobRemoved',"
1563 "path='/org/freedesktop/systemd1'",
1566 if (dbus_error_is_set(&error)) {
1567 log_error("Failed to add match: %s", bus_error_message(&error));
1568 dbus_error_free(&error);
1572 /* This is slightly dirty, since we don't undo the match registrations. */
1576 static int wait_for_jobs(DBusConnection *bus, Set *s) {
1578 WaitData d = { .set = s };
1583 if (!dbus_connection_add_filter(bus, wait_filter, &d, NULL))
1586 while (!set_isempty(s)) {
1588 if (!dbus_connection_read_write_dispatch(bus, -1)) {
1589 log_error("Disconnected from bus.");
1590 return -ECONNREFUSED;
1597 if (streq(d.result, "timeout"))
1598 log_error("Job for %s timed out.", strna(d.name));
1599 else if (streq(d.result, "canceled"))
1600 log_error("Job for %s canceled.", strna(d.name));
1601 else if (streq(d.result, "dependency"))
1602 log_error("A dependency job for %s failed. See 'journalctl -xn' for details.", strna(d.name));
1603 else if (!streq(d.result, "done") && !streq(d.result, "skipped"))
1604 log_error("Job for %s failed. See 'systemctl status %s' and 'journalctl -xn' for details.", strna(d.name), strna(d.name));
1607 if (streq_ptr(d.result, "timeout"))
1609 else if (streq_ptr(d.result, "canceled"))
1611 else if (!streq_ptr(d.result, "done") && !streq_ptr(d.result, "skipped"))
1622 dbus_connection_remove_filter(bus, wait_filter, &d);
1626 static int check_one_unit(DBusConnection *bus, const char *name, char **check_states, bool quiet) {
1627 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1628 _cleanup_free_ char *n = NULL;
1629 DBusMessageIter iter, sub;
1631 *interface = "org.freedesktop.systemd1.Unit",
1632 *property = "ActiveState";
1633 const char *state, *path;
1639 dbus_error_init(&error);
1641 n = unit_name_mangle(name);
1645 r = bus_method_call_with_reply (
1647 "org.freedesktop.systemd1",
1648 "/org/freedesktop/systemd1",
1649 "org.freedesktop.systemd1.Manager",
1653 DBUS_TYPE_STRING, &n,
1656 dbus_error_free(&error);
1663 if (!dbus_message_get_args(reply, NULL,
1664 DBUS_TYPE_OBJECT_PATH, &path,
1665 DBUS_TYPE_INVALID)) {
1666 log_error("Failed to parse reply.");
1670 dbus_message_unref(reply);
1673 r = bus_method_call_with_reply(
1675 "org.freedesktop.systemd1",
1677 "org.freedesktop.DBus.Properties",
1681 DBUS_TYPE_STRING, &interface,
1682 DBUS_TYPE_STRING, &property,
1690 if (!dbus_message_iter_init(reply, &iter) ||
1691 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1692 log_error("Failed to parse reply.");
1696 dbus_message_iter_recurse(&iter, &sub);
1698 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1699 log_error("Failed to parse reply.");
1703 dbus_message_iter_get_basic(&sub, &state);
1708 return strv_find(check_states, state) ? 1 : 0;
1711 static void check_triggering_units(
1712 DBusConnection *bus,
1713 const char *unit_name) {
1715 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1716 DBusMessageIter iter, sub;
1717 const char *interface = "org.freedesktop.systemd1.Unit",
1718 *load_state_property = "LoadState",
1719 *triggered_by_property = "TriggeredBy",
1721 _cleanup_free_ char *unit_path = NULL, *n = NULL;
1722 bool print_warning_label = true;
1725 n = unit_name_mangle(unit_name);
1731 unit_path = unit_dbus_path_from_name(n);
1737 r = bus_method_call_with_reply(
1739 "org.freedesktop.systemd1",
1741 "org.freedesktop.DBus.Properties",
1745 DBUS_TYPE_STRING, &interface,
1746 DBUS_TYPE_STRING, &load_state_property,
1751 if (!dbus_message_iter_init(reply, &iter) ||
1752 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1753 log_error("Failed to parse reply.");
1757 dbus_message_iter_recurse(&iter, &sub);
1759 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1760 log_error("Failed to parse reply.");
1764 dbus_message_iter_get_basic(&sub, &state);
1766 if (streq(state, "masked"))
1769 dbus_message_unref(reply);
1772 r = bus_method_call_with_reply(
1774 "org.freedesktop.systemd1",
1776 "org.freedesktop.DBus.Properties",
1780 DBUS_TYPE_STRING, &interface,
1781 DBUS_TYPE_STRING, &triggered_by_property,
1786 if (!dbus_message_iter_init(reply, &iter) ||
1787 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1788 log_error("Failed to parse reply.");
1792 dbus_message_iter_recurse(&iter, &sub);
1793 dbus_message_iter_recurse(&sub, &iter);
1796 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1797 const char * const check_states[] = {
1802 const char *service_trigger;
1804 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1805 log_error("Failed to parse reply.");
1809 dbus_message_iter_get_basic(&sub, &service_trigger);
1811 r = check_one_unit(bus, service_trigger, (char**) check_states, true);
1815 if (print_warning_label) {
1816 log_warning("Warning: Stopping %s, but it can still be activated by:", unit_name);
1817 print_warning_label = false;
1820 log_warning(" %s", service_trigger);
1823 dbus_message_iter_next(&sub);
1827 static int start_unit_one(
1828 DBusConnection *bus,
1835 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1836 _cleanup_free_ char *n;
1845 n = unit_name_mangle(name);
1849 r = bus_method_call_with_reply(
1851 "org.freedesktop.systemd1",
1852 "/org/freedesktop/systemd1",
1853 "org.freedesktop.systemd1.Manager",
1857 DBUS_TYPE_STRING, &n,
1858 DBUS_TYPE_STRING, &mode,
1861 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
1862 /* There's always a fallback possible for
1863 * legacy actions. */
1866 log_error("Failed to issue method call: %s", bus_error_message(error));
1871 if (!dbus_message_get_args(reply, error,
1872 DBUS_TYPE_OBJECT_PATH, &path,
1873 DBUS_TYPE_INVALID)) {
1874 log_error("Failed to parse reply: %s", bus_error_message(error));
1878 if (need_daemon_reload(bus, n) > 0)
1879 log_warning("Warning: Unit file of %s changed on disk, 'systemctl %sdaemon-reload' recommended.",
1880 n, arg_scope == UNIT_FILE_SYSTEM ? "" : "--user ");
1889 r = set_consume(s, p);
1891 log_error("Failed to add path to set.");
1899 static const struct {
1903 } action_table[_ACTION_MAX] = {
1904 [ACTION_HALT] = { SPECIAL_HALT_TARGET, "halt", "replace-irreversibly" },
1905 [ACTION_POWEROFF] = { SPECIAL_POWEROFF_TARGET, "poweroff", "replace-irreversibly" },
1906 [ACTION_REBOOT] = { SPECIAL_REBOOT_TARGET, "reboot", "replace-irreversibly" },
1907 [ACTION_KEXEC] = { SPECIAL_KEXEC_TARGET, "kexec", "replace-irreversibly" },
1908 [ACTION_RUNLEVEL2] = { SPECIAL_RUNLEVEL2_TARGET, NULL, "isolate" },
1909 [ACTION_RUNLEVEL3] = { SPECIAL_RUNLEVEL3_TARGET, NULL, "isolate" },
1910 [ACTION_RUNLEVEL4] = { SPECIAL_RUNLEVEL4_TARGET, NULL, "isolate" },
1911 [ACTION_RUNLEVEL5] = { SPECIAL_RUNLEVEL5_TARGET, NULL, "isolate" },
1912 [ACTION_RESCUE] = { SPECIAL_RESCUE_TARGET, "rescue", "isolate" },
1913 [ACTION_EMERGENCY] = { SPECIAL_EMERGENCY_TARGET, "emergency", "isolate" },
1914 [ACTION_DEFAULT] = { SPECIAL_DEFAULT_TARGET, "default", "isolate" },
1915 [ACTION_EXIT] = { SPECIAL_EXIT_TARGET, "exit", "replace-irreversibly" },
1916 [ACTION_SUSPEND] = { SPECIAL_SUSPEND_TARGET, "suspend", "replace-irreversibly" },
1917 [ACTION_HIBERNATE] = { SPECIAL_HIBERNATE_TARGET, "hibernate", "replace-irreversibly" },
1918 [ACTION_HYBRID_SLEEP] = { SPECIAL_HYBRID_SLEEP_TARGET, "hybrid-sleep", "replace-irreversibly" },
1921 static enum action verb_to_action(const char *verb) {
1924 for (i = ACTION_INVALID; i < _ACTION_MAX; i++)
1925 if (action_table[i].verb && streq(verb, action_table[i].verb))
1927 return ACTION_INVALID;
1930 static int start_unit(DBusConnection *bus, char **args) {
1933 const char *method, *mode, *one_name;
1934 _cleanup_set_free_free_ Set *s = NULL;
1935 _cleanup_dbus_error_free_ DBusError error;
1938 dbus_error_init(&error);
1942 ask_password_agent_open_if_enabled();
1944 if (arg_action == ACTION_SYSTEMCTL) {
1947 streq(args[0], "stop") ||
1948 streq(args[0], "condstop") ? "StopUnit" :
1949 streq(args[0], "reload") ? "ReloadUnit" :
1950 streq(args[0], "restart") ? "RestartUnit" :
1952 streq(args[0], "try-restart") ||
1953 streq(args[0], "condrestart") ? "TryRestartUnit" :
1955 streq(args[0], "reload-or-restart") ? "ReloadOrRestartUnit" :
1957 streq(args[0], "reload-or-try-restart") ||
1958 streq(args[0], "condreload") ||
1960 streq(args[0], "force-reload") ? "ReloadOrTryRestartUnit" :
1962 action = verb_to_action(args[0]);
1964 mode = streq(args[0], "isolate") ? "isolate" :
1965 action_table[action].mode ?: arg_job_mode;
1967 one_name = action_table[action].target;
1970 assert(arg_action < ELEMENTSOF(action_table));
1971 assert(action_table[arg_action].target);
1973 method = "StartUnit";
1975 mode = action_table[arg_action].mode;
1976 one_name = action_table[arg_action].target;
1979 if (!arg_no_block) {
1980 ret = enable_wait_for_jobs(bus);
1982 log_error("Could not watch jobs: %s", strerror(-ret));
1986 s = set_new(string_hash_func, string_compare_func);
1992 ret = start_unit_one(bus, method, one_name, mode, &error, s);
1994 ret = translate_bus_error_to_exit_status(ret, &error);
1996 STRV_FOREACH(name, args+1) {
1997 r = start_unit_one(bus, method, *name, mode, &error, s);
1999 ret = translate_bus_error_to_exit_status(r, &error);
2000 dbus_error_free(&error);
2005 if (!arg_no_block) {
2006 r = wait_for_jobs(bus, s);
2010 /* When stopping units, warn if they can still be triggered by
2011 * another active unit (socket, path, timer) */
2012 if (!arg_quiet && streq(method, "StopUnit")) {
2014 check_triggering_units(bus, one_name);
2016 STRV_FOREACH(name, args+1)
2017 check_triggering_units(bus, *name);
2024 /* Ask systemd-logind, which might grant access to unprivileged users
2025 * through PolicyKit */
2026 static int reboot_with_logind(DBusConnection *bus, enum action a) {
2029 dbus_bool_t interactive = true;
2034 polkit_agent_open_if_enabled();
2042 case ACTION_POWEROFF:
2043 method = "PowerOff";
2046 case ACTION_SUSPEND:
2050 case ACTION_HIBERNATE:
2051 method = "Hibernate";
2054 case ACTION_HYBRID_SLEEP:
2055 method = "HybridSleep";
2062 return bus_method_call_with_reply(
2064 "org.freedesktop.login1",
2065 "/org/freedesktop/login1",
2066 "org.freedesktop.login1.Manager",
2070 DBUS_TYPE_BOOLEAN, &interactive,
2077 static int check_inhibitors(DBusConnection *bus, enum action a) {
2079 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
2080 DBusMessageIter iter, sub, sub2;
2083 _cleanup_strv_free_ char **sessions = NULL;
2089 if (arg_ignore_inhibitors || arg_force > 0)
2101 r = bus_method_call_with_reply(
2103 "org.freedesktop.login1",
2104 "/org/freedesktop/login1",
2105 "org.freedesktop.login1.Manager",
2111 /* If logind is not around, then there are no inhibitors... */
2114 if (!dbus_message_iter_init(reply, &iter) ||
2115 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
2116 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
2117 log_error("Failed to parse reply.");
2121 dbus_message_iter_recurse(&iter, &sub);
2122 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
2123 const char *what, *who, *why, *mode;
2125 _cleanup_strv_free_ char **sv = NULL;
2126 _cleanup_free_ char *comm = NULL, *user = NULL;
2128 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
2129 log_error("Failed to parse reply.");
2133 dbus_message_iter_recurse(&sub, &sub2);
2135 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &what, true) < 0 ||
2136 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &who, true) < 0 ||
2137 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &why, true) < 0 ||
2138 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &mode, true) < 0 ||
2139 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &uid, true) < 0 ||
2140 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, false) < 0) {
2141 log_error("Failed to parse reply.");
2145 if (!streq(mode, "block"))
2148 sv = strv_split(what, ":");
2152 if (!strv_contains(sv,
2154 a == ACTION_POWEROFF ||
2155 a == ACTION_REBOOT ||
2156 a == ACTION_KEXEC ? "shutdown" : "sleep"))
2159 get_process_comm(pid, &comm);
2160 user = uid_to_name(uid);
2161 log_warning("Operation inhibited by \"%s\" (PID %lu \"%s\", user %s), reason is \"%s\".",
2162 who, (unsigned long) pid, strna(comm), strna(user), why);
2166 dbus_message_iter_next(&sub);
2169 dbus_message_iter_recurse(&iter, &sub);
2171 /* Check for current sessions */
2172 sd_get_sessions(&sessions);
2173 STRV_FOREACH(s, sessions) {
2175 _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL;
2177 if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid())
2180 if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
2183 if (sd_session_get_type(*s, &type) < 0 || (!streq(type, "x11") && !streq(type, "tty")))
2186 sd_session_get_tty(*s, &tty);
2187 sd_session_get_seat(*s, &seat);
2188 sd_session_get_service(*s, &service);
2189 user = uid_to_name(uid);
2191 log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty);
2198 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
2199 action_table[a].verb);
2207 static int start_special(DBusConnection *bus, char **args) {
2213 a = verb_to_action(args[0]);
2215 r = check_inhibitors(bus, a);
2219 if (arg_force >= 2 && geteuid() != 0) {
2220 log_error("Must be root.");
2224 if (arg_force >= 2 &&
2225 (a == ACTION_HALT ||
2226 a == ACTION_POWEROFF ||
2227 a == ACTION_REBOOT))
2230 if (arg_force >= 1 &&
2231 (a == ACTION_HALT ||
2232 a == ACTION_POWEROFF ||
2233 a == ACTION_REBOOT ||
2234 a == ACTION_KEXEC ||
2236 return daemon_reload(bus, args);
2238 /* first try logind, to allow authentication with polkit */
2239 if (geteuid() != 0 &&
2240 (a == ACTION_POWEROFF ||
2241 a == ACTION_REBOOT ||
2242 a == ACTION_SUSPEND ||
2243 a == ACTION_HIBERNATE ||
2244 a == ACTION_HYBRID_SLEEP)) {
2245 r = reboot_with_logind(bus, a);
2250 r = start_unit(bus, args);
2251 if (r == EXIT_SUCCESS)
2257 static int check_unit_active(DBusConnection *bus, char **args) {
2258 const char * const check_states[] = {
2265 int r = 3; /* According to LSB: "program is not running" */
2270 STRV_FOREACH(name, args+1) {
2273 state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
2283 static int check_unit_failed(DBusConnection *bus, char **args) {
2284 const char * const check_states[] = {
2295 STRV_FOREACH(name, args+1) {
2298 state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
2308 static int kill_unit(DBusConnection *bus, char **args) {
2316 arg_kill_who = "all";
2318 STRV_FOREACH(name, args+1) {
2319 _cleanup_free_ char *n = NULL;
2321 n = unit_name_mangle(*name);
2325 r = bus_method_call_with_reply(
2327 "org.freedesktop.systemd1",
2328 "/org/freedesktop/systemd1",
2329 "org.freedesktop.systemd1.Manager",
2333 DBUS_TYPE_STRING, &n,
2334 DBUS_TYPE_STRING, &arg_kill_who,
2335 DBUS_TYPE_INT32, &arg_signal,
2343 typedef struct ExecStatusInfo {
2351 usec_t start_timestamp;
2352 usec_t exit_timestamp;
2357 LIST_FIELDS(struct ExecStatusInfo, exec);
2360 static void exec_status_info_free(ExecStatusInfo *i) {
2369 static int exec_status_info_deserialize(DBusMessageIter *sub, ExecStatusInfo *i) {
2370 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
2371 DBusMessageIter sub2, sub3;
2375 int32_t code, status;
2381 if (dbus_message_iter_get_arg_type(sub) != DBUS_TYPE_STRUCT)
2384 dbus_message_iter_recurse(sub, &sub2);
2386 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0)
2389 i->path = strdup(path);
2393 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_ARRAY ||
2394 dbus_message_iter_get_element_type(&sub2) != DBUS_TYPE_STRING)
2398 dbus_message_iter_recurse(&sub2, &sub3);
2399 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2400 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2401 dbus_message_iter_next(&sub3);
2405 i->argv = new0(char*, n+1);
2410 dbus_message_iter_recurse(&sub2, &sub3);
2411 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2414 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2415 dbus_message_iter_get_basic(&sub3, &s);
2416 dbus_message_iter_next(&sub3);
2418 i->argv[n] = strdup(s);
2425 if (!dbus_message_iter_next(&sub2) ||
2426 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, true) < 0 ||
2427 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp, true) < 0 ||
2428 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp_monotonic, true) < 0 ||
2429 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp, true) < 0 ||
2430 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp_monotonic, true) < 0 ||
2431 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, true) < 0 ||
2432 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &code, true) < 0 ||
2433 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &status, false) < 0)
2437 i->start_timestamp = (usec_t) start_timestamp;
2438 i->exit_timestamp = (usec_t) exit_timestamp;
2439 i->pid = (pid_t) pid;
2446 typedef struct UnitStatusInfo {
2448 const char *load_state;
2449 const char *active_state;
2450 const char *sub_state;
2451 const char *unit_file_state;
2453 const char *description;
2454 const char *following;
2456 char **documentation;
2458 const char *fragment_path;
2459 const char *source_path;
2460 const char *control_group;
2462 char **dropin_paths;
2464 const char *load_error;
2467 usec_t inactive_exit_timestamp;
2468 usec_t inactive_exit_timestamp_monotonic;
2469 usec_t active_enter_timestamp;
2470 usec_t active_exit_timestamp;
2471 usec_t inactive_enter_timestamp;
2473 bool need_daemon_reload;
2478 const char *status_text;
2479 const char *pid_file;
2482 usec_t start_timestamp;
2483 usec_t exit_timestamp;
2485 int exit_code, exit_status;
2487 usec_t condition_timestamp;
2488 bool condition_result;
2489 bool failed_condition_trigger;
2490 bool failed_condition_negate;
2491 const char *failed_condition;
2492 const char *failed_condition_param;
2495 unsigned n_accepted;
2496 unsigned n_connections;
2499 /* Pairs of type, path */
2503 const char *sysfs_path;
2505 /* Mount, Automount */
2511 LIST_HEAD(ExecStatusInfo, exec);
2514 static void print_status_info(UnitStatusInfo *i,
2517 const char *on, *off, *ss;
2519 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
2520 char since2[FORMAT_TIMESTAMP_MAX], *s2;
2523 arg_all * OUTPUT_SHOW_ALL |
2524 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
2525 on_tty() * OUTPUT_COLOR |
2526 !arg_quiet * OUTPUT_WARN_CUTOFF |
2527 arg_full * OUTPUT_FULL_WIDTH;
2532 /* This shows pretty information about a unit. See
2533 * print_property() for a low-level property printer */
2535 printf("%s", strna(i->id));
2537 if (i->description && !streq_ptr(i->id, i->description))
2538 printf(" - %s", i->description);
2543 printf(" Follow: unit currently follows state of %s\n", i->following);
2545 if (streq_ptr(i->load_state, "error")) {
2546 on = ansi_highlight_red();
2547 off = ansi_highlight_off();
2551 path = i->source_path ? i->source_path : i->fragment_path;
2554 printf(" Loaded: %s%s%s (Reason: %s)\n",
2555 on, strna(i->load_state), off, i->load_error);
2556 else if (path && i->unit_file_state)
2557 printf(" Loaded: %s%s%s (%s; %s)\n",
2558 on, strna(i->load_state), off, path, i->unit_file_state);
2560 printf(" Loaded: %s%s%s (%s)\n",
2561 on, strna(i->load_state), off, path);
2563 printf(" Loaded: %s%s%s\n",
2564 on, strna(i->load_state), off);
2566 if (!strv_isempty(i->dropin_paths)) {
2571 STRV_FOREACH(dropin, i->dropin_paths) {
2572 if (! dir || last) {
2573 printf(dir ? " " : " Drop-In: ");
2577 if (path_get_parent(*dropin, &dir) < 0) {
2582 printf("%s\n %s", dir,
2583 draw_special_char(DRAW_TREE_RIGHT));
2586 last = ! (*(dropin + 1) && startswith(*(dropin + 1), dir));
2588 printf("%s%s", path_get_file_name(*dropin), last ? "\n" : ", ");
2594 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
2596 if (streq_ptr(i->active_state, "failed")) {
2597 on = ansi_highlight_red();
2598 off = ansi_highlight_off();
2599 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
2600 on = ansi_highlight_green();
2601 off = ansi_highlight_off();
2606 printf(" Active: %s%s (%s)%s",
2607 on, strna(i->active_state), ss, off);
2609 printf(" Active: %s%s%s",
2610 on, strna(i->active_state), off);
2612 if (!isempty(i->result) && !streq(i->result, "success"))
2613 printf(" (Result: %s)", i->result);
2615 timestamp = (streq_ptr(i->active_state, "active") ||
2616 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
2617 (streq_ptr(i->active_state, "inactive") ||
2618 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
2619 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
2620 i->active_exit_timestamp;
2622 s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
2623 s2 = format_timestamp(since2, sizeof(since2), timestamp);
2626 printf(" since %s; %s\n", s2, s1);
2628 printf(" since %s\n", s2);
2632 if (!i->condition_result && i->condition_timestamp > 0) {
2633 s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
2634 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
2636 printf(" start condition failed at %s%s%s\n",
2637 s2, s1 ? "; " : "", s1 ? s1 : "");
2638 if (i->failed_condition_trigger)
2639 printf(" none of the trigger conditions were met\n");
2640 else if (i->failed_condition)
2641 printf(" %s=%s%s was not met\n",
2642 i->failed_condition,
2643 i->failed_condition_negate ? "!" : "",
2644 i->failed_condition_param);
2648 printf(" Device: %s\n", i->sysfs_path);
2650 printf(" Where: %s\n", i->where);
2652 printf(" What: %s\n", i->what);
2654 STRV_FOREACH(t, i->documentation)
2655 printf(" %*s %s\n", 9, t == i->documentation ? "Docs:" : "", *t);
2657 STRV_FOREACH_PAIR(t, t2, i->listen)
2658 printf(" %*s %s (%s)\n", 9, t == i->listen ? "Listen:" : "", *t2, *t);
2661 printf(" Accepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
2663 LIST_FOREACH(exec, p, i->exec) {
2664 _cleanup_free_ char *argv = NULL;
2667 /* Only show exited processes here */
2671 argv = strv_join(p->argv, " ");
2672 printf(" Process: %u %s=%s ", p->pid, p->name, strna(argv));
2674 good = is_clean_exit_lsb(p->code, p->status, NULL);
2676 on = ansi_highlight_red();
2677 off = ansi_highlight_off();
2681 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
2683 if (p->code == CLD_EXITED) {
2686 printf("status=%i", p->status);
2688 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
2693 printf("signal=%s", signal_to_string(p->status));
2695 printf(")%s\n", off);
2697 if (i->main_pid == p->pid &&
2698 i->start_timestamp == p->start_timestamp &&
2699 i->exit_timestamp == p->start_timestamp)
2700 /* Let's not show this twice */
2703 if (p->pid == i->control_pid)
2707 if (i->main_pid > 0 || i->control_pid > 0) {
2708 if (i->main_pid > 0) {
2709 printf(" Main PID: %u", (unsigned) i->main_pid);
2712 _cleanup_free_ char *comm = NULL;
2713 get_process_comm(i->main_pid, &comm);
2715 printf(" (%s)", comm);
2716 } else if (i->exit_code > 0) {
2717 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
2719 if (i->exit_code == CLD_EXITED) {
2722 printf("status=%i", i->exit_status);
2724 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
2729 printf("signal=%s", signal_to_string(i->exit_status));
2733 if (i->control_pid > 0)
2737 if (i->control_pid > 0) {
2738 _cleanup_free_ char *c = NULL;
2740 printf(" %8s: %u", i->main_pid ? "" : " Control", (unsigned) i->control_pid);
2742 get_process_comm(i->control_pid, &c);
2751 printf(" Status: \"%s\"\n", i->status_text);
2753 if (i->control_group &&
2754 (i->main_pid > 0 || i->control_pid > 0 || cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, i->control_group, false) == 0)) {
2757 printf(" CGroup: %s\n", i->control_group);
2759 if (arg_transport != TRANSPORT_SSH) {
2762 char prefix[] = " ";
2765 if (c > sizeof(prefix) - 1)
2766 c -= sizeof(prefix) - 1;
2770 if (i->main_pid > 0)
2771 extra[k++] = i->main_pid;
2773 if (i->control_pid > 0)
2774 extra[k++] = i->control_pid;
2776 show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, i->control_group, prefix,
2777 c, false, extra, k, flags);
2781 if (i->id && arg_transport != TRANSPORT_SSH) {
2783 show_journal_by_unit(stdout,
2787 i->inactive_exit_timestamp_monotonic,
2791 arg_scope == UNIT_FILE_SYSTEM,
2795 if (i->need_daemon_reload)
2796 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %sdaemon-reload' recommended.\n",
2797 ansi_highlight_red(),
2798 ansi_highlight_off(),
2799 arg_scope == UNIT_FILE_SYSTEM ? "" : "--user ");
2802 static void show_unit_help(UnitStatusInfo *i) {
2807 if (!i->documentation) {
2808 log_info("Documentation for %s not known.", i->id);
2812 STRV_FOREACH(p, i->documentation) {
2814 if (startswith(*p, "man:")) {
2817 _cleanup_free_ char *page = NULL, *section = NULL;
2818 const char *args[4] = { "man", NULL, NULL, NULL };
2823 if ((*p)[k-1] == ')')
2824 e = strrchr(*p, '(');
2827 page = strndup((*p) + 4, e - *p - 4);
2828 section = strndup(e + 1, *p + k - e - 2);
2829 if (!page || !section) {
2841 log_error("Failed to fork: %m");
2847 execvp(args[0], (char**) args);
2848 log_error("Failed to execute man: %m");
2849 _exit(EXIT_FAILURE);
2852 wait_for_terminate(pid, NULL);
2854 log_info("Can't show: %s", *p);
2858 static int status_property(const char *name, DBusMessageIter *iter, UnitStatusInfo *i) {
2864 switch (dbus_message_iter_get_arg_type(iter)) {
2866 case DBUS_TYPE_STRING: {
2869 dbus_message_iter_get_basic(iter, &s);
2872 if (streq(name, "Id"))
2874 else if (streq(name, "LoadState"))
2876 else if (streq(name, "ActiveState"))
2877 i->active_state = s;
2878 else if (streq(name, "SubState"))
2880 else if (streq(name, "Description"))
2882 else if (streq(name, "FragmentPath"))
2883 i->fragment_path = s;
2884 else if (streq(name, "SourcePath"))
2887 else if (streq(name, "DefaultControlGroup")) {
2889 e = startswith(s, SYSTEMD_CGROUP_CONTROLLER ":");
2891 i->control_group = e;
2894 else if (streq(name, "ControlGroup"))
2895 i->control_group = s;
2896 else if (streq(name, "StatusText"))
2898 else if (streq(name, "PIDFile"))
2900 else if (streq(name, "SysFSPath"))
2902 else if (streq(name, "Where"))
2904 else if (streq(name, "What"))
2906 else if (streq(name, "Following"))
2908 else if (streq(name, "UnitFileState"))
2909 i->unit_file_state = s;
2910 else if (streq(name, "Result"))
2917 case DBUS_TYPE_BOOLEAN: {
2920 dbus_message_iter_get_basic(iter, &b);
2922 if (streq(name, "Accept"))
2924 else if (streq(name, "NeedDaemonReload"))
2925 i->need_daemon_reload = b;
2926 else if (streq(name, "ConditionResult"))
2927 i->condition_result = b;
2932 case DBUS_TYPE_UINT32: {
2935 dbus_message_iter_get_basic(iter, &u);
2937 if (streq(name, "MainPID")) {
2939 i->main_pid = (pid_t) u;
2942 } else if (streq(name, "ControlPID"))
2943 i->control_pid = (pid_t) u;
2944 else if (streq(name, "ExecMainPID")) {
2946 i->main_pid = (pid_t) u;
2947 } else if (streq(name, "NAccepted"))
2949 else if (streq(name, "NConnections"))
2950 i->n_connections = u;
2955 case DBUS_TYPE_INT32: {
2958 dbus_message_iter_get_basic(iter, &j);
2960 if (streq(name, "ExecMainCode"))
2961 i->exit_code = (int) j;
2962 else if (streq(name, "ExecMainStatus"))
2963 i->exit_status = (int) j;
2968 case DBUS_TYPE_UINT64: {
2971 dbus_message_iter_get_basic(iter, &u);
2973 if (streq(name, "ExecMainStartTimestamp"))
2974 i->start_timestamp = (usec_t) u;
2975 else if (streq(name, "ExecMainExitTimestamp"))
2976 i->exit_timestamp = (usec_t) u;
2977 else if (streq(name, "ActiveEnterTimestamp"))
2978 i->active_enter_timestamp = (usec_t) u;
2979 else if (streq(name, "InactiveEnterTimestamp"))
2980 i->inactive_enter_timestamp = (usec_t) u;
2981 else if (streq(name, "InactiveExitTimestamp"))
2982 i->inactive_exit_timestamp = (usec_t) u;
2983 else if (streq(name, "InactiveExitTimestampMonotonic"))
2984 i->inactive_exit_timestamp_monotonic = (usec_t) u;
2985 else if (streq(name, "ActiveExitTimestamp"))
2986 i->active_exit_timestamp = (usec_t) u;
2987 else if (streq(name, "ConditionTimestamp"))
2988 i->condition_timestamp = (usec_t) u;
2993 case DBUS_TYPE_ARRAY: {
2995 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
2996 startswith(name, "Exec")) {
2997 DBusMessageIter sub;
2999 dbus_message_iter_recurse(iter, &sub);
3000 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3001 ExecStatusInfo *info;
3004 info = new0(ExecStatusInfo, 1);
3008 info->name = strdup(name);
3014 r = exec_status_info_deserialize(&sub, info);
3020 LIST_PREPEND(ExecStatusInfo, exec, i->exec, info);
3022 dbus_message_iter_next(&sub);
3025 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
3026 streq(name, "Listen")) {
3027 DBusMessageIter sub, sub2;
3029 dbus_message_iter_recurse(iter, &sub);
3030 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3031 const char *type, *path;
3033 dbus_message_iter_recurse(&sub, &sub2);
3035 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
3036 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0) {
3039 r = strv_extend(&i->listen, type);
3042 r = strv_extend(&i->listen, path);
3047 dbus_message_iter_next(&sub);
3052 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
3053 streq(name, "DropInPaths")) {
3054 int r = bus_parse_strv_iter(iter, &i->dropin_paths);
3058 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
3059 streq(name, "Documentation")) {
3061 DBusMessageIter sub;
3063 dbus_message_iter_recurse(iter, &sub);
3064 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING) {
3068 dbus_message_iter_get_basic(&sub, &s);
3070 r = strv_extend(&i->documentation, s);
3074 dbus_message_iter_next(&sub);
3077 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
3078 streq(name, "Conditions")) {
3079 DBusMessageIter sub, sub2;
3081 dbus_message_iter_recurse(iter, &sub);
3082 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3083 const char *cond, *param;
3084 dbus_bool_t trigger, negate;
3087 dbus_message_iter_recurse(&sub, &sub2);
3090 if(bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &cond, true) >= 0 &&
3091 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &trigger, true) >= 0 &&
3092 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &negate, true) >= 0 &&
3093 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, ¶m, true) >= 0 &&
3094 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &state, false) >= 0) {
3095 log_debug("%s %d %d %s %d", cond, trigger, negate, param, state);
3096 if (state < 0 && (!trigger || !i->failed_condition)) {
3097 i->failed_condition = cond;
3098 i->failed_condition_trigger = trigger;
3099 i->failed_condition_negate = negate;
3100 i->failed_condition_param = param;
3104 dbus_message_iter_next(&sub);
3111 case DBUS_TYPE_STRUCT: {
3113 if (streq(name, "LoadError")) {
3114 DBusMessageIter sub;
3115 const char *n, *message;
3118 dbus_message_iter_recurse(iter, &sub);
3120 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &n, true);
3124 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &message, false);
3128 if (!isempty(message))
3129 i->load_error = message;
3139 static int print_property(const char *name, DBusMessageIter *iter) {
3143 /* This is a low-level property printer, see
3144 * print_status_info() for the nicer output */
3146 if (arg_properties && !strv_find(arg_properties, name))
3149 switch (dbus_message_iter_get_arg_type(iter)) {
3151 case DBUS_TYPE_STRUCT: {
3152 DBusMessageIter sub;
3153 dbus_message_iter_recurse(iter, &sub);
3155 if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32 && streq(name, "Job")) {
3158 dbus_message_iter_get_basic(&sub, &u);
3161 printf("%s=%u\n", name, (unsigned) u);
3163 printf("%s=\n", name);
3166 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "Unit")) {
3169 dbus_message_iter_get_basic(&sub, &s);
3171 if (arg_all || s[0])
3172 printf("%s=%s\n", name, s);
3175 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "LoadError")) {
3176 const char *a = NULL, *b = NULL;
3178 if (bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &a, true) >= 0)
3179 bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &b, false);
3181 if (arg_all || !isempty(a) || !isempty(b))
3182 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
3190 case DBUS_TYPE_ARRAY:
3192 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "EnvironmentFiles")) {
3193 DBusMessageIter sub, sub2;
3195 dbus_message_iter_recurse(iter, &sub);
3196 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3200 dbus_message_iter_recurse(&sub, &sub2);
3202 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
3203 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) >= 0)
3204 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
3206 dbus_message_iter_next(&sub);
3211 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Paths")) {
3212 DBusMessageIter sub, sub2;
3214 dbus_message_iter_recurse(iter, &sub);
3216 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3217 const char *type, *path;
3219 dbus_message_iter_recurse(&sub, &sub2);
3221 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
3222 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
3223 printf("%s=%s\n", type, path);
3225 dbus_message_iter_next(&sub);
3230 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Listen")) {
3231 DBusMessageIter sub, sub2;
3233 dbus_message_iter_recurse(iter, &sub);
3234 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3235 const char *type, *path;
3237 dbus_message_iter_recurse(&sub, &sub2);
3239 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
3240 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
3241 printf("Listen%s=%s\n", type, path);
3243 dbus_message_iter_next(&sub);
3248 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Timers")) {
3249 DBusMessageIter sub, sub2;
3251 dbus_message_iter_recurse(iter, &sub);
3252 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3254 uint64_t value, next_elapse;
3256 dbus_message_iter_recurse(&sub, &sub2);
3258 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &base, true) >= 0 &&
3259 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &value, true) >= 0 &&
3260 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &next_elapse, false) >= 0) {
3261 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
3263 printf("%s={ value=%s ; next_elapse=%s }\n",
3265 format_timespan(timespan1, sizeof(timespan1), value, 0),
3266 format_timespan(timespan2, sizeof(timespan2), next_elapse, 0));
3269 dbus_message_iter_next(&sub);
3274 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && startswith(name, "Exec")) {
3275 DBusMessageIter sub;
3277 dbus_message_iter_recurse(iter, &sub);
3278 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3279 ExecStatusInfo info = {};
3281 if (exec_status_info_deserialize(&sub, &info) >= 0) {
3282 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
3283 _cleanup_free_ char *t;
3285 t = strv_join(info.argv, " ");
3287 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
3291 yes_no(info.ignore),
3292 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
3293 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
3294 (unsigned) info. pid,
3295 sigchld_code_to_string(info.code),
3297 info.code == CLD_EXITED ? "" : "/",
3298 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
3302 strv_free(info.argv);
3304 dbus_message_iter_next(&sub);
3309 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "DeviceAllow")) {
3310 DBusMessageIter sub, sub2;
3312 dbus_message_iter_recurse(iter, &sub);
3313 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3314 const char *path, *rwm;
3316 dbus_message_iter_recurse(&sub, &sub2);
3318 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
3319 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &rwm, false) >= 0)
3320 printf("%s=%s %s\n", name, strna(path), strna(rwm));
3322 dbus_message_iter_next(&sub);
3326 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "BlockIODeviceWeight")) {
3327 DBusMessageIter sub, sub2;
3329 dbus_message_iter_recurse(iter, &sub);
3330 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3334 dbus_message_iter_recurse(&sub, &sub2);
3336 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
3337 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &weight, false) >= 0)
3338 printf("%s=%s %" PRIu64 "\n", name, strna(path), weight);
3340 dbus_message_iter_next(&sub);
3344 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && (streq(name, "BlockIOReadBandwidth") || streq(name, "BlockIOWriteBandwidth"))) {
3345 DBusMessageIter sub, sub2;
3347 dbus_message_iter_recurse(iter, &sub);
3348 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3352 dbus_message_iter_recurse(&sub, &sub2);
3354 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
3355 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &bandwidth, false) >= 0)
3356 printf("%s=%s %" PRIu64 "\n", name, strna(path), bandwidth);
3358 dbus_message_iter_next(&sub);
3367 if (generic_print_property(name, iter, arg_all) > 0)
3371 printf("%s=[unprintable]\n", name);
3376 static int show_one(const char *verb,
3377 DBusConnection *bus,
3379 bool show_properties,
3382 _cleanup_free_ DBusMessage *reply = NULL;
3383 const char *interface = "";
3385 DBusMessageIter iter, sub, sub2, sub3;
3386 UnitStatusInfo info = {};
3392 r = bus_method_call_with_reply(
3394 "org.freedesktop.systemd1",
3396 "org.freedesktop.DBus.Properties",
3400 DBUS_TYPE_STRING, &interface,
3405 if (!dbus_message_iter_init(reply, &iter) ||
3406 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3407 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
3408 log_error("Failed to parse reply.");
3412 dbus_message_iter_recurse(&iter, &sub);
3419 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
3422 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_DICT_ENTRY);
3423 dbus_message_iter_recurse(&sub, &sub2);
3425 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
3426 dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
3427 log_error("Failed to parse reply.");
3431 dbus_message_iter_recurse(&sub2, &sub3);
3433 if (show_properties)
3434 r = print_property(name, &sub3);
3436 r = status_property(name, &sub3, &info);
3438 log_error("Failed to parse reply.");
3442 dbus_message_iter_next(&sub);
3447 if (!show_properties) {
3448 if (streq(verb, "help"))
3449 show_unit_help(&info);
3451 print_status_info(&info, ellipsized);
3454 strv_free(info.documentation);
3455 strv_free(info.dropin_paths);
3456 strv_free(info.listen);
3458 if (!streq_ptr(info.active_state, "active") &&
3459 !streq_ptr(info.active_state, "reloading") &&
3460 streq(verb, "status")) {
3461 /* According to LSB: "program not running" */
3462 /* 0: program is running or service is OK
3463 * 1: program is dead and /var/run pid file exists
3464 * 2: program is dead and /var/lock lock file exists
3465 * 3: program is not running
3466 * 4: program or service status is unknown
3468 if (info.pid_file && access(info.pid_file, F_OK) == 0)
3474 while ((p = info.exec)) {
3475 LIST_REMOVE(ExecStatusInfo, exec, info.exec, p);
3476 exec_status_info_free(p);
3482 static int show_one_by_pid(const char *verb,
3483 DBusConnection *bus,
3487 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3488 const char *path = NULL;
3489 _cleanup_dbus_error_free_ DBusError error;
3492 dbus_error_init(&error);
3494 r = bus_method_call_with_reply(
3496 "org.freedesktop.systemd1",
3497 "/org/freedesktop/systemd1",
3498 "org.freedesktop.systemd1.Manager",
3502 DBUS_TYPE_UINT32, &pid,
3507 if (!dbus_message_get_args(reply, &error,
3508 DBUS_TYPE_OBJECT_PATH, &path,
3509 DBUS_TYPE_INVALID)) {
3510 log_error("Failed to parse reply: %s", bus_error_message(&error));
3514 r = show_one(verb, bus, path, false, new_line, ellipsized);
3518 static int show_all(const char* verb,
3519 DBusConnection *bus,
3520 bool show_properties,
3523 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3524 _cleanup_free_ struct unit_info *unit_infos = NULL;
3526 const struct unit_info *u;
3529 r = get_unit_list(bus, &reply, &unit_infos, &c);
3533 qsort(unit_infos, c, sizeof(struct unit_info), compare_unit_info);
3535 for (u = unit_infos; u < unit_infos + c; u++) {
3536 _cleanup_free_ char *p = NULL;
3538 if (!output_show_unit(u))
3541 p = unit_dbus_path_from_name(u->id);
3545 printf("%s -> '%s'\n", u->id, p);
3547 r = show_one(verb, bus, p, show_properties, new_line, ellipsized);
3555 static int show(DBusConnection *bus, char **args) {
3557 bool show_properties, show_status, new_line = false;
3559 bool ellipsized = false;
3564 show_properties = streq(args[0], "show");
3565 show_status = streq(args[0], "status");
3567 if (show_properties)
3568 pager_open_if_enabled();
3570 /* If no argument is specified inspect the manager itself */
3572 if (show_properties && strv_length(args) <= 1)
3573 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line, &ellipsized);
3575 if (show_status && strv_length(args) <= 1)
3576 ret = show_all(args[0], bus, false, &new_line, &ellipsized);
3578 STRV_FOREACH(name, args+1) {
3581 if (safe_atou32(*name, &id) < 0) {
3582 _cleanup_free_ char *p = NULL, *n = NULL;
3583 /* Interpret as unit name */
3585 n = unit_name_mangle(*name);
3589 p = unit_dbus_path_from_name(n);
3593 r = show_one(args[0], bus, p, show_properties, &new_line, &ellipsized);
3597 } else if (show_properties) {
3598 _cleanup_free_ char *p = NULL;
3600 /* Interpret as job id */
3601 if (asprintf(&p, "/org/freedesktop/systemd1/job/%u", id) < 0)
3604 r = show_one(args[0], bus, p, show_properties, &new_line, &ellipsized);
3609 /* Interpret as PID */
3610 r = show_one_by_pid(args[0], bus, id, &new_line, &ellipsized);
3616 if (ellipsized && !arg_quiet)
3617 printf("Hint: Some lines were ellipsized, use -l to show in full.\n");
3622 static int append_assignment(DBusMessageIter *iter, const char *assignment) {
3625 DBusMessageIter sub;
3631 eq = strchr(assignment, '=');
3633 log_error("Not an assignment: %s", assignment);
3637 field = strndupa(assignment, eq - assignment);
3640 if (!dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &field))
3643 if (streq(field, "CPUAccounting") ||
3644 streq(field, "MemoryAccounting") ||
3645 streq(field, "BlockIOAccounting")) {
3648 r = parse_boolean(eq);
3650 log_error("Failed to parse boolean assignment %s.", assignment);
3655 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "b", &sub) ||
3656 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_BOOLEAN, &b))
3659 } else if (streq(field, "MemoryLimit") || streq(field, "MemorySoftLimit")) {
3663 r = parse_bytes(eq, &bytes);
3665 log_error("Failed to parse bytes specification %s", assignment);
3670 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "t", &sub) ||
3671 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_UINT64, &u))
3674 } else if (streq(field, "CPUShares") || streq(field, "BlockIOWeight")) {
3677 r = safe_atou64(eq, &u);
3679 log_error("Failed to parse %s value %s.", field, eq);
3683 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "t", &sub) ||
3684 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_UINT64, &u))
3687 } else if (streq(field, "DevicePolicy")) {
3689 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "s", &sub) ||
3690 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &eq))
3693 } else if (streq(field, "DeviceAllow")) {
3694 DBusMessageIter sub2;
3696 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "a(ss)", &sub) ||
3697 !dbus_message_iter_open_container(&sub, DBUS_TYPE_ARRAY, "(ss)", &sub2))
3701 const char *path, *rwm;
3702 DBusMessageIter sub3;
3705 e = strchr(eq, ' ');
3707 path = strndupa(eq, e - eq);
3714 if (!path_startswith(path, "/dev")) {
3715 log_error("%s is not a device file in /dev.", path);
3719 if (!dbus_message_iter_open_container(&sub2, DBUS_TYPE_STRUCT, NULL, &sub3) ||
3720 !dbus_message_iter_append_basic(&sub3, DBUS_TYPE_STRING, &path) ||
3721 !dbus_message_iter_append_basic(&sub3, DBUS_TYPE_STRING, &rwm) ||
3722 !dbus_message_iter_close_container(&sub2, &sub3))
3726 if (!dbus_message_iter_close_container(&sub, &sub2))
3729 } else if (streq(field, "BlockIOReadBandwidth") || streq(field, "BlockIOWriteBandwidth")) {
3730 DBusMessageIter sub2;
3732 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "a(st)", &sub) ||
3733 !dbus_message_iter_open_container(&sub, DBUS_TYPE_ARRAY, "(st)", &sub2))
3737 const char *path, *bandwidth;
3738 DBusMessageIter sub3;
3743 e = strchr(eq, ' ');
3745 path = strndupa(eq, e - eq);
3748 log_error("Failed to parse %s value %s.", field, eq);
3752 if (!path_startswith(path, "/dev")) {
3753 log_error("%s is not a device file in /dev.", path);
3757 r = parse_bytes(bandwidth, &bytes);
3759 log_error("Failed to parse byte value %s.", bandwidth);
3763 u = (uint64_t) bytes;
3765 if (!dbus_message_iter_open_container(&sub2, DBUS_TYPE_STRUCT, NULL, &sub3) ||
3766 !dbus_message_iter_append_basic(&sub3, DBUS_TYPE_STRING, &path) ||
3767 !dbus_message_iter_append_basic(&sub3, DBUS_TYPE_UINT64, &u) ||
3768 !dbus_message_iter_close_container(&sub2, &sub3))
3772 if (!dbus_message_iter_close_container(&sub, &sub2))
3775 } else if (streq(field, "BlockIODeviceWeight")) {
3776 DBusMessageIter sub2;
3778 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "a(st)", &sub) ||
3779 !dbus_message_iter_open_container(&sub, DBUS_TYPE_ARRAY, "(st)", &sub2))
3783 const char *path, *weight;
3784 DBusMessageIter sub3;
3788 e = strchr(eq, ' ');
3790 path = strndupa(eq, e - eq);
3793 log_error("Failed to parse %s value %s.", field, eq);
3797 if (!path_startswith(path, "/dev")) {
3798 log_error("%s is not a device file in /dev.", path);
3802 r = safe_atou64(weight, &u);
3804 log_error("Failed to parse %s value %s.", field, weight);
3807 if (!dbus_message_iter_open_container(&sub2, DBUS_TYPE_STRUCT, NULL, &sub3) ||
3808 !dbus_message_iter_append_basic(&sub3, DBUS_TYPE_STRING, &path) ||
3809 !dbus_message_iter_append_basic(&sub3, DBUS_TYPE_UINT64, &u) ||
3810 !dbus_message_iter_close_container(&sub2, &sub3))
3814 if (!dbus_message_iter_close_container(&sub, &sub2))
3818 log_error("Unknown assignment %s.", assignment);
3822 if (!dbus_message_iter_close_container(iter, &sub))
3828 static int set_property(DBusConnection *bus, char **args) {
3830 _cleanup_free_ DBusMessage *m = NULL, *reply = NULL;
3831 DBusMessageIter iter, sub;
3832 dbus_bool_t runtime;
3837 dbus_error_init(&error);
3839 m = dbus_message_new_method_call(
3840 "org.freedesktop.systemd1",
3841 "/org/freedesktop/systemd1",
3842 "org.freedesktop.systemd1.Manager",
3843 "SetUnitProperties");
3847 dbus_message_iter_init_append(m, &iter);
3849 runtime = arg_runtime;
3851 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &args[1]) ||
3852 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &runtime) ||
3853 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(sv)", &sub))
3856 STRV_FOREACH(i, args + 2) {
3857 DBusMessageIter sub2;
3859 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
3862 r = append_assignment(&sub2, *i);
3866 if (!dbus_message_iter_close_container(&sub, &sub2))
3871 if (!dbus_message_iter_close_container(&iter, &sub))
3874 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3876 log_error("Failed to issue method call: %s", bus_error_message(&error));
3877 dbus_error_free(&error);
3884 static int snapshot(DBusConnection *bus, char **args) {
3885 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3888 dbus_bool_t cleanup = FALSE;
3889 DBusMessageIter iter, sub;
3892 *interface = "org.freedesktop.systemd1.Unit",
3894 _cleanup_free_ char *n = NULL;
3896 dbus_error_init(&error);
3898 if (strv_length(args) > 1)
3899 n = unit_name_mangle_with_suffix(args[1], ".snapshot");
3905 r = bus_method_call_with_reply(
3907 "org.freedesktop.systemd1",
3908 "/org/freedesktop/systemd1",
3909 "org.freedesktop.systemd1.Manager",
3913 DBUS_TYPE_STRING, &n,
3914 DBUS_TYPE_BOOLEAN, &cleanup,
3919 if (!dbus_message_get_args(reply, &error,
3920 DBUS_TYPE_OBJECT_PATH, &path,
3921 DBUS_TYPE_INVALID)) {
3922 log_error("Failed to parse reply: %s", bus_error_message(&error));
3923 dbus_error_free(&error);
3927 dbus_message_unref(reply);
3930 r = bus_method_call_with_reply (
3932 "org.freedesktop.systemd1",
3934 "org.freedesktop.DBus.Properties",
3938 DBUS_TYPE_STRING, &interface,
3939 DBUS_TYPE_STRING, &property,
3944 if (!dbus_message_iter_init(reply, &iter) ||
3945 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3946 log_error("Failed to parse reply.");
3950 dbus_message_iter_recurse(&iter, &sub);
3952 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
3953 log_error("Failed to parse reply.");
3957 dbus_message_iter_get_basic(&sub, &id);
3965 static int delete_snapshot(DBusConnection *bus, char **args) {
3970 STRV_FOREACH(name, args+1) {
3971 _cleanup_free_ char *n = NULL;
3974 n = unit_name_mangle_with_suffix(*name, ".snapshot");
3978 r = bus_method_call_with_reply(
3980 "org.freedesktop.systemd1",
3981 "/org/freedesktop/systemd1",
3982 "org.freedesktop.systemd1.Manager",
3986 DBUS_TYPE_STRING, &n,
3995 static int daemon_reload(DBusConnection *bus, char **args) {
4000 if (arg_action == ACTION_RELOAD)
4002 else if (arg_action == ACTION_REEXEC)
4003 method = "Reexecute";
4005 assert(arg_action == ACTION_SYSTEMCTL);
4008 streq(args[0], "clear-jobs") ||
4009 streq(args[0], "cancel") ? "ClearJobs" :
4010 streq(args[0], "daemon-reexec") ? "Reexecute" :
4011 streq(args[0], "reset-failed") ? "ResetFailed" :
4012 streq(args[0], "halt") ? "Halt" :
4013 streq(args[0], "poweroff") ? "PowerOff" :
4014 streq(args[0], "reboot") ? "Reboot" :
4015 streq(args[0], "kexec") ? "KExec" :
4016 streq(args[0], "exit") ? "Exit" :
4017 /* "daemon-reload" */ "Reload";
4020 r = bus_method_call_with_reply(
4022 "org.freedesktop.systemd1",
4023 "/org/freedesktop/systemd1",
4024 "org.freedesktop.systemd1.Manager",
4030 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
4031 /* There's always a fallback possible for
4032 * legacy actions. */
4034 else if ((r == -ETIMEDOUT || r == -ECONNRESET) && streq(method, "Reexecute"))
4035 /* On reexecution, we expect a disconnect, not a
4039 log_error("Failed to issue method call: %s", bus_error_message(&error));
4041 dbus_error_free(&error);
4045 static int reset_failed(DBusConnection *bus, char **args) {
4049 if (strv_length(args) <= 1)
4050 return daemon_reload(bus, args);
4052 STRV_FOREACH(name, args+1) {
4053 _cleanup_free_ char *n;
4055 n = unit_name_mangle(*name);
4059 r = bus_method_call_with_reply(
4061 "org.freedesktop.systemd1",
4062 "/org/freedesktop/systemd1",
4063 "org.freedesktop.systemd1.Manager",
4067 DBUS_TYPE_STRING, &n,
4076 static int show_enviroment(DBusConnection *bus, char **args) {
4077 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
4078 DBusMessageIter iter, sub, sub2;
4081 *interface = "org.freedesktop.systemd1.Manager",
4082 *property = "Environment";
4084 pager_open_if_enabled();
4086 r = bus_method_call_with_reply(
4088 "org.freedesktop.systemd1",
4089 "/org/freedesktop/systemd1",
4090 "org.freedesktop.DBus.Properties",
4094 DBUS_TYPE_STRING, &interface,
4095 DBUS_TYPE_STRING, &property,
4100 if (!dbus_message_iter_init(reply, &iter) ||
4101 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
4102 log_error("Failed to parse reply.");
4106 dbus_message_iter_recurse(&iter, &sub);
4108 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_ARRAY ||
4109 dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_STRING) {
4110 log_error("Failed to parse reply.");
4114 dbus_message_iter_recurse(&sub, &sub2);
4116 while (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_INVALID) {
4119 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
4120 log_error("Failed to parse reply.");
4124 dbus_message_iter_get_basic(&sub2, &text);
4127 dbus_message_iter_next(&sub2);
4133 static int switch_root(DBusConnection *bus, char **args) {
4136 _cleanup_free_ char *init = NULL;
4138 l = strv_length(args);
4139 if (l < 2 || l > 3) {
4140 log_error("Wrong number of arguments.");
4147 init = strdup(args[2]);
4149 parse_env_file("/proc/cmdline", WHITESPACE,
4159 log_debug("switching root - root: %s; init: %s", root, init);
4161 return bus_method_call_with_reply(
4163 "org.freedesktop.systemd1",
4164 "/org/freedesktop/systemd1",
4165 "org.freedesktop.systemd1.Manager",
4169 DBUS_TYPE_STRING, &root,
4170 DBUS_TYPE_STRING, &init,
4174 static int set_environment(DBusConnection *bus, char **args) {
4175 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
4178 DBusMessageIter iter;
4184 dbus_error_init(&error);
4186 method = streq(args[0], "set-environment")
4188 : "UnsetEnvironment";
4190 m = dbus_message_new_method_call(
4191 "org.freedesktop.systemd1",
4192 "/org/freedesktop/systemd1",
4193 "org.freedesktop.systemd1.Manager",
4198 dbus_message_iter_init_append(m, &iter);
4200 r = bus_append_strv_iter(&iter, args + 1);
4204 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
4206 log_error("Failed to issue method call: %s", bus_error_message(&error));
4207 dbus_error_free(&error);
4214 static int enable_sysv_units(char **args) {
4217 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
4218 const char *verb = args[0];
4219 unsigned f = 1, t = 1;
4220 LookupPaths paths = {};
4222 if (arg_scope != UNIT_FILE_SYSTEM)
4225 if (!streq(verb, "enable") &&
4226 !streq(verb, "disable") &&
4227 !streq(verb, "is-enabled"))
4230 /* Processes all SysV units, and reshuffles the array so that
4231 * afterwards only the native units remain */
4233 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, NULL, NULL, NULL);
4238 for (f = 1; args[f]; f++) {
4240 _cleanup_free_ char *p = NULL, *q = NULL;
4241 bool found_native = false, found_sysv;
4243 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
4251 if (!endswith(name, ".service"))
4254 if (path_is_absolute(name))
4257 STRV_FOREACH(k, paths.unit_path) {
4258 if (!isempty(arg_root))
4259 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
4261 asprintf(&p, "%s/%s", *k, name);
4268 found_native = access(p, F_OK) >= 0;
4279 if (!isempty(arg_root))
4280 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
4282 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
4288 p[strlen(p) - sizeof(".service") + 1] = 0;
4289 found_sysv = access(p, F_OK) >= 0;
4294 /* Mark this entry, so that we don't try enabling it as native unit */
4295 args[f] = (char*) "";
4297 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
4299 if (!isempty(arg_root))
4300 argv[c++] = q = strappend("--root=", arg_root);
4302 argv[c++] = path_get_file_name(p);
4304 streq(verb, "enable") ? "on" :
4305 streq(verb, "disable") ? "off" : "--level=5";
4308 l = strv_join((char**)argv, " ");
4314 log_info("Executing %s", l);
4319 log_error("Failed to fork: %m");
4322 } else if (pid == 0) {
4325 execv(argv[0], (char**) argv);
4326 _exit(EXIT_FAILURE);
4329 j = wait_for_terminate(pid, &status);
4331 log_error("Failed to wait for child: %s", strerror(-r));
4336 if (status.si_code == CLD_EXITED) {
4337 if (streq(verb, "is-enabled")) {
4338 if (status.si_status == 0) {
4347 } else if (status.si_status != 0) {
4358 lookup_paths_free(&paths);
4360 /* Drop all SysV units */
4361 for (f = 1, t = 1; args[f]; f++) {
4363 if (isempty(args[f]))
4366 args[t++] = args[f];
4375 static int mangle_names(char **original_names, char ***mangled_names) {
4376 char **i, **l, **name;
4378 l = new(char*, strv_length(original_names) + 1);
4383 STRV_FOREACH(name, original_names) {
4385 /* When enabling units qualified path names are OK,
4386 * too, hence allow them explicitly. */
4391 *i = unit_name_mangle(*name);
4407 static int enable_unit(DBusConnection *bus, char **args) {
4408 const char *verb = args[0];
4409 UnitFileChange *changes = NULL;
4410 unsigned n_changes = 0, i;
4411 int carries_install_info = -1;
4412 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
4414 _cleanup_dbus_error_free_ DBusError error;
4415 _cleanup_strv_free_ char **mangled_names = NULL;
4417 dbus_error_init(&error);
4419 r = enable_sysv_units(args);
4426 r = mangle_names(args+1, &mangled_names);
4430 if (!bus || avoid_bus()) {
4431 if (streq(verb, "enable")) {
4432 r = unit_file_enable(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4433 carries_install_info = r;
4434 } else if (streq(verb, "disable"))
4435 r = unit_file_disable(arg_scope, arg_runtime, arg_root, mangled_names, &changes, &n_changes);
4436 else if (streq(verb, "reenable")) {
4437 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4438 carries_install_info = r;
4439 } else if (streq(verb, "link"))
4440 r = unit_file_link(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4441 else if (streq(verb, "preset")) {
4442 r = unit_file_preset(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4443 carries_install_info = r;
4444 } else if (streq(verb, "mask"))
4445 r = unit_file_mask(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4446 else if (streq(verb, "unmask"))
4447 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, mangled_names, &changes, &n_changes);
4448 else if (streq(verb, "set-default"))
4449 r = unit_file_set_default(arg_scope, arg_root, args[1], &changes, &n_changes);
4451 assert_not_reached("Unknown verb");
4454 log_error("Operation failed: %s", strerror(-r));
4459 for (i = 0; i < n_changes; i++) {
4460 if (changes[i].type == UNIT_FILE_SYMLINK)
4461 log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
4463 log_info("rm '%s'", changes[i].path);
4470 bool send_force = true, expect_carries_install_info = false;
4472 DBusMessageIter iter, sub, sub2;
4474 if (streq(verb, "enable")) {
4475 method = "EnableUnitFiles";
4476 expect_carries_install_info = true;
4477 } else if (streq(verb, "disable")) {
4478 method = "DisableUnitFiles";
4480 } else if (streq(verb, "reenable")) {
4481 method = "ReenableUnitFiles";
4482 expect_carries_install_info = true;
4483 } else if (streq(verb, "link"))
4484 method = "LinkUnitFiles";
4485 else if (streq(verb, "preset")) {
4486 method = "PresetUnitFiles";
4487 expect_carries_install_info = true;
4488 } else if (streq(verb, "mask"))
4489 method = "MaskUnitFiles";
4490 else if (streq(verb, "unmask")) {
4491 method = "UnmaskUnitFiles";
4493 } else if (streq(verb, "set-default")) {
4494 method = "SetDefaultTarget";
4496 assert_not_reached("Unknown verb");
4498 m = dbus_message_new_method_call(
4499 "org.freedesktop.systemd1",
4500 "/org/freedesktop/systemd1",
4501 "org.freedesktop.systemd1.Manager",
4508 dbus_message_iter_init_append(m, &iter);
4510 r = bus_append_strv_iter(&iter, mangled_names);
4512 log_error("Failed to append unit files.");
4517 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &a)) {
4518 log_error("Failed to append runtime boolean.");
4526 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b)) {
4527 log_error("Failed to append force boolean.");
4533 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
4535 log_error("Failed to issue method call: %s", bus_error_message(&error));
4540 if (!dbus_message_iter_init(reply, &iter)) {
4541 log_error("Failed to initialize iterator.");
4545 if (expect_carries_install_info) {
4546 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &b, true);
4548 log_error("Failed to parse reply.");
4552 carries_install_info = b;
4555 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
4556 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
4557 log_error("Failed to parse reply.");
4562 dbus_message_iter_recurse(&iter, &sub);
4563 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
4564 const char *type, *path, *source;
4566 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
4567 log_error("Failed to parse reply.");
4572 dbus_message_iter_recurse(&sub, &sub2);
4574 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
4575 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
4576 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &source, false) < 0) {
4577 log_error("Failed to parse reply.");
4583 if (streq(type, "symlink"))
4584 log_info("ln -s '%s' '%s'", source, path);
4586 log_info("rm '%s'", path);
4589 dbus_message_iter_next(&sub);
4592 /* Try to reload if enabeld */
4594 r = daemon_reload(bus, args);
4597 if (carries_install_info == 0)
4598 log_warning("The unit files have no [Install] section. They are not meant to be enabled\n"
4599 "using systemctl.\n"
4600 "Possible reasons for having this kind of units are:\n"
4601 "1) A unit may be statically enabled by being symlinked from another unit's\n"
4602 " .wants/ or .requires/ directory.\n"
4603 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
4604 " a requirement dependency on it.\n"
4605 "3) A unit may be started when needed via activation (socket, path, timer,\n"
4606 " D-Bus, udev, scripted systemctl call, ...).\n");
4609 unit_file_changes_free(changes, n_changes);
4614 static int unit_is_enabled(DBusConnection *bus, char **args) {
4615 _cleanup_dbus_error_free_ DBusError error;
4617 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
4622 dbus_error_init(&error);
4624 r = enable_sysv_units(args);
4630 if (!bus || avoid_bus()) {
4632 STRV_FOREACH(name, args+1) {
4633 UnitFileState state;
4635 n = unit_name_mangle(*name);
4639 state = unit_file_get_state(arg_scope, arg_root, n);
4646 if (state == UNIT_FILE_ENABLED ||
4647 state == UNIT_FILE_ENABLED_RUNTIME ||
4648 state == UNIT_FILE_STATIC)
4652 puts(unit_file_state_to_string(state));
4656 STRV_FOREACH(name, args+1) {
4659 n = unit_name_mangle(*name);
4663 r = bus_method_call_with_reply (
4665 "org.freedesktop.systemd1",
4666 "/org/freedesktop/systemd1",
4667 "org.freedesktop.systemd1.Manager",
4671 DBUS_TYPE_STRING, &n,
4679 if (!dbus_message_get_args(reply, &error,
4680 DBUS_TYPE_STRING, &s,
4681 DBUS_TYPE_INVALID)) {
4682 log_error("Failed to parse reply: %s", bus_error_message(&error));
4686 dbus_message_unref(reply);
4689 if (streq(s, "enabled") ||
4690 streq(s, "enabled-runtime") ||
4699 return enabled ? 0 : 1;
4702 static int systemctl_help(void) {
4704 pager_open_if_enabled();
4706 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
4707 "Query or send control commands to the systemd manager.\n\n"
4708 " -h --help Show this help\n"
4709 " --version Show package version\n"
4710 " -t --type=TYPE List only units of a particular type\n"
4711 " --state=STATE List only units with particular LOAD or SUB or ACTIVE state\n"
4712 " -p --property=NAME Show only properties by this name\n"
4713 " -a --all Show all loaded units/properties, including dead/empty\n"
4714 " ones. To list all units installed on the system, use\n"
4715 " the 'list-unit-files' command instead.\n"
4716 " --reverse Show reverse dependencies with 'list-dependencies'\n"
4717 " -l --full Don't ellipsize unit names on output\n"
4718 " --fail When queueing a new job, fail if conflicting jobs are\n"
4720 " --irreversible When queueing a new job, make sure it cannot be implicitly\n"
4722 " --ignore-dependencies\n"
4723 " When queueing a new job, ignore all its dependencies\n"
4724 " --show-types When showing sockets, explicitly show their type\n"
4725 " -i --ignore-inhibitors\n"
4726 " When shutting down or sleeping, ignore inhibitors\n"
4727 " --kill-who=WHO Who to send signal to\n"
4728 " -s --signal=SIGNAL Which signal to send\n"
4729 " -H --host=[USER@]HOST\n"
4730 " Show information for remote host\n"
4731 " -P --privileged Acquire privileges before execution\n"
4732 " -q --quiet Suppress output\n"
4733 " --no-block Do not wait until operation finished\n"
4734 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4735 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
4737 " --no-legend Do not print a legend (column headers and hints)\n"
4738 " --no-pager Do not pipe output into a pager\n"
4739 " --no-ask-password\n"
4740 " Do not ask for system passwords\n"
4741 " --system Connect to system manager\n"
4742 " --user Connect to user service manager\n"
4743 " --global Enable/disable unit files globally\n"
4744 " --runtime Enable unit files only temporarily until next reboot\n"
4745 " -f --force When enabling unit files, override existing symlinks\n"
4746 " When shutting down, execute action immediately\n"
4747 " --root=PATH Enable unit files in the specified root directory\n"
4748 " -n --lines=INTEGER Numer of journal entries to show\n"
4749 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
4750 " verbose, export, json, json-pretty, json-sse, cat)\n\n"
4752 " list-units List loaded units\n"
4753 " list-sockets List loaded sockets ordered by address\n"
4754 " start [NAME...] Start (activate) one or more units\n"
4755 " stop [NAME...] Stop (deactivate) one or more units\n"
4756 " reload [NAME...] Reload one or more units\n"
4757 " restart [NAME...] Start or restart one or more units\n"
4758 " try-restart [NAME...] Restart one or more units if active\n"
4759 " reload-or-restart [NAME...] Reload one or more units if possible,\n"
4760 " otherwise start or restart\n"
4761 " reload-or-try-restart [NAME...] Reload one or more units if possible,\n"
4762 " otherwise restart if active\n"
4763 " isolate [NAME] Start one unit and stop all others\n"
4764 " kill [NAME...] Send signal to processes of a unit\n"
4765 " is-active [NAME...] Check whether units are active\n"
4766 " is-failed [NAME...] Check whether units are failed\n"
4767 " status [NAME...|PID...] Show runtime status of one or more units\n"
4768 " show [NAME...|JOB...] Show properties of one or more\n"
4769 " units/jobs or the manager\n"
4770 " set-property [NAME] [ASSIGNMENT...]\n"
4771 " Sets one or more properties of a unit\n"
4772 " help [NAME...|PID...] Show manual for one or more units\n"
4773 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
4775 " list-dependencies [NAME] Recursively show units which are required\n"
4776 " or wanted by this unit or by which this\n"
4777 " unit is required or wanted\n\n"
4778 "Unit File Commands:\n"
4779 " list-unit-files List installed unit files\n"
4780 " enable [NAME...] Enable one or more unit files\n"
4781 " disable [NAME...] Disable one or more unit files\n"
4782 " reenable [NAME...] Reenable one or more unit files\n"
4783 " preset [NAME...] Enable/disable one or more unit files\n"
4784 " based on preset configuration\n"
4785 " is-enabled [NAME...] Check whether unit files are enabled\n\n"
4786 " mask [NAME...] Mask one or more units\n"
4787 " unmask [NAME...] Unmask one or more units\n"
4788 " link [PATH...] Link one or more units files into\n"
4789 " the search path\n"
4790 " get-default Get the name of the default target\n"
4791 " set-default NAME Set the default target\n\n"
4793 " list-jobs List jobs\n"
4794 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
4795 "Snapshot Commands:\n"
4796 " snapshot [NAME] Create a snapshot\n"
4797 " delete [NAME...] Remove one or more snapshots\n\n"
4798 "Environment Commands:\n"
4799 " show-environment Dump environment\n"
4800 " set-environment [NAME=VALUE...] Set one or more environment variables\n"
4801 " unset-environment [NAME...] Unset one or more environment variables\n\n"
4802 "Manager Lifecycle Commands:\n"
4803 " daemon-reload Reload systemd manager configuration\n"
4804 " daemon-reexec Reexecute systemd manager\n\n"
4805 "System Commands:\n"
4806 " default Enter system default mode\n"
4807 " rescue Enter system rescue mode\n"
4808 " emergency Enter system emergency mode\n"
4809 " halt Shut down and halt the system\n"
4810 " poweroff Shut down and power-off the system\n"
4811 " reboot Shut down and reboot the system\n"
4812 " kexec Shut down and reboot the system with kexec\n"
4813 " exit Request user instance exit\n"
4814 " switch-root [ROOT] [INIT] Change to a different root file system\n"
4815 " suspend Suspend the system\n"
4816 " hibernate Hibernate the system\n"
4817 " hybrid-sleep Hibernate and suspend the system\n",
4818 program_invocation_short_name);
4823 static int halt_help(void) {
4825 printf("%s [OPTIONS...]\n\n"
4826 "%s the system.\n\n"
4827 " --help Show this help\n"
4828 " --halt Halt the machine\n"
4829 " -p --poweroff Switch off the machine\n"
4830 " --reboot Reboot the machine\n"
4831 " -f --force Force immediate halt/power-off/reboot\n"
4832 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
4833 " -d --no-wtmp Don't write wtmp record\n"
4834 " --no-wall Don't send wall message before halt/power-off/reboot\n",
4835 program_invocation_short_name,
4836 arg_action == ACTION_REBOOT ? "Reboot" :
4837 arg_action == ACTION_POWEROFF ? "Power off" :
4843 static int shutdown_help(void) {
4845 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
4846 "Shut down the system.\n\n"
4847 " --help Show this help\n"
4848 " -H --halt Halt the machine\n"
4849 " -P --poweroff Power-off the machine\n"
4850 " -r --reboot Reboot the machine\n"
4851 " -h Equivalent to --poweroff, overridden by --halt\n"
4852 " -k Don't halt/power-off/reboot, just send warnings\n"
4853 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4854 " -c Cancel a pending shutdown\n",
4855 program_invocation_short_name);
4860 static int telinit_help(void) {
4862 printf("%s [OPTIONS...] {COMMAND}\n\n"
4863 "Send control commands to the init daemon.\n\n"
4864 " --help Show this help\n"
4865 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
4867 " 0 Power-off the machine\n"
4868 " 6 Reboot the machine\n"
4869 " 2, 3, 4, 5 Start runlevelX.target unit\n"
4870 " 1, s, S Enter rescue mode\n"
4871 " q, Q Reload init daemon configuration\n"
4872 " u, U Reexecute init daemon\n",
4873 program_invocation_short_name);
4878 static int runlevel_help(void) {
4880 printf("%s [OPTIONS...]\n\n"
4881 "Prints the previous and current runlevel of the init system.\n\n"
4882 " --help Show this help\n",
4883 program_invocation_short_name);
4888 static int help_types(void) {
4892 puts("Available unit types:");
4893 for(i = 0; i < _UNIT_TYPE_MAX; i++) {
4894 t = unit_type_to_string(i);
4902 static int systemctl_parse_argv(int argc, char *argv[]) {
4911 ARG_IGNORE_DEPENDENCIES,
4923 ARG_NO_ASK_PASSWORD,
4931 static const struct option options[] = {
4932 { "help", no_argument, NULL, 'h' },
4933 { "version", no_argument, NULL, ARG_VERSION },
4934 { "type", required_argument, NULL, 't' },
4935 { "property", required_argument, NULL, 'p' },
4936 { "all", no_argument, NULL, 'a' },
4937 { "reverse", no_argument, NULL, ARG_REVERSE },
4938 { "after", no_argument, NULL, ARG_AFTER },
4939 { "before", no_argument, NULL, ARG_BEFORE },
4940 { "show-types", no_argument, NULL, ARG_SHOW_TYPES },
4941 { "failed", no_argument, NULL, ARG_FAILED }, /* compatibility only */
4942 { "full", no_argument, NULL, 'l' },
4943 { "fail", no_argument, NULL, ARG_FAIL },
4944 { "irreversible", no_argument, NULL, ARG_IRREVERSIBLE },
4945 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
4946 { "ignore-inhibitors", no_argument, NULL, 'i' },
4947 { "user", no_argument, NULL, ARG_USER },
4948 { "system", no_argument, NULL, ARG_SYSTEM },
4949 { "global", no_argument, NULL, ARG_GLOBAL },
4950 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
4951 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
4952 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
4953 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4954 { "quiet", no_argument, NULL, 'q' },
4955 { "root", required_argument, NULL, ARG_ROOT },
4956 { "force", no_argument, NULL, ARG_FORCE },
4957 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
4958 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
4959 { "signal", required_argument, NULL, 's' },
4960 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
4961 { "host", required_argument, NULL, 'H' },
4962 { "privileged", no_argument, NULL, 'P' },
4963 { "runtime", no_argument, NULL, ARG_RUNTIME },
4964 { "lines", required_argument, NULL, 'n' },
4965 { "output", required_argument, NULL, 'o' },
4966 { "plain", no_argument, NULL, ARG_PLAIN },
4967 { "state", required_argument, NULL, ARG_STATE },
4968 { NULL, 0, NULL, 0 }
4976 while ((c = getopt_long(argc, argv, "ht:p:alqfs:H:Pn:o:i", options, NULL)) >= 0) {
4985 puts(PACKAGE_STRING);
4986 puts(SYSTEMD_FEATURES);
4993 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
4994 _cleanup_free_ char *type;
4996 type = strndup(word, size);
5000 if (streq(type, "help")) {
5005 if (unit_type_from_string(type) >= 0) {
5006 if (strv_push(&arg_types, type))
5012 /* It's much nicer to use --state= for
5013 * load states, but let's support this
5014 * in --types= too for compatibility
5015 * with old versions */
5016 if (unit_load_state_from_string(optarg) >= 0) {
5017 if (strv_push(&arg_states, type) < 0)
5023 log_error("Unknown unit type or load state '%s'.", type);
5024 log_info("Use -t help to see a list of allowed values.");
5032 /* Make sure that if the empty property list
5033 was specified, we won't show any properties. */
5034 if (isempty(optarg) && !arg_properties) {
5035 arg_properties = strv_new(NULL, NULL);
5036 if (!arg_properties)
5042 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
5045 prop = strndup(word, size);
5049 if (strv_push(&arg_properties, prop) < 0) {
5056 /* If the user asked for a particular
5057 * property, show it to him, even if it is
5069 arg_dependency = DEPENDENCY_REVERSE;
5073 arg_dependency = DEPENDENCY_AFTER;
5077 arg_dependency = DEPENDENCY_BEFORE;
5080 case ARG_SHOW_TYPES:
5081 arg_show_types = true;
5085 arg_job_mode = "fail";
5088 case ARG_IRREVERSIBLE:
5089 arg_job_mode = "replace-irreversibly";
5092 case ARG_IGNORE_DEPENDENCIES:
5093 arg_job_mode = "ignore-dependencies";
5097 arg_scope = UNIT_FILE_USER;
5101 arg_scope = UNIT_FILE_SYSTEM;
5105 arg_scope = UNIT_FILE_GLOBAL;
5109 arg_no_block = true;
5113 arg_no_legend = true;
5117 arg_no_pager = true;
5133 if (strv_extend(&arg_states, "failed") < 0)
5151 arg_no_reload = true;
5155 arg_kill_who = optarg;
5159 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
5160 log_error("Failed to parse signal string %s.", optarg);
5165 case ARG_NO_ASK_PASSWORD:
5166 arg_ask_password = false;
5170 arg_transport = TRANSPORT_POLKIT;
5174 arg_transport = TRANSPORT_SSH;
5175 parse_user_at_host(optarg, &arg_user, &arg_host);
5183 if (safe_atou(optarg, &arg_lines) < 0) {
5184 log_error("Failed to parse lines '%s'", optarg);
5190 arg_output = output_mode_from_string(optarg);
5191 if (arg_output < 0) {
5192 log_error("Unknown output '%s'.", optarg);
5198 arg_ignore_inhibitors = true;
5209 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
5212 s = strndup(word, size);
5216 if (strv_push(&arg_states, s) < 0) {
5228 log_error("Unknown option code '%c'.", c);
5233 if (arg_transport != TRANSPORT_NORMAL && arg_scope != UNIT_FILE_SYSTEM) {
5234 log_error("Cannot access user instance remotely.");
5241 static int halt_parse_argv(int argc, char *argv[]) {
5250 static const struct option options[] = {
5251 { "help", no_argument, NULL, ARG_HELP },
5252 { "halt", no_argument, NULL, ARG_HALT },
5253 { "poweroff", no_argument, NULL, 'p' },
5254 { "reboot", no_argument, NULL, ARG_REBOOT },
5255 { "force", no_argument, NULL, 'f' },
5256 { "wtmp-only", no_argument, NULL, 'w' },
5257 { "no-wtmp", no_argument, NULL, 'd' },
5258 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5259 { NULL, 0, NULL, 0 }
5267 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
5268 if (runlevel == '0' || runlevel == '6')
5271 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
5279 arg_action = ACTION_HALT;
5283 if (arg_action != ACTION_REBOOT)
5284 arg_action = ACTION_POWEROFF;
5288 arg_action = ACTION_REBOOT;
5310 /* Compatibility nops */
5317 log_error("Unknown option code '%c'.", c);
5322 if (optind < argc) {
5323 log_error("Too many arguments.");
5330 static int parse_time_spec(const char *t, usec_t *_u) {
5334 if (streq(t, "now"))
5336 else if (!strchr(t, ':')) {
5339 if (safe_atou64(t, &u) < 0)
5342 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
5351 hour = strtol(t, &e, 10);
5352 if (errno > 0 || *e != ':' || hour < 0 || hour > 23)
5355 minute = strtol(e+1, &e, 10);
5356 if (errno > 0 || *e != 0 || minute < 0 || minute > 59)
5359 n = now(CLOCK_REALTIME);
5360 s = (time_t) (n / USEC_PER_SEC);
5362 assert_se(localtime_r(&s, &tm));
5364 tm.tm_hour = (int) hour;
5365 tm.tm_min = (int) minute;
5368 assert_se(s = mktime(&tm));
5370 *_u = (usec_t) s * USEC_PER_SEC;
5373 *_u += USEC_PER_DAY;
5379 static int shutdown_parse_argv(int argc, char *argv[]) {
5386 static const struct option options[] = {
5387 { "help", no_argument, NULL, ARG_HELP },
5388 { "halt", no_argument, NULL, 'H' },
5389 { "poweroff", no_argument, NULL, 'P' },
5390 { "reboot", no_argument, NULL, 'r' },
5391 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
5392 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5393 { NULL, 0, NULL, 0 }
5401 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
5409 arg_action = ACTION_HALT;
5413 arg_action = ACTION_POWEROFF;
5418 arg_action = ACTION_KEXEC;
5420 arg_action = ACTION_REBOOT;
5424 arg_action = ACTION_KEXEC;
5428 if (arg_action != ACTION_HALT)
5429 arg_action = ACTION_POWEROFF;
5442 /* Compatibility nops */
5446 arg_action = ACTION_CANCEL_SHUTDOWN;
5453 log_error("Unknown option code '%c'.", c);
5458 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
5459 r = parse_time_spec(argv[optind], &arg_when);
5461 log_error("Failed to parse time specification: %s", argv[optind]);
5465 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
5467 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
5468 /* No time argument for shutdown cancel */
5469 arg_wall = argv + optind;
5470 else if (argc > optind + 1)
5471 /* We skip the time argument */
5472 arg_wall = argv + optind + 1;
5479 static int telinit_parse_argv(int argc, char *argv[]) {
5486 static const struct option options[] = {
5487 { "help", no_argument, NULL, ARG_HELP },
5488 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5489 { NULL, 0, NULL, 0 }
5492 static const struct {
5496 { '0', ACTION_POWEROFF },
5497 { '6', ACTION_REBOOT },
5498 { '1', ACTION_RESCUE },
5499 { '2', ACTION_RUNLEVEL2 },
5500 { '3', ACTION_RUNLEVEL3 },
5501 { '4', ACTION_RUNLEVEL4 },
5502 { '5', ACTION_RUNLEVEL5 },
5503 { 's', ACTION_RESCUE },
5504 { 'S', ACTION_RESCUE },
5505 { 'q', ACTION_RELOAD },
5506 { 'Q', ACTION_RELOAD },
5507 { 'u', ACTION_REEXEC },
5508 { 'U', ACTION_REEXEC }
5517 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
5532 log_error("Unknown option code '%c'.", c);
5537 if (optind >= argc) {
5542 if (optind + 1 < argc) {
5543 log_error("Too many arguments.");
5547 if (strlen(argv[optind]) != 1) {
5548 log_error("Expected single character argument.");
5552 for (i = 0; i < ELEMENTSOF(table); i++)
5553 if (table[i].from == argv[optind][0])
5556 if (i >= ELEMENTSOF(table)) {
5557 log_error("Unknown command '%s'.", argv[optind]);
5561 arg_action = table[i].to;
5568 static int runlevel_parse_argv(int argc, char *argv[]) {
5574 static const struct option options[] = {
5575 { "help", no_argument, NULL, ARG_HELP },
5576 { NULL, 0, NULL, 0 }
5584 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
5595 log_error("Unknown option code '%c'.", c);
5600 if (optind < argc) {
5601 log_error("Too many arguments.");
5608 static int parse_argv(int argc, char *argv[]) {
5612 if (program_invocation_short_name) {
5614 if (strstr(program_invocation_short_name, "halt")) {
5615 arg_action = ACTION_HALT;
5616 return halt_parse_argv(argc, argv);
5617 } else if (strstr(program_invocation_short_name, "poweroff")) {
5618 arg_action = ACTION_POWEROFF;
5619 return halt_parse_argv(argc, argv);
5620 } else if (strstr(program_invocation_short_name, "reboot")) {
5622 arg_action = ACTION_KEXEC;
5624 arg_action = ACTION_REBOOT;
5625 return halt_parse_argv(argc, argv);
5626 } else if (strstr(program_invocation_short_name, "shutdown")) {
5627 arg_action = ACTION_POWEROFF;
5628 return shutdown_parse_argv(argc, argv);
5629 } else if (strstr(program_invocation_short_name, "init")) {
5631 if (sd_booted() > 0) {
5632 arg_action = ACTION_INVALID;
5633 return telinit_parse_argv(argc, argv);
5635 /* Hmm, so some other init system is
5636 * running, we need to forward this
5637 * request to it. For now we simply
5638 * guess that it is Upstart. */
5640 execv(TELINIT, argv);
5642 log_error("Couldn't find an alternative telinit implementation to spawn.");
5646 } else if (strstr(program_invocation_short_name, "runlevel")) {
5647 arg_action = ACTION_RUNLEVEL;
5648 return runlevel_parse_argv(argc, argv);
5652 arg_action = ACTION_SYSTEMCTL;
5653 return systemctl_parse_argv(argc, argv);
5656 _pure_ static int action_to_runlevel(void) {
5658 static const char table[_ACTION_MAX] = {
5659 [ACTION_HALT] = '0',
5660 [ACTION_POWEROFF] = '0',
5661 [ACTION_REBOOT] = '6',
5662 [ACTION_RUNLEVEL2] = '2',
5663 [ACTION_RUNLEVEL3] = '3',
5664 [ACTION_RUNLEVEL4] = '4',
5665 [ACTION_RUNLEVEL5] = '5',
5666 [ACTION_RESCUE] = '1'
5669 assert(arg_action < _ACTION_MAX);
5671 return table[arg_action];
5674 static int talk_upstart(void) {
5675 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
5676 _cleanup_dbus_error_free_ DBusError error;
5677 int previous, rl, r;
5679 env1_buf[] = "RUNLEVEL=X",
5680 env2_buf[] = "PREVLEVEL=X";
5681 char *env1 = env1_buf, *env2 = env2_buf;
5682 const char *emit = "runlevel";
5683 dbus_bool_t b_false = FALSE;
5684 DBusMessageIter iter, sub;
5685 DBusConnection *bus;
5687 dbus_error_init(&error);
5689 if (!(rl = action_to_runlevel()))
5692 if (utmp_get_runlevel(&previous, NULL) < 0)
5695 if (!(bus = dbus_connection_open_private("unix:abstract=/com/ubuntu/upstart", &error))) {
5696 if (dbus_error_has_name(&error, DBUS_ERROR_NO_SERVER)) {
5701 log_error("Failed to connect to Upstart bus: %s", bus_error_message(&error));
5706 if ((r = bus_check_peercred(bus)) < 0) {
5707 log_error("Failed to verify owner of bus.");
5711 if (!(m = dbus_message_new_method_call(
5712 "com.ubuntu.Upstart",
5713 "/com/ubuntu/Upstart",
5714 "com.ubuntu.Upstart0_6",
5717 log_error("Could not allocate message.");
5722 dbus_message_iter_init_append(m, &iter);
5724 env1_buf[sizeof(env1_buf)-2] = rl;
5725 env2_buf[sizeof(env2_buf)-2] = previous;
5727 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &emit) ||
5728 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub) ||
5729 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env1) ||
5730 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env2) ||
5731 !dbus_message_iter_close_container(&iter, &sub) ||
5732 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b_false)) {
5733 log_error("Could not append arguments to message.");
5738 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
5740 if (bus_error_is_no_service(&error)) {
5745 log_error("Failed to issue method call: %s", bus_error_message(&error));
5754 dbus_connection_flush(bus);
5755 dbus_connection_close(bus);
5756 dbus_connection_unref(bus);
5762 static int talk_initctl(void) {
5763 struct init_request request = {};
5765 _cleanup_close_ int fd = -1;
5768 rl = action_to_runlevel();
5772 request.magic = INIT_MAGIC;
5773 request.sleeptime = 0;
5774 request.cmd = INIT_CMD_RUNLVL;
5775 request.runlevel = rl;
5777 fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY);
5779 if (errno == ENOENT)
5782 log_error("Failed to open "INIT_FIFO": %m");
5787 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
5789 log_error("Failed to write to "INIT_FIFO": %m");
5790 return errno > 0 ? -errno : -EIO;
5796 static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
5798 static const struct {
5806 int (* const dispatch)(DBusConnection *bus, char **args);
5808 { "list-units", LESS, 1, list_units },
5809 { "list-unit-files", EQUAL, 1, list_unit_files },
5810 { "list-sockets", LESS, 1, list_sockets },
5811 { "list-jobs", EQUAL, 1, list_jobs },
5812 { "clear-jobs", EQUAL, 1, daemon_reload },
5813 { "cancel", MORE, 2, cancel_job },
5814 { "start", MORE, 2, start_unit },
5815 { "stop", MORE, 2, start_unit },
5816 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5817 { "reload", MORE, 2, start_unit },
5818 { "restart", MORE, 2, start_unit },
5819 { "try-restart", MORE, 2, start_unit },
5820 { "reload-or-restart", MORE, 2, start_unit },
5821 { "reload-or-try-restart", MORE, 2, start_unit },
5822 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
5823 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5824 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
5825 { "isolate", EQUAL, 2, start_unit },
5826 { "kill", MORE, 2, kill_unit },
5827 { "is-active", MORE, 2, check_unit_active },
5828 { "check", MORE, 2, check_unit_active },
5829 { "is-failed", MORE, 2, check_unit_failed },
5830 { "show", MORE, 1, show },
5831 { "status", MORE, 1, show },
5832 { "help", MORE, 2, show },
5833 { "snapshot", LESS, 2, snapshot },
5834 { "delete", MORE, 2, delete_snapshot },
5835 { "daemon-reload", EQUAL, 1, daemon_reload },
5836 { "daemon-reexec", EQUAL, 1, daemon_reload },
5837 { "show-environment", EQUAL, 1, show_enviroment },
5838 { "set-environment", MORE, 2, set_environment },
5839 { "unset-environment", MORE, 2, set_environment },
5840 { "halt", EQUAL, 1, start_special },
5841 { "poweroff", EQUAL, 1, start_special },
5842 { "reboot", EQUAL, 1, start_special },
5843 { "kexec", EQUAL, 1, start_special },
5844 { "suspend", EQUAL, 1, start_special },
5845 { "hibernate", EQUAL, 1, start_special },
5846 { "hybrid-sleep", EQUAL, 1, start_special },
5847 { "default", EQUAL, 1, start_special },
5848 { "rescue", EQUAL, 1, start_special },
5849 { "emergency", EQUAL, 1, start_special },
5850 { "exit", EQUAL, 1, start_special },
5851 { "reset-failed", MORE, 1, reset_failed },
5852 { "enable", MORE, 2, enable_unit },
5853 { "disable", MORE, 2, enable_unit },
5854 { "is-enabled", MORE, 2, unit_is_enabled },
5855 { "reenable", MORE, 2, enable_unit },
5856 { "preset", MORE, 2, enable_unit },
5857 { "mask", MORE, 2, enable_unit },
5858 { "unmask", MORE, 2, enable_unit },
5859 { "link", MORE, 2, enable_unit },
5860 { "switch-root", MORE, 2, switch_root },
5861 { "list-dependencies", LESS, 2, list_dependencies },
5862 { "set-default", EQUAL, 2, enable_unit },
5863 { "get-default", LESS, 1, get_default },
5864 { "set-property", MORE, 3, set_property },
5874 left = argc - optind;
5877 /* Special rule: no arguments means "list-units" */
5880 if (streq(argv[optind], "help") && !argv[optind+1]) {
5881 log_error("This command expects one or more "
5882 "unit names. Did you mean --help?");
5886 for (i = 0; i < ELEMENTSOF(verbs); i++)
5887 if (streq(argv[optind], verbs[i].verb))
5890 if (i >= ELEMENTSOF(verbs)) {
5891 log_error("Unknown operation '%s'.", argv[optind]);
5896 switch (verbs[i].argc_cmp) {
5899 if (left != verbs[i].argc) {
5900 log_error("Invalid number of arguments.");
5907 if (left < verbs[i].argc) {
5908 log_error("Too few arguments.");
5915 if (left > verbs[i].argc) {
5916 log_error("Too many arguments.");
5923 assert_not_reached("Unknown comparison operator.");
5926 /* Require a bus connection for all operations but
5928 if (!streq(verbs[i].verb, "enable") &&
5929 !streq(verbs[i].verb, "disable") &&
5930 !streq(verbs[i].verb, "is-enabled") &&
5931 !streq(verbs[i].verb, "list-unit-files") &&
5932 !streq(verbs[i].verb, "reenable") &&
5933 !streq(verbs[i].verb, "preset") &&
5934 !streq(verbs[i].verb, "mask") &&
5935 !streq(verbs[i].verb, "unmask") &&
5936 !streq(verbs[i].verb, "link") &&
5937 !streq(verbs[i].verb, "set-default") &&
5938 !streq(verbs[i].verb, "get-default")) {
5940 if (running_in_chroot() > 0) {
5941 log_info("Running in chroot, ignoring request.");
5945 if (((!streq(verbs[i].verb, "reboot") &&
5946 !streq(verbs[i].verb, "halt") &&
5947 !streq(verbs[i].verb, "poweroff")) || arg_force <= 0) && !bus) {
5948 log_error("Failed to get D-Bus connection: %s",
5949 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5955 if (!bus && !avoid_bus()) {
5956 log_error("Failed to get D-Bus connection: %s",
5957 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5962 return verbs[i].dispatch(bus, argv + optind);
5965 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
5966 _cleanup_close_ int fd;
5967 struct sd_shutdown_command c = {
5973 union sockaddr_union sockaddr = {
5974 .un.sun_family = AF_UNIX,
5975 .un.sun_path = "/run/systemd/shutdownd",
5977 struct iovec iovec[2] = {
5978 {.iov_base = (char*) &c,
5979 .iov_len = offsetof(struct sd_shutdown_command, wall_message),
5982 struct msghdr msghdr = {
5983 .msg_name = &sockaddr,
5984 .msg_namelen = offsetof(struct sockaddr_un, sun_path)
5985 + sizeof("/run/systemd/shutdownd") - 1,
5990 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
5994 if (!isempty(message)) {
5995 iovec[1].iov_base = (char*) message;
5996 iovec[1].iov_len = strlen(message);
5997 msghdr.msg_iovlen++;
6000 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0)
6006 static int reload_with_fallback(DBusConnection *bus) {
6009 /* First, try systemd via D-Bus. */
6010 if (daemon_reload(bus, NULL) >= 0)
6014 /* Nothing else worked, so let's try signals */
6015 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
6017 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
6018 log_error("kill() failed: %m");
6025 static int start_with_fallback(DBusConnection *bus) {
6028 /* First, try systemd via D-Bus. */
6029 if (start_unit(bus, NULL) >= 0)
6033 /* Hmm, talking to systemd via D-Bus didn't work. Then
6034 * let's try to talk to Upstart via D-Bus. */
6035 if (talk_upstart() > 0)
6038 /* Nothing else worked, so let's try
6040 if (talk_initctl() > 0)
6043 log_error("Failed to talk to init daemon.");
6047 warn_wall(arg_action);
6051 static _noreturn_ void halt_now(enum action a) {
6053 /* Make sure C-A-D is handled by the kernel from this
6055 reboot(RB_ENABLE_CAD);
6060 log_info("Halting.");
6061 reboot(RB_HALT_SYSTEM);
6064 case ACTION_POWEROFF:
6065 log_info("Powering off.");
6066 reboot(RB_POWER_OFF);
6070 log_info("Rebooting.");
6071 reboot(RB_AUTOBOOT);
6075 assert_not_reached("Unknown halt action.");
6078 assert_not_reached("Uh? This shouldn't happen.");
6081 static int halt_main(DBusConnection *bus) {
6084 r = check_inhibitors(bus, arg_action);
6088 if (geteuid() != 0) {
6089 /* Try logind if we are a normal user and no special
6090 * mode applies. Maybe PolicyKit allows us to shutdown
6093 if (arg_when <= 0 &&
6096 (arg_action == ACTION_POWEROFF ||
6097 arg_action == ACTION_REBOOT)) {
6098 r = reboot_with_logind(bus, arg_action);
6103 log_error("Must be root.");
6108 _cleanup_free_ char *m;
6110 m = strv_join(arg_wall, " ");
6111 r = send_shutdownd(arg_when,
6112 arg_action == ACTION_HALT ? 'H' :
6113 arg_action == ACTION_POWEROFF ? 'P' :
6114 arg_action == ACTION_KEXEC ? 'K' :
6121 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
6123 char date[FORMAT_TIMESTAMP_MAX];
6125 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
6126 format_timestamp(date, sizeof(date), arg_when));
6131 if (!arg_dry && !arg_force)
6132 return start_with_fallback(bus);
6135 if (sd_booted() > 0)
6136 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
6138 r = utmp_put_shutdown();
6140 log_warning("Failed to write utmp record: %s", strerror(-r));
6147 halt_now(arg_action);
6148 /* We should never reach this. */
6152 static int runlevel_main(void) {
6153 int r, runlevel, previous;
6155 r = utmp_get_runlevel(&runlevel, &previous);
6162 previous <= 0 ? 'N' : previous,
6163 runlevel <= 0 ? 'N' : runlevel);
6168 int main(int argc, char*argv[]) {
6169 int r, retval = EXIT_FAILURE;
6170 DBusConnection *bus = NULL;
6171 _cleanup_dbus_error_free_ DBusError error;
6173 dbus_error_init(&error);
6175 setlocale(LC_ALL, "");
6176 log_parse_environment();
6179 r = parse_argv(argc, argv);
6183 retval = EXIT_SUCCESS;
6187 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
6188 * let's shortcut this */
6189 if (arg_action == ACTION_RUNLEVEL) {
6190 r = runlevel_main();
6191 retval = r < 0 ? EXIT_FAILURE : r;
6195 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
6196 log_info("Running in chroot, ignoring request.");
6202 if (arg_transport == TRANSPORT_NORMAL)
6203 bus_connect(arg_scope == UNIT_FILE_SYSTEM ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &bus, &private_bus, &error);
6204 else if (arg_transport == TRANSPORT_POLKIT) {
6205 bus_connect_system_polkit(&bus, &error);
6206 private_bus = false;
6207 } else if (arg_transport == TRANSPORT_SSH) {
6208 bus_connect_system_ssh(arg_user, arg_host, &bus, &error);
6209 private_bus = false;
6211 assert_not_reached("Uh, invalid transport...");
6214 switch (arg_action) {
6216 case ACTION_SYSTEMCTL:
6217 r = systemctl_main(bus, argc, argv, &error);
6221 case ACTION_POWEROFF:
6227 case ACTION_RUNLEVEL2:
6228 case ACTION_RUNLEVEL3:
6229 case ACTION_RUNLEVEL4:
6230 case ACTION_RUNLEVEL5:
6232 case ACTION_EMERGENCY:
6233 case ACTION_DEFAULT:
6234 r = start_with_fallback(bus);
6239 r = reload_with_fallback(bus);
6242 case ACTION_CANCEL_SHUTDOWN: {
6246 m = strv_join(arg_wall, " ");
6248 retval = EXIT_FAILURE;
6252 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
6254 log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r));
6259 case ACTION_INVALID:
6260 case ACTION_RUNLEVEL:
6262 assert_not_reached("Unknown action");
6265 retval = r < 0 ? EXIT_FAILURE : r;
6269 dbus_connection_flush(bus);
6270 dbus_connection_close(bus);
6271 dbus_connection_unref(bus);
6276 strv_free(arg_types);
6277 strv_free(arg_states);
6278 strv_free(arg_properties);
6281 ask_password_agent_close();
6282 polkit_agent_close();