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, active_len, sub_len, job_len, desc_len, n_shown = 0;
293 const struct unit_info *u;
296 max_id_len = sizeof("UNIT")-1;
297 active_len = sizeof("ACTIVE")-1;
298 sub_len = sizeof("SUB")-1;
299 job_len = sizeof("JOB")-1;
302 for (u = unit_infos; u < unit_infos + c; u++) {
303 if (!output_show_unit(u))
306 max_id_len = MAX(max_id_len, strlen(u->id));
307 active_len = MAX(active_len, strlen(u->active_state));
308 sub_len = MAX(sub_len, strlen(u->sub_state));
309 if (u->job_id != 0) {
310 job_len = MAX(job_len, strlen(u->job_type));
315 if (!arg_full && original_stdout_is_tty) {
317 id_len = MIN(max_id_len, 25u);
318 basic_len = 5 + id_len + 5 + active_len + sub_len;
320 basic_len += job_len + 1;
321 if (basic_len < (unsigned) columns()) {
322 unsigned extra_len, incr;
323 extra_len = columns() - basic_len;
324 /* Either UNIT already got 25, or is fully satisfied.
325 * Grant up to 25 to DESC now. */
326 incr = MIN(extra_len, 25u);
329 /* split the remaining space between UNIT and DESC,
330 * but do not give UNIT more than it needs. */
332 incr = MIN(extra_len / 2, max_id_len - id_len);
334 desc_len += extra_len - incr;
340 for (u = unit_infos; u < unit_infos + c; u++) {
341 _cleanup_free_ char *e = NULL;
342 const char *on_loaded, *off_loaded, *on = "";
343 const char *on_active, *off_active, *off = "";
345 if (!output_show_unit(u))
348 if (!n_shown && !arg_no_legend) {
349 printf("%-*s %-6s %-*s %-*s ", id_len, "UNIT", "LOAD",
350 active_len, "ACTIVE", sub_len, "SUB");
352 printf("%-*s ", job_len, "JOB");
353 if (!arg_full && arg_no_pager)
354 printf("%.*s\n", desc_len, "DESCRIPTION");
356 printf("%s\n", "DESCRIPTION");
361 if (streq(u->load_state, "error") ||
362 streq(u->load_state, "not-found")) {
363 on_loaded = on = ansi_highlight_red();
364 off_loaded = off = ansi_highlight_off();
366 on_loaded = off_loaded = "";
368 if (streq(u->active_state, "failed")) {
369 on_active = on = ansi_highlight_red();
370 off_active = off = ansi_highlight_off();
372 on_active = off_active = "";
374 e = arg_full ? NULL : ellipsize(u->id, id_len, 33);
376 printf("%s%-*s%s %s%-6s%s %s%-*s %-*s%s %-*s",
377 on, id_len, e ? e : u->id, off,
378 on_loaded, u->load_state, off_loaded,
379 on_active, active_len, u->active_state,
380 sub_len, u->sub_state, off_active,
381 job_count ? job_len + 1 : 0, u->job_id ? u->job_type : "");
383 printf("%.*s\n", desc_len, u->description);
385 printf("%s\n", u->description);
388 if (!arg_no_legend) {
389 const char *on, *off;
392 printf("\nLOAD = Reflects whether the unit definition was properly loaded.\n"
393 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
394 "SUB = The low-level unit activation state, values depend on unit type.\n");
396 printf("JOB = Pending job for the unit.\n");
398 on = ansi_highlight();
399 off = ansi_highlight_off();
401 on = ansi_highlight_red();
402 off = ansi_highlight_off();
406 printf("%s%u loaded units listed.%s\n"
407 "To show all installed unit files use 'systemctl list-unit-files'.\n",
410 printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
411 "To show all installed unit files use 'systemctl list-unit-files'.\n",
416 static int get_unit_list(
419 struct unit_info **unit_infos,
422 DBusMessageIter iter, sub;
430 r = bus_method_call_with_reply(
432 "org.freedesktop.systemd1",
433 "/org/freedesktop/systemd1",
434 "org.freedesktop.systemd1.Manager",
442 if (!dbus_message_iter_init(*reply, &iter) ||
443 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
444 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
445 log_error("Failed to parse reply.");
449 dbus_message_iter_recurse(&iter, &sub);
451 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
452 if (!GREEDY_REALLOC(*unit_infos, size, *c + 1))
455 bus_parse_unit_info(&sub, *unit_infos + *c);
458 dbus_message_iter_next(&sub);
464 static int list_units(DBusConnection *bus, char **args) {
465 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
466 _cleanup_free_ struct unit_info *unit_infos = NULL;
470 pager_open_if_enabled();
472 r = get_unit_list(bus, &reply, &unit_infos, &c);
476 qsort_safe(unit_infos, c, sizeof(struct unit_info), compare_unit_info);
478 output_units_list(unit_infos, c);
483 static int get_triggered_units(
485 const char* unit_path,
488 const char *interface = "org.freedesktop.systemd1.Unit",
489 *triggers_property = "Triggers";
490 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
491 DBusMessageIter iter, sub;
494 r = bus_method_call_with_reply(bus,
495 "org.freedesktop.systemd1",
497 "org.freedesktop.DBus.Properties",
501 DBUS_TYPE_STRING, &interface,
502 DBUS_TYPE_STRING, &triggers_property,
507 if (!dbus_message_iter_init(reply, &iter) ||
508 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
509 log_error("Failed to parse reply.");
513 dbus_message_iter_recurse(&iter, &sub);
514 dbus_message_iter_recurse(&sub, &iter);
517 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
520 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
521 log_error("Failed to parse reply.");
525 dbus_message_iter_get_basic(&sub, &unit);
526 r = strv_extend(triggered, unit);
530 dbus_message_iter_next(&sub);
536 static int get_listening(DBusConnection *bus, const char* unit_path,
537 char*** listen, unsigned *c)
539 const char *interface = "org.freedesktop.systemd1.Socket",
540 *listen_property = "Listen";
541 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
542 DBusMessageIter iter, sub;
545 r = bus_method_call_with_reply(bus,
546 "org.freedesktop.systemd1",
548 "org.freedesktop.DBus.Properties",
552 DBUS_TYPE_STRING, &interface,
553 DBUS_TYPE_STRING, &listen_property,
558 if (!dbus_message_iter_init(reply, &iter) ||
559 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
560 log_error("Failed to parse reply.");
564 dbus_message_iter_recurse(&iter, &sub);
565 dbus_message_iter_recurse(&sub, &iter);
568 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
569 DBusMessageIter sub2;
570 const char *type, *path;
572 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
573 log_error("Failed to parse reply.");
577 dbus_message_iter_recurse(&sub, &sub2);
579 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
580 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0) {
581 r = strv_extend(listen, type);
585 r = strv_extend(listen, path);
592 dbus_message_iter_next(&sub);
604 /* Note: triggered is a list here, although it almost certainly
605 * will always be one unit. Nevertheless, dbus API allows for multiple
606 * values, so let's follow that.*/
609 /* The strv above is shared. free is set only in the first one. */
613 static int socket_info_compare(struct socket_info *a, struct socket_info *b) {
614 int o = strcmp(a->path, b->path);
616 o = strcmp(a->type, b->type);
620 static int output_sockets_list(struct socket_info *socket_infos, unsigned cs) {
621 struct socket_info *s;
622 unsigned pathlen = sizeof("LISTEN") - 1,
623 typelen = (sizeof("TYPE") - 1) * arg_show_types,
624 socklen = sizeof("UNIT") - 1,
625 servlen = sizeof("ACTIVATES") - 1;
626 const char *on, *off;
628 for (s = socket_infos; s < socket_infos + cs; s++) {
632 socklen = MAX(socklen, strlen(s->id));
634 typelen = MAX(typelen, strlen(s->type));
635 pathlen = MAX(pathlen, strlen(s->path));
637 STRV_FOREACH(a, s->triggered)
638 tmp += strlen(*a) + 2*(a != s->triggered);
639 servlen = MAX(servlen, tmp);
644 printf("%-*s %-*.*s%-*s %s\n",
646 typelen + arg_show_types, typelen + arg_show_types, "TYPE ",
650 for (s = socket_infos; s < socket_infos + cs; s++) {
654 printf("%-*s %-*s %-*s",
655 pathlen, s->path, typelen, s->type, socklen, s->id);
658 pathlen, s->path, socklen, s->id);
659 STRV_FOREACH(a, s->triggered)
661 a == s->triggered ? "" : ",", *a);
665 on = ansi_highlight();
666 off = ansi_highlight_off();
670 on = ansi_highlight_red();
671 off = ansi_highlight_off();
674 if (!arg_no_legend) {
675 printf("%s%u sockets listed.%s\n", on, cs, off);
677 printf("Pass --all to see loaded but inactive sockets, too.\n");
683 static int list_sockets(DBusConnection *bus, char **args) {
684 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
685 _cleanup_free_ struct unit_info *unit_infos = NULL;
686 struct socket_info *socket_infos = NULL;
687 const struct unit_info *u;
688 struct socket_info *s;
689 unsigned cu = 0, cs = 0;
693 pager_open_if_enabled();
695 r = get_unit_list(bus, &reply, &unit_infos, &cu);
699 for (u = unit_infos; u < unit_infos + cu; u++) {
701 _cleanup_strv_free_ char **listen = NULL, **triggered = NULL;
704 if (!output_show_unit(u))
707 if ((dot = strrchr(u->id, '.')) && !streq(dot+1, "socket"))
710 r = get_triggered_units(bus, u->unit_path, &triggered);
714 r = get_listening(bus, u->unit_path, &listen, &c);
718 if (!GREEDY_REALLOC(socket_infos, size, cs + c)) {
723 for (i = 0; i < c; i++)
724 socket_infos[cs + i] = (struct socket_info) {
727 .path = listen[i*2 + 1],
728 .triggered = triggered,
729 .own_triggered = i==0,
732 /* from this point on we will cleanup those socket_infos */
735 listen = triggered = NULL; /* avoid cleanup */
738 qsort_safe(socket_infos, cs, sizeof(struct socket_info),
739 (__compar_fn_t) socket_info_compare);
741 output_sockets_list(socket_infos, cs);
744 assert(cs == 0 || socket_infos);
745 for (s = socket_infos; s < socket_infos + cs; s++) {
748 if (s->own_triggered)
749 strv_free(s->triggered);
756 static int compare_unit_file_list(const void *a, const void *b) {
758 const UnitFileList *u = a, *v = b;
760 d1 = strrchr(u->path, '.');
761 d2 = strrchr(v->path, '.');
766 r = strcasecmp(d1, d2);
771 return strcasecmp(path_get_file_name(u->path), path_get_file_name(v->path));
774 static bool output_show_unit_file(const UnitFileList *u) {
777 return !arg_types || ((dot = strrchr(u->path, '.')) && strv_find(arg_types, dot+1));
780 static void output_unit_file_list(const UnitFileList *units, unsigned c) {
781 unsigned max_id_len, id_cols, state_cols, n_shown = 0;
782 const UnitFileList *u;
784 max_id_len = sizeof("UNIT FILE")-1;
785 state_cols = sizeof("STATE")-1;
786 for (u = units; u < units + c; u++) {
787 if (!output_show_unit_file(u))
790 max_id_len = MAX(max_id_len, strlen(path_get_file_name(u->path)));
791 state_cols = MAX(state_cols, strlen(unit_file_state_to_string(u->state)));
796 id_cols = MIN(max_id_len, 25u);
797 basic_cols = 1 + id_cols + state_cols;
798 if (basic_cols < (unsigned) columns())
799 id_cols += MIN(columns() - basic_cols, max_id_len - id_cols);
801 id_cols = max_id_len;
804 printf("%-*s %-*s\n", id_cols, "UNIT FILE", state_cols, "STATE");
806 for (u = units; u < units + c; u++) {
807 _cleanup_free_ char *e = NULL;
808 const char *on, *off;
811 if (!output_show_unit_file(u))
816 if (u->state == UNIT_FILE_MASKED ||
817 u->state == UNIT_FILE_MASKED_RUNTIME ||
818 u->state == UNIT_FILE_DISABLED ||
819 u->state == UNIT_FILE_INVALID) {
820 on = ansi_highlight_red();
821 off = ansi_highlight_off();
822 } else if (u->state == UNIT_FILE_ENABLED) {
823 on = ansi_highlight_green();
824 off = ansi_highlight_off();
828 id = path_get_file_name(u->path);
830 e = arg_full ? NULL : ellipsize(id, id_cols, 33);
832 printf("%-*s %s%-*s%s\n",
834 on, state_cols, unit_file_state_to_string(u->state), off);
838 printf("\n%u unit files listed.\n", n_shown);
841 static int list_unit_files(DBusConnection *bus, char **args) {
842 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
843 _cleanup_free_ UnitFileList *units = NULL;
844 DBusMessageIter iter, sub, sub2;
845 unsigned c = 0, n_units = 0;
848 pager_open_if_enabled();
855 h = hashmap_new(string_hash_func, string_compare_func);
859 r = unit_file_get_list(arg_scope, arg_root, h);
861 unit_file_list_free(h);
862 log_error("Failed to get unit file list: %s", strerror(-r));
866 n_units = hashmap_size(h);
867 units = new(UnitFileList, n_units);
869 unit_file_list_free(h);
873 HASHMAP_FOREACH(u, h, i) {
874 memcpy(units + c++, u, sizeof(UnitFileList));
880 r = bus_method_call_with_reply(
882 "org.freedesktop.systemd1",
883 "/org/freedesktop/systemd1",
884 "org.freedesktop.systemd1.Manager",
892 if (!dbus_message_iter_init(reply, &iter) ||
893 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
894 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
895 log_error("Failed to parse reply.");
899 dbus_message_iter_recurse(&iter, &sub);
901 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
905 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT);
910 n_units = MAX(2*c, 16u);
911 w = realloc(units, sizeof(struct UnitFileList) * n_units);
920 dbus_message_iter_recurse(&sub, &sub2);
922 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->path, true) < 0 ||
923 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, false) < 0) {
924 log_error("Failed to parse reply.");
928 u->state = unit_file_state_from_string(state);
930 dbus_message_iter_next(&sub);
936 qsort(units, c, sizeof(UnitFileList), compare_unit_file_list);
937 output_unit_file_list(units, c);
943 static int list_dependencies_print(const char *name, int level, unsigned int branches, bool last) {
945 _cleanup_free_ char *n = NULL;
947 size_t max_len = MAX(columns(),20u);
950 for (i = level - 1; i >= 0; i--) {
952 if(len > max_len - 3 && !arg_full) {
953 printf("%s...\n",max_len % 2 ? "" : " ");
956 printf("%s", draw_special_char(branches & (1 << i) ? DRAW_TREE_VERT : DRAW_TREE_SPACE));
959 if(len > max_len - 3 && !arg_full) {
960 printf("%s...\n",max_len % 2 ? "" : " ");
963 printf("%s", draw_special_char(last ? DRAW_TREE_RIGHT : DRAW_TREE_BRANCH));
967 printf("%s\n", name);
971 n = ellipsize(name, max_len-len, 100);
979 static int list_dependencies_get_dependencies(DBusConnection *bus, const char *name, char ***deps) {
980 static const char *dependencies[] = {
981 [DEPENDENCY_FORWARD] = "Requires\0"
982 "RequiresOverridable\0"
984 "RequisiteOverridable\0"
986 [DEPENDENCY_REVERSE] = "RequiredBy\0"
987 "RequiredByOverridable\0"
990 [DEPENDENCY_AFTER] = "After\0",
991 [DEPENDENCY_BEFORE] = "Before\0",
994 _cleanup_free_ char *path;
995 const char *interface = "org.freedesktop.systemd1.Unit";
997 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
998 DBusMessageIter iter, sub, sub2, sub3;
1007 path = unit_dbus_path_from_name(name);
1013 r = bus_method_call_with_reply(
1015 "org.freedesktop.systemd1",
1017 "org.freedesktop.DBus.Properties",
1021 DBUS_TYPE_STRING, &interface,
1026 if (!dbus_message_iter_init(reply, &iter) ||
1027 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
1028 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
1029 log_error("Failed to parse reply.");
1034 dbus_message_iter_recurse(&iter, &sub);
1036 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1039 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_DICT_ENTRY);
1040 dbus_message_iter_recurse(&sub, &sub2);
1042 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &prop, true) < 0) {
1043 log_error("Failed to parse reply.");
1048 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
1049 log_error("Failed to parse reply.");
1054 dbus_message_iter_recurse(&sub2, &sub3);
1055 dbus_message_iter_next(&sub);
1057 assert(arg_dependency < ELEMENTSOF(dependencies));
1058 if (!nulstr_contains(dependencies[arg_dependency], prop))
1061 if (dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_ARRAY) {
1062 if (dbus_message_iter_get_element_type(&sub3) == DBUS_TYPE_STRING) {
1063 DBusMessageIter sub4;
1064 dbus_message_iter_recurse(&sub3, &sub4);
1066 while (dbus_message_iter_get_arg_type(&sub4) != DBUS_TYPE_INVALID) {
1069 assert(dbus_message_iter_get_arg_type(&sub4) == DBUS_TYPE_STRING);
1070 dbus_message_iter_get_basic(&sub4, &s);
1072 r = strv_extend(&ret, s);
1078 dbus_message_iter_next(&sub4);
1091 static int list_dependencies_compare(const void *_a, const void *_b) {
1092 const char **a = (const char**) _a, **b = (const char**) _b;
1093 if (unit_name_to_type(*a) == UNIT_TARGET && unit_name_to_type(*b) != UNIT_TARGET)
1095 if (unit_name_to_type(*a) != UNIT_TARGET && unit_name_to_type(*b) == UNIT_TARGET)
1097 return strcasecmp(*a, *b);
1100 static int list_dependencies_one(DBusConnection *bus, const char *name, int level, char ***units, unsigned int branches) {
1101 _cleanup_strv_free_ char **deps = NULL, **u;
1105 u = strv_append(*units, name);
1109 r = list_dependencies_get_dependencies(bus, name, &deps);
1113 qsort_safe(deps, strv_length(deps), sizeof (char*), list_dependencies_compare);
1115 STRV_FOREACH(c, deps) {
1116 if (strv_contains(u, *c)) {
1118 r = list_dependencies_print("...", level + 1, (branches << 1) | (c[1] == NULL ? 0 : 1), 1);
1125 r = list_dependencies_print(*c, level, branches, c[1] == NULL);
1129 if (arg_all || unit_name_to_type(*c) == UNIT_TARGET) {
1130 r = list_dependencies_one(bus, *c, level + 1, &u, (branches << 1) | (c[1] == NULL ? 0 : 1));
1143 static int list_dependencies(DBusConnection *bus, char **args) {
1144 _cleanup_free_ char *unit = NULL;
1145 _cleanup_strv_free_ char **units = NULL;
1151 unit = unit_name_mangle(args[1]);
1156 u = SPECIAL_DEFAULT_TARGET;
1158 pager_open_if_enabled();
1162 return list_dependencies_one(bus, u, 0, &units, 0);
1165 static int get_default(DBusConnection *bus, char **args) {
1167 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1169 _cleanup_dbus_error_free_ DBusError error;
1171 dbus_error_init(&error);
1173 if (!bus || avoid_bus()) {
1174 r = unit_file_get_default(arg_scope, arg_root, &path);
1177 log_error("Operation failed: %s", strerror(-r));
1183 r = bus_method_call_with_reply(
1185 "org.freedesktop.systemd1",
1186 "/org/freedesktop/systemd1",
1187 "org.freedesktop.systemd1.Manager",
1194 log_error("Operation failed: %s", strerror(-r));
1198 if (!dbus_message_get_args(reply, &error,
1199 DBUS_TYPE_STRING, &path,
1200 DBUS_TYPE_INVALID)) {
1201 log_error("Failed to parse reply: %s", bus_error_message(&error));
1202 dbus_error_free(&error);
1208 printf("%s\n", path);
1211 if ((!bus || avoid_bus()) && path)
1220 char *name, *type, *state;
1223 static void list_jobs_print(struct job_info* jobs, size_t n) {
1226 const char *on, *off;
1227 bool shorten = false;
1229 assert(n == 0 || jobs);
1232 on = ansi_highlight_green();
1233 off = ansi_highlight_off();
1235 printf("%sNo jobs running.%s\n", on, off);
1239 pager_open_if_enabled();
1242 /* JOB UNIT TYPE STATE */
1243 unsigned l0 = 3, l1 = 4, l2 = 4, l3 = 5;
1245 for (i = 0, j = jobs; i < n; i++, j++) {
1246 assert(j->name && j->type && j->state);
1247 l0 = MAX(l0, DECIMAL_STR_WIDTH(j->id));
1248 l1 = MAX(l1, strlen(j->name));
1249 l2 = MAX(l2, strlen(j->type));
1250 l3 = MAX(l3, strlen(j->state));
1253 if (!arg_full && l0 + 1 + l1 + l2 + 1 + l3 > columns()) {
1254 l1 = MAX(33u, columns() - l0 - l2 - l3 - 3);
1259 printf("%*s %-*s %-*s %-*s\n",
1265 for (i = 0, j = jobs; i < n; i++, j++) {
1266 _cleanup_free_ char *e = NULL;
1268 if (streq(j->state, "running")) {
1269 on = ansi_highlight();
1270 off = ansi_highlight_off();
1274 e = shorten ? ellipsize(j->name, l1, 33) : NULL;
1275 printf("%*u %s%-*s%s %-*s %s%-*s%s\n",
1277 on, l1, e ? e : j->name, off,
1279 on, l3, j->state, off);
1283 on = ansi_highlight();
1284 off = ansi_highlight_off();
1287 printf("\n%s%zu jobs listed%s.\n", on, n, off);
1290 static int list_jobs(DBusConnection *bus, char **args) {
1291 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1292 DBusMessageIter iter, sub, sub2;
1294 struct job_info *jobs = NULL;
1295 size_t size = 0, used = 0;
1297 r = bus_method_call_with_reply(
1299 "org.freedesktop.systemd1",
1300 "/org/freedesktop/systemd1",
1301 "org.freedesktop.systemd1.Manager",
1309 if (!dbus_message_iter_init(reply, &iter) ||
1310 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
1311 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
1312 log_error("Failed to parse reply.");
1316 dbus_message_iter_recurse(&iter, &sub);
1318 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1319 const char *name, *type, *state, *job_path, *unit_path;
1322 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
1323 log_error("Failed to parse reply.");
1327 dbus_message_iter_recurse(&sub, &sub2);
1329 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &id, true) < 0 ||
1330 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
1331 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
1332 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, true) < 0 ||
1333 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &job_path, true) < 0 ||
1334 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, false) < 0) {
1335 log_error("Failed to parse reply.");
1340 if (!GREEDY_REALLOC(jobs, size, used + 1)) {
1345 jobs[used++] = (struct job_info) { id,
1349 if (!jobs[used-1].name || !jobs[used-1].type || !jobs[used-1].state) {
1354 dbus_message_iter_next(&sub);
1357 list_jobs_print(jobs, used);
1361 free(jobs[used].name);
1362 free(jobs[used].type);
1363 free(jobs[used].state);
1370 static int cancel_job(DBusConnection *bus, char **args) {
1375 if (strv_length(args) <= 1)
1376 return daemon_reload(bus, args);
1378 STRV_FOREACH(name, args+1) {
1382 r = safe_atou32(*name, &id);
1384 log_error("Failed to parse job id: %s", strerror(-r));
1388 r = bus_method_call_with_reply(
1390 "org.freedesktop.systemd1",
1391 "/org/freedesktop/systemd1",
1392 "org.freedesktop.systemd1.Manager",
1396 DBUS_TYPE_UINT32, &id,
1405 static int need_daemon_reload(DBusConnection *bus, const char *unit) {
1406 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1407 _cleanup_dbus_error_free_ DBusError error;
1408 dbus_bool_t b = FALSE;
1409 DBusMessageIter iter, sub;
1411 *interface = "org.freedesktop.systemd1.Unit",
1412 *property = "NeedDaemonReload",
1414 _cleanup_free_ char *n = NULL;
1417 dbus_error_init(&error);
1419 /* We ignore all errors here, since this is used to show a warning only */
1421 n = unit_name_mangle(unit);
1425 r = bus_method_call_with_reply(
1427 "org.freedesktop.systemd1",
1428 "/org/freedesktop/systemd1",
1429 "org.freedesktop.systemd1.Manager",
1433 DBUS_TYPE_STRING, &n,
1438 if (!dbus_message_get_args(reply, NULL,
1439 DBUS_TYPE_OBJECT_PATH, &path,
1443 dbus_message_unref(reply);
1446 r = bus_method_call_with_reply(
1448 "org.freedesktop.systemd1",
1450 "org.freedesktop.DBus.Properties",
1454 DBUS_TYPE_STRING, &interface,
1455 DBUS_TYPE_STRING, &property,
1460 if (!dbus_message_iter_init(reply, &iter) ||
1461 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
1464 dbus_message_iter_recurse(&iter, &sub);
1465 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_BOOLEAN)
1468 dbus_message_iter_get_basic(&sub, &b);
1472 typedef struct WaitData {
1479 static DBusHandlerResult wait_filter(DBusConnection *connection, DBusMessage *message, void *data) {
1480 _cleanup_dbus_error_free_ DBusError error;
1483 dbus_error_init(&error);
1489 log_debug("Got D-Bus request: %s.%s() on %s",
1490 dbus_message_get_interface(message),
1491 dbus_message_get_member(message),
1492 dbus_message_get_path(message));
1494 if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
1495 log_error("Warning! D-Bus connection terminated.");
1496 dbus_connection_close(connection);
1498 } else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
1500 const char *path, *result, *unit;
1503 if (dbus_message_get_args(message, &error,
1504 DBUS_TYPE_UINT32, &id,
1505 DBUS_TYPE_OBJECT_PATH, &path,
1506 DBUS_TYPE_STRING, &unit,
1507 DBUS_TYPE_STRING, &result,
1508 DBUS_TYPE_INVALID)) {
1510 r = set_remove(d->set, (char*) path);
1512 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1516 if (!isempty(result))
1517 d->result = strdup(result);
1520 d->name = strdup(unit);
1522 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1525 dbus_error_free(&error);
1526 if (dbus_message_get_args(message, &error,
1527 DBUS_TYPE_UINT32, &id,
1528 DBUS_TYPE_OBJECT_PATH, &path,
1529 DBUS_TYPE_STRING, &result,
1530 DBUS_TYPE_INVALID)) {
1531 /* Compatibility with older systemd versions <
1532 * 183 during upgrades. This should be dropped
1534 r = set_remove(d->set, (char*) path);
1536 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1541 d->result = strdup(result);
1543 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1547 log_error("Failed to parse message: %s", bus_error_message(&error));
1550 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1553 static int enable_wait_for_jobs(DBusConnection *bus) {
1561 dbus_error_init(&error);
1562 dbus_bus_add_match(bus,
1564 "sender='org.freedesktop.systemd1',"
1565 "interface='org.freedesktop.systemd1.Manager',"
1566 "member='JobRemoved',"
1567 "path='/org/freedesktop/systemd1'",
1570 if (dbus_error_is_set(&error)) {
1571 log_error("Failed to add match: %s", bus_error_message(&error));
1572 dbus_error_free(&error);
1576 /* This is slightly dirty, since we don't undo the match registrations. */
1580 static int wait_for_jobs(DBusConnection *bus, Set *s) {
1582 WaitData d = { .set = s };
1587 if (!dbus_connection_add_filter(bus, wait_filter, &d, NULL))
1590 while (!set_isempty(s)) {
1592 if (!dbus_connection_read_write_dispatch(bus, -1)) {
1593 log_error("Disconnected from bus.");
1594 return -ECONNREFUSED;
1601 if (streq(d.result, "timeout"))
1602 log_error("Job for %s timed out.", strna(d.name));
1603 else if (streq(d.result, "canceled"))
1604 log_error("Job for %s canceled.", strna(d.name));
1605 else if (streq(d.result, "dependency"))
1606 log_error("A dependency job for %s failed. See 'journalctl -xn' for details.", strna(d.name));
1607 else if (!streq(d.result, "done") && !streq(d.result, "skipped"))
1608 log_error("Job for %s failed. See 'systemctl status %s' and 'journalctl -xn' for details.", strna(d.name), strna(d.name));
1611 if (streq_ptr(d.result, "timeout"))
1613 else if (streq_ptr(d.result, "canceled"))
1615 else if (!streq_ptr(d.result, "done") && !streq_ptr(d.result, "skipped"))
1626 dbus_connection_remove_filter(bus, wait_filter, &d);
1630 static int check_one_unit(DBusConnection *bus, const char *name, char **check_states, bool quiet) {
1631 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1632 _cleanup_free_ char *n = NULL;
1633 DBusMessageIter iter, sub;
1635 *interface = "org.freedesktop.systemd1.Unit",
1636 *property = "ActiveState";
1637 const char *state, *path;
1643 dbus_error_init(&error);
1645 n = unit_name_mangle(name);
1649 r = bus_method_call_with_reply (
1651 "org.freedesktop.systemd1",
1652 "/org/freedesktop/systemd1",
1653 "org.freedesktop.systemd1.Manager",
1657 DBUS_TYPE_STRING, &n,
1660 dbus_error_free(&error);
1667 if (!dbus_message_get_args(reply, NULL,
1668 DBUS_TYPE_OBJECT_PATH, &path,
1669 DBUS_TYPE_INVALID)) {
1670 log_error("Failed to parse reply.");
1674 dbus_message_unref(reply);
1677 r = bus_method_call_with_reply(
1679 "org.freedesktop.systemd1",
1681 "org.freedesktop.DBus.Properties",
1685 DBUS_TYPE_STRING, &interface,
1686 DBUS_TYPE_STRING, &property,
1694 if (!dbus_message_iter_init(reply, &iter) ||
1695 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1696 log_error("Failed to parse reply.");
1700 dbus_message_iter_recurse(&iter, &sub);
1702 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1703 log_error("Failed to parse reply.");
1707 dbus_message_iter_get_basic(&sub, &state);
1712 return strv_find(check_states, state) ? 1 : 0;
1715 static void check_triggering_units(
1716 DBusConnection *bus,
1717 const char *unit_name) {
1719 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1720 DBusMessageIter iter, sub;
1721 const char *interface = "org.freedesktop.systemd1.Unit",
1722 *load_state_property = "LoadState",
1723 *triggered_by_property = "TriggeredBy",
1725 _cleanup_free_ char *unit_path = NULL, *n = NULL;
1726 bool print_warning_label = true;
1729 n = unit_name_mangle(unit_name);
1735 unit_path = unit_dbus_path_from_name(n);
1741 r = bus_method_call_with_reply(
1743 "org.freedesktop.systemd1",
1745 "org.freedesktop.DBus.Properties",
1749 DBUS_TYPE_STRING, &interface,
1750 DBUS_TYPE_STRING, &load_state_property,
1755 if (!dbus_message_iter_init(reply, &iter) ||
1756 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1757 log_error("Failed to parse reply.");
1761 dbus_message_iter_recurse(&iter, &sub);
1763 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1764 log_error("Failed to parse reply.");
1768 dbus_message_iter_get_basic(&sub, &state);
1770 if (streq(state, "masked"))
1773 dbus_message_unref(reply);
1776 r = bus_method_call_with_reply(
1778 "org.freedesktop.systemd1",
1780 "org.freedesktop.DBus.Properties",
1784 DBUS_TYPE_STRING, &interface,
1785 DBUS_TYPE_STRING, &triggered_by_property,
1790 if (!dbus_message_iter_init(reply, &iter) ||
1791 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1792 log_error("Failed to parse reply.");
1796 dbus_message_iter_recurse(&iter, &sub);
1797 dbus_message_iter_recurse(&sub, &iter);
1800 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1801 const char * const check_states[] = {
1806 const char *service_trigger;
1808 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1809 log_error("Failed to parse reply.");
1813 dbus_message_iter_get_basic(&sub, &service_trigger);
1815 r = check_one_unit(bus, service_trigger, (char**) check_states, true);
1819 if (print_warning_label) {
1820 log_warning("Warning: Stopping %s, but it can still be activated by:", unit_name);
1821 print_warning_label = false;
1824 log_warning(" %s", service_trigger);
1827 dbus_message_iter_next(&sub);
1831 static int start_unit_one(
1832 DBusConnection *bus,
1839 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1840 _cleanup_free_ char *n;
1849 n = unit_name_mangle(name);
1853 r = bus_method_call_with_reply(
1855 "org.freedesktop.systemd1",
1856 "/org/freedesktop/systemd1",
1857 "org.freedesktop.systemd1.Manager",
1861 DBUS_TYPE_STRING, &n,
1862 DBUS_TYPE_STRING, &mode,
1865 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
1866 /* There's always a fallback possible for
1867 * legacy actions. */
1870 log_error("Failed to issue method call: %s", bus_error_message(error));
1875 if (!dbus_message_get_args(reply, error,
1876 DBUS_TYPE_OBJECT_PATH, &path,
1877 DBUS_TYPE_INVALID)) {
1878 log_error("Failed to parse reply: %s", bus_error_message(error));
1882 if (need_daemon_reload(bus, n) > 0)
1883 log_warning("Warning: Unit file of %s changed on disk, 'systemctl %sdaemon-reload' recommended.",
1884 n, arg_scope == UNIT_FILE_SYSTEM ? "" : "--user ");
1893 r = set_consume(s, p);
1895 log_error("Failed to add path to set.");
1903 static const struct {
1907 } action_table[_ACTION_MAX] = {
1908 [ACTION_HALT] = { SPECIAL_HALT_TARGET, "halt", "replace-irreversibly" },
1909 [ACTION_POWEROFF] = { SPECIAL_POWEROFF_TARGET, "poweroff", "replace-irreversibly" },
1910 [ACTION_REBOOT] = { SPECIAL_REBOOT_TARGET, "reboot", "replace-irreversibly" },
1911 [ACTION_KEXEC] = { SPECIAL_KEXEC_TARGET, "kexec", "replace-irreversibly" },
1912 [ACTION_RUNLEVEL2] = { SPECIAL_RUNLEVEL2_TARGET, NULL, "isolate" },
1913 [ACTION_RUNLEVEL3] = { SPECIAL_RUNLEVEL3_TARGET, NULL, "isolate" },
1914 [ACTION_RUNLEVEL4] = { SPECIAL_RUNLEVEL4_TARGET, NULL, "isolate" },
1915 [ACTION_RUNLEVEL5] = { SPECIAL_RUNLEVEL5_TARGET, NULL, "isolate" },
1916 [ACTION_RESCUE] = { SPECIAL_RESCUE_TARGET, "rescue", "isolate" },
1917 [ACTION_EMERGENCY] = { SPECIAL_EMERGENCY_TARGET, "emergency", "isolate" },
1918 [ACTION_DEFAULT] = { SPECIAL_DEFAULT_TARGET, "default", "isolate" },
1919 [ACTION_EXIT] = { SPECIAL_EXIT_TARGET, "exit", "replace-irreversibly" },
1920 [ACTION_SUSPEND] = { SPECIAL_SUSPEND_TARGET, "suspend", "replace-irreversibly" },
1921 [ACTION_HIBERNATE] = { SPECIAL_HIBERNATE_TARGET, "hibernate", "replace-irreversibly" },
1922 [ACTION_HYBRID_SLEEP] = { SPECIAL_HYBRID_SLEEP_TARGET, "hybrid-sleep", "replace-irreversibly" },
1925 static enum action verb_to_action(const char *verb) {
1928 for (i = ACTION_INVALID; i < _ACTION_MAX; i++)
1929 if (action_table[i].verb && streq(verb, action_table[i].verb))
1931 return ACTION_INVALID;
1934 static int start_unit(DBusConnection *bus, char **args) {
1937 const char *method, *mode, *one_name;
1938 _cleanup_set_free_free_ Set *s = NULL;
1939 _cleanup_dbus_error_free_ DBusError error;
1942 dbus_error_init(&error);
1946 ask_password_agent_open_if_enabled();
1948 if (arg_action == ACTION_SYSTEMCTL) {
1951 streq(args[0], "stop") ||
1952 streq(args[0], "condstop") ? "StopUnit" :
1953 streq(args[0], "reload") ? "ReloadUnit" :
1954 streq(args[0], "restart") ? "RestartUnit" :
1956 streq(args[0], "try-restart") ||
1957 streq(args[0], "condrestart") ? "TryRestartUnit" :
1959 streq(args[0], "reload-or-restart") ? "ReloadOrRestartUnit" :
1961 streq(args[0], "reload-or-try-restart") ||
1962 streq(args[0], "condreload") ||
1964 streq(args[0], "force-reload") ? "ReloadOrTryRestartUnit" :
1966 action = verb_to_action(args[0]);
1968 mode = streq(args[0], "isolate") ? "isolate" :
1969 action_table[action].mode ?: arg_job_mode;
1971 one_name = action_table[action].target;
1974 assert(arg_action < ELEMENTSOF(action_table));
1975 assert(action_table[arg_action].target);
1977 method = "StartUnit";
1979 mode = action_table[arg_action].mode;
1980 one_name = action_table[arg_action].target;
1983 if (!arg_no_block) {
1984 ret = enable_wait_for_jobs(bus);
1986 log_error("Could not watch jobs: %s", strerror(-ret));
1990 s = set_new(string_hash_func, string_compare_func);
1996 ret = start_unit_one(bus, method, one_name, mode, &error, s);
1998 ret = translate_bus_error_to_exit_status(ret, &error);
2000 STRV_FOREACH(name, args+1) {
2001 r = start_unit_one(bus, method, *name, mode, &error, s);
2003 ret = translate_bus_error_to_exit_status(r, &error);
2004 dbus_error_free(&error);
2009 if (!arg_no_block) {
2010 r = wait_for_jobs(bus, s);
2014 /* When stopping units, warn if they can still be triggered by
2015 * another active unit (socket, path, timer) */
2016 if (!arg_quiet && streq(method, "StopUnit")) {
2018 check_triggering_units(bus, one_name);
2020 STRV_FOREACH(name, args+1)
2021 check_triggering_units(bus, *name);
2028 /* Ask systemd-logind, which might grant access to unprivileged users
2029 * through PolicyKit */
2030 static int reboot_with_logind(DBusConnection *bus, enum action a) {
2033 dbus_bool_t interactive = true;
2038 polkit_agent_open_if_enabled();
2046 case ACTION_POWEROFF:
2047 method = "PowerOff";
2050 case ACTION_SUSPEND:
2054 case ACTION_HIBERNATE:
2055 method = "Hibernate";
2058 case ACTION_HYBRID_SLEEP:
2059 method = "HybridSleep";
2066 return bus_method_call_with_reply(
2068 "org.freedesktop.login1",
2069 "/org/freedesktop/login1",
2070 "org.freedesktop.login1.Manager",
2074 DBUS_TYPE_BOOLEAN, &interactive,
2081 static int check_inhibitors(DBusConnection *bus, enum action a) {
2083 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
2084 DBusMessageIter iter, sub, sub2;
2087 _cleanup_strv_free_ char **sessions = NULL;
2093 if (arg_ignore_inhibitors || arg_force > 0)
2105 r = bus_method_call_with_reply(
2107 "org.freedesktop.login1",
2108 "/org/freedesktop/login1",
2109 "org.freedesktop.login1.Manager",
2115 /* If logind is not around, then there are no inhibitors... */
2118 if (!dbus_message_iter_init(reply, &iter) ||
2119 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
2120 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
2121 log_error("Failed to parse reply.");
2125 dbus_message_iter_recurse(&iter, &sub);
2126 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
2127 const char *what, *who, *why, *mode;
2129 _cleanup_strv_free_ char **sv = NULL;
2130 _cleanup_free_ char *comm = NULL, *user = NULL;
2132 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
2133 log_error("Failed to parse reply.");
2137 dbus_message_iter_recurse(&sub, &sub2);
2139 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &what, true) < 0 ||
2140 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &who, true) < 0 ||
2141 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &why, true) < 0 ||
2142 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &mode, true) < 0 ||
2143 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &uid, true) < 0 ||
2144 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, false) < 0) {
2145 log_error("Failed to parse reply.");
2149 if (!streq(mode, "block"))
2152 sv = strv_split(what, ":");
2156 if (!strv_contains(sv,
2158 a == ACTION_POWEROFF ||
2159 a == ACTION_REBOOT ||
2160 a == ACTION_KEXEC ? "shutdown" : "sleep"))
2163 get_process_comm(pid, &comm);
2164 user = uid_to_name(uid);
2165 log_warning("Operation inhibited by \"%s\" (PID %lu \"%s\", user %s), reason is \"%s\".",
2166 who, (unsigned long) pid, strna(comm), strna(user), why);
2170 dbus_message_iter_next(&sub);
2173 dbus_message_iter_recurse(&iter, &sub);
2175 /* Check for current sessions */
2176 sd_get_sessions(&sessions);
2177 STRV_FOREACH(s, sessions) {
2179 _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL;
2181 if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid())
2184 if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
2187 if (sd_session_get_type(*s, &type) < 0 || (!streq(type, "x11") && !streq(type, "tty")))
2190 sd_session_get_tty(*s, &tty);
2191 sd_session_get_seat(*s, &seat);
2192 sd_session_get_service(*s, &service);
2193 user = uid_to_name(uid);
2195 log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty);
2202 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
2203 action_table[a].verb);
2211 static int start_special(DBusConnection *bus, char **args) {
2217 a = verb_to_action(args[0]);
2219 r = check_inhibitors(bus, a);
2223 if (arg_force >= 2 && geteuid() != 0) {
2224 log_error("Must be root.");
2228 if (arg_force >= 2 &&
2229 (a == ACTION_HALT ||
2230 a == ACTION_POWEROFF ||
2231 a == ACTION_REBOOT))
2234 if (arg_force >= 1 &&
2235 (a == ACTION_HALT ||
2236 a == ACTION_POWEROFF ||
2237 a == ACTION_REBOOT ||
2238 a == ACTION_KEXEC ||
2240 return daemon_reload(bus, args);
2242 /* first try logind, to allow authentication with polkit */
2243 if (geteuid() != 0 &&
2244 (a == ACTION_POWEROFF ||
2245 a == ACTION_REBOOT ||
2246 a == ACTION_SUSPEND ||
2247 a == ACTION_HIBERNATE ||
2248 a == ACTION_HYBRID_SLEEP)) {
2249 r = reboot_with_logind(bus, a);
2254 r = start_unit(bus, args);
2255 if (r == EXIT_SUCCESS)
2261 static int check_unit_active(DBusConnection *bus, char **args) {
2262 const char * const check_states[] = {
2269 int r = 3; /* According to LSB: "program is not running" */
2274 STRV_FOREACH(name, args+1) {
2277 state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
2287 static int check_unit_failed(DBusConnection *bus, char **args) {
2288 const char * const check_states[] = {
2299 STRV_FOREACH(name, args+1) {
2302 state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
2312 static int kill_unit(DBusConnection *bus, char **args) {
2320 arg_kill_who = "all";
2322 STRV_FOREACH(name, args+1) {
2323 _cleanup_free_ char *n = NULL;
2325 n = unit_name_mangle(*name);
2329 r = bus_method_call_with_reply(
2331 "org.freedesktop.systemd1",
2332 "/org/freedesktop/systemd1",
2333 "org.freedesktop.systemd1.Manager",
2337 DBUS_TYPE_STRING, &n,
2338 DBUS_TYPE_STRING, &arg_kill_who,
2339 DBUS_TYPE_INT32, &arg_signal,
2347 typedef struct ExecStatusInfo {
2355 usec_t start_timestamp;
2356 usec_t exit_timestamp;
2361 LIST_FIELDS(struct ExecStatusInfo, exec);
2364 static void exec_status_info_free(ExecStatusInfo *i) {
2373 static int exec_status_info_deserialize(DBusMessageIter *sub, ExecStatusInfo *i) {
2374 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
2375 DBusMessageIter sub2, sub3;
2379 int32_t code, status;
2385 if (dbus_message_iter_get_arg_type(sub) != DBUS_TYPE_STRUCT)
2388 dbus_message_iter_recurse(sub, &sub2);
2390 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0)
2393 i->path = strdup(path);
2397 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_ARRAY ||
2398 dbus_message_iter_get_element_type(&sub2) != DBUS_TYPE_STRING)
2402 dbus_message_iter_recurse(&sub2, &sub3);
2403 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2404 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2405 dbus_message_iter_next(&sub3);
2409 i->argv = new0(char*, n+1);
2414 dbus_message_iter_recurse(&sub2, &sub3);
2415 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2418 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2419 dbus_message_iter_get_basic(&sub3, &s);
2420 dbus_message_iter_next(&sub3);
2422 i->argv[n] = strdup(s);
2429 if (!dbus_message_iter_next(&sub2) ||
2430 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, true) < 0 ||
2431 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp, true) < 0 ||
2432 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp_monotonic, true) < 0 ||
2433 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp, true) < 0 ||
2434 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp_monotonic, true) < 0 ||
2435 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, true) < 0 ||
2436 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &code, true) < 0 ||
2437 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &status, false) < 0)
2441 i->start_timestamp = (usec_t) start_timestamp;
2442 i->exit_timestamp = (usec_t) exit_timestamp;
2443 i->pid = (pid_t) pid;
2450 typedef struct UnitStatusInfo {
2452 const char *load_state;
2453 const char *active_state;
2454 const char *sub_state;
2455 const char *unit_file_state;
2457 const char *description;
2458 const char *following;
2460 char **documentation;
2462 const char *fragment_path;
2463 const char *source_path;
2464 const char *control_group;
2466 char **dropin_paths;
2468 const char *load_error;
2471 usec_t inactive_exit_timestamp;
2472 usec_t inactive_exit_timestamp_monotonic;
2473 usec_t active_enter_timestamp;
2474 usec_t active_exit_timestamp;
2475 usec_t inactive_enter_timestamp;
2477 bool need_daemon_reload;
2482 const char *status_text;
2483 const char *pid_file;
2486 usec_t start_timestamp;
2487 usec_t exit_timestamp;
2489 int exit_code, exit_status;
2491 usec_t condition_timestamp;
2492 bool condition_result;
2493 bool failed_condition_trigger;
2494 bool failed_condition_negate;
2495 const char *failed_condition;
2496 const char *failed_condition_param;
2499 unsigned n_accepted;
2500 unsigned n_connections;
2503 /* Pairs of type, path */
2507 const char *sysfs_path;
2509 /* Mount, Automount */
2515 LIST_HEAD(ExecStatusInfo, exec);
2518 static void print_status_info(UnitStatusInfo *i,
2521 const char *on, *off, *ss;
2523 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
2524 char since2[FORMAT_TIMESTAMP_MAX], *s2;
2527 arg_all * OUTPUT_SHOW_ALL |
2528 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
2529 on_tty() * OUTPUT_COLOR |
2530 !arg_quiet * OUTPUT_WARN_CUTOFF |
2531 arg_full * OUTPUT_FULL_WIDTH;
2536 /* This shows pretty information about a unit. See
2537 * print_property() for a low-level property printer */
2539 printf("%s", strna(i->id));
2541 if (i->description && !streq_ptr(i->id, i->description))
2542 printf(" - %s", i->description);
2547 printf(" Follow: unit currently follows state of %s\n", i->following);
2549 if (streq_ptr(i->load_state, "error")) {
2550 on = ansi_highlight_red();
2551 off = ansi_highlight_off();
2555 path = i->source_path ? i->source_path : i->fragment_path;
2558 printf(" Loaded: %s%s%s (Reason: %s)\n",
2559 on, strna(i->load_state), off, i->load_error);
2560 else if (path && i->unit_file_state)
2561 printf(" Loaded: %s%s%s (%s; %s)\n",
2562 on, strna(i->load_state), off, path, i->unit_file_state);
2564 printf(" Loaded: %s%s%s (%s)\n",
2565 on, strna(i->load_state), off, path);
2567 printf(" Loaded: %s%s%s\n",
2568 on, strna(i->load_state), off);
2570 if (!strv_isempty(i->dropin_paths)) {
2575 STRV_FOREACH(dropin, i->dropin_paths) {
2576 if (! dir || last) {
2577 printf(dir ? " " : " Drop-In: ");
2581 if (path_get_parent(*dropin, &dir) < 0) {
2586 printf("%s\n %s", dir,
2587 draw_special_char(DRAW_TREE_RIGHT));
2590 last = ! (*(dropin + 1) && startswith(*(dropin + 1), dir));
2592 printf("%s%s", path_get_file_name(*dropin), last ? "\n" : ", ");
2598 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
2600 if (streq_ptr(i->active_state, "failed")) {
2601 on = ansi_highlight_red();
2602 off = ansi_highlight_off();
2603 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
2604 on = ansi_highlight_green();
2605 off = ansi_highlight_off();
2610 printf(" Active: %s%s (%s)%s",
2611 on, strna(i->active_state), ss, off);
2613 printf(" Active: %s%s%s",
2614 on, strna(i->active_state), off);
2616 if (!isempty(i->result) && !streq(i->result, "success"))
2617 printf(" (Result: %s)", i->result);
2619 timestamp = (streq_ptr(i->active_state, "active") ||
2620 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
2621 (streq_ptr(i->active_state, "inactive") ||
2622 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
2623 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
2624 i->active_exit_timestamp;
2626 s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
2627 s2 = format_timestamp(since2, sizeof(since2), timestamp);
2630 printf(" since %s; %s\n", s2, s1);
2632 printf(" since %s\n", s2);
2636 if (!i->condition_result && i->condition_timestamp > 0) {
2637 s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
2638 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
2640 printf(" start condition failed at %s%s%s\n",
2641 s2, s1 ? "; " : "", s1 ? s1 : "");
2642 if (i->failed_condition_trigger)
2643 printf(" none of the trigger conditions were met\n");
2644 else if (i->failed_condition)
2645 printf(" %s=%s%s was not met\n",
2646 i->failed_condition,
2647 i->failed_condition_negate ? "!" : "",
2648 i->failed_condition_param);
2652 printf(" Device: %s\n", i->sysfs_path);
2654 printf(" Where: %s\n", i->where);
2656 printf(" What: %s\n", i->what);
2658 STRV_FOREACH(t, i->documentation)
2659 printf(" %*s %s\n", 9, t == i->documentation ? "Docs:" : "", *t);
2661 STRV_FOREACH_PAIR(t, t2, i->listen)
2662 printf(" %*s %s (%s)\n", 9, t == i->listen ? "Listen:" : "", *t2, *t);
2665 printf(" Accepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
2667 LIST_FOREACH(exec, p, i->exec) {
2668 _cleanup_free_ char *argv = NULL;
2671 /* Only show exited processes here */
2675 argv = strv_join(p->argv, " ");
2676 printf(" Process: %u %s=%s ", p->pid, p->name, strna(argv));
2678 good = is_clean_exit_lsb(p->code, p->status, NULL);
2680 on = ansi_highlight_red();
2681 off = ansi_highlight_off();
2685 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
2687 if (p->code == CLD_EXITED) {
2690 printf("status=%i", p->status);
2692 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
2697 printf("signal=%s", signal_to_string(p->status));
2699 printf(")%s\n", off);
2701 if (i->main_pid == p->pid &&
2702 i->start_timestamp == p->start_timestamp &&
2703 i->exit_timestamp == p->start_timestamp)
2704 /* Let's not show this twice */
2707 if (p->pid == i->control_pid)
2711 if (i->main_pid > 0 || i->control_pid > 0) {
2712 if (i->main_pid > 0) {
2713 printf(" Main PID: %u", (unsigned) i->main_pid);
2716 _cleanup_free_ char *comm = NULL;
2717 get_process_comm(i->main_pid, &comm);
2719 printf(" (%s)", comm);
2720 } else if (i->exit_code > 0) {
2721 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
2723 if (i->exit_code == CLD_EXITED) {
2726 printf("status=%i", i->exit_status);
2728 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
2733 printf("signal=%s", signal_to_string(i->exit_status));
2737 if (i->control_pid > 0)
2741 if (i->control_pid > 0) {
2742 _cleanup_free_ char *c = NULL;
2744 printf(" %8s: %u", i->main_pid ? "" : " Control", (unsigned) i->control_pid);
2746 get_process_comm(i->control_pid, &c);
2755 printf(" Status: \"%s\"\n", i->status_text);
2757 if (i->control_group &&
2758 (i->main_pid > 0 || i->control_pid > 0 || cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, i->control_group, false) == 0)) {
2761 printf(" CGroup: %s\n", i->control_group);
2763 if (arg_transport != TRANSPORT_SSH) {
2766 char prefix[] = " ";
2769 if (c > sizeof(prefix) - 1)
2770 c -= sizeof(prefix) - 1;
2774 if (i->main_pid > 0)
2775 extra[k++] = i->main_pid;
2777 if (i->control_pid > 0)
2778 extra[k++] = i->control_pid;
2780 show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, i->control_group, prefix,
2781 c, false, extra, k, flags);
2785 if (i->id && arg_transport != TRANSPORT_SSH) {
2787 show_journal_by_unit(stdout,
2791 i->inactive_exit_timestamp_monotonic,
2795 arg_scope == UNIT_FILE_SYSTEM,
2799 if (i->need_daemon_reload)
2800 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %sdaemon-reload' recommended.\n",
2801 ansi_highlight_red(),
2802 ansi_highlight_off(),
2803 arg_scope == UNIT_FILE_SYSTEM ? "" : "--user ");
2806 static void show_unit_help(UnitStatusInfo *i) {
2811 if (!i->documentation) {
2812 log_info("Documentation for %s not known.", i->id);
2816 STRV_FOREACH(p, i->documentation) {
2818 if (startswith(*p, "man:")) {
2821 _cleanup_free_ char *page = NULL, *section = NULL;
2822 const char *args[4] = { "man", NULL, NULL, NULL };
2827 if ((*p)[k-1] == ')')
2828 e = strrchr(*p, '(');
2831 page = strndup((*p) + 4, e - *p - 4);
2832 section = strndup(e + 1, *p + k - e - 2);
2833 if (!page || !section) {
2845 log_error("Failed to fork: %m");
2851 execvp(args[0], (char**) args);
2852 log_error("Failed to execute man: %m");
2853 _exit(EXIT_FAILURE);
2856 wait_for_terminate(pid, NULL);
2858 log_info("Can't show: %s", *p);
2862 static int status_property(const char *name, DBusMessageIter *iter, UnitStatusInfo *i) {
2868 switch (dbus_message_iter_get_arg_type(iter)) {
2870 case DBUS_TYPE_STRING: {
2873 dbus_message_iter_get_basic(iter, &s);
2876 if (streq(name, "Id"))
2878 else if (streq(name, "LoadState"))
2880 else if (streq(name, "ActiveState"))
2881 i->active_state = s;
2882 else if (streq(name, "SubState"))
2884 else if (streq(name, "Description"))
2886 else if (streq(name, "FragmentPath"))
2887 i->fragment_path = s;
2888 else if (streq(name, "SourcePath"))
2891 else if (streq(name, "DefaultControlGroup")) {
2893 e = startswith(s, SYSTEMD_CGROUP_CONTROLLER ":");
2895 i->control_group = e;
2898 else if (streq(name, "ControlGroup"))
2899 i->control_group = s;
2900 else if (streq(name, "StatusText"))
2902 else if (streq(name, "PIDFile"))
2904 else if (streq(name, "SysFSPath"))
2906 else if (streq(name, "Where"))
2908 else if (streq(name, "What"))
2910 else if (streq(name, "Following"))
2912 else if (streq(name, "UnitFileState"))
2913 i->unit_file_state = s;
2914 else if (streq(name, "Result"))
2921 case DBUS_TYPE_BOOLEAN: {
2924 dbus_message_iter_get_basic(iter, &b);
2926 if (streq(name, "Accept"))
2928 else if (streq(name, "NeedDaemonReload"))
2929 i->need_daemon_reload = b;
2930 else if (streq(name, "ConditionResult"))
2931 i->condition_result = b;
2936 case DBUS_TYPE_UINT32: {
2939 dbus_message_iter_get_basic(iter, &u);
2941 if (streq(name, "MainPID")) {
2943 i->main_pid = (pid_t) u;
2946 } else if (streq(name, "ControlPID"))
2947 i->control_pid = (pid_t) u;
2948 else if (streq(name, "ExecMainPID")) {
2950 i->main_pid = (pid_t) u;
2951 } else if (streq(name, "NAccepted"))
2953 else if (streq(name, "NConnections"))
2954 i->n_connections = u;
2959 case DBUS_TYPE_INT32: {
2962 dbus_message_iter_get_basic(iter, &j);
2964 if (streq(name, "ExecMainCode"))
2965 i->exit_code = (int) j;
2966 else if (streq(name, "ExecMainStatus"))
2967 i->exit_status = (int) j;
2972 case DBUS_TYPE_UINT64: {
2975 dbus_message_iter_get_basic(iter, &u);
2977 if (streq(name, "ExecMainStartTimestamp"))
2978 i->start_timestamp = (usec_t) u;
2979 else if (streq(name, "ExecMainExitTimestamp"))
2980 i->exit_timestamp = (usec_t) u;
2981 else if (streq(name, "ActiveEnterTimestamp"))
2982 i->active_enter_timestamp = (usec_t) u;
2983 else if (streq(name, "InactiveEnterTimestamp"))
2984 i->inactive_enter_timestamp = (usec_t) u;
2985 else if (streq(name, "InactiveExitTimestamp"))
2986 i->inactive_exit_timestamp = (usec_t) u;
2987 else if (streq(name, "InactiveExitTimestampMonotonic"))
2988 i->inactive_exit_timestamp_monotonic = (usec_t) u;
2989 else if (streq(name, "ActiveExitTimestamp"))
2990 i->active_exit_timestamp = (usec_t) u;
2991 else if (streq(name, "ConditionTimestamp"))
2992 i->condition_timestamp = (usec_t) u;
2997 case DBUS_TYPE_ARRAY: {
2999 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
3000 startswith(name, "Exec")) {
3001 DBusMessageIter sub;
3003 dbus_message_iter_recurse(iter, &sub);
3004 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3005 ExecStatusInfo *info;
3008 info = new0(ExecStatusInfo, 1);
3012 info->name = strdup(name);
3018 r = exec_status_info_deserialize(&sub, info);
3024 LIST_PREPEND(exec, i->exec, info);
3026 dbus_message_iter_next(&sub);
3029 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
3030 streq(name, "Listen")) {
3031 DBusMessageIter sub, sub2;
3033 dbus_message_iter_recurse(iter, &sub);
3034 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3035 const char *type, *path;
3037 dbus_message_iter_recurse(&sub, &sub2);
3039 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
3040 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0) {
3043 r = strv_extend(&i->listen, type);
3046 r = strv_extend(&i->listen, path);
3051 dbus_message_iter_next(&sub);
3056 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
3057 streq(name, "DropInPaths")) {
3058 int r = bus_parse_strv_iter(iter, &i->dropin_paths);
3062 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
3063 streq(name, "Documentation")) {
3065 DBusMessageIter sub;
3067 dbus_message_iter_recurse(iter, &sub);
3068 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING) {
3072 dbus_message_iter_get_basic(&sub, &s);
3074 r = strv_extend(&i->documentation, s);
3078 dbus_message_iter_next(&sub);
3081 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
3082 streq(name, "Conditions")) {
3083 DBusMessageIter sub, sub2;
3085 dbus_message_iter_recurse(iter, &sub);
3086 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3087 const char *cond, *param;
3088 dbus_bool_t trigger, negate;
3091 dbus_message_iter_recurse(&sub, &sub2);
3094 if(bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &cond, true) >= 0 &&
3095 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &trigger, true) >= 0 &&
3096 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &negate, true) >= 0 &&
3097 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, ¶m, true) >= 0 &&
3098 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &state, false) >= 0) {
3099 log_debug("%s %d %d %s %d", cond, trigger, negate, param, state);
3100 if (state < 0 && (!trigger || !i->failed_condition)) {
3101 i->failed_condition = cond;
3102 i->failed_condition_trigger = trigger;
3103 i->failed_condition_negate = negate;
3104 i->failed_condition_param = param;
3108 dbus_message_iter_next(&sub);
3115 case DBUS_TYPE_STRUCT: {
3117 if (streq(name, "LoadError")) {
3118 DBusMessageIter sub;
3119 const char *n, *message;
3122 dbus_message_iter_recurse(iter, &sub);
3124 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &n, true);
3128 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &message, false);
3132 if (!isempty(message))
3133 i->load_error = message;
3143 static int print_property(const char *name, DBusMessageIter *iter) {
3147 /* This is a low-level property printer, see
3148 * print_status_info() for the nicer output */
3150 if (arg_properties && !strv_find(arg_properties, name))
3153 switch (dbus_message_iter_get_arg_type(iter)) {
3155 case DBUS_TYPE_STRUCT: {
3156 DBusMessageIter sub;
3157 dbus_message_iter_recurse(iter, &sub);
3159 if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32 && streq(name, "Job")) {
3162 dbus_message_iter_get_basic(&sub, &u);
3165 printf("%s=%u\n", name, (unsigned) u);
3167 printf("%s=\n", name);
3170 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "Unit")) {
3173 dbus_message_iter_get_basic(&sub, &s);
3175 if (arg_all || s[0])
3176 printf("%s=%s\n", name, s);
3179 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "LoadError")) {
3180 const char *a = NULL, *b = NULL;
3182 if (bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &a, true) >= 0)
3183 bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &b, false);
3185 if (arg_all || !isempty(a) || !isempty(b))
3186 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
3194 case DBUS_TYPE_ARRAY:
3196 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "EnvironmentFiles")) {
3197 DBusMessageIter sub, sub2;
3199 dbus_message_iter_recurse(iter, &sub);
3200 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3204 dbus_message_iter_recurse(&sub, &sub2);
3206 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
3207 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) >= 0)
3208 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
3210 dbus_message_iter_next(&sub);
3215 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Paths")) {
3216 DBusMessageIter sub, sub2;
3218 dbus_message_iter_recurse(iter, &sub);
3220 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3221 const char *type, *path;
3223 dbus_message_iter_recurse(&sub, &sub2);
3225 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
3226 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
3227 printf("%s=%s\n", type, path);
3229 dbus_message_iter_next(&sub);
3234 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Listen")) {
3235 DBusMessageIter sub, sub2;
3237 dbus_message_iter_recurse(iter, &sub);
3238 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3239 const char *type, *path;
3241 dbus_message_iter_recurse(&sub, &sub2);
3243 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
3244 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
3245 printf("Listen%s=%s\n", type, path);
3247 dbus_message_iter_next(&sub);
3252 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Timers")) {
3253 DBusMessageIter sub, sub2;
3255 dbus_message_iter_recurse(iter, &sub);
3256 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3258 uint64_t value, next_elapse;
3260 dbus_message_iter_recurse(&sub, &sub2);
3262 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &base, true) >= 0 &&
3263 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &value, true) >= 0 &&
3264 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &next_elapse, false) >= 0) {
3265 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
3267 printf("%s={ value=%s ; next_elapse=%s }\n",
3269 format_timespan(timespan1, sizeof(timespan1), value, 0),
3270 format_timespan(timespan2, sizeof(timespan2), next_elapse, 0));
3273 dbus_message_iter_next(&sub);
3278 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && startswith(name, "Exec")) {
3279 DBusMessageIter sub;
3281 dbus_message_iter_recurse(iter, &sub);
3282 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3283 ExecStatusInfo info = {};
3285 if (exec_status_info_deserialize(&sub, &info) >= 0) {
3286 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
3287 _cleanup_free_ char *t;
3289 t = strv_join(info.argv, " ");
3291 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
3295 yes_no(info.ignore),
3296 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
3297 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
3298 (unsigned) info. pid,
3299 sigchld_code_to_string(info.code),
3301 info.code == CLD_EXITED ? "" : "/",
3302 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
3306 strv_free(info.argv);
3308 dbus_message_iter_next(&sub);
3313 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "DeviceAllow")) {
3314 DBusMessageIter sub, sub2;
3316 dbus_message_iter_recurse(iter, &sub);
3317 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3318 const char *path, *rwm;
3320 dbus_message_iter_recurse(&sub, &sub2);
3322 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
3323 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &rwm, false) >= 0)
3324 printf("%s=%s %s\n", name, strna(path), strna(rwm));
3326 dbus_message_iter_next(&sub);
3330 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "BlockIODeviceWeight")) {
3331 DBusMessageIter sub, sub2;
3333 dbus_message_iter_recurse(iter, &sub);
3334 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3338 dbus_message_iter_recurse(&sub, &sub2);
3340 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
3341 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &weight, false) >= 0)
3342 printf("%s=%s %" PRIu64 "\n", name, strna(path), weight);
3344 dbus_message_iter_next(&sub);
3348 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && (streq(name, "BlockIOReadBandwidth") || streq(name, "BlockIOWriteBandwidth"))) {
3349 DBusMessageIter sub, sub2;
3351 dbus_message_iter_recurse(iter, &sub);
3352 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3356 dbus_message_iter_recurse(&sub, &sub2);
3358 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
3359 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &bandwidth, false) >= 0)
3360 printf("%s=%s %" PRIu64 "\n", name, strna(path), bandwidth);
3362 dbus_message_iter_next(&sub);
3371 if (generic_print_property(name, iter, arg_all) > 0)
3375 printf("%s=[unprintable]\n", name);
3380 static int show_one(const char *verb,
3381 DBusConnection *bus,
3383 bool show_properties,
3386 _cleanup_free_ DBusMessage *reply = NULL;
3387 const char *interface = "";
3389 DBusMessageIter iter, sub, sub2, sub3;
3390 UnitStatusInfo info = {};
3396 r = bus_method_call_with_reply(
3398 "org.freedesktop.systemd1",
3400 "org.freedesktop.DBus.Properties",
3404 DBUS_TYPE_STRING, &interface,
3409 if (!dbus_message_iter_init(reply, &iter) ||
3410 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3411 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
3412 log_error("Failed to parse reply.");
3416 dbus_message_iter_recurse(&iter, &sub);
3423 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
3426 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_DICT_ENTRY);
3427 dbus_message_iter_recurse(&sub, &sub2);
3429 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
3430 dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
3431 log_error("Failed to parse reply.");
3435 dbus_message_iter_recurse(&sub2, &sub3);
3437 if (show_properties)
3438 r = print_property(name, &sub3);
3440 r = status_property(name, &sub3, &info);
3442 log_error("Failed to parse reply.");
3446 dbus_message_iter_next(&sub);
3451 if (!show_properties) {
3452 if (streq(verb, "help"))
3453 show_unit_help(&info);
3455 print_status_info(&info, ellipsized);
3458 strv_free(info.documentation);
3459 strv_free(info.dropin_paths);
3460 strv_free(info.listen);
3462 if (!streq_ptr(info.active_state, "active") &&
3463 !streq_ptr(info.active_state, "reloading") &&
3464 streq(verb, "status")) {
3465 /* According to LSB: "program not running" */
3466 /* 0: program is running or service is OK
3467 * 1: program is dead and /var/run pid file exists
3468 * 2: program is dead and /var/lock lock file exists
3469 * 3: program is not running
3470 * 4: program or service status is unknown
3472 if (info.pid_file && access(info.pid_file, F_OK) == 0)
3478 while ((p = info.exec)) {
3479 LIST_REMOVE(exec, info.exec, p);
3480 exec_status_info_free(p);
3486 static int show_one_by_pid(const char *verb,
3487 DBusConnection *bus,
3491 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3492 const char *path = NULL;
3493 _cleanup_dbus_error_free_ DBusError error;
3496 dbus_error_init(&error);
3498 r = bus_method_call_with_reply(
3500 "org.freedesktop.systemd1",
3501 "/org/freedesktop/systemd1",
3502 "org.freedesktop.systemd1.Manager",
3506 DBUS_TYPE_UINT32, &pid,
3511 if (!dbus_message_get_args(reply, &error,
3512 DBUS_TYPE_OBJECT_PATH, &path,
3513 DBUS_TYPE_INVALID)) {
3514 log_error("Failed to parse reply: %s", bus_error_message(&error));
3518 r = show_one(verb, bus, path, false, new_line, ellipsized);
3522 static int show_all(const char* verb,
3523 DBusConnection *bus,
3524 bool show_properties,
3527 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3528 _cleanup_free_ struct unit_info *unit_infos = NULL;
3530 const struct unit_info *u;
3533 r = get_unit_list(bus, &reply, &unit_infos, &c);
3537 qsort_safe(unit_infos, c, sizeof(struct unit_info), compare_unit_info);
3539 for (u = unit_infos; u < unit_infos + c; u++) {
3540 _cleanup_free_ char *p = NULL;
3542 if (!output_show_unit(u))
3545 p = unit_dbus_path_from_name(u->id);
3549 printf("%s -> '%s'\n", u->id, p);
3551 r = show_one(verb, bus, p, show_properties, new_line, ellipsized);
3559 static int show(DBusConnection *bus, char **args) {
3561 bool show_properties, show_status, new_line = false;
3563 bool ellipsized = false;
3568 show_properties = streq(args[0], "show");
3569 show_status = streq(args[0], "status");
3571 if (show_properties)
3572 pager_open_if_enabled();
3574 /* If no argument is specified inspect the manager itself */
3576 if (show_properties && strv_length(args) <= 1)
3577 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line, &ellipsized);
3579 if (show_status && strv_length(args) <= 1)
3580 ret = show_all(args[0], bus, false, &new_line, &ellipsized);
3582 STRV_FOREACH(name, args+1) {
3585 if (safe_atou32(*name, &id) < 0) {
3586 _cleanup_free_ char *p = NULL, *n = NULL;
3587 /* Interpret as unit name */
3589 n = unit_name_mangle(*name);
3593 p = unit_dbus_path_from_name(n);
3597 r = show_one(args[0], bus, p, show_properties, &new_line, &ellipsized);
3601 } else if (show_properties) {
3602 _cleanup_free_ char *p = NULL;
3604 /* Interpret as job id */
3605 if (asprintf(&p, "/org/freedesktop/systemd1/job/%u", id) < 0)
3608 r = show_one(args[0], bus, p, show_properties, &new_line, &ellipsized);
3613 /* Interpret as PID */
3614 r = show_one_by_pid(args[0], bus, id, &new_line, &ellipsized);
3620 if (ellipsized && !arg_quiet)
3621 printf("Hint: Some lines were ellipsized, use -l to show in full.\n");
3626 static int append_assignment(DBusMessageIter *iter, const char *assignment) {
3629 DBusMessageIter sub;
3635 eq = strchr(assignment, '=');
3637 log_error("Not an assignment: %s", assignment);
3641 field = strndupa(assignment, eq - assignment);
3644 if (!dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &field))
3647 if (streq(field, "CPUAccounting") ||
3648 streq(field, "MemoryAccounting") ||
3649 streq(field, "BlockIOAccounting")) {
3652 r = parse_boolean(eq);
3654 log_error("Failed to parse boolean assignment %s.", assignment);
3659 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "b", &sub) ||
3660 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_BOOLEAN, &b))
3663 } else if (streq(field, "MemoryLimit")) {
3667 r = parse_bytes(eq, &bytes);
3669 log_error("Failed to parse bytes specification %s", assignment);
3674 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "t", &sub) ||
3675 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_UINT64, &u))
3678 } else if (streq(field, "CPUShares") || streq(field, "BlockIOWeight")) {
3681 r = safe_atou64(eq, &u);
3683 log_error("Failed to parse %s value %s.", field, eq);
3687 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "t", &sub) ||
3688 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_UINT64, &u))
3691 } else if (streq(field, "DevicePolicy")) {
3693 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "s", &sub) ||
3694 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &eq))
3697 } else if (streq(field, "DeviceAllow")) {
3698 DBusMessageIter sub2;
3700 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "a(ss)", &sub) ||
3701 !dbus_message_iter_open_container(&sub, DBUS_TYPE_ARRAY, "(ss)", &sub2))
3705 const char *path, *rwm;
3706 DBusMessageIter sub3;
3709 e = strchr(eq, ' ');
3711 path = strndupa(eq, e - eq);
3718 if (!path_startswith(path, "/dev")) {
3719 log_error("%s is not a device file in /dev.", path);
3723 if (!dbus_message_iter_open_container(&sub2, DBUS_TYPE_STRUCT, NULL, &sub3) ||
3724 !dbus_message_iter_append_basic(&sub3, DBUS_TYPE_STRING, &path) ||
3725 !dbus_message_iter_append_basic(&sub3, DBUS_TYPE_STRING, &rwm) ||
3726 !dbus_message_iter_close_container(&sub2, &sub3))
3730 if (!dbus_message_iter_close_container(&sub, &sub2))
3733 } else if (streq(field, "BlockIOReadBandwidth") || streq(field, "BlockIOWriteBandwidth")) {
3734 DBusMessageIter sub2;
3736 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "a(st)", &sub) ||
3737 !dbus_message_iter_open_container(&sub, DBUS_TYPE_ARRAY, "(st)", &sub2))
3741 const char *path, *bandwidth;
3742 DBusMessageIter sub3;
3747 e = strchr(eq, ' ');
3749 path = strndupa(eq, e - eq);
3752 log_error("Failed to parse %s value %s.", field, eq);
3756 if (!path_startswith(path, "/dev")) {
3757 log_error("%s is not a device file in /dev.", path);
3761 r = parse_bytes(bandwidth, &bytes);
3763 log_error("Failed to parse byte value %s.", bandwidth);
3767 u = (uint64_t) bytes;
3769 if (!dbus_message_iter_open_container(&sub2, DBUS_TYPE_STRUCT, NULL, &sub3) ||
3770 !dbus_message_iter_append_basic(&sub3, DBUS_TYPE_STRING, &path) ||
3771 !dbus_message_iter_append_basic(&sub3, DBUS_TYPE_UINT64, &u) ||
3772 !dbus_message_iter_close_container(&sub2, &sub3))
3776 if (!dbus_message_iter_close_container(&sub, &sub2))
3779 } else if (streq(field, "BlockIODeviceWeight")) {
3780 DBusMessageIter sub2;
3782 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "a(st)", &sub) ||
3783 !dbus_message_iter_open_container(&sub, DBUS_TYPE_ARRAY, "(st)", &sub2))
3787 const char *path, *weight;
3788 DBusMessageIter sub3;
3792 e = strchr(eq, ' ');
3794 path = strndupa(eq, e - eq);
3797 log_error("Failed to parse %s value %s.", field, eq);
3801 if (!path_startswith(path, "/dev")) {
3802 log_error("%s is not a device file in /dev.", path);
3806 r = safe_atou64(weight, &u);
3808 log_error("Failed to parse %s value %s.", field, weight);
3811 if (!dbus_message_iter_open_container(&sub2, DBUS_TYPE_STRUCT, NULL, &sub3) ||
3812 !dbus_message_iter_append_basic(&sub3, DBUS_TYPE_STRING, &path) ||
3813 !dbus_message_iter_append_basic(&sub3, DBUS_TYPE_UINT64, &u) ||
3814 !dbus_message_iter_close_container(&sub2, &sub3))
3818 if (!dbus_message_iter_close_container(&sub, &sub2))
3822 log_error("Unknown assignment %s.", assignment);
3826 if (!dbus_message_iter_close_container(iter, &sub))
3832 static int set_property(DBusConnection *bus, char **args) {
3834 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
3835 _cleanup_free_ char *n = NULL;
3836 DBusMessageIter iter, sub;
3837 dbus_bool_t runtime;
3842 dbus_error_init(&error);
3844 m = dbus_message_new_method_call(
3845 "org.freedesktop.systemd1",
3846 "/org/freedesktop/systemd1",
3847 "org.freedesktop.systemd1.Manager",
3848 "SetUnitProperties");
3852 dbus_message_iter_init_append(m, &iter);
3854 runtime = arg_runtime;
3856 n = unit_name_mangle(args[1]);
3860 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &n) ||
3861 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &runtime) ||
3862 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(sv)", &sub))
3865 STRV_FOREACH(i, args + 2) {
3866 DBusMessageIter sub2;
3868 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
3871 r = append_assignment(&sub2, *i);
3875 if (!dbus_message_iter_close_container(&sub, &sub2))
3880 if (!dbus_message_iter_close_container(&iter, &sub))
3883 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3885 log_error("Failed to issue method call: %s", bus_error_message(&error));
3886 dbus_error_free(&error);
3893 static int snapshot(DBusConnection *bus, char **args) {
3894 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3897 dbus_bool_t cleanup = FALSE;
3898 DBusMessageIter iter, sub;
3901 *interface = "org.freedesktop.systemd1.Unit",
3903 _cleanup_free_ char *n = NULL;
3905 dbus_error_init(&error);
3907 if (strv_length(args) > 1)
3908 n = unit_name_mangle_with_suffix(args[1], ".snapshot");
3914 r = bus_method_call_with_reply(
3916 "org.freedesktop.systemd1",
3917 "/org/freedesktop/systemd1",
3918 "org.freedesktop.systemd1.Manager",
3922 DBUS_TYPE_STRING, &n,
3923 DBUS_TYPE_BOOLEAN, &cleanup,
3928 if (!dbus_message_get_args(reply, &error,
3929 DBUS_TYPE_OBJECT_PATH, &path,
3930 DBUS_TYPE_INVALID)) {
3931 log_error("Failed to parse reply: %s", bus_error_message(&error));
3932 dbus_error_free(&error);
3936 dbus_message_unref(reply);
3939 r = bus_method_call_with_reply (
3941 "org.freedesktop.systemd1",
3943 "org.freedesktop.DBus.Properties",
3947 DBUS_TYPE_STRING, &interface,
3948 DBUS_TYPE_STRING, &property,
3953 if (!dbus_message_iter_init(reply, &iter) ||
3954 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3955 log_error("Failed to parse reply.");
3959 dbus_message_iter_recurse(&iter, &sub);
3961 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
3962 log_error("Failed to parse reply.");
3966 dbus_message_iter_get_basic(&sub, &id);
3974 static int delete_snapshot(DBusConnection *bus, char **args) {
3979 STRV_FOREACH(name, args+1) {
3980 _cleanup_free_ char *n = NULL;
3983 n = unit_name_mangle_with_suffix(*name, ".snapshot");
3987 r = bus_method_call_with_reply(
3989 "org.freedesktop.systemd1",
3990 "/org/freedesktop/systemd1",
3991 "org.freedesktop.systemd1.Manager",
3995 DBUS_TYPE_STRING, &n,
4004 static int daemon_reload(DBusConnection *bus, char **args) {
4009 if (arg_action == ACTION_RELOAD)
4011 else if (arg_action == ACTION_REEXEC)
4012 method = "Reexecute";
4014 assert(arg_action == ACTION_SYSTEMCTL);
4017 streq(args[0], "clear-jobs") ||
4018 streq(args[0], "cancel") ? "ClearJobs" :
4019 streq(args[0], "daemon-reexec") ? "Reexecute" :
4020 streq(args[0], "reset-failed") ? "ResetFailed" :
4021 streq(args[0], "halt") ? "Halt" :
4022 streq(args[0], "poweroff") ? "PowerOff" :
4023 streq(args[0], "reboot") ? "Reboot" :
4024 streq(args[0], "kexec") ? "KExec" :
4025 streq(args[0], "exit") ? "Exit" :
4026 /* "daemon-reload" */ "Reload";
4029 r = bus_method_call_with_reply(
4031 "org.freedesktop.systemd1",
4032 "/org/freedesktop/systemd1",
4033 "org.freedesktop.systemd1.Manager",
4039 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
4040 /* There's always a fallback possible for
4041 * legacy actions. */
4043 else if ((r == -ETIMEDOUT || r == -ECONNRESET) && streq(method, "Reexecute"))
4044 /* On reexecution, we expect a disconnect, not a
4048 log_error("Failed to issue method call: %s", bus_error_message(&error));
4050 dbus_error_free(&error);
4054 static int reset_failed(DBusConnection *bus, char **args) {
4058 if (strv_length(args) <= 1)
4059 return daemon_reload(bus, args);
4061 STRV_FOREACH(name, args+1) {
4062 _cleanup_free_ char *n;
4064 n = unit_name_mangle(*name);
4068 r = bus_method_call_with_reply(
4070 "org.freedesktop.systemd1",
4071 "/org/freedesktop/systemd1",
4072 "org.freedesktop.systemd1.Manager",
4076 DBUS_TYPE_STRING, &n,
4085 static int show_enviroment(DBusConnection *bus, char **args) {
4086 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
4087 DBusMessageIter iter, sub, sub2;
4090 *interface = "org.freedesktop.systemd1.Manager",
4091 *property = "Environment";
4093 pager_open_if_enabled();
4095 r = bus_method_call_with_reply(
4097 "org.freedesktop.systemd1",
4098 "/org/freedesktop/systemd1",
4099 "org.freedesktop.DBus.Properties",
4103 DBUS_TYPE_STRING, &interface,
4104 DBUS_TYPE_STRING, &property,
4109 if (!dbus_message_iter_init(reply, &iter) ||
4110 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
4111 log_error("Failed to parse reply.");
4115 dbus_message_iter_recurse(&iter, &sub);
4117 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_ARRAY ||
4118 dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_STRING) {
4119 log_error("Failed to parse reply.");
4123 dbus_message_iter_recurse(&sub, &sub2);
4125 while (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_INVALID) {
4128 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
4129 log_error("Failed to parse reply.");
4133 dbus_message_iter_get_basic(&sub2, &text);
4136 dbus_message_iter_next(&sub2);
4142 static int switch_root(DBusConnection *bus, char **args) {
4145 _cleanup_free_ char *init = NULL;
4147 l = strv_length(args);
4148 if (l < 2 || l > 3) {
4149 log_error("Wrong number of arguments.");
4156 init = strdup(args[2]);
4158 parse_env_file("/proc/cmdline", WHITESPACE,
4168 log_debug("switching root - root: %s; init: %s", root, init);
4170 return bus_method_call_with_reply(
4172 "org.freedesktop.systemd1",
4173 "/org/freedesktop/systemd1",
4174 "org.freedesktop.systemd1.Manager",
4178 DBUS_TYPE_STRING, &root,
4179 DBUS_TYPE_STRING, &init,
4183 static int set_environment(DBusConnection *bus, char **args) {
4184 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
4187 DBusMessageIter iter;
4193 dbus_error_init(&error);
4195 method = streq(args[0], "set-environment")
4197 : "UnsetEnvironment";
4199 m = dbus_message_new_method_call(
4200 "org.freedesktop.systemd1",
4201 "/org/freedesktop/systemd1",
4202 "org.freedesktop.systemd1.Manager",
4207 dbus_message_iter_init_append(m, &iter);
4209 r = bus_append_strv_iter(&iter, args + 1);
4213 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
4215 log_error("Failed to issue method call: %s", bus_error_message(&error));
4216 dbus_error_free(&error);
4223 static int enable_sysv_units(const char *verb, char **args) {
4226 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
4227 unsigned f = 1, t = 1;
4228 _cleanup_lookup_paths_free_ LookupPaths paths = {};
4230 if (arg_scope != UNIT_FILE_SYSTEM)
4233 if (!streq(verb, "enable") &&
4234 !streq(verb, "disable") &&
4235 !streq(verb, "is-enabled"))
4238 /* Processes all SysV units, and reshuffles the array so that
4239 * afterwards only the native units remain */
4241 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, NULL, NULL, NULL);
4246 for (f = 0; args[f]; f++) {
4248 _cleanup_free_ char *p = NULL, *q = NULL;
4249 bool found_native = false, found_sysv;
4251 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
4259 if (!endswith(name, ".service"))
4262 if (path_is_absolute(name))
4265 STRV_FOREACH(k, paths.unit_path) {
4266 if (!isempty(arg_root))
4267 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
4269 asprintf(&p, "%s/%s", *k, name);
4276 found_native = access(p, F_OK) >= 0;
4287 if (!isempty(arg_root))
4288 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
4290 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
4296 p[strlen(p) - sizeof(".service") + 1] = 0;
4297 found_sysv = access(p, F_OK) >= 0;
4302 /* Mark this entry, so that we don't try enabling it as native unit */
4303 args[f] = (char*) "";
4305 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
4307 if (!isempty(arg_root))
4308 argv[c++] = q = strappend("--root=", arg_root);
4310 argv[c++] = path_get_file_name(p);
4312 streq(verb, "enable") ? "on" :
4313 streq(verb, "disable") ? "off" : "--level=5";
4316 l = strv_join((char**)argv, " ");
4322 log_info("Executing %s", l);
4327 log_error("Failed to fork: %m");
4330 } else if (pid == 0) {
4333 execv(argv[0], (char**) argv);
4334 _exit(EXIT_FAILURE);
4337 j = wait_for_terminate(pid, &status);
4339 log_error("Failed to wait for child: %s", strerror(-r));
4344 if (status.si_code == CLD_EXITED) {
4345 if (streq(verb, "is-enabled")) {
4346 if (status.si_status == 0) {
4355 } else if (status.si_status != 0) {
4366 /* Drop all SysV units */
4367 for (f = 0, t = 0; args[f]; f++) {
4369 if (isempty(args[f]))
4372 args[t++] = args[f];
4381 static int mangle_names(char **original_names, char ***mangled_names) {
4382 char **i, **l, **name;
4384 l = new(char*, strv_length(original_names) + 1);
4389 STRV_FOREACH(name, original_names) {
4391 /* When enabling units qualified path names are OK,
4392 * too, hence allow them explicitly. */
4397 *i = unit_name_mangle(*name);
4413 static int enable_unit(DBusConnection *bus, char **args) {
4414 const char *verb = args[0];
4415 UnitFileChange *changes = NULL;
4416 unsigned n_changes = 0, i;
4417 int carries_install_info = -1;
4418 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
4420 _cleanup_dbus_error_free_ DBusError error;
4421 _cleanup_strv_free_ char **mangled_names = NULL;
4423 dbus_error_init(&error);
4428 r = mangle_names(args+1, &mangled_names);
4432 r = enable_sysv_units(verb, mangled_names);
4436 if (!bus || avoid_bus()) {
4437 if (streq(verb, "enable")) {
4438 r = unit_file_enable(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4439 carries_install_info = r;
4440 } else if (streq(verb, "disable"))
4441 r = unit_file_disable(arg_scope, arg_runtime, arg_root, mangled_names, &changes, &n_changes);
4442 else if (streq(verb, "reenable")) {
4443 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4444 carries_install_info = r;
4445 } else if (streq(verb, "link"))
4446 r = unit_file_link(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4447 else if (streq(verb, "preset")) {
4448 r = unit_file_preset(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4449 carries_install_info = r;
4450 } else if (streq(verb, "mask"))
4451 r = unit_file_mask(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4452 else if (streq(verb, "unmask"))
4453 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, mangled_names, &changes, &n_changes);
4454 else if (streq(verb, "set-default"))
4455 r = unit_file_set_default(arg_scope, arg_root, args[1], &changes, &n_changes);
4457 assert_not_reached("Unknown verb");
4460 log_error("Operation failed: %s", strerror(-r));
4465 for (i = 0; i < n_changes; i++) {
4466 if (changes[i].type == UNIT_FILE_SYMLINK)
4467 log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
4469 log_info("rm '%s'", changes[i].path);
4476 bool send_force = true, expect_carries_install_info = false;
4478 DBusMessageIter iter, sub, sub2;
4480 if (streq(verb, "enable")) {
4481 method = "EnableUnitFiles";
4482 expect_carries_install_info = true;
4483 } else if (streq(verb, "disable")) {
4484 method = "DisableUnitFiles";
4486 } else if (streq(verb, "reenable")) {
4487 method = "ReenableUnitFiles";
4488 expect_carries_install_info = true;
4489 } else if (streq(verb, "link"))
4490 method = "LinkUnitFiles";
4491 else if (streq(verb, "preset")) {
4492 method = "PresetUnitFiles";
4493 expect_carries_install_info = true;
4494 } else if (streq(verb, "mask"))
4495 method = "MaskUnitFiles";
4496 else if (streq(verb, "unmask")) {
4497 method = "UnmaskUnitFiles";
4499 } else if (streq(verb, "set-default")) {
4500 method = "SetDefaultTarget";
4502 assert_not_reached("Unknown verb");
4504 m = dbus_message_new_method_call(
4505 "org.freedesktop.systemd1",
4506 "/org/freedesktop/systemd1",
4507 "org.freedesktop.systemd1.Manager",
4514 dbus_message_iter_init_append(m, &iter);
4516 r = bus_append_strv_iter(&iter, mangled_names);
4518 log_error("Failed to append unit files.");
4523 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &a)) {
4524 log_error("Failed to append runtime boolean.");
4532 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b)) {
4533 log_error("Failed to append force boolean.");
4539 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
4541 log_error("Failed to issue method call: %s", bus_error_message(&error));
4546 if (!dbus_message_iter_init(reply, &iter)) {
4547 log_error("Failed to initialize iterator.");
4551 if (expect_carries_install_info) {
4552 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &b, true);
4554 log_error("Failed to parse reply.");
4558 carries_install_info = b;
4561 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
4562 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
4563 log_error("Failed to parse reply.");
4568 dbus_message_iter_recurse(&iter, &sub);
4569 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
4570 const char *type, *path, *source;
4572 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
4573 log_error("Failed to parse reply.");
4578 dbus_message_iter_recurse(&sub, &sub2);
4580 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
4581 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
4582 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &source, false) < 0) {
4583 log_error("Failed to parse reply.");
4589 if (streq(type, "symlink"))
4590 log_info("ln -s '%s' '%s'", source, path);
4592 log_info("rm '%s'", path);
4595 dbus_message_iter_next(&sub);
4598 /* Try to reload if enabeld */
4600 r = daemon_reload(bus, args);
4603 if (carries_install_info == 0)
4604 log_warning("The unit files have no [Install] section. They are not meant to be enabled\n"
4605 "using systemctl.\n"
4606 "Possible reasons for having this kind of units are:\n"
4607 "1) A unit may be statically enabled by being symlinked from another unit's\n"
4608 " .wants/ or .requires/ directory.\n"
4609 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
4610 " a requirement dependency on it.\n"
4611 "3) A unit may be started when needed via activation (socket, path, timer,\n"
4612 " D-Bus, udev, scripted systemctl call, ...).\n");
4615 unit_file_changes_free(changes, n_changes);
4620 static int unit_is_enabled(DBusConnection *bus, char **args) {
4621 _cleanup_dbus_error_free_ DBusError error;
4623 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
4626 _cleanup_strv_free_ char **mangled_names = NULL;
4628 dbus_error_init(&error);
4630 r = mangle_names(args+1, &mangled_names);
4634 r = enable_sysv_units(args[0], mangled_names);
4640 if (!bus || avoid_bus()) {
4642 STRV_FOREACH(name, mangled_names) {
4643 UnitFileState state;
4645 state = unit_file_get_state(arg_scope, arg_root, *name);
4650 if (state == UNIT_FILE_ENABLED ||
4651 state == UNIT_FILE_ENABLED_RUNTIME ||
4652 state == UNIT_FILE_STATIC)
4656 puts(unit_file_state_to_string(state));
4660 STRV_FOREACH(name, mangled_names) {
4663 r = bus_method_call_with_reply (
4665 "org.freedesktop.systemd1",
4666 "/org/freedesktop/systemd1",
4667 "org.freedesktop.systemd1.Manager",
4671 DBUS_TYPE_STRING, name,
4677 if (!dbus_message_get_args(reply, &error,
4678 DBUS_TYPE_STRING, &s,
4679 DBUS_TYPE_INVALID)) {
4680 log_error("Failed to parse reply: %s", bus_error_message(&error));
4684 dbus_message_unref(reply);
4687 if (streq(s, "enabled") ||
4688 streq(s, "enabled-runtime") ||
4697 return enabled ? 0 : 1;
4700 static int systemctl_help(void) {
4702 pager_open_if_enabled();
4704 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
4705 "Query or send control commands to the systemd manager.\n\n"
4706 " -h --help Show this help\n"
4707 " --version Show package version\n"
4708 " -t --type=TYPE List only units of a particular type\n"
4709 " --state=STATE List only units with particular LOAD or SUB or ACTIVE state\n"
4710 " -p --property=NAME Show only properties by this name\n"
4711 " -a --all Show all loaded units/properties, including dead/empty\n"
4712 " ones. To list all units installed on the system, use\n"
4713 " the 'list-unit-files' command instead.\n"
4714 " --reverse Show reverse dependencies with 'list-dependencies'\n"
4715 " -l --full Don't ellipsize unit names on output\n"
4716 " --fail When queueing a new job, fail if conflicting jobs are\n"
4718 " --irreversible When queueing a new job, make sure it cannot be implicitly\n"
4720 " --ignore-dependencies\n"
4721 " When queueing a new job, ignore all its dependencies\n"
4722 " --show-types When showing sockets, explicitly show their type\n"
4723 " -i --ignore-inhibitors\n"
4724 " When shutting down or sleeping, ignore inhibitors\n"
4725 " --kill-who=WHO Who to send signal to\n"
4726 " -s --signal=SIGNAL Which signal to send\n"
4727 " -H --host=[USER@]HOST\n"
4728 " Show information for remote host\n"
4729 " -P --privileged Acquire privileges before execution\n"
4730 " -q --quiet Suppress output\n"
4731 " --no-block Do not wait until operation finished\n"
4732 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4733 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
4735 " --no-legend Do not print a legend (column headers and hints)\n"
4736 " --no-pager Do not pipe output into a pager\n"
4737 " --no-ask-password\n"
4738 " Do not ask for system passwords\n"
4739 " --system Connect to system manager\n"
4740 " --user Connect to user service manager\n"
4741 " --global Enable/disable unit files globally\n"
4742 " --runtime Enable unit files only temporarily until next reboot\n"
4743 " -f --force When enabling unit files, override existing symlinks\n"
4744 " When shutting down, execute action immediately\n"
4745 " --root=PATH Enable unit files in the specified root directory\n"
4746 " -n --lines=INTEGER Number of journal entries to show\n"
4747 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
4748 " verbose, export, json, json-pretty, json-sse, cat)\n\n"
4750 " list-units List loaded units\n"
4751 " list-sockets List loaded sockets ordered by address\n"
4752 " start [NAME...] Start (activate) one or more units\n"
4753 " stop [NAME...] Stop (deactivate) one or more units\n"
4754 " reload [NAME...] Reload one or more units\n"
4755 " restart [NAME...] Start or restart one or more units\n"
4756 " try-restart [NAME...] Restart one or more units if active\n"
4757 " reload-or-restart [NAME...] Reload one or more units if possible,\n"
4758 " otherwise start or restart\n"
4759 " reload-or-try-restart [NAME...] Reload one or more units if possible,\n"
4760 " otherwise restart if active\n"
4761 " isolate [NAME] Start one unit and stop all others\n"
4762 " kill [NAME...] Send signal to processes of a unit\n"
4763 " is-active [NAME...] Check whether units are active\n"
4764 " is-failed [NAME...] Check whether units are failed\n"
4765 " status [NAME...|PID...] Show runtime status of one or more units\n"
4766 " show [NAME...|JOB...] Show properties of one or more\n"
4767 " units/jobs or the manager\n"
4768 " set-property [NAME] [ASSIGNMENT...]\n"
4769 " Sets one or more properties of a unit\n"
4770 " help [NAME...|PID...] Show manual for one or more units\n"
4771 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
4773 " list-dependencies [NAME] Recursively show units which are required\n"
4774 " or wanted by this unit or by which this\n"
4775 " unit is required or wanted\n\n"
4776 "Unit File Commands:\n"
4777 " list-unit-files List installed unit files\n"
4778 " enable [NAME...] Enable one or more unit files\n"
4779 " disable [NAME...] Disable one or more unit files\n"
4780 " reenable [NAME...] Reenable one or more unit files\n"
4781 " preset [NAME...] Enable/disable one or more unit files\n"
4782 " based on preset configuration\n"
4783 " is-enabled [NAME...] Check whether unit files are enabled\n\n"
4784 " mask [NAME...] Mask one or more units\n"
4785 " unmask [NAME...] Unmask one or more units\n"
4786 " link [PATH...] Link one or more units files into\n"
4787 " the search path\n"
4788 " get-default Get the name of the default target\n"
4789 " set-default NAME Set the default target\n\n"
4791 " list-jobs List jobs\n"
4792 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
4793 "Snapshot Commands:\n"
4794 " snapshot [NAME] Create a snapshot\n"
4795 " delete [NAME...] Remove one or more snapshots\n\n"
4796 "Environment Commands:\n"
4797 " show-environment Dump environment\n"
4798 " set-environment [NAME=VALUE...] Set one or more environment variables\n"
4799 " unset-environment [NAME...] Unset one or more environment variables\n\n"
4800 "Manager Lifecycle Commands:\n"
4801 " daemon-reload Reload systemd manager configuration\n"
4802 " daemon-reexec Reexecute systemd manager\n\n"
4803 "System Commands:\n"
4804 " default Enter system default mode\n"
4805 " rescue Enter system rescue mode\n"
4806 " emergency Enter system emergency mode\n"
4807 " halt Shut down and halt the system\n"
4808 " poweroff Shut down and power-off the system\n"
4809 " reboot [ARG] Shut down and reboot the system\n"
4810 " kexec Shut down and reboot the system with kexec\n"
4811 " exit Request user instance exit\n"
4812 " switch-root [ROOT] [INIT] Change to a different root file system\n"
4813 " suspend Suspend the system\n"
4814 " hibernate Hibernate the system\n"
4815 " hybrid-sleep Hibernate and suspend the system\n",
4816 program_invocation_short_name);
4821 static int halt_help(void) {
4823 printf("%s [OPTIONS...]%s\n\n"
4824 "%s the system.\n\n"
4825 " --help Show this help\n"
4826 " --halt Halt the machine\n"
4827 " -p --poweroff Switch off the machine\n"
4828 " --reboot Reboot the machine\n"
4829 " -f --force Force immediate halt/power-off/reboot\n"
4830 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
4831 " -d --no-wtmp Don't write wtmp record\n"
4832 " --no-wall Don't send wall message before halt/power-off/reboot\n",
4833 program_invocation_short_name,
4834 arg_action == ACTION_REBOOT ? " [ARG]" : "",
4835 arg_action == ACTION_REBOOT ? "Reboot" :
4836 arg_action == ACTION_POWEROFF ? "Power off" :
4842 static int shutdown_help(void) {
4844 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
4845 "Shut down the system.\n\n"
4846 " --help Show this help\n"
4847 " -H --halt Halt the machine\n"
4848 " -P --poweroff Power-off the machine\n"
4849 " -r --reboot Reboot the machine\n"
4850 " -h Equivalent to --poweroff, overridden by --halt\n"
4851 " -k Don't halt/power-off/reboot, just send warnings\n"
4852 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4853 " -c Cancel a pending shutdown\n",
4854 program_invocation_short_name);
4859 static int telinit_help(void) {
4861 printf("%s [OPTIONS...] {COMMAND}\n\n"
4862 "Send control commands to the init daemon.\n\n"
4863 " --help Show this help\n"
4864 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
4866 " 0 Power-off the machine\n"
4867 " 6 Reboot the machine\n"
4868 " 2, 3, 4, 5 Start runlevelX.target unit\n"
4869 " 1, s, S Enter rescue mode\n"
4870 " q, Q Reload init daemon configuration\n"
4871 " u, U Reexecute init daemon\n",
4872 program_invocation_short_name);
4877 static int runlevel_help(void) {
4879 printf("%s [OPTIONS...]\n\n"
4880 "Prints the previous and current runlevel of the init system.\n\n"
4881 " --help Show this help\n",
4882 program_invocation_short_name);
4887 static int help_types(void) {
4891 puts("Available unit types:");
4892 for(i = 0; i < _UNIT_TYPE_MAX; i++) {
4893 t = unit_type_to_string(i);
4901 static int systemctl_parse_argv(int argc, char *argv[]) {
4910 ARG_IGNORE_DEPENDENCIES,
4922 ARG_NO_ASK_PASSWORD,
4930 static const struct option options[] = {
4931 { "help", no_argument, NULL, 'h' },
4932 { "version", no_argument, NULL, ARG_VERSION },
4933 { "type", required_argument, NULL, 't' },
4934 { "property", required_argument, NULL, 'p' },
4935 { "all", no_argument, NULL, 'a' },
4936 { "reverse", no_argument, NULL, ARG_REVERSE },
4937 { "after", no_argument, NULL, ARG_AFTER },
4938 { "before", no_argument, NULL, ARG_BEFORE },
4939 { "show-types", no_argument, NULL, ARG_SHOW_TYPES },
4940 { "failed", no_argument, NULL, ARG_FAILED }, /* compatibility only */
4941 { "full", no_argument, NULL, 'l' },
4942 { "fail", no_argument, NULL, ARG_FAIL },
4943 { "irreversible", no_argument, NULL, ARG_IRREVERSIBLE },
4944 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
4945 { "ignore-inhibitors", no_argument, NULL, 'i' },
4946 { "user", no_argument, NULL, ARG_USER },
4947 { "system", no_argument, NULL, ARG_SYSTEM },
4948 { "global", no_argument, NULL, ARG_GLOBAL },
4949 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
4950 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
4951 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
4952 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4953 { "quiet", no_argument, NULL, 'q' },
4954 { "root", required_argument, NULL, ARG_ROOT },
4955 { "force", no_argument, NULL, ARG_FORCE },
4956 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
4957 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
4958 { "signal", required_argument, NULL, 's' },
4959 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
4960 { "host", required_argument, NULL, 'H' },
4961 { "privileged", no_argument, NULL, 'P' },
4962 { "runtime", no_argument, NULL, ARG_RUNTIME },
4963 { "lines", required_argument, NULL, 'n' },
4964 { "output", required_argument, NULL, 'o' },
4965 { "plain", no_argument, NULL, ARG_PLAIN },
4966 { "state", required_argument, NULL, ARG_STATE },
4975 while ((c = getopt_long(argc, argv, "ht:p:alqfs:H:Pn:o:i", options, NULL)) >= 0) {
4980 return systemctl_help();
4983 puts(PACKAGE_STRING);
4984 puts(SYSTEMD_FEATURES);
4991 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
4992 _cleanup_free_ char *type;
4994 type = strndup(word, size);
4998 if (streq(type, "help")) {
5003 if (unit_type_from_string(type) >= 0) {
5004 if (strv_push(&arg_types, type))
5010 /* It's much nicer to use --state= for
5011 * load states, but let's support this
5012 * in --types= too for compatibility
5013 * with old versions */
5014 if (unit_load_state_from_string(optarg) >= 0) {
5015 if (strv_push(&arg_states, type) < 0)
5021 log_error("Unknown unit type or load state '%s'.", type);
5022 log_info("Use -t help to see a list of allowed values.");
5030 /* Make sure that if the empty property list
5031 was specified, we won't show any properties. */
5032 if (isempty(optarg) && !arg_properties) {
5033 arg_properties = strv_new(NULL, NULL);
5034 if (!arg_properties)
5040 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
5043 prop = strndup(word, size);
5047 if (strv_push(&arg_properties, prop) < 0) {
5054 /* If the user asked for a particular
5055 * property, show it to him, even if it is
5067 arg_dependency = DEPENDENCY_REVERSE;
5071 arg_dependency = DEPENDENCY_AFTER;
5075 arg_dependency = DEPENDENCY_BEFORE;
5078 case ARG_SHOW_TYPES:
5079 arg_show_types = true;
5083 arg_job_mode = "fail";
5086 case ARG_IRREVERSIBLE:
5087 arg_job_mode = "replace-irreversibly";
5090 case ARG_IGNORE_DEPENDENCIES:
5091 arg_job_mode = "ignore-dependencies";
5095 arg_scope = UNIT_FILE_USER;
5099 arg_scope = UNIT_FILE_SYSTEM;
5103 arg_scope = UNIT_FILE_GLOBAL;
5107 arg_no_block = true;
5111 arg_no_legend = true;
5115 arg_no_pager = true;
5131 if (strv_extend(&arg_states, "failed") < 0)
5149 arg_no_reload = true;
5153 arg_kill_who = optarg;
5157 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
5158 log_error("Failed to parse signal string %s.", optarg);
5163 case ARG_NO_ASK_PASSWORD:
5164 arg_ask_password = false;
5168 arg_transport = TRANSPORT_POLKIT;
5172 arg_transport = TRANSPORT_SSH;
5173 parse_user_at_host(optarg, &arg_user, &arg_host);
5181 if (safe_atou(optarg, &arg_lines) < 0) {
5182 log_error("Failed to parse lines '%s'", optarg);
5188 arg_output = output_mode_from_string(optarg);
5189 if (arg_output < 0) {
5190 log_error("Unknown output '%s'.", optarg);
5196 arg_ignore_inhibitors = true;
5207 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
5210 s = strndup(word, size);
5214 if (strv_push(&arg_states, s) < 0) {
5226 assert_not_reached("Unhandled option");
5230 if (arg_transport != TRANSPORT_NORMAL && arg_scope != UNIT_FILE_SYSTEM) {
5231 log_error("Cannot access user instance remotely.");
5238 static int halt_parse_argv(int argc, char *argv[]) {
5247 static const struct option options[] = {
5248 { "help", no_argument, NULL, ARG_HELP },
5249 { "halt", no_argument, NULL, ARG_HALT },
5250 { "poweroff", no_argument, NULL, 'p' },
5251 { "reboot", no_argument, NULL, ARG_REBOOT },
5252 { "force", no_argument, NULL, 'f' },
5253 { "wtmp-only", no_argument, NULL, 'w' },
5254 { "no-wtmp", no_argument, NULL, 'd' },
5255 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5264 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
5265 if (runlevel == '0' || runlevel == '6')
5268 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
5275 arg_action = ACTION_HALT;
5279 if (arg_action != ACTION_REBOOT)
5280 arg_action = ACTION_POWEROFF;
5284 arg_action = ACTION_REBOOT;
5306 /* Compatibility nops */
5313 assert_not_reached("Unhandled option");
5317 if (arg_action == ACTION_REBOOT && argc == optind + 1) {
5318 r = write_string_file(REBOOT_PARAM_FILE, argv[optind]);
5320 log_error("Failed to write reboot param to "
5321 REBOOT_PARAM_FILE": %s", strerror(-r));
5324 } else if (optind < argc) {
5325 log_error("Too many arguments.");
5332 static int parse_time_spec(const char *t, usec_t *_u) {
5336 if (streq(t, "now"))
5338 else if (!strchr(t, ':')) {
5341 if (safe_atou64(t, &u) < 0)
5344 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
5353 hour = strtol(t, &e, 10);
5354 if (errno > 0 || *e != ':' || hour < 0 || hour > 23)
5357 minute = strtol(e+1, &e, 10);
5358 if (errno > 0 || *e != 0 || minute < 0 || minute > 59)
5361 n = now(CLOCK_REALTIME);
5362 s = (time_t) (n / USEC_PER_SEC);
5364 assert_se(localtime_r(&s, &tm));
5366 tm.tm_hour = (int) hour;
5367 tm.tm_min = (int) minute;
5370 assert_se(s = mktime(&tm));
5372 *_u = (usec_t) s * USEC_PER_SEC;
5375 *_u += USEC_PER_DAY;
5381 static int shutdown_parse_argv(int argc, char *argv[]) {
5388 static const struct option options[] = {
5389 { "help", no_argument, NULL, ARG_HELP },
5390 { "halt", no_argument, NULL, 'H' },
5391 { "poweroff", no_argument, NULL, 'P' },
5392 { "reboot", no_argument, NULL, 'r' },
5393 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
5394 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5403 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
5407 return shutdown_help();
5410 arg_action = ACTION_HALT;
5414 arg_action = ACTION_POWEROFF;
5419 arg_action = ACTION_KEXEC;
5421 arg_action = ACTION_REBOOT;
5425 arg_action = ACTION_KEXEC;
5429 if (arg_action != ACTION_HALT)
5430 arg_action = ACTION_POWEROFF;
5443 /* Compatibility nops */
5447 arg_action = ACTION_CANCEL_SHUTDOWN;
5454 assert_not_reached("Unhandled option");
5458 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
5459 r = parse_time_spec(argv[optind], &arg_when);
5461 log_error("Failed to parse time specification: %s", argv[optind]);
5465 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
5467 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
5468 /* No time argument for shutdown cancel */
5469 arg_wall = argv + optind;
5470 else if (argc > optind + 1)
5471 /* We skip the time argument */
5472 arg_wall = argv + optind + 1;
5479 static int telinit_parse_argv(int argc, char *argv[]) {
5486 static const struct option options[] = {
5487 { "help", no_argument, NULL, ARG_HELP },
5488 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5492 static const struct {
5496 { '0', ACTION_POWEROFF },
5497 { '6', ACTION_REBOOT },
5498 { '1', ACTION_RESCUE },
5499 { '2', ACTION_RUNLEVEL2 },
5500 { '3', ACTION_RUNLEVEL3 },
5501 { '4', ACTION_RUNLEVEL4 },
5502 { '5', ACTION_RUNLEVEL5 },
5503 { 's', ACTION_RESCUE },
5504 { 'S', ACTION_RESCUE },
5505 { 'q', ACTION_RELOAD },
5506 { 'Q', ACTION_RELOAD },
5507 { 'u', ACTION_REEXEC },
5508 { 'U', ACTION_REEXEC }
5517 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
5521 return telinit_help();
5531 assert_not_reached("Unhandled option");
5535 if (optind >= argc) {
5540 if (optind + 1 < argc) {
5541 log_error("Too many arguments.");
5545 if (strlen(argv[optind]) != 1) {
5546 log_error("Expected single character argument.");
5550 for (i = 0; i < ELEMENTSOF(table); i++)
5551 if (table[i].from == argv[optind][0])
5554 if (i >= ELEMENTSOF(table)) {
5555 log_error("Unknown command '%s'.", argv[optind]);
5559 arg_action = table[i].to;
5566 static int runlevel_parse_argv(int argc, char *argv[]) {
5572 static const struct option options[] = {
5573 { "help", no_argument, NULL, ARG_HELP },
5582 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
5586 return runlevel_help();
5593 assert_not_reached("Unhandled option");
5597 if (optind < argc) {
5598 log_error("Too many arguments.");
5605 static int parse_argv(int argc, char *argv[]) {
5609 if (program_invocation_short_name) {
5611 if (strstr(program_invocation_short_name, "halt")) {
5612 arg_action = ACTION_HALT;
5613 return halt_parse_argv(argc, argv);
5614 } else if (strstr(program_invocation_short_name, "poweroff")) {
5615 arg_action = ACTION_POWEROFF;
5616 return halt_parse_argv(argc, argv);
5617 } else if (strstr(program_invocation_short_name, "reboot")) {
5619 arg_action = ACTION_KEXEC;
5621 arg_action = ACTION_REBOOT;
5622 return halt_parse_argv(argc, argv);
5623 } else if (strstr(program_invocation_short_name, "shutdown")) {
5624 arg_action = ACTION_POWEROFF;
5625 return shutdown_parse_argv(argc, argv);
5626 } else if (strstr(program_invocation_short_name, "init")) {
5628 if (sd_booted() > 0) {
5629 arg_action = ACTION_INVALID;
5630 return telinit_parse_argv(argc, argv);
5632 /* Hmm, so some other init system is
5633 * running, we need to forward this
5634 * request to it. For now we simply
5635 * guess that it is Upstart. */
5637 execv(TELINIT, argv);
5639 log_error("Couldn't find an alternative telinit implementation to spawn.");
5643 } else if (strstr(program_invocation_short_name, "runlevel")) {
5644 arg_action = ACTION_RUNLEVEL;
5645 return runlevel_parse_argv(argc, argv);
5649 arg_action = ACTION_SYSTEMCTL;
5650 return systemctl_parse_argv(argc, argv);
5653 _pure_ static int action_to_runlevel(void) {
5655 static const char table[_ACTION_MAX] = {
5656 [ACTION_HALT] = '0',
5657 [ACTION_POWEROFF] = '0',
5658 [ACTION_REBOOT] = '6',
5659 [ACTION_RUNLEVEL2] = '2',
5660 [ACTION_RUNLEVEL3] = '3',
5661 [ACTION_RUNLEVEL4] = '4',
5662 [ACTION_RUNLEVEL5] = '5',
5663 [ACTION_RESCUE] = '1'
5666 assert(arg_action < _ACTION_MAX);
5668 return table[arg_action];
5671 static int talk_initctl(void) {
5672 struct init_request request = {};
5674 _cleanup_close_ int fd = -1;
5677 rl = action_to_runlevel();
5681 request.magic = INIT_MAGIC;
5682 request.sleeptime = 0;
5683 request.cmd = INIT_CMD_RUNLVL;
5684 request.runlevel = rl;
5686 fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY);
5688 if (errno == ENOENT)
5691 log_error("Failed to open "INIT_FIFO": %m");
5696 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
5698 log_error("Failed to write to "INIT_FIFO": %m");
5699 return errno > 0 ? -errno : -EIO;
5705 static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
5707 static const struct {
5715 int (* const dispatch)(DBusConnection *bus, char **args);
5717 { "list-units", LESS, 1, list_units },
5718 { "list-unit-files", EQUAL, 1, list_unit_files },
5719 { "list-sockets", LESS, 1, list_sockets },
5720 { "list-jobs", EQUAL, 1, list_jobs },
5721 { "clear-jobs", EQUAL, 1, daemon_reload },
5722 { "cancel", MORE, 2, cancel_job },
5723 { "start", MORE, 2, start_unit },
5724 { "stop", MORE, 2, start_unit },
5725 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5726 { "reload", MORE, 2, start_unit },
5727 { "restart", MORE, 2, start_unit },
5728 { "try-restart", MORE, 2, start_unit },
5729 { "reload-or-restart", MORE, 2, start_unit },
5730 { "reload-or-try-restart", MORE, 2, start_unit },
5731 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
5732 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5733 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
5734 { "isolate", EQUAL, 2, start_unit },
5735 { "kill", MORE, 2, kill_unit },
5736 { "is-active", MORE, 2, check_unit_active },
5737 { "check", MORE, 2, check_unit_active },
5738 { "is-failed", MORE, 2, check_unit_failed },
5739 { "show", MORE, 1, show },
5740 { "status", MORE, 1, show },
5741 { "help", MORE, 2, show },
5742 { "snapshot", LESS, 2, snapshot },
5743 { "delete", MORE, 2, delete_snapshot },
5744 { "daemon-reload", EQUAL, 1, daemon_reload },
5745 { "daemon-reexec", EQUAL, 1, daemon_reload },
5746 { "show-environment", EQUAL, 1, show_enviroment },
5747 { "set-environment", MORE, 2, set_environment },
5748 { "unset-environment", MORE, 2, set_environment },
5749 { "halt", EQUAL, 1, start_special },
5750 { "poweroff", EQUAL, 1, start_special },
5751 { "reboot", EQUAL, 1, start_special },
5752 { "kexec", EQUAL, 1, start_special },
5753 { "suspend", EQUAL, 1, start_special },
5754 { "hibernate", EQUAL, 1, start_special },
5755 { "hybrid-sleep", EQUAL, 1, start_special },
5756 { "default", EQUAL, 1, start_special },
5757 { "rescue", EQUAL, 1, start_special },
5758 { "emergency", EQUAL, 1, start_special },
5759 { "exit", EQUAL, 1, start_special },
5760 { "reset-failed", MORE, 1, reset_failed },
5761 { "enable", MORE, 2, enable_unit },
5762 { "disable", MORE, 2, enable_unit },
5763 { "is-enabled", MORE, 2, unit_is_enabled },
5764 { "reenable", MORE, 2, enable_unit },
5765 { "preset", MORE, 2, enable_unit },
5766 { "mask", MORE, 2, enable_unit },
5767 { "unmask", MORE, 2, enable_unit },
5768 { "link", MORE, 2, enable_unit },
5769 { "switch-root", MORE, 2, switch_root },
5770 { "list-dependencies", LESS, 2, list_dependencies },
5771 { "set-default", EQUAL, 2, enable_unit },
5772 { "get-default", LESS, 1, get_default },
5773 { "set-property", MORE, 3, set_property },
5783 left = argc - optind;
5786 /* Special rule: no arguments means "list-units" */
5789 if (streq(argv[optind], "help") && !argv[optind+1]) {
5790 log_error("This command expects one or more "
5791 "unit names. Did you mean --help?");
5795 for (i = 0; i < ELEMENTSOF(verbs); i++)
5796 if (streq(argv[optind], verbs[i].verb))
5799 if (i >= ELEMENTSOF(verbs)) {
5800 log_error("Unknown operation '%s'.", argv[optind]);
5805 switch (verbs[i].argc_cmp) {
5808 if (left != verbs[i].argc) {
5809 log_error("Invalid number of arguments.");
5816 if (left < verbs[i].argc) {
5817 log_error("Too few arguments.");
5824 if (left > verbs[i].argc) {
5825 log_error("Too many arguments.");
5832 assert_not_reached("Unknown comparison operator.");
5835 /* Require a bus connection for all operations but
5837 if (!streq(verbs[i].verb, "enable") &&
5838 !streq(verbs[i].verb, "disable") &&
5839 !streq(verbs[i].verb, "is-enabled") &&
5840 !streq(verbs[i].verb, "list-unit-files") &&
5841 !streq(verbs[i].verb, "reenable") &&
5842 !streq(verbs[i].verb, "preset") &&
5843 !streq(verbs[i].verb, "mask") &&
5844 !streq(verbs[i].verb, "unmask") &&
5845 !streq(verbs[i].verb, "link") &&
5846 !streq(verbs[i].verb, "set-default") &&
5847 !streq(verbs[i].verb, "get-default")) {
5849 if (running_in_chroot() > 0) {
5850 log_info("Running in chroot, ignoring request.");
5854 if (((!streq(verbs[i].verb, "reboot") &&
5855 !streq(verbs[i].verb, "halt") &&
5856 !streq(verbs[i].verb, "poweroff")) || arg_force <= 0) && !bus) {
5857 log_error("Failed to get D-Bus connection: %s",
5858 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5864 if (!bus && !avoid_bus()) {
5865 log_error("Failed to get D-Bus connection: %s",
5866 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5871 return verbs[i].dispatch(bus, argv + optind);
5874 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
5875 _cleanup_close_ int fd;
5876 struct sd_shutdown_command c = {
5882 union sockaddr_union sockaddr = {
5883 .un.sun_family = AF_UNIX,
5884 .un.sun_path = "/run/systemd/shutdownd",
5886 struct iovec iovec[2] = {
5887 {.iov_base = (char*) &c,
5888 .iov_len = offsetof(struct sd_shutdown_command, wall_message),
5891 struct msghdr msghdr = {
5892 .msg_name = &sockaddr,
5893 .msg_namelen = offsetof(struct sockaddr_un, sun_path)
5894 + sizeof("/run/systemd/shutdownd") - 1,
5899 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
5903 if (!isempty(message)) {
5904 iovec[1].iov_base = (char*) message;
5905 iovec[1].iov_len = strlen(message);
5906 msghdr.msg_iovlen++;
5909 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0)
5915 static int reload_with_fallback(DBusConnection *bus) {
5918 /* First, try systemd via D-Bus. */
5919 if (daemon_reload(bus, NULL) >= 0)
5923 /* Nothing else worked, so let's try signals */
5924 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
5926 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
5927 log_error("kill() failed: %m");
5934 static int start_with_fallback(DBusConnection *bus) {
5937 /* First, try systemd via D-Bus. */
5938 if (start_unit(bus, NULL) >= 0)
5942 /* Nothing else worked, so let's try
5944 if (talk_initctl() > 0)
5947 log_error("Failed to talk to init daemon.");
5951 warn_wall(arg_action);
5955 static _noreturn_ void halt_now(enum action a) {
5957 _cleanup_free_ char *param = NULL;
5959 /* Make sure C-A-D is handled by the kernel from this
5961 reboot(RB_ENABLE_CAD);
5966 log_info("Halting.");
5967 reboot(RB_HALT_SYSTEM);
5970 case ACTION_POWEROFF:
5971 log_info("Powering off.");
5972 reboot(RB_POWER_OFF);
5976 if (read_one_line_file(REBOOT_PARAM_FILE, ¶m) == 0) {
5977 log_info("Rebooting with arg '%s'.", param);
5978 syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
5979 LINUX_REBOOT_CMD_RESTART2, param);
5981 log_info("Rebooting.");
5982 reboot(RB_AUTOBOOT);
5987 assert_not_reached("Unknown halt action.");
5990 assert_not_reached("Uh? This shouldn't happen.");
5993 static int halt_main(DBusConnection *bus) {
5996 r = check_inhibitors(bus, arg_action);
6000 if (geteuid() != 0) {
6001 /* Try logind if we are a normal user and no special
6002 * mode applies. Maybe PolicyKit allows us to shutdown
6005 if (arg_when <= 0 &&
6008 (arg_action == ACTION_POWEROFF ||
6009 arg_action == ACTION_REBOOT)) {
6010 r = reboot_with_logind(bus, arg_action);
6015 log_error("Must be root.");
6020 _cleanup_free_ char *m;
6022 m = strv_join(arg_wall, " ");
6023 r = send_shutdownd(arg_when,
6024 arg_action == ACTION_HALT ? 'H' :
6025 arg_action == ACTION_POWEROFF ? 'P' :
6026 arg_action == ACTION_KEXEC ? 'K' :
6033 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
6035 char date[FORMAT_TIMESTAMP_MAX];
6037 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
6038 format_timestamp(date, sizeof(date), arg_when));
6043 if (!arg_dry && !arg_force)
6044 return start_with_fallback(bus);
6047 if (sd_booted() > 0)
6048 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
6050 r = utmp_put_shutdown();
6052 log_warning("Failed to write utmp record: %s", strerror(-r));
6059 halt_now(arg_action);
6060 /* We should never reach this. */
6064 static int runlevel_main(void) {
6065 int r, runlevel, previous;
6067 r = utmp_get_runlevel(&runlevel, &previous);
6074 previous <= 0 ? 'N' : previous,
6075 runlevel <= 0 ? 'N' : runlevel);
6080 int main(int argc, char*argv[]) {
6081 int r, retval = EXIT_FAILURE;
6082 DBusConnection *bus = NULL;
6083 _cleanup_dbus_error_free_ DBusError error;
6085 dbus_error_init(&error);
6087 setlocale(LC_ALL, "");
6088 log_parse_environment();
6091 /* Explicitly not on_tty() to avoid setting cached value.
6092 * This becomes relevant for piping output which might be
6094 original_stdout_is_tty = isatty(STDOUT_FILENO);
6096 r = parse_argv(argc, argv);
6100 retval = EXIT_SUCCESS;
6104 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
6105 * let's shortcut this */
6106 if (arg_action == ACTION_RUNLEVEL) {
6107 r = runlevel_main();
6108 retval = r < 0 ? EXIT_FAILURE : r;
6112 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
6113 log_info("Running in chroot, ignoring request.");
6119 if (arg_transport == TRANSPORT_NORMAL)
6120 bus_connect(arg_scope == UNIT_FILE_SYSTEM ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &bus, &private_bus, &error);
6121 else if (arg_transport == TRANSPORT_POLKIT) {
6122 bus_connect_system_polkit(&bus, &error);
6123 private_bus = false;
6124 } else if (arg_transport == TRANSPORT_SSH) {
6125 bus_connect_system_ssh(arg_user, arg_host, &bus, &error);
6126 private_bus = false;
6128 assert_not_reached("Uh, invalid transport...");
6131 switch (arg_action) {
6133 case ACTION_SYSTEMCTL:
6134 r = systemctl_main(bus, argc, argv, &error);
6138 case ACTION_POWEROFF:
6144 case ACTION_RUNLEVEL2:
6145 case ACTION_RUNLEVEL3:
6146 case ACTION_RUNLEVEL4:
6147 case ACTION_RUNLEVEL5:
6149 case ACTION_EMERGENCY:
6150 case ACTION_DEFAULT:
6151 r = start_with_fallback(bus);
6156 r = reload_with_fallback(bus);
6159 case ACTION_CANCEL_SHUTDOWN: {
6163 m = strv_join(arg_wall, " ");
6165 retval = EXIT_FAILURE;
6169 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
6171 log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r));
6176 case ACTION_INVALID:
6177 case ACTION_RUNLEVEL:
6179 assert_not_reached("Unknown action");
6182 retval = r < 0 ? EXIT_FAILURE : r;
6186 dbus_connection_flush(bus);
6187 dbus_connection_close(bus);
6188 dbus_connection_unref(bus);
6193 strv_free(arg_types);
6194 strv_free(arg_states);
6195 strv_free(arg_properties);
6198 ask_password_agent_close();
6199 polkit_agent_close();