1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
22 #include <sys/reboot.h>
29 #include <sys/ioctl.h>
33 #include <sys/socket.h>
36 #include <sys/prctl.h>
37 #include <dbus/dbus.h>
39 #include <systemd/sd-daemon.h>
40 #include <systemd/sd-shutdown.h>
41 #include <systemd/sd-login.h>
47 #include "utmp-wtmp.h"
50 #include "path-util.h"
52 #include "dbus-common.h"
53 #include "cgroup-show.h"
54 #include "cgroup-util.h"
56 #include "path-lookup.h"
57 #include "conf-parser.h"
58 #include "exit-status.h"
59 #include "bus-errors.h"
61 #include "unit-name.h"
63 #include "spawn-ask-password-agent.h"
64 #include "spawn-polkit-agent.h"
66 #include "logs-show.h"
67 #include "path-util.h"
68 #include "socket-util.h"
71 static char **arg_types = NULL;
72 static char **arg_load_states = NULL;
73 static char **arg_properties = NULL;
74 static bool arg_all = false;
75 static enum dependency {
80 } arg_dependency = DEPENDENCY_FORWARD;
81 static const char *arg_job_mode = "replace";
82 static UnitFileScope arg_scope = UNIT_FILE_SYSTEM;
83 static bool arg_no_block = false;
84 static bool arg_no_legend = false;
85 static bool arg_no_pager = false;
86 static bool arg_no_wtmp = false;
87 static bool arg_no_wall = false;
88 static bool arg_no_reload = false;
89 static bool arg_show_types = false;
90 static bool arg_ignore_inhibitors = false;
91 static bool arg_dry = false;
92 static bool arg_quiet = false;
93 static bool arg_full = false;
94 static int arg_force = 0;
95 static bool arg_ask_password = true;
96 static bool arg_failed = false;
97 static bool arg_runtime = false;
98 static char **arg_wall = NULL;
99 static const char *arg_kill_who = NULL;
100 static int arg_signal = SIGTERM;
101 static const char *arg_root = NULL;
102 static usec_t arg_when = 0;
124 ACTION_CANCEL_SHUTDOWN,
126 } arg_action = ACTION_SYSTEMCTL;
127 static enum transport {
131 } arg_transport = TRANSPORT_NORMAL;
132 static char *arg_host = NULL;
133 static char *arg_user = NULL;
134 static unsigned arg_lines = 10;
135 static OutputMode arg_output = OUTPUT_SHORT;
136 static bool arg_plain = false;
138 static bool private_bus = false;
140 static int daemon_reload(DBusConnection *bus, char **args);
141 static void halt_now(enum action a);
143 static void pager_open_if_enabled(void) {
151 static void ask_password_agent_open_if_enabled(void) {
153 /* Open the password agent as a child process if necessary */
155 if (!arg_ask_password)
158 if (arg_scope != UNIT_FILE_SYSTEM)
161 ask_password_agent_open();
165 static void polkit_agent_open_if_enabled(void) {
167 /* Open the polkit agent as a child process if necessary */
169 if (!arg_ask_password)
172 if (arg_scope != UNIT_FILE_SYSTEM)
179 static const char *ansi_highlight(bool b) {
184 return b ? ANSI_HIGHLIGHT_ON : ANSI_HIGHLIGHT_OFF;
187 static const char *ansi_highlight_red(bool b) {
192 return b ? ANSI_HIGHLIGHT_RED_ON : ANSI_HIGHLIGHT_OFF;
195 static const char *ansi_highlight_green(bool b) {
200 return b ? ANSI_HIGHLIGHT_GREEN_ON : ANSI_HIGHLIGHT_OFF;
203 static int translate_bus_error_to_exit_status(int r, const DBusError *error) {
206 if (!dbus_error_is_set(error))
209 if (dbus_error_has_name(error, DBUS_ERROR_ACCESS_DENIED) ||
210 dbus_error_has_name(error, BUS_ERROR_ONLY_BY_DEPENDENCY) ||
211 dbus_error_has_name(error, BUS_ERROR_NO_ISOLATION) ||
212 dbus_error_has_name(error, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE))
213 return EXIT_NOPERMISSION;
215 if (dbus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT))
216 return EXIT_NOTINSTALLED;
218 if (dbus_error_has_name(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE) ||
219 dbus_error_has_name(error, BUS_ERROR_NOT_SUPPORTED))
220 return EXIT_NOTIMPLEMENTED;
222 if (dbus_error_has_name(error, BUS_ERROR_LOAD_FAILED))
223 return EXIT_NOTCONFIGURED;
231 static void warn_wall(enum action a) {
232 static const char *table[_ACTION_MAX] = {
233 [ACTION_HALT] = "The system is going down for system halt NOW!",
234 [ACTION_REBOOT] = "The system is going down for reboot NOW!",
235 [ACTION_POWEROFF] = "The system is going down for power-off NOW!",
236 [ACTION_KEXEC] = "The system is going down for kexec reboot NOW!",
237 [ACTION_RESCUE] = "The system is going down to rescue mode NOW!",
238 [ACTION_EMERGENCY] = "The system is going down to emergency mode NOW!",
239 [ACTION_CANCEL_SHUTDOWN] = "The system shutdown has been cancelled NOW!"
246 _cleanup_free_ char *p;
248 p = strv_join(arg_wall, " ");
263 utmp_wall(table[a], NULL);
266 static bool avoid_bus(void) {
268 if (running_in_chroot() > 0)
271 if (sd_booted() <= 0)
274 if (!isempty(arg_root))
277 if (arg_scope == UNIT_FILE_GLOBAL)
283 static int compare_unit_info(const void *a, const void *b) {
285 const struct unit_info *u = a, *v = b;
287 d1 = strrchr(u->id, '.');
288 d2 = strrchr(v->id, '.');
293 r = strcasecmp(d1, d2);
298 return strcasecmp(u->id, v->id);
301 static bool output_show_unit(const struct unit_info *u) {
305 return streq(u->active_state, "failed");
307 return (!arg_types || ((dot = strrchr(u->id, '.')) &&
308 strv_find(arg_types, dot+1))) &&
309 (!arg_load_states || strv_find(arg_load_states, u->load_state)) &&
310 (arg_all || !(streq(u->active_state, "inactive")
311 || u->following[0]) || u->job_id > 0);
314 static void output_units_list(const struct unit_info *unit_infos, unsigned c) {
315 unsigned id_len, max_id_len, active_len, sub_len, job_len, desc_len, n_shown = 0;
316 const struct unit_info *u;
319 max_id_len = sizeof("UNIT")-1;
320 active_len = sizeof("ACTIVE")-1;
321 sub_len = sizeof("SUB")-1;
322 job_len = sizeof("JOB")-1;
325 for (u = unit_infos; u < unit_infos + c; u++) {
326 if (!output_show_unit(u))
329 max_id_len = MAX(max_id_len, strlen(u->id));
330 active_len = MAX(active_len, strlen(u->active_state));
331 sub_len = MAX(sub_len, strlen(u->sub_state));
332 if (u->job_id != 0) {
333 job_len = MAX(job_len, strlen(u->job_type));
340 id_len = MIN(max_id_len, 25u);
341 basic_len = 5 + id_len + 5 + active_len + sub_len;
343 basic_len += job_len + 1;
344 if (basic_len < (unsigned) columns()) {
345 unsigned extra_len, incr;
346 extra_len = columns() - basic_len;
347 /* Either UNIT already got 25, or is fully satisfied.
348 * Grant up to 25 to DESC now. */
349 incr = MIN(extra_len, 25u);
352 /* split the remaining space between UNIT and DESC,
353 * but do not give UNIT more than it needs. */
355 incr = MIN(extra_len / 2, max_id_len - id_len);
357 desc_len += extra_len - incr;
363 for (u = unit_infos; u < unit_infos + c; u++) {
364 _cleanup_free_ char *e = NULL;
365 const char *on_loaded, *off_loaded, *on = "";
366 const char *on_active, *off_active, *off = "";
368 if (!output_show_unit(u))
371 if (!n_shown && !arg_no_legend) {
372 printf("%-*s %-6s %-*s %-*s ", id_len, "UNIT", "LOAD",
373 active_len, "ACTIVE", sub_len, "SUB");
375 printf("%-*s ", job_len, "JOB");
376 if (!arg_full && arg_no_pager)
377 printf("%.*s\n", desc_len, "DESCRIPTION");
379 printf("%s\n", "DESCRIPTION");
384 if (streq(u->load_state, "error") ||
385 streq(u->load_state, "not-found")) {
386 on_loaded = on = ansi_highlight_red(true);
387 off_loaded = off = ansi_highlight_red(false);
389 on_loaded = off_loaded = "";
391 if (streq(u->active_state, "failed")) {
392 on_active = on = ansi_highlight_red(true);
393 off_active = off = ansi_highlight_red(false);
395 on_active = off_active = "";
397 e = arg_full ? NULL : ellipsize(u->id, id_len, 33);
399 printf("%s%-*s%s %s%-6s%s %s%-*s %-*s%s %-*s",
400 on, id_len, e ? e : u->id, off,
401 on_loaded, u->load_state, off_loaded,
402 on_active, active_len, u->active_state,
403 sub_len, u->sub_state, off_active,
404 job_count ? job_len + 1 : 0, u->job_id ? u->job_type : "");
405 if (!arg_full && arg_no_pager)
406 printf("%.*s\n", desc_len, u->description);
408 printf("%s\n", u->description);
411 if (!arg_no_legend) {
412 const char *on, *off;
415 printf("\nLOAD = Reflects whether the unit definition was properly loaded.\n"
416 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
417 "SUB = The low-level unit activation state, values depend on unit type.\n");
419 printf("JOB = Pending job for the unit.\n");
421 on = ansi_highlight(true);
422 off = ansi_highlight(false);
424 on = ansi_highlight_red(true);
425 off = ansi_highlight_red(false);
429 printf("%s%u loaded units listed.%s\n"
430 "To show all installed unit files use 'systemctl list-unit-files'.\n",
433 printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
434 "To show all installed unit files use 'systemctl list-unit-files'.\n",
439 static int get_unit_list(
442 struct unit_info **unit_infos,
445 DBusMessageIter iter, sub;
453 r = bus_method_call_with_reply(
455 "org.freedesktop.systemd1",
456 "/org/freedesktop/systemd1",
457 "org.freedesktop.systemd1.Manager",
465 if (!dbus_message_iter_init(*reply, &iter) ||
466 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
467 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
468 log_error("Failed to parse reply.");
472 dbus_message_iter_recurse(&iter, &sub);
474 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
475 if (!GREEDY_REALLOC(*unit_infos, size, *c + 1))
478 bus_parse_unit_info(&sub, *unit_infos + *c);
481 dbus_message_iter_next(&sub);
487 static int list_units(DBusConnection *bus, char **args) {
488 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
489 _cleanup_free_ struct unit_info *unit_infos = NULL;
493 pager_open_if_enabled();
495 r = get_unit_list(bus, &reply, &unit_infos, &c);
499 qsort(unit_infos, c, sizeof(struct unit_info), compare_unit_info);
501 output_units_list(unit_infos, c);
506 static int get_triggered_units(
508 const char* unit_path,
511 const char *interface = "org.freedesktop.systemd1.Unit",
512 *triggers_property = "Triggers";
513 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
514 DBusMessageIter iter, sub;
517 r = bus_method_call_with_reply(bus,
518 "org.freedesktop.systemd1",
520 "org.freedesktop.DBus.Properties",
524 DBUS_TYPE_STRING, &interface,
525 DBUS_TYPE_STRING, &triggers_property,
530 if (!dbus_message_iter_init(reply, &iter) ||
531 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
532 log_error("Failed to parse reply.");
536 dbus_message_iter_recurse(&iter, &sub);
537 dbus_message_iter_recurse(&sub, &iter);
540 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
543 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
544 log_error("Failed to parse reply.");
548 dbus_message_iter_get_basic(&sub, &unit);
549 r = strv_extend(triggered, unit);
553 dbus_message_iter_next(&sub);
559 static int get_listening(DBusConnection *bus, const char* unit_path,
560 char*** listen, unsigned *c)
562 const char *interface = "org.freedesktop.systemd1.Socket",
563 *listen_property = "Listen";
564 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
565 DBusMessageIter iter, sub;
568 r = bus_method_call_with_reply(bus,
569 "org.freedesktop.systemd1",
571 "org.freedesktop.DBus.Properties",
575 DBUS_TYPE_STRING, &interface,
576 DBUS_TYPE_STRING, &listen_property,
581 if (!dbus_message_iter_init(reply, &iter) ||
582 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
583 log_error("Failed to parse reply.");
587 dbus_message_iter_recurse(&iter, &sub);
588 dbus_message_iter_recurse(&sub, &iter);
591 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
592 DBusMessageIter sub2;
593 const char *type, *path;
595 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
596 log_error("Failed to parse reply.");
600 dbus_message_iter_recurse(&sub, &sub2);
602 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
603 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0) {
604 r = strv_extend(listen, type);
608 r = strv_extend(listen, path);
615 dbus_message_iter_next(&sub);
627 /* Note: triggered is a list here, although it almost certainly
628 * will always be one unit. Nevertheless, dbus API allows for multiple
629 * values, so let's follow that.*/
632 /* The strv above is shared. free is set only in the first one. */
636 static int socket_info_compare(struct socket_info *a, struct socket_info *b) {
637 int o = strcmp(a->path, b->path);
639 o = strcmp(a->type, b->type);
643 static int output_sockets_list(struct socket_info *socket_infos, unsigned cs) {
644 struct socket_info *s;
645 unsigned pathlen = sizeof("LISTEN") - 1,
646 typelen = (sizeof("TYPE") - 1) * arg_show_types,
647 socklen = sizeof("UNIT") - 1,
648 servlen = sizeof("ACTIVATES") - 1;
649 const char *on, *off;
651 for (s = socket_infos; s < socket_infos + cs; s++) {
655 socklen = MAX(socklen, strlen(s->id));
657 typelen = MAX(typelen, strlen(s->type));
658 pathlen = MAX(pathlen, strlen(s->path));
660 STRV_FOREACH(a, s->triggered)
661 tmp += strlen(*a) + 2*(a != s->triggered);
662 servlen = MAX(servlen, tmp);
667 printf("%-*s %-*.*s%-*s %s\n",
669 typelen + arg_show_types, typelen + arg_show_types, "TYPE ",
673 for (s = socket_infos; s < socket_infos + cs; s++) {
677 printf("%-*s %-*s %-*s",
678 pathlen, s->path, typelen, s->type, socklen, s->id);
681 pathlen, s->path, socklen, s->id);
682 STRV_FOREACH(a, s->triggered)
684 a == s->triggered ? "" : ",", *a);
688 on = ansi_highlight(true);
689 off = ansi_highlight(false);
693 on = ansi_highlight_red(true);
694 off = ansi_highlight_red(false);
697 if (!arg_no_legend) {
698 printf("%s%u sockets listed.%s\n", on, cs, off);
700 printf("Pass --all to see loaded but inactive sockets, too.\n");
706 static int list_sockets(DBusConnection *bus, char **args) {
707 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
708 _cleanup_free_ struct unit_info *unit_infos = NULL;
709 struct socket_info *socket_infos = NULL;
710 const struct unit_info *u;
711 struct socket_info *s;
712 unsigned cu = 0, cs = 0;
716 pager_open_if_enabled();
718 r = get_unit_list(bus, &reply, &unit_infos, &cu);
722 for (u = unit_infos; u < unit_infos + cu; u++) {
724 _cleanup_strv_free_ char **listen = NULL, **triggered = NULL;
727 if (!output_show_unit(u))
730 if ((dot = strrchr(u->id, '.')) && !streq(dot+1, "socket"))
733 r = get_triggered_units(bus, u->unit_path, &triggered);
737 r = get_listening(bus, u->unit_path, &listen, &c);
741 if (!GREEDY_REALLOC(socket_infos, size, cs + c)) {
746 for (i = 0; i < c; i++)
747 socket_infos[cs + i] = (struct socket_info) {
750 .path = listen[i*2 + 1],
751 .triggered = triggered,
752 .own_triggered = i==0,
755 /* from this point on we will cleanup those socket_infos */
758 listen = triggered = NULL; /* avoid cleanup */
761 qsort(socket_infos, cs, sizeof(struct socket_info),
762 (__compar_fn_t) socket_info_compare);
764 output_sockets_list(socket_infos, cs);
767 assert(cs == 0 || socket_infos);
768 for (s = socket_infos; s < socket_infos + cs; s++) {
771 if (s->own_triggered)
772 strv_free(s->triggered);
779 static int compare_unit_file_list(const void *a, const void *b) {
781 const UnitFileList *u = a, *v = b;
783 d1 = strrchr(u->path, '.');
784 d2 = strrchr(v->path, '.');
789 r = strcasecmp(d1, d2);
794 return strcasecmp(path_get_file_name(u->path), path_get_file_name(v->path));
797 static bool output_show_unit_file(const UnitFileList *u) {
800 return !arg_types || ((dot = strrchr(u->path, '.')) && strv_find(arg_types, dot+1));
803 static void output_unit_file_list(const UnitFileList *units, unsigned c) {
804 unsigned max_id_len, id_cols, state_cols, n_shown = 0;
805 const UnitFileList *u;
807 max_id_len = sizeof("UNIT FILE")-1;
808 state_cols = sizeof("STATE")-1;
809 for (u = units; u < units + c; u++) {
810 if (!output_show_unit_file(u))
813 max_id_len = MAX(max_id_len, strlen(path_get_file_name(u->path)));
814 state_cols = MAX(state_cols, strlen(unit_file_state_to_string(u->state)));
819 id_cols = MIN(max_id_len, 25u);
820 basic_cols = 1 + id_cols + state_cols;
821 if (basic_cols < (unsigned) columns())
822 id_cols += MIN(columns() - basic_cols, max_id_len - id_cols);
824 id_cols = max_id_len;
827 printf("%-*s %-*s\n", id_cols, "UNIT FILE", state_cols, "STATE");
829 for (u = units; u < units + c; u++) {
830 _cleanup_free_ char *e = NULL;
831 const char *on, *off;
834 if (!output_show_unit_file(u))
839 if (u->state == UNIT_FILE_MASKED ||
840 u->state == UNIT_FILE_MASKED_RUNTIME ||
841 u->state == UNIT_FILE_DISABLED ||
842 u->state == UNIT_FILE_INVALID) {
843 on = ansi_highlight_red(true);
844 off = ansi_highlight_red(false);
845 } else if (u->state == UNIT_FILE_ENABLED) {
846 on = ansi_highlight_green(true);
847 off = ansi_highlight_green(false);
851 id = path_get_file_name(u->path);
853 e = arg_full ? NULL : ellipsize(id, id_cols, 33);
855 printf("%-*s %s%-*s%s\n",
857 on, state_cols, unit_file_state_to_string(u->state), off);
861 printf("\n%u unit files listed.\n", n_shown);
864 static int list_unit_files(DBusConnection *bus, char **args) {
865 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
866 _cleanup_free_ UnitFileList *units = NULL;
867 DBusMessageIter iter, sub, sub2;
868 unsigned c = 0, n_units = 0;
871 pager_open_if_enabled();
878 h = hashmap_new(string_hash_func, string_compare_func);
882 r = unit_file_get_list(arg_scope, arg_root, h);
884 unit_file_list_free(h);
885 log_error("Failed to get unit file list: %s", strerror(-r));
889 n_units = hashmap_size(h);
890 units = new(UnitFileList, n_units);
892 unit_file_list_free(h);
896 HASHMAP_FOREACH(u, h, i) {
897 memcpy(units + c++, u, sizeof(UnitFileList));
903 r = bus_method_call_with_reply(
905 "org.freedesktop.systemd1",
906 "/org/freedesktop/systemd1",
907 "org.freedesktop.systemd1.Manager",
915 if (!dbus_message_iter_init(reply, &iter) ||
916 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
917 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
918 log_error("Failed to parse reply.");
922 dbus_message_iter_recurse(&iter, &sub);
924 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
928 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT);
933 n_units = MAX(2*c, 16u);
934 w = realloc(units, sizeof(struct UnitFileList) * n_units);
943 dbus_message_iter_recurse(&sub, &sub2);
945 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->path, true) < 0 ||
946 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, false) < 0) {
947 log_error("Failed to parse reply.");
951 u->state = unit_file_state_from_string(state);
953 dbus_message_iter_next(&sub);
959 qsort(units, c, sizeof(UnitFileList), compare_unit_file_list);
960 output_unit_file_list(units, c);
966 static int list_dependencies_print(const char *name, int level, unsigned int branches, bool last) {
968 _cleanup_free_ char *n = NULL;
970 size_t max_len = MAX(columns(),20u);
973 for (i = level - 1; i >= 0; i--) {
975 if(len > max_len - 3 && !arg_full) {
976 printf("%s...\n",max_len % 2 ? "" : " ");
979 printf("%s", draw_special_char(branches & (1 << i) ? DRAW_TREE_VERT : DRAW_TREE_SPACE));
982 if(len > max_len - 3 && !arg_full) {
983 printf("%s...\n",max_len % 2 ? "" : " ");
986 printf("%s", draw_special_char(last ? DRAW_TREE_RIGHT : DRAW_TREE_BRANCH));
990 printf("%s\n", name);
994 n = ellipsize(name, max_len-len, 100);
1002 static int list_dependencies_get_dependencies(DBusConnection *bus, const char *name, char ***deps) {
1003 static const char *dependencies[] = {
1004 [DEPENDENCY_FORWARD] = "Requires\0"
1005 "RequiresOverridable\0"
1007 "RequisiteOverridable\0"
1009 [DEPENDENCY_REVERSE] = "RequiredBy\0"
1010 "RequiredByOverridable\0"
1013 [DEPENDENCY_AFTER] = "After\0",
1014 [DEPENDENCY_BEFORE] = "Before\0",
1017 _cleanup_free_ char *path;
1018 const char *interface = "org.freedesktop.systemd1.Unit";
1020 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1021 DBusMessageIter iter, sub, sub2, sub3;
1030 path = unit_dbus_path_from_name(name);
1036 r = bus_method_call_with_reply(
1038 "org.freedesktop.systemd1",
1040 "org.freedesktop.DBus.Properties",
1044 DBUS_TYPE_STRING, &interface,
1049 if (!dbus_message_iter_init(reply, &iter) ||
1050 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
1051 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
1052 log_error("Failed to parse reply.");
1057 dbus_message_iter_recurse(&iter, &sub);
1059 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1062 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_DICT_ENTRY);
1063 dbus_message_iter_recurse(&sub, &sub2);
1065 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &prop, true) < 0) {
1066 log_error("Failed to parse reply.");
1071 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
1072 log_error("Failed to parse reply.");
1077 dbus_message_iter_recurse(&sub2, &sub3);
1078 dbus_message_iter_next(&sub);
1080 assert(arg_dependency < ELEMENTSOF(dependencies));
1081 if (!nulstr_contains(dependencies[arg_dependency], prop))
1084 if (dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_ARRAY) {
1085 if (dbus_message_iter_get_element_type(&sub3) == DBUS_TYPE_STRING) {
1086 DBusMessageIter sub4;
1087 dbus_message_iter_recurse(&sub3, &sub4);
1089 while (dbus_message_iter_get_arg_type(&sub4) != DBUS_TYPE_INVALID) {
1092 assert(dbus_message_iter_get_arg_type(&sub4) == DBUS_TYPE_STRING);
1093 dbus_message_iter_get_basic(&sub4, &s);
1095 r = strv_extend(&ret, s);
1101 dbus_message_iter_next(&sub4);
1114 static int list_dependencies_compare(const void *_a, const void *_b) {
1115 const char **a = (const char**) _a, **b = (const char**) _b;
1116 if (unit_name_to_type(*a) == UNIT_TARGET && unit_name_to_type(*b) != UNIT_TARGET)
1118 if (unit_name_to_type(*a) != UNIT_TARGET && unit_name_to_type(*b) == UNIT_TARGET)
1120 return strcasecmp(*a, *b);
1123 static int list_dependencies_one(DBusConnection *bus, const char *name, int level, char ***units, unsigned int branches) {
1124 _cleanup_strv_free_ char **deps = NULL, **u;
1128 u = strv_append(*units, name);
1132 r = list_dependencies_get_dependencies(bus, name, &deps);
1136 qsort(deps, strv_length(deps), sizeof (char*), list_dependencies_compare);
1138 STRV_FOREACH(c, deps) {
1139 if (strv_contains(u, *c)) {
1141 r = list_dependencies_print("...", level + 1, (branches << 1) | (c[1] == NULL ? 0 : 1), 1);
1148 r = list_dependencies_print(*c, level, branches, c[1] == NULL);
1152 if (arg_all || unit_name_to_type(*c) == UNIT_TARGET) {
1153 r = list_dependencies_one(bus, *c, level + 1, &u, (branches << 1) | (c[1] == NULL ? 0 : 1));
1166 static int list_dependencies(DBusConnection *bus, char **args) {
1167 _cleanup_free_ char *unit = NULL;
1168 _cleanup_strv_free_ char **units = NULL;
1174 unit = unit_name_mangle(args[1]);
1179 u = SPECIAL_DEFAULT_TARGET;
1181 pager_open_if_enabled();
1185 return list_dependencies_one(bus, u, 0, &units, 0);
1188 static int get_default(DBusConnection *bus, char **args) {
1190 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1192 _cleanup_dbus_error_free_ DBusError error;
1194 dbus_error_init(&error);
1196 if (!bus || avoid_bus()) {
1197 r = unit_file_get_default(arg_scope, arg_root, &path);
1200 log_error("Operation failed: %s", strerror(-r));
1206 r = bus_method_call_with_reply(
1208 "org.freedesktop.systemd1",
1209 "/org/freedesktop/systemd1",
1210 "org.freedesktop.systemd1.Manager",
1217 log_error("Operation failed: %s", strerror(-r));
1221 if (!dbus_message_get_args(reply, &error,
1222 DBUS_TYPE_STRING, &path,
1223 DBUS_TYPE_INVALID)) {
1224 log_error("Failed to parse reply: %s", bus_error_message(&error));
1225 dbus_error_free(&error);
1231 printf("%s\n", path);
1234 if ((!bus || avoid_bus()) && path)
1243 char *name, *type, *state;
1246 static void list_jobs_print(struct job_info* jobs, size_t n) {
1249 const char *on, *off;
1250 bool shorten = false;
1252 assert(n == 0 || jobs);
1255 on = ansi_highlight_green(true);
1256 off = ansi_highlight_green(false);
1258 printf("%sNo jobs running.%s\n", on, off);
1262 pager_open_if_enabled();
1265 /* JOB UNIT TYPE STATE */
1266 unsigned l0 = 3, l1 = 4, l2 = 4, l3 = 5;
1268 for (i = 0, j = jobs; i < n; i++, j++) {
1269 assert(j->name && j->type && j->state);
1270 l0 = MAX(l0, DECIMAL_STR_WIDTH(j->id));
1271 l1 = MAX(l1, strlen(j->name));
1272 l2 = MAX(l2, strlen(j->type));
1273 l3 = MAX(l3, strlen(j->state));
1276 if (!arg_full && l0 + 1 + l1 + l2 + 1 + l3 > columns()) {
1277 l1 = MAX(33u, columns() - l0 - l2 - l3 - 3);
1282 printf("%*s %-*s %-*s %-*s\n",
1288 for (i = 0, j = jobs; i < n; i++, j++) {
1289 _cleanup_free_ char *e = NULL;
1291 if (streq(j->state, "running")) {
1292 on = ansi_highlight(true);
1293 off = ansi_highlight(false);
1297 e = shorten ? ellipsize(j->name, l1, 33) : NULL;
1298 printf("%*u %s%-*s%s %-*s %s%-*s%s\n",
1300 on, l1, e ? e : j->name, off,
1302 on, l3, j->state, off);
1306 on = ansi_highlight(true);
1307 off = ansi_highlight(false);
1310 printf("\n%s%zu jobs listed%s.\n", on, n, off);
1313 static int list_jobs(DBusConnection *bus, char **args) {
1314 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1315 DBusMessageIter iter, sub, sub2;
1317 struct job_info *jobs = NULL;
1318 size_t size = 0, used = 0;
1320 r = bus_method_call_with_reply(
1322 "org.freedesktop.systemd1",
1323 "/org/freedesktop/systemd1",
1324 "org.freedesktop.systemd1.Manager",
1332 if (!dbus_message_iter_init(reply, &iter) ||
1333 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
1334 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
1335 log_error("Failed to parse reply.");
1339 dbus_message_iter_recurse(&iter, &sub);
1341 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1342 const char *name, *type, *state, *job_path, *unit_path;
1345 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
1346 log_error("Failed to parse reply.");
1350 dbus_message_iter_recurse(&sub, &sub2);
1352 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &id, true) < 0 ||
1353 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
1354 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
1355 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, true) < 0 ||
1356 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &job_path, true) < 0 ||
1357 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, false) < 0) {
1358 log_error("Failed to parse reply.");
1363 if (!GREEDY_REALLOC(jobs, size, used + 1)) {
1368 jobs[used++] = (struct job_info) { id,
1372 if (!jobs[used-1].name || !jobs[used-1].type || !jobs[used-1].state) {
1377 dbus_message_iter_next(&sub);
1380 list_jobs_print(jobs, used);
1384 free(jobs[used].name);
1385 free(jobs[used].type);
1386 free(jobs[used].state);
1393 static int load_unit(DBusConnection *bus, char **args) {
1398 STRV_FOREACH(name, args+1) {
1399 _cleanup_free_ char *n = NULL;
1402 n = unit_name_mangle(*name);
1406 r = bus_method_call_with_reply(
1408 "org.freedesktop.systemd1",
1409 "/org/freedesktop/systemd1",
1410 "org.freedesktop.systemd1.Manager",
1414 DBUS_TYPE_STRING, &n,
1423 static int cancel_job(DBusConnection *bus, char **args) {
1428 if (strv_length(args) <= 1)
1429 return daemon_reload(bus, args);
1431 STRV_FOREACH(name, args+1) {
1435 r = safe_atou32(*name, &id);
1437 log_error("Failed to parse job id: %s", strerror(-r));
1441 r = bus_method_call_with_reply(
1443 "org.freedesktop.systemd1",
1444 "/org/freedesktop/systemd1",
1445 "org.freedesktop.systemd1.Manager",
1449 DBUS_TYPE_UINT32, &id,
1458 static int need_daemon_reload(DBusConnection *bus, const char *unit) {
1459 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1460 _cleanup_dbus_error_free_ DBusError error;
1461 dbus_bool_t b = FALSE;
1462 DBusMessageIter iter, sub;
1464 *interface = "org.freedesktop.systemd1.Unit",
1465 *property = "NeedDaemonReload",
1467 _cleanup_free_ char *n = NULL;
1470 dbus_error_init(&error);
1472 /* We ignore all errors here, since this is used to show a warning only */
1474 n = unit_name_mangle(unit);
1478 r = bus_method_call_with_reply(
1480 "org.freedesktop.systemd1",
1481 "/org/freedesktop/systemd1",
1482 "org.freedesktop.systemd1.Manager",
1486 DBUS_TYPE_STRING, &n,
1491 if (!dbus_message_get_args(reply, NULL,
1492 DBUS_TYPE_OBJECT_PATH, &path,
1496 dbus_message_unref(reply);
1499 r = bus_method_call_with_reply(
1501 "org.freedesktop.systemd1",
1503 "org.freedesktop.DBus.Properties",
1507 DBUS_TYPE_STRING, &interface,
1508 DBUS_TYPE_STRING, &property,
1513 if (!dbus_message_iter_init(reply, &iter) ||
1514 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
1517 dbus_message_iter_recurse(&iter, &sub);
1518 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_BOOLEAN)
1521 dbus_message_iter_get_basic(&sub, &b);
1525 typedef struct WaitData {
1532 static DBusHandlerResult wait_filter(DBusConnection *connection, DBusMessage *message, void *data) {
1533 _cleanup_dbus_error_free_ DBusError error;
1536 dbus_error_init(&error);
1542 log_debug("Got D-Bus request: %s.%s() on %s",
1543 dbus_message_get_interface(message),
1544 dbus_message_get_member(message),
1545 dbus_message_get_path(message));
1547 if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
1548 log_error("Warning! D-Bus connection terminated.");
1549 dbus_connection_close(connection);
1551 } else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
1553 const char *path, *result, *unit;
1555 if (dbus_message_get_args(message, &error,
1556 DBUS_TYPE_UINT32, &id,
1557 DBUS_TYPE_OBJECT_PATH, &path,
1558 DBUS_TYPE_STRING, &unit,
1559 DBUS_TYPE_STRING, &result,
1560 DBUS_TYPE_INVALID)) {
1562 free(set_remove(d->set, (char*) path));
1564 if (!isempty(result))
1565 d->result = strdup(result);
1568 d->name = strdup(unit);
1570 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1573 dbus_error_free(&error);
1574 if (dbus_message_get_args(message, &error,
1575 DBUS_TYPE_UINT32, &id,
1576 DBUS_TYPE_OBJECT_PATH, &path,
1577 DBUS_TYPE_STRING, &result,
1578 DBUS_TYPE_INVALID)) {
1579 /* Compatibility with older systemd versions <
1580 * 183 during upgrades. This should be dropped
1582 free(set_remove(d->set, (char*) path));
1585 d->result = strdup(result);
1587 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1591 log_error("Failed to parse message: %s", bus_error_message(&error));
1594 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1597 static int enable_wait_for_jobs(DBusConnection *bus) {
1605 dbus_error_init(&error);
1606 dbus_bus_add_match(bus,
1608 "sender='org.freedesktop.systemd1',"
1609 "interface='org.freedesktop.systemd1.Manager',"
1610 "member='JobRemoved',"
1611 "path='/org/freedesktop/systemd1'",
1614 if (dbus_error_is_set(&error)) {
1615 log_error("Failed to add match: %s", bus_error_message(&error));
1616 dbus_error_free(&error);
1620 /* This is slightly dirty, since we don't undo the match registrations. */
1624 static int wait_for_jobs(DBusConnection *bus, Set *s) {
1626 WaitData d = { .set = s };
1631 if (!dbus_connection_add_filter(bus, wait_filter, &d, NULL))
1634 while (!set_isempty(s)) {
1636 if (!dbus_connection_read_write_dispatch(bus, -1)) {
1637 log_error("Disconnected from bus.");
1638 return -ECONNREFUSED;
1645 if (streq(d.result, "timeout"))
1646 log_error("Job for %s timed out.", strna(d.name));
1647 else if (streq(d.result, "canceled"))
1648 log_error("Job for %s canceled.", strna(d.name));
1649 else if (streq(d.result, "dependency"))
1650 log_error("A dependency job for %s failed. See 'journalctl -xn' for details.", strna(d.name));
1651 else if (!streq(d.result, "done") && !streq(d.result, "skipped"))
1652 log_error("Job for %s failed. See 'systemctl status %s' and 'journalctl -xn' for details.", strna(d.name), strna(d.name));
1655 if (streq_ptr(d.result, "timeout"))
1657 else if (streq_ptr(d.result, "canceled"))
1659 else if (!streq_ptr(d.result, "done") && !streq_ptr(d.result, "skipped"))
1670 dbus_connection_remove_filter(bus, wait_filter, &d);
1674 static int check_one_unit(DBusConnection *bus, const char *name, char **check_states, bool quiet) {
1675 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1676 _cleanup_free_ char *n = NULL;
1677 DBusMessageIter iter, sub;
1679 *interface = "org.freedesktop.systemd1.Unit",
1680 *property = "ActiveState";
1681 const char *state, *path;
1687 dbus_error_init(&error);
1689 n = unit_name_mangle(name);
1693 r = bus_method_call_with_reply (
1695 "org.freedesktop.systemd1",
1696 "/org/freedesktop/systemd1",
1697 "org.freedesktop.systemd1.Manager",
1701 DBUS_TYPE_STRING, &n,
1704 dbus_error_free(&error);
1711 if (!dbus_message_get_args(reply, NULL,
1712 DBUS_TYPE_OBJECT_PATH, &path,
1713 DBUS_TYPE_INVALID)) {
1714 log_error("Failed to parse reply.");
1718 dbus_message_unref(reply);
1721 r = bus_method_call_with_reply(
1723 "org.freedesktop.systemd1",
1725 "org.freedesktop.DBus.Properties",
1729 DBUS_TYPE_STRING, &interface,
1730 DBUS_TYPE_STRING, &property,
1738 if (!dbus_message_iter_init(reply, &iter) ||
1739 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1740 log_error("Failed to parse reply.");
1744 dbus_message_iter_recurse(&iter, &sub);
1746 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1747 log_error("Failed to parse reply.");
1751 dbus_message_iter_get_basic(&sub, &state);
1756 return strv_find(check_states, state) ? 1 : 0;
1759 static void check_triggering_units(
1760 DBusConnection *bus,
1761 const char *unit_name) {
1763 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1764 DBusMessageIter iter, sub;
1765 const char *interface = "org.freedesktop.systemd1.Unit",
1766 *load_state_property = "LoadState",
1767 *triggered_by_property = "TriggeredBy",
1769 _cleanup_free_ char *unit_path = NULL, *n = NULL;
1770 bool print_warning_label = true;
1773 n = unit_name_mangle(unit_name);
1779 unit_path = unit_dbus_path_from_name(n);
1785 r = bus_method_call_with_reply(
1787 "org.freedesktop.systemd1",
1789 "org.freedesktop.DBus.Properties",
1793 DBUS_TYPE_STRING, &interface,
1794 DBUS_TYPE_STRING, &load_state_property,
1799 if (!dbus_message_iter_init(reply, &iter) ||
1800 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1801 log_error("Failed to parse reply.");
1805 dbus_message_iter_recurse(&iter, &sub);
1807 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1808 log_error("Failed to parse reply.");
1812 dbus_message_iter_get_basic(&sub, &state);
1814 if (streq(state, "masked"))
1817 dbus_message_unref(reply);
1820 r = bus_method_call_with_reply(
1822 "org.freedesktop.systemd1",
1824 "org.freedesktop.DBus.Properties",
1828 DBUS_TYPE_STRING, &interface,
1829 DBUS_TYPE_STRING, &triggered_by_property,
1834 if (!dbus_message_iter_init(reply, &iter) ||
1835 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1836 log_error("Failed to parse reply.");
1840 dbus_message_iter_recurse(&iter, &sub);
1841 dbus_message_iter_recurse(&sub, &iter);
1844 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1845 const char * const check_states[] = {
1850 const char *service_trigger;
1852 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1853 log_error("Failed to parse reply.");
1857 dbus_message_iter_get_basic(&sub, &service_trigger);
1859 r = check_one_unit(bus, service_trigger, (char**) check_states, true);
1863 if (print_warning_label) {
1864 log_warning("Warning: Stopping %s, but it can still be activated by:", unit_name);
1865 print_warning_label = false;
1868 log_warning(" %s", service_trigger);
1871 dbus_message_iter_next(&sub);
1875 static int start_unit_one(
1876 DBusConnection *bus,
1883 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1884 _cleanup_free_ char *n;
1893 n = unit_name_mangle(name);
1897 r = bus_method_call_with_reply(
1899 "org.freedesktop.systemd1",
1900 "/org/freedesktop/systemd1",
1901 "org.freedesktop.systemd1.Manager",
1905 DBUS_TYPE_STRING, &n,
1906 DBUS_TYPE_STRING, &mode,
1909 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
1910 /* There's always a fallback possible for
1911 * legacy actions. */
1914 log_error("Failed to issue method call: %s", bus_error_message(error));
1919 if (!dbus_message_get_args(reply, error,
1920 DBUS_TYPE_OBJECT_PATH, &path,
1921 DBUS_TYPE_INVALID)) {
1922 log_error("Failed to parse reply: %s", bus_error_message(error));
1926 if (need_daemon_reload(bus, n) > 0)
1927 log_warning("Warning: Unit file of %s changed on disk, 'systemctl %sdaemon-reload' recommended.",
1928 n, arg_scope == UNIT_FILE_SYSTEM ? "" : "--user ");
1937 r = set_consume(s, p);
1939 log_error("Failed to add path to set.");
1947 static const struct {
1951 } action_table[_ACTION_MAX] = {
1952 [ACTION_HALT] = { SPECIAL_HALT_TARGET, "halt", "replace-irreversibly" },
1953 [ACTION_POWEROFF] = { SPECIAL_POWEROFF_TARGET, "poweroff", "replace-irreversibly" },
1954 [ACTION_REBOOT] = { SPECIAL_REBOOT_TARGET, "reboot", "replace-irreversibly" },
1955 [ACTION_KEXEC] = { SPECIAL_KEXEC_TARGET, "kexec", "replace-irreversibly" },
1956 [ACTION_RUNLEVEL2] = { SPECIAL_RUNLEVEL2_TARGET, NULL, "isolate" },
1957 [ACTION_RUNLEVEL3] = { SPECIAL_RUNLEVEL3_TARGET, NULL, "isolate" },
1958 [ACTION_RUNLEVEL4] = { SPECIAL_RUNLEVEL4_TARGET, NULL, "isolate" },
1959 [ACTION_RUNLEVEL5] = { SPECIAL_RUNLEVEL5_TARGET, NULL, "isolate" },
1960 [ACTION_RESCUE] = { SPECIAL_RESCUE_TARGET, "rescue", "isolate" },
1961 [ACTION_EMERGENCY] = { SPECIAL_EMERGENCY_TARGET, "emergency", "isolate" },
1962 [ACTION_DEFAULT] = { SPECIAL_DEFAULT_TARGET, "default", "isolate" },
1963 [ACTION_EXIT] = { SPECIAL_EXIT_TARGET, "exit", "replace-irreversibly" },
1964 [ACTION_SUSPEND] = { SPECIAL_SUSPEND_TARGET, "suspend", "replace-irreversibly" },
1965 [ACTION_HIBERNATE] = { SPECIAL_HIBERNATE_TARGET, "hibernate", "replace-irreversibly" },
1966 [ACTION_HYBRID_SLEEP] = { SPECIAL_HYBRID_SLEEP_TARGET, "hybrid-sleep", "replace-irreversibly" },
1969 static enum action verb_to_action(const char *verb) {
1972 for (i = ACTION_INVALID; i < _ACTION_MAX; i++)
1973 if (action_table[i].verb && streq(verb, action_table[i].verb))
1975 return ACTION_INVALID;
1978 static int start_unit(DBusConnection *bus, char **args) {
1981 const char *method, *mode, *one_name;
1982 _cleanup_set_free_free_ Set *s = NULL;
1983 _cleanup_dbus_error_free_ DBusError error;
1986 dbus_error_init(&error);
1990 ask_password_agent_open_if_enabled();
1992 if (arg_action == ACTION_SYSTEMCTL) {
1995 streq(args[0], "stop") ||
1996 streq(args[0], "condstop") ? "StopUnit" :
1997 streq(args[0], "reload") ? "ReloadUnit" :
1998 streq(args[0], "restart") ? "RestartUnit" :
2000 streq(args[0], "try-restart") ||
2001 streq(args[0], "condrestart") ? "TryRestartUnit" :
2003 streq(args[0], "reload-or-restart") ? "ReloadOrRestartUnit" :
2005 streq(args[0], "reload-or-try-restart") ||
2006 streq(args[0], "condreload") ||
2008 streq(args[0], "force-reload") ? "ReloadOrTryRestartUnit" :
2010 action = verb_to_action(args[0]);
2012 mode = streq(args[0], "isolate") ? "isolate" :
2013 action_table[action].mode ?: arg_job_mode;
2015 one_name = action_table[action].target;
2018 assert(arg_action < ELEMENTSOF(action_table));
2019 assert(action_table[arg_action].target);
2021 method = "StartUnit";
2023 mode = action_table[arg_action].mode;
2024 one_name = action_table[arg_action].target;
2027 if (!arg_no_block) {
2028 ret = enable_wait_for_jobs(bus);
2030 log_error("Could not watch jobs: %s", strerror(-ret));
2034 s = set_new(string_hash_func, string_compare_func);
2040 ret = start_unit_one(bus, method, one_name, mode, &error, s);
2042 ret = translate_bus_error_to_exit_status(ret, &error);
2044 STRV_FOREACH(name, args+1) {
2045 r = start_unit_one(bus, method, *name, mode, &error, s);
2047 ret = translate_bus_error_to_exit_status(r, &error);
2048 dbus_error_free(&error);
2053 if (!arg_no_block) {
2054 r = wait_for_jobs(bus, s);
2058 /* When stopping units, warn if they can still be triggered by
2059 * another active unit (socket, path, timer) */
2060 if (!arg_quiet && streq(method, "StopUnit")) {
2062 check_triggering_units(bus, one_name);
2064 STRV_FOREACH(name, args+1)
2065 check_triggering_units(bus, *name);
2072 /* Ask systemd-logind, which might grant access to unprivileged users
2073 * through PolicyKit */
2074 static int reboot_with_logind(DBusConnection *bus, enum action a) {
2077 dbus_bool_t interactive = true;
2082 polkit_agent_open_if_enabled();
2090 case ACTION_POWEROFF:
2091 method = "PowerOff";
2094 case ACTION_SUSPEND:
2098 case ACTION_HIBERNATE:
2099 method = "Hibernate";
2102 case ACTION_HYBRID_SLEEP:
2103 method = "HybridSleep";
2110 return bus_method_call_with_reply(
2112 "org.freedesktop.login1",
2113 "/org/freedesktop/login1",
2114 "org.freedesktop.login1.Manager",
2118 DBUS_TYPE_BOOLEAN, &interactive,
2125 static int check_inhibitors(DBusConnection *bus, enum action a) {
2127 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
2128 DBusMessageIter iter, sub, sub2;
2131 _cleanup_strv_free_ char **sessions = NULL;
2137 if (arg_ignore_inhibitors || arg_force > 0)
2149 r = bus_method_call_with_reply(
2151 "org.freedesktop.login1",
2152 "/org/freedesktop/login1",
2153 "org.freedesktop.login1.Manager",
2159 /* If logind is not around, then there are no inhibitors... */
2162 if (!dbus_message_iter_init(reply, &iter) ||
2163 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
2164 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
2165 log_error("Failed to parse reply.");
2169 dbus_message_iter_recurse(&iter, &sub);
2170 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
2171 const char *what, *who, *why, *mode;
2173 _cleanup_strv_free_ char **sv = NULL;
2174 _cleanup_free_ char *comm = NULL, *user = NULL;
2176 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
2177 log_error("Failed to parse reply.");
2181 dbus_message_iter_recurse(&sub, &sub2);
2183 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &what, true) < 0 ||
2184 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &who, true) < 0 ||
2185 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &why, true) < 0 ||
2186 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &mode, true) < 0 ||
2187 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &uid, true) < 0 ||
2188 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, false) < 0) {
2189 log_error("Failed to parse reply.");
2193 if (!streq(mode, "block"))
2196 sv = strv_split(what, ":");
2200 if (!strv_contains(sv,
2202 a == ACTION_POWEROFF ||
2203 a == ACTION_REBOOT ||
2204 a == ACTION_KEXEC ? "shutdown" : "sleep"))
2207 get_process_comm(pid, &comm);
2208 user = uid_to_name(uid);
2209 log_warning("Operation inhibited by \"%s\" (PID %lu \"%s\", user %s), reason is \"%s\".",
2210 who, (unsigned long) pid, strna(comm), strna(user), why);
2214 dbus_message_iter_next(&sub);
2217 dbus_message_iter_recurse(&iter, &sub);
2219 /* Check for current sessions */
2220 sd_get_sessions(&sessions);
2221 STRV_FOREACH(s, sessions) {
2223 _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL;
2225 if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid())
2228 if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
2231 if (sd_session_get_type(*s, &type) < 0 || (!streq(type, "x11") && !streq(type, "tty")))
2234 sd_session_get_tty(*s, &tty);
2235 sd_session_get_seat(*s, &seat);
2236 sd_session_get_service(*s, &service);
2237 user = uid_to_name(uid);
2239 log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty);
2246 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
2247 action_table[a].verb);
2255 static int start_special(DBusConnection *bus, char **args) {
2261 a = verb_to_action(args[0]);
2263 r = check_inhibitors(bus, a);
2267 if (arg_force >= 2 && geteuid() != 0) {
2268 log_error("Must be root.");
2272 if (arg_force >= 2 &&
2273 (a == ACTION_HALT ||
2274 a == ACTION_POWEROFF ||
2275 a == ACTION_REBOOT))
2278 if (arg_force >= 1 &&
2279 (a == ACTION_HALT ||
2280 a == ACTION_POWEROFF ||
2281 a == ACTION_REBOOT ||
2282 a == ACTION_KEXEC ||
2284 return daemon_reload(bus, args);
2286 /* first try logind, to allow authentication with polkit */
2287 if (geteuid() != 0 &&
2288 (a == ACTION_POWEROFF ||
2289 a == ACTION_REBOOT ||
2290 a == ACTION_SUSPEND ||
2291 a == ACTION_HIBERNATE ||
2292 a == ACTION_HYBRID_SLEEP)) {
2293 r = reboot_with_logind(bus, a);
2298 r = start_unit(bus, args);
2299 if (r == EXIT_SUCCESS)
2305 static int check_unit_active(DBusConnection *bus, char **args) {
2306 const char * const check_states[] = {
2313 int r = 3; /* According to LSB: "program is not running" */
2318 STRV_FOREACH(name, args+1) {
2321 state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
2331 static int check_unit_failed(DBusConnection *bus, char **args) {
2332 const char * const check_states[] = {
2343 STRV_FOREACH(name, args+1) {
2346 state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
2356 static int kill_unit(DBusConnection *bus, char **args) {
2364 arg_kill_who = "all";
2366 STRV_FOREACH(name, args+1) {
2367 _cleanup_free_ char *n = NULL;
2369 n = unit_name_mangle(*name);
2373 r = bus_method_call_with_reply(
2375 "org.freedesktop.systemd1",
2376 "/org/freedesktop/systemd1",
2377 "org.freedesktop.systemd1.Manager",
2381 DBUS_TYPE_STRING, &n,
2382 DBUS_TYPE_STRING, &arg_kill_who,
2383 DBUS_TYPE_INT32, &arg_signal,
2391 typedef struct ExecStatusInfo {
2399 usec_t start_timestamp;
2400 usec_t exit_timestamp;
2405 LIST_FIELDS(struct ExecStatusInfo, exec);
2408 static void exec_status_info_free(ExecStatusInfo *i) {
2417 static int exec_status_info_deserialize(DBusMessageIter *sub, ExecStatusInfo *i) {
2418 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
2419 DBusMessageIter sub2, sub3;
2423 int32_t code, status;
2429 if (dbus_message_iter_get_arg_type(sub) != DBUS_TYPE_STRUCT)
2432 dbus_message_iter_recurse(sub, &sub2);
2434 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0)
2437 i->path = strdup(path);
2441 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_ARRAY ||
2442 dbus_message_iter_get_element_type(&sub2) != DBUS_TYPE_STRING)
2446 dbus_message_iter_recurse(&sub2, &sub3);
2447 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2448 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2449 dbus_message_iter_next(&sub3);
2453 i->argv = new0(char*, n+1);
2458 dbus_message_iter_recurse(&sub2, &sub3);
2459 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2462 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2463 dbus_message_iter_get_basic(&sub3, &s);
2464 dbus_message_iter_next(&sub3);
2466 i->argv[n] = strdup(s);
2473 if (!dbus_message_iter_next(&sub2) ||
2474 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, true) < 0 ||
2475 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp, true) < 0 ||
2476 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp_monotonic, true) < 0 ||
2477 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp, true) < 0 ||
2478 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp_monotonic, true) < 0 ||
2479 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, true) < 0 ||
2480 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &code, true) < 0 ||
2481 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &status, false) < 0)
2485 i->start_timestamp = (usec_t) start_timestamp;
2486 i->exit_timestamp = (usec_t) exit_timestamp;
2487 i->pid = (pid_t) pid;
2494 typedef struct UnitStatusInfo {
2496 const char *load_state;
2497 const char *active_state;
2498 const char *sub_state;
2499 const char *unit_file_state;
2501 const char *description;
2502 const char *following;
2504 char **documentation;
2506 const char *fragment_path;
2507 const char *source_path;
2508 const char *control_group;
2510 char **dropin_paths;
2512 const char *load_error;
2515 usec_t inactive_exit_timestamp;
2516 usec_t inactive_exit_timestamp_monotonic;
2517 usec_t active_enter_timestamp;
2518 usec_t active_exit_timestamp;
2519 usec_t inactive_enter_timestamp;
2521 bool need_daemon_reload;
2526 const char *status_text;
2527 const char *pid_file;
2530 usec_t start_timestamp;
2531 usec_t exit_timestamp;
2533 int exit_code, exit_status;
2535 usec_t condition_timestamp;
2536 bool condition_result;
2539 unsigned n_accepted;
2540 unsigned n_connections;
2543 /* Pairs of type, path */
2547 const char *sysfs_path;
2549 /* Mount, Automount */
2555 LIST_HEAD(ExecStatusInfo, exec);
2558 static void print_status_info(UnitStatusInfo *i) {
2560 const char *on, *off, *ss;
2562 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
2563 char since2[FORMAT_TIMESTAMP_MAX], *s2;
2566 arg_all * OUTPUT_SHOW_ALL |
2567 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
2568 on_tty() * OUTPUT_COLOR |
2569 !arg_quiet * OUTPUT_WARN_CUTOFF |
2570 arg_full * OUTPUT_FULL_WIDTH;
2575 /* This shows pretty information about a unit. See
2576 * print_property() for a low-level property printer */
2578 printf("%s", strna(i->id));
2580 if (i->description && !streq_ptr(i->id, i->description))
2581 printf(" - %s", i->description);
2586 printf(" Follow: unit currently follows state of %s\n", i->following);
2588 if (streq_ptr(i->load_state, "error")) {
2589 on = ansi_highlight_red(true);
2590 off = ansi_highlight_red(false);
2594 path = i->source_path ? i->source_path : i->fragment_path;
2597 printf(" Loaded: %s%s%s (Reason: %s)\n",
2598 on, strna(i->load_state), off, i->load_error);
2599 else if (path && i->unit_file_state)
2600 printf(" Loaded: %s%s%s (%s; %s)\n",
2601 on, strna(i->load_state), off, path, i->unit_file_state);
2603 printf(" Loaded: %s%s%s (%s)\n",
2604 on, strna(i->load_state), off, path);
2606 printf(" Loaded: %s%s%s\n",
2607 on, strna(i->load_state), off);
2609 if (!strv_isempty(i->dropin_paths)) {
2614 STRV_FOREACH(dropin, i->dropin_paths) {
2615 if (! dir || last) {
2616 printf(dir ? " " : " Drop-In: ");
2620 if (path_get_parent(*dropin, &dir) < 0) {
2625 printf("%s\n %s", dir,
2626 draw_special_char(DRAW_TREE_RIGHT));
2629 last = ! (*(dropin + 1) && startswith(*(dropin + 1), dir));
2631 printf("%s%s", path_get_file_name(*dropin), last ? "\n" : ", ");
2637 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
2639 if (streq_ptr(i->active_state, "failed")) {
2640 on = ansi_highlight_red(true);
2641 off = ansi_highlight_red(false);
2642 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
2643 on = ansi_highlight_green(true);
2644 off = ansi_highlight_green(false);
2649 printf(" Active: %s%s (%s)%s",
2650 on, strna(i->active_state), ss, off);
2652 printf(" Active: %s%s%s",
2653 on, strna(i->active_state), off);
2655 if (!isempty(i->result) && !streq(i->result, "success"))
2656 printf(" (Result: %s)", i->result);
2658 timestamp = (streq_ptr(i->active_state, "active") ||
2659 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
2660 (streq_ptr(i->active_state, "inactive") ||
2661 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
2662 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
2663 i->active_exit_timestamp;
2665 s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
2666 s2 = format_timestamp(since2, sizeof(since2), timestamp);
2669 printf(" since %s; %s\n", s2, s1);
2671 printf(" since %s\n", s2);
2675 if (!i->condition_result && i->condition_timestamp > 0) {
2676 s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
2677 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
2680 printf(" start condition failed at %s; %s\n", s2, s1);
2682 printf(" start condition failed at %s\n", s2);
2686 printf(" Device: %s\n", i->sysfs_path);
2688 printf(" Where: %s\n", i->where);
2690 printf(" What: %s\n", i->what);
2692 STRV_FOREACH(t, i->documentation)
2693 printf(" %*s %s\n", 9, t == i->documentation ? "Docs:" : "", *t);
2695 STRV_FOREACH_PAIR(t, t2, i->listen)
2696 printf(" %*s %s (%s)\n", 9, t == i->listen ? "Listen:" : "", *t2, *t);
2699 printf(" Accepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
2701 LIST_FOREACH(exec, p, i->exec) {
2702 _cleanup_free_ char *argv = NULL;
2705 /* Only show exited processes here */
2709 argv = strv_join(p->argv, " ");
2710 printf(" Process: %u %s=%s ", p->pid, p->name, strna(argv));
2712 good = is_clean_exit_lsb(p->code, p->status, NULL);
2714 on = ansi_highlight_red(true);
2715 off = ansi_highlight_red(false);
2719 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
2721 if (p->code == CLD_EXITED) {
2724 printf("status=%i", p->status);
2726 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
2731 printf("signal=%s", signal_to_string(p->status));
2733 printf(")%s\n", off);
2735 if (i->main_pid == p->pid &&
2736 i->start_timestamp == p->start_timestamp &&
2737 i->exit_timestamp == p->start_timestamp)
2738 /* Let's not show this twice */
2741 if (p->pid == i->control_pid)
2745 if (i->main_pid > 0 || i->control_pid > 0) {
2746 if (i->main_pid > 0) {
2747 printf(" Main PID: %u", (unsigned) i->main_pid);
2750 _cleanup_free_ char *comm = NULL;
2751 get_process_comm(i->main_pid, &comm);
2753 printf(" (%s)", comm);
2754 } else if (i->exit_code > 0) {
2755 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
2757 if (i->exit_code == CLD_EXITED) {
2760 printf("status=%i", i->exit_status);
2762 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
2767 printf("signal=%s", signal_to_string(i->exit_status));
2771 if (i->control_pid > 0)
2775 if (i->control_pid > 0) {
2776 _cleanup_free_ char *c = NULL;
2778 printf(" %8s: %u", i->main_pid ? "" : " Control", (unsigned) i->control_pid);
2780 get_process_comm(i->control_pid, &c);
2789 printf(" Status: \"%s\"\n", i->status_text);
2791 if (i->control_group &&
2792 (i->main_pid > 0 || i->control_pid > 0 || cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, i->control_group, false) == 0)) {
2795 printf(" CGroup: %s\n", i->control_group);
2797 if (arg_transport != TRANSPORT_SSH) {
2800 char prefix[] = " ";
2803 if (c > sizeof(prefix) - 1)
2804 c -= sizeof(prefix) - 1;
2808 if (i->main_pid > 0)
2809 extra[k++] = i->main_pid;
2811 if (i->control_pid > 0)
2812 extra[k++] = i->control_pid;
2814 show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, i->control_group, prefix,
2815 c, false, extra, k, flags);
2819 if (i->id && arg_transport != TRANSPORT_SSH) {
2821 show_journal_by_unit(stdout,
2825 i->inactive_exit_timestamp_monotonic,
2829 arg_scope == UNIT_FILE_SYSTEM);
2832 if (i->need_daemon_reload)
2833 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %sdaemon-reload' recommended.\n",
2834 ansi_highlight_red(true),
2835 ansi_highlight_red(false),
2836 arg_scope == UNIT_FILE_SYSTEM ? "" : "--user ");
2839 static void show_unit_help(UnitStatusInfo *i) {
2844 if (!i->documentation) {
2845 log_info("Documentation for %s not known.", i->id);
2849 STRV_FOREACH(p, i->documentation) {
2851 if (startswith(*p, "man:")) {
2854 _cleanup_free_ char *page = NULL, *section = NULL;
2855 const char *args[4] = { "man", NULL, NULL, NULL };
2860 if ((*p)[k-1] == ')')
2861 e = strrchr(*p, '(');
2864 page = strndup((*p) + 4, e - *p - 4);
2865 section = strndup(e + 1, *p + k - e - 2);
2866 if (!page || !section) {
2878 log_error("Failed to fork: %m");
2884 execvp(args[0], (char**) args);
2885 log_error("Failed to execute man: %m");
2886 _exit(EXIT_FAILURE);
2889 wait_for_terminate(pid, NULL);
2891 log_info("Can't show: %s", *p);
2895 static int status_property(const char *name, DBusMessageIter *iter, UnitStatusInfo *i) {
2901 switch (dbus_message_iter_get_arg_type(iter)) {
2903 case DBUS_TYPE_STRING: {
2906 dbus_message_iter_get_basic(iter, &s);
2909 if (streq(name, "Id"))
2911 else if (streq(name, "LoadState"))
2913 else if (streq(name, "ActiveState"))
2914 i->active_state = s;
2915 else if (streq(name, "SubState"))
2917 else if (streq(name, "Description"))
2919 else if (streq(name, "FragmentPath"))
2920 i->fragment_path = s;
2921 else if (streq(name, "SourcePath"))
2924 else if (streq(name, "DefaultControlGroup")) {
2926 e = startswith(s, SYSTEMD_CGROUP_CONTROLLER ":");
2928 i->control_group = e;
2931 else if (streq(name, "ControlGroup"))
2932 i->control_group = s;
2933 else if (streq(name, "StatusText"))
2935 else if (streq(name, "PIDFile"))
2937 else if (streq(name, "SysFSPath"))
2939 else if (streq(name, "Where"))
2941 else if (streq(name, "What"))
2943 else if (streq(name, "Following"))
2945 else if (streq(name, "UnitFileState"))
2946 i->unit_file_state = s;
2947 else if (streq(name, "Result"))
2954 case DBUS_TYPE_BOOLEAN: {
2957 dbus_message_iter_get_basic(iter, &b);
2959 if (streq(name, "Accept"))
2961 else if (streq(name, "NeedDaemonReload"))
2962 i->need_daemon_reload = b;
2963 else if (streq(name, "ConditionResult"))
2964 i->condition_result = b;
2969 case DBUS_TYPE_UINT32: {
2972 dbus_message_iter_get_basic(iter, &u);
2974 if (streq(name, "MainPID")) {
2976 i->main_pid = (pid_t) u;
2979 } else if (streq(name, "ControlPID"))
2980 i->control_pid = (pid_t) u;
2981 else if (streq(name, "ExecMainPID")) {
2983 i->main_pid = (pid_t) u;
2984 } else if (streq(name, "NAccepted"))
2986 else if (streq(name, "NConnections"))
2987 i->n_connections = u;
2992 case DBUS_TYPE_INT32: {
2995 dbus_message_iter_get_basic(iter, &j);
2997 if (streq(name, "ExecMainCode"))
2998 i->exit_code = (int) j;
2999 else if (streq(name, "ExecMainStatus"))
3000 i->exit_status = (int) j;
3005 case DBUS_TYPE_UINT64: {
3008 dbus_message_iter_get_basic(iter, &u);
3010 if (streq(name, "ExecMainStartTimestamp"))
3011 i->start_timestamp = (usec_t) u;
3012 else if (streq(name, "ExecMainExitTimestamp"))
3013 i->exit_timestamp = (usec_t) u;
3014 else if (streq(name, "ActiveEnterTimestamp"))
3015 i->active_enter_timestamp = (usec_t) u;
3016 else if (streq(name, "InactiveEnterTimestamp"))
3017 i->inactive_enter_timestamp = (usec_t) u;
3018 else if (streq(name, "InactiveExitTimestamp"))
3019 i->inactive_exit_timestamp = (usec_t) u;
3020 else if (streq(name, "InactiveExitTimestampMonotonic"))
3021 i->inactive_exit_timestamp_monotonic = (usec_t) u;
3022 else if (streq(name, "ActiveExitTimestamp"))
3023 i->active_exit_timestamp = (usec_t) u;
3024 else if (streq(name, "ConditionTimestamp"))
3025 i->condition_timestamp = (usec_t) u;
3030 case DBUS_TYPE_ARRAY: {
3032 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
3033 startswith(name, "Exec")) {
3034 DBusMessageIter sub;
3036 dbus_message_iter_recurse(iter, &sub);
3037 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3038 ExecStatusInfo *info;
3041 if (!(info = new0(ExecStatusInfo, 1)))
3044 if (!(info->name = strdup(name))) {
3049 if ((r = exec_status_info_deserialize(&sub, info)) < 0) {
3054 LIST_PREPEND(ExecStatusInfo, exec, i->exec, info);
3056 dbus_message_iter_next(&sub);
3059 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Listen")) {
3060 DBusMessageIter sub, sub2;
3062 dbus_message_iter_recurse(iter, &sub);
3063 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3064 const char *type, *path;
3066 dbus_message_iter_recurse(&sub, &sub2);
3068 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
3069 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0) {
3072 r = strv_extend(&i->listen, type);
3075 r = strv_extend(&i->listen, path);
3080 dbus_message_iter_next(&sub);
3085 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING && streq(name, "DropInPaths")) {
3086 int r = bus_parse_strv_iter(iter, &i->dropin_paths);
3090 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
3091 streq(name, "Documentation")) {
3093 DBusMessageIter sub;
3095 dbus_message_iter_recurse(iter, &sub);
3096 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING) {
3100 dbus_message_iter_get_basic(&sub, &s);
3102 r = strv_extend(&i->documentation, s);
3106 dbus_message_iter_next(&sub);
3113 case DBUS_TYPE_STRUCT: {
3115 if (streq(name, "LoadError")) {
3116 DBusMessageIter sub;
3117 const char *n, *message;
3120 dbus_message_iter_recurse(iter, &sub);
3122 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &n, true);
3126 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &message, false);
3130 if (!isempty(message))
3131 i->load_error = message;
3141 static int print_property(const char *name, DBusMessageIter *iter) {
3145 /* This is a low-level property printer, see
3146 * print_status_info() for the nicer output */
3148 if (arg_properties && !strv_find(arg_properties, name))
3151 switch (dbus_message_iter_get_arg_type(iter)) {
3153 case DBUS_TYPE_STRUCT: {
3154 DBusMessageIter sub;
3155 dbus_message_iter_recurse(iter, &sub);
3157 if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32 && streq(name, "Job")) {
3160 dbus_message_iter_get_basic(&sub, &u);
3163 printf("%s=%u\n", name, (unsigned) u);
3165 printf("%s=\n", name);
3168 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "Unit")) {
3171 dbus_message_iter_get_basic(&sub, &s);
3173 if (arg_all || s[0])
3174 printf("%s=%s\n", name, s);
3177 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "LoadError")) {
3178 const char *a = NULL, *b = NULL;
3180 if (bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &a, true) >= 0)
3181 bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &b, false);
3183 if (arg_all || !isempty(a) || !isempty(b))
3184 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
3192 case DBUS_TYPE_ARRAY:
3194 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "EnvironmentFiles")) {
3195 DBusMessageIter sub, sub2;
3197 dbus_message_iter_recurse(iter, &sub);
3198 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3202 dbus_message_iter_recurse(&sub, &sub2);
3204 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
3205 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) >= 0)
3206 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
3208 dbus_message_iter_next(&sub);
3213 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Paths")) {
3214 DBusMessageIter sub, sub2;
3216 dbus_message_iter_recurse(iter, &sub);
3218 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3219 const char *type, *path;
3221 dbus_message_iter_recurse(&sub, &sub2);
3223 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
3224 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
3225 printf("%s=%s\n", type, path);
3227 dbus_message_iter_next(&sub);
3232 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Listen")) {
3233 DBusMessageIter sub, sub2;
3235 dbus_message_iter_recurse(iter, &sub);
3236 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3237 const char *type, *path;
3239 dbus_message_iter_recurse(&sub, &sub2);
3241 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
3242 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
3243 printf("Listen%s=%s\n", type, path);
3245 dbus_message_iter_next(&sub);
3250 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Timers")) {
3251 DBusMessageIter sub, sub2;
3253 dbus_message_iter_recurse(iter, &sub);
3254 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3256 uint64_t value, next_elapse;
3258 dbus_message_iter_recurse(&sub, &sub2);
3260 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &base, true) >= 0 &&
3261 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &value, true) >= 0 &&
3262 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &next_elapse, false) >= 0) {
3263 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
3265 printf("%s={ value=%s ; next_elapse=%s }\n",
3267 format_timespan(timespan1, sizeof(timespan1), value, 0),
3268 format_timespan(timespan2, sizeof(timespan2), next_elapse, 0));
3271 dbus_message_iter_next(&sub);
3276 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && startswith(name, "Exec")) {
3277 DBusMessageIter sub;
3279 dbus_message_iter_recurse(iter, &sub);
3280 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3281 ExecStatusInfo info = {};
3283 if (exec_status_info_deserialize(&sub, &info) >= 0) {
3284 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
3285 _cleanup_free_ char *t;
3287 t = strv_join(info.argv, " ");
3289 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
3293 yes_no(info.ignore),
3294 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
3295 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
3296 (unsigned) info. pid,
3297 sigchld_code_to_string(info.code),
3299 info.code == CLD_EXITED ? "" : "/",
3300 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
3304 strv_free(info.argv);
3306 dbus_message_iter_next(&sub);
3311 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "DeviceAllow")) {
3312 DBusMessageIter sub, sub2;
3314 dbus_message_iter_recurse(iter, &sub);
3315 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3316 const char *path, *rwm;
3318 dbus_message_iter_recurse(&sub, &sub2);
3320 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
3321 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &rwm, false) >= 0)
3322 printf("%s=%s %s\n", name, strna(path), strna(rwm));
3324 dbus_message_iter_next(&sub);
3328 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && (streq(name, "BlockIOReadBandwidth") || streq(name, "BlockIOWriteBandwidth"))) {
3329 DBusMessageIter sub, sub2;
3331 dbus_message_iter_recurse(iter, &sub);
3332 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3336 dbus_message_iter_recurse(&sub, &sub2);
3338 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
3339 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &bandwidth, false) >= 0)
3340 printf("%s=%s %" PRIu64 "\n", name, strna(path), bandwidth);
3342 dbus_message_iter_next(&sub);
3351 if (generic_print_property(name, iter, arg_all) > 0)
3355 printf("%s=[unprintable]\n", name);
3360 static int show_one(const char *verb, DBusConnection *bus, const char *path, bool show_properties, bool *new_line) {
3361 _cleanup_free_ DBusMessage *reply = NULL;
3362 const char *interface = "";
3364 DBusMessageIter iter, sub, sub2, sub3;
3365 UnitStatusInfo info = {};
3371 r = bus_method_call_with_reply(
3373 "org.freedesktop.systemd1",
3375 "org.freedesktop.DBus.Properties",
3379 DBUS_TYPE_STRING, &interface,
3384 if (!dbus_message_iter_init(reply, &iter) ||
3385 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3386 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
3387 log_error("Failed to parse reply.");
3391 dbus_message_iter_recurse(&iter, &sub);
3398 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
3401 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_DICT_ENTRY);
3402 dbus_message_iter_recurse(&sub, &sub2);
3404 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
3405 dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
3406 log_error("Failed to parse reply.");
3410 dbus_message_iter_recurse(&sub2, &sub3);
3412 if (show_properties)
3413 r = print_property(name, &sub3);
3415 r = status_property(name, &sub3, &info);
3417 log_error("Failed to parse reply.");
3421 dbus_message_iter_next(&sub);
3426 if (!show_properties) {
3427 if (streq(verb, "help"))
3428 show_unit_help(&info);
3430 print_status_info(&info);
3433 strv_free(info.documentation);
3434 strv_free(info.dropin_paths);
3435 strv_free(info.listen);
3437 if (!streq_ptr(info.active_state, "active") &&
3438 !streq_ptr(info.active_state, "reloading") &&
3439 streq(verb, "status")) {
3440 /* According to LSB: "program not running" */
3441 /* 0: program is running or service is OK
3442 * 1: program is dead and /var/run pid file exists
3443 * 2: program is dead and /var/lock lock file exists
3444 * 3: program is not running
3445 * 4: program or service status is unknown
3447 if (info.pid_file && access(info.pid_file, F_OK) == 0)
3453 while ((p = info.exec)) {
3454 LIST_REMOVE(ExecStatusInfo, exec, info.exec, p);
3455 exec_status_info_free(p);
3461 static int show_one_by_pid(const char *verb, DBusConnection *bus, uint32_t pid, bool *new_line) {
3462 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3463 const char *path = NULL;
3464 _cleanup_dbus_error_free_ DBusError error;
3467 dbus_error_init(&error);
3469 r = bus_method_call_with_reply(
3471 "org.freedesktop.systemd1",
3472 "/org/freedesktop/systemd1",
3473 "org.freedesktop.systemd1.Manager",
3477 DBUS_TYPE_UINT32, &pid,
3482 if (!dbus_message_get_args(reply, &error,
3483 DBUS_TYPE_OBJECT_PATH, &path,
3484 DBUS_TYPE_INVALID)) {
3485 log_error("Failed to parse reply: %s", bus_error_message(&error));
3489 r = show_one(verb, bus, path, false, new_line);
3493 static int show_all(const char* verb, DBusConnection *bus, bool show_properties, bool *new_line) {
3494 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3495 _cleanup_free_ struct unit_info *unit_infos = NULL;
3497 const struct unit_info *u;
3500 r = get_unit_list(bus, &reply, &unit_infos, &c);
3504 qsort(unit_infos, c, sizeof(struct unit_info), compare_unit_info);
3506 for (u = unit_infos; u < unit_infos + c; u++) {
3507 _cleanup_free_ char *p = NULL;
3509 if (!output_show_unit(u))
3512 p = unit_dbus_path_from_name(u->id);
3516 printf("%s -> '%s'\n", u->id, p);
3518 r = show_one(verb, bus, p, show_properties, new_line);
3526 static int show(DBusConnection *bus, char **args) {
3528 bool show_properties, show_status, new_line = false;
3534 show_properties = streq(args[0], "show");
3535 show_status = streq(args[0], "status");
3537 if (show_properties)
3538 pager_open_if_enabled();
3540 /* If no argument is specified inspect the manager itself */
3542 if (show_properties && strv_length(args) <= 1)
3543 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line);
3545 if (show_status && strv_length(args) <= 1)
3546 return show_all(args[0], bus, false, &new_line);
3548 STRV_FOREACH(name, args+1) {
3551 if (safe_atou32(*name, &id) < 0) {
3552 _cleanup_free_ char *p = NULL, *n = NULL;
3553 /* Interpret as unit name */
3555 n = unit_name_mangle(*name);
3559 p = unit_dbus_path_from_name(n);
3563 r = show_one(args[0], bus, p, show_properties, &new_line);
3567 } else if (show_properties) {
3568 _cleanup_free_ char *p = NULL;
3570 /* Interpret as job id */
3571 if (asprintf(&p, "/org/freedesktop/systemd1/job/%u", id) < 0)
3574 r = show_one(args[0], bus, p, show_properties, &new_line);
3579 /* Interpret as PID */
3580 r = show_one_by_pid(args[0], bus, id, &new_line);
3589 static int append_assignment(DBusMessageIter *iter, const char *assignment) {
3592 DBusMessageIter sub;
3598 eq = strchr(assignment, '=');
3600 log_error("Not an assignment: %s", assignment);
3604 field = strndupa(assignment, eq - assignment);
3607 if (!dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &field))
3610 if (streq(field, "CPUAccounting") ||
3611 streq(field, "MemoryAccounting") ||
3612 streq(field, "BlockIOAccounting")) {
3615 r = parse_boolean(eq);
3617 log_error("Failed to parse boolean assignment %s.", assignment);
3622 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "b", &sub) ||
3623 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_BOOLEAN, &b))
3626 } else if (streq(field, "MemoryLimit") || streq(field, "MemorySoftLimit")) {
3630 r = parse_bytes(eq, &bytes);
3632 log_error("Failed to parse bytes specification %s", assignment);
3637 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "t", &sub) ||
3638 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_UINT64, &u))
3641 } else if (streq(field, "CPUShares") || streq(field, "BlockIOWeight")) {
3644 r = safe_atou64(eq, &u);
3646 log_error("Failed to parse %s value %s.", field, eq);
3650 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "t", &sub) ||
3651 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_UINT64, &u))
3654 } else if (streq(field, "DevicePolicy")) {
3656 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "s", &sub) ||
3657 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &eq))
3660 } else if (streq(field, "DeviceAllow")) {
3661 DBusMessageIter sub2;
3663 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "a(ss)", &sub) ||
3664 !dbus_message_iter_open_container(&sub, DBUS_TYPE_ARRAY, "(ss)", &sub2))
3668 const char *path, *rwm;
3669 DBusMessageIter sub3;
3672 e = strchr(eq, ' ');
3674 path = strndupa(eq, e - eq);
3681 if (!dbus_message_iter_open_container(&sub2, DBUS_TYPE_STRUCT, NULL, &sub3) ||
3682 !dbus_message_iter_append_basic(&sub3, DBUS_TYPE_STRING, &path) ||
3683 !dbus_message_iter_append_basic(&sub3, DBUS_TYPE_STRING, &rwm) ||
3684 !dbus_message_iter_close_container(&sub2, &sub3))
3688 if (!dbus_message_iter_close_container(&sub, &sub2))
3692 log_error("Unknown assignment %s.", assignment);
3696 if (!dbus_message_iter_close_container(iter, &sub))
3702 static int set_property(DBusConnection *bus, char **args) {
3704 _cleanup_free_ DBusMessage *m = NULL, *reply = NULL;
3705 DBusMessageIter iter, sub;
3706 dbus_bool_t runtime;
3711 dbus_error_init(&error);
3713 m = dbus_message_new_method_call(
3714 "org.freedesktop.systemd1",
3715 "/org/freedesktop/systemd1",
3716 "org.freedesktop.systemd1.Manager",
3717 "SetUnitProperties");
3721 dbus_message_iter_init_append(m, &iter);
3723 runtime = arg_runtime;
3725 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &args[1]) ||
3726 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &runtime) ||
3727 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(sv)", &sub))
3730 STRV_FOREACH(i, args + 2) {
3731 DBusMessageIter sub2;
3733 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
3736 r = append_assignment(&sub2, *i);
3740 if (!dbus_message_iter_close_container(&sub, &sub2))
3745 if (!dbus_message_iter_close_container(&iter, &sub))
3748 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3750 log_error("Failed to issue method call: %s", bus_error_message(&error));
3751 dbus_error_free(&error);
3758 static int dump(DBusConnection *bus, char **args) {
3759 _cleanup_free_ DBusMessage *reply = NULL;
3764 dbus_error_init(&error);
3766 pager_open_if_enabled();
3768 r = bus_method_call_with_reply(
3770 "org.freedesktop.systemd1",
3771 "/org/freedesktop/systemd1",
3772 "org.freedesktop.systemd1.Manager",
3780 if (!dbus_message_get_args(reply, &error,
3781 DBUS_TYPE_STRING, &text,
3782 DBUS_TYPE_INVALID)) {
3783 log_error("Failed to parse reply: %s", bus_error_message(&error));
3784 dbus_error_free(&error);
3788 fputs(text, stdout);
3792 static int snapshot(DBusConnection *bus, char **args) {
3793 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3796 dbus_bool_t cleanup = FALSE;
3797 DBusMessageIter iter, sub;
3800 *interface = "org.freedesktop.systemd1.Unit",
3802 _cleanup_free_ char *n = NULL;
3804 dbus_error_init(&error);
3806 if (strv_length(args) > 1)
3807 n = unit_name_mangle_with_suffix(args[1], ".snapshot");
3813 r = bus_method_call_with_reply(
3815 "org.freedesktop.systemd1",
3816 "/org/freedesktop/systemd1",
3817 "org.freedesktop.systemd1.Manager",
3821 DBUS_TYPE_STRING, &n,
3822 DBUS_TYPE_BOOLEAN, &cleanup,
3827 if (!dbus_message_get_args(reply, &error,
3828 DBUS_TYPE_OBJECT_PATH, &path,
3829 DBUS_TYPE_INVALID)) {
3830 log_error("Failed to parse reply: %s", bus_error_message(&error));
3831 dbus_error_free(&error);
3835 dbus_message_unref(reply);
3838 r = bus_method_call_with_reply (
3840 "org.freedesktop.systemd1",
3842 "org.freedesktop.DBus.Properties",
3846 DBUS_TYPE_STRING, &interface,
3847 DBUS_TYPE_STRING, &property,
3852 if (!dbus_message_iter_init(reply, &iter) ||
3853 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3854 log_error("Failed to parse reply.");
3858 dbus_message_iter_recurse(&iter, &sub);
3860 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
3861 log_error("Failed to parse reply.");
3865 dbus_message_iter_get_basic(&sub, &id);
3873 static int delete_snapshot(DBusConnection *bus, char **args) {
3878 STRV_FOREACH(name, args+1) {
3879 _cleanup_free_ char *n = NULL;
3882 n = unit_name_mangle_with_suffix(*name, ".snapshot");
3886 r = bus_method_call_with_reply(
3888 "org.freedesktop.systemd1",
3889 "/org/freedesktop/systemd1",
3890 "org.freedesktop.systemd1.Manager",
3894 DBUS_TYPE_STRING, &n,
3903 static int daemon_reload(DBusConnection *bus, char **args) {
3908 if (arg_action == ACTION_RELOAD)
3910 else if (arg_action == ACTION_REEXEC)
3911 method = "Reexecute";
3913 assert(arg_action == ACTION_SYSTEMCTL);
3916 streq(args[0], "clear-jobs") ||
3917 streq(args[0], "cancel") ? "ClearJobs" :
3918 streq(args[0], "daemon-reexec") ? "Reexecute" :
3919 streq(args[0], "reset-failed") ? "ResetFailed" :
3920 streq(args[0], "halt") ? "Halt" :
3921 streq(args[0], "poweroff") ? "PowerOff" :
3922 streq(args[0], "reboot") ? "Reboot" :
3923 streq(args[0], "kexec") ? "KExec" :
3924 streq(args[0], "exit") ? "Exit" :
3925 /* "daemon-reload" */ "Reload";
3928 r = bus_method_call_with_reply(
3930 "org.freedesktop.systemd1",
3931 "/org/freedesktop/systemd1",
3932 "org.freedesktop.systemd1.Manager",
3938 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
3939 /* There's always a fallback possible for
3940 * legacy actions. */
3942 else if ((r == -ETIMEDOUT || r == -ECONNRESET) && streq(method, "Reexecute"))
3943 /* On reexecution, we expect a disconnect, not a
3947 log_error("Failed to issue method call: %s", bus_error_message(&error));
3949 dbus_error_free(&error);
3953 static int reset_failed(DBusConnection *bus, char **args) {
3957 if (strv_length(args) <= 1)
3958 return daemon_reload(bus, args);
3960 STRV_FOREACH(name, args+1) {
3961 _cleanup_free_ char *n;
3963 n = unit_name_mangle(*name);
3967 r = bus_method_call_with_reply(
3969 "org.freedesktop.systemd1",
3970 "/org/freedesktop/systemd1",
3971 "org.freedesktop.systemd1.Manager",
3975 DBUS_TYPE_STRING, &n,
3984 static int show_enviroment(DBusConnection *bus, char **args) {
3985 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3986 DBusMessageIter iter, sub, sub2;
3989 *interface = "org.freedesktop.systemd1.Manager",
3990 *property = "Environment";
3992 pager_open_if_enabled();
3994 r = bus_method_call_with_reply(
3996 "org.freedesktop.systemd1",
3997 "/org/freedesktop/systemd1",
3998 "org.freedesktop.DBus.Properties",
4002 DBUS_TYPE_STRING, &interface,
4003 DBUS_TYPE_STRING, &property,
4008 if (!dbus_message_iter_init(reply, &iter) ||
4009 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
4010 log_error("Failed to parse reply.");
4014 dbus_message_iter_recurse(&iter, &sub);
4016 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_ARRAY ||
4017 dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_STRING) {
4018 log_error("Failed to parse reply.");
4022 dbus_message_iter_recurse(&sub, &sub2);
4024 while (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_INVALID) {
4027 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
4028 log_error("Failed to parse reply.");
4032 dbus_message_iter_get_basic(&sub2, &text);
4035 dbus_message_iter_next(&sub2);
4041 static int switch_root(DBusConnection *bus, char **args) {
4044 _cleanup_free_ char *init = NULL;
4046 l = strv_length(args);
4047 if (l < 2 || l > 3) {
4048 log_error("Wrong number of arguments.");
4055 init = strdup(args[2]);
4057 parse_env_file("/proc/cmdline", WHITESPACE,
4067 log_debug("switching root - root: %s; init: %s", root, init);
4069 return bus_method_call_with_reply(
4071 "org.freedesktop.systemd1",
4072 "/org/freedesktop/systemd1",
4073 "org.freedesktop.systemd1.Manager",
4077 DBUS_TYPE_STRING, &root,
4078 DBUS_TYPE_STRING, &init,
4082 static int set_environment(DBusConnection *bus, char **args) {
4083 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
4086 DBusMessageIter iter;
4092 dbus_error_init(&error);
4094 method = streq(args[0], "set-environment")
4096 : "UnsetEnvironment";
4098 m = dbus_message_new_method_call(
4099 "org.freedesktop.systemd1",
4100 "/org/freedesktop/systemd1",
4101 "org.freedesktop.systemd1.Manager",
4106 dbus_message_iter_init_append(m, &iter);
4108 r = bus_append_strv_iter(&iter, args + 1);
4112 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
4114 log_error("Failed to issue method call: %s", bus_error_message(&error));
4115 dbus_error_free(&error);
4122 static int enable_sysv_units(char **args) {
4125 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
4126 const char *verb = args[0];
4127 unsigned f = 1, t = 1;
4128 LookupPaths paths = {};
4130 if (arg_scope != UNIT_FILE_SYSTEM)
4133 if (!streq(verb, "enable") &&
4134 !streq(verb, "disable") &&
4135 !streq(verb, "is-enabled"))
4138 /* Processes all SysV units, and reshuffles the array so that
4139 * afterwards only the native units remain */
4141 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, NULL, NULL, NULL);
4146 for (f = 1; args[f]; f++) {
4148 _cleanup_free_ char *p = NULL, *q = NULL;
4149 bool found_native = false, found_sysv;
4151 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
4159 if (!endswith(name, ".service"))
4162 if (path_is_absolute(name))
4165 STRV_FOREACH(k, paths.unit_path) {
4166 if (!isempty(arg_root))
4167 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
4169 asprintf(&p, "%s/%s", *k, name);
4176 found_native = access(p, F_OK) >= 0;
4187 if (!isempty(arg_root))
4188 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
4190 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
4196 p[strlen(p) - sizeof(".service") + 1] = 0;
4197 found_sysv = access(p, F_OK) >= 0;
4202 /* Mark this entry, so that we don't try enabling it as native unit */
4203 args[f] = (char*) "";
4205 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
4207 if (!isempty(arg_root))
4208 argv[c++] = q = strappend("--root=", arg_root);
4210 argv[c++] = path_get_file_name(p);
4212 streq(verb, "enable") ? "on" :
4213 streq(verb, "disable") ? "off" : "--level=5";
4216 l = strv_join((char**)argv, " ");
4222 log_info("Executing %s", l);
4227 log_error("Failed to fork: %m");
4230 } else if (pid == 0) {
4233 execv(argv[0], (char**) argv);
4234 _exit(EXIT_FAILURE);
4237 j = wait_for_terminate(pid, &status);
4239 log_error("Failed to wait for child: %s", strerror(-r));
4244 if (status.si_code == CLD_EXITED) {
4245 if (streq(verb, "is-enabled")) {
4246 if (status.si_status == 0) {
4255 } else if (status.si_status != 0) {
4266 lookup_paths_free(&paths);
4268 /* Drop all SysV units */
4269 for (f = 1, t = 1; args[f]; f++) {
4271 if (isempty(args[f]))
4274 args[t++] = args[f];
4283 static int mangle_names(char **original_names, char ***mangled_names) {
4284 char **i, **l, **name;
4286 l = new(char*, strv_length(original_names) + 1);
4291 STRV_FOREACH(name, original_names) {
4293 /* When enabling units qualified path names are OK,
4294 * too, hence allow them explicitly. */
4299 *i = unit_name_mangle(*name);
4315 static int enable_unit(DBusConnection *bus, char **args) {
4316 const char *verb = args[0];
4317 UnitFileChange *changes = NULL;
4318 unsigned n_changes = 0, i;
4319 int carries_install_info = -1;
4320 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
4322 _cleanup_dbus_error_free_ DBusError error;
4323 _cleanup_strv_free_ char **mangled_names = NULL;
4325 dbus_error_init(&error);
4327 r = enable_sysv_units(args);
4334 r = mangle_names(args+1, &mangled_names);
4338 if (!bus || avoid_bus()) {
4339 if (streq(verb, "enable")) {
4340 r = unit_file_enable(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4341 carries_install_info = r;
4342 } else if (streq(verb, "disable"))
4343 r = unit_file_disable(arg_scope, arg_runtime, arg_root, mangled_names, &changes, &n_changes);
4344 else if (streq(verb, "reenable")) {
4345 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4346 carries_install_info = r;
4347 } else if (streq(verb, "link"))
4348 r = unit_file_link(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4349 else if (streq(verb, "preset")) {
4350 r = unit_file_preset(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4351 carries_install_info = r;
4352 } else if (streq(verb, "mask"))
4353 r = unit_file_mask(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4354 else if (streq(verb, "unmask"))
4355 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, mangled_names, &changes, &n_changes);
4356 else if (streq(verb, "set-default"))
4357 r = unit_file_set_default(arg_scope, arg_root, args[1], &changes, &n_changes);
4359 assert_not_reached("Unknown verb");
4362 log_error("Operation failed: %s", strerror(-r));
4367 for (i = 0; i < n_changes; i++) {
4368 if (changes[i].type == UNIT_FILE_SYMLINK)
4369 log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
4371 log_info("rm '%s'", changes[i].path);
4378 bool send_force = true, expect_carries_install_info = false;
4380 DBusMessageIter iter, sub, sub2;
4382 if (streq(verb, "enable")) {
4383 method = "EnableUnitFiles";
4384 expect_carries_install_info = true;
4385 } else if (streq(verb, "disable")) {
4386 method = "DisableUnitFiles";
4388 } else if (streq(verb, "reenable")) {
4389 method = "ReenableUnitFiles";
4390 expect_carries_install_info = true;
4391 } else if (streq(verb, "link"))
4392 method = "LinkUnitFiles";
4393 else if (streq(verb, "preset")) {
4394 method = "PresetUnitFiles";
4395 expect_carries_install_info = true;
4396 } else if (streq(verb, "mask"))
4397 method = "MaskUnitFiles";
4398 else if (streq(verb, "unmask")) {
4399 method = "UnmaskUnitFiles";
4401 } else if (streq(verb, "set-default")) {
4402 method = "SetDefaultTarget";
4404 assert_not_reached("Unknown verb");
4406 m = dbus_message_new_method_call(
4407 "org.freedesktop.systemd1",
4408 "/org/freedesktop/systemd1",
4409 "org.freedesktop.systemd1.Manager",
4416 dbus_message_iter_init_append(m, &iter);
4418 r = bus_append_strv_iter(&iter, mangled_names);
4420 log_error("Failed to append unit files.");
4425 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &a)) {
4426 log_error("Failed to append runtime boolean.");
4434 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b)) {
4435 log_error("Failed to append force boolean.");
4441 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
4443 log_error("Failed to issue method call: %s", bus_error_message(&error));
4448 if (!dbus_message_iter_init(reply, &iter)) {
4449 log_error("Failed to initialize iterator.");
4453 if (expect_carries_install_info) {
4454 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &b, true);
4456 log_error("Failed to parse reply.");
4460 carries_install_info = b;
4463 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
4464 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
4465 log_error("Failed to parse reply.");
4470 dbus_message_iter_recurse(&iter, &sub);
4471 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
4472 const char *type, *path, *source;
4474 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
4475 log_error("Failed to parse reply.");
4480 dbus_message_iter_recurse(&sub, &sub2);
4482 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
4483 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
4484 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &source, false) < 0) {
4485 log_error("Failed to parse reply.");
4491 if (streq(type, "symlink"))
4492 log_info("ln -s '%s' '%s'", source, path);
4494 log_info("rm '%s'", path);
4497 dbus_message_iter_next(&sub);
4500 /* Try to reload if enabeld */
4502 r = daemon_reload(bus, args);
4505 if (carries_install_info == 0)
4506 log_warning("The unit files have no [Install] section. They are not meant to be enabled\n"
4507 "using systemctl.\n"
4508 "Possible reasons for having this kind of units are:\n"
4509 "1) A unit may be statically enabled by being symlinked from another unit's\n"
4510 " .wants/ or .requires/ directory.\n"
4511 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
4512 " a requirement dependency on it.\n"
4513 "3) A unit may be started when needed via activation (socket, path, timer,\n"
4514 " D-Bus, udev, scripted systemctl call, ...).\n");
4517 unit_file_changes_free(changes, n_changes);
4522 static int set_log_level(DBusConnection *bus, char **args) {
4523 _cleanup_dbus_error_free_ DBusError error;
4524 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
4525 DBusMessageIter iter, sub;
4526 const char* property = "LogLevel";
4527 const char* interface = "org.freedesktop.systemd1.Manager";
4534 dbus_error_init(&error);
4536 m = dbus_message_new_method_call("org.freedesktop.systemd1",
4537 "/org/freedesktop/systemd1",
4538 "org.freedesktop.DBus.Properties",
4543 dbus_message_iter_init_append(m, &iter);
4545 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &interface) ||
4546 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &property) ||
4547 !dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT, "s", &sub))
4550 if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &value)) {
4551 dbus_message_iter_abandon_container(&iter, &sub);
4555 if (!dbus_message_iter_close_container(&iter, &sub))
4558 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
4560 log_error("Failed to issue method call: %s", bus_error_message(&error));
4567 static int unit_is_enabled(DBusConnection *bus, char **args) {
4568 _cleanup_dbus_error_free_ DBusError error;
4570 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
4575 dbus_error_init(&error);
4577 r = enable_sysv_units(args);
4583 if (!bus || avoid_bus()) {
4585 STRV_FOREACH(name, args+1) {
4586 UnitFileState state;
4588 n = unit_name_mangle(*name);
4592 state = unit_file_get_state(arg_scope, arg_root, n);
4599 if (state == UNIT_FILE_ENABLED ||
4600 state == UNIT_FILE_ENABLED_RUNTIME ||
4601 state == UNIT_FILE_STATIC)
4605 puts(unit_file_state_to_string(state));
4609 STRV_FOREACH(name, args+1) {
4612 n = unit_name_mangle(*name);
4616 r = bus_method_call_with_reply (
4618 "org.freedesktop.systemd1",
4619 "/org/freedesktop/systemd1",
4620 "org.freedesktop.systemd1.Manager",
4624 DBUS_TYPE_STRING, &n,
4632 if (!dbus_message_get_args(reply, &error,
4633 DBUS_TYPE_STRING, &s,
4634 DBUS_TYPE_INVALID)) {
4635 log_error("Failed to parse reply: %s", bus_error_message(&error));
4639 dbus_message_unref(reply);
4642 if (streq(s, "enabled") ||
4643 streq(s, "enabled-runtime") ||
4652 return enabled ? 0 : 1;
4655 static int systemctl_help(void) {
4657 pager_open_if_enabled();
4659 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
4660 "Query or send control commands to the systemd manager.\n\n"
4661 " -h --help Show this help\n"
4662 " --version Show package version\n"
4663 " -t --type=TYPE List only units of a particular type\n"
4664 " -p --property=NAME Show only properties by this name\n"
4665 " -a --all Show all loaded units/properties, including dead/empty\n"
4666 " ones. To list all units installed on the system, use\n"
4667 " the 'list-unit-files' command instead.\n"
4668 " --reverse Show reverse dependencies with 'list-dependencies'\n"
4669 " --failed Show only failed units\n"
4670 " -l --full Don't ellipsize unit names on output\n"
4671 " --fail When queueing a new job, fail if conflicting jobs are\n"
4673 " --irreversible Create jobs which cannot be implicitly cancelled\n"
4674 " --show-types When showing sockets, explicitly show their type\n"
4675 " --ignore-dependencies\n"
4676 " When queueing a new job, ignore all its dependencies\n"
4677 " -i --ignore-inhibitors\n"
4678 " When shutting down or sleeping, ignore inhibitors\n"
4679 " --kill-who=WHO Who to send signal to\n"
4680 " -s --signal=SIGNAL Which signal to send\n"
4681 " -H --host=[USER@]HOST\n"
4682 " Show information for remote host\n"
4683 " -P --privileged Acquire privileges before execution\n"
4684 " -q --quiet Suppress output\n"
4685 " --no-block Do not wait until operation finished\n"
4686 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4687 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
4689 " --no-legend Do not print a legend (column headers and hints)\n"
4690 " --no-pager Do not pipe output into a pager\n"
4691 " --no-ask-password\n"
4692 " Do not ask for system passwords\n"
4693 " --system Connect to system manager\n"
4694 " --user Connect to user service manager\n"
4695 " --global Enable/disable unit files globally\n"
4696 " -f --force When enabling unit files, override existing symlinks\n"
4697 " When shutting down, execute action immediately\n"
4698 " --root=PATH Enable unit files in the specified root directory\n"
4699 " --runtime Enable unit files only temporarily until next reboot\n"
4700 " -n --lines=INTEGER Journal entries to show\n"
4701 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
4702 " verbose, export, json, json-pretty, json-sse, cat)\n\n"
4704 " list-units List loaded units\n"
4705 " list-sockets List loaded sockets ordered by address\n"
4706 " start [NAME...] Start (activate) one or more units\n"
4707 " stop [NAME...] Stop (deactivate) one or more units\n"
4708 " reload [NAME...] Reload one or more units\n"
4709 " restart [NAME...] Start or restart one or more units\n"
4710 " try-restart [NAME...] Restart one or more units if active\n"
4711 " reload-or-restart [NAME...] Reload one or more units if possible,\n"
4712 " otherwise start or restart\n"
4713 " reload-or-try-restart [NAME...] Reload one or more units if possible,\n"
4714 " otherwise restart if active\n"
4715 " isolate [NAME] Start one unit and stop all others\n"
4716 " kill [NAME...] Send signal to processes of a unit\n"
4717 " is-active [NAME...] Check whether units are active\n"
4718 " is-failed [NAME...] Check whether units are failed\n"
4719 " status [NAME...|PID...] Show runtime status of one or more units\n"
4720 " show [NAME...|JOB...] Show properties of one or more\n"
4721 " units/jobs or the manager\n"
4722 " set-property [NAME] [ASSIGNMENT...]\n"
4723 " Sets one or more properties of a unit\n"
4724 " help [NAME...|PID...] Show manual for one or more units\n"
4725 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
4727 " load [NAME...] Load one or more units\n"
4728 " list-dependencies [NAME] Recursively show units which are required\n"
4729 " or wanted by this unit or by which this\n"
4730 " unit is required or wanted\n\n"
4731 "Unit File Commands:\n"
4732 " list-unit-files List installed unit files\n"
4733 " enable [NAME...] Enable one or more unit files\n"
4734 " disable [NAME...] Disable one or more unit files\n"
4735 " reenable [NAME...] Reenable one or more unit files\n"
4736 " preset [NAME...] Enable/disable one or more unit files\n"
4737 " based on preset configuration\n"
4738 " mask [NAME...] Mask one or more units\n"
4739 " unmask [NAME...] Unmask one or more units\n"
4740 " link [PATH...] Link one or more units files into\n"
4741 " the search path\n"
4742 " get-default Get the name of the default target\n"
4743 " set-default NAME Set the default target\n"
4744 " is-enabled [NAME...] Check whether unit files are enabled\n\n"
4746 " list-jobs List jobs\n"
4747 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
4748 "Status Commands:\n"
4749 " dump Dump server status\n"
4750 "Snapshot Commands:\n"
4751 " snapshot [NAME] Create a snapshot\n"
4752 " delete [NAME...] Remove one or more snapshots\n\n"
4753 "Environment Commands:\n"
4754 " show-environment Dump environment\n"
4755 " set-environment [NAME=VALUE...] Set one or more environment variables\n"
4756 " unset-environment [NAME...] Unset one or more environment variables\n"
4757 " set-log-level LEVEL Set logging threshold for systemd\n\n"
4758 "Manager Lifecycle Commands:\n"
4759 " daemon-reload Reload systemd manager configuration\n"
4760 " daemon-reexec Reexecute systemd manager\n\n"
4761 "System Commands:\n"
4762 " default Enter system default mode\n"
4763 " rescue Enter system rescue mode\n"
4764 " emergency Enter system emergency mode\n"
4765 " halt Shut down and halt the system\n"
4766 " poweroff Shut down and power-off the system\n"
4767 " reboot Shut down and reboot the system\n"
4768 " kexec Shut down and reboot the system with kexec\n"
4769 " exit Request user instance exit\n"
4770 " switch-root [ROOT] [INIT] Change to a different root file system\n"
4771 " suspend Suspend the system\n"
4772 " hibernate Hibernate the system\n"
4773 " hybrid-sleep Hibernate and suspend the system\n",
4774 program_invocation_short_name);
4779 static int halt_help(void) {
4781 printf("%s [OPTIONS...]\n\n"
4782 "%s the system.\n\n"
4783 " --help Show this help\n"
4784 " --halt Halt the machine\n"
4785 " -p --poweroff Switch off the machine\n"
4786 " --reboot Reboot the machine\n"
4787 " -f --force Force immediate halt/power-off/reboot\n"
4788 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
4789 " -d --no-wtmp Don't write wtmp record\n"
4790 " --no-wall Don't send wall message before halt/power-off/reboot\n",
4791 program_invocation_short_name,
4792 arg_action == ACTION_REBOOT ? "Reboot" :
4793 arg_action == ACTION_POWEROFF ? "Power off" :
4799 static int shutdown_help(void) {
4801 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
4802 "Shut down the system.\n\n"
4803 " --help Show this help\n"
4804 " -H --halt Halt the machine\n"
4805 " -P --poweroff Power-off the machine\n"
4806 " -r --reboot Reboot the machine\n"
4807 " -h Equivalent to --poweroff, overridden by --halt\n"
4808 " -k Don't halt/power-off/reboot, just send warnings\n"
4809 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4810 " -c Cancel a pending shutdown\n",
4811 program_invocation_short_name);
4816 static int telinit_help(void) {
4818 printf("%s [OPTIONS...] {COMMAND}\n\n"
4819 "Send control commands to the init daemon.\n\n"
4820 " --help Show this help\n"
4821 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
4823 " 0 Power-off the machine\n"
4824 " 6 Reboot the machine\n"
4825 " 2, 3, 4, 5 Start runlevelX.target unit\n"
4826 " 1, s, S Enter rescue mode\n"
4827 " q, Q Reload init daemon configuration\n"
4828 " u, U Reexecute init daemon\n",
4829 program_invocation_short_name);
4834 static int runlevel_help(void) {
4836 printf("%s [OPTIONS...]\n\n"
4837 "Prints the previous and current runlevel of the init system.\n\n"
4838 " --help Show this help\n",
4839 program_invocation_short_name);
4844 static int help_types(void) {
4848 puts("Available unit types:");
4849 for(i = 0; i < _UNIT_TYPE_MAX; i++) {
4850 t = unit_type_to_string(i);
4855 puts("\nAvailable unit load states: ");
4856 for(i = 0; i < _UNIT_LOAD_STATE_MAX; i++) {
4857 t = unit_load_state_to_string(i);
4865 static int systemctl_parse_argv(int argc, char *argv[]) {
4874 ARG_IGNORE_DEPENDENCIES,
4886 ARG_NO_ASK_PASSWORD,
4893 static const struct option options[] = {
4894 { "help", no_argument, NULL, 'h' },
4895 { "version", no_argument, NULL, ARG_VERSION },
4896 { "type", required_argument, NULL, 't' },
4897 { "property", required_argument, NULL, 'p' },
4898 { "all", no_argument, NULL, 'a' },
4899 { "reverse", no_argument, NULL, ARG_REVERSE },
4900 { "after", no_argument, NULL, ARG_AFTER },
4901 { "before", no_argument, NULL, ARG_BEFORE },
4902 { "show-types", no_argument, NULL, ARG_SHOW_TYPES },
4903 { "failed", no_argument, NULL, ARG_FAILED },
4904 { "full", no_argument, NULL, 'l' },
4905 { "fail", no_argument, NULL, ARG_FAIL },
4906 { "irreversible", no_argument, NULL, ARG_IRREVERSIBLE },
4907 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
4908 { "ignore-inhibitors", no_argument, NULL, 'i' },
4909 { "user", no_argument, NULL, ARG_USER },
4910 { "system", no_argument, NULL, ARG_SYSTEM },
4911 { "global", no_argument, NULL, ARG_GLOBAL },
4912 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
4913 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
4914 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
4915 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4916 { "quiet", no_argument, NULL, 'q' },
4917 { "root", required_argument, NULL, ARG_ROOT },
4918 { "force", no_argument, NULL, ARG_FORCE },
4919 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
4920 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
4921 { "signal", required_argument, NULL, 's' },
4922 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
4923 { "host", required_argument, NULL, 'H' },
4924 { "privileged",no_argument, NULL, 'P' },
4925 { "runtime", no_argument, NULL, ARG_RUNTIME },
4926 { "lines", required_argument, NULL, 'n' },
4927 { "output", required_argument, NULL, 'o' },
4928 { "plain", no_argument, NULL, ARG_PLAIN },
4929 { NULL, 0, NULL, 0 }
4937 while ((c = getopt_long(argc, argv, "ht:p:alqfs:H:Pn:o:i", options, NULL)) >= 0) {
4946 puts(PACKAGE_STRING);
4947 puts(SYSTEMD_FEATURES);
4954 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
4955 _cleanup_free_ char *type;
4957 type = strndup(word, size);
4961 if (streq(type, "help")) {
4966 if (unit_type_from_string(type) >= 0) {
4967 if (strv_push(&arg_types, type))
4973 if (unit_load_state_from_string(optarg) >= 0) {
4974 if (strv_push(&arg_load_states, type))
4980 log_error("Unknown unit type or load state '%s'.", type);
4981 log_info("Use -t help to see a list of allowed values.");
4989 /* Make sure that if the empty property list
4990 was specified, we won't show any properties. */
4991 if (isempty(optarg) && !arg_properties) {
4992 arg_properties = strv_new(NULL, NULL);
4993 if (!arg_properties)
4999 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
5002 prop = strndup(word, size);
5006 if (strv_push(&arg_properties, prop)) {
5013 /* If the user asked for a particular
5014 * property, show it to him, even if it is
5026 arg_dependency = DEPENDENCY_REVERSE;
5030 arg_dependency = DEPENDENCY_AFTER;
5034 arg_dependency = DEPENDENCY_BEFORE;
5037 case ARG_SHOW_TYPES:
5038 arg_show_types = true;
5042 arg_job_mode = "fail";
5045 case ARG_IRREVERSIBLE:
5046 arg_job_mode = "replace-irreversibly";
5049 case ARG_IGNORE_DEPENDENCIES:
5050 arg_job_mode = "ignore-dependencies";
5054 arg_scope = UNIT_FILE_USER;
5058 arg_scope = UNIT_FILE_SYSTEM;
5062 arg_scope = UNIT_FILE_GLOBAL;
5066 arg_no_block = true;
5070 arg_no_legend = true;
5074 arg_no_pager = true;
5106 arg_no_reload = true;
5110 arg_kill_who = optarg;
5114 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
5115 log_error("Failed to parse signal string %s.", optarg);
5120 case ARG_NO_ASK_PASSWORD:
5121 arg_ask_password = false;
5125 arg_transport = TRANSPORT_POLKIT;
5129 arg_transport = TRANSPORT_SSH;
5130 parse_user_at_host(optarg, &arg_user, &arg_host);
5138 if (safe_atou(optarg, &arg_lines) < 0) {
5139 log_error("Failed to parse lines '%s'", optarg);
5145 arg_output = output_mode_from_string(optarg);
5146 if (arg_output < 0) {
5147 log_error("Unknown output '%s'.", optarg);
5153 arg_ignore_inhibitors = true;
5164 log_error("Unknown option code '%c'.", c);
5169 if (arg_transport != TRANSPORT_NORMAL && arg_scope != UNIT_FILE_SYSTEM) {
5170 log_error("Cannot access user instance remotely.");
5177 static int halt_parse_argv(int argc, char *argv[]) {
5186 static const struct option options[] = {
5187 { "help", no_argument, NULL, ARG_HELP },
5188 { "halt", no_argument, NULL, ARG_HALT },
5189 { "poweroff", no_argument, NULL, 'p' },
5190 { "reboot", no_argument, NULL, ARG_REBOOT },
5191 { "force", no_argument, NULL, 'f' },
5192 { "wtmp-only", no_argument, NULL, 'w' },
5193 { "no-wtmp", no_argument, NULL, 'd' },
5194 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5195 { NULL, 0, NULL, 0 }
5203 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
5204 if (runlevel == '0' || runlevel == '6')
5207 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
5215 arg_action = ACTION_HALT;
5219 if (arg_action != ACTION_REBOOT)
5220 arg_action = ACTION_POWEROFF;
5224 arg_action = ACTION_REBOOT;
5246 /* Compatibility nops */
5253 log_error("Unknown option code '%c'.", c);
5258 if (optind < argc) {
5259 log_error("Too many arguments.");
5266 static int parse_time_spec(const char *t, usec_t *_u) {
5270 if (streq(t, "now"))
5272 else if (!strchr(t, ':')) {
5275 if (safe_atou64(t, &u) < 0)
5278 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
5287 hour = strtol(t, &e, 10);
5288 if (errno > 0 || *e != ':' || hour < 0 || hour > 23)
5291 minute = strtol(e+1, &e, 10);
5292 if (errno > 0 || *e != 0 || minute < 0 || minute > 59)
5295 n = now(CLOCK_REALTIME);
5296 s = (time_t) (n / USEC_PER_SEC);
5298 assert_se(localtime_r(&s, &tm));
5300 tm.tm_hour = (int) hour;
5301 tm.tm_min = (int) minute;
5304 assert_se(s = mktime(&tm));
5306 *_u = (usec_t) s * USEC_PER_SEC;
5309 *_u += USEC_PER_DAY;
5315 static int shutdown_parse_argv(int argc, char *argv[]) {
5322 static const struct option options[] = {
5323 { "help", no_argument, NULL, ARG_HELP },
5324 { "halt", no_argument, NULL, 'H' },
5325 { "poweroff", no_argument, NULL, 'P' },
5326 { "reboot", no_argument, NULL, 'r' },
5327 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
5328 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5329 { NULL, 0, NULL, 0 }
5337 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
5345 arg_action = ACTION_HALT;
5349 arg_action = ACTION_POWEROFF;
5354 arg_action = ACTION_KEXEC;
5356 arg_action = ACTION_REBOOT;
5360 arg_action = ACTION_KEXEC;
5364 if (arg_action != ACTION_HALT)
5365 arg_action = ACTION_POWEROFF;
5378 /* Compatibility nops */
5382 arg_action = ACTION_CANCEL_SHUTDOWN;
5389 log_error("Unknown option code '%c'.", c);
5394 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
5395 r = parse_time_spec(argv[optind], &arg_when);
5397 log_error("Failed to parse time specification: %s", argv[optind]);
5401 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
5403 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
5404 /* No time argument for shutdown cancel */
5405 arg_wall = argv + optind;
5406 else if (argc > optind + 1)
5407 /* We skip the time argument */
5408 arg_wall = argv + optind + 1;
5415 static int telinit_parse_argv(int argc, char *argv[]) {
5422 static const struct option options[] = {
5423 { "help", no_argument, NULL, ARG_HELP },
5424 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5425 { NULL, 0, NULL, 0 }
5428 static const struct {
5432 { '0', ACTION_POWEROFF },
5433 { '6', ACTION_REBOOT },
5434 { '1', ACTION_RESCUE },
5435 { '2', ACTION_RUNLEVEL2 },
5436 { '3', ACTION_RUNLEVEL3 },
5437 { '4', ACTION_RUNLEVEL4 },
5438 { '5', ACTION_RUNLEVEL5 },
5439 { 's', ACTION_RESCUE },
5440 { 'S', ACTION_RESCUE },
5441 { 'q', ACTION_RELOAD },
5442 { 'Q', ACTION_RELOAD },
5443 { 'u', ACTION_REEXEC },
5444 { 'U', ACTION_REEXEC }
5453 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
5468 log_error("Unknown option code '%c'.", c);
5473 if (optind >= argc) {
5478 if (optind + 1 < argc) {
5479 log_error("Too many arguments.");
5483 if (strlen(argv[optind]) != 1) {
5484 log_error("Expected single character argument.");
5488 for (i = 0; i < ELEMENTSOF(table); i++)
5489 if (table[i].from == argv[optind][0])
5492 if (i >= ELEMENTSOF(table)) {
5493 log_error("Unknown command '%s'.", argv[optind]);
5497 arg_action = table[i].to;
5504 static int runlevel_parse_argv(int argc, char *argv[]) {
5510 static const struct option options[] = {
5511 { "help", no_argument, NULL, ARG_HELP },
5512 { NULL, 0, NULL, 0 }
5520 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
5531 log_error("Unknown option code '%c'.", c);
5536 if (optind < argc) {
5537 log_error("Too many arguments.");
5544 static int parse_argv(int argc, char *argv[]) {
5548 if (program_invocation_short_name) {
5550 if (strstr(program_invocation_short_name, "halt")) {
5551 arg_action = ACTION_HALT;
5552 return halt_parse_argv(argc, argv);
5553 } else if (strstr(program_invocation_short_name, "poweroff")) {
5554 arg_action = ACTION_POWEROFF;
5555 return halt_parse_argv(argc, argv);
5556 } else if (strstr(program_invocation_short_name, "reboot")) {
5558 arg_action = ACTION_KEXEC;
5560 arg_action = ACTION_REBOOT;
5561 return halt_parse_argv(argc, argv);
5562 } else if (strstr(program_invocation_short_name, "shutdown")) {
5563 arg_action = ACTION_POWEROFF;
5564 return shutdown_parse_argv(argc, argv);
5565 } else if (strstr(program_invocation_short_name, "init")) {
5567 if (sd_booted() > 0) {
5568 arg_action = ACTION_INVALID;
5569 return telinit_parse_argv(argc, argv);
5571 /* Hmm, so some other init system is
5572 * running, we need to forward this
5573 * request to it. For now we simply
5574 * guess that it is Upstart. */
5576 execv(TELINIT, argv);
5578 log_error("Couldn't find an alternative telinit implementation to spawn.");
5582 } else if (strstr(program_invocation_short_name, "runlevel")) {
5583 arg_action = ACTION_RUNLEVEL;
5584 return runlevel_parse_argv(argc, argv);
5588 arg_action = ACTION_SYSTEMCTL;
5589 return systemctl_parse_argv(argc, argv);
5592 _pure_ static int action_to_runlevel(void) {
5594 static const char table[_ACTION_MAX] = {
5595 [ACTION_HALT] = '0',
5596 [ACTION_POWEROFF] = '0',
5597 [ACTION_REBOOT] = '6',
5598 [ACTION_RUNLEVEL2] = '2',
5599 [ACTION_RUNLEVEL3] = '3',
5600 [ACTION_RUNLEVEL4] = '4',
5601 [ACTION_RUNLEVEL5] = '5',
5602 [ACTION_RESCUE] = '1'
5605 assert(arg_action < _ACTION_MAX);
5607 return table[arg_action];
5610 static int talk_upstart(void) {
5611 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
5612 _cleanup_dbus_error_free_ DBusError error;
5613 int previous, rl, r;
5615 env1_buf[] = "RUNLEVEL=X",
5616 env2_buf[] = "PREVLEVEL=X";
5617 char *env1 = env1_buf, *env2 = env2_buf;
5618 const char *emit = "runlevel";
5619 dbus_bool_t b_false = FALSE;
5620 DBusMessageIter iter, sub;
5621 DBusConnection *bus;
5623 dbus_error_init(&error);
5625 if (!(rl = action_to_runlevel()))
5628 if (utmp_get_runlevel(&previous, NULL) < 0)
5631 if (!(bus = dbus_connection_open_private("unix:abstract=/com/ubuntu/upstart", &error))) {
5632 if (dbus_error_has_name(&error, DBUS_ERROR_NO_SERVER)) {
5637 log_error("Failed to connect to Upstart bus: %s", bus_error_message(&error));
5642 if ((r = bus_check_peercred(bus)) < 0) {
5643 log_error("Failed to verify owner of bus.");
5647 if (!(m = dbus_message_new_method_call(
5648 "com.ubuntu.Upstart",
5649 "/com/ubuntu/Upstart",
5650 "com.ubuntu.Upstart0_6",
5653 log_error("Could not allocate message.");
5658 dbus_message_iter_init_append(m, &iter);
5660 env1_buf[sizeof(env1_buf)-2] = rl;
5661 env2_buf[sizeof(env2_buf)-2] = previous;
5663 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &emit) ||
5664 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub) ||
5665 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env1) ||
5666 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env2) ||
5667 !dbus_message_iter_close_container(&iter, &sub) ||
5668 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b_false)) {
5669 log_error("Could not append arguments to message.");
5674 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
5676 if (bus_error_is_no_service(&error)) {
5681 log_error("Failed to issue method call: %s", bus_error_message(&error));
5690 dbus_connection_flush(bus);
5691 dbus_connection_close(bus);
5692 dbus_connection_unref(bus);
5698 static int talk_initctl(void) {
5699 struct init_request request = {};
5701 _cleanup_close_ int fd = -1;
5704 rl = action_to_runlevel();
5708 request.magic = INIT_MAGIC;
5709 request.sleeptime = 0;
5710 request.cmd = INIT_CMD_RUNLVL;
5711 request.runlevel = rl;
5713 fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY);
5715 if (errno == ENOENT)
5718 log_error("Failed to open "INIT_FIFO": %m");
5723 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
5725 log_error("Failed to write to "INIT_FIFO": %m");
5726 return errno > 0 ? -errno : -EIO;
5732 static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
5734 static const struct {
5742 int (* const dispatch)(DBusConnection *bus, char **args);
5744 { "list-units", LESS, 1, list_units },
5745 { "list-unit-files", EQUAL, 1, list_unit_files },
5746 { "list-sockets", LESS, 1, list_sockets },
5747 { "list-jobs", EQUAL, 1, list_jobs },
5748 { "clear-jobs", EQUAL, 1, daemon_reload },
5749 { "load", MORE, 2, load_unit },
5750 { "cancel", MORE, 2, cancel_job },
5751 { "start", MORE, 2, start_unit },
5752 { "stop", MORE, 2, start_unit },
5753 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5754 { "reload", MORE, 2, start_unit },
5755 { "restart", MORE, 2, start_unit },
5756 { "try-restart", MORE, 2, start_unit },
5757 { "reload-or-restart", MORE, 2, start_unit },
5758 { "reload-or-try-restart", MORE, 2, start_unit },
5759 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
5760 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5761 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
5762 { "isolate", EQUAL, 2, start_unit },
5763 { "kill", MORE, 2, kill_unit },
5764 { "is-active", MORE, 2, check_unit_active },
5765 { "check", MORE, 2, check_unit_active },
5766 { "is-failed", MORE, 2, check_unit_failed },
5767 { "show", MORE, 1, show },
5768 { "status", MORE, 1, show },
5769 { "help", MORE, 2, show },
5770 { "dump", EQUAL, 1, dump },
5771 { "snapshot", LESS, 2, snapshot },
5772 { "delete", MORE, 2, delete_snapshot },
5773 { "daemon-reload", EQUAL, 1, daemon_reload },
5774 { "daemon-reexec", EQUAL, 1, daemon_reload },
5775 { "show-environment", EQUAL, 1, show_enviroment },
5776 { "set-environment", MORE, 2, set_environment },
5777 { "unset-environment", MORE, 2, set_environment },
5778 { "halt", EQUAL, 1, start_special },
5779 { "poweroff", EQUAL, 1, start_special },
5780 { "reboot", EQUAL, 1, start_special },
5781 { "kexec", EQUAL, 1, start_special },
5782 { "suspend", EQUAL, 1, start_special },
5783 { "hibernate", EQUAL, 1, start_special },
5784 { "hybrid-sleep", EQUAL, 1, start_special },
5785 { "default", EQUAL, 1, start_special },
5786 { "rescue", EQUAL, 1, start_special },
5787 { "emergency", EQUAL, 1, start_special },
5788 { "exit", EQUAL, 1, start_special },
5789 { "reset-failed", MORE, 1, reset_failed },
5790 { "enable", MORE, 2, enable_unit },
5791 { "disable", MORE, 2, enable_unit },
5792 { "is-enabled", MORE, 2, unit_is_enabled },
5793 { "reenable", MORE, 2, enable_unit },
5794 { "preset", MORE, 2, enable_unit },
5795 { "mask", MORE, 2, enable_unit },
5796 { "unmask", MORE, 2, enable_unit },
5797 { "link", MORE, 2, enable_unit },
5798 { "switch-root", MORE, 2, switch_root },
5799 { "list-dependencies", LESS, 2, list_dependencies },
5800 { "set-default", EQUAL, 2, enable_unit },
5801 { "get-default", LESS, 1, get_default },
5802 { "set-log-level", EQUAL, 2, set_log_level },
5803 { "set-property", MORE, 3, set_property },
5813 left = argc - optind;
5816 /* Special rule: no arguments means "list-units" */
5819 if (streq(argv[optind], "help") && !argv[optind+1]) {
5820 log_error("This command expects one or more "
5821 "unit names. Did you mean --help?");
5825 for (i = 0; i < ELEMENTSOF(verbs); i++)
5826 if (streq(argv[optind], verbs[i].verb))
5829 if (i >= ELEMENTSOF(verbs)) {
5830 log_error("Unknown operation '%s'.", argv[optind]);
5835 switch (verbs[i].argc_cmp) {
5838 if (left != verbs[i].argc) {
5839 log_error("Invalid number of arguments.");
5846 if (left < verbs[i].argc) {
5847 log_error("Too few arguments.");
5854 if (left > verbs[i].argc) {
5855 log_error("Too many arguments.");
5862 assert_not_reached("Unknown comparison operator.");
5865 /* Require a bus connection for all operations but
5867 if (!streq(verbs[i].verb, "enable") &&
5868 !streq(verbs[i].verb, "disable") &&
5869 !streq(verbs[i].verb, "is-enabled") &&
5870 !streq(verbs[i].verb, "list-unit-files") &&
5871 !streq(verbs[i].verb, "reenable") &&
5872 !streq(verbs[i].verb, "preset") &&
5873 !streq(verbs[i].verb, "mask") &&
5874 !streq(verbs[i].verb, "unmask") &&
5875 !streq(verbs[i].verb, "link") &&
5876 !streq(verbs[i].verb, "set-default") &&
5877 !streq(verbs[i].verb, "get-default")) {
5879 if (running_in_chroot() > 0) {
5880 log_info("Running in chroot, ignoring request.");
5884 if (((!streq(verbs[i].verb, "reboot") &&
5885 !streq(verbs[i].verb, "halt") &&
5886 !streq(verbs[i].verb, "poweroff")) || arg_force <= 0) && !bus) {
5887 log_error("Failed to get D-Bus connection: %s",
5888 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5894 if (!bus && !avoid_bus()) {
5895 log_error("Failed to get D-Bus connection: %s",
5896 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5901 return verbs[i].dispatch(bus, argv + optind);
5904 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
5905 _cleanup_close_ int fd;
5906 struct sd_shutdown_command c = {
5912 union sockaddr_union sockaddr = {
5913 .un.sun_family = AF_UNIX,
5914 .un.sun_path = "/run/systemd/shutdownd",
5916 struct iovec iovec[2] = {
5917 {.iov_base = (char*) &c,
5918 .iov_len = offsetof(struct sd_shutdown_command, wall_message),
5921 struct msghdr msghdr = {
5922 .msg_name = &sockaddr,
5923 .msg_namelen = offsetof(struct sockaddr_un, sun_path)
5924 + sizeof("/run/systemd/shutdownd") - 1,
5929 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
5933 if (!isempty(message)) {
5934 iovec[1].iov_base = (char*) message;
5935 iovec[1].iov_len = strlen(message);
5936 msghdr.msg_iovlen++;
5939 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0)
5945 static int reload_with_fallback(DBusConnection *bus) {
5948 /* First, try systemd via D-Bus. */
5949 if (daemon_reload(bus, NULL) >= 0)
5953 /* Nothing else worked, so let's try signals */
5954 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
5956 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
5957 log_error("kill() failed: %m");
5964 static int start_with_fallback(DBusConnection *bus) {
5967 /* First, try systemd via D-Bus. */
5968 if (start_unit(bus, NULL) >= 0)
5972 /* Hmm, talking to systemd via D-Bus didn't work. Then
5973 * let's try to talk to Upstart via D-Bus. */
5974 if (talk_upstart() > 0)
5977 /* Nothing else worked, so let's try
5979 if (talk_initctl() > 0)
5982 log_error("Failed to talk to init daemon.");
5986 warn_wall(arg_action);
5990 static _noreturn_ void halt_now(enum action a) {
5992 /* Make sure C-A-D is handled by the kernel from this
5994 reboot(RB_ENABLE_CAD);
5999 log_info("Halting.");
6000 reboot(RB_HALT_SYSTEM);
6003 case ACTION_POWEROFF:
6004 log_info("Powering off.");
6005 reboot(RB_POWER_OFF);
6009 log_info("Rebooting.");
6010 reboot(RB_AUTOBOOT);
6014 assert_not_reached("Unknown halt action.");
6017 assert_not_reached("Uh? This shouldn't happen.");
6020 static int halt_main(DBusConnection *bus) {
6023 r = check_inhibitors(bus, arg_action);
6027 if (geteuid() != 0) {
6028 /* Try logind if we are a normal user and no special
6029 * mode applies. Maybe PolicyKit allows us to shutdown
6032 if (arg_when <= 0 &&
6035 (arg_action == ACTION_POWEROFF ||
6036 arg_action == ACTION_REBOOT)) {
6037 r = reboot_with_logind(bus, arg_action);
6042 log_error("Must be root.");
6047 _cleanup_free_ char *m;
6049 m = strv_join(arg_wall, " ");
6050 r = send_shutdownd(arg_when,
6051 arg_action == ACTION_HALT ? 'H' :
6052 arg_action == ACTION_POWEROFF ? 'P' :
6053 arg_action == ACTION_KEXEC ? 'K' :
6060 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
6062 char date[FORMAT_TIMESTAMP_MAX];
6064 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
6065 format_timestamp(date, sizeof(date), arg_when));
6070 if (!arg_dry && !arg_force)
6071 return start_with_fallback(bus);
6074 if (sd_booted() > 0)
6075 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
6077 r = utmp_put_shutdown();
6079 log_warning("Failed to write utmp record: %s", strerror(-r));
6086 halt_now(arg_action);
6087 /* We should never reach this. */
6091 static int runlevel_main(void) {
6092 int r, runlevel, previous;
6094 r = utmp_get_runlevel(&runlevel, &previous);
6101 previous <= 0 ? 'N' : previous,
6102 runlevel <= 0 ? 'N' : runlevel);
6107 int main(int argc, char*argv[]) {
6108 int r, retval = EXIT_FAILURE;
6109 DBusConnection *bus = NULL;
6110 _cleanup_dbus_error_free_ DBusError error;
6112 dbus_error_init(&error);
6114 setlocale(LC_ALL, "");
6115 log_parse_environment();
6118 r = parse_argv(argc, argv);
6122 retval = EXIT_SUCCESS;
6126 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
6127 * let's shortcut this */
6128 if (arg_action == ACTION_RUNLEVEL) {
6129 r = runlevel_main();
6130 retval = r < 0 ? EXIT_FAILURE : r;
6134 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
6135 log_info("Running in chroot, ignoring request.");
6141 if (arg_transport == TRANSPORT_NORMAL)
6142 bus_connect(arg_scope == UNIT_FILE_SYSTEM ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &bus, &private_bus, &error);
6143 else if (arg_transport == TRANSPORT_POLKIT) {
6144 bus_connect_system_polkit(&bus, &error);
6145 private_bus = false;
6146 } else if (arg_transport == TRANSPORT_SSH) {
6147 bus_connect_system_ssh(arg_user, arg_host, &bus, &error);
6148 private_bus = false;
6150 assert_not_reached("Uh, invalid transport...");
6153 switch (arg_action) {
6155 case ACTION_SYSTEMCTL:
6156 r = systemctl_main(bus, argc, argv, &error);
6160 case ACTION_POWEROFF:
6166 case ACTION_RUNLEVEL2:
6167 case ACTION_RUNLEVEL3:
6168 case ACTION_RUNLEVEL4:
6169 case ACTION_RUNLEVEL5:
6171 case ACTION_EMERGENCY:
6172 case ACTION_DEFAULT:
6173 r = start_with_fallback(bus);
6178 r = reload_with_fallback(bus);
6181 case ACTION_CANCEL_SHUTDOWN: {
6185 m = strv_join(arg_wall, " ");
6187 retval = EXIT_FAILURE;
6191 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
6193 log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r));
6198 case ACTION_INVALID:
6199 case ACTION_RUNLEVEL:
6201 assert_not_reached("Unknown action");
6204 retval = r < 0 ? EXIT_FAILURE : r;
6208 dbus_connection_flush(bus);
6209 dbus_connection_close(bus);
6210 dbus_connection_unref(bus);
6215 strv_free(arg_types);
6216 strv_free(arg_load_states);
6217 strv_free(arg_properties);
6220 ask_password_agent_close();
6221 polkit_agent_close();