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 on_loaded = on = ansi_highlight_red(true);
386 off_loaded = off = ansi_highlight_red(false);
388 on_loaded = off_loaded = "";
390 if (streq(u->active_state, "failed")) {
391 on_active = on = ansi_highlight_red(true);
392 off_active = off = ansi_highlight_red(false);
394 on_active = off_active = "";
396 e = arg_full ? NULL : ellipsize(u->id, id_len, 33);
398 printf("%s%-*s%s %s%-6s%s %s%-*s %-*s%s %-*s",
399 on, id_len, e ? e : u->id, off,
400 on_loaded, u->load_state, off_loaded,
401 on_active, active_len, u->active_state,
402 sub_len, u->sub_state, off_active,
403 job_count ? job_len + 1 : 0, u->job_id ? u->job_type : "");
404 if (!arg_full && arg_no_pager)
405 printf("%.*s\n", desc_len, u->description);
407 printf("%s\n", u->description);
410 if (!arg_no_legend) {
411 const char *on, *off;
414 printf("\nLOAD = Reflects whether the unit definition was properly loaded.\n"
415 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
416 "SUB = The low-level unit activation state, values depend on unit type.\n");
418 printf("JOB = Pending job for the unit.\n");
420 on = ansi_highlight(true);
421 off = ansi_highlight(false);
423 on = ansi_highlight_red(true);
424 off = ansi_highlight_red(false);
428 printf("%s%u loaded units listed.%s\n"
429 "To show all installed unit files use 'systemctl list-unit-files'.\n",
432 printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
433 "To show all installed unit files use 'systemctl list-unit-files'.\n",
438 static int get_unit_list(
441 struct unit_info **unit_infos,
444 DBusMessageIter iter, sub;
452 r = bus_method_call_with_reply(
454 "org.freedesktop.systemd1",
455 "/org/freedesktop/systemd1",
456 "org.freedesktop.systemd1.Manager",
464 if (!dbus_message_iter_init(*reply, &iter) ||
465 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
466 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
467 log_error("Failed to parse reply.");
471 dbus_message_iter_recurse(&iter, &sub);
473 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
474 if (!GREEDY_REALLOC(*unit_infos, size, *c + 1))
477 bus_parse_unit_info(&sub, *unit_infos + *c);
480 dbus_message_iter_next(&sub);
486 static int list_units(DBusConnection *bus, char **args) {
487 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
488 _cleanup_free_ struct unit_info *unit_infos = NULL;
492 pager_open_if_enabled();
494 r = get_unit_list(bus, &reply, &unit_infos, &c);
498 qsort(unit_infos, c, sizeof(struct unit_info), compare_unit_info);
500 output_units_list(unit_infos, c);
505 static int get_triggered_units(
507 const char* unit_path,
510 const char *interface = "org.freedesktop.systemd1.Unit",
511 *triggers_property = "Triggers";
512 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
513 DBusMessageIter iter, sub;
516 r = bus_method_call_with_reply(bus,
517 "org.freedesktop.systemd1",
519 "org.freedesktop.DBus.Properties",
523 DBUS_TYPE_STRING, &interface,
524 DBUS_TYPE_STRING, &triggers_property,
529 if (!dbus_message_iter_init(reply, &iter) ||
530 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
531 log_error("Failed to parse reply.");
535 dbus_message_iter_recurse(&iter, &sub);
536 dbus_message_iter_recurse(&sub, &iter);
539 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
542 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
543 log_error("Failed to parse reply.");
547 dbus_message_iter_get_basic(&sub, &unit);
548 r = strv_extend(triggered, unit);
552 dbus_message_iter_next(&sub);
558 static int get_listening(DBusConnection *bus, const char* unit_path,
559 char*** listen, unsigned *c)
561 const char *interface = "org.freedesktop.systemd1.Socket",
562 *listen_property = "Listen";
563 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
564 DBusMessageIter iter, sub;
567 r = bus_method_call_with_reply(bus,
568 "org.freedesktop.systemd1",
570 "org.freedesktop.DBus.Properties",
574 DBUS_TYPE_STRING, &interface,
575 DBUS_TYPE_STRING, &listen_property,
580 if (!dbus_message_iter_init(reply, &iter) ||
581 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
582 log_error("Failed to parse reply.");
586 dbus_message_iter_recurse(&iter, &sub);
587 dbus_message_iter_recurse(&sub, &iter);
590 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
591 DBusMessageIter sub2;
592 const char *type, *path;
594 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
595 log_error("Failed to parse reply.");
599 dbus_message_iter_recurse(&sub, &sub2);
601 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
602 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0) {
603 r = strv_extend(listen, type);
607 r = strv_extend(listen, path);
614 dbus_message_iter_next(&sub);
626 /* Note: triggered is a list here, although it almost certainly
627 * will always be one unit. Nevertheless, dbus API allows for multiple
628 * values, so let's follow that.*/
631 /* The strv above is shared. free is set only in the first one. */
635 static int socket_info_compare(struct socket_info *a, struct socket_info *b) {
636 int o = strcmp(a->path, b->path);
638 o = strcmp(a->type, b->type);
642 static int output_sockets_list(struct socket_info *socket_infos, unsigned cs) {
643 struct socket_info *s;
644 unsigned pathlen = sizeof("LISTEN") - 1,
645 typelen = (sizeof("TYPE") - 1) * arg_show_types,
646 socklen = sizeof("UNIT") - 1,
647 servlen = sizeof("ACTIVATES") - 1;
648 const char *on, *off;
650 for (s = socket_infos; s < socket_infos + cs; s++) {
654 socklen = MAX(socklen, strlen(s->id));
656 typelen = MAX(typelen, strlen(s->type));
657 pathlen = MAX(pathlen, strlen(s->path));
659 STRV_FOREACH(a, s->triggered)
660 tmp += strlen(*a) + 2*(a != s->triggered);
661 servlen = MAX(servlen, tmp);
666 printf("%-*s %-*.*s%-*s %s\n",
668 typelen + arg_show_types, typelen + arg_show_types, "TYPE ",
672 for (s = socket_infos; s < socket_infos + cs; s++) {
676 printf("%-*s %-*s %-*s",
677 pathlen, s->path, typelen, s->type, socklen, s->id);
680 pathlen, s->path, socklen, s->id);
681 STRV_FOREACH(a, s->triggered)
683 a == s->triggered ? "" : ",", *a);
687 on = ansi_highlight(true);
688 off = ansi_highlight(false);
692 on = ansi_highlight_red(true);
693 off = ansi_highlight_red(false);
696 if (!arg_no_legend) {
697 printf("%s%u sockets listed.%s\n", on, cs, off);
699 printf("Pass --all to see loaded but inactive sockets, too.\n");
705 static int list_sockets(DBusConnection *bus, char **args) {
706 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
707 _cleanup_free_ struct unit_info *unit_infos = NULL;
708 struct socket_info *socket_infos = NULL;
709 const struct unit_info *u;
710 struct socket_info *s;
711 unsigned cu = 0, cs = 0;
715 pager_open_if_enabled();
717 r = get_unit_list(bus, &reply, &unit_infos, &cu);
721 for (u = unit_infos; u < unit_infos + cu; u++) {
723 _cleanup_strv_free_ char **listen = NULL, **triggered = NULL;
726 if (!output_show_unit(u))
729 if ((dot = strrchr(u->id, '.')) && !streq(dot+1, "socket"))
732 r = get_triggered_units(bus, u->unit_path, &triggered);
736 r = get_listening(bus, u->unit_path, &listen, &c);
740 if (!GREEDY_REALLOC(socket_infos, size, cs + c)) {
745 for (i = 0; i < c; i++)
746 socket_infos[cs + i] = (struct socket_info) {
749 .path = listen[i*2 + 1],
750 .triggered = triggered,
751 .own_triggered = i==0,
754 /* from this point on we will cleanup those socket_infos */
757 listen = triggered = NULL; /* avoid cleanup */
760 qsort(socket_infos, cs, sizeof(struct socket_info),
761 (__compar_fn_t) socket_info_compare);
763 output_sockets_list(socket_infos, cs);
766 assert(cs == 0 || socket_infos);
767 for (s = socket_infos; s < socket_infos + cs; s++) {
770 if (s->own_triggered)
771 strv_free(s->triggered);
778 static int compare_unit_file_list(const void *a, const void *b) {
780 const UnitFileList *u = a, *v = b;
782 d1 = strrchr(u->path, '.');
783 d2 = strrchr(v->path, '.');
788 r = strcasecmp(d1, d2);
793 return strcasecmp(path_get_file_name(u->path), path_get_file_name(v->path));
796 static bool output_show_unit_file(const UnitFileList *u) {
799 return !arg_types || ((dot = strrchr(u->path, '.')) && strv_find(arg_types, dot+1));
802 static void output_unit_file_list(const UnitFileList *units, unsigned c) {
803 unsigned max_id_len, id_cols, state_cols, n_shown = 0;
804 const UnitFileList *u;
806 max_id_len = sizeof("UNIT FILE")-1;
807 state_cols = sizeof("STATE")-1;
808 for (u = units; u < units + c; u++) {
809 if (!output_show_unit_file(u))
812 max_id_len = MAX(max_id_len, strlen(path_get_file_name(u->path)));
813 state_cols = MAX(state_cols, strlen(unit_file_state_to_string(u->state)));
818 id_cols = MIN(max_id_len, 25u);
819 basic_cols = 1 + id_cols + state_cols;
820 if (basic_cols < (unsigned) columns())
821 id_cols += MIN(columns() - basic_cols, max_id_len - id_cols);
823 id_cols = max_id_len;
826 printf("%-*s %-*s\n", id_cols, "UNIT FILE", state_cols, "STATE");
828 for (u = units; u < units + c; u++) {
829 _cleanup_free_ char *e = NULL;
830 const char *on, *off;
833 if (!output_show_unit_file(u))
838 if (u->state == UNIT_FILE_MASKED ||
839 u->state == UNIT_FILE_MASKED_RUNTIME ||
840 u->state == UNIT_FILE_DISABLED ||
841 u->state == UNIT_FILE_INVALID) {
842 on = ansi_highlight_red(true);
843 off = ansi_highlight_red(false);
844 } else if (u->state == UNIT_FILE_ENABLED) {
845 on = ansi_highlight_green(true);
846 off = ansi_highlight_green(false);
850 id = path_get_file_name(u->path);
852 e = arg_full ? NULL : ellipsize(id, id_cols, 33);
854 printf("%-*s %s%-*s%s\n",
856 on, state_cols, unit_file_state_to_string(u->state), off);
860 printf("\n%u unit files listed.\n", n_shown);
863 static int list_unit_files(DBusConnection *bus, char **args) {
864 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
865 _cleanup_free_ UnitFileList *units = NULL;
866 DBusMessageIter iter, sub, sub2;
867 unsigned c = 0, n_units = 0;
870 pager_open_if_enabled();
877 h = hashmap_new(string_hash_func, string_compare_func);
881 r = unit_file_get_list(arg_scope, arg_root, h);
883 unit_file_list_free(h);
884 log_error("Failed to get unit file list: %s", strerror(-r));
888 n_units = hashmap_size(h);
889 units = new(UnitFileList, n_units);
891 unit_file_list_free(h);
895 HASHMAP_FOREACH(u, h, i) {
896 memcpy(units + c++, u, sizeof(UnitFileList));
902 r = bus_method_call_with_reply(
904 "org.freedesktop.systemd1",
905 "/org/freedesktop/systemd1",
906 "org.freedesktop.systemd1.Manager",
914 if (!dbus_message_iter_init(reply, &iter) ||
915 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
916 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
917 log_error("Failed to parse reply.");
921 dbus_message_iter_recurse(&iter, &sub);
923 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
927 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT);
932 n_units = MAX(2*c, 16u);
933 w = realloc(units, sizeof(struct UnitFileList) * n_units);
942 dbus_message_iter_recurse(&sub, &sub2);
944 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->path, true) < 0 ||
945 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, false) < 0) {
946 log_error("Failed to parse reply.");
950 u->state = unit_file_state_from_string(state);
952 dbus_message_iter_next(&sub);
958 qsort(units, c, sizeof(UnitFileList), compare_unit_file_list);
959 output_unit_file_list(units, c);
965 static int list_dependencies_print(const char *name, int level, unsigned int branches, bool last) {
967 _cleanup_free_ char *n = NULL;
969 size_t max_len = MAX(columns(),20u);
972 for (i = level - 1; i >= 0; i--) {
974 if(len > max_len - 3 && !arg_full) {
975 printf("%s...\n",max_len % 2 ? "" : " ");
978 printf("%s", draw_special_char(branches & (1 << i) ? DRAW_TREE_VERT : DRAW_TREE_SPACE));
981 if(len > max_len - 3 && !arg_full) {
982 printf("%s...\n",max_len % 2 ? "" : " ");
985 printf("%s", draw_special_char(last ? DRAW_TREE_RIGHT : DRAW_TREE_BRANCH));
989 printf("%s\n", name);
993 n = ellipsize(name, max_len-len, 100);
1001 static int list_dependencies_get_dependencies(DBusConnection *bus, const char *name, char ***deps) {
1002 static const char *dependencies[] = {
1003 [DEPENDENCY_FORWARD] = "Requires\0"
1004 "RequiresOverridable\0"
1006 "RequisiteOverridable\0"
1008 [DEPENDENCY_REVERSE] = "RequiredBy\0"
1009 "RequiredByOverridable\0"
1012 [DEPENDENCY_AFTER] = "After\0",
1013 [DEPENDENCY_BEFORE] = "Before\0",
1016 _cleanup_free_ char *path;
1017 const char *interface = "org.freedesktop.systemd1.Unit";
1019 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1020 DBusMessageIter iter, sub, sub2, sub3;
1029 path = unit_dbus_path_from_name(name);
1035 r = bus_method_call_with_reply(
1037 "org.freedesktop.systemd1",
1039 "org.freedesktop.DBus.Properties",
1043 DBUS_TYPE_STRING, &interface,
1048 if (!dbus_message_iter_init(reply, &iter) ||
1049 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
1050 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
1051 log_error("Failed to parse reply.");
1056 dbus_message_iter_recurse(&iter, &sub);
1058 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1061 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_DICT_ENTRY);
1062 dbus_message_iter_recurse(&sub, &sub2);
1064 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &prop, true) < 0) {
1065 log_error("Failed to parse reply.");
1070 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
1071 log_error("Failed to parse reply.");
1076 dbus_message_iter_recurse(&sub2, &sub3);
1077 dbus_message_iter_next(&sub);
1079 assert(arg_dependency < ELEMENTSOF(dependencies));
1080 if (!nulstr_contains(dependencies[arg_dependency], prop))
1083 if (dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_ARRAY) {
1084 if (dbus_message_iter_get_element_type(&sub3) == DBUS_TYPE_STRING) {
1085 DBusMessageIter sub4;
1086 dbus_message_iter_recurse(&sub3, &sub4);
1088 while (dbus_message_iter_get_arg_type(&sub4) != DBUS_TYPE_INVALID) {
1091 assert(dbus_message_iter_get_arg_type(&sub4) == DBUS_TYPE_STRING);
1092 dbus_message_iter_get_basic(&sub4, &s);
1094 r = strv_extend(&ret, s);
1100 dbus_message_iter_next(&sub4);
1113 static int list_dependencies_compare(const void *_a, const void *_b) {
1114 const char **a = (const char**) _a, **b = (const char**) _b;
1115 if (unit_name_to_type(*a) == UNIT_TARGET && unit_name_to_type(*b) != UNIT_TARGET)
1117 if (unit_name_to_type(*a) != UNIT_TARGET && unit_name_to_type(*b) == UNIT_TARGET)
1119 return strcasecmp(*a, *b);
1122 static int list_dependencies_one(DBusConnection *bus, const char *name, int level, char ***units, unsigned int branches) {
1123 _cleanup_strv_free_ char **deps = NULL, **u;
1127 u = strv_append(*units, name);
1131 r = list_dependencies_get_dependencies(bus, name, &deps);
1135 qsort(deps, strv_length(deps), sizeof (char*), list_dependencies_compare);
1137 STRV_FOREACH(c, deps) {
1138 if (strv_contains(u, *c)) {
1140 r = list_dependencies_print("...", level + 1, (branches << 1) | (c[1] == NULL ? 0 : 1), 1);
1147 r = list_dependencies_print(*c, level, branches, c[1] == NULL);
1151 if (arg_all || unit_name_to_type(*c) == UNIT_TARGET) {
1152 r = list_dependencies_one(bus, *c, level + 1, &u, (branches << 1) | (c[1] == NULL ? 0 : 1));
1165 static int list_dependencies(DBusConnection *bus, char **args) {
1166 _cleanup_free_ char *unit = NULL;
1167 _cleanup_strv_free_ char **units = NULL;
1173 unit = unit_name_mangle(args[1]);
1178 u = SPECIAL_DEFAULT_TARGET;
1180 pager_open_if_enabled();
1184 return list_dependencies_one(bus, u, 0, &units, 0);
1187 static int get_default(DBusConnection *bus, char **args) {
1189 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
1191 _cleanup_dbus_error_free_ DBusError error;
1193 dbus_error_init(&error);
1195 if (!bus || avoid_bus()) {
1196 r = unit_file_get_default(arg_scope, arg_root, &path);
1199 log_error("Operation failed: %s", strerror(-r));
1205 r = bus_method_call_with_reply(
1207 "org.freedesktop.systemd1",
1208 "/org/freedesktop/systemd1",
1209 "org.freedesktop.systemd1.Manager",
1216 log_error("Operation failed: %s", strerror(-r));
1220 if (!dbus_message_get_args(reply, &error,
1221 DBUS_TYPE_STRING, &path,
1222 DBUS_TYPE_INVALID)) {
1223 log_error("Failed to parse reply: %s", bus_error_message(&error));
1224 dbus_error_free(&error);
1230 printf("%s\n", path);
1233 if ((!bus || avoid_bus()) && path)
1242 char *name, *type, *state;
1245 static void list_jobs_print(struct job_info* jobs, size_t n) {
1248 const char *on, *off;
1249 bool shorten = false;
1251 assert(n == 0 || jobs);
1254 on = ansi_highlight_green(true);
1255 off = ansi_highlight_green(false);
1257 printf("%sNo jobs running.%s\n", on, off);
1261 pager_open_if_enabled();
1264 /* JOB UNIT TYPE STATE */
1265 unsigned l0 = 3, l1 = 4, l2 = 4, l3 = 5;
1267 for (i = 0, j = jobs; i < n; i++, j++) {
1268 assert(j->name && j->type && j->state);
1269 l0 = MAX(l0, DECIMAL_STR_WIDTH(j->id));
1270 l1 = MAX(l1, strlen(j->name));
1271 l2 = MAX(l2, strlen(j->type));
1272 l3 = MAX(l3, strlen(j->state));
1275 if (!arg_full && l0 + 1 + l1 + l2 + 1 + l3 > columns()) {
1276 l1 = MAX(33u, columns() - l0 - l2 - l3 - 3);
1281 printf("%*s %-*s %-*s %-*s\n",
1287 for (i = 0, j = jobs; i < n; i++, j++) {
1288 _cleanup_free_ char *e = NULL;
1290 if (streq(j->state, "running")) {
1291 on = ansi_highlight(true);
1292 off = ansi_highlight(false);
1296 e = shorten ? ellipsize(j->name, l1, 33) : NULL;
1297 printf("%*u %s%-*s%s %-*s %s%-*s%s\n",
1299 on, l1, e ? e : j->name, off,
1301 on, l3, j->state, off);
1305 on = ansi_highlight(true);
1306 off = ansi_highlight(false);
1309 printf("\n%s%zu jobs listed%s.\n", on, n, off);
1312 static int list_jobs(DBusConnection *bus, char **args) {
1313 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1314 DBusMessageIter iter, sub, sub2;
1316 struct job_info *jobs = NULL;
1317 size_t size = 0, used = 0;
1319 r = bus_method_call_with_reply(
1321 "org.freedesktop.systemd1",
1322 "/org/freedesktop/systemd1",
1323 "org.freedesktop.systemd1.Manager",
1331 if (!dbus_message_iter_init(reply, &iter) ||
1332 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
1333 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
1334 log_error("Failed to parse reply.");
1338 dbus_message_iter_recurse(&iter, &sub);
1340 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1341 const char *name, *type, *state, *job_path, *unit_path;
1344 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
1345 log_error("Failed to parse reply.");
1349 dbus_message_iter_recurse(&sub, &sub2);
1351 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &id, true) < 0 ||
1352 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
1353 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
1354 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, true) < 0 ||
1355 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &job_path, true) < 0 ||
1356 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, false) < 0) {
1357 log_error("Failed to parse reply.");
1362 if (!GREEDY_REALLOC(jobs, size, used + 1)) {
1367 jobs[used++] = (struct job_info) { id,
1371 if (!jobs[used-1].name || !jobs[used-1].type || !jobs[used-1].state) {
1376 dbus_message_iter_next(&sub);
1379 list_jobs_print(jobs, used);
1383 free(jobs[used].name);
1384 free(jobs[used].type);
1385 free(jobs[used].state);
1392 static int load_unit(DBusConnection *bus, char **args) {
1397 STRV_FOREACH(name, args+1) {
1398 _cleanup_free_ char *n = NULL;
1401 n = unit_name_mangle(*name);
1405 r = bus_method_call_with_reply(
1407 "org.freedesktop.systemd1",
1408 "/org/freedesktop/systemd1",
1409 "org.freedesktop.systemd1.Manager",
1413 DBUS_TYPE_STRING, &n,
1422 static int cancel_job(DBusConnection *bus, char **args) {
1427 if (strv_length(args) <= 1)
1428 return daemon_reload(bus, args);
1430 STRV_FOREACH(name, args+1) {
1434 r = safe_atou32(*name, &id);
1436 log_error("Failed to parse job id: %s", strerror(-r));
1440 r = bus_method_call_with_reply(
1442 "org.freedesktop.systemd1",
1443 "/org/freedesktop/systemd1",
1444 "org.freedesktop.systemd1.Manager",
1448 DBUS_TYPE_UINT32, &id,
1457 static int need_daemon_reload(DBusConnection *bus, const char *unit) {
1458 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1459 _cleanup_dbus_error_free_ DBusError error;
1460 dbus_bool_t b = FALSE;
1461 DBusMessageIter iter, sub;
1463 *interface = "org.freedesktop.systemd1.Unit",
1464 *property = "NeedDaemonReload",
1466 _cleanup_free_ char *n = NULL;
1469 dbus_error_init(&error);
1471 /* We ignore all errors here, since this is used to show a warning only */
1473 n = unit_name_mangle(unit);
1477 r = bus_method_call_with_reply(
1479 "org.freedesktop.systemd1",
1480 "/org/freedesktop/systemd1",
1481 "org.freedesktop.systemd1.Manager",
1485 DBUS_TYPE_STRING, &n,
1490 if (!dbus_message_get_args(reply, NULL,
1491 DBUS_TYPE_OBJECT_PATH, &path,
1495 dbus_message_unref(reply);
1498 r = bus_method_call_with_reply(
1500 "org.freedesktop.systemd1",
1502 "org.freedesktop.DBus.Properties",
1506 DBUS_TYPE_STRING, &interface,
1507 DBUS_TYPE_STRING, &property,
1512 if (!dbus_message_iter_init(reply, &iter) ||
1513 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
1516 dbus_message_iter_recurse(&iter, &sub);
1517 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_BOOLEAN)
1520 dbus_message_iter_get_basic(&sub, &b);
1524 typedef struct WaitData {
1531 static DBusHandlerResult wait_filter(DBusConnection *connection, DBusMessage *message, void *data) {
1532 _cleanup_dbus_error_free_ DBusError error;
1535 dbus_error_init(&error);
1541 log_debug("Got D-Bus request: %s.%s() on %s",
1542 dbus_message_get_interface(message),
1543 dbus_message_get_member(message),
1544 dbus_message_get_path(message));
1546 if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
1547 log_error("Warning! D-Bus connection terminated.");
1548 dbus_connection_close(connection);
1550 } else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
1552 const char *path, *result, *unit;
1554 if (dbus_message_get_args(message, &error,
1555 DBUS_TYPE_UINT32, &id,
1556 DBUS_TYPE_OBJECT_PATH, &path,
1557 DBUS_TYPE_STRING, &unit,
1558 DBUS_TYPE_STRING, &result,
1559 DBUS_TYPE_INVALID)) {
1561 free(set_remove(d->set, (char*) path));
1563 if (!isempty(result))
1564 d->result = strdup(result);
1567 d->name = strdup(unit);
1569 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1572 dbus_error_free(&error);
1573 if (dbus_message_get_args(message, &error,
1574 DBUS_TYPE_UINT32, &id,
1575 DBUS_TYPE_OBJECT_PATH, &path,
1576 DBUS_TYPE_STRING, &result,
1577 DBUS_TYPE_INVALID)) {
1578 /* Compatibility with older systemd versions <
1579 * 183 during upgrades. This should be dropped
1581 free(set_remove(d->set, (char*) path));
1584 d->result = strdup(result);
1586 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1590 log_error("Failed to parse message: %s", bus_error_message(&error));
1593 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1596 static int enable_wait_for_jobs(DBusConnection *bus) {
1604 dbus_error_init(&error);
1605 dbus_bus_add_match(bus,
1607 "sender='org.freedesktop.systemd1',"
1608 "interface='org.freedesktop.systemd1.Manager',"
1609 "member='JobRemoved',"
1610 "path='/org/freedesktop/systemd1'",
1613 if (dbus_error_is_set(&error)) {
1614 log_error("Failed to add match: %s", bus_error_message(&error));
1615 dbus_error_free(&error);
1619 /* This is slightly dirty, since we don't undo the match registrations. */
1623 static int wait_for_jobs(DBusConnection *bus, Set *s) {
1625 WaitData d = { .set = s };
1630 if (!dbus_connection_add_filter(bus, wait_filter, &d, NULL))
1633 while (!set_isempty(s)) {
1635 if (!dbus_connection_read_write_dispatch(bus, -1)) {
1636 log_error("Disconnected from bus.");
1637 return -ECONNREFUSED;
1644 if (streq(d.result, "timeout"))
1645 log_error("Job for %s timed out.", strna(d.name));
1646 else if (streq(d.result, "canceled"))
1647 log_error("Job for %s canceled.", strna(d.name));
1648 else if (streq(d.result, "dependency"))
1649 log_error("A dependency job for %s failed. See 'journalctl -xn' for details.", strna(d.name));
1650 else if (!streq(d.result, "done") && !streq(d.result, "skipped"))
1651 log_error("Job for %s failed. See 'systemctl status %s' and 'journalctl -xn' for details.", strna(d.name), strna(d.name));
1654 if (streq_ptr(d.result, "timeout"))
1656 else if (streq_ptr(d.result, "canceled"))
1658 else if (!streq_ptr(d.result, "done") && !streq_ptr(d.result, "skipped"))
1669 dbus_connection_remove_filter(bus, wait_filter, &d);
1673 static int check_one_unit(DBusConnection *bus, const char *name, char **check_states, bool quiet) {
1674 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1675 _cleanup_free_ char *n = NULL;
1676 DBusMessageIter iter, sub;
1678 *interface = "org.freedesktop.systemd1.Unit",
1679 *property = "ActiveState";
1680 const char *state, *path;
1686 dbus_error_init(&error);
1688 n = unit_name_mangle(name);
1692 r = bus_method_call_with_reply (
1694 "org.freedesktop.systemd1",
1695 "/org/freedesktop/systemd1",
1696 "org.freedesktop.systemd1.Manager",
1700 DBUS_TYPE_STRING, &n,
1703 dbus_error_free(&error);
1710 if (!dbus_message_get_args(reply, NULL,
1711 DBUS_TYPE_OBJECT_PATH, &path,
1712 DBUS_TYPE_INVALID)) {
1713 log_error("Failed to parse reply.");
1717 dbus_message_unref(reply);
1720 r = bus_method_call_with_reply(
1722 "org.freedesktop.systemd1",
1724 "org.freedesktop.DBus.Properties",
1728 DBUS_TYPE_STRING, &interface,
1729 DBUS_TYPE_STRING, &property,
1737 if (!dbus_message_iter_init(reply, &iter) ||
1738 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1739 log_error("Failed to parse reply.");
1743 dbus_message_iter_recurse(&iter, &sub);
1745 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1746 log_error("Failed to parse reply.");
1750 dbus_message_iter_get_basic(&sub, &state);
1755 return strv_find(check_states, state) ? 1 : 0;
1758 static void check_triggering_units(
1759 DBusConnection *bus,
1760 const char *unit_name) {
1762 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1763 DBusMessageIter iter, sub;
1764 const char *interface = "org.freedesktop.systemd1.Unit",
1765 *load_state_property = "LoadState",
1766 *triggered_by_property = "TriggeredBy",
1768 _cleanup_free_ char *unit_path = NULL, *n = NULL;
1769 bool print_warning_label = true;
1772 n = unit_name_mangle(unit_name);
1778 unit_path = unit_dbus_path_from_name(n);
1784 r = bus_method_call_with_reply(
1786 "org.freedesktop.systemd1",
1788 "org.freedesktop.DBus.Properties",
1792 DBUS_TYPE_STRING, &interface,
1793 DBUS_TYPE_STRING, &load_state_property,
1798 if (!dbus_message_iter_init(reply, &iter) ||
1799 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1800 log_error("Failed to parse reply.");
1804 dbus_message_iter_recurse(&iter, &sub);
1806 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1807 log_error("Failed to parse reply.");
1811 dbus_message_iter_get_basic(&sub, &state);
1813 if (streq(state, "masked"))
1816 dbus_message_unref(reply);
1819 r = bus_method_call_with_reply(
1821 "org.freedesktop.systemd1",
1823 "org.freedesktop.DBus.Properties",
1827 DBUS_TYPE_STRING, &interface,
1828 DBUS_TYPE_STRING, &triggered_by_property,
1833 if (!dbus_message_iter_init(reply, &iter) ||
1834 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1835 log_error("Failed to parse reply.");
1839 dbus_message_iter_recurse(&iter, &sub);
1840 dbus_message_iter_recurse(&sub, &iter);
1843 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1844 const char * const check_states[] = {
1849 const char *service_trigger;
1851 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1852 log_error("Failed to parse reply.");
1856 dbus_message_iter_get_basic(&sub, &service_trigger);
1858 r = check_one_unit(bus, service_trigger, (char**) check_states, true);
1862 if (print_warning_label) {
1863 log_warning("Warning: Stopping %s, but it can still be activated by:", unit_name);
1864 print_warning_label = false;
1867 log_warning(" %s", service_trigger);
1870 dbus_message_iter_next(&sub);
1874 static int start_unit_one(
1875 DBusConnection *bus,
1882 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1883 _cleanup_free_ char *n;
1892 n = unit_name_mangle(name);
1896 r = bus_method_call_with_reply(
1898 "org.freedesktop.systemd1",
1899 "/org/freedesktop/systemd1",
1900 "org.freedesktop.systemd1.Manager",
1904 DBUS_TYPE_STRING, &n,
1905 DBUS_TYPE_STRING, &mode,
1908 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
1909 /* There's always a fallback possible for
1910 * legacy actions. */
1913 log_error("Failed to issue method call: %s", bus_error_message(error));
1918 if (!dbus_message_get_args(reply, error,
1919 DBUS_TYPE_OBJECT_PATH, &path,
1920 DBUS_TYPE_INVALID)) {
1921 log_error("Failed to parse reply: %s", bus_error_message(error));
1925 if (need_daemon_reload(bus, n) > 0)
1926 log_warning("Warning: Unit file of %s changed on disk, 'systemctl %sdaemon-reload' recommended.",
1927 n, arg_scope == UNIT_FILE_SYSTEM ? "" : "--user ");
1936 r = set_consume(s, p);
1938 log_error("Failed to add path to set.");
1946 static const struct {
1950 } action_table[_ACTION_MAX] = {
1951 [ACTION_HALT] = { SPECIAL_HALT_TARGET, "halt", "replace-irreversibly" },
1952 [ACTION_POWEROFF] = { SPECIAL_POWEROFF_TARGET, "poweroff", "replace-irreversibly" },
1953 [ACTION_REBOOT] = { SPECIAL_REBOOT_TARGET, "reboot", "replace-irreversibly" },
1954 [ACTION_KEXEC] = { SPECIAL_KEXEC_TARGET, "kexec", "replace-irreversibly" },
1955 [ACTION_RUNLEVEL2] = { SPECIAL_RUNLEVEL2_TARGET, NULL, "isolate" },
1956 [ACTION_RUNLEVEL3] = { SPECIAL_RUNLEVEL3_TARGET, NULL, "isolate" },
1957 [ACTION_RUNLEVEL4] = { SPECIAL_RUNLEVEL4_TARGET, NULL, "isolate" },
1958 [ACTION_RUNLEVEL5] = { SPECIAL_RUNLEVEL5_TARGET, NULL, "isolate" },
1959 [ACTION_RESCUE] = { SPECIAL_RESCUE_TARGET, "rescue", "isolate" },
1960 [ACTION_EMERGENCY] = { SPECIAL_EMERGENCY_TARGET, "emergency", "isolate" },
1961 [ACTION_DEFAULT] = { SPECIAL_DEFAULT_TARGET, "default", "isolate" },
1962 [ACTION_EXIT] = { SPECIAL_EXIT_TARGET, "exit", "replace-irreversibly" },
1963 [ACTION_SUSPEND] = { SPECIAL_SUSPEND_TARGET, "suspend", "replace-irreversibly" },
1964 [ACTION_HIBERNATE] = { SPECIAL_HIBERNATE_TARGET, "hibernate", "replace-irreversibly" },
1965 [ACTION_HYBRID_SLEEP] = { SPECIAL_HYBRID_SLEEP_TARGET, "hybrid-sleep", "replace-irreversibly" },
1968 static enum action verb_to_action(const char *verb) {
1971 for (i = ACTION_INVALID; i < _ACTION_MAX; i++)
1972 if (action_table[i].verb && streq(verb, action_table[i].verb))
1974 return ACTION_INVALID;
1977 static int start_unit(DBusConnection *bus, char **args) {
1980 const char *method, *mode, *one_name;
1981 _cleanup_set_free_free_ Set *s = NULL;
1982 _cleanup_dbus_error_free_ DBusError error;
1985 dbus_error_init(&error);
1989 ask_password_agent_open_if_enabled();
1991 if (arg_action == ACTION_SYSTEMCTL) {
1994 streq(args[0], "stop") ||
1995 streq(args[0], "condstop") ? "StopUnit" :
1996 streq(args[0], "reload") ? "ReloadUnit" :
1997 streq(args[0], "restart") ? "RestartUnit" :
1999 streq(args[0], "try-restart") ||
2000 streq(args[0], "condrestart") ? "TryRestartUnit" :
2002 streq(args[0], "reload-or-restart") ? "ReloadOrRestartUnit" :
2004 streq(args[0], "reload-or-try-restart") ||
2005 streq(args[0], "condreload") ||
2007 streq(args[0], "force-reload") ? "ReloadOrTryRestartUnit" :
2009 action = verb_to_action(args[0]);
2011 mode = streq(args[0], "isolate") ? "isolate" :
2012 action_table[action].mode ?: arg_job_mode;
2014 one_name = action_table[action].target;
2017 assert(arg_action < ELEMENTSOF(action_table));
2018 assert(action_table[arg_action].target);
2020 method = "StartUnit";
2022 mode = action_table[arg_action].mode;
2023 one_name = action_table[arg_action].target;
2026 if (!arg_no_block) {
2027 ret = enable_wait_for_jobs(bus);
2029 log_error("Could not watch jobs: %s", strerror(-ret));
2033 s = set_new(string_hash_func, string_compare_func);
2039 ret = start_unit_one(bus, method, one_name, mode, &error, s);
2041 ret = translate_bus_error_to_exit_status(ret, &error);
2043 STRV_FOREACH(name, args+1) {
2044 r = start_unit_one(bus, method, *name, mode, &error, s);
2046 ret = translate_bus_error_to_exit_status(r, &error);
2047 dbus_error_free(&error);
2052 if (!arg_no_block) {
2053 r = wait_for_jobs(bus, s);
2057 /* When stopping units, warn if they can still be triggered by
2058 * another active unit (socket, path, timer) */
2059 if (!arg_quiet && streq(method, "StopUnit")) {
2061 check_triggering_units(bus, one_name);
2063 STRV_FOREACH(name, args+1)
2064 check_triggering_units(bus, *name);
2071 /* Ask systemd-logind, which might grant access to unprivileged users
2072 * through PolicyKit */
2073 static int reboot_with_logind(DBusConnection *bus, enum action a) {
2076 dbus_bool_t interactive = true;
2081 polkit_agent_open_if_enabled();
2089 case ACTION_POWEROFF:
2090 method = "PowerOff";
2093 case ACTION_SUSPEND:
2097 case ACTION_HIBERNATE:
2098 method = "Hibernate";
2101 case ACTION_HYBRID_SLEEP:
2102 method = "HybridSleep";
2109 return bus_method_call_with_reply(
2111 "org.freedesktop.login1",
2112 "/org/freedesktop/login1",
2113 "org.freedesktop.login1.Manager",
2117 DBUS_TYPE_BOOLEAN, &interactive,
2124 static int check_inhibitors(DBusConnection *bus, enum action a) {
2126 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
2127 DBusMessageIter iter, sub, sub2;
2130 _cleanup_strv_free_ char **sessions = NULL;
2136 if (arg_ignore_inhibitors || arg_force > 0)
2148 r = bus_method_call_with_reply(
2150 "org.freedesktop.login1",
2151 "/org/freedesktop/login1",
2152 "org.freedesktop.login1.Manager",
2158 /* If logind is not around, then there are no inhibitors... */
2161 if (!dbus_message_iter_init(reply, &iter) ||
2162 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
2163 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
2164 log_error("Failed to parse reply.");
2168 dbus_message_iter_recurse(&iter, &sub);
2169 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
2170 const char *what, *who, *why, *mode;
2172 _cleanup_strv_free_ char **sv = NULL;
2173 _cleanup_free_ char *comm = NULL, *user = NULL;
2175 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
2176 log_error("Failed to parse reply.");
2180 dbus_message_iter_recurse(&sub, &sub2);
2182 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &what, true) < 0 ||
2183 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &who, true) < 0 ||
2184 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &why, true) < 0 ||
2185 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &mode, true) < 0 ||
2186 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &uid, true) < 0 ||
2187 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, false) < 0) {
2188 log_error("Failed to parse reply.");
2192 if (!streq(mode, "block"))
2195 sv = strv_split(what, ":");
2199 if (!strv_contains(sv,
2201 a == ACTION_POWEROFF ||
2202 a == ACTION_REBOOT ||
2203 a == ACTION_KEXEC ? "shutdown" : "sleep"))
2206 get_process_comm(pid, &comm);
2207 user = uid_to_name(uid);
2208 log_warning("Operation inhibited by \"%s\" (PID %lu \"%s\", user %s), reason is \"%s\".",
2209 who, (unsigned long) pid, strna(comm), strna(user), why);
2213 dbus_message_iter_next(&sub);
2216 dbus_message_iter_recurse(&iter, &sub);
2218 /* Check for current sessions */
2219 sd_get_sessions(&sessions);
2220 STRV_FOREACH(s, sessions) {
2222 _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL;
2224 if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid())
2227 if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
2230 if (sd_session_get_type(*s, &type) < 0 || (!streq(type, "x11") && !streq(type, "tty")))
2233 sd_session_get_tty(*s, &tty);
2234 sd_session_get_seat(*s, &seat);
2235 sd_session_get_service(*s, &service);
2236 user = uid_to_name(uid);
2238 log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty);
2245 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
2246 action_table[a].verb);
2254 static int start_special(DBusConnection *bus, char **args) {
2260 a = verb_to_action(args[0]);
2262 r = check_inhibitors(bus, a);
2266 if (arg_force >= 2 && geteuid() != 0) {
2267 log_error("Must be root.");
2271 if (arg_force >= 2 &&
2272 (a == ACTION_HALT ||
2273 a == ACTION_POWEROFF ||
2274 a == ACTION_REBOOT))
2277 if (arg_force >= 1 &&
2278 (a == ACTION_HALT ||
2279 a == ACTION_POWEROFF ||
2280 a == ACTION_REBOOT ||
2281 a == ACTION_KEXEC ||
2283 return daemon_reload(bus, args);
2285 /* first try logind, to allow authentication with polkit */
2286 if (geteuid() != 0 &&
2287 (a == ACTION_POWEROFF ||
2288 a == ACTION_REBOOT ||
2289 a == ACTION_SUSPEND ||
2290 a == ACTION_HIBERNATE ||
2291 a == ACTION_HYBRID_SLEEP)) {
2292 r = reboot_with_logind(bus, a);
2297 r = start_unit(bus, args);
2298 if (r == EXIT_SUCCESS)
2304 static int check_unit_active(DBusConnection *bus, char **args) {
2305 const char * const check_states[] = {
2312 int r = 3; /* According to LSB: "program is not running" */
2317 STRV_FOREACH(name, args+1) {
2320 state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
2330 static int check_unit_failed(DBusConnection *bus, char **args) {
2331 const char * const check_states[] = {
2342 STRV_FOREACH(name, args+1) {
2345 state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
2355 static int kill_unit(DBusConnection *bus, char **args) {
2363 arg_kill_who = "all";
2365 STRV_FOREACH(name, args+1) {
2366 _cleanup_free_ char *n = NULL;
2368 n = unit_name_mangle(*name);
2372 r = bus_method_call_with_reply(
2374 "org.freedesktop.systemd1",
2375 "/org/freedesktop/systemd1",
2376 "org.freedesktop.systemd1.Manager",
2380 DBUS_TYPE_STRING, &n,
2381 DBUS_TYPE_STRING, &arg_kill_who,
2382 DBUS_TYPE_INT32, &arg_signal,
2390 typedef struct ExecStatusInfo {
2398 usec_t start_timestamp;
2399 usec_t exit_timestamp;
2404 LIST_FIELDS(struct ExecStatusInfo, exec);
2407 static void exec_status_info_free(ExecStatusInfo *i) {
2416 static int exec_status_info_deserialize(DBusMessageIter *sub, ExecStatusInfo *i) {
2417 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
2418 DBusMessageIter sub2, sub3;
2422 int32_t code, status;
2428 if (dbus_message_iter_get_arg_type(sub) != DBUS_TYPE_STRUCT)
2431 dbus_message_iter_recurse(sub, &sub2);
2433 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0)
2436 i->path = strdup(path);
2440 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_ARRAY ||
2441 dbus_message_iter_get_element_type(&sub2) != DBUS_TYPE_STRING)
2445 dbus_message_iter_recurse(&sub2, &sub3);
2446 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2447 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2448 dbus_message_iter_next(&sub3);
2452 i->argv = new0(char*, n+1);
2457 dbus_message_iter_recurse(&sub2, &sub3);
2458 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2461 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2462 dbus_message_iter_get_basic(&sub3, &s);
2463 dbus_message_iter_next(&sub3);
2465 i->argv[n] = strdup(s);
2472 if (!dbus_message_iter_next(&sub2) ||
2473 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, true) < 0 ||
2474 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp, true) < 0 ||
2475 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp_monotonic, true) < 0 ||
2476 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp, true) < 0 ||
2477 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp_monotonic, true) < 0 ||
2478 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, true) < 0 ||
2479 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &code, true) < 0 ||
2480 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &status, false) < 0)
2484 i->start_timestamp = (usec_t) start_timestamp;
2485 i->exit_timestamp = (usec_t) exit_timestamp;
2486 i->pid = (pid_t) pid;
2493 typedef struct UnitStatusInfo {
2495 const char *load_state;
2496 const char *active_state;
2497 const char *sub_state;
2498 const char *unit_file_state;
2500 const char *description;
2501 const char *following;
2503 char **documentation;
2505 const char *fragment_path;
2506 const char *source_path;
2507 const char *control_group;
2509 char **dropin_paths;
2511 const char *load_error;
2514 usec_t inactive_exit_timestamp;
2515 usec_t inactive_exit_timestamp_monotonic;
2516 usec_t active_enter_timestamp;
2517 usec_t active_exit_timestamp;
2518 usec_t inactive_enter_timestamp;
2520 bool need_daemon_reload;
2525 const char *status_text;
2526 const char *pid_file;
2529 usec_t start_timestamp;
2530 usec_t exit_timestamp;
2532 int exit_code, exit_status;
2534 usec_t condition_timestamp;
2535 bool condition_result;
2538 unsigned n_accepted;
2539 unsigned n_connections;
2542 /* Pairs of type, path */
2546 const char *sysfs_path;
2548 /* Mount, Automount */
2554 LIST_HEAD(ExecStatusInfo, exec);
2557 static void print_status_info(UnitStatusInfo *i) {
2559 const char *on, *off, *ss;
2561 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
2562 char since2[FORMAT_TIMESTAMP_MAX], *s2;
2565 arg_all * OUTPUT_SHOW_ALL |
2566 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
2567 on_tty() * OUTPUT_COLOR |
2568 !arg_quiet * OUTPUT_WARN_CUTOFF |
2569 arg_full * OUTPUT_FULL_WIDTH;
2574 /* This shows pretty information about a unit. See
2575 * print_property() for a low-level property printer */
2577 printf("%s", strna(i->id));
2579 if (i->description && !streq_ptr(i->id, i->description))
2580 printf(" - %s", i->description);
2585 printf(" Follow: unit currently follows state of %s\n", i->following);
2587 if (streq_ptr(i->load_state, "error")) {
2588 on = ansi_highlight_red(true);
2589 off = ansi_highlight_red(false);
2593 path = i->source_path ? i->source_path : i->fragment_path;
2596 printf(" Loaded: %s%s%s (Reason: %s)\n",
2597 on, strna(i->load_state), off, i->load_error);
2598 else if (path && i->unit_file_state)
2599 printf(" Loaded: %s%s%s (%s; %s)\n",
2600 on, strna(i->load_state), off, path, i->unit_file_state);
2602 printf(" Loaded: %s%s%s (%s)\n",
2603 on, strna(i->load_state), off, path);
2605 printf(" Loaded: %s%s%s\n",
2606 on, strna(i->load_state), off);
2608 if (!strv_isempty(i->dropin_paths)) {
2613 STRV_FOREACH(dropin, i->dropin_paths) {
2614 if (! dir || last) {
2615 printf(dir ? " " : " Drop-In: ");
2619 if (path_get_parent(*dropin, &dir) < 0) {
2624 printf("%s\n %s", dir,
2625 draw_special_char(DRAW_TREE_RIGHT));
2628 last = ! (*(dropin + 1) && startswith(*(dropin + 1), dir));
2630 printf("%s%s", path_get_file_name(*dropin), last ? "\n" : ", ");
2636 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
2638 if (streq_ptr(i->active_state, "failed")) {
2639 on = ansi_highlight_red(true);
2640 off = ansi_highlight_red(false);
2641 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
2642 on = ansi_highlight_green(true);
2643 off = ansi_highlight_green(false);
2648 printf(" Active: %s%s (%s)%s",
2649 on, strna(i->active_state), ss, off);
2651 printf(" Active: %s%s%s",
2652 on, strna(i->active_state), off);
2654 if (!isempty(i->result) && !streq(i->result, "success"))
2655 printf(" (Result: %s)", i->result);
2657 timestamp = (streq_ptr(i->active_state, "active") ||
2658 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
2659 (streq_ptr(i->active_state, "inactive") ||
2660 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
2661 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
2662 i->active_exit_timestamp;
2664 s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
2665 s2 = format_timestamp(since2, sizeof(since2), timestamp);
2668 printf(" since %s; %s\n", s2, s1);
2670 printf(" since %s\n", s2);
2674 if (!i->condition_result && i->condition_timestamp > 0) {
2675 s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
2676 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
2679 printf(" start condition failed at %s; %s\n", s2, s1);
2681 printf(" start condition failed at %s\n", s2);
2685 printf(" Device: %s\n", i->sysfs_path);
2687 printf(" Where: %s\n", i->where);
2689 printf(" What: %s\n", i->what);
2691 STRV_FOREACH(t, i->documentation)
2692 printf(" %*s %s\n", 9, t == i->documentation ? "Docs:" : "", *t);
2694 STRV_FOREACH_PAIR(t, t2, i->listen)
2695 printf(" %*s %s (%s)\n", 9, t == i->listen ? "Listen:" : "", *t2, *t);
2698 printf(" Accepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
2700 LIST_FOREACH(exec, p, i->exec) {
2701 _cleanup_free_ char *argv = NULL;
2704 /* Only show exited processes here */
2708 argv = strv_join(p->argv, " ");
2709 printf(" Process: %u %s=%s ", p->pid, p->name, strna(argv));
2711 good = is_clean_exit_lsb(p->code, p->status, NULL);
2713 on = ansi_highlight_red(true);
2714 off = ansi_highlight_red(false);
2718 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
2720 if (p->code == CLD_EXITED) {
2723 printf("status=%i", p->status);
2725 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
2730 printf("signal=%s", signal_to_string(p->status));
2732 printf(")%s\n", off);
2734 if (i->main_pid == p->pid &&
2735 i->start_timestamp == p->start_timestamp &&
2736 i->exit_timestamp == p->start_timestamp)
2737 /* Let's not show this twice */
2740 if (p->pid == i->control_pid)
2744 if (i->main_pid > 0 || i->control_pid > 0) {
2745 if (i->main_pid > 0) {
2746 printf(" Main PID: %u", (unsigned) i->main_pid);
2749 _cleanup_free_ char *comm = NULL;
2750 get_process_comm(i->main_pid, &comm);
2752 printf(" (%s)", comm);
2753 } else if (i->exit_code > 0) {
2754 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
2756 if (i->exit_code == CLD_EXITED) {
2759 printf("status=%i", i->exit_status);
2761 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
2766 printf("signal=%s", signal_to_string(i->exit_status));
2770 if (i->control_pid > 0)
2774 if (i->control_pid > 0) {
2775 _cleanup_free_ char *c = NULL;
2777 printf(" %8s: %u", i->main_pid ? "" : " Control", (unsigned) i->control_pid);
2779 get_process_comm(i->control_pid, &c);
2788 printf(" Status: \"%s\"\n", i->status_text);
2790 if (i->control_group &&
2791 (i->main_pid > 0 || i->control_pid > 0 || cg_is_empty(SYSTEMD_CGROUP_CONTROLLER, i->control_group, false) == 0)) {
2794 printf(" CGroup: %s\n", i->control_group);
2796 if (arg_transport != TRANSPORT_SSH) {
2799 char prefix[] = " ";
2802 if (c > sizeof(prefix) - 1)
2803 c -= sizeof(prefix) - 1;
2807 if (i->main_pid > 0)
2808 extra[k++] = i->main_pid;
2810 if (i->control_pid > 0)
2811 extra[k++] = i->control_pid;
2813 show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, i->control_group, prefix,
2814 c, false, extra, k, flags);
2818 if (i->id && arg_transport != TRANSPORT_SSH) {
2820 show_journal_by_unit(stdout,
2824 i->inactive_exit_timestamp_monotonic,
2828 arg_scope == UNIT_FILE_SYSTEM);
2831 if (i->need_daemon_reload)
2832 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %sdaemon-reload' recommended.\n",
2833 ansi_highlight_red(true),
2834 ansi_highlight_red(false),
2835 arg_scope == UNIT_FILE_SYSTEM ? "" : "--user ");
2838 static void show_unit_help(UnitStatusInfo *i) {
2843 if (!i->documentation) {
2844 log_info("Documentation for %s not known.", i->id);
2848 STRV_FOREACH(p, i->documentation) {
2850 if (startswith(*p, "man:")) {
2853 _cleanup_free_ char *page = NULL, *section = NULL;
2854 const char *args[4] = { "man", NULL, NULL, NULL };
2859 if ((*p)[k-1] == ')')
2860 e = strrchr(*p, '(');
2863 page = strndup((*p) + 4, e - *p - 4);
2864 section = strndup(e + 1, *p + k - e - 2);
2865 if (!page || !section) {
2877 log_error("Failed to fork: %m");
2883 execvp(args[0], (char**) args);
2884 log_error("Failed to execute man: %m");
2885 _exit(EXIT_FAILURE);
2888 wait_for_terminate(pid, NULL);
2890 log_info("Can't show: %s", *p);
2894 static int status_property(const char *name, DBusMessageIter *iter, UnitStatusInfo *i) {
2900 switch (dbus_message_iter_get_arg_type(iter)) {
2902 case DBUS_TYPE_STRING: {
2905 dbus_message_iter_get_basic(iter, &s);
2908 if (streq(name, "Id"))
2910 else if (streq(name, "LoadState"))
2912 else if (streq(name, "ActiveState"))
2913 i->active_state = s;
2914 else if (streq(name, "SubState"))
2916 else if (streq(name, "Description"))
2918 else if (streq(name, "FragmentPath"))
2919 i->fragment_path = s;
2920 else if (streq(name, "SourcePath"))
2923 else if (streq(name, "DefaultControlGroup")) {
2925 e = startswith(s, SYSTEMD_CGROUP_CONTROLLER ":");
2927 i->control_group = e;
2930 else if (streq(name, "ControlGroup"))
2931 i->control_group = s;
2932 else if (streq(name, "StatusText"))
2934 else if (streq(name, "PIDFile"))
2936 else if (streq(name, "SysFSPath"))
2938 else if (streq(name, "Where"))
2940 else if (streq(name, "What"))
2942 else if (streq(name, "Following"))
2944 else if (streq(name, "UnitFileState"))
2945 i->unit_file_state = s;
2946 else if (streq(name, "Result"))
2953 case DBUS_TYPE_BOOLEAN: {
2956 dbus_message_iter_get_basic(iter, &b);
2958 if (streq(name, "Accept"))
2960 else if (streq(name, "NeedDaemonReload"))
2961 i->need_daemon_reload = b;
2962 else if (streq(name, "ConditionResult"))
2963 i->condition_result = b;
2968 case DBUS_TYPE_UINT32: {
2971 dbus_message_iter_get_basic(iter, &u);
2973 if (streq(name, "MainPID")) {
2975 i->main_pid = (pid_t) u;
2978 } else if (streq(name, "ControlPID"))
2979 i->control_pid = (pid_t) u;
2980 else if (streq(name, "ExecMainPID")) {
2982 i->main_pid = (pid_t) u;
2983 } else if (streq(name, "NAccepted"))
2985 else if (streq(name, "NConnections"))
2986 i->n_connections = u;
2991 case DBUS_TYPE_INT32: {
2994 dbus_message_iter_get_basic(iter, &j);
2996 if (streq(name, "ExecMainCode"))
2997 i->exit_code = (int) j;
2998 else if (streq(name, "ExecMainStatus"))
2999 i->exit_status = (int) j;
3004 case DBUS_TYPE_UINT64: {
3007 dbus_message_iter_get_basic(iter, &u);
3009 if (streq(name, "ExecMainStartTimestamp"))
3010 i->start_timestamp = (usec_t) u;
3011 else if (streq(name, "ExecMainExitTimestamp"))
3012 i->exit_timestamp = (usec_t) u;
3013 else if (streq(name, "ActiveEnterTimestamp"))
3014 i->active_enter_timestamp = (usec_t) u;
3015 else if (streq(name, "InactiveEnterTimestamp"))
3016 i->inactive_enter_timestamp = (usec_t) u;
3017 else if (streq(name, "InactiveExitTimestamp"))
3018 i->inactive_exit_timestamp = (usec_t) u;
3019 else if (streq(name, "InactiveExitTimestampMonotonic"))
3020 i->inactive_exit_timestamp_monotonic = (usec_t) u;
3021 else if (streq(name, "ActiveExitTimestamp"))
3022 i->active_exit_timestamp = (usec_t) u;
3023 else if (streq(name, "ConditionTimestamp"))
3024 i->condition_timestamp = (usec_t) u;
3029 case DBUS_TYPE_ARRAY: {
3031 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
3032 startswith(name, "Exec")) {
3033 DBusMessageIter sub;
3035 dbus_message_iter_recurse(iter, &sub);
3036 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3037 ExecStatusInfo *info;
3040 if (!(info = new0(ExecStatusInfo, 1)))
3043 if (!(info->name = strdup(name))) {
3048 if ((r = exec_status_info_deserialize(&sub, info)) < 0) {
3053 LIST_PREPEND(ExecStatusInfo, exec, i->exec, info);
3055 dbus_message_iter_next(&sub);
3058 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Listen")) {
3059 DBusMessageIter sub, sub2;
3061 dbus_message_iter_recurse(iter, &sub);
3062 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3063 const char *type, *path;
3065 dbus_message_iter_recurse(&sub, &sub2);
3067 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
3068 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0) {
3071 r = strv_extend(&i->listen, type);
3074 r = strv_extend(&i->listen, path);
3079 dbus_message_iter_next(&sub);
3084 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING && streq(name, "DropInPaths")) {
3085 int r = bus_parse_strv_iter(iter, &i->dropin_paths);
3089 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
3090 streq(name, "Documentation")) {
3092 DBusMessageIter sub;
3094 dbus_message_iter_recurse(iter, &sub);
3095 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING) {
3099 dbus_message_iter_get_basic(&sub, &s);
3101 r = strv_extend(&i->documentation, s);
3105 dbus_message_iter_next(&sub);
3112 case DBUS_TYPE_STRUCT: {
3114 if (streq(name, "LoadError")) {
3115 DBusMessageIter sub;
3116 const char *n, *message;
3119 dbus_message_iter_recurse(iter, &sub);
3121 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &n, true);
3125 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &message, false);
3129 if (!isempty(message))
3130 i->load_error = message;
3140 static int print_property(const char *name, DBusMessageIter *iter) {
3144 /* This is a low-level property printer, see
3145 * print_status_info() for the nicer output */
3147 if (arg_properties && !strv_find(arg_properties, name))
3150 switch (dbus_message_iter_get_arg_type(iter)) {
3152 case DBUS_TYPE_STRUCT: {
3153 DBusMessageIter sub;
3154 dbus_message_iter_recurse(iter, &sub);
3156 if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32 && streq(name, "Job")) {
3159 dbus_message_iter_get_basic(&sub, &u);
3162 printf("%s=%u\n", name, (unsigned) u);
3164 printf("%s=\n", name);
3167 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "Unit")) {
3170 dbus_message_iter_get_basic(&sub, &s);
3172 if (arg_all || s[0])
3173 printf("%s=%s\n", name, s);
3176 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "LoadError")) {
3177 const char *a = NULL, *b = NULL;
3179 if (bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &a, true) >= 0)
3180 bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &b, false);
3182 if (arg_all || !isempty(a) || !isempty(b))
3183 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
3191 case DBUS_TYPE_ARRAY:
3193 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "EnvironmentFiles")) {
3194 DBusMessageIter sub, sub2;
3196 dbus_message_iter_recurse(iter, &sub);
3197 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3201 dbus_message_iter_recurse(&sub, &sub2);
3203 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
3204 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) >= 0)
3205 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
3207 dbus_message_iter_next(&sub);
3212 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Paths")) {
3213 DBusMessageIter sub, sub2;
3215 dbus_message_iter_recurse(iter, &sub);
3217 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3218 const char *type, *path;
3220 dbus_message_iter_recurse(&sub, &sub2);
3222 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
3223 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
3224 printf("%s=%s\n", type, path);
3226 dbus_message_iter_next(&sub);
3231 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Listen")) {
3232 DBusMessageIter sub, sub2;
3234 dbus_message_iter_recurse(iter, &sub);
3235 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3236 const char *type, *path;
3238 dbus_message_iter_recurse(&sub, &sub2);
3240 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
3241 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
3242 printf("Listen%s=%s\n", type, path);
3244 dbus_message_iter_next(&sub);
3249 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Timers")) {
3250 DBusMessageIter sub, sub2;
3252 dbus_message_iter_recurse(iter, &sub);
3253 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3255 uint64_t value, next_elapse;
3257 dbus_message_iter_recurse(&sub, &sub2);
3259 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &base, true) >= 0 &&
3260 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &value, true) >= 0 &&
3261 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &next_elapse, false) >= 0) {
3262 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
3264 printf("%s={ value=%s ; next_elapse=%s }\n",
3266 format_timespan(timespan1, sizeof(timespan1), value, 0),
3267 format_timespan(timespan2, sizeof(timespan2), next_elapse, 0));
3270 dbus_message_iter_next(&sub);
3275 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && startswith(name, "Exec")) {
3276 DBusMessageIter sub;
3278 dbus_message_iter_recurse(iter, &sub);
3279 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3280 ExecStatusInfo info = {};
3282 if (exec_status_info_deserialize(&sub, &info) >= 0) {
3283 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
3284 _cleanup_free_ char *t;
3286 t = strv_join(info.argv, " ");
3288 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
3292 yes_no(info.ignore),
3293 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
3294 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
3295 (unsigned) info. pid,
3296 sigchld_code_to_string(info.code),
3298 info.code == CLD_EXITED ? "" : "/",
3299 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
3303 strv_free(info.argv);
3305 dbus_message_iter_next(&sub);
3310 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "DeviceAllow")) {
3311 DBusMessageIter sub, sub2;
3313 dbus_message_iter_recurse(iter, &sub);
3314 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3315 const char *path, *rwm;
3317 dbus_message_iter_recurse(&sub, &sub2);
3319 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
3320 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &rwm, false) >= 0)
3321 printf("%s=%s %s\n", name, strna(path), strna(rwm));
3323 dbus_message_iter_next(&sub);
3327 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && (streq(name, "BlockIOReadBandwidth") || streq(name, "BlockIOWriteBandwidth"))) {
3328 DBusMessageIter sub, sub2;
3330 dbus_message_iter_recurse(iter, &sub);
3331 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3335 dbus_message_iter_recurse(&sub, &sub2);
3337 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
3338 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &bandwidth, false) >= 0)
3339 printf("%s=%s %" PRIu64 "\n", name, strna(path), bandwidth);
3341 dbus_message_iter_next(&sub);
3350 if (generic_print_property(name, iter, arg_all) > 0)
3354 printf("%s=[unprintable]\n", name);
3359 static int show_one(const char *verb, DBusConnection *bus, const char *path, bool show_properties, bool *new_line) {
3360 _cleanup_free_ DBusMessage *reply = NULL;
3361 const char *interface = "";
3363 DBusMessageIter iter, sub, sub2, sub3;
3364 UnitStatusInfo info = {};
3370 r = bus_method_call_with_reply(
3372 "org.freedesktop.systemd1",
3374 "org.freedesktop.DBus.Properties",
3378 DBUS_TYPE_STRING, &interface,
3383 if (!dbus_message_iter_init(reply, &iter) ||
3384 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3385 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
3386 log_error("Failed to parse reply.");
3390 dbus_message_iter_recurse(&iter, &sub);
3397 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
3400 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_DICT_ENTRY);
3401 dbus_message_iter_recurse(&sub, &sub2);
3403 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
3404 dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
3405 log_error("Failed to parse reply.");
3409 dbus_message_iter_recurse(&sub2, &sub3);
3411 if (show_properties)
3412 r = print_property(name, &sub3);
3414 r = status_property(name, &sub3, &info);
3416 log_error("Failed to parse reply.");
3420 dbus_message_iter_next(&sub);
3425 if (!show_properties) {
3426 if (streq(verb, "help"))
3427 show_unit_help(&info);
3429 print_status_info(&info);
3432 strv_free(info.documentation);
3433 strv_free(info.dropin_paths);
3434 strv_free(info.listen);
3436 if (!streq_ptr(info.active_state, "active") &&
3437 !streq_ptr(info.active_state, "reloading") &&
3438 streq(verb, "status")) {
3439 /* According to LSB: "program not running" */
3440 /* 0: program is running or service is OK
3441 * 1: program is dead and /var/run pid file exists
3442 * 2: program is dead and /var/lock lock file exists
3443 * 3: program is not running
3444 * 4: program or service status is unknown
3446 if (info.pid_file && access(info.pid_file, F_OK) == 0)
3452 while ((p = info.exec)) {
3453 LIST_REMOVE(ExecStatusInfo, exec, info.exec, p);
3454 exec_status_info_free(p);
3460 static int show_one_by_pid(const char *verb, DBusConnection *bus, uint32_t pid, bool *new_line) {
3461 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3462 const char *path = NULL;
3463 _cleanup_dbus_error_free_ DBusError error;
3466 dbus_error_init(&error);
3468 r = bus_method_call_with_reply(
3470 "org.freedesktop.systemd1",
3471 "/org/freedesktop/systemd1",
3472 "org.freedesktop.systemd1.Manager",
3476 DBUS_TYPE_UINT32, &pid,
3481 if (!dbus_message_get_args(reply, &error,
3482 DBUS_TYPE_OBJECT_PATH, &path,
3483 DBUS_TYPE_INVALID)) {
3484 log_error("Failed to parse reply: %s", bus_error_message(&error));
3488 r = show_one(verb, bus, path, false, new_line);
3492 static int show_all(const char* verb, DBusConnection *bus, bool show_properties, bool *new_line) {
3493 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3494 _cleanup_free_ struct unit_info *unit_infos = NULL;
3496 const struct unit_info *u;
3499 r = get_unit_list(bus, &reply, &unit_infos, &c);
3503 qsort(unit_infos, c, sizeof(struct unit_info), compare_unit_info);
3505 for (u = unit_infos; u < unit_infos + c; u++) {
3506 _cleanup_free_ char *p = NULL;
3508 if (!output_show_unit(u))
3511 p = unit_dbus_path_from_name(u->id);
3515 printf("%s -> '%s'\n", u->id, p);
3517 r = show_one(verb, bus, p, show_properties, new_line);
3525 static int show(DBusConnection *bus, char **args) {
3527 bool show_properties, show_status, new_line = false;
3533 show_properties = streq(args[0], "show");
3534 show_status = streq(args[0], "status");
3536 if (show_properties)
3537 pager_open_if_enabled();
3539 /* If no argument is specified inspect the manager itself */
3541 if (show_properties && strv_length(args) <= 1)
3542 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line);
3544 if (show_status && strv_length(args) <= 1)
3545 return show_all(args[0], bus, false, &new_line);
3547 STRV_FOREACH(name, args+1) {
3550 if (safe_atou32(*name, &id) < 0) {
3551 _cleanup_free_ char *p = NULL, *n = NULL;
3552 /* Interpret as unit name */
3554 n = unit_name_mangle(*name);
3558 p = unit_dbus_path_from_name(n);
3562 r = show_one(args[0], bus, p, show_properties, &new_line);
3566 } else if (show_properties) {
3567 _cleanup_free_ char *p = NULL;
3569 /* Interpret as job id */
3570 if (asprintf(&p, "/org/freedesktop/systemd1/job/%u", id) < 0)
3573 r = show_one(args[0], bus, p, show_properties, &new_line);
3578 /* Interpret as PID */
3579 r = show_one_by_pid(args[0], bus, id, &new_line);
3588 static int append_assignment(DBusMessageIter *iter, const char *assignment) {
3591 DBusMessageIter sub;
3597 eq = strchr(assignment, '=');
3599 log_error("Not an assignment: %s", assignment);
3603 field = strndupa(assignment, eq - assignment);
3606 if (!dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &field))
3609 if (streq(field, "CPUAccounting") ||
3610 streq(field, "MemoryAccounting") ||
3611 streq(field, "BlockIOAccounting")) {
3614 r = parse_boolean(eq);
3616 log_error("Failed to parse boolean assignment %s.", assignment);
3621 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "b", &sub) ||
3622 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_BOOLEAN, &b))
3625 } else if (streq(field, "MemoryLimit") || streq(field, "MemorySoftLimit")) {
3629 r = parse_bytes(eq, &bytes);
3631 log_error("Failed to parse bytes specification %s", assignment);
3636 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "t", &sub) ||
3637 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_UINT64, &u))
3640 } else if (streq(field, "CPUShares") || streq(field, "BlockIOWeight")) {
3643 r = safe_atou64(eq, &u);
3645 log_error("Failed to parse %s value %s.", field, eq);
3649 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "t", &sub) ||
3650 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_UINT64, &u))
3653 } else if (streq(field, "DevicePolicy")) {
3655 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "s", &sub) ||
3656 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &eq))
3659 } else if (streq(field, "DeviceAllow")) {
3660 DBusMessageIter sub2;
3662 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "a(ss)", &sub) ||
3663 !dbus_message_iter_open_container(&sub, DBUS_TYPE_ARRAY, "(ss)", &sub2))
3667 const char *path, *rwm;
3668 DBusMessageIter sub3;
3671 e = strchr(eq, ' ');
3673 path = strndupa(eq, e - eq);
3680 if (!dbus_message_iter_open_container(&sub2, DBUS_TYPE_STRUCT, NULL, &sub3) ||
3681 !dbus_message_iter_append_basic(&sub3, DBUS_TYPE_STRING, &path) ||
3682 !dbus_message_iter_append_basic(&sub3, DBUS_TYPE_STRING, &rwm) ||
3683 !dbus_message_iter_close_container(&sub2, &sub3))
3687 if (!dbus_message_iter_close_container(&sub, &sub2))
3691 log_error("Unknown assignment %s.", assignment);
3695 if (!dbus_message_iter_close_container(iter, &sub))
3701 static int set_property(DBusConnection *bus, char **args) {
3703 _cleanup_free_ DBusMessage *m = NULL, *reply = NULL;
3704 DBusMessageIter iter, sub;
3705 dbus_bool_t runtime;
3710 dbus_error_init(&error);
3712 m = dbus_message_new_method_call(
3713 "org.freedesktop.systemd1",
3714 "/org/freedesktop/systemd1",
3715 "org.freedesktop.systemd1.Manager",
3716 "SetUnitProperties");
3720 dbus_message_iter_init_append(m, &iter);
3722 runtime = arg_runtime;
3724 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &args[1]) ||
3725 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &runtime) ||
3726 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(sv)", &sub))
3729 STRV_FOREACH(i, args + 2) {
3730 DBusMessageIter sub2;
3732 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
3735 r = append_assignment(&sub2, *i);
3739 if (!dbus_message_iter_close_container(&sub, &sub2))
3744 if (!dbus_message_iter_close_container(&iter, &sub))
3747 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3749 log_error("Failed to issue method call: %s", bus_error_message(&error));
3750 dbus_error_free(&error);
3757 static int dump(DBusConnection *bus, char **args) {
3758 _cleanup_free_ DBusMessage *reply = NULL;
3763 dbus_error_init(&error);
3765 pager_open_if_enabled();
3767 r = bus_method_call_with_reply(
3769 "org.freedesktop.systemd1",
3770 "/org/freedesktop/systemd1",
3771 "org.freedesktop.systemd1.Manager",
3779 if (!dbus_message_get_args(reply, &error,
3780 DBUS_TYPE_STRING, &text,
3781 DBUS_TYPE_INVALID)) {
3782 log_error("Failed to parse reply: %s", bus_error_message(&error));
3783 dbus_error_free(&error);
3787 fputs(text, stdout);
3791 static int snapshot(DBusConnection *bus, char **args) {
3792 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3795 dbus_bool_t cleanup = FALSE;
3796 DBusMessageIter iter, sub;
3799 *interface = "org.freedesktop.systemd1.Unit",
3801 _cleanup_free_ char *n = NULL;
3803 dbus_error_init(&error);
3805 if (strv_length(args) > 1)
3806 n = unit_name_mangle_with_suffix(args[1], ".snapshot");
3812 r = bus_method_call_with_reply(
3814 "org.freedesktop.systemd1",
3815 "/org/freedesktop/systemd1",
3816 "org.freedesktop.systemd1.Manager",
3820 DBUS_TYPE_STRING, &n,
3821 DBUS_TYPE_BOOLEAN, &cleanup,
3826 if (!dbus_message_get_args(reply, &error,
3827 DBUS_TYPE_OBJECT_PATH, &path,
3828 DBUS_TYPE_INVALID)) {
3829 log_error("Failed to parse reply: %s", bus_error_message(&error));
3830 dbus_error_free(&error);
3834 dbus_message_unref(reply);
3837 r = bus_method_call_with_reply (
3839 "org.freedesktop.systemd1",
3841 "org.freedesktop.DBus.Properties",
3845 DBUS_TYPE_STRING, &interface,
3846 DBUS_TYPE_STRING, &property,
3851 if (!dbus_message_iter_init(reply, &iter) ||
3852 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3853 log_error("Failed to parse reply.");
3857 dbus_message_iter_recurse(&iter, &sub);
3859 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
3860 log_error("Failed to parse reply.");
3864 dbus_message_iter_get_basic(&sub, &id);
3872 static int delete_snapshot(DBusConnection *bus, char **args) {
3877 STRV_FOREACH(name, args+1) {
3878 _cleanup_free_ char *n = NULL;
3881 n = unit_name_mangle_with_suffix(*name, ".snapshot");
3885 r = bus_method_call_with_reply(
3887 "org.freedesktop.systemd1",
3888 "/org/freedesktop/systemd1",
3889 "org.freedesktop.systemd1.Manager",
3893 DBUS_TYPE_STRING, &n,
3902 static int daemon_reload(DBusConnection *bus, char **args) {
3907 if (arg_action == ACTION_RELOAD)
3909 else if (arg_action == ACTION_REEXEC)
3910 method = "Reexecute";
3912 assert(arg_action == ACTION_SYSTEMCTL);
3915 streq(args[0], "clear-jobs") ||
3916 streq(args[0], "cancel") ? "ClearJobs" :
3917 streq(args[0], "daemon-reexec") ? "Reexecute" :
3918 streq(args[0], "reset-failed") ? "ResetFailed" :
3919 streq(args[0], "halt") ? "Halt" :
3920 streq(args[0], "poweroff") ? "PowerOff" :
3921 streq(args[0], "reboot") ? "Reboot" :
3922 streq(args[0], "kexec") ? "KExec" :
3923 streq(args[0], "exit") ? "Exit" :
3924 /* "daemon-reload" */ "Reload";
3927 r = bus_method_call_with_reply(
3929 "org.freedesktop.systemd1",
3930 "/org/freedesktop/systemd1",
3931 "org.freedesktop.systemd1.Manager",
3937 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
3938 /* There's always a fallback possible for
3939 * legacy actions. */
3941 else if ((r == -ETIMEDOUT || r == -ECONNRESET) && streq(method, "Reexecute"))
3942 /* On reexecution, we expect a disconnect, not a
3946 log_error("Failed to issue method call: %s", bus_error_message(&error));
3948 dbus_error_free(&error);
3952 static int reset_failed(DBusConnection *bus, char **args) {
3956 if (strv_length(args) <= 1)
3957 return daemon_reload(bus, args);
3959 STRV_FOREACH(name, args+1) {
3960 _cleanup_free_ char *n;
3962 n = unit_name_mangle(*name);
3966 r = bus_method_call_with_reply(
3968 "org.freedesktop.systemd1",
3969 "/org/freedesktop/systemd1",
3970 "org.freedesktop.systemd1.Manager",
3974 DBUS_TYPE_STRING, &n,
3983 static int show_enviroment(DBusConnection *bus, char **args) {
3984 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3985 DBusMessageIter iter, sub, sub2;
3988 *interface = "org.freedesktop.systemd1.Manager",
3989 *property = "Environment";
3991 pager_open_if_enabled();
3993 r = bus_method_call_with_reply(
3995 "org.freedesktop.systemd1",
3996 "/org/freedesktop/systemd1",
3997 "org.freedesktop.DBus.Properties",
4001 DBUS_TYPE_STRING, &interface,
4002 DBUS_TYPE_STRING, &property,
4007 if (!dbus_message_iter_init(reply, &iter) ||
4008 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
4009 log_error("Failed to parse reply.");
4013 dbus_message_iter_recurse(&iter, &sub);
4015 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_ARRAY ||
4016 dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_STRING) {
4017 log_error("Failed to parse reply.");
4021 dbus_message_iter_recurse(&sub, &sub2);
4023 while (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_INVALID) {
4026 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
4027 log_error("Failed to parse reply.");
4031 dbus_message_iter_get_basic(&sub2, &text);
4034 dbus_message_iter_next(&sub2);
4040 static int switch_root(DBusConnection *bus, char **args) {
4043 _cleanup_free_ char *init = NULL;
4045 l = strv_length(args);
4046 if (l < 2 || l > 3) {
4047 log_error("Wrong number of arguments.");
4054 init = strdup(args[2]);
4056 parse_env_file("/proc/cmdline", WHITESPACE,
4066 log_debug("switching root - root: %s; init: %s", root, init);
4068 return bus_method_call_with_reply(
4070 "org.freedesktop.systemd1",
4071 "/org/freedesktop/systemd1",
4072 "org.freedesktop.systemd1.Manager",
4076 DBUS_TYPE_STRING, &root,
4077 DBUS_TYPE_STRING, &init,
4081 static int set_environment(DBusConnection *bus, char **args) {
4082 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
4085 DBusMessageIter iter;
4091 dbus_error_init(&error);
4093 method = streq(args[0], "set-environment")
4095 : "UnsetEnvironment";
4097 m = dbus_message_new_method_call(
4098 "org.freedesktop.systemd1",
4099 "/org/freedesktop/systemd1",
4100 "org.freedesktop.systemd1.Manager",
4105 dbus_message_iter_init_append(m, &iter);
4107 r = bus_append_strv_iter(&iter, args + 1);
4111 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
4113 log_error("Failed to issue method call: %s", bus_error_message(&error));
4114 dbus_error_free(&error);
4121 static int enable_sysv_units(char **args) {
4124 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
4125 const char *verb = args[0];
4126 unsigned f = 1, t = 1;
4127 LookupPaths paths = {};
4129 if (arg_scope != UNIT_FILE_SYSTEM)
4132 if (!streq(verb, "enable") &&
4133 !streq(verb, "disable") &&
4134 !streq(verb, "is-enabled"))
4137 /* Processes all SysV units, and reshuffles the array so that
4138 * afterwards only the native units remain */
4140 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, NULL, NULL, NULL);
4145 for (f = 1; args[f]; f++) {
4147 _cleanup_free_ char *p = NULL, *q = NULL;
4148 bool found_native = false, found_sysv;
4150 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
4158 if (!endswith(name, ".service"))
4161 if (path_is_absolute(name))
4164 STRV_FOREACH(k, paths.unit_path) {
4165 if (!isempty(arg_root))
4166 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
4168 asprintf(&p, "%s/%s", *k, name);
4175 found_native = access(p, F_OK) >= 0;
4186 if (!isempty(arg_root))
4187 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
4189 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
4195 p[strlen(p) - sizeof(".service") + 1] = 0;
4196 found_sysv = access(p, F_OK) >= 0;
4201 /* Mark this entry, so that we don't try enabling it as native unit */
4202 args[f] = (char*) "";
4204 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
4206 if (!isempty(arg_root))
4207 argv[c++] = q = strappend("--root=", arg_root);
4209 argv[c++] = path_get_file_name(p);
4211 streq(verb, "enable") ? "on" :
4212 streq(verb, "disable") ? "off" : "--level=5";
4215 l = strv_join((char**)argv, " ");
4221 log_info("Executing %s", l);
4226 log_error("Failed to fork: %m");
4229 } else if (pid == 0) {
4232 execv(argv[0], (char**) argv);
4233 _exit(EXIT_FAILURE);
4236 j = wait_for_terminate(pid, &status);
4238 log_error("Failed to wait for child: %s", strerror(-r));
4243 if (status.si_code == CLD_EXITED) {
4244 if (streq(verb, "is-enabled")) {
4245 if (status.si_status == 0) {
4254 } else if (status.si_status != 0) {
4265 lookup_paths_free(&paths);
4267 /* Drop all SysV units */
4268 for (f = 1, t = 1; args[f]; f++) {
4270 if (isempty(args[f]))
4273 args[t++] = args[f];
4282 static int mangle_names(char **original_names, char ***mangled_names) {
4283 char **i, **l, **name;
4285 l = new(char*, strv_length(original_names) + 1);
4290 STRV_FOREACH(name, original_names) {
4292 /* When enabling units qualified path names are OK,
4293 * too, hence allow them explicitly. */
4298 *i = unit_name_mangle(*name);
4314 static int enable_unit(DBusConnection *bus, char **args) {
4315 const char *verb = args[0];
4316 UnitFileChange *changes = NULL;
4317 unsigned n_changes = 0, i;
4318 int carries_install_info = -1;
4319 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
4321 _cleanup_dbus_error_free_ DBusError error;
4322 _cleanup_strv_free_ char **mangled_names = NULL;
4324 dbus_error_init(&error);
4326 r = enable_sysv_units(args);
4333 r = mangle_names(args+1, &mangled_names);
4337 if (!bus || avoid_bus()) {
4338 if (streq(verb, "enable")) {
4339 r = unit_file_enable(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4340 carries_install_info = r;
4341 } else if (streq(verb, "disable"))
4342 r = unit_file_disable(arg_scope, arg_runtime, arg_root, mangled_names, &changes, &n_changes);
4343 else if (streq(verb, "reenable")) {
4344 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4345 carries_install_info = r;
4346 } else if (streq(verb, "link"))
4347 r = unit_file_link(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4348 else if (streq(verb, "preset")) {
4349 r = unit_file_preset(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4350 carries_install_info = r;
4351 } else if (streq(verb, "mask"))
4352 r = unit_file_mask(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4353 else if (streq(verb, "unmask"))
4354 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, mangled_names, &changes, &n_changes);
4355 else if (streq(verb, "set-default"))
4356 r = unit_file_set_default(arg_scope, arg_root, args[1], &changes, &n_changes);
4358 assert_not_reached("Unknown verb");
4361 log_error("Operation failed: %s", strerror(-r));
4366 for (i = 0; i < n_changes; i++) {
4367 if (changes[i].type == UNIT_FILE_SYMLINK)
4368 log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
4370 log_info("rm '%s'", changes[i].path);
4377 bool send_force = true, expect_carries_install_info = false;
4379 DBusMessageIter iter, sub, sub2;
4381 if (streq(verb, "enable")) {
4382 method = "EnableUnitFiles";
4383 expect_carries_install_info = true;
4384 } else if (streq(verb, "disable")) {
4385 method = "DisableUnitFiles";
4387 } else if (streq(verb, "reenable")) {
4388 method = "ReenableUnitFiles";
4389 expect_carries_install_info = true;
4390 } else if (streq(verb, "link"))
4391 method = "LinkUnitFiles";
4392 else if (streq(verb, "preset")) {
4393 method = "PresetUnitFiles";
4394 expect_carries_install_info = true;
4395 } else if (streq(verb, "mask"))
4396 method = "MaskUnitFiles";
4397 else if (streq(verb, "unmask")) {
4398 method = "UnmaskUnitFiles";
4400 } else if (streq(verb, "set-default")) {
4401 method = "SetDefaultTarget";
4403 assert_not_reached("Unknown verb");
4405 m = dbus_message_new_method_call(
4406 "org.freedesktop.systemd1",
4407 "/org/freedesktop/systemd1",
4408 "org.freedesktop.systemd1.Manager",
4415 dbus_message_iter_init_append(m, &iter);
4417 r = bus_append_strv_iter(&iter, mangled_names);
4419 log_error("Failed to append unit files.");
4424 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &a)) {
4425 log_error("Failed to append runtime boolean.");
4433 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b)) {
4434 log_error("Failed to append force boolean.");
4440 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
4442 log_error("Failed to issue method call: %s", bus_error_message(&error));
4447 if (!dbus_message_iter_init(reply, &iter)) {
4448 log_error("Failed to initialize iterator.");
4452 if (expect_carries_install_info) {
4453 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &b, true);
4455 log_error("Failed to parse reply.");
4459 carries_install_info = b;
4462 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
4463 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
4464 log_error("Failed to parse reply.");
4469 dbus_message_iter_recurse(&iter, &sub);
4470 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
4471 const char *type, *path, *source;
4473 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
4474 log_error("Failed to parse reply.");
4479 dbus_message_iter_recurse(&sub, &sub2);
4481 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
4482 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
4483 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &source, false) < 0) {
4484 log_error("Failed to parse reply.");
4490 if (streq(type, "symlink"))
4491 log_info("ln -s '%s' '%s'", source, path);
4493 log_info("rm '%s'", path);
4496 dbus_message_iter_next(&sub);
4499 /* Try to reload if enabeld */
4501 r = daemon_reload(bus, args);
4504 if (carries_install_info == 0)
4505 log_warning("The unit files have no [Install] section. They are not meant to be enabled\n"
4506 "using systemctl.\n"
4507 "Possible reasons for having this kind of units are:\n"
4508 "1) A unit may be statically enabled by being symlinked from another unit's\n"
4509 " .wants/ or .requires/ directory.\n"
4510 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
4511 " a requirement dependency on it.\n"
4512 "3) A unit may be started when needed via activation (socket, path, timer,\n"
4513 " D-Bus, udev, scripted systemctl call, ...).\n");
4516 unit_file_changes_free(changes, n_changes);
4521 static int set_log_level(DBusConnection *bus, char **args) {
4522 _cleanup_dbus_error_free_ DBusError error;
4523 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
4524 DBusMessageIter iter, sub;
4525 const char* property = "LogLevel";
4526 const char* interface = "org.freedesktop.systemd1.Manager";
4533 dbus_error_init(&error);
4535 m = dbus_message_new_method_call("org.freedesktop.systemd1",
4536 "/org/freedesktop/systemd1",
4537 "org.freedesktop.DBus.Properties",
4542 dbus_message_iter_init_append(m, &iter);
4544 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &interface) ||
4545 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &property) ||
4546 !dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT, "s", &sub))
4549 if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &value)) {
4550 dbus_message_iter_abandon_container(&iter, &sub);
4554 if (!dbus_message_iter_close_container(&iter, &sub))
4557 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
4559 log_error("Failed to issue method call: %s", bus_error_message(&error));
4566 static int unit_is_enabled(DBusConnection *bus, char **args) {
4567 _cleanup_dbus_error_free_ DBusError error;
4569 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
4574 dbus_error_init(&error);
4576 r = enable_sysv_units(args);
4582 if (!bus || avoid_bus()) {
4584 STRV_FOREACH(name, args+1) {
4585 UnitFileState state;
4587 n = unit_name_mangle(*name);
4591 state = unit_file_get_state(arg_scope, arg_root, n);
4598 if (state == UNIT_FILE_ENABLED ||
4599 state == UNIT_FILE_ENABLED_RUNTIME ||
4600 state == UNIT_FILE_STATIC)
4604 puts(unit_file_state_to_string(state));
4608 STRV_FOREACH(name, args+1) {
4611 n = unit_name_mangle(*name);
4615 r = bus_method_call_with_reply (
4617 "org.freedesktop.systemd1",
4618 "/org/freedesktop/systemd1",
4619 "org.freedesktop.systemd1.Manager",
4623 DBUS_TYPE_STRING, &n,
4631 if (!dbus_message_get_args(reply, &error,
4632 DBUS_TYPE_STRING, &s,
4633 DBUS_TYPE_INVALID)) {
4634 log_error("Failed to parse reply: %s", bus_error_message(&error));
4638 dbus_message_unref(reply);
4641 if (streq(s, "enabled") ||
4642 streq(s, "enabled-runtime") ||
4651 return enabled ? 0 : 1;
4654 static int systemctl_help(void) {
4656 pager_open_if_enabled();
4658 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
4659 "Query or send control commands to the systemd manager.\n\n"
4660 " -h --help Show this help\n"
4661 " --version Show package version\n"
4662 " -t --type=TYPE List only units of a particular type\n"
4663 " -p --property=NAME Show only properties by this name\n"
4664 " -a --all Show all loaded units/properties, including dead/empty\n"
4665 " ones. To list all units installed on the system, use\n"
4666 " the 'list-unit-files' command instead.\n"
4667 " --reverse Show reverse dependencies with 'list-dependencies'\n"
4668 " --failed Show only failed units\n"
4669 " -l --full Don't ellipsize unit names on output\n"
4670 " --fail When queueing a new job, fail if conflicting jobs are\n"
4672 " --irreversible Create jobs which cannot be implicitly cancelled\n"
4673 " --show-types When showing sockets, explicitly show their type\n"
4674 " --ignore-dependencies\n"
4675 " When queueing a new job, ignore all its dependencies\n"
4676 " -i --ignore-inhibitors\n"
4677 " When shutting down or sleeping, ignore inhibitors\n"
4678 " --kill-who=WHO Who to send signal to\n"
4679 " -s --signal=SIGNAL Which signal to send\n"
4680 " -H --host=[USER@]HOST\n"
4681 " Show information for remote host\n"
4682 " -P --privileged Acquire privileges before execution\n"
4683 " -q --quiet Suppress output\n"
4684 " --no-block Do not wait until operation finished\n"
4685 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4686 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
4688 " --no-legend Do not print a legend (column headers and hints)\n"
4689 " --no-pager Do not pipe output into a pager\n"
4690 " --no-ask-password\n"
4691 " Do not ask for system passwords\n"
4692 " --system Connect to system manager\n"
4693 " --user Connect to user service manager\n"
4694 " --global Enable/disable unit files globally\n"
4695 " -f --force When enabling unit files, override existing symlinks\n"
4696 " When shutting down, execute action immediately\n"
4697 " --root=PATH Enable unit files in the specified root directory\n"
4698 " --runtime Enable unit files only temporarily until next reboot\n"
4699 " -n --lines=INTEGER Journal entries to show\n"
4700 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
4701 " verbose, export, json, json-pretty, json-sse, cat)\n\n"
4703 " list-units List loaded units\n"
4704 " list-sockets List loaded sockets ordered by address\n"
4705 " start [NAME...] Start (activate) one or more units\n"
4706 " stop [NAME...] Stop (deactivate) one or more units\n"
4707 " reload [NAME...] Reload one or more units\n"
4708 " restart [NAME...] Start or restart one or more units\n"
4709 " try-restart [NAME...] Restart one or more units if active\n"
4710 " reload-or-restart [NAME...] Reload one or more units if possible,\n"
4711 " otherwise start or restart\n"
4712 " reload-or-try-restart [NAME...] Reload one or more units if possible,\n"
4713 " otherwise restart if active\n"
4714 " isolate [NAME] Start one unit and stop all others\n"
4715 " kill [NAME...] Send signal to processes of a unit\n"
4716 " is-active [NAME...] Check whether units are active\n"
4717 " is-failed [NAME...] Check whether units are failed\n"
4718 " status [NAME...|PID...] Show runtime status of one or more units\n"
4719 " show [NAME...|JOB...] Show properties of one or more\n"
4720 " units/jobs or the manager\n"
4721 " set-property [NAME] [ASSIGNMENT...]\n"
4722 " Sets one or more properties of a unit\n"
4723 " help [NAME...|PID...] Show manual for one or more units\n"
4724 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
4726 " load [NAME...] Load one or more units\n"
4727 " list-dependencies [NAME] Recursively show units which are required\n"
4728 " or wanted by this unit or by which this\n"
4729 " unit is required or wanted\n\n"
4730 "Unit File Commands:\n"
4731 " list-unit-files List installed unit files\n"
4732 " enable [NAME...] Enable one or more unit files\n"
4733 " disable [NAME...] Disable one or more unit files\n"
4734 " reenable [NAME...] Reenable one or more unit files\n"
4735 " preset [NAME...] Enable/disable one or more unit files\n"
4736 " based on preset configuration\n"
4737 " mask [NAME...] Mask one or more units\n"
4738 " unmask [NAME...] Unmask one or more units\n"
4739 " link [PATH...] Link one or more units files into\n"
4740 " the search path\n"
4741 " get-default Get the name of the default target\n"
4742 " set-default NAME Set the default target\n"
4743 " is-enabled [NAME...] Check whether unit files are enabled\n\n"
4745 " list-jobs List jobs\n"
4746 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
4747 "Status Commands:\n"
4748 " dump Dump server status\n"
4749 "Snapshot Commands:\n"
4750 " snapshot [NAME] Create a snapshot\n"
4751 " delete [NAME...] Remove one or more snapshots\n\n"
4752 "Environment Commands:\n"
4753 " show-environment Dump environment\n"
4754 " set-environment [NAME=VALUE...] Set one or more environment variables\n"
4755 " unset-environment [NAME...] Unset one or more environment variables\n"
4756 " set-log-level LEVEL Set logging threshold for systemd\n\n"
4757 "Manager Lifecycle Commands:\n"
4758 " daemon-reload Reload systemd manager configuration\n"
4759 " daemon-reexec Reexecute systemd manager\n\n"
4760 "System Commands:\n"
4761 " default Enter system default mode\n"
4762 " rescue Enter system rescue mode\n"
4763 " emergency Enter system emergency mode\n"
4764 " halt Shut down and halt the system\n"
4765 " poweroff Shut down and power-off the system\n"
4766 " reboot Shut down and reboot the system\n"
4767 " kexec Shut down and reboot the system with kexec\n"
4768 " exit Request user instance exit\n"
4769 " switch-root [ROOT] [INIT] Change to a different root file system\n"
4770 " suspend Suspend the system\n"
4771 " hibernate Hibernate the system\n"
4772 " hybrid-sleep Hibernate and suspend the system\n",
4773 program_invocation_short_name);
4778 static int halt_help(void) {
4780 printf("%s [OPTIONS...]\n\n"
4781 "%s the system.\n\n"
4782 " --help Show this help\n"
4783 " --halt Halt the machine\n"
4784 " -p --poweroff Switch off the machine\n"
4785 " --reboot Reboot the machine\n"
4786 " -f --force Force immediate halt/power-off/reboot\n"
4787 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
4788 " -d --no-wtmp Don't write wtmp record\n"
4789 " --no-wall Don't send wall message before halt/power-off/reboot\n",
4790 program_invocation_short_name,
4791 arg_action == ACTION_REBOOT ? "Reboot" :
4792 arg_action == ACTION_POWEROFF ? "Power off" :
4798 static int shutdown_help(void) {
4800 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
4801 "Shut down the system.\n\n"
4802 " --help Show this help\n"
4803 " -H --halt Halt the machine\n"
4804 " -P --poweroff Power-off the machine\n"
4805 " -r --reboot Reboot the machine\n"
4806 " -h Equivalent to --poweroff, overridden by --halt\n"
4807 " -k Don't halt/power-off/reboot, just send warnings\n"
4808 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4809 " -c Cancel a pending shutdown\n",
4810 program_invocation_short_name);
4815 static int telinit_help(void) {
4817 printf("%s [OPTIONS...] {COMMAND}\n\n"
4818 "Send control commands to the init daemon.\n\n"
4819 " --help Show this help\n"
4820 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
4822 " 0 Power-off the machine\n"
4823 " 6 Reboot the machine\n"
4824 " 2, 3, 4, 5 Start runlevelX.target unit\n"
4825 " 1, s, S Enter rescue mode\n"
4826 " q, Q Reload init daemon configuration\n"
4827 " u, U Reexecute init daemon\n",
4828 program_invocation_short_name);
4833 static int runlevel_help(void) {
4835 printf("%s [OPTIONS...]\n\n"
4836 "Prints the previous and current runlevel of the init system.\n\n"
4837 " --help Show this help\n",
4838 program_invocation_short_name);
4843 static int help_types(void) {
4847 puts("Available unit types:");
4848 for(i = 0; i < _UNIT_TYPE_MAX; i++) {
4849 t = unit_type_to_string(i);
4854 puts("\nAvailable unit load states: ");
4855 for(i = 0; i < _UNIT_LOAD_STATE_MAX; i++) {
4856 t = unit_load_state_to_string(i);
4864 static int systemctl_parse_argv(int argc, char *argv[]) {
4873 ARG_IGNORE_DEPENDENCIES,
4885 ARG_NO_ASK_PASSWORD,
4892 static const struct option options[] = {
4893 { "help", no_argument, NULL, 'h' },
4894 { "version", no_argument, NULL, ARG_VERSION },
4895 { "type", required_argument, NULL, 't' },
4896 { "property", required_argument, NULL, 'p' },
4897 { "all", no_argument, NULL, 'a' },
4898 { "reverse", no_argument, NULL, ARG_REVERSE },
4899 { "after", no_argument, NULL, ARG_AFTER },
4900 { "before", no_argument, NULL, ARG_BEFORE },
4901 { "show-types", no_argument, NULL, ARG_SHOW_TYPES },
4902 { "failed", no_argument, NULL, ARG_FAILED },
4903 { "full", no_argument, NULL, 'l' },
4904 { "fail", no_argument, NULL, ARG_FAIL },
4905 { "irreversible", no_argument, NULL, ARG_IRREVERSIBLE },
4906 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
4907 { "ignore-inhibitors", no_argument, NULL, 'i' },
4908 { "user", no_argument, NULL, ARG_USER },
4909 { "system", no_argument, NULL, ARG_SYSTEM },
4910 { "global", no_argument, NULL, ARG_GLOBAL },
4911 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
4912 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
4913 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
4914 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4915 { "quiet", no_argument, NULL, 'q' },
4916 { "root", required_argument, NULL, ARG_ROOT },
4917 { "force", no_argument, NULL, ARG_FORCE },
4918 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
4919 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
4920 { "signal", required_argument, NULL, 's' },
4921 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
4922 { "host", required_argument, NULL, 'H' },
4923 { "privileged",no_argument, NULL, 'P' },
4924 { "runtime", no_argument, NULL, ARG_RUNTIME },
4925 { "lines", required_argument, NULL, 'n' },
4926 { "output", required_argument, NULL, 'o' },
4927 { "plain", no_argument, NULL, ARG_PLAIN },
4928 { NULL, 0, NULL, 0 }
4936 while ((c = getopt_long(argc, argv, "ht:p:alqfs:H:Pn:o:i", options, NULL)) >= 0) {
4945 puts(PACKAGE_STRING);
4946 puts(SYSTEMD_FEATURES);
4953 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
4954 _cleanup_free_ char *type;
4956 type = strndup(word, size);
4960 if (streq(type, "help")) {
4965 if (unit_type_from_string(type) >= 0) {
4966 if (strv_push(&arg_types, type))
4972 if (unit_load_state_from_string(optarg) >= 0) {
4973 if (strv_push(&arg_load_states, type))
4979 log_error("Unknown unit type or load state '%s'.", type);
4980 log_info("Use -t help to see a list of allowed values.");
4988 /* Make sure that if the empty property list
4989 was specified, we won't show any properties. */
4990 if (isempty(optarg) && !arg_properties) {
4991 arg_properties = strv_new(NULL, NULL);
4992 if (!arg_properties)
4998 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
5001 prop = strndup(word, size);
5005 if (strv_push(&arg_properties, prop)) {
5012 /* If the user asked for a particular
5013 * property, show it to him, even if it is
5025 arg_dependency = DEPENDENCY_REVERSE;
5029 arg_dependency = DEPENDENCY_AFTER;
5033 arg_dependency = DEPENDENCY_BEFORE;
5036 case ARG_SHOW_TYPES:
5037 arg_show_types = true;
5041 arg_job_mode = "fail";
5044 case ARG_IRREVERSIBLE:
5045 arg_job_mode = "replace-irreversibly";
5048 case ARG_IGNORE_DEPENDENCIES:
5049 arg_job_mode = "ignore-dependencies";
5053 arg_scope = UNIT_FILE_USER;
5057 arg_scope = UNIT_FILE_SYSTEM;
5061 arg_scope = UNIT_FILE_GLOBAL;
5065 arg_no_block = true;
5069 arg_no_legend = true;
5073 arg_no_pager = true;
5105 arg_no_reload = true;
5109 arg_kill_who = optarg;
5113 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
5114 log_error("Failed to parse signal string %s.", optarg);
5119 case ARG_NO_ASK_PASSWORD:
5120 arg_ask_password = false;
5124 arg_transport = TRANSPORT_POLKIT;
5128 arg_transport = TRANSPORT_SSH;
5129 parse_user_at_host(optarg, &arg_user, &arg_host);
5137 if (safe_atou(optarg, &arg_lines) < 0) {
5138 log_error("Failed to parse lines '%s'", optarg);
5144 arg_output = output_mode_from_string(optarg);
5145 if (arg_output < 0) {
5146 log_error("Unknown output '%s'.", optarg);
5152 arg_ignore_inhibitors = true;
5163 log_error("Unknown option code '%c'.", c);
5168 if (arg_transport != TRANSPORT_NORMAL && arg_scope != UNIT_FILE_SYSTEM) {
5169 log_error("Cannot access user instance remotely.");
5176 static int halt_parse_argv(int argc, char *argv[]) {
5185 static const struct option options[] = {
5186 { "help", no_argument, NULL, ARG_HELP },
5187 { "halt", no_argument, NULL, ARG_HALT },
5188 { "poweroff", no_argument, NULL, 'p' },
5189 { "reboot", no_argument, NULL, ARG_REBOOT },
5190 { "force", no_argument, NULL, 'f' },
5191 { "wtmp-only", no_argument, NULL, 'w' },
5192 { "no-wtmp", no_argument, NULL, 'd' },
5193 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5194 { NULL, 0, NULL, 0 }
5202 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
5203 if (runlevel == '0' || runlevel == '6')
5206 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
5214 arg_action = ACTION_HALT;
5218 if (arg_action != ACTION_REBOOT)
5219 arg_action = ACTION_POWEROFF;
5223 arg_action = ACTION_REBOOT;
5245 /* Compatibility nops */
5252 log_error("Unknown option code '%c'.", c);
5257 if (optind < argc) {
5258 log_error("Too many arguments.");
5265 static int parse_time_spec(const char *t, usec_t *_u) {
5269 if (streq(t, "now"))
5271 else if (!strchr(t, ':')) {
5274 if (safe_atou64(t, &u) < 0)
5277 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
5286 hour = strtol(t, &e, 10);
5287 if (errno > 0 || *e != ':' || hour < 0 || hour > 23)
5290 minute = strtol(e+1, &e, 10);
5291 if (errno > 0 || *e != 0 || minute < 0 || minute > 59)
5294 n = now(CLOCK_REALTIME);
5295 s = (time_t) (n / USEC_PER_SEC);
5297 assert_se(localtime_r(&s, &tm));
5299 tm.tm_hour = (int) hour;
5300 tm.tm_min = (int) minute;
5303 assert_se(s = mktime(&tm));
5305 *_u = (usec_t) s * USEC_PER_SEC;
5308 *_u += USEC_PER_DAY;
5314 static int shutdown_parse_argv(int argc, char *argv[]) {
5321 static const struct option options[] = {
5322 { "help", no_argument, NULL, ARG_HELP },
5323 { "halt", no_argument, NULL, 'H' },
5324 { "poweroff", no_argument, NULL, 'P' },
5325 { "reboot", no_argument, NULL, 'r' },
5326 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
5327 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5328 { NULL, 0, NULL, 0 }
5336 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
5344 arg_action = ACTION_HALT;
5348 arg_action = ACTION_POWEROFF;
5353 arg_action = ACTION_KEXEC;
5355 arg_action = ACTION_REBOOT;
5359 arg_action = ACTION_KEXEC;
5363 if (arg_action != ACTION_HALT)
5364 arg_action = ACTION_POWEROFF;
5377 /* Compatibility nops */
5381 arg_action = ACTION_CANCEL_SHUTDOWN;
5388 log_error("Unknown option code '%c'.", c);
5393 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
5394 r = parse_time_spec(argv[optind], &arg_when);
5396 log_error("Failed to parse time specification: %s", argv[optind]);
5400 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
5402 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
5403 /* No time argument for shutdown cancel */
5404 arg_wall = argv + optind;
5405 else if (argc > optind + 1)
5406 /* We skip the time argument */
5407 arg_wall = argv + optind + 1;
5414 static int telinit_parse_argv(int argc, char *argv[]) {
5421 static const struct option options[] = {
5422 { "help", no_argument, NULL, ARG_HELP },
5423 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5424 { NULL, 0, NULL, 0 }
5427 static const struct {
5431 { '0', ACTION_POWEROFF },
5432 { '6', ACTION_REBOOT },
5433 { '1', ACTION_RESCUE },
5434 { '2', ACTION_RUNLEVEL2 },
5435 { '3', ACTION_RUNLEVEL3 },
5436 { '4', ACTION_RUNLEVEL4 },
5437 { '5', ACTION_RUNLEVEL5 },
5438 { 's', ACTION_RESCUE },
5439 { 'S', ACTION_RESCUE },
5440 { 'q', ACTION_RELOAD },
5441 { 'Q', ACTION_RELOAD },
5442 { 'u', ACTION_REEXEC },
5443 { 'U', ACTION_REEXEC }
5452 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
5467 log_error("Unknown option code '%c'.", c);
5472 if (optind >= argc) {
5477 if (optind + 1 < argc) {
5478 log_error("Too many arguments.");
5482 if (strlen(argv[optind]) != 1) {
5483 log_error("Expected single character argument.");
5487 for (i = 0; i < ELEMENTSOF(table); i++)
5488 if (table[i].from == argv[optind][0])
5491 if (i >= ELEMENTSOF(table)) {
5492 log_error("Unknown command '%s'.", argv[optind]);
5496 arg_action = table[i].to;
5503 static int runlevel_parse_argv(int argc, char *argv[]) {
5509 static const struct option options[] = {
5510 { "help", no_argument, NULL, ARG_HELP },
5511 { NULL, 0, NULL, 0 }
5519 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
5530 log_error("Unknown option code '%c'.", c);
5535 if (optind < argc) {
5536 log_error("Too many arguments.");
5543 static int parse_argv(int argc, char *argv[]) {
5547 if (program_invocation_short_name) {
5549 if (strstr(program_invocation_short_name, "halt")) {
5550 arg_action = ACTION_HALT;
5551 return halt_parse_argv(argc, argv);
5552 } else if (strstr(program_invocation_short_name, "poweroff")) {
5553 arg_action = ACTION_POWEROFF;
5554 return halt_parse_argv(argc, argv);
5555 } else if (strstr(program_invocation_short_name, "reboot")) {
5557 arg_action = ACTION_KEXEC;
5559 arg_action = ACTION_REBOOT;
5560 return halt_parse_argv(argc, argv);
5561 } else if (strstr(program_invocation_short_name, "shutdown")) {
5562 arg_action = ACTION_POWEROFF;
5563 return shutdown_parse_argv(argc, argv);
5564 } else if (strstr(program_invocation_short_name, "init")) {
5566 if (sd_booted() > 0) {
5567 arg_action = ACTION_INVALID;
5568 return telinit_parse_argv(argc, argv);
5570 /* Hmm, so some other init system is
5571 * running, we need to forward this
5572 * request to it. For now we simply
5573 * guess that it is Upstart. */
5575 execv(TELINIT, argv);
5577 log_error("Couldn't find an alternative telinit implementation to spawn.");
5581 } else if (strstr(program_invocation_short_name, "runlevel")) {
5582 arg_action = ACTION_RUNLEVEL;
5583 return runlevel_parse_argv(argc, argv);
5587 arg_action = ACTION_SYSTEMCTL;
5588 return systemctl_parse_argv(argc, argv);
5591 _pure_ static int action_to_runlevel(void) {
5593 static const char table[_ACTION_MAX] = {
5594 [ACTION_HALT] = '0',
5595 [ACTION_POWEROFF] = '0',
5596 [ACTION_REBOOT] = '6',
5597 [ACTION_RUNLEVEL2] = '2',
5598 [ACTION_RUNLEVEL3] = '3',
5599 [ACTION_RUNLEVEL4] = '4',
5600 [ACTION_RUNLEVEL5] = '5',
5601 [ACTION_RESCUE] = '1'
5604 assert(arg_action < _ACTION_MAX);
5606 return table[arg_action];
5609 static int talk_upstart(void) {
5610 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
5611 _cleanup_dbus_error_free_ DBusError error;
5612 int previous, rl, r;
5614 env1_buf[] = "RUNLEVEL=X",
5615 env2_buf[] = "PREVLEVEL=X";
5616 char *env1 = env1_buf, *env2 = env2_buf;
5617 const char *emit = "runlevel";
5618 dbus_bool_t b_false = FALSE;
5619 DBusMessageIter iter, sub;
5620 DBusConnection *bus;
5622 dbus_error_init(&error);
5624 if (!(rl = action_to_runlevel()))
5627 if (utmp_get_runlevel(&previous, NULL) < 0)
5630 if (!(bus = dbus_connection_open_private("unix:abstract=/com/ubuntu/upstart", &error))) {
5631 if (dbus_error_has_name(&error, DBUS_ERROR_NO_SERVER)) {
5636 log_error("Failed to connect to Upstart bus: %s", bus_error_message(&error));
5641 if ((r = bus_check_peercred(bus)) < 0) {
5642 log_error("Failed to verify owner of bus.");
5646 if (!(m = dbus_message_new_method_call(
5647 "com.ubuntu.Upstart",
5648 "/com/ubuntu/Upstart",
5649 "com.ubuntu.Upstart0_6",
5652 log_error("Could not allocate message.");
5657 dbus_message_iter_init_append(m, &iter);
5659 env1_buf[sizeof(env1_buf)-2] = rl;
5660 env2_buf[sizeof(env2_buf)-2] = previous;
5662 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &emit) ||
5663 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub) ||
5664 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env1) ||
5665 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env2) ||
5666 !dbus_message_iter_close_container(&iter, &sub) ||
5667 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b_false)) {
5668 log_error("Could not append arguments to message.");
5673 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
5675 if (bus_error_is_no_service(&error)) {
5680 log_error("Failed to issue method call: %s", bus_error_message(&error));
5689 dbus_connection_flush(bus);
5690 dbus_connection_close(bus);
5691 dbus_connection_unref(bus);
5697 static int talk_initctl(void) {
5698 struct init_request request = {};
5700 _cleanup_close_ int fd = -1;
5703 rl = action_to_runlevel();
5707 request.magic = INIT_MAGIC;
5708 request.sleeptime = 0;
5709 request.cmd = INIT_CMD_RUNLVL;
5710 request.runlevel = rl;
5712 fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY);
5714 if (errno == ENOENT)
5717 log_error("Failed to open "INIT_FIFO": %m");
5722 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
5724 log_error("Failed to write to "INIT_FIFO": %m");
5725 return errno > 0 ? -errno : -EIO;
5731 static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
5733 static const struct {
5741 int (* const dispatch)(DBusConnection *bus, char **args);
5743 { "list-units", LESS, 1, list_units },
5744 { "list-unit-files", EQUAL, 1, list_unit_files },
5745 { "list-sockets", LESS, 1, list_sockets },
5746 { "list-jobs", EQUAL, 1, list_jobs },
5747 { "clear-jobs", EQUAL, 1, daemon_reload },
5748 { "load", MORE, 2, load_unit },
5749 { "cancel", MORE, 2, cancel_job },
5750 { "start", MORE, 2, start_unit },
5751 { "stop", MORE, 2, start_unit },
5752 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5753 { "reload", MORE, 2, start_unit },
5754 { "restart", MORE, 2, start_unit },
5755 { "try-restart", MORE, 2, start_unit },
5756 { "reload-or-restart", MORE, 2, start_unit },
5757 { "reload-or-try-restart", MORE, 2, start_unit },
5758 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
5759 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5760 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
5761 { "isolate", EQUAL, 2, start_unit },
5762 { "kill", MORE, 2, kill_unit },
5763 { "is-active", MORE, 2, check_unit_active },
5764 { "check", MORE, 2, check_unit_active },
5765 { "is-failed", MORE, 2, check_unit_failed },
5766 { "show", MORE, 1, show },
5767 { "status", MORE, 1, show },
5768 { "help", MORE, 2, show },
5769 { "dump", EQUAL, 1, dump },
5770 { "snapshot", LESS, 2, snapshot },
5771 { "delete", MORE, 2, delete_snapshot },
5772 { "daemon-reload", EQUAL, 1, daemon_reload },
5773 { "daemon-reexec", EQUAL, 1, daemon_reload },
5774 { "show-environment", EQUAL, 1, show_enviroment },
5775 { "set-environment", MORE, 2, set_environment },
5776 { "unset-environment", MORE, 2, set_environment },
5777 { "halt", EQUAL, 1, start_special },
5778 { "poweroff", EQUAL, 1, start_special },
5779 { "reboot", EQUAL, 1, start_special },
5780 { "kexec", EQUAL, 1, start_special },
5781 { "suspend", EQUAL, 1, start_special },
5782 { "hibernate", EQUAL, 1, start_special },
5783 { "hybrid-sleep", EQUAL, 1, start_special },
5784 { "default", EQUAL, 1, start_special },
5785 { "rescue", EQUAL, 1, start_special },
5786 { "emergency", EQUAL, 1, start_special },
5787 { "exit", EQUAL, 1, start_special },
5788 { "reset-failed", MORE, 1, reset_failed },
5789 { "enable", MORE, 2, enable_unit },
5790 { "disable", MORE, 2, enable_unit },
5791 { "is-enabled", MORE, 2, unit_is_enabled },
5792 { "reenable", MORE, 2, enable_unit },
5793 { "preset", MORE, 2, enable_unit },
5794 { "mask", MORE, 2, enable_unit },
5795 { "unmask", MORE, 2, enable_unit },
5796 { "link", MORE, 2, enable_unit },
5797 { "switch-root", MORE, 2, switch_root },
5798 { "list-dependencies", LESS, 2, list_dependencies },
5799 { "set-default", EQUAL, 2, enable_unit },
5800 { "get-default", LESS, 1, get_default },
5801 { "set-log-level", EQUAL, 2, set_log_level },
5802 { "set-property", MORE, 3, set_property },
5812 left = argc - optind;
5815 /* Special rule: no arguments means "list-units" */
5818 if (streq(argv[optind], "help") && !argv[optind+1]) {
5819 log_error("This command expects one or more "
5820 "unit names. Did you mean --help?");
5824 for (i = 0; i < ELEMENTSOF(verbs); i++)
5825 if (streq(argv[optind], verbs[i].verb))
5828 if (i >= ELEMENTSOF(verbs)) {
5829 log_error("Unknown operation '%s'.", argv[optind]);
5834 switch (verbs[i].argc_cmp) {
5837 if (left != verbs[i].argc) {
5838 log_error("Invalid number of arguments.");
5845 if (left < verbs[i].argc) {
5846 log_error("Too few arguments.");
5853 if (left > verbs[i].argc) {
5854 log_error("Too many arguments.");
5861 assert_not_reached("Unknown comparison operator.");
5864 /* Require a bus connection for all operations but
5866 if (!streq(verbs[i].verb, "enable") &&
5867 !streq(verbs[i].verb, "disable") &&
5868 !streq(verbs[i].verb, "is-enabled") &&
5869 !streq(verbs[i].verb, "list-unit-files") &&
5870 !streq(verbs[i].verb, "reenable") &&
5871 !streq(verbs[i].verb, "preset") &&
5872 !streq(verbs[i].verb, "mask") &&
5873 !streq(verbs[i].verb, "unmask") &&
5874 !streq(verbs[i].verb, "link") &&
5875 !streq(verbs[i].verb, "set-default") &&
5876 !streq(verbs[i].verb, "get-default")) {
5878 if (running_in_chroot() > 0) {
5879 log_info("Running in chroot, ignoring request.");
5883 if (((!streq(verbs[i].verb, "reboot") &&
5884 !streq(verbs[i].verb, "halt") &&
5885 !streq(verbs[i].verb, "poweroff")) || arg_force <= 0) && !bus) {
5886 log_error("Failed to get D-Bus connection: %s",
5887 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5893 if (!bus && !avoid_bus()) {
5894 log_error("Failed to get D-Bus connection: %s",
5895 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5900 return verbs[i].dispatch(bus, argv + optind);
5903 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
5904 _cleanup_close_ int fd;
5905 struct sd_shutdown_command c = {
5911 union sockaddr_union sockaddr = {
5912 .un.sun_family = AF_UNIX,
5913 .un.sun_path = "/run/systemd/shutdownd",
5915 struct iovec iovec[2] = {
5916 {.iov_base = (char*) &c,
5917 .iov_len = offsetof(struct sd_shutdown_command, wall_message),
5920 struct msghdr msghdr = {
5921 .msg_name = &sockaddr,
5922 .msg_namelen = offsetof(struct sockaddr_un, sun_path)
5923 + sizeof("/run/systemd/shutdownd") - 1,
5928 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
5932 if (!isempty(message)) {
5933 iovec[1].iov_base = (char*) message;
5934 iovec[1].iov_len = strlen(message);
5935 msghdr.msg_iovlen++;
5938 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0)
5944 static int reload_with_fallback(DBusConnection *bus) {
5947 /* First, try systemd via D-Bus. */
5948 if (daemon_reload(bus, NULL) >= 0)
5952 /* Nothing else worked, so let's try signals */
5953 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
5955 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
5956 log_error("kill() failed: %m");
5963 static int start_with_fallback(DBusConnection *bus) {
5966 /* First, try systemd via D-Bus. */
5967 if (start_unit(bus, NULL) >= 0)
5971 /* Hmm, talking to systemd via D-Bus didn't work. Then
5972 * let's try to talk to Upstart via D-Bus. */
5973 if (talk_upstart() > 0)
5976 /* Nothing else worked, so let's try
5978 if (talk_initctl() > 0)
5981 log_error("Failed to talk to init daemon.");
5985 warn_wall(arg_action);
5989 static _noreturn_ void halt_now(enum action a) {
5991 /* Make sure C-A-D is handled by the kernel from this
5993 reboot(RB_ENABLE_CAD);
5998 log_info("Halting.");
5999 reboot(RB_HALT_SYSTEM);
6002 case ACTION_POWEROFF:
6003 log_info("Powering off.");
6004 reboot(RB_POWER_OFF);
6008 log_info("Rebooting.");
6009 reboot(RB_AUTOBOOT);
6013 assert_not_reached("Unknown halt action.");
6016 assert_not_reached("Uh? This shouldn't happen.");
6019 static int halt_main(DBusConnection *bus) {
6022 r = check_inhibitors(bus, arg_action);
6026 if (geteuid() != 0) {
6027 /* Try logind if we are a normal user and no special
6028 * mode applies. Maybe PolicyKit allows us to shutdown
6031 if (arg_when <= 0 &&
6034 (arg_action == ACTION_POWEROFF ||
6035 arg_action == ACTION_REBOOT)) {
6036 r = reboot_with_logind(bus, arg_action);
6041 log_error("Must be root.");
6046 _cleanup_free_ char *m;
6048 m = strv_join(arg_wall, " ");
6049 r = send_shutdownd(arg_when,
6050 arg_action == ACTION_HALT ? 'H' :
6051 arg_action == ACTION_POWEROFF ? 'P' :
6052 arg_action == ACTION_KEXEC ? 'K' :
6059 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
6061 char date[FORMAT_TIMESTAMP_MAX];
6063 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
6064 format_timestamp(date, sizeof(date), arg_when));
6069 if (!arg_dry && !arg_force)
6070 return start_with_fallback(bus);
6073 if (sd_booted() > 0)
6074 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
6076 r = utmp_put_shutdown();
6078 log_warning("Failed to write utmp record: %s", strerror(-r));
6085 halt_now(arg_action);
6086 /* We should never reach this. */
6090 static int runlevel_main(void) {
6091 int r, runlevel, previous;
6093 r = utmp_get_runlevel(&runlevel, &previous);
6100 previous <= 0 ? 'N' : previous,
6101 runlevel <= 0 ? 'N' : runlevel);
6106 int main(int argc, char*argv[]) {
6107 int r, retval = EXIT_FAILURE;
6108 DBusConnection *bus = NULL;
6109 _cleanup_dbus_error_free_ DBusError error;
6111 dbus_error_init(&error);
6113 setlocale(LC_ALL, "");
6114 log_parse_environment();
6117 r = parse_argv(argc, argv);
6121 retval = EXIT_SUCCESS;
6125 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
6126 * let's shortcut this */
6127 if (arg_action == ACTION_RUNLEVEL) {
6128 r = runlevel_main();
6129 retval = r < 0 ? EXIT_FAILURE : r;
6133 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
6134 log_info("Running in chroot, ignoring request.");
6140 if (arg_transport == TRANSPORT_NORMAL)
6141 bus_connect(arg_scope == UNIT_FILE_SYSTEM ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &bus, &private_bus, &error);
6142 else if (arg_transport == TRANSPORT_POLKIT) {
6143 bus_connect_system_polkit(&bus, &error);
6144 private_bus = false;
6145 } else if (arg_transport == TRANSPORT_SSH) {
6146 bus_connect_system_ssh(arg_user, arg_host, &bus, &error);
6147 private_bus = false;
6149 assert_not_reached("Uh, invalid transport...");
6152 switch (arg_action) {
6154 case ACTION_SYSTEMCTL:
6155 r = systemctl_main(bus, argc, argv, &error);
6159 case ACTION_POWEROFF:
6165 case ACTION_RUNLEVEL2:
6166 case ACTION_RUNLEVEL3:
6167 case ACTION_RUNLEVEL4:
6168 case ACTION_RUNLEVEL5:
6170 case ACTION_EMERGENCY:
6171 case ACTION_DEFAULT:
6172 r = start_with_fallback(bus);
6177 r = reload_with_fallback(bus);
6180 case ACTION_CANCEL_SHUTDOWN: {
6184 m = strv_join(arg_wall, " ");
6186 retval = EXIT_FAILURE;
6190 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
6192 log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r));
6197 case ACTION_INVALID:
6198 case ACTION_RUNLEVEL:
6200 assert_not_reached("Unknown action");
6203 retval = r < 0 ? EXIT_FAILURE : r;
6207 dbus_connection_flush(bus);
6208 dbus_connection_close(bus);
6209 dbus_connection_unref(bus);
6214 strv_free(arg_types);
6215 strv_free(arg_load_states);
6216 strv_free(arg_properties);
6219 ask_password_agent_close();
6220 polkit_agent_close();