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 bool need_daemon_reload(DBusConnection *bus, const char *unit) {
1458 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1459 dbus_bool_t b = FALSE;
1460 DBusMessageIter iter, sub;
1462 *interface = "org.freedesktop.systemd1.Unit",
1463 *property = "NeedDaemonReload",
1465 _cleanup_free_ char *n = NULL;
1468 /* We ignore all errors here, since this is used to show a warning only */
1470 n = unit_name_mangle(unit);
1474 r = bus_method_call_with_reply(
1476 "org.freedesktop.systemd1",
1477 "/org/freedesktop/systemd1",
1478 "org.freedesktop.systemd1.Manager",
1482 DBUS_TYPE_STRING, &n,
1487 if (!dbus_message_get_args(reply, NULL,
1488 DBUS_TYPE_OBJECT_PATH, &path,
1492 dbus_message_unref(reply);
1495 r = bus_method_call_with_reply(
1497 "org.freedesktop.systemd1",
1499 "org.freedesktop.DBus.Properties",
1503 DBUS_TYPE_STRING, &interface,
1504 DBUS_TYPE_STRING, &property,
1509 if (!dbus_message_iter_init(reply, &iter) ||
1510 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
1513 dbus_message_iter_recurse(&iter, &sub);
1514 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_BOOLEAN)
1517 dbus_message_iter_get_basic(&sub, &b);
1521 typedef struct WaitData {
1528 static DBusHandlerResult wait_filter(DBusConnection *connection, DBusMessage *message, void *data) {
1529 _cleanup_dbus_error_free_ DBusError error;
1532 dbus_error_init(&error);
1538 log_debug("Got D-Bus request: %s.%s() on %s",
1539 dbus_message_get_interface(message),
1540 dbus_message_get_member(message),
1541 dbus_message_get_path(message));
1543 if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
1544 log_error("Warning! D-Bus connection terminated.");
1545 dbus_connection_close(connection);
1547 } else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
1549 const char *path, *result, *unit;
1551 if (dbus_message_get_args(message, &error,
1552 DBUS_TYPE_UINT32, &id,
1553 DBUS_TYPE_OBJECT_PATH, &path,
1554 DBUS_TYPE_STRING, &unit,
1555 DBUS_TYPE_STRING, &result,
1556 DBUS_TYPE_INVALID)) {
1558 free(set_remove(d->set, (char*) path));
1560 if (!isempty(result))
1561 d->result = strdup(result);
1564 d->name = strdup(unit);
1566 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1569 dbus_error_free(&error);
1570 if (dbus_message_get_args(message, &error,
1571 DBUS_TYPE_UINT32, &id,
1572 DBUS_TYPE_OBJECT_PATH, &path,
1573 DBUS_TYPE_STRING, &result,
1574 DBUS_TYPE_INVALID)) {
1575 /* Compatibility with older systemd versions <
1576 * 183 during upgrades. This should be dropped
1578 free(set_remove(d->set, (char*) path));
1581 d->result = strdup(result);
1583 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1587 log_error("Failed to parse message: %s", bus_error_message(&error));
1590 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1593 static int enable_wait_for_jobs(DBusConnection *bus) {
1601 dbus_error_init(&error);
1602 dbus_bus_add_match(bus,
1604 "sender='org.freedesktop.systemd1',"
1605 "interface='org.freedesktop.systemd1.Manager',"
1606 "member='JobRemoved',"
1607 "path='/org/freedesktop/systemd1'",
1610 if (dbus_error_is_set(&error)) {
1611 log_error("Failed to add match: %s", bus_error_message(&error));
1612 dbus_error_free(&error);
1616 /* This is slightly dirty, since we don't undo the match registrations. */
1620 static int wait_for_jobs(DBusConnection *bus, Set *s) {
1622 WaitData d = { .set = s };
1627 if (!dbus_connection_add_filter(bus, wait_filter, &d, NULL))
1630 while (!set_isempty(s)) {
1632 if (!dbus_connection_read_write_dispatch(bus, -1)) {
1633 log_error("Disconnected from bus.");
1634 return -ECONNREFUSED;
1641 if (streq(d.result, "timeout"))
1642 log_error("Job for %s timed out.", strna(d.name));
1643 else if (streq(d.result, "canceled"))
1644 log_error("Job for %s canceled.", strna(d.name));
1645 else if (streq(d.result, "dependency"))
1646 log_error("A dependency job for %s failed. See 'journalctl -xn' for details.", strna(d.name));
1647 else if (!streq(d.result, "done") && !streq(d.result, "skipped"))
1648 log_error("Job for %s failed. See 'systemctl status %s' and 'journalctl -xn' for details.", strna(d.name), strna(d.name));
1651 if (streq_ptr(d.result, "timeout"))
1653 else if (streq_ptr(d.result, "canceled"))
1655 else if (!streq_ptr(d.result, "done") && !streq_ptr(d.result, "skipped"))
1666 dbus_connection_remove_filter(bus, wait_filter, &d);
1670 static int check_one_unit(DBusConnection *bus, const char *name, char **check_states, bool quiet) {
1671 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1672 _cleanup_free_ char *n = NULL;
1673 DBusMessageIter iter, sub;
1675 *interface = "org.freedesktop.systemd1.Unit",
1676 *property = "ActiveState";
1677 const char *state, *path;
1683 dbus_error_init(&error);
1685 n = unit_name_mangle(name);
1689 r = bus_method_call_with_reply (
1691 "org.freedesktop.systemd1",
1692 "/org/freedesktop/systemd1",
1693 "org.freedesktop.systemd1.Manager",
1697 DBUS_TYPE_STRING, &n,
1700 dbus_error_free(&error);
1707 if (!dbus_message_get_args(reply, NULL,
1708 DBUS_TYPE_OBJECT_PATH, &path,
1709 DBUS_TYPE_INVALID)) {
1710 log_error("Failed to parse reply.");
1714 dbus_message_unref(reply);
1717 r = bus_method_call_with_reply(
1719 "org.freedesktop.systemd1",
1721 "org.freedesktop.DBus.Properties",
1725 DBUS_TYPE_STRING, &interface,
1726 DBUS_TYPE_STRING, &property,
1734 if (!dbus_message_iter_init(reply, &iter) ||
1735 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1736 log_error("Failed to parse reply.");
1740 dbus_message_iter_recurse(&iter, &sub);
1742 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1743 log_error("Failed to parse reply.");
1747 dbus_message_iter_get_basic(&sub, &state);
1752 return strv_find(check_states, state) ? 1 : 0;
1755 static void check_triggering_units(
1756 DBusConnection *bus,
1757 const char *unit_name) {
1759 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1760 DBusMessageIter iter, sub;
1761 const char *interface = "org.freedesktop.systemd1.Unit",
1762 *load_state_property = "LoadState",
1763 *triggered_by_property = "TriggeredBy",
1765 _cleanup_free_ char *unit_path = NULL, *n = NULL;
1766 bool print_warning_label = true;
1769 n = unit_name_mangle(unit_name);
1775 unit_path = unit_dbus_path_from_name(n);
1781 r = bus_method_call_with_reply(
1783 "org.freedesktop.systemd1",
1785 "org.freedesktop.DBus.Properties",
1789 DBUS_TYPE_STRING, &interface,
1790 DBUS_TYPE_STRING, &load_state_property,
1795 if (!dbus_message_iter_init(reply, &iter) ||
1796 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1797 log_error("Failed to parse reply.");
1801 dbus_message_iter_recurse(&iter, &sub);
1803 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1804 log_error("Failed to parse reply.");
1808 dbus_message_iter_get_basic(&sub, &state);
1810 if (streq(state, "masked"))
1813 dbus_message_unref(reply);
1816 r = bus_method_call_with_reply(
1818 "org.freedesktop.systemd1",
1820 "org.freedesktop.DBus.Properties",
1824 DBUS_TYPE_STRING, &interface,
1825 DBUS_TYPE_STRING, &triggered_by_property,
1830 if (!dbus_message_iter_init(reply, &iter) ||
1831 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1832 log_error("Failed to parse reply.");
1836 dbus_message_iter_recurse(&iter, &sub);
1837 dbus_message_iter_recurse(&sub, &iter);
1840 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1841 const char * const check_states[] = {
1846 const char *service_trigger;
1848 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1849 log_error("Failed to parse reply.");
1853 dbus_message_iter_get_basic(&sub, &service_trigger);
1855 r = check_one_unit(bus, service_trigger, (char**) check_states, true);
1859 if (print_warning_label) {
1860 log_warning("Warning: Stopping %s, but it can still be activated by:", unit_name);
1861 print_warning_label = false;
1864 log_warning(" %s", service_trigger);
1867 dbus_message_iter_next(&sub);
1871 static int start_unit_one(
1872 DBusConnection *bus,
1879 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1880 _cleanup_free_ char *n;
1889 n = unit_name_mangle(name);
1893 r = bus_method_call_with_reply(
1895 "org.freedesktop.systemd1",
1896 "/org/freedesktop/systemd1",
1897 "org.freedesktop.systemd1.Manager",
1901 DBUS_TYPE_STRING, &n,
1902 DBUS_TYPE_STRING, &mode,
1905 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
1906 /* There's always a fallback possible for
1907 * legacy actions. */
1910 log_error("Failed to issue method call: %s", bus_error_message(error));
1915 if (!dbus_message_get_args(reply, error,
1916 DBUS_TYPE_OBJECT_PATH, &path,
1917 DBUS_TYPE_INVALID)) {
1918 log_error("Failed to parse reply: %s", bus_error_message(error));
1922 if (need_daemon_reload(bus, n))
1923 log_warning("Warning: Unit file of %s changed on disk, 'systemctl %sdaemon-reload' recommended.",
1924 n, arg_scope == UNIT_FILE_SYSTEM ? "" : "--user ");
1933 r = set_consume(s, p);
1935 log_error("Failed to add path to set.");
1943 static const struct {
1947 } action_table[_ACTION_MAX] = {
1948 [ACTION_HALT] = { SPECIAL_HALT_TARGET, "halt", "replace-irreversibly" },
1949 [ACTION_POWEROFF] = { SPECIAL_POWEROFF_TARGET, "poweroff", "replace-irreversibly" },
1950 [ACTION_REBOOT] = { SPECIAL_REBOOT_TARGET, "reboot", "replace-irreversibly" },
1951 [ACTION_KEXEC] = { SPECIAL_KEXEC_TARGET, "kexec", "replace-irreversibly" },
1952 [ACTION_RUNLEVEL2] = { SPECIAL_RUNLEVEL2_TARGET, NULL, "isolate" },
1953 [ACTION_RUNLEVEL3] = { SPECIAL_RUNLEVEL3_TARGET, NULL, "isolate" },
1954 [ACTION_RUNLEVEL4] = { SPECIAL_RUNLEVEL4_TARGET, NULL, "isolate" },
1955 [ACTION_RUNLEVEL5] = { SPECIAL_RUNLEVEL5_TARGET, NULL, "isolate" },
1956 [ACTION_RESCUE] = { SPECIAL_RESCUE_TARGET, "rescue", "isolate" },
1957 [ACTION_EMERGENCY] = { SPECIAL_EMERGENCY_TARGET, "emergency", "isolate" },
1958 [ACTION_DEFAULT] = { SPECIAL_DEFAULT_TARGET, "default", "isolate" },
1959 [ACTION_EXIT] = { SPECIAL_EXIT_TARGET, "exit", "replace-irreversibly" },
1960 [ACTION_SUSPEND] = { SPECIAL_SUSPEND_TARGET, "suspend", "replace-irreversibly" },
1961 [ACTION_HIBERNATE] = { SPECIAL_HIBERNATE_TARGET, "hibernate", "replace-irreversibly" },
1962 [ACTION_HYBRID_SLEEP] = { SPECIAL_HYBRID_SLEEP_TARGET, "hybrid-sleep", "replace-irreversibly" },
1965 static enum action verb_to_action(const char *verb) {
1968 for (i = ACTION_INVALID; i < _ACTION_MAX; i++)
1969 if (action_table[i].verb && streq(verb, action_table[i].verb))
1971 return ACTION_INVALID;
1974 static int start_unit(DBusConnection *bus, char **args) {
1977 const char *method, *mode, *one_name;
1978 _cleanup_set_free_free_ Set *s = NULL;
1979 _cleanup_dbus_error_free_ DBusError error;
1982 dbus_error_init(&error);
1986 ask_password_agent_open_if_enabled();
1988 if (arg_action == ACTION_SYSTEMCTL) {
1991 streq(args[0], "stop") ||
1992 streq(args[0], "condstop") ? "StopUnit" :
1993 streq(args[0], "reload") ? "ReloadUnit" :
1994 streq(args[0], "restart") ? "RestartUnit" :
1996 streq(args[0], "try-restart") ||
1997 streq(args[0], "condrestart") ? "TryRestartUnit" :
1999 streq(args[0], "reload-or-restart") ? "ReloadOrRestartUnit" :
2001 streq(args[0], "reload-or-try-restart") ||
2002 streq(args[0], "condreload") ||
2004 streq(args[0], "force-reload") ? "ReloadOrTryRestartUnit" :
2006 action = verb_to_action(args[0]);
2008 mode = streq(args[0], "isolate") ? "isolate" :
2009 action_table[action].mode ?: arg_job_mode;
2011 one_name = action_table[action].target;
2014 assert(arg_action < ELEMENTSOF(action_table));
2015 assert(action_table[arg_action].target);
2017 method = "StartUnit";
2019 mode = action_table[arg_action].mode;
2020 one_name = action_table[arg_action].target;
2023 if (!arg_no_block) {
2024 ret = enable_wait_for_jobs(bus);
2026 log_error("Could not watch jobs: %s", strerror(-ret));
2030 s = set_new(string_hash_func, string_compare_func);
2036 ret = start_unit_one(bus, method, one_name, mode, &error, s);
2038 ret = translate_bus_error_to_exit_status(ret, &error);
2040 STRV_FOREACH(name, args+1) {
2041 r = start_unit_one(bus, method, *name, mode, &error, s);
2043 ret = translate_bus_error_to_exit_status(r, &error);
2044 dbus_error_free(&error);
2049 if (!arg_no_block) {
2050 r = wait_for_jobs(bus, s);
2054 /* When stopping units, warn if they can still be triggered by
2055 * another active unit (socket, path, timer) */
2056 if (!arg_quiet && streq(method, "StopUnit")) {
2058 check_triggering_units(bus, one_name);
2060 STRV_FOREACH(name, args+1)
2061 check_triggering_units(bus, *name);
2068 /* Ask systemd-logind, which might grant access to unprivileged users
2069 * through PolicyKit */
2070 static int reboot_with_logind(DBusConnection *bus, enum action a) {
2073 dbus_bool_t interactive = true;
2078 polkit_agent_open_if_enabled();
2086 case ACTION_POWEROFF:
2087 method = "PowerOff";
2090 case ACTION_SUSPEND:
2094 case ACTION_HIBERNATE:
2095 method = "Hibernate";
2098 case ACTION_HYBRID_SLEEP:
2099 method = "HybridSleep";
2106 return bus_method_call_with_reply(
2108 "org.freedesktop.login1",
2109 "/org/freedesktop/login1",
2110 "org.freedesktop.login1.Manager",
2114 DBUS_TYPE_BOOLEAN, &interactive,
2121 static int check_inhibitors(DBusConnection *bus, enum action a) {
2123 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
2124 DBusMessageIter iter, sub, sub2;
2127 _cleanup_strv_free_ char **sessions = NULL;
2133 if (arg_ignore_inhibitors || arg_force > 0)
2145 r = bus_method_call_with_reply(
2147 "org.freedesktop.login1",
2148 "/org/freedesktop/login1",
2149 "org.freedesktop.login1.Manager",
2155 /* If logind is not around, then there are no inhibitors... */
2158 if (!dbus_message_iter_init(reply, &iter) ||
2159 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
2160 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
2161 log_error("Failed to parse reply.");
2165 dbus_message_iter_recurse(&iter, &sub);
2166 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
2167 const char *what, *who, *why, *mode;
2169 _cleanup_strv_free_ char **sv = NULL;
2170 _cleanup_free_ char *comm = NULL, *user = NULL;
2172 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
2173 log_error("Failed to parse reply.");
2177 dbus_message_iter_recurse(&sub, &sub2);
2179 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &what, true) < 0 ||
2180 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &who, true) < 0 ||
2181 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &why, true) < 0 ||
2182 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &mode, true) < 0 ||
2183 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &uid, true) < 0 ||
2184 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, false) < 0) {
2185 log_error("Failed to parse reply.");
2189 if (!streq(mode, "block"))
2192 sv = strv_split(what, ":");
2196 if (!strv_contains(sv,
2198 a == ACTION_POWEROFF ||
2199 a == ACTION_REBOOT ||
2200 a == ACTION_KEXEC ? "shutdown" : "sleep"))
2203 get_process_comm(pid, &comm);
2204 user = uid_to_name(uid);
2205 log_warning("Operation inhibited by \"%s\" (PID %lu \"%s\", user %s), reason is \"%s\".",
2206 who, (unsigned long) pid, strna(comm), strna(user), why);
2210 dbus_message_iter_next(&sub);
2213 dbus_message_iter_recurse(&iter, &sub);
2215 /* Check for current sessions */
2216 sd_get_sessions(&sessions);
2217 STRV_FOREACH(s, sessions) {
2219 _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL;
2221 if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid())
2224 if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
2227 if (sd_session_get_type(*s, &type) < 0 || (!streq(type, "x11") && !streq(type, "tty")))
2230 sd_session_get_tty(*s, &tty);
2231 sd_session_get_seat(*s, &seat);
2232 sd_session_get_service(*s, &service);
2233 user = uid_to_name(uid);
2235 log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty);
2242 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
2243 action_table[a].verb);
2251 static int start_special(DBusConnection *bus, char **args) {
2257 a = verb_to_action(args[0]);
2259 r = check_inhibitors(bus, a);
2263 if (arg_force >= 2 && geteuid() != 0) {
2264 log_error("Must be root.");
2268 if (arg_force >= 2 &&
2269 (a == ACTION_HALT ||
2270 a == ACTION_POWEROFF ||
2271 a == ACTION_REBOOT))
2274 if (arg_force >= 1 &&
2275 (a == ACTION_HALT ||
2276 a == ACTION_POWEROFF ||
2277 a == ACTION_REBOOT ||
2278 a == ACTION_KEXEC ||
2280 return daemon_reload(bus, args);
2282 /* first try logind, to allow authentication with polkit */
2283 if (geteuid() != 0 &&
2284 (a == ACTION_POWEROFF ||
2285 a == ACTION_REBOOT ||
2286 a == ACTION_SUSPEND ||
2287 a == ACTION_HIBERNATE ||
2288 a == ACTION_HYBRID_SLEEP)) {
2289 r = reboot_with_logind(bus, a);
2294 r = start_unit(bus, args);
2295 if (r == EXIT_SUCCESS)
2301 static int check_unit_active(DBusConnection *bus, char **args) {
2302 const char * const check_states[] = {
2309 int r = 3; /* According to LSB: "program is not running" */
2314 STRV_FOREACH(name, args+1) {
2317 state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
2327 static int check_unit_failed(DBusConnection *bus, char **args) {
2328 const char * const check_states[] = {
2339 STRV_FOREACH(name, args+1) {
2342 state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
2352 static int kill_unit(DBusConnection *bus, char **args) {
2360 arg_kill_who = "all";
2362 STRV_FOREACH(name, args+1) {
2363 _cleanup_free_ char *n = NULL;
2365 n = unit_name_mangle(*name);
2369 r = bus_method_call_with_reply(
2371 "org.freedesktop.systemd1",
2372 "/org/freedesktop/systemd1",
2373 "org.freedesktop.systemd1.Manager",
2377 DBUS_TYPE_STRING, &n,
2378 DBUS_TYPE_STRING, &arg_kill_who,
2379 DBUS_TYPE_INT32, &arg_signal,
2387 typedef struct ExecStatusInfo {
2395 usec_t start_timestamp;
2396 usec_t exit_timestamp;
2401 LIST_FIELDS(struct ExecStatusInfo, exec);
2404 static void exec_status_info_free(ExecStatusInfo *i) {
2413 static int exec_status_info_deserialize(DBusMessageIter *sub, ExecStatusInfo *i) {
2414 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
2415 DBusMessageIter sub2, sub3;
2419 int32_t code, status;
2425 if (dbus_message_iter_get_arg_type(sub) != DBUS_TYPE_STRUCT)
2428 dbus_message_iter_recurse(sub, &sub2);
2430 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0)
2433 i->path = strdup(path);
2437 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_ARRAY ||
2438 dbus_message_iter_get_element_type(&sub2) != DBUS_TYPE_STRING)
2442 dbus_message_iter_recurse(&sub2, &sub3);
2443 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2444 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2445 dbus_message_iter_next(&sub3);
2449 i->argv = new0(char*, n+1);
2454 dbus_message_iter_recurse(&sub2, &sub3);
2455 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2458 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2459 dbus_message_iter_get_basic(&sub3, &s);
2460 dbus_message_iter_next(&sub3);
2462 i->argv[n] = strdup(s);
2469 if (!dbus_message_iter_next(&sub2) ||
2470 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, true) < 0 ||
2471 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp, true) < 0 ||
2472 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp_monotonic, true) < 0 ||
2473 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp, true) < 0 ||
2474 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp_monotonic, true) < 0 ||
2475 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, true) < 0 ||
2476 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &code, true) < 0 ||
2477 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &status, false) < 0)
2481 i->start_timestamp = (usec_t) start_timestamp;
2482 i->exit_timestamp = (usec_t) exit_timestamp;
2483 i->pid = (pid_t) pid;
2490 typedef struct UnitStatusInfo {
2492 const char *load_state;
2493 const char *active_state;
2494 const char *sub_state;
2495 const char *unit_file_state;
2497 const char *description;
2498 const char *following;
2500 char **documentation;
2502 const char *fragment_path;
2503 const char *source_path;
2504 const char *control_group;
2506 char **dropin_paths;
2508 const char *load_error;
2511 usec_t inactive_exit_timestamp;
2512 usec_t inactive_exit_timestamp_monotonic;
2513 usec_t active_enter_timestamp;
2514 usec_t active_exit_timestamp;
2515 usec_t inactive_enter_timestamp;
2517 bool need_daemon_reload;
2522 const char *status_text;
2523 const char *pid_file;
2526 usec_t start_timestamp;
2527 usec_t exit_timestamp;
2529 int exit_code, exit_status;
2531 usec_t condition_timestamp;
2532 bool condition_result;
2535 unsigned n_accepted;
2536 unsigned n_connections;
2539 /* Pairs of type, path */
2543 const char *sysfs_path;
2545 /* Mount, Automount */
2551 LIST_HEAD(ExecStatusInfo, exec);
2554 static void print_status_info(UnitStatusInfo *i) {
2556 const char *on, *off, *ss;
2558 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
2559 char since2[FORMAT_TIMESTAMP_MAX], *s2;
2562 arg_all * OUTPUT_SHOW_ALL |
2563 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
2564 on_tty() * OUTPUT_COLOR |
2565 !arg_quiet * OUTPUT_WARN_CUTOFF |
2566 arg_full * OUTPUT_FULL_WIDTH;
2571 /* This shows pretty information about a unit. See
2572 * print_property() for a low-level property printer */
2574 printf("%s", strna(i->id));
2576 if (i->description && !streq_ptr(i->id, i->description))
2577 printf(" - %s", i->description);
2582 printf(" Follow: unit currently follows state of %s\n", i->following);
2584 if (streq_ptr(i->load_state, "error")) {
2585 on = ansi_highlight_red(true);
2586 off = ansi_highlight_red(false);
2590 path = i->source_path ? i->source_path : i->fragment_path;
2593 printf(" Loaded: %s%s%s (Reason: %s)\n",
2594 on, strna(i->load_state), off, i->load_error);
2595 else if (path && i->unit_file_state)
2596 printf(" Loaded: %s%s%s (%s; %s)\n",
2597 on, strna(i->load_state), off, path, i->unit_file_state);
2599 printf(" Loaded: %s%s%s (%s)\n",
2600 on, strna(i->load_state), off, path);
2602 printf(" Loaded: %s%s%s\n",
2603 on, strna(i->load_state), off);
2605 if (!strv_isempty(i->dropin_paths)) {
2610 STRV_FOREACH(dropin, i->dropin_paths) {
2611 if (! dir || last) {
2612 printf(dir ? " " : " Drop-In: ");
2616 if (path_get_parent(*dropin, &dir) < 0) {
2621 printf("%s\n %s", dir,
2622 draw_special_char(DRAW_TREE_RIGHT));
2625 last = ! (*(dropin + 1) && startswith(*(dropin + 1), dir));
2627 printf("%s%s", path_get_file_name(*dropin), last ? "\n" : ", ");
2633 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
2635 if (streq_ptr(i->active_state, "failed")) {
2636 on = ansi_highlight_red(true);
2637 off = ansi_highlight_red(false);
2638 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
2639 on = ansi_highlight_green(true);
2640 off = ansi_highlight_green(false);
2645 printf(" Active: %s%s (%s)%s",
2646 on, strna(i->active_state), ss, off);
2648 printf(" Active: %s%s%s",
2649 on, strna(i->active_state), off);
2651 if (!isempty(i->result) && !streq(i->result, "success"))
2652 printf(" (Result: %s)", i->result);
2654 timestamp = (streq_ptr(i->active_state, "active") ||
2655 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
2656 (streq_ptr(i->active_state, "inactive") ||
2657 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
2658 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
2659 i->active_exit_timestamp;
2661 s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
2662 s2 = format_timestamp(since2, sizeof(since2), timestamp);
2665 printf(" since %s; %s\n", s2, s1);
2667 printf(" since %s\n", s2);
2671 if (!i->condition_result && i->condition_timestamp > 0) {
2672 s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
2673 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
2676 printf(" start condition failed at %s; %s\n", s2, s1);
2678 printf(" start condition failed at %s\n", s2);
2682 printf(" Device: %s\n", i->sysfs_path);
2684 printf(" Where: %s\n", i->where);
2686 printf(" What: %s\n", i->what);
2688 STRV_FOREACH(t, i->documentation)
2689 printf(" %*s %s\n", 9, t == i->documentation ? "Docs:" : "", *t);
2691 STRV_FOREACH_PAIR(t, t2, i->listen)
2692 printf(" %*s %s (%s)\n", 9, t == i->listen ? "Listen:" : "", *t2, *t);
2695 printf(" Accepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
2697 LIST_FOREACH(exec, p, i->exec) {
2698 _cleanup_free_ char *argv = NULL;
2701 /* Only show exited processes here */
2705 argv = strv_join(p->argv, " ");
2706 printf(" Process: %u %s=%s ", p->pid, p->name, strna(argv));
2708 good = is_clean_exit_lsb(p->code, p->status, NULL);
2710 on = ansi_highlight_red(true);
2711 off = ansi_highlight_red(false);
2715 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
2717 if (p->code == CLD_EXITED) {
2720 printf("status=%i", p->status);
2722 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
2727 printf("signal=%s", signal_to_string(p->status));
2729 printf(")%s\n", off);
2731 if (i->main_pid == p->pid &&
2732 i->start_timestamp == p->start_timestamp &&
2733 i->exit_timestamp == p->start_timestamp)
2734 /* Let's not show this twice */
2737 if (p->pid == i->control_pid)
2741 if (i->main_pid > 0 || i->control_pid > 0) {
2742 if (i->main_pid > 0) {
2743 printf(" Main PID: %u", (unsigned) i->main_pid);
2746 _cleanup_free_ char *comm = NULL;
2747 get_process_comm(i->main_pid, &comm);
2749 printf(" (%s)", comm);
2750 } else if (i->exit_code > 0) {
2751 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
2753 if (i->exit_code == CLD_EXITED) {
2756 printf("status=%i", i->exit_status);
2758 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
2763 printf("signal=%s", signal_to_string(i->exit_status));
2767 if (i->control_pid > 0)
2771 if (i->control_pid > 0) {
2772 _cleanup_free_ char *c = NULL;
2774 printf(" %8s: %u", i->main_pid ? "" : " Control", (unsigned) i->control_pid);
2776 get_process_comm(i->control_pid, &c);
2785 printf(" Status: \"%s\"\n", i->status_text);
2787 if (i->control_group &&
2788 (i->main_pid > 0 || i->control_pid > 0 || cg_is_empty(SYSTEMD_CGROUP_CONTROLLER, i->control_group, false) == 0)) {
2791 printf(" CGroup: %s\n", i->control_group);
2793 if (arg_transport != TRANSPORT_SSH) {
2796 char prefix[] = " ";
2799 if (c > sizeof(prefix) - 1)
2800 c -= sizeof(prefix) - 1;
2804 if (i->main_pid > 0)
2805 extra[k++] = i->main_pid;
2807 if (i->control_pid > 0)
2808 extra[k++] = i->control_pid;
2810 show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, i->control_group, prefix,
2811 c, false, extra, k, flags);
2815 if (i->id && arg_transport != TRANSPORT_SSH) {
2817 show_journal_by_unit(stdout,
2821 i->inactive_exit_timestamp_monotonic,
2825 arg_scope == UNIT_FILE_SYSTEM);
2828 if (i->need_daemon_reload)
2829 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %sdaemon-reload' recommended.\n",
2830 ansi_highlight_red(true),
2831 ansi_highlight_red(false),
2832 arg_scope == UNIT_FILE_SYSTEM ? "" : "--user ");
2835 static void show_unit_help(UnitStatusInfo *i) {
2840 if (!i->documentation) {
2841 log_info("Documentation for %s not known.", i->id);
2845 STRV_FOREACH(p, i->documentation) {
2847 if (startswith(*p, "man:")) {
2850 _cleanup_free_ char *page = NULL, *section = NULL;
2851 const char *args[4] = { "man", NULL, NULL, NULL };
2856 if ((*p)[k-1] == ')')
2857 e = strrchr(*p, '(');
2860 page = strndup((*p) + 4, e - *p - 4);
2861 section = strndup(e + 1, *p + k - e - 2);
2862 if (!page || !section) {
2874 log_error("Failed to fork: %m");
2880 execvp(args[0], (char**) args);
2881 log_error("Failed to execute man: %m");
2882 _exit(EXIT_FAILURE);
2885 wait_for_terminate(pid, NULL);
2887 log_info("Can't show: %s", *p);
2891 static int status_property(const char *name, DBusMessageIter *iter, UnitStatusInfo *i) {
2897 switch (dbus_message_iter_get_arg_type(iter)) {
2899 case DBUS_TYPE_STRING: {
2902 dbus_message_iter_get_basic(iter, &s);
2905 if (streq(name, "Id"))
2907 else if (streq(name, "LoadState"))
2909 else if (streq(name, "ActiveState"))
2910 i->active_state = s;
2911 else if (streq(name, "SubState"))
2913 else if (streq(name, "Description"))
2915 else if (streq(name, "FragmentPath"))
2916 i->fragment_path = s;
2917 else if (streq(name, "SourcePath"))
2920 else if (streq(name, "DefaultControlGroup")) {
2922 e = startswith(s, SYSTEMD_CGROUP_CONTROLLER ":");
2924 i->control_group = e;
2927 else if (streq(name, "ControlGroup"))
2928 i->control_group = s;
2929 else if (streq(name, "StatusText"))
2931 else if (streq(name, "PIDFile"))
2933 else if (streq(name, "SysFSPath"))
2935 else if (streq(name, "Where"))
2937 else if (streq(name, "What"))
2939 else if (streq(name, "Following"))
2941 else if (streq(name, "UnitFileState"))
2942 i->unit_file_state = s;
2943 else if (streq(name, "Result"))
2950 case DBUS_TYPE_BOOLEAN: {
2953 dbus_message_iter_get_basic(iter, &b);
2955 if (streq(name, "Accept"))
2957 else if (streq(name, "NeedDaemonReload"))
2958 i->need_daemon_reload = b;
2959 else if (streq(name, "ConditionResult"))
2960 i->condition_result = b;
2965 case DBUS_TYPE_UINT32: {
2968 dbus_message_iter_get_basic(iter, &u);
2970 if (streq(name, "MainPID")) {
2972 i->main_pid = (pid_t) u;
2975 } else if (streq(name, "ControlPID"))
2976 i->control_pid = (pid_t) u;
2977 else if (streq(name, "ExecMainPID")) {
2979 i->main_pid = (pid_t) u;
2980 } else if (streq(name, "NAccepted"))
2982 else if (streq(name, "NConnections"))
2983 i->n_connections = u;
2988 case DBUS_TYPE_INT32: {
2991 dbus_message_iter_get_basic(iter, &j);
2993 if (streq(name, "ExecMainCode"))
2994 i->exit_code = (int) j;
2995 else if (streq(name, "ExecMainStatus"))
2996 i->exit_status = (int) j;
3001 case DBUS_TYPE_UINT64: {
3004 dbus_message_iter_get_basic(iter, &u);
3006 if (streq(name, "ExecMainStartTimestamp"))
3007 i->start_timestamp = (usec_t) u;
3008 else if (streq(name, "ExecMainExitTimestamp"))
3009 i->exit_timestamp = (usec_t) u;
3010 else if (streq(name, "ActiveEnterTimestamp"))
3011 i->active_enter_timestamp = (usec_t) u;
3012 else if (streq(name, "InactiveEnterTimestamp"))
3013 i->inactive_enter_timestamp = (usec_t) u;
3014 else if (streq(name, "InactiveExitTimestamp"))
3015 i->inactive_exit_timestamp = (usec_t) u;
3016 else if (streq(name, "InactiveExitTimestampMonotonic"))
3017 i->inactive_exit_timestamp_monotonic = (usec_t) u;
3018 else if (streq(name, "ActiveExitTimestamp"))
3019 i->active_exit_timestamp = (usec_t) u;
3020 else if (streq(name, "ConditionTimestamp"))
3021 i->condition_timestamp = (usec_t) u;
3026 case DBUS_TYPE_ARRAY: {
3028 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
3029 startswith(name, "Exec")) {
3030 DBusMessageIter sub;
3032 dbus_message_iter_recurse(iter, &sub);
3033 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3034 ExecStatusInfo *info;
3037 if (!(info = new0(ExecStatusInfo, 1)))
3040 if (!(info->name = strdup(name))) {
3045 if ((r = exec_status_info_deserialize(&sub, info)) < 0) {
3050 LIST_PREPEND(ExecStatusInfo, exec, i->exec, info);
3052 dbus_message_iter_next(&sub);
3055 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Listen")) {
3056 DBusMessageIter sub, sub2;
3058 dbus_message_iter_recurse(iter, &sub);
3059 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3060 const char *type, *path;
3062 dbus_message_iter_recurse(&sub, &sub2);
3064 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
3065 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0) {
3068 r = strv_extend(&i->listen, type);
3071 r = strv_extend(&i->listen, path);
3076 dbus_message_iter_next(&sub);
3081 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING && streq(name, "DropInPaths")) {
3082 int r = bus_parse_strv_iter(iter, &i->dropin_paths);
3086 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
3087 streq(name, "Documentation")) {
3089 DBusMessageIter sub;
3091 dbus_message_iter_recurse(iter, &sub);
3092 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING) {
3096 dbus_message_iter_get_basic(&sub, &s);
3098 r = strv_extend(&i->documentation, s);
3102 dbus_message_iter_next(&sub);
3109 case DBUS_TYPE_STRUCT: {
3111 if (streq(name, "LoadError")) {
3112 DBusMessageIter sub;
3113 const char *n, *message;
3116 dbus_message_iter_recurse(iter, &sub);
3118 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &n, true);
3122 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &message, false);
3126 if (!isempty(message))
3127 i->load_error = message;
3137 static int print_property(const char *name, DBusMessageIter *iter) {
3141 /* This is a low-level property printer, see
3142 * print_status_info() for the nicer output */
3144 if (arg_properties && !strv_find(arg_properties, name))
3147 switch (dbus_message_iter_get_arg_type(iter)) {
3149 case DBUS_TYPE_STRUCT: {
3150 DBusMessageIter sub;
3151 dbus_message_iter_recurse(iter, &sub);
3153 if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32 && streq(name, "Job")) {
3156 dbus_message_iter_get_basic(&sub, &u);
3159 printf("%s=%u\n", name, (unsigned) u);
3161 printf("%s=\n", name);
3164 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "Unit")) {
3167 dbus_message_iter_get_basic(&sub, &s);
3169 if (arg_all || s[0])
3170 printf("%s=%s\n", name, s);
3173 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "LoadError")) {
3174 const char *a = NULL, *b = NULL;
3176 if (bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &a, true) >= 0)
3177 bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &b, false);
3179 if (arg_all || !isempty(a) || !isempty(b))
3180 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
3188 case DBUS_TYPE_ARRAY:
3190 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "EnvironmentFiles")) {
3191 DBusMessageIter sub, sub2;
3193 dbus_message_iter_recurse(iter, &sub);
3194 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3198 dbus_message_iter_recurse(&sub, &sub2);
3200 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
3201 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) >= 0)
3202 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
3204 dbus_message_iter_next(&sub);
3209 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Paths")) {
3210 DBusMessageIter sub, sub2;
3212 dbus_message_iter_recurse(iter, &sub);
3214 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3215 const char *type, *path;
3217 dbus_message_iter_recurse(&sub, &sub2);
3219 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
3220 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
3221 printf("%s=%s\n", type, path);
3223 dbus_message_iter_next(&sub);
3228 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Listen")) {
3229 DBusMessageIter sub, sub2;
3231 dbus_message_iter_recurse(iter, &sub);
3232 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3233 const char *type, *path;
3235 dbus_message_iter_recurse(&sub, &sub2);
3237 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
3238 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
3239 printf("Listen%s=%s\n", type, path);
3241 dbus_message_iter_next(&sub);
3246 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Timers")) {
3247 DBusMessageIter sub, sub2;
3249 dbus_message_iter_recurse(iter, &sub);
3250 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3252 uint64_t value, next_elapse;
3254 dbus_message_iter_recurse(&sub, &sub2);
3256 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &base, true) >= 0 &&
3257 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &value, true) >= 0 &&
3258 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &next_elapse, false) >= 0) {
3259 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
3261 printf("%s={ value=%s ; next_elapse=%s }\n",
3263 format_timespan(timespan1, sizeof(timespan1), value, 0),
3264 format_timespan(timespan2, sizeof(timespan2), next_elapse, 0));
3267 dbus_message_iter_next(&sub);
3272 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && startswith(name, "Exec")) {
3273 DBusMessageIter sub;
3275 dbus_message_iter_recurse(iter, &sub);
3276 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3277 ExecStatusInfo info = {};
3279 if (exec_status_info_deserialize(&sub, &info) >= 0) {
3280 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
3281 _cleanup_free_ char *t;
3283 t = strv_join(info.argv, " ");
3285 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
3289 yes_no(info.ignore),
3290 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
3291 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
3292 (unsigned) info. pid,
3293 sigchld_code_to_string(info.code),
3295 info.code == CLD_EXITED ? "" : "/",
3296 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
3300 strv_free(info.argv);
3302 dbus_message_iter_next(&sub);
3307 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "DeviceAllow")) {
3308 DBusMessageIter sub, sub2;
3310 dbus_message_iter_recurse(iter, &sub);
3311 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3312 const char *path, *rwm;
3314 dbus_message_iter_recurse(&sub, &sub2);
3316 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
3317 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &rwm, false) >= 0)
3318 printf("%s=%s %s\n", name, strna(path), strna(rwm));
3320 dbus_message_iter_next(&sub);
3324 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && (streq(name, "BlockIOReadBandwidth") || streq(name, "BlockIOWriteBandwidth"))) {
3325 DBusMessageIter sub, sub2;
3327 dbus_message_iter_recurse(iter, &sub);
3328 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3332 dbus_message_iter_recurse(&sub, &sub2);
3334 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
3335 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &bandwidth, false) >= 0)
3336 printf("%s=%s %" PRIu64 "\n", name, strna(path), bandwidth);
3338 dbus_message_iter_next(&sub);
3347 if (generic_print_property(name, iter, arg_all) > 0)
3351 printf("%s=[unprintable]\n", name);
3356 static int show_one(const char *verb, DBusConnection *bus, const char *path, bool show_properties, bool *new_line) {
3357 _cleanup_free_ DBusMessage *reply = NULL;
3358 const char *interface = "";
3360 DBusMessageIter iter, sub, sub2, sub3;
3361 UnitStatusInfo info = {};
3367 r = bus_method_call_with_reply(
3369 "org.freedesktop.systemd1",
3371 "org.freedesktop.DBus.Properties",
3375 DBUS_TYPE_STRING, &interface,
3380 if (!dbus_message_iter_init(reply, &iter) ||
3381 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3382 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
3383 log_error("Failed to parse reply.");
3387 dbus_message_iter_recurse(&iter, &sub);
3394 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
3397 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_DICT_ENTRY);
3398 dbus_message_iter_recurse(&sub, &sub2);
3400 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
3401 dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
3402 log_error("Failed to parse reply.");
3406 dbus_message_iter_recurse(&sub2, &sub3);
3408 if (show_properties)
3409 r = print_property(name, &sub3);
3411 r = status_property(name, &sub3, &info);
3413 log_error("Failed to parse reply.");
3417 dbus_message_iter_next(&sub);
3422 if (!show_properties) {
3423 if (streq(verb, "help"))
3424 show_unit_help(&info);
3426 print_status_info(&info);
3429 strv_free(info.documentation);
3430 strv_free(info.dropin_paths);
3431 strv_free(info.listen);
3433 if (!streq_ptr(info.active_state, "active") &&
3434 !streq_ptr(info.active_state, "reloading") &&
3435 streq(verb, "status")) {
3436 /* According to LSB: "program not running" */
3437 /* 0: program is running or service is OK
3438 * 1: program is dead and /var/run pid file exists
3439 * 2: program is dead and /var/lock lock file exists
3440 * 3: program is not running
3441 * 4: program or service status is unknown
3443 if (info.pid_file && access(info.pid_file, F_OK) == 0)
3449 while ((p = info.exec)) {
3450 LIST_REMOVE(ExecStatusInfo, exec, info.exec, p);
3451 exec_status_info_free(p);
3457 static int show_one_by_pid(const char *verb, DBusConnection *bus, uint32_t pid, bool *new_line) {
3458 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3459 const char *path = NULL;
3460 _cleanup_dbus_error_free_ DBusError error;
3463 dbus_error_init(&error);
3465 r = bus_method_call_with_reply(
3467 "org.freedesktop.systemd1",
3468 "/org/freedesktop/systemd1",
3469 "org.freedesktop.systemd1.Manager",
3473 DBUS_TYPE_UINT32, &pid,
3478 if (!dbus_message_get_args(reply, &error,
3479 DBUS_TYPE_OBJECT_PATH, &path,
3480 DBUS_TYPE_INVALID)) {
3481 log_error("Failed to parse reply: %s", bus_error_message(&error));
3485 r = show_one(verb, bus, path, false, new_line);
3489 static int show_all(const char* verb, DBusConnection *bus, bool show_properties, bool *new_line) {
3490 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3491 _cleanup_free_ struct unit_info *unit_infos = NULL;
3493 const struct unit_info *u;
3496 r = get_unit_list(bus, &reply, &unit_infos, &c);
3500 qsort(unit_infos, c, sizeof(struct unit_info), compare_unit_info);
3502 for (u = unit_infos; u < unit_infos + c; u++) {
3503 _cleanup_free_ char *p = NULL;
3505 if (!output_show_unit(u))
3508 p = unit_dbus_path_from_name(u->id);
3512 printf("%s -> '%s'\n", u->id, p);
3514 r = show_one(verb, bus, p, show_properties, new_line);
3522 static int show(DBusConnection *bus, char **args) {
3524 bool show_properties, show_status, new_line = false;
3530 show_properties = streq(args[0], "show");
3531 show_status = streq(args[0], "status");
3533 if (show_properties)
3534 pager_open_if_enabled();
3536 /* If no argument is specified inspect the manager itself */
3538 if (show_properties && strv_length(args) <= 1)
3539 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line);
3541 if (show_status && strv_length(args) <= 1)
3542 return show_all(args[0], bus, false, &new_line);
3544 STRV_FOREACH(name, args+1) {
3547 if (safe_atou32(*name, &id) < 0) {
3548 _cleanup_free_ char *p = NULL, *n = NULL;
3549 /* Interpret as unit name */
3551 n = unit_name_mangle(*name);
3555 p = unit_dbus_path_from_name(n);
3559 r = show_one(args[0], bus, p, show_properties, &new_line);
3563 } else if (show_properties) {
3564 _cleanup_free_ char *p = NULL;
3566 /* Interpret as job id */
3567 if (asprintf(&p, "/org/freedesktop/systemd1/job/%u", id) < 0)
3570 r = show_one(args[0], bus, p, show_properties, &new_line);
3575 /* Interpret as PID */
3576 r = show_one_by_pid(args[0], bus, id, &new_line);
3585 static int append_assignment(DBusMessageIter *iter, const char *assignment) {
3588 DBusMessageIter sub;
3594 eq = strchr(assignment, '=');
3596 log_error("Not an assignment: %s", assignment);
3600 field = strndupa(assignment, eq - assignment);
3603 if (!dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &field))
3606 if (streq(field, "CPUAccounting") ||
3607 streq(field, "MemoryAccounting") ||
3608 streq(field, "BlockIOAccounting")) {
3611 r = parse_boolean(eq);
3613 log_error("Failed to parse boolean assignment %s.", assignment);
3618 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "b", &sub) ||
3619 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_BOOLEAN, &b))
3622 } else if (streq(field, "MemoryLimit") || streq(field, "MemorySoftLimit")) {
3626 r = parse_bytes(eq, &bytes);
3628 log_error("Failed to parse bytes specification %s", assignment);
3633 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "t", &sub) ||
3634 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_UINT64, &u))
3637 } else if (streq(field, "CPUShares") || streq(field, "BlockIOWeight")) {
3640 r = safe_atou64(eq, &u);
3642 log_error("Failed to parse %s value %s.", field, eq);
3646 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "t", &sub) ||
3647 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_UINT64, &u))
3650 } else if (streq(field, "DevicePolicy")) {
3652 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "s", &sub) ||
3653 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &eq))
3656 } else if (streq(field, "DeviceAllow")) {
3657 DBusMessageIter sub2;
3659 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "a(ss)", &sub) ||
3660 !dbus_message_iter_open_container(&sub, DBUS_TYPE_ARRAY, "(ss)", &sub2))
3664 const char *path, *rwm;
3665 DBusMessageIter sub3;
3668 e = strchr(eq, ' ');
3670 path = strndupa(eq, e - eq);
3677 if (!dbus_message_iter_open_container(&sub2, DBUS_TYPE_STRUCT, NULL, &sub3) ||
3678 !dbus_message_iter_append_basic(&sub3, DBUS_TYPE_STRING, &path) ||
3679 !dbus_message_iter_append_basic(&sub3, DBUS_TYPE_STRING, &rwm) ||
3680 !dbus_message_iter_close_container(&sub2, &sub3))
3684 if (!dbus_message_iter_close_container(&sub, &sub2))
3688 log_error("Unknown assignment %s.", assignment);
3692 if (!dbus_message_iter_close_container(iter, &sub))
3698 static int set_property(DBusConnection *bus, char **args) {
3700 _cleanup_free_ DBusMessage *m = NULL, *reply = NULL;
3701 DBusMessageIter iter, sub;
3702 dbus_bool_t runtime;
3707 dbus_error_init(&error);
3709 m = dbus_message_new_method_call(
3710 "org.freedesktop.systemd1",
3711 "/org/freedesktop/systemd1",
3712 "org.freedesktop.systemd1.Manager",
3713 "SetUnitProperties");
3717 dbus_message_iter_init_append(m, &iter);
3719 runtime = arg_runtime;
3721 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &args[1]) ||
3722 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &runtime) ||
3723 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(sv)", &sub))
3726 STRV_FOREACH(i, args + 2) {
3727 DBusMessageIter sub2;
3729 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
3732 r = append_assignment(&sub2, *i);
3736 if (!dbus_message_iter_close_container(&sub, &sub2))
3741 if (!dbus_message_iter_close_container(&iter, &sub))
3744 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3746 log_error("Failed to issue method call: %s", bus_error_message(&error));
3747 dbus_error_free(&error);
3754 static int dump(DBusConnection *bus, char **args) {
3755 _cleanup_free_ DBusMessage *reply = NULL;
3760 dbus_error_init(&error);
3762 pager_open_if_enabled();
3764 r = bus_method_call_with_reply(
3766 "org.freedesktop.systemd1",
3767 "/org/freedesktop/systemd1",
3768 "org.freedesktop.systemd1.Manager",
3776 if (!dbus_message_get_args(reply, &error,
3777 DBUS_TYPE_STRING, &text,
3778 DBUS_TYPE_INVALID)) {
3779 log_error("Failed to parse reply: %s", bus_error_message(&error));
3780 dbus_error_free(&error);
3784 fputs(text, stdout);
3788 static int snapshot(DBusConnection *bus, char **args) {
3789 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3792 dbus_bool_t cleanup = FALSE;
3793 DBusMessageIter iter, sub;
3796 *interface = "org.freedesktop.systemd1.Unit",
3798 _cleanup_free_ char *n = NULL;
3800 dbus_error_init(&error);
3802 if (strv_length(args) > 1)
3803 n = unit_name_mangle_with_suffix(args[1], ".snapshot");
3809 r = bus_method_call_with_reply(
3811 "org.freedesktop.systemd1",
3812 "/org/freedesktop/systemd1",
3813 "org.freedesktop.systemd1.Manager",
3817 DBUS_TYPE_STRING, &n,
3818 DBUS_TYPE_BOOLEAN, &cleanup,
3823 if (!dbus_message_get_args(reply, &error,
3824 DBUS_TYPE_OBJECT_PATH, &path,
3825 DBUS_TYPE_INVALID)) {
3826 log_error("Failed to parse reply: %s", bus_error_message(&error));
3827 dbus_error_free(&error);
3831 dbus_message_unref(reply);
3834 r = bus_method_call_with_reply (
3836 "org.freedesktop.systemd1",
3838 "org.freedesktop.DBus.Properties",
3842 DBUS_TYPE_STRING, &interface,
3843 DBUS_TYPE_STRING, &property,
3848 if (!dbus_message_iter_init(reply, &iter) ||
3849 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3850 log_error("Failed to parse reply.");
3854 dbus_message_iter_recurse(&iter, &sub);
3856 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
3857 log_error("Failed to parse reply.");
3861 dbus_message_iter_get_basic(&sub, &id);
3869 static int delete_snapshot(DBusConnection *bus, char **args) {
3874 STRV_FOREACH(name, args+1) {
3875 _cleanup_free_ char *n = NULL;
3878 n = unit_name_mangle_with_suffix(*name, ".snapshot");
3882 r = bus_method_call_with_reply(
3884 "org.freedesktop.systemd1",
3885 "/org/freedesktop/systemd1",
3886 "org.freedesktop.systemd1.Manager",
3890 DBUS_TYPE_STRING, &n,
3899 static int daemon_reload(DBusConnection *bus, char **args) {
3904 if (arg_action == ACTION_RELOAD)
3906 else if (arg_action == ACTION_REEXEC)
3907 method = "Reexecute";
3909 assert(arg_action == ACTION_SYSTEMCTL);
3912 streq(args[0], "clear-jobs") ||
3913 streq(args[0], "cancel") ? "ClearJobs" :
3914 streq(args[0], "daemon-reexec") ? "Reexecute" :
3915 streq(args[0], "reset-failed") ? "ResetFailed" :
3916 streq(args[0], "halt") ? "Halt" :
3917 streq(args[0], "poweroff") ? "PowerOff" :
3918 streq(args[0], "reboot") ? "Reboot" :
3919 streq(args[0], "kexec") ? "KExec" :
3920 streq(args[0], "exit") ? "Exit" :
3921 /* "daemon-reload" */ "Reload";
3924 r = bus_method_call_with_reply(
3926 "org.freedesktop.systemd1",
3927 "/org/freedesktop/systemd1",
3928 "org.freedesktop.systemd1.Manager",
3934 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
3935 /* There's always a fallback possible for
3936 * legacy actions. */
3938 else if (r == -ETIMEDOUT && streq(method, "Reexecute"))
3939 /* On reexecution, we expect a disconnect, not
3943 log_error("Failed to issue method call: %s", bus_error_message(&error));
3945 dbus_error_free(&error);
3949 static int reset_failed(DBusConnection *bus, char **args) {
3953 if (strv_length(args) <= 1)
3954 return daemon_reload(bus, args);
3956 STRV_FOREACH(name, args+1) {
3957 _cleanup_free_ char *n;
3959 n = unit_name_mangle(*name);
3963 r = bus_method_call_with_reply(
3965 "org.freedesktop.systemd1",
3966 "/org/freedesktop/systemd1",
3967 "org.freedesktop.systemd1.Manager",
3971 DBUS_TYPE_STRING, &n,
3980 static int show_enviroment(DBusConnection *bus, char **args) {
3981 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3982 DBusMessageIter iter, sub, sub2;
3985 *interface = "org.freedesktop.systemd1.Manager",
3986 *property = "Environment";
3988 pager_open_if_enabled();
3990 r = bus_method_call_with_reply(
3992 "org.freedesktop.systemd1",
3993 "/org/freedesktop/systemd1",
3994 "org.freedesktop.DBus.Properties",
3998 DBUS_TYPE_STRING, &interface,
3999 DBUS_TYPE_STRING, &property,
4004 if (!dbus_message_iter_init(reply, &iter) ||
4005 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
4006 log_error("Failed to parse reply.");
4010 dbus_message_iter_recurse(&iter, &sub);
4012 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_ARRAY ||
4013 dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_STRING) {
4014 log_error("Failed to parse reply.");
4018 dbus_message_iter_recurse(&sub, &sub2);
4020 while (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_INVALID) {
4023 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
4024 log_error("Failed to parse reply.");
4028 dbus_message_iter_get_basic(&sub2, &text);
4031 dbus_message_iter_next(&sub2);
4037 static int switch_root(DBusConnection *bus, char **args) {
4040 _cleanup_free_ char *init = NULL;
4042 l = strv_length(args);
4043 if (l < 2 || l > 3) {
4044 log_error("Wrong number of arguments.");
4051 init = strdup(args[2]);
4053 parse_env_file("/proc/cmdline", WHITESPACE,
4063 log_debug("switching root - root: %s; init: %s", root, init);
4065 return bus_method_call_with_reply(
4067 "org.freedesktop.systemd1",
4068 "/org/freedesktop/systemd1",
4069 "org.freedesktop.systemd1.Manager",
4073 DBUS_TYPE_STRING, &root,
4074 DBUS_TYPE_STRING, &init,
4078 static int set_environment(DBusConnection *bus, char **args) {
4079 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
4082 DBusMessageIter iter;
4088 dbus_error_init(&error);
4090 method = streq(args[0], "set-environment")
4092 : "UnsetEnvironment";
4094 m = dbus_message_new_method_call(
4095 "org.freedesktop.systemd1",
4096 "/org/freedesktop/systemd1",
4097 "org.freedesktop.systemd1.Manager",
4102 dbus_message_iter_init_append(m, &iter);
4104 r = bus_append_strv_iter(&iter, args + 1);
4108 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
4110 log_error("Failed to issue method call: %s", bus_error_message(&error));
4111 dbus_error_free(&error);
4118 static int enable_sysv_units(char **args) {
4121 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
4122 const char *verb = args[0];
4123 unsigned f = 1, t = 1;
4124 LookupPaths paths = {};
4126 if (arg_scope != UNIT_FILE_SYSTEM)
4129 if (!streq(verb, "enable") &&
4130 !streq(verb, "disable") &&
4131 !streq(verb, "is-enabled"))
4134 /* Processes all SysV units, and reshuffles the array so that
4135 * afterwards only the native units remain */
4137 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, NULL, NULL, NULL);
4142 for (f = 1; args[f]; f++) {
4144 _cleanup_free_ char *p = NULL, *q = NULL;
4145 bool found_native = false, found_sysv;
4147 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
4155 if (!endswith(name, ".service"))
4158 if (path_is_absolute(name))
4161 STRV_FOREACH(k, paths.unit_path) {
4162 if (!isempty(arg_root))
4163 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
4165 asprintf(&p, "%s/%s", *k, name);
4172 found_native = access(p, F_OK) >= 0;
4183 if (!isempty(arg_root))
4184 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
4186 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
4192 p[strlen(p) - sizeof(".service") + 1] = 0;
4193 found_sysv = access(p, F_OK) >= 0;
4198 /* Mark this entry, so that we don't try enabling it as native unit */
4199 args[f] = (char*) "";
4201 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
4203 if (!isempty(arg_root))
4204 argv[c++] = q = strappend("--root=", arg_root);
4206 argv[c++] = path_get_file_name(p);
4208 streq(verb, "enable") ? "on" :
4209 streq(verb, "disable") ? "off" : "--level=5";
4212 l = strv_join((char**)argv, " ");
4218 log_info("Executing %s", l);
4223 log_error("Failed to fork: %m");
4226 } else if (pid == 0) {
4229 execv(argv[0], (char**) argv);
4230 _exit(EXIT_FAILURE);
4233 j = wait_for_terminate(pid, &status);
4235 log_error("Failed to wait for child: %s", strerror(-r));
4240 if (status.si_code == CLD_EXITED) {
4241 if (streq(verb, "is-enabled")) {
4242 if (status.si_status == 0) {
4251 } else if (status.si_status != 0) {
4262 lookup_paths_free(&paths);
4264 /* Drop all SysV units */
4265 for (f = 1, t = 1; args[f]; f++) {
4267 if (isempty(args[f]))
4270 args[t++] = args[f];
4279 static int mangle_names(char **original_names, char ***mangled_names) {
4280 char **i, **l, **name;
4282 l = new(char*, strv_length(original_names) + 1);
4287 STRV_FOREACH(name, original_names) {
4289 /* When enabling units qualified path names are OK,
4290 * too, hence allow them explicitly. */
4295 *i = unit_name_mangle(*name);
4311 static int enable_unit(DBusConnection *bus, char **args) {
4312 const char *verb = args[0];
4313 UnitFileChange *changes = NULL;
4314 unsigned n_changes = 0, i;
4315 int carries_install_info = -1;
4316 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
4318 _cleanup_dbus_error_free_ DBusError error;
4319 _cleanup_strv_free_ char **mangled_names = NULL;
4321 dbus_error_init(&error);
4323 r = enable_sysv_units(args);
4330 r = mangle_names(args+1, &mangled_names);
4334 if (!bus || avoid_bus()) {
4335 if (streq(verb, "enable")) {
4336 r = unit_file_enable(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4337 carries_install_info = r;
4338 } else if (streq(verb, "disable"))
4339 r = unit_file_disable(arg_scope, arg_runtime, arg_root, mangled_names, &changes, &n_changes);
4340 else if (streq(verb, "reenable")) {
4341 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4342 carries_install_info = r;
4343 } else if (streq(verb, "link"))
4344 r = unit_file_link(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4345 else if (streq(verb, "preset")) {
4346 r = unit_file_preset(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4347 carries_install_info = r;
4348 } else if (streq(verb, "mask"))
4349 r = unit_file_mask(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4350 else if (streq(verb, "unmask"))
4351 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, mangled_names, &changes, &n_changes);
4352 else if (streq(verb, "set-default"))
4353 r = unit_file_set_default(arg_scope, arg_root, args[1], &changes, &n_changes);
4355 assert_not_reached("Unknown verb");
4358 log_error("Operation failed: %s", strerror(-r));
4363 for (i = 0; i < n_changes; i++) {
4364 if (changes[i].type == UNIT_FILE_SYMLINK)
4365 log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
4367 log_info("rm '%s'", changes[i].path);
4374 bool send_force = true, expect_carries_install_info = false;
4376 DBusMessageIter iter, sub, sub2;
4378 if (streq(verb, "enable")) {
4379 method = "EnableUnitFiles";
4380 expect_carries_install_info = true;
4381 } else if (streq(verb, "disable")) {
4382 method = "DisableUnitFiles";
4384 } else if (streq(verb, "reenable")) {
4385 method = "ReenableUnitFiles";
4386 expect_carries_install_info = true;
4387 } else if (streq(verb, "link"))
4388 method = "LinkUnitFiles";
4389 else if (streq(verb, "preset")) {
4390 method = "PresetUnitFiles";
4391 expect_carries_install_info = true;
4392 } else if (streq(verb, "mask"))
4393 method = "MaskUnitFiles";
4394 else if (streq(verb, "unmask")) {
4395 method = "UnmaskUnitFiles";
4397 } else if (streq(verb, "set-default")) {
4398 method = "SetDefaultTarget";
4400 assert_not_reached("Unknown verb");
4402 m = dbus_message_new_method_call(
4403 "org.freedesktop.systemd1",
4404 "/org/freedesktop/systemd1",
4405 "org.freedesktop.systemd1.Manager",
4412 dbus_message_iter_init_append(m, &iter);
4414 r = bus_append_strv_iter(&iter, mangled_names);
4416 log_error("Failed to append unit files.");
4421 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &a)) {
4422 log_error("Failed to append runtime boolean.");
4430 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b)) {
4431 log_error("Failed to append force boolean.");
4437 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
4439 log_error("Failed to issue method call: %s", bus_error_message(&error));
4444 if (!dbus_message_iter_init(reply, &iter)) {
4445 log_error("Failed to initialize iterator.");
4449 if (expect_carries_install_info) {
4450 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &b, true);
4452 log_error("Failed to parse reply.");
4456 carries_install_info = b;
4459 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
4460 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
4461 log_error("Failed to parse reply.");
4466 dbus_message_iter_recurse(&iter, &sub);
4467 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
4468 const char *type, *path, *source;
4470 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
4471 log_error("Failed to parse reply.");
4476 dbus_message_iter_recurse(&sub, &sub2);
4478 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
4479 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
4480 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &source, false) < 0) {
4481 log_error("Failed to parse reply.");
4487 if (streq(type, "symlink"))
4488 log_info("ln -s '%s' '%s'", source, path);
4490 log_info("rm '%s'", path);
4493 dbus_message_iter_next(&sub);
4496 /* Try to reload if enabeld */
4498 r = daemon_reload(bus, args);
4501 if (carries_install_info == 0)
4502 log_warning("The unit files have no [Install] section. They are not meant to be enabled\n"
4503 "using systemctl.\n"
4504 "Possible reasons for having this kind of units are:\n"
4505 "1) A unit may be statically enabled by being symlinked from another unit's\n"
4506 " .wants/ or .requires/ directory.\n"
4507 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
4508 " a requirement dependency on it.\n"
4509 "3) A unit may be started when needed via activation (socket, path, timer,\n"
4510 " D-Bus, udev, scripted systemctl call, ...).\n");
4513 unit_file_changes_free(changes, n_changes);
4518 static int set_log_level(DBusConnection *bus, char **args) {
4519 _cleanup_dbus_error_free_ DBusError error;
4520 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
4521 DBusMessageIter iter, sub;
4522 const char* property = "LogLevel";
4523 const char* interface = "org.freedesktop.systemd1.Manager";
4530 dbus_error_init(&error);
4532 m = dbus_message_new_method_call("org.freedesktop.systemd1",
4533 "/org/freedesktop/systemd1",
4534 "org.freedesktop.DBus.Properties",
4539 dbus_message_iter_init_append(m, &iter);
4541 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &interface) ||
4542 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &property) ||
4543 !dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT, "s", &sub))
4546 if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &value)) {
4547 dbus_message_iter_abandon_container(&iter, &sub);
4551 if (!dbus_message_iter_close_container(&iter, &sub))
4554 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
4556 log_error("Failed to issue method call: %s", bus_error_message(&error));
4563 static int unit_is_enabled(DBusConnection *bus, char **args) {
4564 _cleanup_dbus_error_free_ DBusError error;
4566 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
4571 dbus_error_init(&error);
4573 r = enable_sysv_units(args);
4579 if (!bus || avoid_bus()) {
4581 STRV_FOREACH(name, args+1) {
4582 UnitFileState state;
4584 n = unit_name_mangle(*name);
4588 state = unit_file_get_state(arg_scope, arg_root, n);
4595 if (state == UNIT_FILE_ENABLED ||
4596 state == UNIT_FILE_ENABLED_RUNTIME ||
4597 state == UNIT_FILE_STATIC)
4601 puts(unit_file_state_to_string(state));
4605 STRV_FOREACH(name, args+1) {
4608 n = unit_name_mangle(*name);
4612 r = bus_method_call_with_reply (
4614 "org.freedesktop.systemd1",
4615 "/org/freedesktop/systemd1",
4616 "org.freedesktop.systemd1.Manager",
4620 DBUS_TYPE_STRING, &n,
4628 if (!dbus_message_get_args(reply, &error,
4629 DBUS_TYPE_STRING, &s,
4630 DBUS_TYPE_INVALID)) {
4631 log_error("Failed to parse reply: %s", bus_error_message(&error));
4635 dbus_message_unref(reply);
4638 if (streq(s, "enabled") ||
4639 streq(s, "enabled-runtime") ||
4648 return enabled ? 0 : 1;
4651 static int systemctl_help(void) {
4653 pager_open_if_enabled();
4655 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
4656 "Query or send control commands to the systemd manager.\n\n"
4657 " -h --help Show this help\n"
4658 " --version Show package version\n"
4659 " -t --type=TYPE List only units of a particular type\n"
4660 " -p --property=NAME Show only properties by this name\n"
4661 " -a --all Show all loaded units/properties, including dead/empty\n"
4662 " ones. To list all units installed on the system, use\n"
4663 " the 'list-unit-files' command instead.\n"
4664 " --reverse Show reverse dependencies with 'list-dependencies'\n"
4665 " --failed Show only failed units\n"
4666 " -l --full Don't ellipsize unit names on output\n"
4667 " --fail When queueing a new job, fail if conflicting jobs are\n"
4669 " --irreversible Create jobs which cannot be implicitly cancelled\n"
4670 " --show-types When showing sockets, explicitly show their type\n"
4671 " --ignore-dependencies\n"
4672 " When queueing a new job, ignore all its dependencies\n"
4673 " -i --ignore-inhibitors\n"
4674 " When shutting down or sleeping, ignore inhibitors\n"
4675 " --kill-who=WHO Who to send signal to\n"
4676 " -s --signal=SIGNAL Which signal to send\n"
4677 " -H --host=[USER@]HOST\n"
4678 " Show information for remote host\n"
4679 " -P --privileged Acquire privileges before execution\n"
4680 " -q --quiet Suppress output\n"
4681 " --no-block Do not wait until operation finished\n"
4682 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4683 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
4685 " --no-legend Do not print a legend (column headers and hints)\n"
4686 " --no-pager Do not pipe output into a pager\n"
4687 " --no-ask-password\n"
4688 " Do not ask for system passwords\n"
4689 " --system Connect to system manager\n"
4690 " --user Connect to user service manager\n"
4691 " --global Enable/disable unit files globally\n"
4692 " -f --force When enabling unit files, override existing symlinks\n"
4693 " When shutting down, execute action immediately\n"
4694 " --root=PATH Enable unit files in the specified root directory\n"
4695 " --runtime Enable unit files only temporarily until next reboot\n"
4696 " -n --lines=INTEGER Journal entries to show\n"
4697 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
4698 " verbose, export, json, json-pretty, json-sse, cat)\n\n"
4700 " list-units List loaded units\n"
4701 " list-sockets List loaded sockets ordered by address\n"
4702 " start [NAME...] Start (activate) one or more units\n"
4703 " stop [NAME...] Stop (deactivate) one or more units\n"
4704 " reload [NAME...] Reload one or more units\n"
4705 " restart [NAME...] Start or restart one or more units\n"
4706 " try-restart [NAME...] Restart one or more units if active\n"
4707 " reload-or-restart [NAME...] Reload one or more units if possible,\n"
4708 " otherwise start or restart\n"
4709 " reload-or-try-restart [NAME...] Reload one or more units if possible,\n"
4710 " otherwise restart if active\n"
4711 " isolate [NAME] Start one unit and stop all others\n"
4712 " kill [NAME...] Send signal to processes of a unit\n"
4713 " is-active [NAME...] Check whether units are active\n"
4714 " is-failed [NAME...] Check whether units are failed\n"
4715 " status [NAME...|PID...] Show runtime status of one or more units\n"
4716 " show [NAME...|JOB...] Show properties of one or more\n"
4717 " units/jobs or the manager\n"
4718 " set-property [NAME] [ASSIGNMENT...]\n"
4719 " Sets one or more properties of a unit\n"
4720 " help [NAME...|PID...] Show manual for one or more units\n"
4721 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
4723 " load [NAME...] Load one or more units\n"
4724 " list-dependencies [NAME] Recursively show units which are required\n"
4725 " or wanted by this unit or by which this\n"
4726 " unit is required or wanted\n\n"
4727 "Unit File Commands:\n"
4728 " list-unit-files List installed unit files\n"
4729 " enable [NAME...] Enable one or more unit files\n"
4730 " disable [NAME...] Disable one or more unit files\n"
4731 " reenable [NAME...] Reenable one or more unit files\n"
4732 " preset [NAME...] Enable/disable one or more unit files\n"
4733 " based on preset configuration\n"
4734 " mask [NAME...] Mask one or more units\n"
4735 " unmask [NAME...] Unmask one or more units\n"
4736 " link [PATH...] Link one or more units files into\n"
4737 " the search path\n"
4738 " get-default Get the name of the default target\n"
4739 " set-default NAME Set the default target\n"
4740 " is-enabled [NAME...] Check whether unit files are enabled\n\n"
4742 " list-jobs List jobs\n"
4743 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
4744 "Status Commands:\n"
4745 " dump Dump server status\n"
4746 "Snapshot Commands:\n"
4747 " snapshot [NAME] Create a snapshot\n"
4748 " delete [NAME...] Remove one or more snapshots\n\n"
4749 "Environment Commands:\n"
4750 " show-environment Dump environment\n"
4751 " set-environment [NAME=VALUE...] Set one or more environment variables\n"
4752 " unset-environment [NAME...] Unset one or more environment variables\n"
4753 " set-log-level LEVEL Set logging threshold for systemd\n\n"
4754 "Manager Lifecycle Commands:\n"
4755 " daemon-reload Reload systemd manager configuration\n"
4756 " daemon-reexec Reexecute systemd manager\n\n"
4757 "System Commands:\n"
4758 " default Enter system default mode\n"
4759 " rescue Enter system rescue mode\n"
4760 " emergency Enter system emergency mode\n"
4761 " halt Shut down and halt the system\n"
4762 " poweroff Shut down and power-off the system\n"
4763 " reboot Shut down and reboot the system\n"
4764 " kexec Shut down and reboot the system with kexec\n"
4765 " exit Request user instance exit\n"
4766 " switch-root [ROOT] [INIT] Change to a different root file system\n"
4767 " suspend Suspend the system\n"
4768 " hibernate Hibernate the system\n"
4769 " hybrid-sleep Hibernate and suspend the system\n",
4770 program_invocation_short_name);
4775 static int halt_help(void) {
4777 printf("%s [OPTIONS...]\n\n"
4778 "%s the system.\n\n"
4779 " --help Show this help\n"
4780 " --halt Halt the machine\n"
4781 " -p --poweroff Switch off the machine\n"
4782 " --reboot Reboot the machine\n"
4783 " -f --force Force immediate halt/power-off/reboot\n"
4784 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
4785 " -d --no-wtmp Don't write wtmp record\n"
4786 " --no-wall Don't send wall message before halt/power-off/reboot\n",
4787 program_invocation_short_name,
4788 arg_action == ACTION_REBOOT ? "Reboot" :
4789 arg_action == ACTION_POWEROFF ? "Power off" :
4795 static int shutdown_help(void) {
4797 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
4798 "Shut down the system.\n\n"
4799 " --help Show this help\n"
4800 " -H --halt Halt the machine\n"
4801 " -P --poweroff Power-off the machine\n"
4802 " -r --reboot Reboot the machine\n"
4803 " -h Equivalent to --poweroff, overridden by --halt\n"
4804 " -k Don't halt/power-off/reboot, just send warnings\n"
4805 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4806 " -c Cancel a pending shutdown\n",
4807 program_invocation_short_name);
4812 static int telinit_help(void) {
4814 printf("%s [OPTIONS...] {COMMAND}\n\n"
4815 "Send control commands to the init daemon.\n\n"
4816 " --help Show this help\n"
4817 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
4819 " 0 Power-off the machine\n"
4820 " 6 Reboot the machine\n"
4821 " 2, 3, 4, 5 Start runlevelX.target unit\n"
4822 " 1, s, S Enter rescue mode\n"
4823 " q, Q Reload init daemon configuration\n"
4824 " u, U Reexecute init daemon\n",
4825 program_invocation_short_name);
4830 static int runlevel_help(void) {
4832 printf("%s [OPTIONS...]\n\n"
4833 "Prints the previous and current runlevel of the init system.\n\n"
4834 " --help Show this help\n",
4835 program_invocation_short_name);
4840 static int help_types(void) {
4844 puts("Available unit types:");
4845 for(i = 0; i < _UNIT_TYPE_MAX; i++) {
4846 t = unit_type_to_string(i);
4851 puts("\nAvailable unit load states: ");
4852 for(i = 0; i < _UNIT_LOAD_STATE_MAX; i++) {
4853 t = unit_load_state_to_string(i);
4861 static int systemctl_parse_argv(int argc, char *argv[]) {
4870 ARG_IGNORE_DEPENDENCIES,
4882 ARG_NO_ASK_PASSWORD,
4889 static const struct option options[] = {
4890 { "help", no_argument, NULL, 'h' },
4891 { "version", no_argument, NULL, ARG_VERSION },
4892 { "type", required_argument, NULL, 't' },
4893 { "property", required_argument, NULL, 'p' },
4894 { "all", no_argument, NULL, 'a' },
4895 { "reverse", no_argument, NULL, ARG_REVERSE },
4896 { "after", no_argument, NULL, ARG_AFTER },
4897 { "before", no_argument, NULL, ARG_BEFORE },
4898 { "show-types", no_argument, NULL, ARG_SHOW_TYPES },
4899 { "failed", no_argument, NULL, ARG_FAILED },
4900 { "full", no_argument, NULL, 'l' },
4901 { "fail", no_argument, NULL, ARG_FAIL },
4902 { "irreversible", no_argument, NULL, ARG_IRREVERSIBLE },
4903 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
4904 { "ignore-inhibitors", no_argument, NULL, 'i' },
4905 { "user", no_argument, NULL, ARG_USER },
4906 { "system", no_argument, NULL, ARG_SYSTEM },
4907 { "global", no_argument, NULL, ARG_GLOBAL },
4908 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
4909 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
4910 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
4911 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4912 { "quiet", no_argument, NULL, 'q' },
4913 { "root", required_argument, NULL, ARG_ROOT },
4914 { "force", no_argument, NULL, ARG_FORCE },
4915 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
4916 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
4917 { "signal", required_argument, NULL, 's' },
4918 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
4919 { "host", required_argument, NULL, 'H' },
4920 { "privileged",no_argument, NULL, 'P' },
4921 { "runtime", no_argument, NULL, ARG_RUNTIME },
4922 { "lines", required_argument, NULL, 'n' },
4923 { "output", required_argument, NULL, 'o' },
4924 { "plain", no_argument, NULL, ARG_PLAIN },
4925 { NULL, 0, NULL, 0 }
4933 while ((c = getopt_long(argc, argv, "ht:p:alqfs:H:Pn:o:i", options, NULL)) >= 0) {
4942 puts(PACKAGE_STRING);
4943 puts(SYSTEMD_FEATURES);
4950 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
4951 _cleanup_free_ char *type;
4953 type = strndup(word, size);
4957 if (streq(type, "help")) {
4962 if (unit_type_from_string(type) >= 0) {
4963 if (strv_push(&arg_types, type))
4969 if (unit_load_state_from_string(optarg) >= 0) {
4970 if (strv_push(&arg_load_states, type))
4976 log_error("Unknown unit type or load state '%s'.", type);
4977 log_info("Use -t help to see a list of allowed values.");
4985 /* Make sure that if the empty property list
4986 was specified, we won't show any properties. */
4987 if (isempty(optarg) && !arg_properties) {
4988 arg_properties = strv_new(NULL, NULL);
4989 if (!arg_properties)
4995 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
4998 prop = strndup(word, size);
5002 if (strv_push(&arg_properties, prop)) {
5009 /* If the user asked for a particular
5010 * property, show it to him, even if it is
5022 arg_dependency = DEPENDENCY_REVERSE;
5026 arg_dependency = DEPENDENCY_AFTER;
5030 arg_dependency = DEPENDENCY_BEFORE;
5033 case ARG_SHOW_TYPES:
5034 arg_show_types = true;
5038 arg_job_mode = "fail";
5041 case ARG_IRREVERSIBLE:
5042 arg_job_mode = "replace-irreversibly";
5045 case ARG_IGNORE_DEPENDENCIES:
5046 arg_job_mode = "ignore-dependencies";
5050 arg_scope = UNIT_FILE_USER;
5054 arg_scope = UNIT_FILE_SYSTEM;
5058 arg_scope = UNIT_FILE_GLOBAL;
5062 arg_no_block = true;
5066 arg_no_legend = true;
5070 arg_no_pager = true;
5102 arg_no_reload = true;
5106 arg_kill_who = optarg;
5110 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
5111 log_error("Failed to parse signal string %s.", optarg);
5116 case ARG_NO_ASK_PASSWORD:
5117 arg_ask_password = false;
5121 arg_transport = TRANSPORT_POLKIT;
5125 arg_transport = TRANSPORT_SSH;
5126 parse_user_at_host(optarg, &arg_user, &arg_host);
5134 if (safe_atou(optarg, &arg_lines) < 0) {
5135 log_error("Failed to parse lines '%s'", optarg);
5141 arg_output = output_mode_from_string(optarg);
5142 if (arg_output < 0) {
5143 log_error("Unknown output '%s'.", optarg);
5149 arg_ignore_inhibitors = true;
5160 log_error("Unknown option code '%c'.", c);
5165 if (arg_transport != TRANSPORT_NORMAL && arg_scope != UNIT_FILE_SYSTEM) {
5166 log_error("Cannot access user instance remotely.");
5173 static int halt_parse_argv(int argc, char *argv[]) {
5182 static const struct option options[] = {
5183 { "help", no_argument, NULL, ARG_HELP },
5184 { "halt", no_argument, NULL, ARG_HALT },
5185 { "poweroff", no_argument, NULL, 'p' },
5186 { "reboot", no_argument, NULL, ARG_REBOOT },
5187 { "force", no_argument, NULL, 'f' },
5188 { "wtmp-only", no_argument, NULL, 'w' },
5189 { "no-wtmp", no_argument, NULL, 'd' },
5190 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5191 { NULL, 0, NULL, 0 }
5199 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
5200 if (runlevel == '0' || runlevel == '6')
5203 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
5211 arg_action = ACTION_HALT;
5215 if (arg_action != ACTION_REBOOT)
5216 arg_action = ACTION_POWEROFF;
5220 arg_action = ACTION_REBOOT;
5242 /* Compatibility nops */
5249 log_error("Unknown option code '%c'.", c);
5254 if (optind < argc) {
5255 log_error("Too many arguments.");
5262 static int parse_time_spec(const char *t, usec_t *_u) {
5266 if (streq(t, "now"))
5268 else if (!strchr(t, ':')) {
5271 if (safe_atou64(t, &u) < 0)
5274 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
5283 hour = strtol(t, &e, 10);
5284 if (errno > 0 || *e != ':' || hour < 0 || hour > 23)
5287 minute = strtol(e+1, &e, 10);
5288 if (errno > 0 || *e != 0 || minute < 0 || minute > 59)
5291 n = now(CLOCK_REALTIME);
5292 s = (time_t) (n / USEC_PER_SEC);
5294 assert_se(localtime_r(&s, &tm));
5296 tm.tm_hour = (int) hour;
5297 tm.tm_min = (int) minute;
5300 assert_se(s = mktime(&tm));
5302 *_u = (usec_t) s * USEC_PER_SEC;
5305 *_u += USEC_PER_DAY;
5311 static int shutdown_parse_argv(int argc, char *argv[]) {
5318 static const struct option options[] = {
5319 { "help", no_argument, NULL, ARG_HELP },
5320 { "halt", no_argument, NULL, 'H' },
5321 { "poweroff", no_argument, NULL, 'P' },
5322 { "reboot", no_argument, NULL, 'r' },
5323 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
5324 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5325 { NULL, 0, NULL, 0 }
5333 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
5341 arg_action = ACTION_HALT;
5345 arg_action = ACTION_POWEROFF;
5350 arg_action = ACTION_KEXEC;
5352 arg_action = ACTION_REBOOT;
5356 arg_action = ACTION_KEXEC;
5360 if (arg_action != ACTION_HALT)
5361 arg_action = ACTION_POWEROFF;
5374 /* Compatibility nops */
5378 arg_action = ACTION_CANCEL_SHUTDOWN;
5385 log_error("Unknown option code '%c'.", c);
5390 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
5391 r = parse_time_spec(argv[optind], &arg_when);
5393 log_error("Failed to parse time specification: %s", argv[optind]);
5397 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
5399 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
5400 /* No time argument for shutdown cancel */
5401 arg_wall = argv + optind;
5402 else if (argc > optind + 1)
5403 /* We skip the time argument */
5404 arg_wall = argv + optind + 1;
5411 static int telinit_parse_argv(int argc, char *argv[]) {
5418 static const struct option options[] = {
5419 { "help", no_argument, NULL, ARG_HELP },
5420 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5421 { NULL, 0, NULL, 0 }
5424 static const struct {
5428 { '0', ACTION_POWEROFF },
5429 { '6', ACTION_REBOOT },
5430 { '1', ACTION_RESCUE },
5431 { '2', ACTION_RUNLEVEL2 },
5432 { '3', ACTION_RUNLEVEL3 },
5433 { '4', ACTION_RUNLEVEL4 },
5434 { '5', ACTION_RUNLEVEL5 },
5435 { 's', ACTION_RESCUE },
5436 { 'S', ACTION_RESCUE },
5437 { 'q', ACTION_RELOAD },
5438 { 'Q', ACTION_RELOAD },
5439 { 'u', ACTION_REEXEC },
5440 { 'U', ACTION_REEXEC }
5449 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
5464 log_error("Unknown option code '%c'.", c);
5469 if (optind >= argc) {
5474 if (optind + 1 < argc) {
5475 log_error("Too many arguments.");
5479 if (strlen(argv[optind]) != 1) {
5480 log_error("Expected single character argument.");
5484 for (i = 0; i < ELEMENTSOF(table); i++)
5485 if (table[i].from == argv[optind][0])
5488 if (i >= ELEMENTSOF(table)) {
5489 log_error("Unknown command '%s'.", argv[optind]);
5493 arg_action = table[i].to;
5500 static int runlevel_parse_argv(int argc, char *argv[]) {
5506 static const struct option options[] = {
5507 { "help", no_argument, NULL, ARG_HELP },
5508 { NULL, 0, NULL, 0 }
5516 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
5527 log_error("Unknown option code '%c'.", c);
5532 if (optind < argc) {
5533 log_error("Too many arguments.");
5540 static int parse_argv(int argc, char *argv[]) {
5544 if (program_invocation_short_name) {
5546 if (strstr(program_invocation_short_name, "halt")) {
5547 arg_action = ACTION_HALT;
5548 return halt_parse_argv(argc, argv);
5549 } else if (strstr(program_invocation_short_name, "poweroff")) {
5550 arg_action = ACTION_POWEROFF;
5551 return halt_parse_argv(argc, argv);
5552 } else if (strstr(program_invocation_short_name, "reboot")) {
5554 arg_action = ACTION_KEXEC;
5556 arg_action = ACTION_REBOOT;
5557 return halt_parse_argv(argc, argv);
5558 } else if (strstr(program_invocation_short_name, "shutdown")) {
5559 arg_action = ACTION_POWEROFF;
5560 return shutdown_parse_argv(argc, argv);
5561 } else if (strstr(program_invocation_short_name, "init")) {
5563 if (sd_booted() > 0) {
5564 arg_action = ACTION_INVALID;
5565 return telinit_parse_argv(argc, argv);
5567 /* Hmm, so some other init system is
5568 * running, we need to forward this
5569 * request to it. For now we simply
5570 * guess that it is Upstart. */
5572 execv(TELINIT, argv);
5574 log_error("Couldn't find an alternative telinit implementation to spawn.");
5578 } else if (strstr(program_invocation_short_name, "runlevel")) {
5579 arg_action = ACTION_RUNLEVEL;
5580 return runlevel_parse_argv(argc, argv);
5584 arg_action = ACTION_SYSTEMCTL;
5585 return systemctl_parse_argv(argc, argv);
5588 _pure_ static int action_to_runlevel(void) {
5590 static const char table[_ACTION_MAX] = {
5591 [ACTION_HALT] = '0',
5592 [ACTION_POWEROFF] = '0',
5593 [ACTION_REBOOT] = '6',
5594 [ACTION_RUNLEVEL2] = '2',
5595 [ACTION_RUNLEVEL3] = '3',
5596 [ACTION_RUNLEVEL4] = '4',
5597 [ACTION_RUNLEVEL5] = '5',
5598 [ACTION_RESCUE] = '1'
5601 assert(arg_action < _ACTION_MAX);
5603 return table[arg_action];
5606 static int talk_upstart(void) {
5607 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
5608 _cleanup_dbus_error_free_ DBusError error;
5609 int previous, rl, r;
5611 env1_buf[] = "RUNLEVEL=X",
5612 env2_buf[] = "PREVLEVEL=X";
5613 char *env1 = env1_buf, *env2 = env2_buf;
5614 const char *emit = "runlevel";
5615 dbus_bool_t b_false = FALSE;
5616 DBusMessageIter iter, sub;
5617 DBusConnection *bus;
5619 dbus_error_init(&error);
5621 if (!(rl = action_to_runlevel()))
5624 if (utmp_get_runlevel(&previous, NULL) < 0)
5627 if (!(bus = dbus_connection_open_private("unix:abstract=/com/ubuntu/upstart", &error))) {
5628 if (dbus_error_has_name(&error, DBUS_ERROR_NO_SERVER)) {
5633 log_error("Failed to connect to Upstart bus: %s", bus_error_message(&error));
5638 if ((r = bus_check_peercred(bus)) < 0) {
5639 log_error("Failed to verify owner of bus.");
5643 if (!(m = dbus_message_new_method_call(
5644 "com.ubuntu.Upstart",
5645 "/com/ubuntu/Upstart",
5646 "com.ubuntu.Upstart0_6",
5649 log_error("Could not allocate message.");
5654 dbus_message_iter_init_append(m, &iter);
5656 env1_buf[sizeof(env1_buf)-2] = rl;
5657 env2_buf[sizeof(env2_buf)-2] = previous;
5659 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &emit) ||
5660 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub) ||
5661 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env1) ||
5662 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env2) ||
5663 !dbus_message_iter_close_container(&iter, &sub) ||
5664 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b_false)) {
5665 log_error("Could not append arguments to message.");
5670 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
5672 if (bus_error_is_no_service(&error)) {
5677 log_error("Failed to issue method call: %s", bus_error_message(&error));
5686 dbus_connection_flush(bus);
5687 dbus_connection_close(bus);
5688 dbus_connection_unref(bus);
5694 static int talk_initctl(void) {
5695 struct init_request request = {};
5697 _cleanup_close_ int fd = -1;
5700 rl = action_to_runlevel();
5704 request.magic = INIT_MAGIC;
5705 request.sleeptime = 0;
5706 request.cmd = INIT_CMD_RUNLVL;
5707 request.runlevel = rl;
5709 fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY);
5711 if (errno == ENOENT)
5714 log_error("Failed to open "INIT_FIFO": %m");
5719 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
5721 log_error("Failed to write to "INIT_FIFO": %m");
5722 return errno > 0 ? -errno : -EIO;
5728 static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
5730 static const struct {
5738 int (* const dispatch)(DBusConnection *bus, char **args);
5740 { "list-units", LESS, 1, list_units },
5741 { "list-unit-files", EQUAL, 1, list_unit_files },
5742 { "list-sockets", LESS, 1, list_sockets },
5743 { "list-jobs", EQUAL, 1, list_jobs },
5744 { "clear-jobs", EQUAL, 1, daemon_reload },
5745 { "load", MORE, 2, load_unit },
5746 { "cancel", MORE, 2, cancel_job },
5747 { "start", MORE, 2, start_unit },
5748 { "stop", MORE, 2, start_unit },
5749 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5750 { "reload", MORE, 2, start_unit },
5751 { "restart", MORE, 2, start_unit },
5752 { "try-restart", MORE, 2, start_unit },
5753 { "reload-or-restart", MORE, 2, start_unit },
5754 { "reload-or-try-restart", MORE, 2, start_unit },
5755 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
5756 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5757 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
5758 { "isolate", EQUAL, 2, start_unit },
5759 { "kill", MORE, 2, kill_unit },
5760 { "is-active", MORE, 2, check_unit_active },
5761 { "check", MORE, 2, check_unit_active },
5762 { "is-failed", MORE, 2, check_unit_failed },
5763 { "show", MORE, 1, show },
5764 { "status", MORE, 1, show },
5765 { "help", MORE, 2, show },
5766 { "dump", EQUAL, 1, dump },
5767 { "snapshot", LESS, 2, snapshot },
5768 { "delete", MORE, 2, delete_snapshot },
5769 { "daemon-reload", EQUAL, 1, daemon_reload },
5770 { "daemon-reexec", EQUAL, 1, daemon_reload },
5771 { "show-environment", EQUAL, 1, show_enviroment },
5772 { "set-environment", MORE, 2, set_environment },
5773 { "unset-environment", MORE, 2, set_environment },
5774 { "halt", EQUAL, 1, start_special },
5775 { "poweroff", EQUAL, 1, start_special },
5776 { "reboot", EQUAL, 1, start_special },
5777 { "kexec", EQUAL, 1, start_special },
5778 { "suspend", EQUAL, 1, start_special },
5779 { "hibernate", EQUAL, 1, start_special },
5780 { "hybrid-sleep", EQUAL, 1, start_special },
5781 { "default", EQUAL, 1, start_special },
5782 { "rescue", EQUAL, 1, start_special },
5783 { "emergency", EQUAL, 1, start_special },
5784 { "exit", EQUAL, 1, start_special },
5785 { "reset-failed", MORE, 1, reset_failed },
5786 { "enable", MORE, 2, enable_unit },
5787 { "disable", MORE, 2, enable_unit },
5788 { "is-enabled", MORE, 2, unit_is_enabled },
5789 { "reenable", MORE, 2, enable_unit },
5790 { "preset", MORE, 2, enable_unit },
5791 { "mask", MORE, 2, enable_unit },
5792 { "unmask", MORE, 2, enable_unit },
5793 { "link", MORE, 2, enable_unit },
5794 { "switch-root", MORE, 2, switch_root },
5795 { "list-dependencies", LESS, 2, list_dependencies },
5796 { "set-default", EQUAL, 2, enable_unit },
5797 { "get-default", LESS, 1, get_default },
5798 { "set-log-level", EQUAL, 2, set_log_level },
5799 { "set-property", MORE, 3, set_property },
5809 left = argc - optind;
5812 /* Special rule: no arguments means "list-units" */
5815 if (streq(argv[optind], "help") && !argv[optind+1]) {
5816 log_error("This command expects one or more "
5817 "unit names. Did you mean --help?");
5821 for (i = 0; i < ELEMENTSOF(verbs); i++)
5822 if (streq(argv[optind], verbs[i].verb))
5825 if (i >= ELEMENTSOF(verbs)) {
5826 log_error("Unknown operation '%s'.", argv[optind]);
5831 switch (verbs[i].argc_cmp) {
5834 if (left != verbs[i].argc) {
5835 log_error("Invalid number of arguments.");
5842 if (left < verbs[i].argc) {
5843 log_error("Too few arguments.");
5850 if (left > verbs[i].argc) {
5851 log_error("Too many arguments.");
5858 assert_not_reached("Unknown comparison operator.");
5861 /* Require a bus connection for all operations but
5863 if (!streq(verbs[i].verb, "enable") &&
5864 !streq(verbs[i].verb, "disable") &&
5865 !streq(verbs[i].verb, "is-enabled") &&
5866 !streq(verbs[i].verb, "list-unit-files") &&
5867 !streq(verbs[i].verb, "reenable") &&
5868 !streq(verbs[i].verb, "preset") &&
5869 !streq(verbs[i].verb, "mask") &&
5870 !streq(verbs[i].verb, "unmask") &&
5871 !streq(verbs[i].verb, "link") &&
5872 !streq(verbs[i].verb, "set-default") &&
5873 !streq(verbs[i].verb, "get-default")) {
5875 if (running_in_chroot() > 0) {
5876 log_info("Running in chroot, ignoring request.");
5880 if (((!streq(verbs[i].verb, "reboot") &&
5881 !streq(verbs[i].verb, "halt") &&
5882 !streq(verbs[i].verb, "poweroff")) || arg_force <= 0) && !bus) {
5883 log_error("Failed to get D-Bus connection: %s",
5884 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5890 if (!bus && !avoid_bus()) {
5891 log_error("Failed to get D-Bus connection: %s",
5892 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5897 return verbs[i].dispatch(bus, argv + optind);
5900 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
5901 _cleanup_close_ int fd;
5902 struct sd_shutdown_command c = {
5908 union sockaddr_union sockaddr = {
5909 .un.sun_family = AF_UNIX,
5910 .un.sun_path = "/run/systemd/shutdownd",
5912 struct iovec iovec[2] = {
5913 {.iov_base = (char*) &c,
5914 .iov_len = offsetof(struct sd_shutdown_command, wall_message),
5917 struct msghdr msghdr = {
5918 .msg_name = &sockaddr,
5919 .msg_namelen = offsetof(struct sockaddr_un, sun_path)
5920 + sizeof("/run/systemd/shutdownd") - 1,
5925 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
5929 if (!isempty(message)) {
5930 iovec[1].iov_base = (char*) message;
5931 iovec[1].iov_len = strlen(message);
5932 msghdr.msg_iovlen++;
5935 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0)
5941 static int reload_with_fallback(DBusConnection *bus) {
5944 /* First, try systemd via D-Bus. */
5945 if (daemon_reload(bus, NULL) >= 0)
5949 /* Nothing else worked, so let's try signals */
5950 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
5952 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
5953 log_error("kill() failed: %m");
5960 static int start_with_fallback(DBusConnection *bus) {
5963 /* First, try systemd via D-Bus. */
5964 if (start_unit(bus, NULL) >= 0)
5968 /* Hmm, talking to systemd via D-Bus didn't work. Then
5969 * let's try to talk to Upstart via D-Bus. */
5970 if (talk_upstart() > 0)
5973 /* Nothing else worked, so let's try
5975 if (talk_initctl() > 0)
5978 log_error("Failed to talk to init daemon.");
5982 warn_wall(arg_action);
5986 static _noreturn_ void halt_now(enum action a) {
5988 /* Make sure C-A-D is handled by the kernel from this
5990 reboot(RB_ENABLE_CAD);
5995 log_info("Halting.");
5996 reboot(RB_HALT_SYSTEM);
5999 case ACTION_POWEROFF:
6000 log_info("Powering off.");
6001 reboot(RB_POWER_OFF);
6005 log_info("Rebooting.");
6006 reboot(RB_AUTOBOOT);
6010 assert_not_reached("Unknown halt action.");
6013 assert_not_reached("Uh? This shouldn't happen.");
6016 static int halt_main(DBusConnection *bus) {
6019 r = check_inhibitors(bus, arg_action);
6023 if (geteuid() != 0) {
6024 /* Try logind if we are a normal user and no special
6025 * mode applies. Maybe PolicyKit allows us to shutdown
6028 if (arg_when <= 0 &&
6031 (arg_action == ACTION_POWEROFF ||
6032 arg_action == ACTION_REBOOT)) {
6033 r = reboot_with_logind(bus, arg_action);
6038 log_error("Must be root.");
6043 _cleanup_free_ char *m;
6045 m = strv_join(arg_wall, " ");
6046 r = send_shutdownd(arg_when,
6047 arg_action == ACTION_HALT ? 'H' :
6048 arg_action == ACTION_POWEROFF ? 'P' :
6049 arg_action == ACTION_KEXEC ? 'K' :
6056 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
6058 char date[FORMAT_TIMESTAMP_MAX];
6060 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
6061 format_timestamp(date, sizeof(date), arg_when));
6066 if (!arg_dry && !arg_force)
6067 return start_with_fallback(bus);
6070 if (sd_booted() > 0)
6071 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
6073 r = utmp_put_shutdown();
6075 log_warning("Failed to write utmp record: %s", strerror(-r));
6082 halt_now(arg_action);
6083 /* We should never reach this. */
6087 static int runlevel_main(void) {
6088 int r, runlevel, previous;
6090 r = utmp_get_runlevel(&runlevel, &previous);
6097 previous <= 0 ? 'N' : previous,
6098 runlevel <= 0 ? 'N' : runlevel);
6103 int main(int argc, char*argv[]) {
6104 int r, retval = EXIT_FAILURE;
6105 DBusConnection *bus = NULL;
6106 _cleanup_dbus_error_free_ DBusError error;
6108 dbus_error_init(&error);
6110 setlocale(LC_ALL, "");
6111 log_parse_environment();
6114 r = parse_argv(argc, argv);
6118 retval = EXIT_SUCCESS;
6122 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
6123 * let's shortcut this */
6124 if (arg_action == ACTION_RUNLEVEL) {
6125 r = runlevel_main();
6126 retval = r < 0 ? EXIT_FAILURE : r;
6130 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
6131 log_info("Running in chroot, ignoring request.");
6137 if (arg_transport == TRANSPORT_NORMAL)
6138 bus_connect(arg_scope == UNIT_FILE_SYSTEM ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &bus, &private_bus, &error);
6139 else if (arg_transport == TRANSPORT_POLKIT) {
6140 bus_connect_system_polkit(&bus, &error);
6141 private_bus = false;
6142 } else if (arg_transport == TRANSPORT_SSH) {
6143 bus_connect_system_ssh(arg_user, arg_host, &bus, &error);
6144 private_bus = false;
6146 assert_not_reached("Uh, invalid transport...");
6149 switch (arg_action) {
6151 case ACTION_SYSTEMCTL:
6152 r = systemctl_main(bus, argc, argv, &error);
6156 case ACTION_POWEROFF:
6162 case ACTION_RUNLEVEL2:
6163 case ACTION_RUNLEVEL3:
6164 case ACTION_RUNLEVEL4:
6165 case ACTION_RUNLEVEL5:
6167 case ACTION_EMERGENCY:
6168 case ACTION_DEFAULT:
6169 r = start_with_fallback(bus);
6174 r = reload_with_fallback(bus);
6177 case ACTION_CANCEL_SHUTDOWN: {
6181 m = strv_join(arg_wall, " ");
6183 retval = EXIT_FAILURE;
6187 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
6189 log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r));
6194 case ACTION_INVALID:
6195 case ACTION_RUNLEVEL:
6197 assert_not_reached("Unknown action");
6200 retval = r < 0 ? EXIT_FAILURE : r;
6204 dbus_connection_flush(bus);
6205 dbus_connection_close(bus);
6206 dbus_connection_unref(bus);
6211 strv_free(arg_types);
6212 strv_free(arg_load_states);
6213 strv_free(arg_properties);
6216 ask_password_agent_close();
6217 polkit_agent_close();