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>
23 #include <linux/reboot.h>
24 #include <sys/syscall.h>
31 #include <sys/ioctl.h>
35 #include <sys/socket.h>
38 #include <sys/prctl.h>
39 #include <dbus/dbus.h>
41 #include <systemd/sd-daemon.h>
42 #include <systemd/sd-shutdown.h>
43 #include <systemd/sd-login.h>
49 #include "utmp-wtmp.h"
52 #include "path-util.h"
54 #include "dbus-common.h"
55 #include "cgroup-show.h"
56 #include "cgroup-util.h"
58 #include "path-lookup.h"
59 #include "conf-parser.h"
60 #include "exit-status.h"
61 #include "bus-errors.h"
63 #include "unit-name.h"
65 #include "spawn-ask-password-agent.h"
66 #include "spawn-polkit-agent.h"
68 #include "logs-show.h"
69 #include "path-util.h"
70 #include "socket-util.h"
73 static char **arg_types = NULL;
74 static char **arg_states = NULL;
75 static char **arg_properties = NULL;
76 static bool arg_all = false;
77 static bool original_stdout_is_tty;
78 static enum dependency {
83 } arg_dependency = DEPENDENCY_FORWARD;
84 static const char *arg_job_mode = "replace";
85 static UnitFileScope arg_scope = UNIT_FILE_SYSTEM;
86 static bool arg_no_block = false;
87 static bool arg_no_legend = false;
88 static bool arg_no_pager = false;
89 static bool arg_no_wtmp = false;
90 static bool arg_no_wall = false;
91 static bool arg_no_reload = false;
92 static bool arg_show_types = false;
93 static bool arg_ignore_inhibitors = false;
94 static bool arg_dry = false;
95 static bool arg_quiet = false;
96 static bool arg_full = false;
97 static int arg_force = 0;
98 static bool arg_ask_password = true;
99 static bool arg_runtime = false;
100 static char **arg_wall = NULL;
101 static const char *arg_kill_who = NULL;
102 static int arg_signal = SIGTERM;
103 static const char *arg_root = NULL;
104 static usec_t arg_when = 0;
126 ACTION_CANCEL_SHUTDOWN,
128 } arg_action = ACTION_SYSTEMCTL;
129 static enum transport {
133 } arg_transport = TRANSPORT_NORMAL;
134 static char *arg_host = NULL;
135 static char *arg_user = NULL;
136 static unsigned arg_lines = 10;
137 static OutputMode arg_output = OUTPUT_SHORT;
138 static bool arg_plain = false;
140 static bool private_bus = false;
142 static int daemon_reload(DBusConnection *bus, char **args);
143 static void halt_now(enum action a);
145 static void pager_open_if_enabled(void) {
153 static void ask_password_agent_open_if_enabled(void) {
155 /* Open the password agent as a child process if necessary */
157 if (!arg_ask_password)
160 if (arg_scope != UNIT_FILE_SYSTEM)
163 ask_password_agent_open();
167 static void polkit_agent_open_if_enabled(void) {
169 /* Open the polkit agent as a child process if necessary */
171 if (!arg_ask_password)
174 if (arg_scope != UNIT_FILE_SYSTEM)
181 static int translate_bus_error_to_exit_status(int r, const DBusError *error) {
184 if (!dbus_error_is_set(error))
187 if (dbus_error_has_name(error, DBUS_ERROR_ACCESS_DENIED) ||
188 dbus_error_has_name(error, BUS_ERROR_ONLY_BY_DEPENDENCY) ||
189 dbus_error_has_name(error, BUS_ERROR_NO_ISOLATION) ||
190 dbus_error_has_name(error, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE))
191 return EXIT_NOPERMISSION;
193 if (dbus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT))
194 return EXIT_NOTINSTALLED;
196 if (dbus_error_has_name(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE) ||
197 dbus_error_has_name(error, BUS_ERROR_NOT_SUPPORTED))
198 return EXIT_NOTIMPLEMENTED;
200 if (dbus_error_has_name(error, BUS_ERROR_LOAD_FAILED))
201 return EXIT_NOTCONFIGURED;
209 static void warn_wall(enum action a) {
210 static const char *table[_ACTION_MAX] = {
211 [ACTION_HALT] = "The system is going down for system halt NOW!",
212 [ACTION_REBOOT] = "The system is going down for reboot NOW!",
213 [ACTION_POWEROFF] = "The system is going down for power-off NOW!",
214 [ACTION_KEXEC] = "The system is going down for kexec reboot NOW!",
215 [ACTION_RESCUE] = "The system is going down to rescue mode NOW!",
216 [ACTION_EMERGENCY] = "The system is going down to emergency mode NOW!",
217 [ACTION_CANCEL_SHUTDOWN] = "The system shutdown has been cancelled NOW!"
224 _cleanup_free_ char *p;
226 p = strv_join(arg_wall, " ");
241 utmp_wall(table[a], NULL);
244 static bool avoid_bus(void) {
246 if (running_in_chroot() > 0)
249 if (sd_booted() <= 0)
252 if (!isempty(arg_root))
255 if (arg_scope == UNIT_FILE_GLOBAL)
261 static int compare_unit_info(const void *a, const void *b) {
263 const struct unit_info *u = a, *v = b;
265 d1 = strrchr(u->id, '.');
266 d2 = strrchr(v->id, '.');
271 r = strcasecmp(d1, d2);
276 return strcasecmp(u->id, v->id);
279 static bool output_show_unit(const struct unit_info *u) {
282 if (!strv_isempty(arg_states))
283 return strv_contains(arg_states, u->load_state) || strv_contains(arg_states, u->sub_state) || strv_contains(arg_states, u->active_state);
285 return (!arg_types || ((dot = strrchr(u->id, '.')) &&
286 strv_find(arg_types, dot+1))) &&
287 (arg_all || !(streq(u->active_state, "inactive")
288 || u->following[0]) || u->job_id > 0);
291 static void output_units_list(const struct unit_info *unit_infos, unsigned c) {
292 unsigned id_len, max_id_len, load_len, active_len, sub_len, job_len, desc_len;
293 unsigned n_shown = 0;
294 const struct unit_info *u;
297 max_id_len = strlen("UNIT");
298 load_len = strlen("LOAD");
299 active_len = strlen("ACTIVE");
300 sub_len = strlen("SUB");
301 job_len = strlen("JOB");
304 for (u = unit_infos; u < unit_infos + c; u++) {
305 if (!output_show_unit(u))
308 max_id_len = MAX(max_id_len, strlen(u->id));
309 load_len = MAX(load_len, strlen(u->load_state));
310 active_len = MAX(active_len, strlen(u->active_state));
311 sub_len = MAX(sub_len, strlen(u->sub_state));
312 if (u->job_id != 0) {
313 job_len = MAX(job_len, strlen(u->job_type));
318 if (!arg_full && original_stdout_is_tty) {
320 id_len = MIN(max_id_len, 25u);
321 basic_len = 5 + id_len + 5 + active_len + sub_len;
323 basic_len += job_len + 1;
324 if (basic_len < (unsigned) columns()) {
325 unsigned extra_len, incr;
326 extra_len = columns() - basic_len;
327 /* Either UNIT already got 25, or is fully satisfied.
328 * Grant up to 25 to DESC now. */
329 incr = MIN(extra_len, 25u);
332 /* split the remaining space between UNIT and DESC,
333 * but do not give UNIT more than it needs. */
335 incr = MIN(extra_len / 2, max_id_len - id_len);
337 desc_len += extra_len - incr;
343 for (u = unit_infos; u < unit_infos + c; u++) {
344 _cleanup_free_ char *e = NULL;
345 const char *on_loaded, *off_loaded, *on = "";
346 const char *on_active, *off_active, *off = "";
348 if (!output_show_unit(u))
351 if (!n_shown && !arg_no_legend) {
352 printf("%-*s %-*s %-*s %-*s ", id_len, "UNIT", load_len, "LOAD",
353 active_len, "ACTIVE", sub_len, "SUB");
355 printf("%-*s ", job_len, "JOB");
356 if (!arg_full && arg_no_pager)
357 printf("%.*s\n", desc_len, "DESCRIPTION");
359 printf("%s\n", "DESCRIPTION");
364 if (streq(u->load_state, "error") ||
365 streq(u->load_state, "not-found")) {
366 on_loaded = on = ansi_highlight_red();
367 off_loaded = off = ansi_highlight_off();
369 on_loaded = off_loaded = "";
371 if (streq(u->active_state, "failed")) {
372 on_active = on = ansi_highlight_red();
373 off_active = off = ansi_highlight_off();
375 on_active = off_active = "";
377 e = arg_full ? NULL : ellipsize(u->id, id_len, 33);
379 printf("%s%-*s%s %s%-*s%s %s%-*s %-*s%s %-*s",
380 on, id_len, e ? e : u->id, off,
381 on_loaded, load_len, u->load_state, off_loaded,
382 on_active, active_len, u->active_state,
383 sub_len, u->sub_state, off_active,
384 job_count ? job_len + 1 : 0, u->job_id ? u->job_type : "");
386 printf("%.*s\n", desc_len, u->description);
388 printf("%s\n", u->description);
391 if (!arg_no_legend) {
392 const char *on, *off;
395 printf("\nLOAD = Reflects whether the unit definition was properly loaded.\n"
396 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
397 "SUB = The low-level unit activation state, values depend on unit type.\n");
399 printf("JOB = Pending job for the unit.\n");
401 on = ansi_highlight();
402 off = ansi_highlight_off();
404 on = ansi_highlight_red();
405 off = ansi_highlight_off();
409 printf("%s%u loaded units listed.%s\n"
410 "To show all installed unit files use 'systemctl list-unit-files'.\n",
413 printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
414 "To show all installed unit files use 'systemctl list-unit-files'.\n",
419 static int get_unit_list(
422 struct unit_info **unit_infos,
425 DBusMessageIter iter, sub;
433 r = bus_method_call_with_reply(
435 "org.freedesktop.systemd1",
436 "/org/freedesktop/systemd1",
437 "org.freedesktop.systemd1.Manager",
445 if (!dbus_message_iter_init(*reply, &iter) ||
446 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
447 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
448 log_error("Failed to parse reply.");
452 dbus_message_iter_recurse(&iter, &sub);
454 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
455 if (!GREEDY_REALLOC(*unit_infos, size, *c + 1))
458 bus_parse_unit_info(&sub, *unit_infos + *c);
461 dbus_message_iter_next(&sub);
467 static int list_units(DBusConnection *bus, char **args) {
468 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
469 _cleanup_free_ struct unit_info *unit_infos = NULL;
473 pager_open_if_enabled();
475 r = get_unit_list(bus, &reply, &unit_infos, &c);
479 qsort_safe(unit_infos, c, sizeof(struct unit_info), compare_unit_info);
481 output_units_list(unit_infos, c);
486 static int get_triggered_units(
488 const char* unit_path,
491 const char *interface = "org.freedesktop.systemd1.Unit",
492 *triggers_property = "Triggers";
493 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
494 DBusMessageIter iter, sub;
497 r = bus_method_call_with_reply(bus,
498 "org.freedesktop.systemd1",
500 "org.freedesktop.DBus.Properties",
504 DBUS_TYPE_STRING, &interface,
505 DBUS_TYPE_STRING, &triggers_property,
510 if (!dbus_message_iter_init(reply, &iter) ||
511 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
512 log_error("Failed to parse reply.");
516 dbus_message_iter_recurse(&iter, &sub);
517 dbus_message_iter_recurse(&sub, &iter);
520 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
523 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
524 log_error("Failed to parse reply.");
528 dbus_message_iter_get_basic(&sub, &unit);
529 r = strv_extend(triggered, unit);
533 dbus_message_iter_next(&sub);
539 static int get_listening(DBusConnection *bus, const char* unit_path,
540 char*** listen, unsigned *c)
542 const char *interface = "org.freedesktop.systemd1.Socket",
543 *listen_property = "Listen";
544 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
545 DBusMessageIter iter, sub;
548 r = bus_method_call_with_reply(bus,
549 "org.freedesktop.systemd1",
551 "org.freedesktop.DBus.Properties",
555 DBUS_TYPE_STRING, &interface,
556 DBUS_TYPE_STRING, &listen_property,
561 if (!dbus_message_iter_init(reply, &iter) ||
562 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
563 log_error("Failed to parse reply.");
567 dbus_message_iter_recurse(&iter, &sub);
568 dbus_message_iter_recurse(&sub, &iter);
571 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
572 DBusMessageIter sub2;
573 const char *type, *path;
575 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
576 log_error("Failed to parse reply.");
580 dbus_message_iter_recurse(&sub, &sub2);
582 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
583 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0) {
584 r = strv_extend(listen, type);
588 r = strv_extend(listen, path);
595 dbus_message_iter_next(&sub);
607 /* Note: triggered is a list here, although it almost certainly
608 * will always be one unit. Nevertheless, dbus API allows for multiple
609 * values, so let's follow that.*/
612 /* The strv above is shared. free is set only in the first one. */
616 static int socket_info_compare(struct socket_info *a, struct socket_info *b) {
617 int o = strcmp(a->path, b->path);
619 o = strcmp(a->type, b->type);
623 static int output_sockets_list(struct socket_info *socket_infos, unsigned cs) {
624 struct socket_info *s;
625 unsigned pathlen = sizeof("LISTEN") - 1,
626 typelen = (sizeof("TYPE") - 1) * arg_show_types,
627 socklen = sizeof("UNIT") - 1,
628 servlen = sizeof("ACTIVATES") - 1;
629 const char *on, *off;
631 for (s = socket_infos; s < socket_infos + cs; s++) {
635 socklen = MAX(socklen, strlen(s->id));
637 typelen = MAX(typelen, strlen(s->type));
638 pathlen = MAX(pathlen, strlen(s->path));
640 STRV_FOREACH(a, s->triggered)
641 tmp += strlen(*a) + 2*(a != s->triggered);
642 servlen = MAX(servlen, tmp);
647 printf("%-*s %-*.*s%-*s %s\n",
649 typelen + arg_show_types, typelen + arg_show_types, "TYPE ",
653 for (s = socket_infos; s < socket_infos + cs; s++) {
657 printf("%-*s %-*s %-*s",
658 pathlen, s->path, typelen, s->type, socklen, s->id);
661 pathlen, s->path, socklen, s->id);
662 STRV_FOREACH(a, s->triggered)
664 a == s->triggered ? "" : ",", *a);
668 on = ansi_highlight();
669 off = ansi_highlight_off();
673 on = ansi_highlight_red();
674 off = ansi_highlight_off();
677 if (!arg_no_legend) {
678 printf("%s%u sockets listed.%s\n", on, cs, off);
680 printf("Pass --all to see loaded but inactive sockets, too.\n");
686 static int list_sockets(DBusConnection *bus, char **args) {
687 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
688 _cleanup_free_ struct unit_info *unit_infos = NULL;
689 struct socket_info *socket_infos = NULL;
690 const struct unit_info *u;
691 struct socket_info *s;
692 unsigned cu = 0, cs = 0;
696 pager_open_if_enabled();
698 r = get_unit_list(bus, &reply, &unit_infos, &cu);
702 for (u = unit_infos; u < unit_infos + cu; u++) {
704 _cleanup_strv_free_ char **listen = NULL, **triggered = NULL;
707 if (!output_show_unit(u))
710 if ((dot = strrchr(u->id, '.')) && !streq(dot+1, "socket"))
713 r = get_triggered_units(bus, u->unit_path, &triggered);
717 r = get_listening(bus, u->unit_path, &listen, &c);
721 if (!GREEDY_REALLOC(socket_infos, size, cs + c)) {
726 for (i = 0; i < c; i++)
727 socket_infos[cs + i] = (struct socket_info) {
730 .path = listen[i*2 + 1],
731 .triggered = triggered,
732 .own_triggered = i==0,
735 /* from this point on we will cleanup those socket_infos */
738 listen = triggered = NULL; /* avoid cleanup */
741 qsort_safe(socket_infos, cs, sizeof(struct socket_info),
742 (__compar_fn_t) socket_info_compare);
744 output_sockets_list(socket_infos, cs);
747 assert(cs == 0 || socket_infos);
748 for (s = socket_infos; s < socket_infos + cs; s++) {
751 if (s->own_triggered)
752 strv_free(s->triggered);
759 static int compare_unit_file_list(const void *a, const void *b) {
761 const UnitFileList *u = a, *v = b;
763 d1 = strrchr(u->path, '.');
764 d2 = strrchr(v->path, '.');
769 r = strcasecmp(d1, d2);
774 return strcasecmp(path_get_file_name(u->path), path_get_file_name(v->path));
777 static bool output_show_unit_file(const UnitFileList *u) {
780 return !arg_types || ((dot = strrchr(u->path, '.')) && strv_find(arg_types, dot+1));
783 static void output_unit_file_list(const UnitFileList *units, unsigned c) {
784 unsigned max_id_len, id_cols, state_cols, n_shown = 0;
785 const UnitFileList *u;
787 max_id_len = sizeof("UNIT FILE")-1;
788 state_cols = sizeof("STATE")-1;
789 for (u = units; u < units + c; u++) {
790 if (!output_show_unit_file(u))
793 max_id_len = MAX(max_id_len, strlen(path_get_file_name(u->path)));
794 state_cols = MAX(state_cols, strlen(unit_file_state_to_string(u->state)));
799 id_cols = MIN(max_id_len, 25u);
800 basic_cols = 1 + id_cols + state_cols;
801 if (basic_cols < (unsigned) columns())
802 id_cols += MIN(columns() - basic_cols, max_id_len - id_cols);
804 id_cols = max_id_len;
807 printf("%-*s %-*s\n", id_cols, "UNIT FILE", state_cols, "STATE");
809 for (u = units; u < units + c; u++) {
810 _cleanup_free_ char *e = NULL;
811 const char *on, *off;
814 if (!output_show_unit_file(u))
819 if (u->state == UNIT_FILE_MASKED ||
820 u->state == UNIT_FILE_MASKED_RUNTIME ||
821 u->state == UNIT_FILE_DISABLED ||
822 u->state == UNIT_FILE_INVALID) {
823 on = ansi_highlight_red();
824 off = ansi_highlight_off();
825 } else if (u->state == UNIT_FILE_ENABLED) {
826 on = ansi_highlight_green();
827 off = ansi_highlight_off();
831 id = path_get_file_name(u->path);
833 e = arg_full ? NULL : ellipsize(id, id_cols, 33);
835 printf("%-*s %s%-*s%s\n",
837 on, state_cols, unit_file_state_to_string(u->state), off);
841 printf("\n%u unit files listed.\n", n_shown);
844 static int list_unit_files(DBusConnection *bus, char **args) {
845 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
846 _cleanup_free_ UnitFileList *units = NULL;
847 DBusMessageIter iter, sub, sub2;
848 unsigned c = 0, n_units = 0;
851 pager_open_if_enabled();
858 h = hashmap_new(string_hash_func, string_compare_func);
862 r = unit_file_get_list(arg_scope, arg_root, h);
864 unit_file_list_free(h);
865 log_error("Failed to get unit file list: %s", strerror(-r));
869 n_units = hashmap_size(h);
870 units = new(UnitFileList, n_units);
872 unit_file_list_free(h);
876 HASHMAP_FOREACH(u, h, i) {
877 memcpy(units + c++, u, sizeof(UnitFileList));
883 r = bus_method_call_with_reply(
885 "org.freedesktop.systemd1",
886 "/org/freedesktop/systemd1",
887 "org.freedesktop.systemd1.Manager",
895 if (!dbus_message_iter_init(reply, &iter) ||
896 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
897 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
898 log_error("Failed to parse reply.");
902 dbus_message_iter_recurse(&iter, &sub);
904 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
908 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT);
913 n_units = MAX(2*c, 16u);
914 w = realloc(units, sizeof(struct UnitFileList) * n_units);
923 dbus_message_iter_recurse(&sub, &sub2);
925 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->path, true) < 0 ||
926 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, false) < 0) {
927 log_error("Failed to parse reply.");
931 u->state = unit_file_state_from_string(state);
933 dbus_message_iter_next(&sub);
939 qsort(units, c, sizeof(UnitFileList), compare_unit_file_list);
940 output_unit_file_list(units, c);
946 static int list_dependencies_print(const char *name, int level, unsigned int branches, bool last) {
948 _cleanup_free_ char *n = NULL;
950 size_t max_len = MAX(columns(),20u);
953 for (i = level - 1; i >= 0; i--) {
955 if(len > max_len - 3 && !arg_full) {
956 printf("%s...\n",max_len % 2 ? "" : " ");
959 printf("%s", draw_special_char(branches & (1 << i) ? DRAW_TREE_VERT : DRAW_TREE_SPACE));
962 if(len > max_len - 3 && !arg_full) {
963 printf("%s...\n",max_len % 2 ? "" : " ");
966 printf("%s", draw_special_char(last ? DRAW_TREE_RIGHT : DRAW_TREE_BRANCH));
970 printf("%s\n", name);
974 n = ellipsize(name, max_len-len, 100);
982 static int list_dependencies_get_dependencies(DBusConnection *bus, const char *name, char ***deps) {
983 static const char *dependencies[] = {
984 [DEPENDENCY_FORWARD] = "Requires\0"
985 "RequiresOverridable\0"
987 "RequisiteOverridable\0"
989 [DEPENDENCY_REVERSE] = "RequiredBy\0"
990 "RequiredByOverridable\0"
993 [DEPENDENCY_AFTER] = "After\0",
994 [DEPENDENCY_BEFORE] = "Before\0",
997 _cleanup_free_ char *path;
998 const char *interface = "org.freedesktop.systemd1.Unit";
1000 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1001 DBusMessageIter iter, sub, sub2, sub3;
1010 path = unit_dbus_path_from_name(name);
1016 r = bus_method_call_with_reply(
1018 "org.freedesktop.systemd1",
1020 "org.freedesktop.DBus.Properties",
1024 DBUS_TYPE_STRING, &interface,
1029 if (!dbus_message_iter_init(reply, &iter) ||
1030 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
1031 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
1032 log_error("Failed to parse reply.");
1037 dbus_message_iter_recurse(&iter, &sub);
1039 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1042 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_DICT_ENTRY);
1043 dbus_message_iter_recurse(&sub, &sub2);
1045 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &prop, true) < 0) {
1046 log_error("Failed to parse reply.");
1051 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
1052 log_error("Failed to parse reply.");
1057 dbus_message_iter_recurse(&sub2, &sub3);
1058 dbus_message_iter_next(&sub);
1060 assert(arg_dependency < ELEMENTSOF(dependencies));
1061 if (!nulstr_contains(dependencies[arg_dependency], prop))
1064 if (dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_ARRAY) {
1065 if (dbus_message_iter_get_element_type(&sub3) == DBUS_TYPE_STRING) {
1066 DBusMessageIter sub4;
1067 dbus_message_iter_recurse(&sub3, &sub4);
1069 while (dbus_message_iter_get_arg_type(&sub4) != DBUS_TYPE_INVALID) {
1072 assert(dbus_message_iter_get_arg_type(&sub4) == DBUS_TYPE_STRING);
1073 dbus_message_iter_get_basic(&sub4, &s);
1075 r = strv_extend(&ret, s);
1081 dbus_message_iter_next(&sub4);
1094 static int list_dependencies_compare(const void *_a, const void *_b) {
1095 const char **a = (const char**) _a, **b = (const char**) _b;
1096 if (unit_name_to_type(*a) == UNIT_TARGET && unit_name_to_type(*b) != UNIT_TARGET)
1098 if (unit_name_to_type(*a) != UNIT_TARGET && unit_name_to_type(*b) == UNIT_TARGET)
1100 return strcasecmp(*a, *b);
1103 static int list_dependencies_one(DBusConnection *bus, const char *name, int level, char ***units, unsigned int branches) {
1104 _cleanup_strv_free_ char **deps = NULL, **u;
1108 u = strv_append(*units, name);
1112 r = list_dependencies_get_dependencies(bus, name, &deps);
1116 qsort_safe(deps, strv_length(deps), sizeof (char*), list_dependencies_compare);
1118 STRV_FOREACH(c, deps) {
1119 if (strv_contains(u, *c)) {
1121 r = list_dependencies_print("...", level + 1, (branches << 1) | (c[1] == NULL ? 0 : 1), 1);
1128 r = list_dependencies_print(*c, level, branches, c[1] == NULL);
1132 if (arg_all || unit_name_to_type(*c) == UNIT_TARGET) {
1133 r = list_dependencies_one(bus, *c, level + 1, &u, (branches << 1) | (c[1] == NULL ? 0 : 1));
1146 static int list_dependencies(DBusConnection *bus, char **args) {
1147 _cleanup_free_ char *unit = NULL;
1148 _cleanup_strv_free_ char **units = NULL;
1154 unit = unit_name_mangle(args[1]);
1159 u = SPECIAL_DEFAULT_TARGET;
1161 pager_open_if_enabled();
1165 return list_dependencies_one(bus, u, 0, &units, 0);
1168 static int get_default(DBusConnection *bus, char **args) {
1170 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1172 _cleanup_dbus_error_free_ DBusError error;
1174 dbus_error_init(&error);
1176 if (!bus || avoid_bus()) {
1177 r = unit_file_get_default(arg_scope, arg_root, &path);
1180 log_error("Operation failed: %s", strerror(-r));
1186 r = bus_method_call_with_reply(
1188 "org.freedesktop.systemd1",
1189 "/org/freedesktop/systemd1",
1190 "org.freedesktop.systemd1.Manager",
1197 log_error("Operation failed: %s", strerror(-r));
1201 if (!dbus_message_get_args(reply, &error,
1202 DBUS_TYPE_STRING, &path,
1203 DBUS_TYPE_INVALID)) {
1204 log_error("Failed to parse reply: %s", bus_error_message(&error));
1205 dbus_error_free(&error);
1211 printf("%s\n", path);
1214 if ((!bus || avoid_bus()) && path)
1223 char *name, *type, *state;
1226 static void list_jobs_print(struct job_info* jobs, size_t n) {
1229 const char *on, *off;
1230 bool shorten = false;
1232 assert(n == 0 || jobs);
1235 on = ansi_highlight_green();
1236 off = ansi_highlight_off();
1238 printf("%sNo jobs running.%s\n", on, off);
1242 pager_open_if_enabled();
1245 /* JOB UNIT TYPE STATE */
1246 unsigned l0 = 3, l1 = 4, l2 = 4, l3 = 5;
1248 for (i = 0, j = jobs; i < n; i++, j++) {
1249 assert(j->name && j->type && j->state);
1250 l0 = MAX(l0, DECIMAL_STR_WIDTH(j->id));
1251 l1 = MAX(l1, strlen(j->name));
1252 l2 = MAX(l2, strlen(j->type));
1253 l3 = MAX(l3, strlen(j->state));
1256 if (!arg_full && l0 + 1 + l1 + l2 + 1 + l3 > columns()) {
1257 l1 = MAX(33u, columns() - l0 - l2 - l3 - 3);
1261 printf("%*s %-*s %-*s %-*s\n",
1267 for (i = 0, j = jobs; i < n; i++, j++) {
1268 _cleanup_free_ char *e = NULL;
1270 if (streq(j->state, "running")) {
1271 on = ansi_highlight();
1272 off = ansi_highlight_off();
1276 e = shorten ? ellipsize(j->name, l1, 33) : NULL;
1277 printf("%*u %s%-*s%s %-*s %s%-*s%s\n",
1279 on, l1, e ? e : j->name, off,
1281 on, l3, j->state, off);
1285 on = ansi_highlight();
1286 off = ansi_highlight_off();
1288 printf("\n%s%zu jobs listed%s.\n", on, n, off);
1291 static int list_jobs(DBusConnection *bus, char **args) {
1292 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1293 DBusMessageIter iter, sub, sub2;
1295 struct job_info *jobs = NULL;
1296 size_t size = 0, used = 0;
1298 r = bus_method_call_with_reply(
1300 "org.freedesktop.systemd1",
1301 "/org/freedesktop/systemd1",
1302 "org.freedesktop.systemd1.Manager",
1310 if (!dbus_message_iter_init(reply, &iter) ||
1311 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
1312 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
1313 log_error("Failed to parse reply.");
1317 dbus_message_iter_recurse(&iter, &sub);
1319 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1320 const char *name, *type, *state, *job_path, *unit_path;
1323 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
1324 log_error("Failed to parse reply.");
1328 dbus_message_iter_recurse(&sub, &sub2);
1330 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &id, true) < 0 ||
1331 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
1332 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
1333 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, true) < 0 ||
1334 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &job_path, true) < 0 ||
1335 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, false) < 0) {
1336 log_error("Failed to parse reply.");
1341 if (!GREEDY_REALLOC(jobs, size, used + 1)) {
1346 jobs[used++] = (struct job_info) { id,
1350 if (!jobs[used-1].name || !jobs[used-1].type || !jobs[used-1].state) {
1355 dbus_message_iter_next(&sub);
1358 list_jobs_print(jobs, used);
1362 free(jobs[used].name);
1363 free(jobs[used].type);
1364 free(jobs[used].state);
1371 static int cancel_job(DBusConnection *bus, char **args) {
1376 if (strv_length(args) <= 1)
1377 return daemon_reload(bus, args);
1379 STRV_FOREACH(name, args+1) {
1383 r = safe_atou32(*name, &id);
1385 log_error("Failed to parse job id: %s", strerror(-r));
1389 r = bus_method_call_with_reply(
1391 "org.freedesktop.systemd1",
1392 "/org/freedesktop/systemd1",
1393 "org.freedesktop.systemd1.Manager",
1397 DBUS_TYPE_UINT32, &id,
1406 static int need_daemon_reload(DBusConnection *bus, const char *unit) {
1407 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1408 _cleanup_dbus_error_free_ DBusError error;
1409 dbus_bool_t b = FALSE;
1410 DBusMessageIter iter, sub;
1412 *interface = "org.freedesktop.systemd1.Unit",
1413 *property = "NeedDaemonReload",
1415 _cleanup_free_ char *n = NULL;
1418 dbus_error_init(&error);
1420 /* We ignore all errors here, since this is used to show a warning only */
1422 n = unit_name_mangle(unit);
1426 r = bus_method_call_with_reply(
1428 "org.freedesktop.systemd1",
1429 "/org/freedesktop/systemd1",
1430 "org.freedesktop.systemd1.Manager",
1434 DBUS_TYPE_STRING, &n,
1439 if (!dbus_message_get_args(reply, NULL,
1440 DBUS_TYPE_OBJECT_PATH, &path,
1444 dbus_message_unref(reply);
1447 r = bus_method_call_with_reply(
1449 "org.freedesktop.systemd1",
1451 "org.freedesktop.DBus.Properties",
1455 DBUS_TYPE_STRING, &interface,
1456 DBUS_TYPE_STRING, &property,
1461 if (!dbus_message_iter_init(reply, &iter) ||
1462 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
1465 dbus_message_iter_recurse(&iter, &sub);
1466 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_BOOLEAN)
1469 dbus_message_iter_get_basic(&sub, &b);
1473 typedef struct WaitData {
1480 static DBusHandlerResult wait_filter(DBusConnection *connection, DBusMessage *message, void *data) {
1481 _cleanup_dbus_error_free_ DBusError error;
1484 dbus_error_init(&error);
1490 log_debug("Got D-Bus request: %s.%s() on %s",
1491 dbus_message_get_interface(message),
1492 dbus_message_get_member(message),
1493 dbus_message_get_path(message));
1495 if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
1496 log_error("Warning! D-Bus connection terminated.");
1497 dbus_connection_close(connection);
1499 } else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
1501 const char *path, *result, *unit;
1504 if (dbus_message_get_args(message, &error,
1505 DBUS_TYPE_UINT32, &id,
1506 DBUS_TYPE_OBJECT_PATH, &path,
1507 DBUS_TYPE_STRING, &unit,
1508 DBUS_TYPE_STRING, &result,
1509 DBUS_TYPE_INVALID)) {
1511 r = set_remove(d->set, (char*) path);
1513 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1517 if (!isempty(result))
1518 d->result = strdup(result);
1521 d->name = strdup(unit);
1523 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1526 dbus_error_free(&error);
1527 if (dbus_message_get_args(message, &error,
1528 DBUS_TYPE_UINT32, &id,
1529 DBUS_TYPE_OBJECT_PATH, &path,
1530 DBUS_TYPE_STRING, &result,
1531 DBUS_TYPE_INVALID)) {
1532 /* Compatibility with older systemd versions <
1533 * 183 during upgrades. This should be dropped
1535 r = set_remove(d->set, (char*) path);
1537 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1542 d->result = strdup(result);
1544 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1548 log_error("Failed to parse message: %s", bus_error_message(&error));
1551 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1554 static int enable_wait_for_jobs(DBusConnection *bus) {
1562 dbus_error_init(&error);
1563 dbus_bus_add_match(bus,
1565 "sender='org.freedesktop.systemd1',"
1566 "interface='org.freedesktop.systemd1.Manager',"
1567 "member='JobRemoved',"
1568 "path='/org/freedesktop/systemd1'",
1571 if (dbus_error_is_set(&error)) {
1572 log_error("Failed to add match: %s", bus_error_message(&error));
1573 dbus_error_free(&error);
1577 /* This is slightly dirty, since we don't undo the match registrations. */
1581 static int wait_for_jobs(DBusConnection *bus, Set *s) {
1583 WaitData d = { .set = s };
1588 if (!dbus_connection_add_filter(bus, wait_filter, &d, NULL))
1591 while (!set_isempty(s)) {
1593 if (!dbus_connection_read_write_dispatch(bus, -1)) {
1594 log_error("Disconnected from bus.");
1595 return -ECONNREFUSED;
1602 if (streq(d.result, "timeout"))
1603 log_error("Job for %s timed out.", strna(d.name));
1604 else if (streq(d.result, "canceled"))
1605 log_error("Job for %s canceled.", strna(d.name));
1606 else if (streq(d.result, "dependency"))
1607 log_error("A dependency job for %s failed. See 'journalctl -xn' for details.", strna(d.name));
1608 else if (!streq(d.result, "done") && !streq(d.result, "skipped"))
1609 log_error("Job for %s failed. See 'systemctl status %s' and 'journalctl -xn' for details.", strna(d.name), strna(d.name));
1612 if (streq_ptr(d.result, "timeout"))
1614 else if (streq_ptr(d.result, "canceled"))
1616 else if (!streq_ptr(d.result, "done") && !streq_ptr(d.result, "skipped"))
1627 dbus_connection_remove_filter(bus, wait_filter, &d);
1631 static int check_one_unit(DBusConnection *bus, const char *name, char **check_states, bool quiet) {
1632 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1633 _cleanup_free_ char *n = NULL;
1634 DBusMessageIter iter, sub;
1636 *interface = "org.freedesktop.systemd1.Unit",
1637 *property = "ActiveState";
1638 const char *state, *path;
1644 dbus_error_init(&error);
1646 n = unit_name_mangle(name);
1650 r = bus_method_call_with_reply (
1652 "org.freedesktop.systemd1",
1653 "/org/freedesktop/systemd1",
1654 "org.freedesktop.systemd1.Manager",
1658 DBUS_TYPE_STRING, &n,
1661 dbus_error_free(&error);
1668 if (!dbus_message_get_args(reply, NULL,
1669 DBUS_TYPE_OBJECT_PATH, &path,
1670 DBUS_TYPE_INVALID)) {
1671 log_error("Failed to parse reply.");
1675 dbus_message_unref(reply);
1678 r = bus_method_call_with_reply(
1680 "org.freedesktop.systemd1",
1682 "org.freedesktop.DBus.Properties",
1686 DBUS_TYPE_STRING, &interface,
1687 DBUS_TYPE_STRING, &property,
1695 if (!dbus_message_iter_init(reply, &iter) ||
1696 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1697 log_error("Failed to parse reply.");
1701 dbus_message_iter_recurse(&iter, &sub);
1703 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1704 log_error("Failed to parse reply.");
1708 dbus_message_iter_get_basic(&sub, &state);
1713 return strv_find(check_states, state) ? 1 : 0;
1716 static void check_triggering_units(
1717 DBusConnection *bus,
1718 const char *unit_name) {
1720 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1721 DBusMessageIter iter, sub;
1722 const char *interface = "org.freedesktop.systemd1.Unit",
1723 *load_state_property = "LoadState",
1724 *triggered_by_property = "TriggeredBy",
1726 _cleanup_free_ char *unit_path = NULL, *n = NULL;
1727 bool print_warning_label = true;
1730 n = unit_name_mangle(unit_name);
1736 unit_path = unit_dbus_path_from_name(n);
1742 r = bus_method_call_with_reply(
1744 "org.freedesktop.systemd1",
1746 "org.freedesktop.DBus.Properties",
1750 DBUS_TYPE_STRING, &interface,
1751 DBUS_TYPE_STRING, &load_state_property,
1756 if (!dbus_message_iter_init(reply, &iter) ||
1757 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1758 log_error("Failed to parse reply.");
1762 dbus_message_iter_recurse(&iter, &sub);
1764 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1765 log_error("Failed to parse reply.");
1769 dbus_message_iter_get_basic(&sub, &state);
1771 if (streq(state, "masked"))
1774 dbus_message_unref(reply);
1777 r = bus_method_call_with_reply(
1779 "org.freedesktop.systemd1",
1781 "org.freedesktop.DBus.Properties",
1785 DBUS_TYPE_STRING, &interface,
1786 DBUS_TYPE_STRING, &triggered_by_property,
1791 if (!dbus_message_iter_init(reply, &iter) ||
1792 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1793 log_error("Failed to parse reply.");
1797 dbus_message_iter_recurse(&iter, &sub);
1798 dbus_message_iter_recurse(&sub, &iter);
1801 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1802 const char * const check_states[] = {
1807 const char *service_trigger;
1809 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1810 log_error("Failed to parse reply.");
1814 dbus_message_iter_get_basic(&sub, &service_trigger);
1816 r = check_one_unit(bus, service_trigger, (char**) check_states, true);
1820 if (print_warning_label) {
1821 log_warning("Warning: Stopping %s, but it can still be activated by:", unit_name);
1822 print_warning_label = false;
1825 log_warning(" %s", service_trigger);
1828 dbus_message_iter_next(&sub);
1832 static int start_unit_one(
1833 DBusConnection *bus,
1840 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1841 _cleanup_free_ char *n;
1850 n = unit_name_mangle(name);
1854 r = bus_method_call_with_reply(
1856 "org.freedesktop.systemd1",
1857 "/org/freedesktop/systemd1",
1858 "org.freedesktop.systemd1.Manager",
1862 DBUS_TYPE_STRING, &n,
1863 DBUS_TYPE_STRING, &mode,
1866 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
1867 /* There's always a fallback possible for
1868 * legacy actions. */
1871 log_error("Failed to issue method call: %s", bus_error_message(error));
1876 if (!dbus_message_get_args(reply, error,
1877 DBUS_TYPE_OBJECT_PATH, &path,
1878 DBUS_TYPE_INVALID)) {
1879 log_error("Failed to parse reply: %s", bus_error_message(error));
1883 if (need_daemon_reload(bus, n) > 0)
1884 log_warning("Warning: Unit file of %s changed on disk, 'systemctl %sdaemon-reload' recommended.",
1885 n, arg_scope == UNIT_FILE_SYSTEM ? "" : "--user ");
1894 r = set_consume(s, p);
1896 log_error("Failed to add path to set.");
1904 static const struct {
1908 } action_table[_ACTION_MAX] = {
1909 [ACTION_HALT] = { SPECIAL_HALT_TARGET, "halt", "replace-irreversibly" },
1910 [ACTION_POWEROFF] = { SPECIAL_POWEROFF_TARGET, "poweroff", "replace-irreversibly" },
1911 [ACTION_REBOOT] = { SPECIAL_REBOOT_TARGET, "reboot", "replace-irreversibly" },
1912 [ACTION_KEXEC] = { SPECIAL_KEXEC_TARGET, "kexec", "replace-irreversibly" },
1913 [ACTION_RUNLEVEL2] = { SPECIAL_RUNLEVEL2_TARGET, NULL, "isolate" },
1914 [ACTION_RUNLEVEL3] = { SPECIAL_RUNLEVEL3_TARGET, NULL, "isolate" },
1915 [ACTION_RUNLEVEL4] = { SPECIAL_RUNLEVEL4_TARGET, NULL, "isolate" },
1916 [ACTION_RUNLEVEL5] = { SPECIAL_RUNLEVEL5_TARGET, NULL, "isolate" },
1917 [ACTION_RESCUE] = { SPECIAL_RESCUE_TARGET, "rescue", "isolate" },
1918 [ACTION_EMERGENCY] = { SPECIAL_EMERGENCY_TARGET, "emergency", "isolate" },
1919 [ACTION_DEFAULT] = { SPECIAL_DEFAULT_TARGET, "default", "isolate" },
1920 [ACTION_EXIT] = { SPECIAL_EXIT_TARGET, "exit", "replace-irreversibly" },
1921 [ACTION_SUSPEND] = { SPECIAL_SUSPEND_TARGET, "suspend", "replace-irreversibly" },
1922 [ACTION_HIBERNATE] = { SPECIAL_HIBERNATE_TARGET, "hibernate", "replace-irreversibly" },
1923 [ACTION_HYBRID_SLEEP] = { SPECIAL_HYBRID_SLEEP_TARGET, "hybrid-sleep", "replace-irreversibly" },
1926 static enum action verb_to_action(const char *verb) {
1929 for (i = ACTION_INVALID; i < _ACTION_MAX; i++)
1930 if (action_table[i].verb && streq(verb, action_table[i].verb))
1932 return ACTION_INVALID;
1935 static int start_unit(DBusConnection *bus, char **args) {
1938 const char *method, *mode, *one_name;
1939 _cleanup_set_free_free_ Set *s = NULL;
1940 _cleanup_dbus_error_free_ DBusError error;
1943 dbus_error_init(&error);
1947 ask_password_agent_open_if_enabled();
1949 if (arg_action == ACTION_SYSTEMCTL) {
1952 streq(args[0], "stop") ||
1953 streq(args[0], "condstop") ? "StopUnit" :
1954 streq(args[0], "reload") ? "ReloadUnit" :
1955 streq(args[0], "restart") ? "RestartUnit" :
1957 streq(args[0], "try-restart") ||
1958 streq(args[0], "condrestart") ? "TryRestartUnit" :
1960 streq(args[0], "reload-or-restart") ? "ReloadOrRestartUnit" :
1962 streq(args[0], "reload-or-try-restart") ||
1963 streq(args[0], "condreload") ||
1965 streq(args[0], "force-reload") ? "ReloadOrTryRestartUnit" :
1967 action = verb_to_action(args[0]);
1969 mode = streq(args[0], "isolate") ? "isolate" :
1970 action_table[action].mode ?: arg_job_mode;
1972 one_name = action_table[action].target;
1975 assert(arg_action < ELEMENTSOF(action_table));
1976 assert(action_table[arg_action].target);
1978 method = "StartUnit";
1980 mode = action_table[arg_action].mode;
1981 one_name = action_table[arg_action].target;
1984 if (!arg_no_block) {
1985 ret = enable_wait_for_jobs(bus);
1987 log_error("Could not watch jobs: %s", strerror(-ret));
1991 s = set_new(string_hash_func, string_compare_func);
1997 ret = start_unit_one(bus, method, one_name, mode, &error, s);
1999 ret = translate_bus_error_to_exit_status(ret, &error);
2001 STRV_FOREACH(name, args+1) {
2002 r = start_unit_one(bus, method, *name, mode, &error, s);
2004 ret = translate_bus_error_to_exit_status(r, &error);
2005 dbus_error_free(&error);
2010 if (!arg_no_block) {
2011 r = wait_for_jobs(bus, s);
2015 /* When stopping units, warn if they can still be triggered by
2016 * another active unit (socket, path, timer) */
2017 if (!arg_quiet && streq(method, "StopUnit")) {
2019 check_triggering_units(bus, one_name);
2021 STRV_FOREACH(name, args+1)
2022 check_triggering_units(bus, *name);
2029 /* Ask systemd-logind, which might grant access to unprivileged users
2030 * through PolicyKit */
2031 static int reboot_with_logind(DBusConnection *bus, enum action a) {
2034 dbus_bool_t interactive = true;
2039 polkit_agent_open_if_enabled();
2047 case ACTION_POWEROFF:
2048 method = "PowerOff";
2051 case ACTION_SUSPEND:
2055 case ACTION_HIBERNATE:
2056 method = "Hibernate";
2059 case ACTION_HYBRID_SLEEP:
2060 method = "HybridSleep";
2067 return bus_method_call_with_reply(
2069 "org.freedesktop.login1",
2070 "/org/freedesktop/login1",
2071 "org.freedesktop.login1.Manager",
2075 DBUS_TYPE_BOOLEAN, &interactive,
2082 static int check_inhibitors(DBusConnection *bus, enum action a) {
2084 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
2085 DBusMessageIter iter, sub, sub2;
2088 _cleanup_strv_free_ char **sessions = NULL;
2094 if (arg_ignore_inhibitors || arg_force > 0)
2106 r = bus_method_call_with_reply(
2108 "org.freedesktop.login1",
2109 "/org/freedesktop/login1",
2110 "org.freedesktop.login1.Manager",
2116 /* If logind is not around, then there are no inhibitors... */
2119 if (!dbus_message_iter_init(reply, &iter) ||
2120 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
2121 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
2122 log_error("Failed to parse reply.");
2126 dbus_message_iter_recurse(&iter, &sub);
2127 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
2128 const char *what, *who, *why, *mode;
2130 _cleanup_strv_free_ char **sv = NULL;
2131 _cleanup_free_ char *comm = NULL, *user = NULL;
2133 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
2134 log_error("Failed to parse reply.");
2138 dbus_message_iter_recurse(&sub, &sub2);
2140 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &what, true) < 0 ||
2141 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &who, true) < 0 ||
2142 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &why, true) < 0 ||
2143 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &mode, true) < 0 ||
2144 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &uid, true) < 0 ||
2145 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, false) < 0) {
2146 log_error("Failed to parse reply.");
2150 if (!streq(mode, "block"))
2153 sv = strv_split(what, ":");
2157 if (!strv_contains(sv,
2159 a == ACTION_POWEROFF ||
2160 a == ACTION_REBOOT ||
2161 a == ACTION_KEXEC ? "shutdown" : "sleep"))
2164 get_process_comm(pid, &comm);
2165 user = uid_to_name(uid);
2166 log_warning("Operation inhibited by \"%s\" (PID %lu \"%s\", user %s), reason is \"%s\".",
2167 who, (unsigned long) pid, strna(comm), strna(user), why);
2171 dbus_message_iter_next(&sub);
2174 dbus_message_iter_recurse(&iter, &sub);
2176 /* Check for current sessions */
2177 sd_get_sessions(&sessions);
2178 STRV_FOREACH(s, sessions) {
2180 _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL;
2182 if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid())
2185 if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
2188 if (sd_session_get_type(*s, &type) < 0 || (!streq(type, "x11") && !streq(type, "tty")))
2191 sd_session_get_tty(*s, &tty);
2192 sd_session_get_seat(*s, &seat);
2193 sd_session_get_service(*s, &service);
2194 user = uid_to_name(uid);
2196 log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty);
2203 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
2204 action_table[a].verb);
2212 static int start_special(DBusConnection *bus, char **args) {
2218 a = verb_to_action(args[0]);
2220 r = check_inhibitors(bus, a);
2224 if (arg_force >= 2 && geteuid() != 0) {
2225 log_error("Must be root.");
2229 if (arg_force >= 2 &&
2230 (a == ACTION_HALT ||
2231 a == ACTION_POWEROFF ||
2232 a == ACTION_REBOOT))
2235 if (arg_force >= 1 &&
2236 (a == ACTION_HALT ||
2237 a == ACTION_POWEROFF ||
2238 a == ACTION_REBOOT ||
2239 a == ACTION_KEXEC ||
2241 return daemon_reload(bus, args);
2243 /* first try logind, to allow authentication with polkit */
2244 if (geteuid() != 0 &&
2245 (a == ACTION_POWEROFF ||
2246 a == ACTION_REBOOT ||
2247 a == ACTION_SUSPEND ||
2248 a == ACTION_HIBERNATE ||
2249 a == ACTION_HYBRID_SLEEP)) {
2250 r = reboot_with_logind(bus, a);
2255 r = start_unit(bus, args);
2256 if (r == EXIT_SUCCESS)
2262 static int check_unit_active(DBusConnection *bus, char **args) {
2263 const char * const check_states[] = {
2270 int r = 3; /* According to LSB: "program is not running" */
2275 STRV_FOREACH(name, args+1) {
2278 state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
2288 static int check_unit_failed(DBusConnection *bus, char **args) {
2289 const char * const check_states[] = {
2300 STRV_FOREACH(name, args+1) {
2303 state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
2313 static int kill_unit(DBusConnection *bus, char **args) {
2321 arg_kill_who = "all";
2323 STRV_FOREACH(name, args+1) {
2324 _cleanup_free_ char *n = NULL;
2326 n = unit_name_mangle(*name);
2330 r = bus_method_call_with_reply(
2332 "org.freedesktop.systemd1",
2333 "/org/freedesktop/systemd1",
2334 "org.freedesktop.systemd1.Manager",
2338 DBUS_TYPE_STRING, &n,
2339 DBUS_TYPE_STRING, &arg_kill_who,
2340 DBUS_TYPE_INT32, &arg_signal,
2348 typedef struct ExecStatusInfo {
2356 usec_t start_timestamp;
2357 usec_t exit_timestamp;
2362 LIST_FIELDS(struct ExecStatusInfo, exec);
2365 static void exec_status_info_free(ExecStatusInfo *i) {
2374 static int exec_status_info_deserialize(DBusMessageIter *sub, ExecStatusInfo *i) {
2375 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
2376 DBusMessageIter sub2, sub3;
2380 int32_t code, status;
2386 if (dbus_message_iter_get_arg_type(sub) != DBUS_TYPE_STRUCT)
2389 dbus_message_iter_recurse(sub, &sub2);
2391 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0)
2394 i->path = strdup(path);
2398 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_ARRAY ||
2399 dbus_message_iter_get_element_type(&sub2) != DBUS_TYPE_STRING)
2403 dbus_message_iter_recurse(&sub2, &sub3);
2404 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2405 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2406 dbus_message_iter_next(&sub3);
2410 i->argv = new0(char*, n+1);
2415 dbus_message_iter_recurse(&sub2, &sub3);
2416 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2419 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2420 dbus_message_iter_get_basic(&sub3, &s);
2421 dbus_message_iter_next(&sub3);
2423 i->argv[n] = strdup(s);
2430 if (!dbus_message_iter_next(&sub2) ||
2431 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, true) < 0 ||
2432 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp, true) < 0 ||
2433 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp_monotonic, true) < 0 ||
2434 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp, true) < 0 ||
2435 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp_monotonic, true) < 0 ||
2436 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, true) < 0 ||
2437 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &code, true) < 0 ||
2438 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &status, false) < 0)
2442 i->start_timestamp = (usec_t) start_timestamp;
2443 i->exit_timestamp = (usec_t) exit_timestamp;
2444 i->pid = (pid_t) pid;
2451 typedef struct UnitStatusInfo {
2453 const char *load_state;
2454 const char *active_state;
2455 const char *sub_state;
2456 const char *unit_file_state;
2458 const char *description;
2459 const char *following;
2461 char **documentation;
2463 const char *fragment_path;
2464 const char *source_path;
2465 const char *control_group;
2467 char **dropin_paths;
2469 const char *load_error;
2472 usec_t inactive_exit_timestamp;
2473 usec_t inactive_exit_timestamp_monotonic;
2474 usec_t active_enter_timestamp;
2475 usec_t active_exit_timestamp;
2476 usec_t inactive_enter_timestamp;
2478 bool need_daemon_reload;
2483 const char *status_text;
2484 const char *pid_file;
2487 usec_t start_timestamp;
2488 usec_t exit_timestamp;
2490 int exit_code, exit_status;
2492 usec_t condition_timestamp;
2493 bool condition_result;
2494 bool failed_condition_trigger;
2495 bool failed_condition_negate;
2496 const char *failed_condition;
2497 const char *failed_condition_param;
2500 unsigned n_accepted;
2501 unsigned n_connections;
2504 /* Pairs of type, path */
2508 const char *sysfs_path;
2510 /* Mount, Automount */
2516 LIST_HEAD(ExecStatusInfo, exec);
2519 static void print_status_info(UnitStatusInfo *i,
2522 const char *on, *off, *ss;
2524 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
2525 char since2[FORMAT_TIMESTAMP_MAX], *s2;
2528 arg_all * OUTPUT_SHOW_ALL |
2529 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
2530 on_tty() * OUTPUT_COLOR |
2531 !arg_quiet * OUTPUT_WARN_CUTOFF |
2532 arg_full * OUTPUT_FULL_WIDTH;
2537 /* This shows pretty information about a unit. See
2538 * print_property() for a low-level property printer */
2540 printf("%s", strna(i->id));
2542 if (i->description && !streq_ptr(i->id, i->description))
2543 printf(" - %s", i->description);
2548 printf(" Follow: unit currently follows state of %s\n", i->following);
2550 if (streq_ptr(i->load_state, "error")) {
2551 on = ansi_highlight_red();
2552 off = ansi_highlight_off();
2556 path = i->source_path ? i->source_path : i->fragment_path;
2559 printf(" Loaded: %s%s%s (Reason: %s)\n",
2560 on, strna(i->load_state), off, i->load_error);
2561 else if (path && i->unit_file_state)
2562 printf(" Loaded: %s%s%s (%s; %s)\n",
2563 on, strna(i->load_state), off, path, i->unit_file_state);
2565 printf(" Loaded: %s%s%s (%s)\n",
2566 on, strna(i->load_state), off, path);
2568 printf(" Loaded: %s%s%s\n",
2569 on, strna(i->load_state), off);
2571 if (!strv_isempty(i->dropin_paths)) {
2576 STRV_FOREACH(dropin, i->dropin_paths) {
2577 if (! dir || last) {
2578 printf(dir ? " " : " Drop-In: ");
2582 if (path_get_parent(*dropin, &dir) < 0) {
2587 printf("%s\n %s", dir,
2588 draw_special_char(DRAW_TREE_RIGHT));
2591 last = ! (*(dropin + 1) && startswith(*(dropin + 1), dir));
2593 printf("%s%s", path_get_file_name(*dropin), last ? "\n" : ", ");
2599 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
2601 if (streq_ptr(i->active_state, "failed")) {
2602 on = ansi_highlight_red();
2603 off = ansi_highlight_off();
2604 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
2605 on = ansi_highlight_green();
2606 off = ansi_highlight_off();
2611 printf(" Active: %s%s (%s)%s",
2612 on, strna(i->active_state), ss, off);
2614 printf(" Active: %s%s%s",
2615 on, strna(i->active_state), off);
2617 if (!isempty(i->result) && !streq(i->result, "success"))
2618 printf(" (Result: %s)", i->result);
2620 timestamp = (streq_ptr(i->active_state, "active") ||
2621 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
2622 (streq_ptr(i->active_state, "inactive") ||
2623 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
2624 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
2625 i->active_exit_timestamp;
2627 s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
2628 s2 = format_timestamp(since2, sizeof(since2), timestamp);
2631 printf(" since %s; %s\n", s2, s1);
2633 printf(" since %s\n", s2);
2637 if (!i->condition_result && i->condition_timestamp > 0) {
2638 s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
2639 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
2641 printf(" start condition failed at %s%s%s\n",
2642 s2, s1 ? "; " : "", s1 ? s1 : "");
2643 if (i->failed_condition_trigger)
2644 printf(" none of the trigger conditions were met\n");
2645 else if (i->failed_condition)
2646 printf(" %s=%s%s was not met\n",
2647 i->failed_condition,
2648 i->failed_condition_negate ? "!" : "",
2649 i->failed_condition_param);
2653 printf(" Device: %s\n", i->sysfs_path);
2655 printf(" Where: %s\n", i->where);
2657 printf(" What: %s\n", i->what);
2659 STRV_FOREACH(t, i->documentation)
2660 printf(" %*s %s\n", 9, t == i->documentation ? "Docs:" : "", *t);
2662 STRV_FOREACH_PAIR(t, t2, i->listen)
2663 printf(" %*s %s (%s)\n", 9, t == i->listen ? "Listen:" : "", *t2, *t);
2666 printf(" Accepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
2668 LIST_FOREACH(exec, p, i->exec) {
2669 _cleanup_free_ char *argv = NULL;
2672 /* Only show exited processes here */
2676 argv = strv_join(p->argv, " ");
2677 printf(" Process: %u %s=%s ", p->pid, p->name, strna(argv));
2679 good = is_clean_exit_lsb(p->code, p->status, NULL);
2681 on = ansi_highlight_red();
2682 off = ansi_highlight_off();
2686 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
2688 if (p->code == CLD_EXITED) {
2691 printf("status=%i", p->status);
2693 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
2698 printf("signal=%s", signal_to_string(p->status));
2700 printf(")%s\n", off);
2702 if (i->main_pid == p->pid &&
2703 i->start_timestamp == p->start_timestamp &&
2704 i->exit_timestamp == p->start_timestamp)
2705 /* Let's not show this twice */
2708 if (p->pid == i->control_pid)
2712 if (i->main_pid > 0 || i->control_pid > 0) {
2713 if (i->main_pid > 0) {
2714 printf(" Main PID: %u", (unsigned) i->main_pid);
2717 _cleanup_free_ char *comm = NULL;
2718 get_process_comm(i->main_pid, &comm);
2720 printf(" (%s)", comm);
2721 } else if (i->exit_code > 0) {
2722 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
2724 if (i->exit_code == CLD_EXITED) {
2727 printf("status=%i", i->exit_status);
2729 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
2734 printf("signal=%s", signal_to_string(i->exit_status));
2738 if (i->control_pid > 0)
2742 if (i->control_pid > 0) {
2743 _cleanup_free_ char *c = NULL;
2745 printf(" %8s: %u", i->main_pid ? "" : " Control", (unsigned) i->control_pid);
2747 get_process_comm(i->control_pid, &c);
2756 printf(" Status: \"%s\"\n", i->status_text);
2758 if (i->control_group &&
2759 (i->main_pid > 0 || i->control_pid > 0 || cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, i->control_group, false) == 0)) {
2762 printf(" CGroup: %s\n", i->control_group);
2764 if (arg_transport != TRANSPORT_SSH) {
2767 char prefix[] = " ";
2770 if (c > sizeof(prefix) - 1)
2771 c -= sizeof(prefix) - 1;
2775 if (i->main_pid > 0)
2776 extra[k++] = i->main_pid;
2778 if (i->control_pid > 0)
2779 extra[k++] = i->control_pid;
2781 show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, i->control_group, prefix,
2782 c, false, extra, k, flags);
2786 if (i->id && arg_transport != TRANSPORT_SSH) {
2788 show_journal_by_unit(stdout,
2792 i->inactive_exit_timestamp_monotonic,
2796 arg_scope == UNIT_FILE_SYSTEM,
2800 if (i->need_daemon_reload)
2801 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %sdaemon-reload' recommended.\n",
2802 ansi_highlight_red(),
2803 ansi_highlight_off(),
2804 arg_scope == UNIT_FILE_SYSTEM ? "" : "--user ");
2807 static void show_unit_help(UnitStatusInfo *i) {
2812 if (!i->documentation) {
2813 log_info("Documentation for %s not known.", i->id);
2817 STRV_FOREACH(p, i->documentation) {
2819 if (startswith(*p, "man:")) {
2822 _cleanup_free_ char *page = NULL, *section = NULL;
2823 const char *args[4] = { "man", NULL, NULL, NULL };
2828 if ((*p)[k-1] == ')')
2829 e = strrchr(*p, '(');
2832 page = strndup((*p) + 4, e - *p - 4);
2833 section = strndup(e + 1, *p + k - e - 2);
2834 if (!page || !section) {
2846 log_error("Failed to fork: %m");
2852 execvp(args[0], (char**) args);
2853 log_error("Failed to execute man: %m");
2854 _exit(EXIT_FAILURE);
2857 wait_for_terminate(pid, NULL);
2859 log_info("Can't show: %s", *p);
2863 static int status_property(const char *name, DBusMessageIter *iter, UnitStatusInfo *i) {
2869 switch (dbus_message_iter_get_arg_type(iter)) {
2871 case DBUS_TYPE_STRING: {
2874 dbus_message_iter_get_basic(iter, &s);
2877 if (streq(name, "Id"))
2879 else if (streq(name, "LoadState"))
2881 else if (streq(name, "ActiveState"))
2882 i->active_state = s;
2883 else if (streq(name, "SubState"))
2885 else if (streq(name, "Description"))
2887 else if (streq(name, "FragmentPath"))
2888 i->fragment_path = s;
2889 else if (streq(name, "SourcePath"))
2892 else if (streq(name, "DefaultControlGroup")) {
2894 e = startswith(s, SYSTEMD_CGROUP_CONTROLLER ":");
2896 i->control_group = e;
2899 else if (streq(name, "ControlGroup"))
2900 i->control_group = s;
2901 else if (streq(name, "StatusText"))
2903 else if (streq(name, "PIDFile"))
2905 else if (streq(name, "SysFSPath"))
2907 else if (streq(name, "Where"))
2909 else if (streq(name, "What"))
2911 else if (streq(name, "Following"))
2913 else if (streq(name, "UnitFileState"))
2914 i->unit_file_state = s;
2915 else if (streq(name, "Result"))
2922 case DBUS_TYPE_BOOLEAN: {
2925 dbus_message_iter_get_basic(iter, &b);
2927 if (streq(name, "Accept"))
2929 else if (streq(name, "NeedDaemonReload"))
2930 i->need_daemon_reload = b;
2931 else if (streq(name, "ConditionResult"))
2932 i->condition_result = b;
2937 case DBUS_TYPE_UINT32: {
2940 dbus_message_iter_get_basic(iter, &u);
2942 if (streq(name, "MainPID")) {
2944 i->main_pid = (pid_t) u;
2947 } else if (streq(name, "ControlPID"))
2948 i->control_pid = (pid_t) u;
2949 else if (streq(name, "ExecMainPID")) {
2951 i->main_pid = (pid_t) u;
2952 } else if (streq(name, "NAccepted"))
2954 else if (streq(name, "NConnections"))
2955 i->n_connections = u;
2960 case DBUS_TYPE_INT32: {
2963 dbus_message_iter_get_basic(iter, &j);
2965 if (streq(name, "ExecMainCode"))
2966 i->exit_code = (int) j;
2967 else if (streq(name, "ExecMainStatus"))
2968 i->exit_status = (int) j;
2973 case DBUS_TYPE_UINT64: {
2976 dbus_message_iter_get_basic(iter, &u);
2978 if (streq(name, "ExecMainStartTimestamp"))
2979 i->start_timestamp = (usec_t) u;
2980 else if (streq(name, "ExecMainExitTimestamp"))
2981 i->exit_timestamp = (usec_t) u;
2982 else if (streq(name, "ActiveEnterTimestamp"))
2983 i->active_enter_timestamp = (usec_t) u;
2984 else if (streq(name, "InactiveEnterTimestamp"))
2985 i->inactive_enter_timestamp = (usec_t) u;
2986 else if (streq(name, "InactiveExitTimestamp"))
2987 i->inactive_exit_timestamp = (usec_t) u;
2988 else if (streq(name, "InactiveExitTimestampMonotonic"))
2989 i->inactive_exit_timestamp_monotonic = (usec_t) u;
2990 else if (streq(name, "ActiveExitTimestamp"))
2991 i->active_exit_timestamp = (usec_t) u;
2992 else if (streq(name, "ConditionTimestamp"))
2993 i->condition_timestamp = (usec_t) u;
2998 case DBUS_TYPE_ARRAY: {
3000 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
3001 startswith(name, "Exec")) {
3002 DBusMessageIter sub;
3004 dbus_message_iter_recurse(iter, &sub);
3005 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3006 ExecStatusInfo *info;
3009 info = new0(ExecStatusInfo, 1);
3013 info->name = strdup(name);
3019 r = exec_status_info_deserialize(&sub, info);
3025 LIST_PREPEND(exec, i->exec, info);
3027 dbus_message_iter_next(&sub);
3030 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
3031 streq(name, "Listen")) {
3032 DBusMessageIter sub, sub2;
3034 dbus_message_iter_recurse(iter, &sub);
3035 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3036 const char *type, *path;
3038 dbus_message_iter_recurse(&sub, &sub2);
3040 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
3041 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0) {
3044 r = strv_extend(&i->listen, type);
3047 r = strv_extend(&i->listen, path);
3052 dbus_message_iter_next(&sub);
3057 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
3058 streq(name, "DropInPaths")) {
3059 int r = bus_parse_strv_iter(iter, &i->dropin_paths);
3063 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
3064 streq(name, "Documentation")) {
3066 DBusMessageIter sub;
3068 dbus_message_iter_recurse(iter, &sub);
3069 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING) {
3073 dbus_message_iter_get_basic(&sub, &s);
3075 r = strv_extend(&i->documentation, s);
3079 dbus_message_iter_next(&sub);
3082 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
3083 streq(name, "Conditions")) {
3084 DBusMessageIter sub, sub2;
3086 dbus_message_iter_recurse(iter, &sub);
3087 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3088 const char *cond, *param;
3089 dbus_bool_t trigger, negate;
3092 dbus_message_iter_recurse(&sub, &sub2);
3095 if(bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &cond, true) >= 0 &&
3096 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &trigger, true) >= 0 &&
3097 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &negate, true) >= 0 &&
3098 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, ¶m, true) >= 0 &&
3099 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &state, false) >= 0) {
3100 log_debug("%s %d %d %s %d", cond, trigger, negate, param, state);
3101 if (state < 0 && (!trigger || !i->failed_condition)) {
3102 i->failed_condition = cond;
3103 i->failed_condition_trigger = trigger;
3104 i->failed_condition_negate = negate;
3105 i->failed_condition_param = param;
3109 dbus_message_iter_next(&sub);
3116 case DBUS_TYPE_STRUCT: {
3118 if (streq(name, "LoadError")) {
3119 DBusMessageIter sub;
3120 const char *n, *message;
3123 dbus_message_iter_recurse(iter, &sub);
3125 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &n, true);
3129 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &message, false);
3133 if (!isempty(message))
3134 i->load_error = message;
3144 static int print_property(const char *name, DBusMessageIter *iter) {
3148 /* This is a low-level property printer, see
3149 * print_status_info() for the nicer output */
3151 if (arg_properties && !strv_find(arg_properties, name))
3154 switch (dbus_message_iter_get_arg_type(iter)) {
3156 case DBUS_TYPE_STRUCT: {
3157 DBusMessageIter sub;
3158 dbus_message_iter_recurse(iter, &sub);
3160 if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32 && streq(name, "Job")) {
3163 dbus_message_iter_get_basic(&sub, &u);
3166 printf("%s=%u\n", name, (unsigned) u);
3168 printf("%s=\n", name);
3171 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "Unit")) {
3174 dbus_message_iter_get_basic(&sub, &s);
3176 if (arg_all || s[0])
3177 printf("%s=%s\n", name, s);
3180 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "LoadError")) {
3181 const char *a = NULL, *b = NULL;
3183 if (bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &a, true) >= 0)
3184 bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &b, false);
3186 if (arg_all || !isempty(a) || !isempty(b))
3187 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
3195 case DBUS_TYPE_ARRAY:
3197 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "EnvironmentFiles")) {
3198 DBusMessageIter sub, sub2;
3200 dbus_message_iter_recurse(iter, &sub);
3201 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3205 dbus_message_iter_recurse(&sub, &sub2);
3207 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
3208 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) >= 0)
3209 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
3211 dbus_message_iter_next(&sub);
3216 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Paths")) {
3217 DBusMessageIter sub, sub2;
3219 dbus_message_iter_recurse(iter, &sub);
3221 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3222 const char *type, *path;
3224 dbus_message_iter_recurse(&sub, &sub2);
3226 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
3227 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
3228 printf("%s=%s\n", type, path);
3230 dbus_message_iter_next(&sub);
3235 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Listen")) {
3236 DBusMessageIter sub, sub2;
3238 dbus_message_iter_recurse(iter, &sub);
3239 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3240 const char *type, *path;
3242 dbus_message_iter_recurse(&sub, &sub2);
3244 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
3245 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
3246 printf("Listen%s=%s\n", type, path);
3248 dbus_message_iter_next(&sub);
3253 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Timers")) {
3254 DBusMessageIter sub, sub2;
3256 dbus_message_iter_recurse(iter, &sub);
3257 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3259 uint64_t value, next_elapse;
3261 dbus_message_iter_recurse(&sub, &sub2);
3263 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &base, true) >= 0 &&
3264 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &value, true) >= 0 &&
3265 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &next_elapse, false) >= 0) {
3266 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
3268 printf("%s={ value=%s ; next_elapse=%s }\n",
3270 format_timespan(timespan1, sizeof(timespan1), value, 0),
3271 format_timespan(timespan2, sizeof(timespan2), next_elapse, 0));
3274 dbus_message_iter_next(&sub);
3279 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && startswith(name, "Exec")) {
3280 DBusMessageIter sub;
3282 dbus_message_iter_recurse(iter, &sub);
3283 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3284 ExecStatusInfo info = {};
3286 if (exec_status_info_deserialize(&sub, &info) >= 0) {
3287 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
3288 _cleanup_free_ char *t;
3290 t = strv_join(info.argv, " ");
3292 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
3296 yes_no(info.ignore),
3297 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
3298 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
3299 (unsigned) info. pid,
3300 sigchld_code_to_string(info.code),
3302 info.code == CLD_EXITED ? "" : "/",
3303 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
3307 strv_free(info.argv);
3309 dbus_message_iter_next(&sub);
3314 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "DeviceAllow")) {
3315 DBusMessageIter sub, sub2;
3317 dbus_message_iter_recurse(iter, &sub);
3318 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3319 const char *path, *rwm;
3321 dbus_message_iter_recurse(&sub, &sub2);
3323 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
3324 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &rwm, false) >= 0)
3325 printf("%s=%s %s\n", name, strna(path), strna(rwm));
3327 dbus_message_iter_next(&sub);
3331 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "BlockIODeviceWeight")) {
3332 DBusMessageIter sub, sub2;
3334 dbus_message_iter_recurse(iter, &sub);
3335 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3339 dbus_message_iter_recurse(&sub, &sub2);
3341 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
3342 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &weight, false) >= 0)
3343 printf("%s=%s %" PRIu64 "\n", name, strna(path), weight);
3345 dbus_message_iter_next(&sub);
3349 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && (streq(name, "BlockIOReadBandwidth") || streq(name, "BlockIOWriteBandwidth"))) {
3350 DBusMessageIter sub, sub2;
3352 dbus_message_iter_recurse(iter, &sub);
3353 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3357 dbus_message_iter_recurse(&sub, &sub2);
3359 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
3360 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &bandwidth, false) >= 0)
3361 printf("%s=%s %" PRIu64 "\n", name, strna(path), bandwidth);
3363 dbus_message_iter_next(&sub);
3372 if (generic_print_property(name, iter, arg_all) > 0)
3376 printf("%s=[unprintable]\n", name);
3381 static int show_one(const char *verb,
3382 DBusConnection *bus,
3384 bool show_properties,
3387 _cleanup_free_ DBusMessage *reply = NULL;
3388 const char *interface = "";
3390 DBusMessageIter iter, sub, sub2, sub3;
3391 UnitStatusInfo info = {};
3397 r = bus_method_call_with_reply(
3399 "org.freedesktop.systemd1",
3401 "org.freedesktop.DBus.Properties",
3405 DBUS_TYPE_STRING, &interface,
3410 if (!dbus_message_iter_init(reply, &iter) ||
3411 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3412 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
3413 log_error("Failed to parse reply.");
3417 dbus_message_iter_recurse(&iter, &sub);
3424 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
3427 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_DICT_ENTRY);
3428 dbus_message_iter_recurse(&sub, &sub2);
3430 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
3431 dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
3432 log_error("Failed to parse reply.");
3436 dbus_message_iter_recurse(&sub2, &sub3);
3438 if (show_properties)
3439 r = print_property(name, &sub3);
3441 r = status_property(name, &sub3, &info);
3443 log_error("Failed to parse reply.");
3447 dbus_message_iter_next(&sub);
3452 if (!show_properties) {
3453 if (streq(verb, "help"))
3454 show_unit_help(&info);
3456 print_status_info(&info, ellipsized);
3459 strv_free(info.documentation);
3460 strv_free(info.dropin_paths);
3461 strv_free(info.listen);
3463 if (!streq_ptr(info.active_state, "active") &&
3464 !streq_ptr(info.active_state, "reloading") &&
3465 streq(verb, "status")) {
3466 /* According to LSB: "program not running" */
3467 /* 0: program is running or service is OK
3468 * 1: program is dead and /var/run pid file exists
3469 * 2: program is dead and /var/lock lock file exists
3470 * 3: program is not running
3471 * 4: program or service status is unknown
3473 if (info.pid_file && access(info.pid_file, F_OK) == 0)
3479 while ((p = info.exec)) {
3480 LIST_REMOVE(exec, info.exec, p);
3481 exec_status_info_free(p);
3487 static int show_one_by_pid(const char *verb,
3488 DBusConnection *bus,
3492 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3493 const char *path = NULL;
3494 _cleanup_dbus_error_free_ DBusError error;
3497 dbus_error_init(&error);
3499 r = bus_method_call_with_reply(
3501 "org.freedesktop.systemd1",
3502 "/org/freedesktop/systemd1",
3503 "org.freedesktop.systemd1.Manager",
3507 DBUS_TYPE_UINT32, &pid,
3512 if (!dbus_message_get_args(reply, &error,
3513 DBUS_TYPE_OBJECT_PATH, &path,
3514 DBUS_TYPE_INVALID)) {
3515 log_error("Failed to parse reply: %s", bus_error_message(&error));
3519 r = show_one(verb, bus, path, false, new_line, ellipsized);
3523 static int show_all(const char* verb,
3524 DBusConnection *bus,
3525 bool show_properties,
3528 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3529 _cleanup_free_ struct unit_info *unit_infos = NULL;
3531 const struct unit_info *u;
3534 r = get_unit_list(bus, &reply, &unit_infos, &c);
3538 qsort_safe(unit_infos, c, sizeof(struct unit_info), compare_unit_info);
3540 for (u = unit_infos; u < unit_infos + c; u++) {
3541 _cleanup_free_ char *p = NULL;
3543 if (!output_show_unit(u))
3546 p = unit_dbus_path_from_name(u->id);
3550 printf("%s -> '%s'\n", u->id, p);
3552 r = show_one(verb, bus, p, show_properties, new_line, ellipsized);
3560 static int show(DBusConnection *bus, char **args) {
3562 bool show_properties, show_status, new_line = false;
3564 bool ellipsized = false;
3569 show_properties = streq(args[0], "show");
3570 show_status = streq(args[0], "status");
3572 if (show_properties)
3573 pager_open_if_enabled();
3575 /* If no argument is specified inspect the manager itself */
3577 if (show_properties && strv_length(args) <= 1)
3578 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line, &ellipsized);
3580 if (show_status && strv_length(args) <= 1)
3581 ret = show_all(args[0], bus, false, &new_line, &ellipsized);
3583 STRV_FOREACH(name, args+1) {
3586 if (safe_atou32(*name, &id) < 0) {
3587 _cleanup_free_ char *p = NULL, *n = NULL;
3588 /* Interpret as unit name */
3590 n = unit_name_mangle(*name);
3594 p = unit_dbus_path_from_name(n);
3598 r = show_one(args[0], bus, p, show_properties, &new_line, &ellipsized);
3602 } else if (show_properties) {
3603 _cleanup_free_ char *p = NULL;
3605 /* Interpret as job id */
3606 if (asprintf(&p, "/org/freedesktop/systemd1/job/%u", id) < 0)
3609 r = show_one(args[0], bus, p, show_properties, &new_line, &ellipsized);
3614 /* Interpret as PID */
3615 r = show_one_by_pid(args[0], bus, id, &new_line, &ellipsized);
3621 if (ellipsized && !arg_quiet)
3622 printf("Hint: Some lines were ellipsized, use -l to show in full.\n");
3627 static int append_assignment(DBusMessageIter *iter, const char *assignment) {
3630 DBusMessageIter sub;
3636 eq = strchr(assignment, '=');
3638 log_error("Not an assignment: %s", assignment);
3642 field = strndupa(assignment, eq - assignment);
3645 if (!dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &field))
3648 if (streq(field, "CPUAccounting") ||
3649 streq(field, "MemoryAccounting") ||
3650 streq(field, "BlockIOAccounting")) {
3653 r = parse_boolean(eq);
3655 log_error("Failed to parse boolean assignment %s.", assignment);
3660 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "b", &sub) ||
3661 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_BOOLEAN, &b))
3664 } else if (streq(field, "MemoryLimit")) {
3668 r = parse_bytes(eq, &bytes);
3670 log_error("Failed to parse bytes specification %s", assignment);
3675 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "t", &sub) ||
3676 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_UINT64, &u))
3679 } else if (streq(field, "CPUShares") || streq(field, "BlockIOWeight")) {
3682 r = safe_atou64(eq, &u);
3684 log_error("Failed to parse %s value %s.", field, eq);
3688 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "t", &sub) ||
3689 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_UINT64, &u))
3692 } else if (streq(field, "DevicePolicy")) {
3694 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "s", &sub) ||
3695 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &eq))
3698 } else if (streq(field, "DeviceAllow")) {
3699 DBusMessageIter sub2;
3701 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "a(ss)", &sub) ||
3702 !dbus_message_iter_open_container(&sub, DBUS_TYPE_ARRAY, "(ss)", &sub2))
3706 const char *path, *rwm;
3707 DBusMessageIter sub3;
3710 e = strchr(eq, ' ');
3712 path = strndupa(eq, e - eq);
3719 if (!path_startswith(path, "/dev")) {
3720 log_error("%s is not a device file in /dev.", path);
3724 if (!dbus_message_iter_open_container(&sub2, DBUS_TYPE_STRUCT, NULL, &sub3) ||
3725 !dbus_message_iter_append_basic(&sub3, DBUS_TYPE_STRING, &path) ||
3726 !dbus_message_iter_append_basic(&sub3, DBUS_TYPE_STRING, &rwm) ||
3727 !dbus_message_iter_close_container(&sub2, &sub3))
3731 if (!dbus_message_iter_close_container(&sub, &sub2))
3734 } else if (streq(field, "BlockIOReadBandwidth") || streq(field, "BlockIOWriteBandwidth")) {
3735 DBusMessageIter sub2;
3737 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "a(st)", &sub) ||
3738 !dbus_message_iter_open_container(&sub, DBUS_TYPE_ARRAY, "(st)", &sub2))
3742 const char *path, *bandwidth;
3743 DBusMessageIter sub3;
3748 e = strchr(eq, ' ');
3750 path = strndupa(eq, e - eq);
3753 log_error("Failed to parse %s value %s.", field, eq);
3757 if (!path_startswith(path, "/dev")) {
3758 log_error("%s is not a device file in /dev.", path);
3762 r = parse_bytes(bandwidth, &bytes);
3764 log_error("Failed to parse byte value %s.", bandwidth);
3768 u = (uint64_t) bytes;
3770 if (!dbus_message_iter_open_container(&sub2, DBUS_TYPE_STRUCT, NULL, &sub3) ||
3771 !dbus_message_iter_append_basic(&sub3, DBUS_TYPE_STRING, &path) ||
3772 !dbus_message_iter_append_basic(&sub3, DBUS_TYPE_UINT64, &u) ||
3773 !dbus_message_iter_close_container(&sub2, &sub3))
3777 if (!dbus_message_iter_close_container(&sub, &sub2))
3780 } else if (streq(field, "BlockIODeviceWeight")) {
3781 DBusMessageIter sub2;
3783 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "a(st)", &sub) ||
3784 !dbus_message_iter_open_container(&sub, DBUS_TYPE_ARRAY, "(st)", &sub2))
3788 const char *path, *weight;
3789 DBusMessageIter sub3;
3793 e = strchr(eq, ' ');
3795 path = strndupa(eq, e - eq);
3798 log_error("Failed to parse %s value %s.", field, eq);
3802 if (!path_startswith(path, "/dev")) {
3803 log_error("%s is not a device file in /dev.", path);
3807 r = safe_atou64(weight, &u);
3809 log_error("Failed to parse %s value %s.", field, weight);
3812 if (!dbus_message_iter_open_container(&sub2, DBUS_TYPE_STRUCT, NULL, &sub3) ||
3813 !dbus_message_iter_append_basic(&sub3, DBUS_TYPE_STRING, &path) ||
3814 !dbus_message_iter_append_basic(&sub3, DBUS_TYPE_UINT64, &u) ||
3815 !dbus_message_iter_close_container(&sub2, &sub3))
3819 if (!dbus_message_iter_close_container(&sub, &sub2))
3823 log_error("Unknown assignment %s.", assignment);
3827 if (!dbus_message_iter_close_container(iter, &sub))
3833 static int set_property(DBusConnection *bus, char **args) {
3835 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
3836 _cleanup_free_ char *n = NULL;
3837 DBusMessageIter iter, sub;
3838 dbus_bool_t runtime;
3843 dbus_error_init(&error);
3845 m = dbus_message_new_method_call(
3846 "org.freedesktop.systemd1",
3847 "/org/freedesktop/systemd1",
3848 "org.freedesktop.systemd1.Manager",
3849 "SetUnitProperties");
3853 dbus_message_iter_init_append(m, &iter);
3855 runtime = arg_runtime;
3857 n = unit_name_mangle(args[1]);
3861 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &n) ||
3862 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &runtime) ||
3863 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(sv)", &sub))
3866 STRV_FOREACH(i, args + 2) {
3867 DBusMessageIter sub2;
3869 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
3872 r = append_assignment(&sub2, *i);
3876 if (!dbus_message_iter_close_container(&sub, &sub2))
3881 if (!dbus_message_iter_close_container(&iter, &sub))
3884 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3886 log_error("Failed to issue method call: %s", bus_error_message(&error));
3887 dbus_error_free(&error);
3894 static int snapshot(DBusConnection *bus, char **args) {
3895 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3898 dbus_bool_t cleanup = FALSE;
3899 DBusMessageIter iter, sub;
3902 *interface = "org.freedesktop.systemd1.Unit",
3904 _cleanup_free_ char *n = NULL;
3906 dbus_error_init(&error);
3908 if (strv_length(args) > 1)
3909 n = unit_name_mangle_with_suffix(args[1], ".snapshot");
3915 r = bus_method_call_with_reply(
3917 "org.freedesktop.systemd1",
3918 "/org/freedesktop/systemd1",
3919 "org.freedesktop.systemd1.Manager",
3923 DBUS_TYPE_STRING, &n,
3924 DBUS_TYPE_BOOLEAN, &cleanup,
3929 if (!dbus_message_get_args(reply, &error,
3930 DBUS_TYPE_OBJECT_PATH, &path,
3931 DBUS_TYPE_INVALID)) {
3932 log_error("Failed to parse reply: %s", bus_error_message(&error));
3933 dbus_error_free(&error);
3937 dbus_message_unref(reply);
3940 r = bus_method_call_with_reply (
3942 "org.freedesktop.systemd1",
3944 "org.freedesktop.DBus.Properties",
3948 DBUS_TYPE_STRING, &interface,
3949 DBUS_TYPE_STRING, &property,
3954 if (!dbus_message_iter_init(reply, &iter) ||
3955 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3956 log_error("Failed to parse reply.");
3960 dbus_message_iter_recurse(&iter, &sub);
3962 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
3963 log_error("Failed to parse reply.");
3967 dbus_message_iter_get_basic(&sub, &id);
3975 static int delete_snapshot(DBusConnection *bus, char **args) {
3980 STRV_FOREACH(name, args+1) {
3981 _cleanup_free_ char *n = NULL;
3984 n = unit_name_mangle_with_suffix(*name, ".snapshot");
3988 r = bus_method_call_with_reply(
3990 "org.freedesktop.systemd1",
3991 "/org/freedesktop/systemd1",
3992 "org.freedesktop.systemd1.Manager",
3996 DBUS_TYPE_STRING, &n,
4005 static int daemon_reload(DBusConnection *bus, char **args) {
4010 if (arg_action == ACTION_RELOAD)
4012 else if (arg_action == ACTION_REEXEC)
4013 method = "Reexecute";
4015 assert(arg_action == ACTION_SYSTEMCTL);
4018 streq(args[0], "clear-jobs") ||
4019 streq(args[0], "cancel") ? "ClearJobs" :
4020 streq(args[0], "daemon-reexec") ? "Reexecute" :
4021 streq(args[0], "reset-failed") ? "ResetFailed" :
4022 streq(args[0], "halt") ? "Halt" :
4023 streq(args[0], "poweroff") ? "PowerOff" :
4024 streq(args[0], "reboot") ? "Reboot" :
4025 streq(args[0], "kexec") ? "KExec" :
4026 streq(args[0], "exit") ? "Exit" :
4027 /* "daemon-reload" */ "Reload";
4030 r = bus_method_call_with_reply(
4032 "org.freedesktop.systemd1",
4033 "/org/freedesktop/systemd1",
4034 "org.freedesktop.systemd1.Manager",
4040 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
4041 /* There's always a fallback possible for
4042 * legacy actions. */
4044 else if ((r == -ETIMEDOUT || r == -ECONNRESET) && streq(method, "Reexecute"))
4045 /* On reexecution, we expect a disconnect, not a
4049 log_error("Failed to issue method call: %s", bus_error_message(&error));
4051 dbus_error_free(&error);
4055 static int reset_failed(DBusConnection *bus, char **args) {
4059 if (strv_length(args) <= 1)
4060 return daemon_reload(bus, args);
4062 STRV_FOREACH(name, args+1) {
4063 _cleanup_free_ char *n;
4065 n = unit_name_mangle(*name);
4069 r = bus_method_call_with_reply(
4071 "org.freedesktop.systemd1",
4072 "/org/freedesktop/systemd1",
4073 "org.freedesktop.systemd1.Manager",
4077 DBUS_TYPE_STRING, &n,
4086 static int show_enviroment(DBusConnection *bus, char **args) {
4087 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
4088 DBusMessageIter iter, sub, sub2;
4091 *interface = "org.freedesktop.systemd1.Manager",
4092 *property = "Environment";
4094 pager_open_if_enabled();
4096 r = bus_method_call_with_reply(
4098 "org.freedesktop.systemd1",
4099 "/org/freedesktop/systemd1",
4100 "org.freedesktop.DBus.Properties",
4104 DBUS_TYPE_STRING, &interface,
4105 DBUS_TYPE_STRING, &property,
4110 if (!dbus_message_iter_init(reply, &iter) ||
4111 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
4112 log_error("Failed to parse reply.");
4116 dbus_message_iter_recurse(&iter, &sub);
4118 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_ARRAY ||
4119 dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_STRING) {
4120 log_error("Failed to parse reply.");
4124 dbus_message_iter_recurse(&sub, &sub2);
4126 while (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_INVALID) {
4129 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
4130 log_error("Failed to parse reply.");
4134 dbus_message_iter_get_basic(&sub2, &text);
4137 dbus_message_iter_next(&sub2);
4143 static int switch_root(DBusConnection *bus, char **args) {
4146 _cleanup_free_ char *init = NULL;
4148 l = strv_length(args);
4149 if (l < 2 || l > 3) {
4150 log_error("Wrong number of arguments.");
4157 init = strdup(args[2]);
4159 parse_env_file("/proc/cmdline", WHITESPACE,
4169 log_debug("switching root - root: %s; init: %s", root, init);
4171 return bus_method_call_with_reply(
4173 "org.freedesktop.systemd1",
4174 "/org/freedesktop/systemd1",
4175 "org.freedesktop.systemd1.Manager",
4179 DBUS_TYPE_STRING, &root,
4180 DBUS_TYPE_STRING, &init,
4184 static int set_environment(DBusConnection *bus, char **args) {
4185 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
4188 DBusMessageIter iter;
4194 dbus_error_init(&error);
4196 method = streq(args[0], "set-environment")
4198 : "UnsetEnvironment";
4200 m = dbus_message_new_method_call(
4201 "org.freedesktop.systemd1",
4202 "/org/freedesktop/systemd1",
4203 "org.freedesktop.systemd1.Manager",
4208 dbus_message_iter_init_append(m, &iter);
4210 r = bus_append_strv_iter(&iter, args + 1);
4214 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
4216 log_error("Failed to issue method call: %s", bus_error_message(&error));
4217 dbus_error_free(&error);
4224 static int enable_sysv_units(const char *verb, char **args) {
4227 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
4228 unsigned f = 1, t = 1;
4229 _cleanup_lookup_paths_free_ LookupPaths paths = {};
4231 if (arg_scope != UNIT_FILE_SYSTEM)
4234 if (!streq(verb, "enable") &&
4235 !streq(verb, "disable") &&
4236 !streq(verb, "is-enabled"))
4239 /* Processes all SysV units, and reshuffles the array so that
4240 * afterwards only the native units remain */
4242 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, NULL, NULL, NULL);
4247 for (f = 0; args[f]; f++) {
4249 _cleanup_free_ char *p = NULL, *q = NULL;
4250 bool found_native = false, found_sysv;
4252 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
4260 if (!endswith(name, ".service"))
4263 if (path_is_absolute(name))
4266 STRV_FOREACH(k, paths.unit_path) {
4267 if (!isempty(arg_root))
4268 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
4270 asprintf(&p, "%s/%s", *k, name);
4277 found_native = access(p, F_OK) >= 0;
4288 if (!isempty(arg_root))
4289 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
4291 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
4297 p[strlen(p) - sizeof(".service") + 1] = 0;
4298 found_sysv = access(p, F_OK) >= 0;
4303 /* Mark this entry, so that we don't try enabling it as native unit */
4304 args[f] = (char*) "";
4306 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
4308 if (!isempty(arg_root))
4309 argv[c++] = q = strappend("--root=", arg_root);
4311 argv[c++] = path_get_file_name(p);
4313 streq(verb, "enable") ? "on" :
4314 streq(verb, "disable") ? "off" : "--level=5";
4317 l = strv_join((char**)argv, " ");
4323 log_info("Executing %s", l);
4328 log_error("Failed to fork: %m");
4331 } else if (pid == 0) {
4334 execv(argv[0], (char**) argv);
4335 _exit(EXIT_FAILURE);
4338 j = wait_for_terminate(pid, &status);
4340 log_error("Failed to wait for child: %s", strerror(-r));
4345 if (status.si_code == CLD_EXITED) {
4346 if (streq(verb, "is-enabled")) {
4347 if (status.si_status == 0) {
4356 } else if (status.si_status != 0) {
4367 /* Drop all SysV units */
4368 for (f = 0, t = 0; args[f]; f++) {
4370 if (isempty(args[f]))
4373 args[t++] = args[f];
4382 static int mangle_names(char **original_names, char ***mangled_names) {
4383 char **i, **l, **name;
4385 l = new(char*, strv_length(original_names) + 1);
4390 STRV_FOREACH(name, original_names) {
4392 /* When enabling units qualified path names are OK,
4393 * too, hence allow them explicitly. */
4398 *i = unit_name_mangle(*name);
4414 static int enable_unit(DBusConnection *bus, char **args) {
4415 const char *verb = args[0];
4416 UnitFileChange *changes = NULL;
4417 unsigned n_changes = 0, i;
4418 int carries_install_info = -1;
4419 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
4421 _cleanup_dbus_error_free_ DBusError error;
4422 _cleanup_strv_free_ char **mangled_names = NULL;
4424 dbus_error_init(&error);
4429 r = mangle_names(args+1, &mangled_names);
4433 r = enable_sysv_units(verb, mangled_names);
4437 if (!bus || avoid_bus()) {
4438 if (streq(verb, "enable")) {
4439 r = unit_file_enable(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4440 carries_install_info = r;
4441 } else if (streq(verb, "disable"))
4442 r = unit_file_disable(arg_scope, arg_runtime, arg_root, mangled_names, &changes, &n_changes);
4443 else if (streq(verb, "reenable")) {
4444 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4445 carries_install_info = r;
4446 } else if (streq(verb, "link"))
4447 r = unit_file_link(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4448 else if (streq(verb, "preset")) {
4449 r = unit_file_preset(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4450 carries_install_info = r;
4451 } else if (streq(verb, "mask"))
4452 r = unit_file_mask(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4453 else if (streq(verb, "unmask"))
4454 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, mangled_names, &changes, &n_changes);
4455 else if (streq(verb, "set-default"))
4456 r = unit_file_set_default(arg_scope, arg_root, args[1], &changes, &n_changes);
4458 assert_not_reached("Unknown verb");
4461 log_error("Operation failed: %s", strerror(-r));
4466 for (i = 0; i < n_changes; i++) {
4467 if (changes[i].type == UNIT_FILE_SYMLINK)
4468 log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
4470 log_info("rm '%s'", changes[i].path);
4477 bool send_force = true, expect_carries_install_info = false;
4479 DBusMessageIter iter, sub, sub2;
4481 if (streq(verb, "enable")) {
4482 method = "EnableUnitFiles";
4483 expect_carries_install_info = true;
4484 } else if (streq(verb, "disable")) {
4485 method = "DisableUnitFiles";
4487 } else if (streq(verb, "reenable")) {
4488 method = "ReenableUnitFiles";
4489 expect_carries_install_info = true;
4490 } else if (streq(verb, "link"))
4491 method = "LinkUnitFiles";
4492 else if (streq(verb, "preset")) {
4493 method = "PresetUnitFiles";
4494 expect_carries_install_info = true;
4495 } else if (streq(verb, "mask"))
4496 method = "MaskUnitFiles";
4497 else if (streq(verb, "unmask")) {
4498 method = "UnmaskUnitFiles";
4500 } else if (streq(verb, "set-default")) {
4501 method = "SetDefaultTarget";
4503 assert_not_reached("Unknown verb");
4505 m = dbus_message_new_method_call(
4506 "org.freedesktop.systemd1",
4507 "/org/freedesktop/systemd1",
4508 "org.freedesktop.systemd1.Manager",
4515 dbus_message_iter_init_append(m, &iter);
4517 r = bus_append_strv_iter(&iter, mangled_names);
4519 log_error("Failed to append unit files.");
4524 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &a)) {
4525 log_error("Failed to append runtime boolean.");
4533 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b)) {
4534 log_error("Failed to append force boolean.");
4540 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
4542 log_error("Failed to issue method call: %s", bus_error_message(&error));
4547 if (!dbus_message_iter_init(reply, &iter)) {
4548 log_error("Failed to initialize iterator.");
4552 if (expect_carries_install_info) {
4553 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &b, true);
4555 log_error("Failed to parse reply.");
4559 carries_install_info = b;
4562 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
4563 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
4564 log_error("Failed to parse reply.");
4569 dbus_message_iter_recurse(&iter, &sub);
4570 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
4571 const char *type, *path, *source;
4573 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
4574 log_error("Failed to parse reply.");
4579 dbus_message_iter_recurse(&sub, &sub2);
4581 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
4582 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
4583 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &source, false) < 0) {
4584 log_error("Failed to parse reply.");
4590 if (streq(type, "symlink"))
4591 log_info("ln -s '%s' '%s'", source, path);
4593 log_info("rm '%s'", path);
4596 dbus_message_iter_next(&sub);
4599 /* Try to reload if enabeld */
4601 r = daemon_reload(bus, args);
4604 if (carries_install_info == 0)
4605 log_warning("The unit files have no [Install] section. They are not meant to be enabled\n"
4606 "using systemctl.\n"
4607 "Possible reasons for having this kind of units are:\n"
4608 "1) A unit may be statically enabled by being symlinked from another unit's\n"
4609 " .wants/ or .requires/ directory.\n"
4610 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
4611 " a requirement dependency on it.\n"
4612 "3) A unit may be started when needed via activation (socket, path, timer,\n"
4613 " D-Bus, udev, scripted systemctl call, ...).\n");
4616 unit_file_changes_free(changes, n_changes);
4621 static int unit_is_enabled(DBusConnection *bus, char **args) {
4622 _cleanup_dbus_error_free_ DBusError error;
4624 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
4627 _cleanup_strv_free_ char **mangled_names = NULL;
4629 dbus_error_init(&error);
4631 r = mangle_names(args+1, &mangled_names);
4635 r = enable_sysv_units(args[0], mangled_names);
4641 if (!bus || avoid_bus()) {
4643 STRV_FOREACH(name, mangled_names) {
4644 UnitFileState state;
4646 state = unit_file_get_state(arg_scope, arg_root, *name);
4651 if (state == UNIT_FILE_ENABLED ||
4652 state == UNIT_FILE_ENABLED_RUNTIME ||
4653 state == UNIT_FILE_STATIC)
4657 puts(unit_file_state_to_string(state));
4661 STRV_FOREACH(name, mangled_names) {
4664 r = bus_method_call_with_reply (
4666 "org.freedesktop.systemd1",
4667 "/org/freedesktop/systemd1",
4668 "org.freedesktop.systemd1.Manager",
4672 DBUS_TYPE_STRING, name,
4678 if (!dbus_message_get_args(reply, &error,
4679 DBUS_TYPE_STRING, &s,
4680 DBUS_TYPE_INVALID)) {
4681 log_error("Failed to parse reply: %s", bus_error_message(&error));
4685 dbus_message_unref(reply);
4688 if (streq(s, "enabled") ||
4689 streq(s, "enabled-runtime") ||
4698 return enabled ? 0 : 1;
4701 static int systemctl_help(void) {
4703 pager_open_if_enabled();
4705 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
4706 "Query or send control commands to the systemd manager.\n\n"
4707 " -h --help Show this help\n"
4708 " --version Show package version\n"
4709 " -t --type=TYPE List only units of a particular type\n"
4710 " --state=STATE List only units with particular LOAD or SUB or ACTIVE state\n"
4711 " -p --property=NAME Show only properties by this name\n"
4712 " -a --all Show all loaded units/properties, including dead/empty\n"
4713 " ones. To list all units installed on the system, use\n"
4714 " the 'list-unit-files' command instead.\n"
4715 " --reverse Show reverse dependencies with 'list-dependencies'\n"
4716 " -l --full Don't ellipsize unit names on output\n"
4717 " --fail When queueing a new job, fail if conflicting jobs are\n"
4719 " --irreversible When queueing a new job, make sure it cannot be implicitly\n"
4721 " --ignore-dependencies\n"
4722 " When queueing a new job, ignore all its dependencies\n"
4723 " --show-types When showing sockets, explicitly show their type\n"
4724 " -i --ignore-inhibitors\n"
4725 " When shutting down or sleeping, ignore inhibitors\n"
4726 " --kill-who=WHO Who to send signal to\n"
4727 " -s --signal=SIGNAL Which signal to send\n"
4728 " -H --host=[USER@]HOST\n"
4729 " Show information for remote host\n"
4730 " -P --privileged Acquire privileges before execution\n"
4731 " -q --quiet Suppress output\n"
4732 " --no-block Do not wait until operation finished\n"
4733 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4734 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
4736 " --no-legend Do not print a legend (column headers and hints)\n"
4737 " --no-pager Do not pipe output into a pager\n"
4738 " --no-ask-password\n"
4739 " Do not ask for system passwords\n"
4740 " --system Connect to system manager\n"
4741 " --user Connect to user service manager\n"
4742 " --global Enable/disable unit files globally\n"
4743 " --runtime Enable unit files only temporarily until next reboot\n"
4744 " -f --force When enabling unit files, override existing symlinks\n"
4745 " When shutting down, execute action immediately\n"
4746 " --root=PATH Enable unit files in the specified root directory\n"
4747 " -n --lines=INTEGER Number of journal entries to show\n"
4748 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
4749 " verbose, export, json, json-pretty, json-sse, cat)\n\n"
4751 " list-units List loaded units\n"
4752 " list-sockets List loaded sockets ordered by address\n"
4753 " start [NAME...] Start (activate) one or more units\n"
4754 " stop [NAME...] Stop (deactivate) one or more units\n"
4755 " reload [NAME...] Reload one or more units\n"
4756 " restart [NAME...] Start or restart one or more units\n"
4757 " try-restart [NAME...] Restart one or more units if active\n"
4758 " reload-or-restart [NAME...] Reload one or more units if possible,\n"
4759 " otherwise start or restart\n"
4760 " reload-or-try-restart [NAME...] Reload one or more units if possible,\n"
4761 " otherwise restart if active\n"
4762 " isolate [NAME] Start one unit and stop all others\n"
4763 " kill [NAME...] Send signal to processes of a unit\n"
4764 " is-active [NAME...] Check whether units are active\n"
4765 " is-failed [NAME...] Check whether units are failed\n"
4766 " status [NAME...|PID...] Show runtime status of one or more units\n"
4767 " show [NAME...|JOB...] Show properties of one or more\n"
4768 " units/jobs or the manager\n"
4769 " set-property [NAME] [ASSIGNMENT...]\n"
4770 " Sets one or more properties of a unit\n"
4771 " help [NAME...|PID...] Show manual for one or more units\n"
4772 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
4774 " list-dependencies [NAME] Recursively show units which are required\n"
4775 " or wanted by this unit or by which this\n"
4776 " unit is required or wanted\n\n"
4777 "Unit File Commands:\n"
4778 " list-unit-files List installed unit files\n"
4779 " enable [NAME...] Enable one or more unit files\n"
4780 " disable [NAME...] Disable one or more unit files\n"
4781 " reenable [NAME...] Reenable one or more unit files\n"
4782 " preset [NAME...] Enable/disable one or more unit files\n"
4783 " based on preset configuration\n"
4784 " is-enabled [NAME...] Check whether unit files are enabled\n\n"
4785 " mask [NAME...] Mask one or more units\n"
4786 " unmask [NAME...] Unmask one or more units\n"
4787 " link [PATH...] Link one or more units files into\n"
4788 " the search path\n"
4789 " get-default Get the name of the default target\n"
4790 " set-default NAME Set the default target\n\n"
4792 " list-jobs List jobs\n"
4793 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
4794 "Snapshot Commands:\n"
4795 " snapshot [NAME] Create a snapshot\n"
4796 " delete [NAME...] Remove one or more snapshots\n\n"
4797 "Environment Commands:\n"
4798 " show-environment Dump environment\n"
4799 " set-environment [NAME=VALUE...] Set one or more environment variables\n"
4800 " unset-environment [NAME...] Unset one or more environment variables\n\n"
4801 "Manager Lifecycle Commands:\n"
4802 " daemon-reload Reload systemd manager configuration\n"
4803 " daemon-reexec Reexecute systemd manager\n\n"
4804 "System Commands:\n"
4805 " default Enter system default mode\n"
4806 " rescue Enter system rescue mode\n"
4807 " emergency Enter system emergency mode\n"
4808 " halt Shut down and halt the system\n"
4809 " poweroff Shut down and power-off the system\n"
4810 " reboot [ARG] Shut down and reboot the system\n"
4811 " kexec Shut down and reboot the system with kexec\n"
4812 " exit Request user instance exit\n"
4813 " switch-root [ROOT] [INIT] Change to a different root file system\n"
4814 " suspend Suspend the system\n"
4815 " hibernate Hibernate the system\n"
4816 " hybrid-sleep Hibernate and suspend the system\n",
4817 program_invocation_short_name);
4822 static int halt_help(void) {
4824 printf("%s [OPTIONS...]%s\n\n"
4825 "%s the system.\n\n"
4826 " --help Show this help\n"
4827 " --halt Halt the machine\n"
4828 " -p --poweroff Switch off the machine\n"
4829 " --reboot Reboot the machine\n"
4830 " -f --force Force immediate halt/power-off/reboot\n"
4831 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
4832 " -d --no-wtmp Don't write wtmp record\n"
4833 " --no-wall Don't send wall message before halt/power-off/reboot\n",
4834 program_invocation_short_name,
4835 arg_action == ACTION_REBOOT ? " [ARG]" : "",
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 },
4976 while ((c = getopt_long(argc, argv, "ht:p:alqfs:H:Pn:o:i", options, NULL)) >= 0) {
4981 return systemctl_help();
4984 puts(PACKAGE_STRING);
4985 puts(SYSTEMD_FEATURES);
4992 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
4993 _cleanup_free_ char *type;
4995 type = strndup(word, size);
4999 if (streq(type, "help")) {
5004 if (unit_type_from_string(type) >= 0) {
5005 if (strv_push(&arg_types, type))
5011 /* It's much nicer to use --state= for
5012 * load states, but let's support this
5013 * in --types= too for compatibility
5014 * with old versions */
5015 if (unit_load_state_from_string(optarg) >= 0) {
5016 if (strv_push(&arg_states, type) < 0)
5022 log_error("Unknown unit type or load state '%s'.", type);
5023 log_info("Use -t help to see a list of allowed values.");
5031 /* Make sure that if the empty property list
5032 was specified, we won't show any properties. */
5033 if (isempty(optarg) && !arg_properties) {
5034 arg_properties = strv_new(NULL, NULL);
5035 if (!arg_properties)
5041 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
5044 prop = strndup(word, size);
5048 if (strv_push(&arg_properties, prop) < 0) {
5055 /* If the user asked for a particular
5056 * property, show it to him, even if it is
5068 arg_dependency = DEPENDENCY_REVERSE;
5072 arg_dependency = DEPENDENCY_AFTER;
5076 arg_dependency = DEPENDENCY_BEFORE;
5079 case ARG_SHOW_TYPES:
5080 arg_show_types = true;
5084 arg_job_mode = "fail";
5087 case ARG_IRREVERSIBLE:
5088 arg_job_mode = "replace-irreversibly";
5091 case ARG_IGNORE_DEPENDENCIES:
5092 arg_job_mode = "ignore-dependencies";
5096 arg_scope = UNIT_FILE_USER;
5100 arg_scope = UNIT_FILE_SYSTEM;
5104 arg_scope = UNIT_FILE_GLOBAL;
5108 arg_no_block = true;
5112 arg_no_legend = true;
5116 arg_no_pager = true;
5132 if (strv_extend(&arg_states, "failed") < 0)
5150 arg_no_reload = true;
5154 arg_kill_who = optarg;
5158 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
5159 log_error("Failed to parse signal string %s.", optarg);
5164 case ARG_NO_ASK_PASSWORD:
5165 arg_ask_password = false;
5169 arg_transport = TRANSPORT_POLKIT;
5173 arg_transport = TRANSPORT_SSH;
5174 parse_user_at_host(optarg, &arg_user, &arg_host);
5182 if (safe_atou(optarg, &arg_lines) < 0) {
5183 log_error("Failed to parse lines '%s'", optarg);
5189 arg_output = output_mode_from_string(optarg);
5190 if (arg_output < 0) {
5191 log_error("Unknown output '%s'.", optarg);
5197 arg_ignore_inhibitors = true;
5208 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
5211 s = strndup(word, size);
5215 if (strv_push(&arg_states, s) < 0) {
5227 assert_not_reached("Unhandled option");
5231 if (arg_transport != TRANSPORT_NORMAL && arg_scope != UNIT_FILE_SYSTEM) {
5232 log_error("Cannot access user instance remotely.");
5239 static int halt_parse_argv(int argc, char *argv[]) {
5248 static const struct option options[] = {
5249 { "help", no_argument, NULL, ARG_HELP },
5250 { "halt", no_argument, NULL, ARG_HALT },
5251 { "poweroff", no_argument, NULL, 'p' },
5252 { "reboot", no_argument, NULL, ARG_REBOOT },
5253 { "force", no_argument, NULL, 'f' },
5254 { "wtmp-only", no_argument, NULL, 'w' },
5255 { "no-wtmp", no_argument, NULL, 'd' },
5256 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5265 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
5266 if (runlevel == '0' || runlevel == '6')
5269 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
5276 arg_action = ACTION_HALT;
5280 if (arg_action != ACTION_REBOOT)
5281 arg_action = ACTION_POWEROFF;
5285 arg_action = ACTION_REBOOT;
5307 /* Compatibility nops */
5314 assert_not_reached("Unhandled option");
5318 if (arg_action == ACTION_REBOOT && argc == optind + 1) {
5319 r = write_string_file(REBOOT_PARAM_FILE, argv[optind]);
5321 log_error("Failed to write reboot param to "
5322 REBOOT_PARAM_FILE": %s", strerror(-r));
5325 } else if (optind < argc) {
5326 log_error("Too many arguments.");
5333 static int parse_time_spec(const char *t, usec_t *_u) {
5337 if (streq(t, "now"))
5339 else if (!strchr(t, ':')) {
5342 if (safe_atou64(t, &u) < 0)
5345 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
5354 hour = strtol(t, &e, 10);
5355 if (errno > 0 || *e != ':' || hour < 0 || hour > 23)
5358 minute = strtol(e+1, &e, 10);
5359 if (errno > 0 || *e != 0 || minute < 0 || minute > 59)
5362 n = now(CLOCK_REALTIME);
5363 s = (time_t) (n / USEC_PER_SEC);
5365 assert_se(localtime_r(&s, &tm));
5367 tm.tm_hour = (int) hour;
5368 tm.tm_min = (int) minute;
5371 assert_se(s = mktime(&tm));
5373 *_u = (usec_t) s * USEC_PER_SEC;
5376 *_u += USEC_PER_DAY;
5382 static int shutdown_parse_argv(int argc, char *argv[]) {
5389 static const struct option options[] = {
5390 { "help", no_argument, NULL, ARG_HELP },
5391 { "halt", no_argument, NULL, 'H' },
5392 { "poweroff", no_argument, NULL, 'P' },
5393 { "reboot", no_argument, NULL, 'r' },
5394 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
5395 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5404 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
5408 return shutdown_help();
5411 arg_action = ACTION_HALT;
5415 arg_action = ACTION_POWEROFF;
5420 arg_action = ACTION_KEXEC;
5422 arg_action = ACTION_REBOOT;
5426 arg_action = ACTION_KEXEC;
5430 if (arg_action != ACTION_HALT)
5431 arg_action = ACTION_POWEROFF;
5444 /* Compatibility nops */
5448 arg_action = ACTION_CANCEL_SHUTDOWN;
5455 assert_not_reached("Unhandled option");
5459 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
5460 r = parse_time_spec(argv[optind], &arg_when);
5462 log_error("Failed to parse time specification: %s", argv[optind]);
5466 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
5468 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
5469 /* No time argument for shutdown cancel */
5470 arg_wall = argv + optind;
5471 else if (argc > optind + 1)
5472 /* We skip the time argument */
5473 arg_wall = argv + optind + 1;
5480 static int telinit_parse_argv(int argc, char *argv[]) {
5487 static const struct option options[] = {
5488 { "help", no_argument, NULL, ARG_HELP },
5489 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5493 static const struct {
5497 { '0', ACTION_POWEROFF },
5498 { '6', ACTION_REBOOT },
5499 { '1', ACTION_RESCUE },
5500 { '2', ACTION_RUNLEVEL2 },
5501 { '3', ACTION_RUNLEVEL3 },
5502 { '4', ACTION_RUNLEVEL4 },
5503 { '5', ACTION_RUNLEVEL5 },
5504 { 's', ACTION_RESCUE },
5505 { 'S', ACTION_RESCUE },
5506 { 'q', ACTION_RELOAD },
5507 { 'Q', ACTION_RELOAD },
5508 { 'u', ACTION_REEXEC },
5509 { 'U', ACTION_REEXEC }
5518 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
5522 return telinit_help();
5532 assert_not_reached("Unhandled option");
5536 if (optind >= argc) {
5541 if (optind + 1 < argc) {
5542 log_error("Too many arguments.");
5546 if (strlen(argv[optind]) != 1) {
5547 log_error("Expected single character argument.");
5551 for (i = 0; i < ELEMENTSOF(table); i++)
5552 if (table[i].from == argv[optind][0])
5555 if (i >= ELEMENTSOF(table)) {
5556 log_error("Unknown command '%s'.", argv[optind]);
5560 arg_action = table[i].to;
5567 static int runlevel_parse_argv(int argc, char *argv[]) {
5573 static const struct option options[] = {
5574 { "help", no_argument, NULL, ARG_HELP },
5583 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
5587 return runlevel_help();
5594 assert_not_reached("Unhandled option");
5598 if (optind < argc) {
5599 log_error("Too many arguments.");
5606 static int parse_argv(int argc, char *argv[]) {
5610 if (program_invocation_short_name) {
5612 if (strstr(program_invocation_short_name, "halt")) {
5613 arg_action = ACTION_HALT;
5614 return halt_parse_argv(argc, argv);
5615 } else if (strstr(program_invocation_short_name, "poweroff")) {
5616 arg_action = ACTION_POWEROFF;
5617 return halt_parse_argv(argc, argv);
5618 } else if (strstr(program_invocation_short_name, "reboot")) {
5620 arg_action = ACTION_KEXEC;
5622 arg_action = ACTION_REBOOT;
5623 return halt_parse_argv(argc, argv);
5624 } else if (strstr(program_invocation_short_name, "shutdown")) {
5625 arg_action = ACTION_POWEROFF;
5626 return shutdown_parse_argv(argc, argv);
5627 } else if (strstr(program_invocation_short_name, "init")) {
5629 if (sd_booted() > 0) {
5630 arg_action = ACTION_INVALID;
5631 return telinit_parse_argv(argc, argv);
5633 /* Hmm, so some other init system is
5634 * running, we need to forward this
5635 * request to it. For now we simply
5636 * guess that it is Upstart. */
5638 execv(TELINIT, argv);
5640 log_error("Couldn't find an alternative telinit implementation to spawn.");
5644 } else if (strstr(program_invocation_short_name, "runlevel")) {
5645 arg_action = ACTION_RUNLEVEL;
5646 return runlevel_parse_argv(argc, argv);
5650 arg_action = ACTION_SYSTEMCTL;
5651 return systemctl_parse_argv(argc, argv);
5654 _pure_ static int action_to_runlevel(void) {
5656 static const char table[_ACTION_MAX] = {
5657 [ACTION_HALT] = '0',
5658 [ACTION_POWEROFF] = '0',
5659 [ACTION_REBOOT] = '6',
5660 [ACTION_RUNLEVEL2] = '2',
5661 [ACTION_RUNLEVEL3] = '3',
5662 [ACTION_RUNLEVEL4] = '4',
5663 [ACTION_RUNLEVEL5] = '5',
5664 [ACTION_RESCUE] = '1'
5667 assert(arg_action < _ACTION_MAX);
5669 return table[arg_action];
5672 static int talk_initctl(void) {
5673 struct init_request request = {};
5675 _cleanup_close_ int fd = -1;
5678 rl = action_to_runlevel();
5682 request.magic = INIT_MAGIC;
5683 request.sleeptime = 0;
5684 request.cmd = INIT_CMD_RUNLVL;
5685 request.runlevel = rl;
5687 fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY);
5689 if (errno == ENOENT)
5692 log_error("Failed to open "INIT_FIFO": %m");
5697 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
5699 log_error("Failed to write to "INIT_FIFO": %m");
5700 return errno > 0 ? -errno : -EIO;
5706 static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
5708 static const struct {
5716 int (* const dispatch)(DBusConnection *bus, char **args);
5718 { "list-units", LESS, 1, list_units },
5719 { "list-unit-files", EQUAL, 1, list_unit_files },
5720 { "list-sockets", LESS, 1, list_sockets },
5721 { "list-jobs", EQUAL, 1, list_jobs },
5722 { "clear-jobs", EQUAL, 1, daemon_reload },
5723 { "cancel", MORE, 2, cancel_job },
5724 { "start", MORE, 2, start_unit },
5725 { "stop", MORE, 2, start_unit },
5726 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5727 { "reload", MORE, 2, start_unit },
5728 { "restart", MORE, 2, start_unit },
5729 { "try-restart", MORE, 2, start_unit },
5730 { "reload-or-restart", MORE, 2, start_unit },
5731 { "reload-or-try-restart", MORE, 2, start_unit },
5732 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
5733 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5734 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
5735 { "isolate", EQUAL, 2, start_unit },
5736 { "kill", MORE, 2, kill_unit },
5737 { "is-active", MORE, 2, check_unit_active },
5738 { "check", MORE, 2, check_unit_active },
5739 { "is-failed", MORE, 2, check_unit_failed },
5740 { "show", MORE, 1, show },
5741 { "status", MORE, 1, show },
5742 { "help", MORE, 2, show },
5743 { "snapshot", LESS, 2, snapshot },
5744 { "delete", MORE, 2, delete_snapshot },
5745 { "daemon-reload", EQUAL, 1, daemon_reload },
5746 { "daemon-reexec", EQUAL, 1, daemon_reload },
5747 { "show-environment", EQUAL, 1, show_enviroment },
5748 { "set-environment", MORE, 2, set_environment },
5749 { "unset-environment", MORE, 2, set_environment },
5750 { "halt", EQUAL, 1, start_special },
5751 { "poweroff", EQUAL, 1, start_special },
5752 { "reboot", EQUAL, 1, start_special },
5753 { "kexec", EQUAL, 1, start_special },
5754 { "suspend", EQUAL, 1, start_special },
5755 { "hibernate", EQUAL, 1, start_special },
5756 { "hybrid-sleep", EQUAL, 1, start_special },
5757 { "default", EQUAL, 1, start_special },
5758 { "rescue", EQUAL, 1, start_special },
5759 { "emergency", EQUAL, 1, start_special },
5760 { "exit", EQUAL, 1, start_special },
5761 { "reset-failed", MORE, 1, reset_failed },
5762 { "enable", MORE, 2, enable_unit },
5763 { "disable", MORE, 2, enable_unit },
5764 { "is-enabled", MORE, 2, unit_is_enabled },
5765 { "reenable", MORE, 2, enable_unit },
5766 { "preset", MORE, 2, enable_unit },
5767 { "mask", MORE, 2, enable_unit },
5768 { "unmask", MORE, 2, enable_unit },
5769 { "link", MORE, 2, enable_unit },
5770 { "switch-root", MORE, 2, switch_root },
5771 { "list-dependencies", LESS, 2, list_dependencies },
5772 { "set-default", EQUAL, 2, enable_unit },
5773 { "get-default", LESS, 1, get_default },
5774 { "set-property", MORE, 3, set_property },
5784 left = argc - optind;
5787 /* Special rule: no arguments means "list-units" */
5790 if (streq(argv[optind], "help") && !argv[optind+1]) {
5791 log_error("This command expects one or more "
5792 "unit names. Did you mean --help?");
5796 for (i = 0; i < ELEMENTSOF(verbs); i++)
5797 if (streq(argv[optind], verbs[i].verb))
5800 if (i >= ELEMENTSOF(verbs)) {
5801 log_error("Unknown operation '%s'.", argv[optind]);
5806 switch (verbs[i].argc_cmp) {
5809 if (left != verbs[i].argc) {
5810 log_error("Invalid number of arguments.");
5817 if (left < verbs[i].argc) {
5818 log_error("Too few arguments.");
5825 if (left > verbs[i].argc) {
5826 log_error("Too many arguments.");
5833 assert_not_reached("Unknown comparison operator.");
5836 /* Require a bus connection for all operations but
5838 if (!streq(verbs[i].verb, "enable") &&
5839 !streq(verbs[i].verb, "disable") &&
5840 !streq(verbs[i].verb, "is-enabled") &&
5841 !streq(verbs[i].verb, "list-unit-files") &&
5842 !streq(verbs[i].verb, "reenable") &&
5843 !streq(verbs[i].verb, "preset") &&
5844 !streq(verbs[i].verb, "mask") &&
5845 !streq(verbs[i].verb, "unmask") &&
5846 !streq(verbs[i].verb, "link") &&
5847 !streq(verbs[i].verb, "set-default") &&
5848 !streq(verbs[i].verb, "get-default")) {
5850 if (running_in_chroot() > 0) {
5851 log_info("Running in chroot, ignoring request.");
5855 if (((!streq(verbs[i].verb, "reboot") &&
5856 !streq(verbs[i].verb, "halt") &&
5857 !streq(verbs[i].verb, "poweroff")) || arg_force <= 0) && !bus) {
5858 log_error("Failed to get D-Bus connection: %s",
5859 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5865 if (!bus && !avoid_bus()) {
5866 log_error("Failed to get D-Bus connection: %s",
5867 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5872 return verbs[i].dispatch(bus, argv + optind);
5875 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
5876 _cleanup_close_ int fd;
5877 struct sd_shutdown_command c = {
5883 union sockaddr_union sockaddr = {
5884 .un.sun_family = AF_UNIX,
5885 .un.sun_path = "/run/systemd/shutdownd",
5887 struct iovec iovec[2] = {
5888 {.iov_base = (char*) &c,
5889 .iov_len = offsetof(struct sd_shutdown_command, wall_message),
5892 struct msghdr msghdr = {
5893 .msg_name = &sockaddr,
5894 .msg_namelen = offsetof(struct sockaddr_un, sun_path)
5895 + sizeof("/run/systemd/shutdownd") - 1,
5900 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
5904 if (!isempty(message)) {
5905 iovec[1].iov_base = (char*) message;
5906 iovec[1].iov_len = strlen(message);
5907 msghdr.msg_iovlen++;
5910 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0)
5916 static int reload_with_fallback(DBusConnection *bus) {
5919 /* First, try systemd via D-Bus. */
5920 if (daemon_reload(bus, NULL) >= 0)
5924 /* Nothing else worked, so let's try signals */
5925 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
5927 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
5928 log_error("kill() failed: %m");
5935 static int start_with_fallback(DBusConnection *bus) {
5938 /* First, try systemd via D-Bus. */
5939 if (start_unit(bus, NULL) >= 0)
5943 /* Nothing else worked, so let's try
5945 if (talk_initctl() > 0)
5948 log_error("Failed to talk to init daemon.");
5952 warn_wall(arg_action);
5956 static _noreturn_ void halt_now(enum action a) {
5958 _cleanup_free_ char *param = NULL;
5960 /* Make sure C-A-D is handled by the kernel from this
5962 reboot(RB_ENABLE_CAD);
5967 log_info("Halting.");
5968 reboot(RB_HALT_SYSTEM);
5971 case ACTION_POWEROFF:
5972 log_info("Powering off.");
5973 reboot(RB_POWER_OFF);
5977 if (read_one_line_file(REBOOT_PARAM_FILE, ¶m) == 0) {
5978 log_info("Rebooting with arg '%s'.", param);
5979 syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
5980 LINUX_REBOOT_CMD_RESTART2, param);
5982 log_info("Rebooting.");
5983 reboot(RB_AUTOBOOT);
5988 assert_not_reached("Unknown halt action.");
5991 assert_not_reached("Uh? This shouldn't happen.");
5994 static int halt_main(DBusConnection *bus) {
5997 r = check_inhibitors(bus, arg_action);
6001 if (geteuid() != 0) {
6002 /* Try logind if we are a normal user and no special
6003 * mode applies. Maybe PolicyKit allows us to shutdown
6006 if (arg_when <= 0 &&
6009 (arg_action == ACTION_POWEROFF ||
6010 arg_action == ACTION_REBOOT)) {
6011 r = reboot_with_logind(bus, arg_action);
6016 log_error("Must be root.");
6021 _cleanup_free_ char *m;
6023 m = strv_join(arg_wall, " ");
6024 r = send_shutdownd(arg_when,
6025 arg_action == ACTION_HALT ? 'H' :
6026 arg_action == ACTION_POWEROFF ? 'P' :
6027 arg_action == ACTION_KEXEC ? 'K' :
6034 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
6036 char date[FORMAT_TIMESTAMP_MAX];
6038 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
6039 format_timestamp(date, sizeof(date), arg_when));
6044 if (!arg_dry && !arg_force)
6045 return start_with_fallback(bus);
6048 if (sd_booted() > 0)
6049 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
6051 r = utmp_put_shutdown();
6053 log_warning("Failed to write utmp record: %s", strerror(-r));
6060 halt_now(arg_action);
6061 /* We should never reach this. */
6065 static int runlevel_main(void) {
6066 int r, runlevel, previous;
6068 r = utmp_get_runlevel(&runlevel, &previous);
6075 previous <= 0 ? 'N' : previous,
6076 runlevel <= 0 ? 'N' : runlevel);
6081 int main(int argc, char*argv[]) {
6082 int r, retval = EXIT_FAILURE;
6083 DBusConnection *bus = NULL;
6084 _cleanup_dbus_error_free_ DBusError error;
6086 dbus_error_init(&error);
6088 setlocale(LC_ALL, "");
6089 log_parse_environment();
6092 /* Explicitly not on_tty() to avoid setting cached value.
6093 * This becomes relevant for piping output which might be
6095 original_stdout_is_tty = isatty(STDOUT_FILENO);
6097 r = parse_argv(argc, argv);
6101 retval = EXIT_SUCCESS;
6105 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
6106 * let's shortcut this */
6107 if (arg_action == ACTION_RUNLEVEL) {
6108 r = runlevel_main();
6109 retval = r < 0 ? EXIT_FAILURE : r;
6113 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
6114 log_info("Running in chroot, ignoring request.");
6120 if (arg_transport == TRANSPORT_NORMAL)
6121 bus_connect(arg_scope == UNIT_FILE_SYSTEM ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &bus, &private_bus, &error);
6122 else if (arg_transport == TRANSPORT_POLKIT) {
6123 bus_connect_system_polkit(&bus, &error);
6124 private_bus = false;
6125 } else if (arg_transport == TRANSPORT_SSH) {
6126 bus_connect_system_ssh(arg_user, arg_host, &bus, &error);
6127 private_bus = false;
6129 assert_not_reached("Uh, invalid transport...");
6132 switch (arg_action) {
6134 case ACTION_SYSTEMCTL:
6135 r = systemctl_main(bus, argc, argv, &error);
6139 case ACTION_POWEROFF:
6145 case ACTION_RUNLEVEL2:
6146 case ACTION_RUNLEVEL3:
6147 case ACTION_RUNLEVEL4:
6148 case ACTION_RUNLEVEL5:
6150 case ACTION_EMERGENCY:
6151 case ACTION_DEFAULT:
6152 r = start_with_fallback(bus);
6157 r = reload_with_fallback(bus);
6160 case ACTION_CANCEL_SHUTDOWN: {
6164 m = strv_join(arg_wall, " ");
6166 retval = EXIT_FAILURE;
6170 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
6172 log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r));
6177 case ACTION_INVALID:
6178 case ACTION_RUNLEVEL:
6180 assert_not_reached("Unknown action");
6183 retval = r < 0 ? EXIT_FAILURE : r;
6187 dbus_connection_flush(bus);
6188 dbus_connection_close(bus);
6189 dbus_connection_unref(bus);
6194 strv_free(arg_types);
6195 strv_free(arg_states);
6196 strv_free(arg_properties);
6199 ask_password_agent_close();
6200 polkit_agent_close();