1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
22 #include <sys/reboot.h>
29 #include <sys/ioctl.h>
33 #include <sys/socket.h>
36 #include <sys/prctl.h>
37 #include <dbus/dbus.h>
39 #include <systemd/sd-daemon.h>
40 #include <systemd/sd-shutdown.h>
41 #include <systemd/sd-login.h>
47 #include "utmp-wtmp.h"
50 #include "path-util.h"
52 #include "dbus-common.h"
53 #include "cgroup-show.h"
54 #include "cgroup-util.h"
56 #include "path-lookup.h"
57 #include "conf-parser.h"
58 #include "exit-status.h"
59 #include "bus-errors.h"
61 #include "unit-name.h"
63 #include "spawn-ask-password-agent.h"
64 #include "spawn-polkit-agent.h"
66 #include "logs-show.h"
67 #include "path-util.h"
68 #include "socket-util.h"
71 static char **arg_types = NULL;
72 static char **arg_load_states = NULL;
73 static char **arg_properties = NULL;
74 static bool arg_all = false;
75 static enum dependency {
80 } arg_dependency = DEPENDENCY_FORWARD;
81 static const char *arg_job_mode = "replace";
82 static UnitFileScope arg_scope = UNIT_FILE_SYSTEM;
83 static bool arg_no_block = false;
84 static bool arg_no_legend = false;
85 static bool arg_no_pager = false;
86 static bool arg_no_wtmp = false;
87 static bool arg_no_wall = false;
88 static bool arg_no_reload = false;
89 static bool arg_show_types = false;
90 static bool arg_ignore_inhibitors = false;
91 static bool arg_dry = false;
92 static bool arg_quiet = false;
93 static bool arg_full = false;
94 static int arg_force = 0;
95 static bool arg_ask_password = true;
96 static bool arg_failed = false;
97 static bool arg_runtime = false;
98 static char **arg_wall = NULL;
99 static const char *arg_kill_who = NULL;
100 static int arg_signal = SIGTERM;
101 static const char *arg_root = NULL;
102 static usec_t arg_when = 0;
124 ACTION_CANCEL_SHUTDOWN,
126 } arg_action = ACTION_SYSTEMCTL;
127 static enum transport {
131 } arg_transport = TRANSPORT_NORMAL;
132 static char *arg_host = NULL;
133 static char *arg_user = NULL;
134 static unsigned arg_lines = 10;
135 static OutputMode arg_output = OUTPUT_SHORT;
136 static bool arg_plain = false;
138 static bool private_bus = false;
140 static int daemon_reload(DBusConnection *bus, char **args);
141 static void halt_now(enum action a);
143 static void pager_open_if_enabled(void) {
151 static void ask_password_agent_open_if_enabled(void) {
153 /* Open the password agent as a child process if necessary */
155 if (!arg_ask_password)
158 if (arg_scope != UNIT_FILE_SYSTEM)
161 ask_password_agent_open();
165 static void polkit_agent_open_if_enabled(void) {
167 /* Open the polkit agent as a child process if necessary */
169 if (!arg_ask_password)
172 if (arg_scope != UNIT_FILE_SYSTEM)
179 static const char *ansi_highlight(bool b) {
184 return b ? ANSI_HIGHLIGHT_ON : ANSI_HIGHLIGHT_OFF;
187 static const char *ansi_highlight_red(bool b) {
192 return b ? ANSI_HIGHLIGHT_RED_ON : ANSI_HIGHLIGHT_OFF;
195 static const char *ansi_highlight_green(bool b) {
200 return b ? ANSI_HIGHLIGHT_GREEN_ON : ANSI_HIGHLIGHT_OFF;
203 static int translate_bus_error_to_exit_status(int r, const DBusError *error) {
206 if (!dbus_error_is_set(error))
209 if (dbus_error_has_name(error, DBUS_ERROR_ACCESS_DENIED) ||
210 dbus_error_has_name(error, BUS_ERROR_ONLY_BY_DEPENDENCY) ||
211 dbus_error_has_name(error, BUS_ERROR_NO_ISOLATION) ||
212 dbus_error_has_name(error, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE))
213 return EXIT_NOPERMISSION;
215 if (dbus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT))
216 return EXIT_NOTINSTALLED;
218 if (dbus_error_has_name(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE) ||
219 dbus_error_has_name(error, BUS_ERROR_NOT_SUPPORTED))
220 return EXIT_NOTIMPLEMENTED;
222 if (dbus_error_has_name(error, BUS_ERROR_LOAD_FAILED))
223 return EXIT_NOTCONFIGURED;
231 static void warn_wall(enum action a) {
232 static const char *table[_ACTION_MAX] = {
233 [ACTION_HALT] = "The system is going down for system halt NOW!",
234 [ACTION_REBOOT] = "The system is going down for reboot NOW!",
235 [ACTION_POWEROFF] = "The system is going down for power-off NOW!",
236 [ACTION_KEXEC] = "The system is going down for kexec reboot NOW!",
237 [ACTION_RESCUE] = "The system is going down to rescue mode NOW!",
238 [ACTION_EMERGENCY] = "The system is going down to emergency mode NOW!",
239 [ACTION_CANCEL_SHUTDOWN] = "The system shutdown has been cancelled NOW!"
246 _cleanup_free_ char *p;
248 p = strv_join(arg_wall, " ");
263 utmp_wall(table[a], NULL);
266 static bool avoid_bus(void) {
268 if (running_in_chroot() > 0)
271 if (sd_booted() <= 0)
274 if (!isempty(arg_root))
277 if (arg_scope == UNIT_FILE_GLOBAL)
283 static int compare_unit_info(const void *a, const void *b) {
285 const struct unit_info *u = a, *v = b;
287 d1 = strrchr(u->id, '.');
288 d2 = strrchr(v->id, '.');
293 r = strcasecmp(d1, d2);
298 return strcasecmp(u->id, v->id);
301 static bool output_show_unit(const struct unit_info *u) {
305 return streq(u->active_state, "failed");
307 return (!arg_types || ((dot = strrchr(u->id, '.')) &&
308 strv_find(arg_types, dot+1))) &&
309 (!arg_load_states || strv_find(arg_load_states, u->load_state)) &&
310 (arg_all || !(streq(u->active_state, "inactive")
311 || u->following[0]) || u->job_id > 0);
314 static void output_units_list(const struct unit_info *unit_infos, unsigned c) {
315 unsigned id_len, max_id_len, active_len, sub_len, job_len, desc_len, n_shown = 0;
316 const struct unit_info *u;
319 max_id_len = sizeof("UNIT")-1;
320 active_len = sizeof("ACTIVE")-1;
321 sub_len = sizeof("SUB")-1;
322 job_len = sizeof("JOB")-1;
325 for (u = unit_infos; u < unit_infos + c; u++) {
326 if (!output_show_unit(u))
329 max_id_len = MAX(max_id_len, strlen(u->id));
330 active_len = MAX(active_len, strlen(u->active_state));
331 sub_len = MAX(sub_len, strlen(u->sub_state));
332 if (u->job_id != 0) {
333 job_len = MAX(job_len, strlen(u->job_type));
340 id_len = MIN(max_id_len, 25u);
341 basic_len = 5 + id_len + 5 + active_len + sub_len;
343 basic_len += job_len + 1;
344 if (basic_len < (unsigned) columns()) {
345 unsigned extra_len, incr;
346 extra_len = columns() - basic_len;
347 /* Either UNIT already got 25, or is fully satisfied.
348 * Grant up to 25 to DESC now. */
349 incr = MIN(extra_len, 25u);
352 /* split the remaining space between UNIT and DESC,
353 * but do not give UNIT more than it needs. */
355 incr = MIN(extra_len / 2, max_id_len - id_len);
357 desc_len += extra_len - incr;
363 for (u = unit_infos; u < unit_infos + c; u++) {
364 _cleanup_free_ char *e = NULL;
365 const char *on_loaded, *off_loaded, *on = "";
366 const char *on_active, *off_active, *off = "";
368 if (!output_show_unit(u))
371 if (!n_shown && !arg_no_legend) {
372 printf("%-*s %-6s %-*s %-*s ", id_len, "UNIT", "LOAD",
373 active_len, "ACTIVE", sub_len, "SUB");
375 printf("%-*s ", job_len, "JOB");
376 if (!arg_full && arg_no_pager)
377 printf("%.*s\n", desc_len, "DESCRIPTION");
379 printf("%s\n", "DESCRIPTION");
384 if (streq(u->load_state, "error") ||
385 streq(u->load_state, "not-found")) {
386 on_loaded = on = ansi_highlight_red(true);
387 off_loaded = off = ansi_highlight_red(false);
389 on_loaded = off_loaded = "";
391 if (streq(u->active_state, "failed")) {
392 on_active = on = ansi_highlight_red(true);
393 off_active = off = ansi_highlight_red(false);
395 on_active = off_active = "";
397 e = arg_full ? NULL : ellipsize(u->id, id_len, 33);
399 printf("%s%-*s%s %s%-6s%s %s%-*s %-*s%s %-*s",
400 on, id_len, e ? e : u->id, off,
401 on_loaded, u->load_state, off_loaded,
402 on_active, active_len, u->active_state,
403 sub_len, u->sub_state, off_active,
404 job_count ? job_len + 1 : 0, u->job_id ? u->job_type : "");
405 if (!arg_full && arg_no_pager)
406 printf("%.*s\n", desc_len, u->description);
408 printf("%s\n", u->description);
411 if (!arg_no_legend) {
412 const char *on, *off;
415 printf("\nLOAD = Reflects whether the unit definition was properly loaded.\n"
416 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
417 "SUB = The low-level unit activation state, values depend on unit type.\n");
419 printf("JOB = Pending job for the unit.\n");
421 on = ansi_highlight(true);
422 off = ansi_highlight(false);
424 on = ansi_highlight_red(true);
425 off = ansi_highlight_red(false);
429 printf("%s%u loaded units listed.%s\n"
430 "To show all installed unit files use 'systemctl list-unit-files'.\n",
433 printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
434 "To show all installed unit files use 'systemctl list-unit-files'.\n",
439 static int get_unit_list(
442 struct unit_info **unit_infos,
445 DBusMessageIter iter, sub;
453 r = bus_method_call_with_reply(
455 "org.freedesktop.systemd1",
456 "/org/freedesktop/systemd1",
457 "org.freedesktop.systemd1.Manager",
465 if (!dbus_message_iter_init(*reply, &iter) ||
466 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
467 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
468 log_error("Failed to parse reply.");
472 dbus_message_iter_recurse(&iter, &sub);
474 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
475 if (!GREEDY_REALLOC(*unit_infos, size, *c + 1))
478 bus_parse_unit_info(&sub, *unit_infos + *c);
481 dbus_message_iter_next(&sub);
487 static int list_units(DBusConnection *bus, char **args) {
488 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
489 _cleanup_free_ struct unit_info *unit_infos = NULL;
493 pager_open_if_enabled();
495 r = get_unit_list(bus, &reply, &unit_infos, &c);
499 qsort(unit_infos, c, sizeof(struct unit_info), compare_unit_info);
501 output_units_list(unit_infos, c);
506 static int get_triggered_units(
508 const char* unit_path,
511 const char *interface = "org.freedesktop.systemd1.Unit",
512 *triggers_property = "Triggers";
513 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
514 DBusMessageIter iter, sub;
517 r = bus_method_call_with_reply(bus,
518 "org.freedesktop.systemd1",
520 "org.freedesktop.DBus.Properties",
524 DBUS_TYPE_STRING, &interface,
525 DBUS_TYPE_STRING, &triggers_property,
530 if (!dbus_message_iter_init(reply, &iter) ||
531 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
532 log_error("Failed to parse reply.");
536 dbus_message_iter_recurse(&iter, &sub);
537 dbus_message_iter_recurse(&sub, &iter);
540 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
543 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
544 log_error("Failed to parse reply.");
548 dbus_message_iter_get_basic(&sub, &unit);
549 r = strv_extend(triggered, unit);
553 dbus_message_iter_next(&sub);
559 static int get_listening(DBusConnection *bus, const char* unit_path,
560 char*** listen, unsigned *c)
562 const char *interface = "org.freedesktop.systemd1.Socket",
563 *listen_property = "Listen";
564 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
565 DBusMessageIter iter, sub;
568 r = bus_method_call_with_reply(bus,
569 "org.freedesktop.systemd1",
571 "org.freedesktop.DBus.Properties",
575 DBUS_TYPE_STRING, &interface,
576 DBUS_TYPE_STRING, &listen_property,
581 if (!dbus_message_iter_init(reply, &iter) ||
582 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
583 log_error("Failed to parse reply.");
587 dbus_message_iter_recurse(&iter, &sub);
588 dbus_message_iter_recurse(&sub, &iter);
591 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
592 DBusMessageIter sub2;
593 const char *type, *path;
595 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
596 log_error("Failed to parse reply.");
600 dbus_message_iter_recurse(&sub, &sub2);
602 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
603 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0) {
604 r = strv_extend(listen, type);
608 r = strv_extend(listen, path);
615 dbus_message_iter_next(&sub);
627 /* Note: triggered is a list here, although it almost certainly
628 * will always be one unit. Nevertheless, dbus API allows for multiple
629 * values, so let's follow that.*/
632 /* The strv above is shared. free is set only in the first one. */
636 static int socket_info_compare(struct socket_info *a, struct socket_info *b) {
637 int o = strcmp(a->path, b->path);
639 o = strcmp(a->type, b->type);
643 static int output_sockets_list(struct socket_info *socket_infos, unsigned cs) {
644 struct socket_info *s;
645 unsigned pathlen = sizeof("LISTEN") - 1,
646 typelen = (sizeof("TYPE") - 1) * arg_show_types,
647 socklen = sizeof("UNIT") - 1,
648 servlen = sizeof("ACTIVATES") - 1;
649 const char *on, *off;
651 for (s = socket_infos; s < socket_infos + cs; s++) {
655 socklen = MAX(socklen, strlen(s->id));
657 typelen = MAX(typelen, strlen(s->type));
658 pathlen = MAX(pathlen, strlen(s->path));
660 STRV_FOREACH(a, s->triggered)
661 tmp += strlen(*a) + 2*(a != s->triggered);
662 servlen = MAX(servlen, tmp);
667 printf("%-*s %-*.*s%-*s %s\n",
669 typelen + arg_show_types, typelen + arg_show_types, "TYPE ",
673 for (s = socket_infos; s < socket_infos + cs; s++) {
677 printf("%-*s %-*s %-*s",
678 pathlen, s->path, typelen, s->type, socklen, s->id);
681 pathlen, s->path, socklen, s->id);
682 STRV_FOREACH(a, s->triggered)
684 a == s->triggered ? "" : ",", *a);
688 on = ansi_highlight(true);
689 off = ansi_highlight(false);
693 on = ansi_highlight_red(true);
694 off = ansi_highlight_red(false);
697 if (!arg_no_legend) {
698 printf("%s%u sockets listed.%s\n", on, cs, off);
700 printf("Pass --all to see loaded but inactive sockets, too.\n");
706 static int list_sockets(DBusConnection *bus, char **args) {
707 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
708 _cleanup_free_ struct unit_info *unit_infos = NULL;
709 struct socket_info *socket_infos = NULL;
710 const struct unit_info *u;
711 struct socket_info *s;
712 unsigned cu = 0, cs = 0;
716 pager_open_if_enabled();
718 r = get_unit_list(bus, &reply, &unit_infos, &cu);
722 for (u = unit_infos; u < unit_infos + cu; u++) {
724 _cleanup_strv_free_ char **listen = NULL, **triggered = NULL;
727 if (!output_show_unit(u))
730 if ((dot = strrchr(u->id, '.')) && !streq(dot+1, "socket"))
733 r = get_triggered_units(bus, u->unit_path, &triggered);
737 r = get_listening(bus, u->unit_path, &listen, &c);
741 if (!GREEDY_REALLOC(socket_infos, size, cs + c)) {
746 for (i = 0; i < c; i++)
747 socket_infos[cs + i] = (struct socket_info) {
750 .path = listen[i*2 + 1],
751 .triggered = triggered,
752 .own_triggered = i==0,
755 /* from this point on we will cleanup those socket_infos */
758 listen = triggered = NULL; /* avoid cleanup */
761 qsort(socket_infos, cs, sizeof(struct socket_info),
762 (__compar_fn_t) socket_info_compare);
764 output_sockets_list(socket_infos, cs);
767 assert(cs == 0 || socket_infos);
768 for (s = socket_infos; s < socket_infos + cs; s++) {
771 if (s->own_triggered)
772 strv_free(s->triggered);
779 static int compare_unit_file_list(const void *a, const void *b) {
781 const UnitFileList *u = a, *v = b;
783 d1 = strrchr(u->path, '.');
784 d2 = strrchr(v->path, '.');
789 r = strcasecmp(d1, d2);
794 return strcasecmp(path_get_file_name(u->path), path_get_file_name(v->path));
797 static bool output_show_unit_file(const UnitFileList *u) {
800 return !arg_types || ((dot = strrchr(u->path, '.')) && strv_find(arg_types, dot+1));
803 static void output_unit_file_list(const UnitFileList *units, unsigned c) {
804 unsigned max_id_len, id_cols, state_cols, n_shown = 0;
805 const UnitFileList *u;
807 max_id_len = sizeof("UNIT FILE")-1;
808 state_cols = sizeof("STATE")-1;
809 for (u = units; u < units + c; u++) {
810 if (!output_show_unit_file(u))
813 max_id_len = MAX(max_id_len, strlen(path_get_file_name(u->path)));
814 state_cols = MAX(state_cols, strlen(unit_file_state_to_string(u->state)));
819 id_cols = MIN(max_id_len, 25u);
820 basic_cols = 1 + id_cols + state_cols;
821 if (basic_cols < (unsigned) columns())
822 id_cols += MIN(columns() - basic_cols, max_id_len - id_cols);
824 id_cols = max_id_len;
827 printf("%-*s %-*s\n", id_cols, "UNIT FILE", state_cols, "STATE");
829 for (u = units; u < units + c; u++) {
830 _cleanup_free_ char *e = NULL;
831 const char *on, *off;
834 if (!output_show_unit_file(u))
839 if (u->state == UNIT_FILE_MASKED ||
840 u->state == UNIT_FILE_MASKED_RUNTIME ||
841 u->state == UNIT_FILE_DISABLED ||
842 u->state == UNIT_FILE_INVALID) {
843 on = ansi_highlight_red(true);
844 off = ansi_highlight_red(false);
845 } else if (u->state == UNIT_FILE_ENABLED) {
846 on = ansi_highlight_green(true);
847 off = ansi_highlight_green(false);
851 id = path_get_file_name(u->path);
853 e = arg_full ? NULL : ellipsize(id, id_cols, 33);
855 printf("%-*s %s%-*s%s\n",
857 on, state_cols, unit_file_state_to_string(u->state), off);
861 printf("\n%u unit files listed.\n", n_shown);
864 static int list_unit_files(DBusConnection *bus, char **args) {
865 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
866 _cleanup_free_ UnitFileList *units = NULL;
867 DBusMessageIter iter, sub, sub2;
868 unsigned c = 0, n_units = 0;
871 pager_open_if_enabled();
878 h = hashmap_new(string_hash_func, string_compare_func);
882 r = unit_file_get_list(arg_scope, arg_root, h);
884 unit_file_list_free(h);
885 log_error("Failed to get unit file list: %s", strerror(-r));
889 n_units = hashmap_size(h);
890 units = new(UnitFileList, n_units);
892 unit_file_list_free(h);
896 HASHMAP_FOREACH(u, h, i) {
897 memcpy(units + c++, u, sizeof(UnitFileList));
903 r = bus_method_call_with_reply(
905 "org.freedesktop.systemd1",
906 "/org/freedesktop/systemd1",
907 "org.freedesktop.systemd1.Manager",
915 if (!dbus_message_iter_init(reply, &iter) ||
916 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
917 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
918 log_error("Failed to parse reply.");
922 dbus_message_iter_recurse(&iter, &sub);
924 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
928 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT);
933 n_units = MAX(2*c, 16u);
934 w = realloc(units, sizeof(struct UnitFileList) * n_units);
943 dbus_message_iter_recurse(&sub, &sub2);
945 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->path, true) < 0 ||
946 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, false) < 0) {
947 log_error("Failed to parse reply.");
951 u->state = unit_file_state_from_string(state);
953 dbus_message_iter_next(&sub);
959 qsort(units, c, sizeof(UnitFileList), compare_unit_file_list);
960 output_unit_file_list(units, c);
966 static int list_dependencies_print(const char *name, int level, unsigned int branches, bool last) {
968 _cleanup_free_ char *n = NULL;
970 size_t max_len = MAX(columns(),20u);
973 for (i = level - 1; i >= 0; i--) {
975 if(len > max_len - 3 && !arg_full) {
976 printf("%s...\n",max_len % 2 ? "" : " ");
979 printf("%s", draw_special_char(branches & (1 << i) ? DRAW_TREE_VERT : DRAW_TREE_SPACE));
982 if(len > max_len - 3 && !arg_full) {
983 printf("%s...\n",max_len % 2 ? "" : " ");
986 printf("%s", draw_special_char(last ? DRAW_TREE_RIGHT : DRAW_TREE_BRANCH));
990 printf("%s\n", name);
994 n = ellipsize(name, max_len-len, 100);
1002 static int list_dependencies_get_dependencies(DBusConnection *bus, const char *name, char ***deps) {
1003 static const char *dependencies[] = {
1004 [DEPENDENCY_FORWARD] = "Requires\0"
1005 "RequiresOverridable\0"
1007 "RequisiteOverridable\0"
1009 [DEPENDENCY_REVERSE] = "RequiredBy\0"
1010 "RequiredByOverridable\0"
1013 [DEPENDENCY_AFTER] = "After\0",
1014 [DEPENDENCY_BEFORE] = "Before\0",
1017 _cleanup_free_ char *path;
1018 const char *interface = "org.freedesktop.systemd1.Unit";
1020 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1021 DBusMessageIter iter, sub, sub2, sub3;
1030 path = unit_dbus_path_from_name(name);
1036 r = bus_method_call_with_reply(
1038 "org.freedesktop.systemd1",
1040 "org.freedesktop.DBus.Properties",
1044 DBUS_TYPE_STRING, &interface,
1049 if (!dbus_message_iter_init(reply, &iter) ||
1050 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
1051 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
1052 log_error("Failed to parse reply.");
1057 dbus_message_iter_recurse(&iter, &sub);
1059 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1062 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_DICT_ENTRY);
1063 dbus_message_iter_recurse(&sub, &sub2);
1065 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &prop, true) < 0) {
1066 log_error("Failed to parse reply.");
1071 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
1072 log_error("Failed to parse reply.");
1077 dbus_message_iter_recurse(&sub2, &sub3);
1078 dbus_message_iter_next(&sub);
1080 assert(arg_dependency < ELEMENTSOF(dependencies));
1081 if (!nulstr_contains(dependencies[arg_dependency], prop))
1084 if (dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_ARRAY) {
1085 if (dbus_message_iter_get_element_type(&sub3) == DBUS_TYPE_STRING) {
1086 DBusMessageIter sub4;
1087 dbus_message_iter_recurse(&sub3, &sub4);
1089 while (dbus_message_iter_get_arg_type(&sub4) != DBUS_TYPE_INVALID) {
1092 assert(dbus_message_iter_get_arg_type(&sub4) == DBUS_TYPE_STRING);
1093 dbus_message_iter_get_basic(&sub4, &s);
1095 r = strv_extend(&ret, s);
1101 dbus_message_iter_next(&sub4);
1114 static int list_dependencies_compare(const void *_a, const void *_b) {
1115 const char **a = (const char**) _a, **b = (const char**) _b;
1116 if (unit_name_to_type(*a) == UNIT_TARGET && unit_name_to_type(*b) != UNIT_TARGET)
1118 if (unit_name_to_type(*a) != UNIT_TARGET && unit_name_to_type(*b) == UNIT_TARGET)
1120 return strcasecmp(*a, *b);
1123 static int list_dependencies_one(DBusConnection *bus, const char *name, int level, char ***units, unsigned int branches) {
1124 _cleanup_strv_free_ char **deps = NULL, **u;
1128 u = strv_append(*units, name);
1132 r = list_dependencies_get_dependencies(bus, name, &deps);
1136 qsort(deps, strv_length(deps), sizeof (char*), list_dependencies_compare);
1138 STRV_FOREACH(c, deps) {
1139 if (strv_contains(u, *c)) {
1141 r = list_dependencies_print("...", level + 1, (branches << 1) | (c[1] == NULL ? 0 : 1), 1);
1148 r = list_dependencies_print(*c, level, branches, c[1] == NULL);
1152 if (arg_all || unit_name_to_type(*c) == UNIT_TARGET) {
1153 r = list_dependencies_one(bus, *c, level + 1, &u, (branches << 1) | (c[1] == NULL ? 0 : 1));
1166 static int list_dependencies(DBusConnection *bus, char **args) {
1167 _cleanup_free_ char *unit = NULL;
1168 _cleanup_strv_free_ char **units = NULL;
1174 unit = unit_name_mangle(args[1]);
1179 u = SPECIAL_DEFAULT_TARGET;
1181 pager_open_if_enabled();
1185 return list_dependencies_one(bus, u, 0, &units, 0);
1188 static int get_default(DBusConnection *bus, char **args) {
1190 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1192 _cleanup_dbus_error_free_ DBusError error;
1194 dbus_error_init(&error);
1196 if (!bus || avoid_bus()) {
1197 r = unit_file_get_default(arg_scope, arg_root, &path);
1200 log_error("Operation failed: %s", strerror(-r));
1206 r = bus_method_call_with_reply(
1208 "org.freedesktop.systemd1",
1209 "/org/freedesktop/systemd1",
1210 "org.freedesktop.systemd1.Manager",
1217 log_error("Operation failed: %s", strerror(-r));
1221 if (!dbus_message_get_args(reply, &error,
1222 DBUS_TYPE_STRING, &path,
1223 DBUS_TYPE_INVALID)) {
1224 log_error("Failed to parse reply: %s", bus_error_message(&error));
1225 dbus_error_free(&error);
1231 printf("%s\n", path);
1234 if ((!bus || avoid_bus()) && path)
1243 char *name, *type, *state;
1246 static void list_jobs_print(struct job_info* jobs, size_t n) {
1249 const char *on, *off;
1250 bool shorten = false;
1252 assert(n == 0 || jobs);
1255 on = ansi_highlight_green(true);
1256 off = ansi_highlight_green(false);
1258 printf("%sNo jobs running.%s\n", on, off);
1262 pager_open_if_enabled();
1265 /* JOB UNIT TYPE STATE */
1266 unsigned l0 = 3, l1 = 4, l2 = 4, l3 = 5;
1268 for (i = 0, j = jobs; i < n; i++, j++) {
1269 assert(j->name && j->type && j->state);
1270 l0 = MAX(l0, DECIMAL_STR_WIDTH(j->id));
1271 l1 = MAX(l1, strlen(j->name));
1272 l2 = MAX(l2, strlen(j->type));
1273 l3 = MAX(l3, strlen(j->state));
1276 if (!arg_full && l0 + 1 + l1 + l2 + 1 + l3 > columns()) {
1277 l1 = MAX(33u, columns() - l0 - l2 - l3 - 3);
1282 printf("%*s %-*s %-*s %-*s\n",
1288 for (i = 0, j = jobs; i < n; i++, j++) {
1289 _cleanup_free_ char *e = NULL;
1291 if (streq(j->state, "running")) {
1292 on = ansi_highlight(true);
1293 off = ansi_highlight(false);
1297 e = shorten ? ellipsize(j->name, l1, 33) : NULL;
1298 printf("%*u %s%-*s%s %-*s %s%-*s%s\n",
1300 on, l1, e ? e : j->name, off,
1302 on, l3, j->state, off);
1306 on = ansi_highlight(true);
1307 off = ansi_highlight(false);
1310 printf("\n%s%zu jobs listed%s.\n", on, n, off);
1313 static int list_jobs(DBusConnection *bus, char **args) {
1314 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1315 DBusMessageIter iter, sub, sub2;
1317 struct job_info *jobs = NULL;
1318 size_t size = 0, used = 0;
1320 r = bus_method_call_with_reply(
1322 "org.freedesktop.systemd1",
1323 "/org/freedesktop/systemd1",
1324 "org.freedesktop.systemd1.Manager",
1332 if (!dbus_message_iter_init(reply, &iter) ||
1333 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
1334 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
1335 log_error("Failed to parse reply.");
1339 dbus_message_iter_recurse(&iter, &sub);
1341 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1342 const char *name, *type, *state, *job_path, *unit_path;
1345 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
1346 log_error("Failed to parse reply.");
1350 dbus_message_iter_recurse(&sub, &sub2);
1352 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &id, true) < 0 ||
1353 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
1354 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
1355 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, true) < 0 ||
1356 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &job_path, true) < 0 ||
1357 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, false) < 0) {
1358 log_error("Failed to parse reply.");
1363 if (!GREEDY_REALLOC(jobs, size, used + 1)) {
1368 jobs[used++] = (struct job_info) { id,
1372 if (!jobs[used-1].name || !jobs[used-1].type || !jobs[used-1].state) {
1377 dbus_message_iter_next(&sub);
1380 list_jobs_print(jobs, used);
1384 free(jobs[used].name);
1385 free(jobs[used].type);
1386 free(jobs[used].state);
1393 static int load_unit(DBusConnection *bus, char **args) {
1398 STRV_FOREACH(name, args+1) {
1399 _cleanup_free_ char *n = NULL;
1402 n = unit_name_mangle(*name);
1406 r = bus_method_call_with_reply(
1408 "org.freedesktop.systemd1",
1409 "/org/freedesktop/systemd1",
1410 "org.freedesktop.systemd1.Manager",
1414 DBUS_TYPE_STRING, &n,
1423 static int cancel_job(DBusConnection *bus, char **args) {
1428 if (strv_length(args) <= 1)
1429 return daemon_reload(bus, args);
1431 STRV_FOREACH(name, args+1) {
1435 r = safe_atou32(*name, &id);
1437 log_error("Failed to parse job id: %s", strerror(-r));
1441 r = bus_method_call_with_reply(
1443 "org.freedesktop.systemd1",
1444 "/org/freedesktop/systemd1",
1445 "org.freedesktop.systemd1.Manager",
1449 DBUS_TYPE_UINT32, &id,
1458 static int need_daemon_reload(DBusConnection *bus, const char *unit) {
1459 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1460 _cleanup_dbus_error_free_ DBusError error;
1461 dbus_bool_t b = FALSE;
1462 DBusMessageIter iter, sub;
1464 *interface = "org.freedesktop.systemd1.Unit",
1465 *property = "NeedDaemonReload",
1467 _cleanup_free_ char *n = NULL;
1470 dbus_error_init(&error);
1472 /* We ignore all errors here, since this is used to show a warning only */
1474 n = unit_name_mangle(unit);
1478 r = bus_method_call_with_reply(
1480 "org.freedesktop.systemd1",
1481 "/org/freedesktop/systemd1",
1482 "org.freedesktop.systemd1.Manager",
1486 DBUS_TYPE_STRING, &n,
1491 if (!dbus_message_get_args(reply, NULL,
1492 DBUS_TYPE_OBJECT_PATH, &path,
1496 dbus_message_unref(reply);
1499 r = bus_method_call_with_reply(
1501 "org.freedesktop.systemd1",
1503 "org.freedesktop.DBus.Properties",
1507 DBUS_TYPE_STRING, &interface,
1508 DBUS_TYPE_STRING, &property,
1513 if (!dbus_message_iter_init(reply, &iter) ||
1514 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
1517 dbus_message_iter_recurse(&iter, &sub);
1518 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_BOOLEAN)
1521 dbus_message_iter_get_basic(&sub, &b);
1525 typedef struct WaitData {
1532 static DBusHandlerResult wait_filter(DBusConnection *connection, DBusMessage *message, void *data) {
1533 _cleanup_dbus_error_free_ DBusError error;
1536 dbus_error_init(&error);
1542 log_debug("Got D-Bus request: %s.%s() on %s",
1543 dbus_message_get_interface(message),
1544 dbus_message_get_member(message),
1545 dbus_message_get_path(message));
1547 if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
1548 log_error("Warning! D-Bus connection terminated.");
1549 dbus_connection_close(connection);
1551 } else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
1553 const char *path, *result, *unit;
1555 if (dbus_message_get_args(message, &error,
1556 DBUS_TYPE_UINT32, &id,
1557 DBUS_TYPE_OBJECT_PATH, &path,
1558 DBUS_TYPE_STRING, &unit,
1559 DBUS_TYPE_STRING, &result,
1560 DBUS_TYPE_INVALID)) {
1562 free(set_remove(d->set, (char*) path));
1564 if (!isempty(result))
1565 d->result = strdup(result);
1568 d->name = strdup(unit);
1570 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1573 dbus_error_free(&error);
1574 if (dbus_message_get_args(message, &error,
1575 DBUS_TYPE_UINT32, &id,
1576 DBUS_TYPE_OBJECT_PATH, &path,
1577 DBUS_TYPE_STRING, &result,
1578 DBUS_TYPE_INVALID)) {
1579 /* Compatibility with older systemd versions <
1580 * 183 during upgrades. This should be dropped
1582 free(set_remove(d->set, (char*) path));
1585 d->result = strdup(result);
1587 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1591 log_error("Failed to parse message: %s", bus_error_message(&error));
1594 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1597 static int enable_wait_for_jobs(DBusConnection *bus) {
1605 dbus_error_init(&error);
1606 dbus_bus_add_match(bus,
1608 "sender='org.freedesktop.systemd1',"
1609 "interface='org.freedesktop.systemd1.Manager',"
1610 "member='JobRemoved',"
1611 "path='/org/freedesktop/systemd1'",
1614 if (dbus_error_is_set(&error)) {
1615 log_error("Failed to add match: %s", bus_error_message(&error));
1616 dbus_error_free(&error);
1620 /* This is slightly dirty, since we don't undo the match registrations. */
1624 static int wait_for_jobs(DBusConnection *bus, Set *s) {
1626 WaitData d = { .set = s };
1631 if (!dbus_connection_add_filter(bus, wait_filter, &d, NULL))
1634 while (!set_isempty(s)) {
1636 if (!dbus_connection_read_write_dispatch(bus, -1)) {
1637 log_error("Disconnected from bus.");
1638 return -ECONNREFUSED;
1645 if (streq(d.result, "timeout"))
1646 log_error("Job for %s timed out.", strna(d.name));
1647 else if (streq(d.result, "canceled"))
1648 log_error("Job for %s canceled.", strna(d.name));
1649 else if (streq(d.result, "dependency"))
1650 log_error("A dependency job for %s failed. See 'journalctl -xn' for details.", strna(d.name));
1651 else if (!streq(d.result, "done") && !streq(d.result, "skipped"))
1652 log_error("Job for %s failed. See 'systemctl status %s' and 'journalctl -xn' for details.", strna(d.name), strna(d.name));
1655 if (streq_ptr(d.result, "timeout"))
1657 else if (streq_ptr(d.result, "canceled"))
1659 else if (!streq_ptr(d.result, "done") && !streq_ptr(d.result, "skipped"))
1670 dbus_connection_remove_filter(bus, wait_filter, &d);
1674 static int check_one_unit(DBusConnection *bus, const char *name, char **check_states, bool quiet) {
1675 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1676 _cleanup_free_ char *n = NULL;
1677 DBusMessageIter iter, sub;
1679 *interface = "org.freedesktop.systemd1.Unit",
1680 *property = "ActiveState";
1681 const char *state, *path;
1687 dbus_error_init(&error);
1689 n = unit_name_mangle(name);
1693 r = bus_method_call_with_reply (
1695 "org.freedesktop.systemd1",
1696 "/org/freedesktop/systemd1",
1697 "org.freedesktop.systemd1.Manager",
1701 DBUS_TYPE_STRING, &n,
1704 dbus_error_free(&error);
1711 if (!dbus_message_get_args(reply, NULL,
1712 DBUS_TYPE_OBJECT_PATH, &path,
1713 DBUS_TYPE_INVALID)) {
1714 log_error("Failed to parse reply.");
1718 dbus_message_unref(reply);
1721 r = bus_method_call_with_reply(
1723 "org.freedesktop.systemd1",
1725 "org.freedesktop.DBus.Properties",
1729 DBUS_TYPE_STRING, &interface,
1730 DBUS_TYPE_STRING, &property,
1738 if (!dbus_message_iter_init(reply, &iter) ||
1739 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1740 log_error("Failed to parse reply.");
1744 dbus_message_iter_recurse(&iter, &sub);
1746 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1747 log_error("Failed to parse reply.");
1751 dbus_message_iter_get_basic(&sub, &state);
1756 return strv_find(check_states, state) ? 1 : 0;
1759 static void check_triggering_units(
1760 DBusConnection *bus,
1761 const char *unit_name) {
1763 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1764 DBusMessageIter iter, sub;
1765 const char *interface = "org.freedesktop.systemd1.Unit",
1766 *load_state_property = "LoadState",
1767 *triggered_by_property = "TriggeredBy",
1769 _cleanup_free_ char *unit_path = NULL, *n = NULL;
1770 bool print_warning_label = true;
1773 n = unit_name_mangle(unit_name);
1779 unit_path = unit_dbus_path_from_name(n);
1785 r = bus_method_call_with_reply(
1787 "org.freedesktop.systemd1",
1789 "org.freedesktop.DBus.Properties",
1793 DBUS_TYPE_STRING, &interface,
1794 DBUS_TYPE_STRING, &load_state_property,
1799 if (!dbus_message_iter_init(reply, &iter) ||
1800 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1801 log_error("Failed to parse reply.");
1805 dbus_message_iter_recurse(&iter, &sub);
1807 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1808 log_error("Failed to parse reply.");
1812 dbus_message_iter_get_basic(&sub, &state);
1814 if (streq(state, "masked"))
1817 dbus_message_unref(reply);
1820 r = bus_method_call_with_reply(
1822 "org.freedesktop.systemd1",
1824 "org.freedesktop.DBus.Properties",
1828 DBUS_TYPE_STRING, &interface,
1829 DBUS_TYPE_STRING, &triggered_by_property,
1834 if (!dbus_message_iter_init(reply, &iter) ||
1835 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1836 log_error("Failed to parse reply.");
1840 dbus_message_iter_recurse(&iter, &sub);
1841 dbus_message_iter_recurse(&sub, &iter);
1844 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1845 const char * const check_states[] = {
1850 const char *service_trigger;
1852 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1853 log_error("Failed to parse reply.");
1857 dbus_message_iter_get_basic(&sub, &service_trigger);
1859 r = check_one_unit(bus, service_trigger, (char**) check_states, true);
1863 if (print_warning_label) {
1864 log_warning("Warning: Stopping %s, but it can still be activated by:", unit_name);
1865 print_warning_label = false;
1868 log_warning(" %s", service_trigger);
1871 dbus_message_iter_next(&sub);
1875 static int start_unit_one(
1876 DBusConnection *bus,
1883 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1884 _cleanup_free_ char *n;
1893 n = unit_name_mangle(name);
1897 r = bus_method_call_with_reply(
1899 "org.freedesktop.systemd1",
1900 "/org/freedesktop/systemd1",
1901 "org.freedesktop.systemd1.Manager",
1905 DBUS_TYPE_STRING, &n,
1906 DBUS_TYPE_STRING, &mode,
1909 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
1910 /* There's always a fallback possible for
1911 * legacy actions. */
1914 log_error("Failed to issue method call: %s", bus_error_message(error));
1919 if (!dbus_message_get_args(reply, error,
1920 DBUS_TYPE_OBJECT_PATH, &path,
1921 DBUS_TYPE_INVALID)) {
1922 log_error("Failed to parse reply: %s", bus_error_message(error));
1926 if (need_daemon_reload(bus, n) > 0)
1927 log_warning("Warning: Unit file of %s changed on disk, 'systemctl %sdaemon-reload' recommended.",
1928 n, arg_scope == UNIT_FILE_SYSTEM ? "" : "--user ");
1937 r = set_consume(s, p);
1939 log_error("Failed to add path to set.");
1947 static const struct {
1951 } action_table[_ACTION_MAX] = {
1952 [ACTION_HALT] = { SPECIAL_HALT_TARGET, "halt", "replace-irreversibly" },
1953 [ACTION_POWEROFF] = { SPECIAL_POWEROFF_TARGET, "poweroff", "replace-irreversibly" },
1954 [ACTION_REBOOT] = { SPECIAL_REBOOT_TARGET, "reboot", "replace-irreversibly" },
1955 [ACTION_KEXEC] = { SPECIAL_KEXEC_TARGET, "kexec", "replace-irreversibly" },
1956 [ACTION_RUNLEVEL2] = { SPECIAL_RUNLEVEL2_TARGET, NULL, "isolate" },
1957 [ACTION_RUNLEVEL3] = { SPECIAL_RUNLEVEL3_TARGET, NULL, "isolate" },
1958 [ACTION_RUNLEVEL4] = { SPECIAL_RUNLEVEL4_TARGET, NULL, "isolate" },
1959 [ACTION_RUNLEVEL5] = { SPECIAL_RUNLEVEL5_TARGET, NULL, "isolate" },
1960 [ACTION_RESCUE] = { SPECIAL_RESCUE_TARGET, "rescue", "isolate" },
1961 [ACTION_EMERGENCY] = { SPECIAL_EMERGENCY_TARGET, "emergency", "isolate" },
1962 [ACTION_DEFAULT] = { SPECIAL_DEFAULT_TARGET, "default", "isolate" },
1963 [ACTION_EXIT] = { SPECIAL_EXIT_TARGET, "exit", "replace-irreversibly" },
1964 [ACTION_SUSPEND] = { SPECIAL_SUSPEND_TARGET, "suspend", "replace-irreversibly" },
1965 [ACTION_HIBERNATE] = { SPECIAL_HIBERNATE_TARGET, "hibernate", "replace-irreversibly" },
1966 [ACTION_HYBRID_SLEEP] = { SPECIAL_HYBRID_SLEEP_TARGET, "hybrid-sleep", "replace-irreversibly" },
1969 static enum action verb_to_action(const char *verb) {
1972 for (i = ACTION_INVALID; i < _ACTION_MAX; i++)
1973 if (action_table[i].verb && streq(verb, action_table[i].verb))
1975 return ACTION_INVALID;
1978 static int start_unit(DBusConnection *bus, char **args) {
1981 const char *method, *mode, *one_name;
1982 _cleanup_set_free_free_ Set *s = NULL;
1983 _cleanup_dbus_error_free_ DBusError error;
1986 dbus_error_init(&error);
1990 ask_password_agent_open_if_enabled();
1992 if (arg_action == ACTION_SYSTEMCTL) {
1995 streq(args[0], "stop") ||
1996 streq(args[0], "condstop") ? "StopUnit" :
1997 streq(args[0], "reload") ? "ReloadUnit" :
1998 streq(args[0], "restart") ? "RestartUnit" :
2000 streq(args[0], "try-restart") ||
2001 streq(args[0], "condrestart") ? "TryRestartUnit" :
2003 streq(args[0], "reload-or-restart") ? "ReloadOrRestartUnit" :
2005 streq(args[0], "reload-or-try-restart") ||
2006 streq(args[0], "condreload") ||
2008 streq(args[0], "force-reload") ? "ReloadOrTryRestartUnit" :
2010 action = verb_to_action(args[0]);
2012 mode = streq(args[0], "isolate") ? "isolate" :
2013 action_table[action].mode ?: arg_job_mode;
2015 one_name = action_table[action].target;
2018 assert(arg_action < ELEMENTSOF(action_table));
2019 assert(action_table[arg_action].target);
2021 method = "StartUnit";
2023 mode = action_table[arg_action].mode;
2024 one_name = action_table[arg_action].target;
2027 if (!arg_no_block) {
2028 ret = enable_wait_for_jobs(bus);
2030 log_error("Could not watch jobs: %s", strerror(-ret));
2034 s = set_new(string_hash_func, string_compare_func);
2040 ret = start_unit_one(bus, method, one_name, mode, &error, s);
2042 ret = translate_bus_error_to_exit_status(ret, &error);
2044 STRV_FOREACH(name, args+1) {
2045 r = start_unit_one(bus, method, *name, mode, &error, s);
2047 ret = translate_bus_error_to_exit_status(r, &error);
2048 dbus_error_free(&error);
2053 if (!arg_no_block) {
2054 r = wait_for_jobs(bus, s);
2058 /* When stopping units, warn if they can still be triggered by
2059 * another active unit (socket, path, timer) */
2060 if (!arg_quiet && streq(method, "StopUnit")) {
2062 check_triggering_units(bus, one_name);
2064 STRV_FOREACH(name, args+1)
2065 check_triggering_units(bus, *name);
2072 /* Ask systemd-logind, which might grant access to unprivileged users
2073 * through PolicyKit */
2074 static int reboot_with_logind(DBusConnection *bus, enum action a) {
2077 dbus_bool_t interactive = true;
2082 polkit_agent_open_if_enabled();
2090 case ACTION_POWEROFF:
2091 method = "PowerOff";
2094 case ACTION_SUSPEND:
2098 case ACTION_HIBERNATE:
2099 method = "Hibernate";
2102 case ACTION_HYBRID_SLEEP:
2103 method = "HybridSleep";
2110 return bus_method_call_with_reply(
2112 "org.freedesktop.login1",
2113 "/org/freedesktop/login1",
2114 "org.freedesktop.login1.Manager",
2118 DBUS_TYPE_BOOLEAN, &interactive,
2125 static int check_inhibitors(DBusConnection *bus, enum action a) {
2127 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
2128 DBusMessageIter iter, sub, sub2;
2131 _cleanup_strv_free_ char **sessions = NULL;
2137 if (arg_ignore_inhibitors || arg_force > 0)
2149 r = bus_method_call_with_reply(
2151 "org.freedesktop.login1",
2152 "/org/freedesktop/login1",
2153 "org.freedesktop.login1.Manager",
2159 /* If logind is not around, then there are no inhibitors... */
2162 if (!dbus_message_iter_init(reply, &iter) ||
2163 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
2164 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
2165 log_error("Failed to parse reply.");
2169 dbus_message_iter_recurse(&iter, &sub);
2170 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
2171 const char *what, *who, *why, *mode;
2173 _cleanup_strv_free_ char **sv = NULL;
2174 _cleanup_free_ char *comm = NULL, *user = NULL;
2176 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
2177 log_error("Failed to parse reply.");
2181 dbus_message_iter_recurse(&sub, &sub2);
2183 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &what, true) < 0 ||
2184 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &who, true) < 0 ||
2185 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &why, true) < 0 ||
2186 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &mode, true) < 0 ||
2187 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &uid, true) < 0 ||
2188 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, false) < 0) {
2189 log_error("Failed to parse reply.");
2193 if (!streq(mode, "block"))
2196 sv = strv_split(what, ":");
2200 if (!strv_contains(sv,
2202 a == ACTION_POWEROFF ||
2203 a == ACTION_REBOOT ||
2204 a == ACTION_KEXEC ? "shutdown" : "sleep"))
2207 get_process_comm(pid, &comm);
2208 user = uid_to_name(uid);
2209 log_warning("Operation inhibited by \"%s\" (PID %lu \"%s\", user %s), reason is \"%s\".",
2210 who, (unsigned long) pid, strna(comm), strna(user), why);
2214 dbus_message_iter_next(&sub);
2217 dbus_message_iter_recurse(&iter, &sub);
2219 /* Check for current sessions */
2220 sd_get_sessions(&sessions);
2221 STRV_FOREACH(s, sessions) {
2223 _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL;
2225 if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid())
2228 if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
2231 if (sd_session_get_type(*s, &type) < 0 || (!streq(type, "x11") && !streq(type, "tty")))
2234 sd_session_get_tty(*s, &tty);
2235 sd_session_get_seat(*s, &seat);
2236 sd_session_get_service(*s, &service);
2237 user = uid_to_name(uid);
2239 log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty);
2246 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
2247 action_table[a].verb);
2255 static int start_special(DBusConnection *bus, char **args) {
2261 a = verb_to_action(args[0]);
2263 r = check_inhibitors(bus, a);
2267 if (arg_force >= 2 && geteuid() != 0) {
2268 log_error("Must be root.");
2272 if (arg_force >= 2 &&
2273 (a == ACTION_HALT ||
2274 a == ACTION_POWEROFF ||
2275 a == ACTION_REBOOT))
2278 if (arg_force >= 1 &&
2279 (a == ACTION_HALT ||
2280 a == ACTION_POWEROFF ||
2281 a == ACTION_REBOOT ||
2282 a == ACTION_KEXEC ||
2284 return daemon_reload(bus, args);
2286 /* first try logind, to allow authentication with polkit */
2287 if (geteuid() != 0 &&
2288 (a == ACTION_POWEROFF ||
2289 a == ACTION_REBOOT ||
2290 a == ACTION_SUSPEND ||
2291 a == ACTION_HIBERNATE ||
2292 a == ACTION_HYBRID_SLEEP)) {
2293 r = reboot_with_logind(bus, a);
2298 r = start_unit(bus, args);
2299 if (r == EXIT_SUCCESS)
2305 static int check_unit_active(DBusConnection *bus, char **args) {
2306 const char * const check_states[] = {
2313 int r = 3; /* According to LSB: "program is not running" */
2318 STRV_FOREACH(name, args+1) {
2321 state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
2331 static int check_unit_failed(DBusConnection *bus, char **args) {
2332 const char * const check_states[] = {
2343 STRV_FOREACH(name, args+1) {
2346 state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
2356 static int kill_unit(DBusConnection *bus, char **args) {
2364 arg_kill_who = "all";
2366 STRV_FOREACH(name, args+1) {
2367 _cleanup_free_ char *n = NULL;
2369 n = unit_name_mangle(*name);
2373 r = bus_method_call_with_reply(
2375 "org.freedesktop.systemd1",
2376 "/org/freedesktop/systemd1",
2377 "org.freedesktop.systemd1.Manager",
2381 DBUS_TYPE_STRING, &n,
2382 DBUS_TYPE_STRING, &arg_kill_who,
2383 DBUS_TYPE_INT32, &arg_signal,
2391 typedef struct ExecStatusInfo {
2399 usec_t start_timestamp;
2400 usec_t exit_timestamp;
2405 LIST_FIELDS(struct ExecStatusInfo, exec);
2408 static void exec_status_info_free(ExecStatusInfo *i) {
2417 static int exec_status_info_deserialize(DBusMessageIter *sub, ExecStatusInfo *i) {
2418 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
2419 DBusMessageIter sub2, sub3;
2423 int32_t code, status;
2429 if (dbus_message_iter_get_arg_type(sub) != DBUS_TYPE_STRUCT)
2432 dbus_message_iter_recurse(sub, &sub2);
2434 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0)
2437 i->path = strdup(path);
2441 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_ARRAY ||
2442 dbus_message_iter_get_element_type(&sub2) != DBUS_TYPE_STRING)
2446 dbus_message_iter_recurse(&sub2, &sub3);
2447 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2448 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2449 dbus_message_iter_next(&sub3);
2453 i->argv = new0(char*, n+1);
2458 dbus_message_iter_recurse(&sub2, &sub3);
2459 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2462 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2463 dbus_message_iter_get_basic(&sub3, &s);
2464 dbus_message_iter_next(&sub3);
2466 i->argv[n] = strdup(s);
2473 if (!dbus_message_iter_next(&sub2) ||
2474 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, true) < 0 ||
2475 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp, true) < 0 ||
2476 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp_monotonic, true) < 0 ||
2477 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp, true) < 0 ||
2478 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp_monotonic, true) < 0 ||
2479 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, true) < 0 ||
2480 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &code, true) < 0 ||
2481 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &status, false) < 0)
2485 i->start_timestamp = (usec_t) start_timestamp;
2486 i->exit_timestamp = (usec_t) exit_timestamp;
2487 i->pid = (pid_t) pid;
2494 typedef struct UnitStatusInfo {
2496 const char *load_state;
2497 const char *active_state;
2498 const char *sub_state;
2499 const char *unit_file_state;
2501 const char *description;
2502 const char *following;
2504 char **documentation;
2506 const char *fragment_path;
2507 const char *source_path;
2508 const char *control_group;
2510 char **dropin_paths;
2512 const char *load_error;
2515 usec_t inactive_exit_timestamp;
2516 usec_t inactive_exit_timestamp_monotonic;
2517 usec_t active_enter_timestamp;
2518 usec_t active_exit_timestamp;
2519 usec_t inactive_enter_timestamp;
2521 bool need_daemon_reload;
2526 const char *status_text;
2527 const char *pid_file;
2530 usec_t start_timestamp;
2531 usec_t exit_timestamp;
2533 int exit_code, exit_status;
2535 usec_t condition_timestamp;
2536 bool condition_result;
2537 bool failed_condition_trigger;
2538 bool failed_condition_negate;
2539 const char *failed_condition;
2540 const char *failed_condition_param;
2543 unsigned n_accepted;
2544 unsigned n_connections;
2547 /* Pairs of type, path */
2551 const char *sysfs_path;
2553 /* Mount, Automount */
2559 LIST_HEAD(ExecStatusInfo, exec);
2562 static void print_status_info(UnitStatusInfo *i) {
2564 const char *on, *off, *ss;
2566 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
2567 char since2[FORMAT_TIMESTAMP_MAX], *s2;
2570 arg_all * OUTPUT_SHOW_ALL |
2571 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
2572 on_tty() * OUTPUT_COLOR |
2573 !arg_quiet * OUTPUT_WARN_CUTOFF |
2574 arg_full * OUTPUT_FULL_WIDTH;
2579 /* This shows pretty information about a unit. See
2580 * print_property() for a low-level property printer */
2582 printf("%s", strna(i->id));
2584 if (i->description && !streq_ptr(i->id, i->description))
2585 printf(" - %s", i->description);
2590 printf(" Follow: unit currently follows state of %s\n", i->following);
2592 if (streq_ptr(i->load_state, "error")) {
2593 on = ansi_highlight_red(true);
2594 off = ansi_highlight_red(false);
2598 path = i->source_path ? i->source_path : i->fragment_path;
2601 printf(" Loaded: %s%s%s (Reason: %s)\n",
2602 on, strna(i->load_state), off, i->load_error);
2603 else if (path && i->unit_file_state)
2604 printf(" Loaded: %s%s%s (%s; %s)\n",
2605 on, strna(i->load_state), off, path, i->unit_file_state);
2607 printf(" Loaded: %s%s%s (%s)\n",
2608 on, strna(i->load_state), off, path);
2610 printf(" Loaded: %s%s%s\n",
2611 on, strna(i->load_state), off);
2613 if (!strv_isempty(i->dropin_paths)) {
2618 STRV_FOREACH(dropin, i->dropin_paths) {
2619 if (! dir || last) {
2620 printf(dir ? " " : " Drop-In: ");
2624 if (path_get_parent(*dropin, &dir) < 0) {
2629 printf("%s\n %s", dir,
2630 draw_special_char(DRAW_TREE_RIGHT));
2633 last = ! (*(dropin + 1) && startswith(*(dropin + 1), dir));
2635 printf("%s%s", path_get_file_name(*dropin), last ? "\n" : ", ");
2641 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
2643 if (streq_ptr(i->active_state, "failed")) {
2644 on = ansi_highlight_red(true);
2645 off = ansi_highlight_red(false);
2646 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
2647 on = ansi_highlight_green(true);
2648 off = ansi_highlight_green(false);
2653 printf(" Active: %s%s (%s)%s",
2654 on, strna(i->active_state), ss, off);
2656 printf(" Active: %s%s%s",
2657 on, strna(i->active_state), off);
2659 if (!isempty(i->result) && !streq(i->result, "success"))
2660 printf(" (Result: %s)", i->result);
2662 timestamp = (streq_ptr(i->active_state, "active") ||
2663 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
2664 (streq_ptr(i->active_state, "inactive") ||
2665 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
2666 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
2667 i->active_exit_timestamp;
2669 s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
2670 s2 = format_timestamp(since2, sizeof(since2), timestamp);
2673 printf(" since %s; %s\n", s2, s1);
2675 printf(" since %s\n", s2);
2679 if (!i->condition_result && i->condition_timestamp > 0) {
2680 s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
2681 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
2683 printf(" start condition failed at %s%s%s\n",
2684 s2, s1 ? "; " : "", s1 ? s1 : "");
2685 if (i->failed_condition_trigger)
2686 printf(" none of the trigger conditions were met\n");
2687 else if (i->failed_condition)
2688 printf(" %s=%s%s was not met\n",
2689 i->failed_condition,
2690 i->failed_condition_negate ? "!" : "",
2691 i->failed_condition_param);
2695 printf(" Device: %s\n", i->sysfs_path);
2697 printf(" Where: %s\n", i->where);
2699 printf(" What: %s\n", i->what);
2701 STRV_FOREACH(t, i->documentation)
2702 printf(" %*s %s\n", 9, t == i->documentation ? "Docs:" : "", *t);
2704 STRV_FOREACH_PAIR(t, t2, i->listen)
2705 printf(" %*s %s (%s)\n", 9, t == i->listen ? "Listen:" : "", *t2, *t);
2708 printf(" Accepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
2710 LIST_FOREACH(exec, p, i->exec) {
2711 _cleanup_free_ char *argv = NULL;
2714 /* Only show exited processes here */
2718 argv = strv_join(p->argv, " ");
2719 printf(" Process: %u %s=%s ", p->pid, p->name, strna(argv));
2721 good = is_clean_exit_lsb(p->code, p->status, NULL);
2723 on = ansi_highlight_red(true);
2724 off = ansi_highlight_red(false);
2728 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
2730 if (p->code == CLD_EXITED) {
2733 printf("status=%i", p->status);
2735 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
2740 printf("signal=%s", signal_to_string(p->status));
2742 printf(")%s\n", off);
2744 if (i->main_pid == p->pid &&
2745 i->start_timestamp == p->start_timestamp &&
2746 i->exit_timestamp == p->start_timestamp)
2747 /* Let's not show this twice */
2750 if (p->pid == i->control_pid)
2754 if (i->main_pid > 0 || i->control_pid > 0) {
2755 if (i->main_pid > 0) {
2756 printf(" Main PID: %u", (unsigned) i->main_pid);
2759 _cleanup_free_ char *comm = NULL;
2760 get_process_comm(i->main_pid, &comm);
2762 printf(" (%s)", comm);
2763 } else if (i->exit_code > 0) {
2764 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
2766 if (i->exit_code == CLD_EXITED) {
2769 printf("status=%i", i->exit_status);
2771 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
2776 printf("signal=%s", signal_to_string(i->exit_status));
2780 if (i->control_pid > 0)
2784 if (i->control_pid > 0) {
2785 _cleanup_free_ char *c = NULL;
2787 printf(" %8s: %u", i->main_pid ? "" : " Control", (unsigned) i->control_pid);
2789 get_process_comm(i->control_pid, &c);
2798 printf(" Status: \"%s\"\n", i->status_text);
2800 if (i->control_group &&
2801 (i->main_pid > 0 || i->control_pid > 0 || cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, i->control_group, false) == 0)) {
2804 printf(" CGroup: %s\n", i->control_group);
2806 if (arg_transport != TRANSPORT_SSH) {
2809 char prefix[] = " ";
2812 if (c > sizeof(prefix) - 1)
2813 c -= sizeof(prefix) - 1;
2817 if (i->main_pid > 0)
2818 extra[k++] = i->main_pid;
2820 if (i->control_pid > 0)
2821 extra[k++] = i->control_pid;
2823 show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, i->control_group, prefix,
2824 c, false, extra, k, flags);
2828 if (i->id && arg_transport != TRANSPORT_SSH) {
2830 show_journal_by_unit(stdout,
2834 i->inactive_exit_timestamp_monotonic,
2838 arg_scope == UNIT_FILE_SYSTEM);
2841 if (i->need_daemon_reload)
2842 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %sdaemon-reload' recommended.\n",
2843 ansi_highlight_red(true),
2844 ansi_highlight_red(false),
2845 arg_scope == UNIT_FILE_SYSTEM ? "" : "--user ");
2848 static void show_unit_help(UnitStatusInfo *i) {
2853 if (!i->documentation) {
2854 log_info("Documentation for %s not known.", i->id);
2858 STRV_FOREACH(p, i->documentation) {
2860 if (startswith(*p, "man:")) {
2863 _cleanup_free_ char *page = NULL, *section = NULL;
2864 const char *args[4] = { "man", NULL, NULL, NULL };
2869 if ((*p)[k-1] == ')')
2870 e = strrchr(*p, '(');
2873 page = strndup((*p) + 4, e - *p - 4);
2874 section = strndup(e + 1, *p + k - e - 2);
2875 if (!page || !section) {
2887 log_error("Failed to fork: %m");
2893 execvp(args[0], (char**) args);
2894 log_error("Failed to execute man: %m");
2895 _exit(EXIT_FAILURE);
2898 wait_for_terminate(pid, NULL);
2900 log_info("Can't show: %s", *p);
2904 static int status_property(const char *name, DBusMessageIter *iter, UnitStatusInfo *i) {
2910 switch (dbus_message_iter_get_arg_type(iter)) {
2912 case DBUS_TYPE_STRING: {
2915 dbus_message_iter_get_basic(iter, &s);
2918 if (streq(name, "Id"))
2920 else if (streq(name, "LoadState"))
2922 else if (streq(name, "ActiveState"))
2923 i->active_state = s;
2924 else if (streq(name, "SubState"))
2926 else if (streq(name, "Description"))
2928 else if (streq(name, "FragmentPath"))
2929 i->fragment_path = s;
2930 else if (streq(name, "SourcePath"))
2933 else if (streq(name, "DefaultControlGroup")) {
2935 e = startswith(s, SYSTEMD_CGROUP_CONTROLLER ":");
2937 i->control_group = e;
2940 else if (streq(name, "ControlGroup"))
2941 i->control_group = s;
2942 else if (streq(name, "StatusText"))
2944 else if (streq(name, "PIDFile"))
2946 else if (streq(name, "SysFSPath"))
2948 else if (streq(name, "Where"))
2950 else if (streq(name, "What"))
2952 else if (streq(name, "Following"))
2954 else if (streq(name, "UnitFileState"))
2955 i->unit_file_state = s;
2956 else if (streq(name, "Result"))
2963 case DBUS_TYPE_BOOLEAN: {
2966 dbus_message_iter_get_basic(iter, &b);
2968 if (streq(name, "Accept"))
2970 else if (streq(name, "NeedDaemonReload"))
2971 i->need_daemon_reload = b;
2972 else if (streq(name, "ConditionResult"))
2973 i->condition_result = b;
2978 case DBUS_TYPE_UINT32: {
2981 dbus_message_iter_get_basic(iter, &u);
2983 if (streq(name, "MainPID")) {
2985 i->main_pid = (pid_t) u;
2988 } else if (streq(name, "ControlPID"))
2989 i->control_pid = (pid_t) u;
2990 else if (streq(name, "ExecMainPID")) {
2992 i->main_pid = (pid_t) u;
2993 } else if (streq(name, "NAccepted"))
2995 else if (streq(name, "NConnections"))
2996 i->n_connections = u;
3001 case DBUS_TYPE_INT32: {
3004 dbus_message_iter_get_basic(iter, &j);
3006 if (streq(name, "ExecMainCode"))
3007 i->exit_code = (int) j;
3008 else if (streq(name, "ExecMainStatus"))
3009 i->exit_status = (int) j;
3014 case DBUS_TYPE_UINT64: {
3017 dbus_message_iter_get_basic(iter, &u);
3019 if (streq(name, "ExecMainStartTimestamp"))
3020 i->start_timestamp = (usec_t) u;
3021 else if (streq(name, "ExecMainExitTimestamp"))
3022 i->exit_timestamp = (usec_t) u;
3023 else if (streq(name, "ActiveEnterTimestamp"))
3024 i->active_enter_timestamp = (usec_t) u;
3025 else if (streq(name, "InactiveEnterTimestamp"))
3026 i->inactive_enter_timestamp = (usec_t) u;
3027 else if (streq(name, "InactiveExitTimestamp"))
3028 i->inactive_exit_timestamp = (usec_t) u;
3029 else if (streq(name, "InactiveExitTimestampMonotonic"))
3030 i->inactive_exit_timestamp_monotonic = (usec_t) u;
3031 else if (streq(name, "ActiveExitTimestamp"))
3032 i->active_exit_timestamp = (usec_t) u;
3033 else if (streq(name, "ConditionTimestamp"))
3034 i->condition_timestamp = (usec_t) u;
3039 case DBUS_TYPE_ARRAY: {
3041 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
3042 startswith(name, "Exec")) {
3043 DBusMessageIter sub;
3045 dbus_message_iter_recurse(iter, &sub);
3046 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3047 ExecStatusInfo *info;
3050 info = new0(ExecStatusInfo, 1);
3054 info->name = strdup(name);
3060 r = exec_status_info_deserialize(&sub, info);
3066 LIST_PREPEND(ExecStatusInfo, exec, i->exec, info);
3068 dbus_message_iter_next(&sub);
3071 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
3072 streq(name, "Listen")) {
3073 DBusMessageIter sub, sub2;
3075 dbus_message_iter_recurse(iter, &sub);
3076 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3077 const char *type, *path;
3079 dbus_message_iter_recurse(&sub, &sub2);
3081 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
3082 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0) {
3085 r = strv_extend(&i->listen, type);
3088 r = strv_extend(&i->listen, path);
3093 dbus_message_iter_next(&sub);
3098 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
3099 streq(name, "DropInPaths")) {
3100 int r = bus_parse_strv_iter(iter, &i->dropin_paths);
3104 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
3105 streq(name, "Documentation")) {
3107 DBusMessageIter sub;
3109 dbus_message_iter_recurse(iter, &sub);
3110 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING) {
3114 dbus_message_iter_get_basic(&sub, &s);
3116 r = strv_extend(&i->documentation, s);
3120 dbus_message_iter_next(&sub);
3123 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
3124 streq(name, "Conditions")) {
3125 DBusMessageIter sub, sub2;
3127 dbus_message_iter_recurse(iter, &sub);
3128 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3129 const char *cond, *param;
3130 dbus_bool_t trigger, negate;
3133 dbus_message_iter_recurse(&sub, &sub2);
3136 if(bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &cond, true) >= 0 &&
3137 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &trigger, true) >= 0 &&
3138 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &negate, true) >= 0 &&
3139 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, ¶m, true) >= 0 &&
3140 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &state, false) >= 0) {
3141 log_debug("%s %d %d %s %d", cond, trigger, negate, param, state);
3142 if (state < 0 && (!trigger || !i->failed_condition)) {
3143 i->failed_condition = cond;
3144 i->failed_condition_trigger = trigger;
3145 i->failed_condition_negate = negate;
3146 i->failed_condition_param = param;
3150 dbus_message_iter_next(&sub);
3157 case DBUS_TYPE_STRUCT: {
3159 if (streq(name, "LoadError")) {
3160 DBusMessageIter sub;
3161 const char *n, *message;
3164 dbus_message_iter_recurse(iter, &sub);
3166 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &n, true);
3170 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &message, false);
3174 if (!isempty(message))
3175 i->load_error = message;
3185 static int print_property(const char *name, DBusMessageIter *iter) {
3189 /* This is a low-level property printer, see
3190 * print_status_info() for the nicer output */
3192 if (arg_properties && !strv_find(arg_properties, name))
3195 switch (dbus_message_iter_get_arg_type(iter)) {
3197 case DBUS_TYPE_STRUCT: {
3198 DBusMessageIter sub;
3199 dbus_message_iter_recurse(iter, &sub);
3201 if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32 && streq(name, "Job")) {
3204 dbus_message_iter_get_basic(&sub, &u);
3207 printf("%s=%u\n", name, (unsigned) u);
3209 printf("%s=\n", name);
3212 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "Unit")) {
3215 dbus_message_iter_get_basic(&sub, &s);
3217 if (arg_all || s[0])
3218 printf("%s=%s\n", name, s);
3221 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "LoadError")) {
3222 const char *a = NULL, *b = NULL;
3224 if (bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &a, true) >= 0)
3225 bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &b, false);
3227 if (arg_all || !isempty(a) || !isempty(b))
3228 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
3236 case DBUS_TYPE_ARRAY:
3238 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "EnvironmentFiles")) {
3239 DBusMessageIter sub, sub2;
3241 dbus_message_iter_recurse(iter, &sub);
3242 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3246 dbus_message_iter_recurse(&sub, &sub2);
3248 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
3249 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) >= 0)
3250 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
3252 dbus_message_iter_next(&sub);
3257 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Paths")) {
3258 DBusMessageIter sub, sub2;
3260 dbus_message_iter_recurse(iter, &sub);
3262 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3263 const char *type, *path;
3265 dbus_message_iter_recurse(&sub, &sub2);
3267 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
3268 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
3269 printf("%s=%s\n", type, path);
3271 dbus_message_iter_next(&sub);
3276 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Listen")) {
3277 DBusMessageIter sub, sub2;
3279 dbus_message_iter_recurse(iter, &sub);
3280 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3281 const char *type, *path;
3283 dbus_message_iter_recurse(&sub, &sub2);
3285 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
3286 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
3287 printf("Listen%s=%s\n", type, path);
3289 dbus_message_iter_next(&sub);
3294 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Timers")) {
3295 DBusMessageIter sub, sub2;
3297 dbus_message_iter_recurse(iter, &sub);
3298 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3300 uint64_t value, next_elapse;
3302 dbus_message_iter_recurse(&sub, &sub2);
3304 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &base, true) >= 0 &&
3305 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &value, true) >= 0 &&
3306 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &next_elapse, false) >= 0) {
3307 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
3309 printf("%s={ value=%s ; next_elapse=%s }\n",
3311 format_timespan(timespan1, sizeof(timespan1), value, 0),
3312 format_timespan(timespan2, sizeof(timespan2), next_elapse, 0));
3315 dbus_message_iter_next(&sub);
3320 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && startswith(name, "Exec")) {
3321 DBusMessageIter sub;
3323 dbus_message_iter_recurse(iter, &sub);
3324 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3325 ExecStatusInfo info = {};
3327 if (exec_status_info_deserialize(&sub, &info) >= 0) {
3328 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
3329 _cleanup_free_ char *t;
3331 t = strv_join(info.argv, " ");
3333 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
3337 yes_no(info.ignore),
3338 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
3339 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
3340 (unsigned) info. pid,
3341 sigchld_code_to_string(info.code),
3343 info.code == CLD_EXITED ? "" : "/",
3344 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
3348 strv_free(info.argv);
3350 dbus_message_iter_next(&sub);
3355 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "DeviceAllow")) {
3356 DBusMessageIter sub, sub2;
3358 dbus_message_iter_recurse(iter, &sub);
3359 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3360 const char *path, *rwm;
3362 dbus_message_iter_recurse(&sub, &sub2);
3364 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
3365 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &rwm, false) >= 0)
3366 printf("%s=%s %s\n", name, strna(path), strna(rwm));
3368 dbus_message_iter_next(&sub);
3372 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && (streq(name, "BlockIOReadBandwidth") || streq(name, "BlockIOWriteBandwidth"))) {
3373 DBusMessageIter sub, sub2;
3375 dbus_message_iter_recurse(iter, &sub);
3376 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3380 dbus_message_iter_recurse(&sub, &sub2);
3382 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
3383 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &bandwidth, false) >= 0)
3384 printf("%s=%s %" PRIu64 "\n", name, strna(path), bandwidth);
3386 dbus_message_iter_next(&sub);
3395 if (generic_print_property(name, iter, arg_all) > 0)
3399 printf("%s=[unprintable]\n", name);
3404 static int show_one(const char *verb, DBusConnection *bus, const char *path, bool show_properties, bool *new_line) {
3405 _cleanup_free_ DBusMessage *reply = NULL;
3406 const char *interface = "";
3408 DBusMessageIter iter, sub, sub2, sub3;
3409 UnitStatusInfo info = {};
3415 r = bus_method_call_with_reply(
3417 "org.freedesktop.systemd1",
3419 "org.freedesktop.DBus.Properties",
3423 DBUS_TYPE_STRING, &interface,
3428 if (!dbus_message_iter_init(reply, &iter) ||
3429 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3430 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
3431 log_error("Failed to parse reply.");
3435 dbus_message_iter_recurse(&iter, &sub);
3442 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
3445 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_DICT_ENTRY);
3446 dbus_message_iter_recurse(&sub, &sub2);
3448 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
3449 dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
3450 log_error("Failed to parse reply.");
3454 dbus_message_iter_recurse(&sub2, &sub3);
3456 if (show_properties)
3457 r = print_property(name, &sub3);
3459 r = status_property(name, &sub3, &info);
3461 log_error("Failed to parse reply.");
3465 dbus_message_iter_next(&sub);
3470 if (!show_properties) {
3471 if (streq(verb, "help"))
3472 show_unit_help(&info);
3474 print_status_info(&info);
3477 strv_free(info.documentation);
3478 strv_free(info.dropin_paths);
3479 strv_free(info.listen);
3481 if (!streq_ptr(info.active_state, "active") &&
3482 !streq_ptr(info.active_state, "reloading") &&
3483 streq(verb, "status")) {
3484 /* According to LSB: "program not running" */
3485 /* 0: program is running or service is OK
3486 * 1: program is dead and /var/run pid file exists
3487 * 2: program is dead and /var/lock lock file exists
3488 * 3: program is not running
3489 * 4: program or service status is unknown
3491 if (info.pid_file && access(info.pid_file, F_OK) == 0)
3497 while ((p = info.exec)) {
3498 LIST_REMOVE(ExecStatusInfo, exec, info.exec, p);
3499 exec_status_info_free(p);
3505 static int show_one_by_pid(const char *verb, DBusConnection *bus, uint32_t pid, bool *new_line) {
3506 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3507 const char *path = NULL;
3508 _cleanup_dbus_error_free_ DBusError error;
3511 dbus_error_init(&error);
3513 r = bus_method_call_with_reply(
3515 "org.freedesktop.systemd1",
3516 "/org/freedesktop/systemd1",
3517 "org.freedesktop.systemd1.Manager",
3521 DBUS_TYPE_UINT32, &pid,
3526 if (!dbus_message_get_args(reply, &error,
3527 DBUS_TYPE_OBJECT_PATH, &path,
3528 DBUS_TYPE_INVALID)) {
3529 log_error("Failed to parse reply: %s", bus_error_message(&error));
3533 r = show_one(verb, bus, path, false, new_line);
3537 static int show_all(const char* verb, DBusConnection *bus, bool show_properties, bool *new_line) {
3538 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3539 _cleanup_free_ struct unit_info *unit_infos = NULL;
3541 const struct unit_info *u;
3544 r = get_unit_list(bus, &reply, &unit_infos, &c);
3548 qsort(unit_infos, c, sizeof(struct unit_info), compare_unit_info);
3550 for (u = unit_infos; u < unit_infos + c; u++) {
3551 _cleanup_free_ char *p = NULL;
3553 if (!output_show_unit(u))
3556 p = unit_dbus_path_from_name(u->id);
3560 printf("%s -> '%s'\n", u->id, p);
3562 r = show_one(verb, bus, p, show_properties, new_line);
3570 static int show(DBusConnection *bus, char **args) {
3572 bool show_properties, show_status, new_line = false;
3578 show_properties = streq(args[0], "show");
3579 show_status = streq(args[0], "status");
3581 if (show_properties)
3582 pager_open_if_enabled();
3584 /* If no argument is specified inspect the manager itself */
3586 if (show_properties && strv_length(args) <= 1)
3587 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line);
3589 if (show_status && strv_length(args) <= 1)
3590 return show_all(args[0], bus, false, &new_line);
3592 STRV_FOREACH(name, args+1) {
3595 if (safe_atou32(*name, &id) < 0) {
3596 _cleanup_free_ char *p = NULL, *n = NULL;
3597 /* Interpret as unit name */
3599 n = unit_name_mangle(*name);
3603 p = unit_dbus_path_from_name(n);
3607 r = show_one(args[0], bus, p, show_properties, &new_line);
3611 } else if (show_properties) {
3612 _cleanup_free_ char *p = NULL;
3614 /* Interpret as job id */
3615 if (asprintf(&p, "/org/freedesktop/systemd1/job/%u", id) < 0)
3618 r = show_one(args[0], bus, p, show_properties, &new_line);
3623 /* Interpret as PID */
3624 r = show_one_by_pid(args[0], bus, id, &new_line);
3633 static int append_assignment(DBusMessageIter *iter, const char *assignment) {
3636 DBusMessageIter sub;
3642 eq = strchr(assignment, '=');
3644 log_error("Not an assignment: %s", assignment);
3648 field = strndupa(assignment, eq - assignment);
3651 if (!dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &field))
3654 if (streq(field, "CPUAccounting") ||
3655 streq(field, "MemoryAccounting") ||
3656 streq(field, "BlockIOAccounting")) {
3659 r = parse_boolean(eq);
3661 log_error("Failed to parse boolean assignment %s.", assignment);
3666 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "b", &sub) ||
3667 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_BOOLEAN, &b))
3670 } else if (streq(field, "MemoryLimit") || streq(field, "MemorySoftLimit")) {
3674 r = parse_bytes(eq, &bytes);
3676 log_error("Failed to parse bytes specification %s", assignment);
3681 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "t", &sub) ||
3682 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_UINT64, &u))
3685 } else if (streq(field, "CPUShares") || streq(field, "BlockIOWeight")) {
3688 r = safe_atou64(eq, &u);
3690 log_error("Failed to parse %s value %s.", field, eq);
3694 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "t", &sub) ||
3695 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_UINT64, &u))
3698 } else if (streq(field, "DevicePolicy")) {
3700 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "s", &sub) ||
3701 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &eq))
3704 } else if (streq(field, "DeviceAllow")) {
3705 DBusMessageIter sub2;
3707 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "a(ss)", &sub) ||
3708 !dbus_message_iter_open_container(&sub, DBUS_TYPE_ARRAY, "(ss)", &sub2))
3712 const char *path, *rwm;
3713 DBusMessageIter sub3;
3716 e = strchr(eq, ' ');
3718 path = strndupa(eq, e - eq);
3725 if (!dbus_message_iter_open_container(&sub2, DBUS_TYPE_STRUCT, NULL, &sub3) ||
3726 !dbus_message_iter_append_basic(&sub3, DBUS_TYPE_STRING, &path) ||
3727 !dbus_message_iter_append_basic(&sub3, DBUS_TYPE_STRING, &rwm) ||
3728 !dbus_message_iter_close_container(&sub2, &sub3))
3732 if (!dbus_message_iter_close_container(&sub, &sub2))
3736 log_error("Unknown assignment %s.", assignment);
3740 if (!dbus_message_iter_close_container(iter, &sub))
3746 static int set_property(DBusConnection *bus, char **args) {
3748 _cleanup_free_ DBusMessage *m = NULL, *reply = NULL;
3749 DBusMessageIter iter, sub;
3750 dbus_bool_t runtime;
3755 dbus_error_init(&error);
3757 m = dbus_message_new_method_call(
3758 "org.freedesktop.systemd1",
3759 "/org/freedesktop/systemd1",
3760 "org.freedesktop.systemd1.Manager",
3761 "SetUnitProperties");
3765 dbus_message_iter_init_append(m, &iter);
3767 runtime = arg_runtime;
3769 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &args[1]) ||
3770 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &runtime) ||
3771 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(sv)", &sub))
3774 STRV_FOREACH(i, args + 2) {
3775 DBusMessageIter sub2;
3777 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
3780 r = append_assignment(&sub2, *i);
3784 if (!dbus_message_iter_close_container(&sub, &sub2))
3789 if (!dbus_message_iter_close_container(&iter, &sub))
3792 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3794 log_error("Failed to issue method call: %s", bus_error_message(&error));
3795 dbus_error_free(&error);
3802 static int dump(DBusConnection *bus, char **args) {
3803 _cleanup_free_ DBusMessage *reply = NULL;
3808 dbus_error_init(&error);
3810 pager_open_if_enabled();
3812 r = bus_method_call_with_reply(
3814 "org.freedesktop.systemd1",
3815 "/org/freedesktop/systemd1",
3816 "org.freedesktop.systemd1.Manager",
3824 if (!dbus_message_get_args(reply, &error,
3825 DBUS_TYPE_STRING, &text,
3826 DBUS_TYPE_INVALID)) {
3827 log_error("Failed to parse reply: %s", bus_error_message(&error));
3828 dbus_error_free(&error);
3832 fputs(text, stdout);
3836 static int snapshot(DBusConnection *bus, char **args) {
3837 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3840 dbus_bool_t cleanup = FALSE;
3841 DBusMessageIter iter, sub;
3844 *interface = "org.freedesktop.systemd1.Unit",
3846 _cleanup_free_ char *n = NULL;
3848 dbus_error_init(&error);
3850 if (strv_length(args) > 1)
3851 n = unit_name_mangle_with_suffix(args[1], ".snapshot");
3857 r = bus_method_call_with_reply(
3859 "org.freedesktop.systemd1",
3860 "/org/freedesktop/systemd1",
3861 "org.freedesktop.systemd1.Manager",
3865 DBUS_TYPE_STRING, &n,
3866 DBUS_TYPE_BOOLEAN, &cleanup,
3871 if (!dbus_message_get_args(reply, &error,
3872 DBUS_TYPE_OBJECT_PATH, &path,
3873 DBUS_TYPE_INVALID)) {
3874 log_error("Failed to parse reply: %s", bus_error_message(&error));
3875 dbus_error_free(&error);
3879 dbus_message_unref(reply);
3882 r = bus_method_call_with_reply (
3884 "org.freedesktop.systemd1",
3886 "org.freedesktop.DBus.Properties",
3890 DBUS_TYPE_STRING, &interface,
3891 DBUS_TYPE_STRING, &property,
3896 if (!dbus_message_iter_init(reply, &iter) ||
3897 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3898 log_error("Failed to parse reply.");
3902 dbus_message_iter_recurse(&iter, &sub);
3904 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
3905 log_error("Failed to parse reply.");
3909 dbus_message_iter_get_basic(&sub, &id);
3917 static int delete_snapshot(DBusConnection *bus, char **args) {
3922 STRV_FOREACH(name, args+1) {
3923 _cleanup_free_ char *n = NULL;
3926 n = unit_name_mangle_with_suffix(*name, ".snapshot");
3930 r = bus_method_call_with_reply(
3932 "org.freedesktop.systemd1",
3933 "/org/freedesktop/systemd1",
3934 "org.freedesktop.systemd1.Manager",
3938 DBUS_TYPE_STRING, &n,
3947 static int daemon_reload(DBusConnection *bus, char **args) {
3952 if (arg_action == ACTION_RELOAD)
3954 else if (arg_action == ACTION_REEXEC)
3955 method = "Reexecute";
3957 assert(arg_action == ACTION_SYSTEMCTL);
3960 streq(args[0], "clear-jobs") ||
3961 streq(args[0], "cancel") ? "ClearJobs" :
3962 streq(args[0], "daemon-reexec") ? "Reexecute" :
3963 streq(args[0], "reset-failed") ? "ResetFailed" :
3964 streq(args[0], "halt") ? "Halt" :
3965 streq(args[0], "poweroff") ? "PowerOff" :
3966 streq(args[0], "reboot") ? "Reboot" :
3967 streq(args[0], "kexec") ? "KExec" :
3968 streq(args[0], "exit") ? "Exit" :
3969 /* "daemon-reload" */ "Reload";
3972 r = bus_method_call_with_reply(
3974 "org.freedesktop.systemd1",
3975 "/org/freedesktop/systemd1",
3976 "org.freedesktop.systemd1.Manager",
3982 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
3983 /* There's always a fallback possible for
3984 * legacy actions. */
3986 else if ((r == -ETIMEDOUT || r == -ECONNRESET) && streq(method, "Reexecute"))
3987 /* On reexecution, we expect a disconnect, not a
3991 log_error("Failed to issue method call: %s", bus_error_message(&error));
3993 dbus_error_free(&error);
3997 static int reset_failed(DBusConnection *bus, char **args) {
4001 if (strv_length(args) <= 1)
4002 return daemon_reload(bus, args);
4004 STRV_FOREACH(name, args+1) {
4005 _cleanup_free_ char *n;
4007 n = unit_name_mangle(*name);
4011 r = bus_method_call_with_reply(
4013 "org.freedesktop.systemd1",
4014 "/org/freedesktop/systemd1",
4015 "org.freedesktop.systemd1.Manager",
4019 DBUS_TYPE_STRING, &n,
4028 static int show_enviroment(DBusConnection *bus, char **args) {
4029 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
4030 DBusMessageIter iter, sub, sub2;
4033 *interface = "org.freedesktop.systemd1.Manager",
4034 *property = "Environment";
4036 pager_open_if_enabled();
4038 r = bus_method_call_with_reply(
4040 "org.freedesktop.systemd1",
4041 "/org/freedesktop/systemd1",
4042 "org.freedesktop.DBus.Properties",
4046 DBUS_TYPE_STRING, &interface,
4047 DBUS_TYPE_STRING, &property,
4052 if (!dbus_message_iter_init(reply, &iter) ||
4053 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
4054 log_error("Failed to parse reply.");
4058 dbus_message_iter_recurse(&iter, &sub);
4060 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_ARRAY ||
4061 dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_STRING) {
4062 log_error("Failed to parse reply.");
4066 dbus_message_iter_recurse(&sub, &sub2);
4068 while (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_INVALID) {
4071 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
4072 log_error("Failed to parse reply.");
4076 dbus_message_iter_get_basic(&sub2, &text);
4079 dbus_message_iter_next(&sub2);
4085 static int switch_root(DBusConnection *bus, char **args) {
4088 _cleanup_free_ char *init = NULL;
4090 l = strv_length(args);
4091 if (l < 2 || l > 3) {
4092 log_error("Wrong number of arguments.");
4099 init = strdup(args[2]);
4101 parse_env_file("/proc/cmdline", WHITESPACE,
4111 log_debug("switching root - root: %s; init: %s", root, init);
4113 return bus_method_call_with_reply(
4115 "org.freedesktop.systemd1",
4116 "/org/freedesktop/systemd1",
4117 "org.freedesktop.systemd1.Manager",
4121 DBUS_TYPE_STRING, &root,
4122 DBUS_TYPE_STRING, &init,
4126 static int set_environment(DBusConnection *bus, char **args) {
4127 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
4130 DBusMessageIter iter;
4136 dbus_error_init(&error);
4138 method = streq(args[0], "set-environment")
4140 : "UnsetEnvironment";
4142 m = dbus_message_new_method_call(
4143 "org.freedesktop.systemd1",
4144 "/org/freedesktop/systemd1",
4145 "org.freedesktop.systemd1.Manager",
4150 dbus_message_iter_init_append(m, &iter);
4152 r = bus_append_strv_iter(&iter, args + 1);
4156 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
4158 log_error("Failed to issue method call: %s", bus_error_message(&error));
4159 dbus_error_free(&error);
4166 static int enable_sysv_units(char **args) {
4169 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
4170 const char *verb = args[0];
4171 unsigned f = 1, t = 1;
4172 LookupPaths paths = {};
4174 if (arg_scope != UNIT_FILE_SYSTEM)
4177 if (!streq(verb, "enable") &&
4178 !streq(verb, "disable") &&
4179 !streq(verb, "is-enabled"))
4182 /* Processes all SysV units, and reshuffles the array so that
4183 * afterwards only the native units remain */
4185 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, NULL, NULL, NULL);
4190 for (f = 1; args[f]; f++) {
4192 _cleanup_free_ char *p = NULL, *q = NULL;
4193 bool found_native = false, found_sysv;
4195 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
4203 if (!endswith(name, ".service"))
4206 if (path_is_absolute(name))
4209 STRV_FOREACH(k, paths.unit_path) {
4210 if (!isempty(arg_root))
4211 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
4213 asprintf(&p, "%s/%s", *k, name);
4220 found_native = access(p, F_OK) >= 0;
4231 if (!isempty(arg_root))
4232 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
4234 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
4240 p[strlen(p) - sizeof(".service") + 1] = 0;
4241 found_sysv = access(p, F_OK) >= 0;
4246 /* Mark this entry, so that we don't try enabling it as native unit */
4247 args[f] = (char*) "";
4249 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
4251 if (!isempty(arg_root))
4252 argv[c++] = q = strappend("--root=", arg_root);
4254 argv[c++] = path_get_file_name(p);
4256 streq(verb, "enable") ? "on" :
4257 streq(verb, "disable") ? "off" : "--level=5";
4260 l = strv_join((char**)argv, " ");
4266 log_info("Executing %s", l);
4271 log_error("Failed to fork: %m");
4274 } else if (pid == 0) {
4277 execv(argv[0], (char**) argv);
4278 _exit(EXIT_FAILURE);
4281 j = wait_for_terminate(pid, &status);
4283 log_error("Failed to wait for child: %s", strerror(-r));
4288 if (status.si_code == CLD_EXITED) {
4289 if (streq(verb, "is-enabled")) {
4290 if (status.si_status == 0) {
4299 } else if (status.si_status != 0) {
4310 lookup_paths_free(&paths);
4312 /* Drop all SysV units */
4313 for (f = 1, t = 1; args[f]; f++) {
4315 if (isempty(args[f]))
4318 args[t++] = args[f];
4327 static int mangle_names(char **original_names, char ***mangled_names) {
4328 char **i, **l, **name;
4330 l = new(char*, strv_length(original_names) + 1);
4335 STRV_FOREACH(name, original_names) {
4337 /* When enabling units qualified path names are OK,
4338 * too, hence allow them explicitly. */
4343 *i = unit_name_mangle(*name);
4359 static int enable_unit(DBusConnection *bus, char **args) {
4360 const char *verb = args[0];
4361 UnitFileChange *changes = NULL;
4362 unsigned n_changes = 0, i;
4363 int carries_install_info = -1;
4364 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
4366 _cleanup_dbus_error_free_ DBusError error;
4367 _cleanup_strv_free_ char **mangled_names = NULL;
4369 dbus_error_init(&error);
4371 r = enable_sysv_units(args);
4378 r = mangle_names(args+1, &mangled_names);
4382 if (!bus || avoid_bus()) {
4383 if (streq(verb, "enable")) {
4384 r = unit_file_enable(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4385 carries_install_info = r;
4386 } else if (streq(verb, "disable"))
4387 r = unit_file_disable(arg_scope, arg_runtime, arg_root, mangled_names, &changes, &n_changes);
4388 else if (streq(verb, "reenable")) {
4389 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4390 carries_install_info = r;
4391 } else if (streq(verb, "link"))
4392 r = unit_file_link(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4393 else if (streq(verb, "preset")) {
4394 r = unit_file_preset(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4395 carries_install_info = r;
4396 } else if (streq(verb, "mask"))
4397 r = unit_file_mask(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4398 else if (streq(verb, "unmask"))
4399 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, mangled_names, &changes, &n_changes);
4400 else if (streq(verb, "set-default"))
4401 r = unit_file_set_default(arg_scope, arg_root, args[1], &changes, &n_changes);
4403 assert_not_reached("Unknown verb");
4406 log_error("Operation failed: %s", strerror(-r));
4411 for (i = 0; i < n_changes; i++) {
4412 if (changes[i].type == UNIT_FILE_SYMLINK)
4413 log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
4415 log_info("rm '%s'", changes[i].path);
4422 bool send_force = true, expect_carries_install_info = false;
4424 DBusMessageIter iter, sub, sub2;
4426 if (streq(verb, "enable")) {
4427 method = "EnableUnitFiles";
4428 expect_carries_install_info = true;
4429 } else if (streq(verb, "disable")) {
4430 method = "DisableUnitFiles";
4432 } else if (streq(verb, "reenable")) {
4433 method = "ReenableUnitFiles";
4434 expect_carries_install_info = true;
4435 } else if (streq(verb, "link"))
4436 method = "LinkUnitFiles";
4437 else if (streq(verb, "preset")) {
4438 method = "PresetUnitFiles";
4439 expect_carries_install_info = true;
4440 } else if (streq(verb, "mask"))
4441 method = "MaskUnitFiles";
4442 else if (streq(verb, "unmask")) {
4443 method = "UnmaskUnitFiles";
4445 } else if (streq(verb, "set-default")) {
4446 method = "SetDefaultTarget";
4448 assert_not_reached("Unknown verb");
4450 m = dbus_message_new_method_call(
4451 "org.freedesktop.systemd1",
4452 "/org/freedesktop/systemd1",
4453 "org.freedesktop.systemd1.Manager",
4460 dbus_message_iter_init_append(m, &iter);
4462 r = bus_append_strv_iter(&iter, mangled_names);
4464 log_error("Failed to append unit files.");
4469 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &a)) {
4470 log_error("Failed to append runtime boolean.");
4478 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b)) {
4479 log_error("Failed to append force boolean.");
4485 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
4487 log_error("Failed to issue method call: %s", bus_error_message(&error));
4492 if (!dbus_message_iter_init(reply, &iter)) {
4493 log_error("Failed to initialize iterator.");
4497 if (expect_carries_install_info) {
4498 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &b, true);
4500 log_error("Failed to parse reply.");
4504 carries_install_info = b;
4507 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
4508 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
4509 log_error("Failed to parse reply.");
4514 dbus_message_iter_recurse(&iter, &sub);
4515 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
4516 const char *type, *path, *source;
4518 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
4519 log_error("Failed to parse reply.");
4524 dbus_message_iter_recurse(&sub, &sub2);
4526 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
4527 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
4528 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &source, false) < 0) {
4529 log_error("Failed to parse reply.");
4535 if (streq(type, "symlink"))
4536 log_info("ln -s '%s' '%s'", source, path);
4538 log_info("rm '%s'", path);
4541 dbus_message_iter_next(&sub);
4544 /* Try to reload if enabeld */
4546 r = daemon_reload(bus, args);
4549 if (carries_install_info == 0)
4550 log_warning("The unit files have no [Install] section. They are not meant to be enabled\n"
4551 "using systemctl.\n"
4552 "Possible reasons for having this kind of units are:\n"
4553 "1) A unit may be statically enabled by being symlinked from another unit's\n"
4554 " .wants/ or .requires/ directory.\n"
4555 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
4556 " a requirement dependency on it.\n"
4557 "3) A unit may be started when needed via activation (socket, path, timer,\n"
4558 " D-Bus, udev, scripted systemctl call, ...).\n");
4561 unit_file_changes_free(changes, n_changes);
4566 static int set_log_level(DBusConnection *bus, char **args) {
4567 _cleanup_dbus_error_free_ DBusError error;
4568 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
4569 DBusMessageIter iter, sub;
4570 const char* property = "LogLevel";
4571 const char* interface = "org.freedesktop.systemd1.Manager";
4578 dbus_error_init(&error);
4580 m = dbus_message_new_method_call("org.freedesktop.systemd1",
4581 "/org/freedesktop/systemd1",
4582 "org.freedesktop.DBus.Properties",
4587 dbus_message_iter_init_append(m, &iter);
4589 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &interface) ||
4590 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &property) ||
4591 !dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT, "s", &sub))
4594 if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &value)) {
4595 dbus_message_iter_abandon_container(&iter, &sub);
4599 if (!dbus_message_iter_close_container(&iter, &sub))
4602 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
4604 log_error("Failed to issue method call: %s", bus_error_message(&error));
4611 static int unit_is_enabled(DBusConnection *bus, char **args) {
4612 _cleanup_dbus_error_free_ DBusError error;
4614 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
4619 dbus_error_init(&error);
4621 r = enable_sysv_units(args);
4627 if (!bus || avoid_bus()) {
4629 STRV_FOREACH(name, args+1) {
4630 UnitFileState state;
4632 n = unit_name_mangle(*name);
4636 state = unit_file_get_state(arg_scope, arg_root, n);
4643 if (state == UNIT_FILE_ENABLED ||
4644 state == UNIT_FILE_ENABLED_RUNTIME ||
4645 state == UNIT_FILE_STATIC)
4649 puts(unit_file_state_to_string(state));
4653 STRV_FOREACH(name, args+1) {
4656 n = unit_name_mangle(*name);
4660 r = bus_method_call_with_reply (
4662 "org.freedesktop.systemd1",
4663 "/org/freedesktop/systemd1",
4664 "org.freedesktop.systemd1.Manager",
4668 DBUS_TYPE_STRING, &n,
4676 if (!dbus_message_get_args(reply, &error,
4677 DBUS_TYPE_STRING, &s,
4678 DBUS_TYPE_INVALID)) {
4679 log_error("Failed to parse reply: %s", bus_error_message(&error));
4683 dbus_message_unref(reply);
4686 if (streq(s, "enabled") ||
4687 streq(s, "enabled-runtime") ||
4696 return enabled ? 0 : 1;
4699 static int systemctl_help(void) {
4701 pager_open_if_enabled();
4703 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
4704 "Query or send control commands to the systemd manager.\n\n"
4705 " -h --help Show this help\n"
4706 " --version Show package version\n"
4707 " -t --type=TYPE List only units of a particular type\n"
4708 " -p --property=NAME Show only properties by this name\n"
4709 " -a --all Show all loaded units/properties, including dead/empty\n"
4710 " ones. To list all units installed on the system, use\n"
4711 " the 'list-unit-files' command instead.\n"
4712 " --reverse Show reverse dependencies with 'list-dependencies'\n"
4713 " --failed Show only failed units\n"
4714 " -l --full Don't ellipsize unit names on output\n"
4715 " --fail When queueing a new job, fail if conflicting jobs are\n"
4717 " --irreversible Create jobs which cannot be implicitly cancelled\n"
4718 " --show-types When showing sockets, explicitly show their type\n"
4719 " --ignore-dependencies\n"
4720 " When queueing a new job, ignore all its dependencies\n"
4721 " -i --ignore-inhibitors\n"
4722 " When shutting down or sleeping, ignore inhibitors\n"
4723 " --kill-who=WHO Who to send signal to\n"
4724 " -s --signal=SIGNAL Which signal to send\n"
4725 " -H --host=[USER@]HOST\n"
4726 " Show information for remote host\n"
4727 " -P --privileged Acquire privileges before execution\n"
4728 " -q --quiet Suppress output\n"
4729 " --no-block Do not wait until operation finished\n"
4730 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4731 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
4733 " --no-legend Do not print a legend (column headers and hints)\n"
4734 " --no-pager Do not pipe output into a pager\n"
4735 " --no-ask-password\n"
4736 " Do not ask for system passwords\n"
4737 " --system Connect to system manager\n"
4738 " --user Connect to user service manager\n"
4739 " --global Enable/disable unit files globally\n"
4740 " -f --force When enabling unit files, override existing symlinks\n"
4741 " When shutting down, execute action immediately\n"
4742 " --root=PATH Enable unit files in the specified root directory\n"
4743 " --runtime Enable unit files only temporarily until next reboot\n"
4744 " -n --lines=INTEGER Journal entries to show\n"
4745 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
4746 " verbose, export, json, json-pretty, json-sse, cat)\n\n"
4748 " list-units List loaded units\n"
4749 " list-sockets List loaded sockets ordered by address\n"
4750 " start [NAME...] Start (activate) one or more units\n"
4751 " stop [NAME...] Stop (deactivate) one or more units\n"
4752 " reload [NAME...] Reload one or more units\n"
4753 " restart [NAME...] Start or restart one or more units\n"
4754 " try-restart [NAME...] Restart one or more units if active\n"
4755 " reload-or-restart [NAME...] Reload one or more units if possible,\n"
4756 " otherwise start or restart\n"
4757 " reload-or-try-restart [NAME...] Reload one or more units if possible,\n"
4758 " otherwise restart if active\n"
4759 " isolate [NAME] Start one unit and stop all others\n"
4760 " kill [NAME...] Send signal to processes of a unit\n"
4761 " is-active [NAME...] Check whether units are active\n"
4762 " is-failed [NAME...] Check whether units are failed\n"
4763 " status [NAME...|PID...] Show runtime status of one or more units\n"
4764 " show [NAME...|JOB...] Show properties of one or more\n"
4765 " units/jobs or the manager\n"
4766 " set-property [NAME] [ASSIGNMENT...]\n"
4767 " Sets one or more properties of a unit\n"
4768 " help [NAME...|PID...] Show manual for one or more units\n"
4769 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
4771 " load [NAME...] Load one or more units\n"
4772 " list-dependencies [NAME] Recursively show units which are required\n"
4773 " or wanted by this unit or by which this\n"
4774 " unit is required or wanted\n\n"
4775 "Unit File Commands:\n"
4776 " list-unit-files List installed unit files\n"
4777 " enable [NAME...] Enable one or more unit files\n"
4778 " disable [NAME...] Disable one or more unit files\n"
4779 " reenable [NAME...] Reenable one or more unit files\n"
4780 " preset [NAME...] Enable/disable one or more unit files\n"
4781 " based on preset configuration\n"
4782 " mask [NAME...] Mask one or more units\n"
4783 " unmask [NAME...] Unmask one or more units\n"
4784 " link [PATH...] Link one or more units files into\n"
4785 " the search path\n"
4786 " get-default Get the name of the default target\n"
4787 " set-default NAME Set the default target\n"
4788 " is-enabled [NAME...] Check whether unit files are enabled\n\n"
4790 " list-jobs List jobs\n"
4791 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
4792 "Status Commands:\n"
4793 " dump Dump server status\n"
4794 "Snapshot Commands:\n"
4795 " snapshot [NAME] Create a snapshot\n"
4796 " delete [NAME...] Remove one or more snapshots\n\n"
4797 "Environment Commands:\n"
4798 " show-environment Dump environment\n"
4799 " set-environment [NAME=VALUE...] Set one or more environment variables\n"
4800 " unset-environment [NAME...] Unset one or more environment variables\n"
4801 " set-log-level LEVEL Set logging threshold for systemd\n\n"
4802 "Manager Lifecycle Commands:\n"
4803 " daemon-reload Reload systemd manager configuration\n"
4804 " daemon-reexec Reexecute systemd manager\n\n"
4805 "System Commands:\n"
4806 " default Enter system default mode\n"
4807 " rescue Enter system rescue mode\n"
4808 " emergency Enter system emergency mode\n"
4809 " halt Shut down and halt the system\n"
4810 " poweroff Shut down and power-off the system\n"
4811 " reboot Shut down and reboot the system\n"
4812 " kexec Shut down and reboot the system with kexec\n"
4813 " exit Request user instance exit\n"
4814 " switch-root [ROOT] [INIT] Change to a different root file system\n"
4815 " suspend Suspend the system\n"
4816 " hibernate Hibernate the system\n"
4817 " hybrid-sleep Hibernate and suspend the system\n",
4818 program_invocation_short_name);
4823 static int halt_help(void) {
4825 printf("%s [OPTIONS...]\n\n"
4826 "%s the system.\n\n"
4827 " --help Show this help\n"
4828 " --halt Halt the machine\n"
4829 " -p --poweroff Switch off the machine\n"
4830 " --reboot Reboot the machine\n"
4831 " -f --force Force immediate halt/power-off/reboot\n"
4832 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
4833 " -d --no-wtmp Don't write wtmp record\n"
4834 " --no-wall Don't send wall message before halt/power-off/reboot\n",
4835 program_invocation_short_name,
4836 arg_action == ACTION_REBOOT ? "Reboot" :
4837 arg_action == ACTION_POWEROFF ? "Power off" :
4843 static int shutdown_help(void) {
4845 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
4846 "Shut down the system.\n\n"
4847 " --help Show this help\n"
4848 " -H --halt Halt the machine\n"
4849 " -P --poweroff Power-off the machine\n"
4850 " -r --reboot Reboot the machine\n"
4851 " -h Equivalent to --poweroff, overridden by --halt\n"
4852 " -k Don't halt/power-off/reboot, just send warnings\n"
4853 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4854 " -c Cancel a pending shutdown\n",
4855 program_invocation_short_name);
4860 static int telinit_help(void) {
4862 printf("%s [OPTIONS...] {COMMAND}\n\n"
4863 "Send control commands to the init daemon.\n\n"
4864 " --help Show this help\n"
4865 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
4867 " 0 Power-off the machine\n"
4868 " 6 Reboot the machine\n"
4869 " 2, 3, 4, 5 Start runlevelX.target unit\n"
4870 " 1, s, S Enter rescue mode\n"
4871 " q, Q Reload init daemon configuration\n"
4872 " u, U Reexecute init daemon\n",
4873 program_invocation_short_name);
4878 static int runlevel_help(void) {
4880 printf("%s [OPTIONS...]\n\n"
4881 "Prints the previous and current runlevel of the init system.\n\n"
4882 " --help Show this help\n",
4883 program_invocation_short_name);
4888 static int help_types(void) {
4892 puts("Available unit types:");
4893 for(i = 0; i < _UNIT_TYPE_MAX; i++) {
4894 t = unit_type_to_string(i);
4899 puts("\nAvailable unit load states: ");
4900 for(i = 0; i < _UNIT_LOAD_STATE_MAX; i++) {
4901 t = unit_load_state_to_string(i);
4909 static int systemctl_parse_argv(int argc, char *argv[]) {
4918 ARG_IGNORE_DEPENDENCIES,
4930 ARG_NO_ASK_PASSWORD,
4937 static const struct option options[] = {
4938 { "help", no_argument, NULL, 'h' },
4939 { "version", no_argument, NULL, ARG_VERSION },
4940 { "type", required_argument, NULL, 't' },
4941 { "property", required_argument, NULL, 'p' },
4942 { "all", no_argument, NULL, 'a' },
4943 { "reverse", no_argument, NULL, ARG_REVERSE },
4944 { "after", no_argument, NULL, ARG_AFTER },
4945 { "before", no_argument, NULL, ARG_BEFORE },
4946 { "show-types", no_argument, NULL, ARG_SHOW_TYPES },
4947 { "failed", no_argument, NULL, ARG_FAILED },
4948 { "full", no_argument, NULL, 'l' },
4949 { "fail", no_argument, NULL, ARG_FAIL },
4950 { "irreversible", no_argument, NULL, ARG_IRREVERSIBLE },
4951 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
4952 { "ignore-inhibitors", no_argument, NULL, 'i' },
4953 { "user", no_argument, NULL, ARG_USER },
4954 { "system", no_argument, NULL, ARG_SYSTEM },
4955 { "global", no_argument, NULL, ARG_GLOBAL },
4956 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
4957 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
4958 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
4959 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4960 { "quiet", no_argument, NULL, 'q' },
4961 { "root", required_argument, NULL, ARG_ROOT },
4962 { "force", no_argument, NULL, ARG_FORCE },
4963 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
4964 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
4965 { "signal", required_argument, NULL, 's' },
4966 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
4967 { "host", required_argument, NULL, 'H' },
4968 { "privileged",no_argument, NULL, 'P' },
4969 { "runtime", no_argument, NULL, ARG_RUNTIME },
4970 { "lines", required_argument, NULL, 'n' },
4971 { "output", required_argument, NULL, 'o' },
4972 { "plain", no_argument, NULL, ARG_PLAIN },
4973 { NULL, 0, NULL, 0 }
4981 while ((c = getopt_long(argc, argv, "ht:p:alqfs:H:Pn:o:i", options, NULL)) >= 0) {
4990 puts(PACKAGE_STRING);
4991 puts(SYSTEMD_FEATURES);
4998 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
4999 _cleanup_free_ char *type;
5001 type = strndup(word, size);
5005 if (streq(type, "help")) {
5010 if (unit_type_from_string(type) >= 0) {
5011 if (strv_push(&arg_types, type))
5017 if (unit_load_state_from_string(optarg) >= 0) {
5018 if (strv_push(&arg_load_states, type))
5024 log_error("Unknown unit type or load state '%s'.", type);
5025 log_info("Use -t help to see a list of allowed values.");
5033 /* Make sure that if the empty property list
5034 was specified, we won't show any properties. */
5035 if (isempty(optarg) && !arg_properties) {
5036 arg_properties = strv_new(NULL, NULL);
5037 if (!arg_properties)
5043 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
5046 prop = strndup(word, size);
5050 if (strv_push(&arg_properties, prop)) {
5057 /* If the user asked for a particular
5058 * property, show it to him, even if it is
5070 arg_dependency = DEPENDENCY_REVERSE;
5074 arg_dependency = DEPENDENCY_AFTER;
5078 arg_dependency = DEPENDENCY_BEFORE;
5081 case ARG_SHOW_TYPES:
5082 arg_show_types = true;
5086 arg_job_mode = "fail";
5089 case ARG_IRREVERSIBLE:
5090 arg_job_mode = "replace-irreversibly";
5093 case ARG_IGNORE_DEPENDENCIES:
5094 arg_job_mode = "ignore-dependencies";
5098 arg_scope = UNIT_FILE_USER;
5102 arg_scope = UNIT_FILE_SYSTEM;
5106 arg_scope = UNIT_FILE_GLOBAL;
5110 arg_no_block = true;
5114 arg_no_legend = true;
5118 arg_no_pager = true;
5150 arg_no_reload = true;
5154 arg_kill_who = optarg;
5158 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
5159 log_error("Failed to parse signal string %s.", optarg);
5164 case ARG_NO_ASK_PASSWORD:
5165 arg_ask_password = false;
5169 arg_transport = TRANSPORT_POLKIT;
5173 arg_transport = TRANSPORT_SSH;
5174 parse_user_at_host(optarg, &arg_user, &arg_host);
5182 if (safe_atou(optarg, &arg_lines) < 0) {
5183 log_error("Failed to parse lines '%s'", optarg);
5189 arg_output = output_mode_from_string(optarg);
5190 if (arg_output < 0) {
5191 log_error("Unknown output '%s'.", optarg);
5197 arg_ignore_inhibitors = true;
5208 log_error("Unknown option code '%c'.", c);
5213 if (arg_transport != TRANSPORT_NORMAL && arg_scope != UNIT_FILE_SYSTEM) {
5214 log_error("Cannot access user instance remotely.");
5221 static int halt_parse_argv(int argc, char *argv[]) {
5230 static const struct option options[] = {
5231 { "help", no_argument, NULL, ARG_HELP },
5232 { "halt", no_argument, NULL, ARG_HALT },
5233 { "poweroff", no_argument, NULL, 'p' },
5234 { "reboot", no_argument, NULL, ARG_REBOOT },
5235 { "force", no_argument, NULL, 'f' },
5236 { "wtmp-only", no_argument, NULL, 'w' },
5237 { "no-wtmp", no_argument, NULL, 'd' },
5238 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5239 { NULL, 0, NULL, 0 }
5247 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
5248 if (runlevel == '0' || runlevel == '6')
5251 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
5259 arg_action = ACTION_HALT;
5263 if (arg_action != ACTION_REBOOT)
5264 arg_action = ACTION_POWEROFF;
5268 arg_action = ACTION_REBOOT;
5290 /* Compatibility nops */
5297 log_error("Unknown option code '%c'.", c);
5302 if (optind < argc) {
5303 log_error("Too many arguments.");
5310 static int parse_time_spec(const char *t, usec_t *_u) {
5314 if (streq(t, "now"))
5316 else if (!strchr(t, ':')) {
5319 if (safe_atou64(t, &u) < 0)
5322 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
5331 hour = strtol(t, &e, 10);
5332 if (errno > 0 || *e != ':' || hour < 0 || hour > 23)
5335 minute = strtol(e+1, &e, 10);
5336 if (errno > 0 || *e != 0 || minute < 0 || minute > 59)
5339 n = now(CLOCK_REALTIME);
5340 s = (time_t) (n / USEC_PER_SEC);
5342 assert_se(localtime_r(&s, &tm));
5344 tm.tm_hour = (int) hour;
5345 tm.tm_min = (int) minute;
5348 assert_se(s = mktime(&tm));
5350 *_u = (usec_t) s * USEC_PER_SEC;
5353 *_u += USEC_PER_DAY;
5359 static int shutdown_parse_argv(int argc, char *argv[]) {
5366 static const struct option options[] = {
5367 { "help", no_argument, NULL, ARG_HELP },
5368 { "halt", no_argument, NULL, 'H' },
5369 { "poweroff", no_argument, NULL, 'P' },
5370 { "reboot", no_argument, NULL, 'r' },
5371 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
5372 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5373 { NULL, 0, NULL, 0 }
5381 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
5389 arg_action = ACTION_HALT;
5393 arg_action = ACTION_POWEROFF;
5398 arg_action = ACTION_KEXEC;
5400 arg_action = ACTION_REBOOT;
5404 arg_action = ACTION_KEXEC;
5408 if (arg_action != ACTION_HALT)
5409 arg_action = ACTION_POWEROFF;
5422 /* Compatibility nops */
5426 arg_action = ACTION_CANCEL_SHUTDOWN;
5433 log_error("Unknown option code '%c'.", c);
5438 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
5439 r = parse_time_spec(argv[optind], &arg_when);
5441 log_error("Failed to parse time specification: %s", argv[optind]);
5445 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
5447 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
5448 /* No time argument for shutdown cancel */
5449 arg_wall = argv + optind;
5450 else if (argc > optind + 1)
5451 /* We skip the time argument */
5452 arg_wall = argv + optind + 1;
5459 static int telinit_parse_argv(int argc, char *argv[]) {
5466 static const struct option options[] = {
5467 { "help", no_argument, NULL, ARG_HELP },
5468 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5469 { NULL, 0, NULL, 0 }
5472 static const struct {
5476 { '0', ACTION_POWEROFF },
5477 { '6', ACTION_REBOOT },
5478 { '1', ACTION_RESCUE },
5479 { '2', ACTION_RUNLEVEL2 },
5480 { '3', ACTION_RUNLEVEL3 },
5481 { '4', ACTION_RUNLEVEL4 },
5482 { '5', ACTION_RUNLEVEL5 },
5483 { 's', ACTION_RESCUE },
5484 { 'S', ACTION_RESCUE },
5485 { 'q', ACTION_RELOAD },
5486 { 'Q', ACTION_RELOAD },
5487 { 'u', ACTION_REEXEC },
5488 { 'U', ACTION_REEXEC }
5497 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
5512 log_error("Unknown option code '%c'.", c);
5517 if (optind >= argc) {
5522 if (optind + 1 < argc) {
5523 log_error("Too many arguments.");
5527 if (strlen(argv[optind]) != 1) {
5528 log_error("Expected single character argument.");
5532 for (i = 0; i < ELEMENTSOF(table); i++)
5533 if (table[i].from == argv[optind][0])
5536 if (i >= ELEMENTSOF(table)) {
5537 log_error("Unknown command '%s'.", argv[optind]);
5541 arg_action = table[i].to;
5548 static int runlevel_parse_argv(int argc, char *argv[]) {
5554 static const struct option options[] = {
5555 { "help", no_argument, NULL, ARG_HELP },
5556 { NULL, 0, NULL, 0 }
5564 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
5575 log_error("Unknown option code '%c'.", c);
5580 if (optind < argc) {
5581 log_error("Too many arguments.");
5588 static int parse_argv(int argc, char *argv[]) {
5592 if (program_invocation_short_name) {
5594 if (strstr(program_invocation_short_name, "halt")) {
5595 arg_action = ACTION_HALT;
5596 return halt_parse_argv(argc, argv);
5597 } else if (strstr(program_invocation_short_name, "poweroff")) {
5598 arg_action = ACTION_POWEROFF;
5599 return halt_parse_argv(argc, argv);
5600 } else if (strstr(program_invocation_short_name, "reboot")) {
5602 arg_action = ACTION_KEXEC;
5604 arg_action = ACTION_REBOOT;
5605 return halt_parse_argv(argc, argv);
5606 } else if (strstr(program_invocation_short_name, "shutdown")) {
5607 arg_action = ACTION_POWEROFF;
5608 return shutdown_parse_argv(argc, argv);
5609 } else if (strstr(program_invocation_short_name, "init")) {
5611 if (sd_booted() > 0) {
5612 arg_action = ACTION_INVALID;
5613 return telinit_parse_argv(argc, argv);
5615 /* Hmm, so some other init system is
5616 * running, we need to forward this
5617 * request to it. For now we simply
5618 * guess that it is Upstart. */
5620 execv(TELINIT, argv);
5622 log_error("Couldn't find an alternative telinit implementation to spawn.");
5626 } else if (strstr(program_invocation_short_name, "runlevel")) {
5627 arg_action = ACTION_RUNLEVEL;
5628 return runlevel_parse_argv(argc, argv);
5632 arg_action = ACTION_SYSTEMCTL;
5633 return systemctl_parse_argv(argc, argv);
5636 _pure_ static int action_to_runlevel(void) {
5638 static const char table[_ACTION_MAX] = {
5639 [ACTION_HALT] = '0',
5640 [ACTION_POWEROFF] = '0',
5641 [ACTION_REBOOT] = '6',
5642 [ACTION_RUNLEVEL2] = '2',
5643 [ACTION_RUNLEVEL3] = '3',
5644 [ACTION_RUNLEVEL4] = '4',
5645 [ACTION_RUNLEVEL5] = '5',
5646 [ACTION_RESCUE] = '1'
5649 assert(arg_action < _ACTION_MAX);
5651 return table[arg_action];
5654 static int talk_upstart(void) {
5655 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
5656 _cleanup_dbus_error_free_ DBusError error;
5657 int previous, rl, r;
5659 env1_buf[] = "RUNLEVEL=X",
5660 env2_buf[] = "PREVLEVEL=X";
5661 char *env1 = env1_buf, *env2 = env2_buf;
5662 const char *emit = "runlevel";
5663 dbus_bool_t b_false = FALSE;
5664 DBusMessageIter iter, sub;
5665 DBusConnection *bus;
5667 dbus_error_init(&error);
5669 if (!(rl = action_to_runlevel()))
5672 if (utmp_get_runlevel(&previous, NULL) < 0)
5675 if (!(bus = dbus_connection_open_private("unix:abstract=/com/ubuntu/upstart", &error))) {
5676 if (dbus_error_has_name(&error, DBUS_ERROR_NO_SERVER)) {
5681 log_error("Failed to connect to Upstart bus: %s", bus_error_message(&error));
5686 if ((r = bus_check_peercred(bus)) < 0) {
5687 log_error("Failed to verify owner of bus.");
5691 if (!(m = dbus_message_new_method_call(
5692 "com.ubuntu.Upstart",
5693 "/com/ubuntu/Upstart",
5694 "com.ubuntu.Upstart0_6",
5697 log_error("Could not allocate message.");
5702 dbus_message_iter_init_append(m, &iter);
5704 env1_buf[sizeof(env1_buf)-2] = rl;
5705 env2_buf[sizeof(env2_buf)-2] = previous;
5707 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &emit) ||
5708 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub) ||
5709 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env1) ||
5710 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env2) ||
5711 !dbus_message_iter_close_container(&iter, &sub) ||
5712 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b_false)) {
5713 log_error("Could not append arguments to message.");
5718 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
5720 if (bus_error_is_no_service(&error)) {
5725 log_error("Failed to issue method call: %s", bus_error_message(&error));
5734 dbus_connection_flush(bus);
5735 dbus_connection_close(bus);
5736 dbus_connection_unref(bus);
5742 static int talk_initctl(void) {
5743 struct init_request request = {};
5745 _cleanup_close_ int fd = -1;
5748 rl = action_to_runlevel();
5752 request.magic = INIT_MAGIC;
5753 request.sleeptime = 0;
5754 request.cmd = INIT_CMD_RUNLVL;
5755 request.runlevel = rl;
5757 fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY);
5759 if (errno == ENOENT)
5762 log_error("Failed to open "INIT_FIFO": %m");
5767 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
5769 log_error("Failed to write to "INIT_FIFO": %m");
5770 return errno > 0 ? -errno : -EIO;
5776 static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
5778 static const struct {
5786 int (* const dispatch)(DBusConnection *bus, char **args);
5788 { "list-units", LESS, 1, list_units },
5789 { "list-unit-files", EQUAL, 1, list_unit_files },
5790 { "list-sockets", LESS, 1, list_sockets },
5791 { "list-jobs", EQUAL, 1, list_jobs },
5792 { "clear-jobs", EQUAL, 1, daemon_reload },
5793 { "load", MORE, 2, load_unit },
5794 { "cancel", MORE, 2, cancel_job },
5795 { "start", MORE, 2, start_unit },
5796 { "stop", MORE, 2, start_unit },
5797 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5798 { "reload", MORE, 2, start_unit },
5799 { "restart", MORE, 2, start_unit },
5800 { "try-restart", MORE, 2, start_unit },
5801 { "reload-or-restart", MORE, 2, start_unit },
5802 { "reload-or-try-restart", MORE, 2, start_unit },
5803 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
5804 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5805 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
5806 { "isolate", EQUAL, 2, start_unit },
5807 { "kill", MORE, 2, kill_unit },
5808 { "is-active", MORE, 2, check_unit_active },
5809 { "check", MORE, 2, check_unit_active },
5810 { "is-failed", MORE, 2, check_unit_failed },
5811 { "show", MORE, 1, show },
5812 { "status", MORE, 1, show },
5813 { "help", MORE, 2, show },
5814 { "dump", EQUAL, 1, dump },
5815 { "snapshot", LESS, 2, snapshot },
5816 { "delete", MORE, 2, delete_snapshot },
5817 { "daemon-reload", EQUAL, 1, daemon_reload },
5818 { "daemon-reexec", EQUAL, 1, daemon_reload },
5819 { "show-environment", EQUAL, 1, show_enviroment },
5820 { "set-environment", MORE, 2, set_environment },
5821 { "unset-environment", MORE, 2, set_environment },
5822 { "halt", EQUAL, 1, start_special },
5823 { "poweroff", EQUAL, 1, start_special },
5824 { "reboot", EQUAL, 1, start_special },
5825 { "kexec", EQUAL, 1, start_special },
5826 { "suspend", EQUAL, 1, start_special },
5827 { "hibernate", EQUAL, 1, start_special },
5828 { "hybrid-sleep", EQUAL, 1, start_special },
5829 { "default", EQUAL, 1, start_special },
5830 { "rescue", EQUAL, 1, start_special },
5831 { "emergency", EQUAL, 1, start_special },
5832 { "exit", EQUAL, 1, start_special },
5833 { "reset-failed", MORE, 1, reset_failed },
5834 { "enable", MORE, 2, enable_unit },
5835 { "disable", MORE, 2, enable_unit },
5836 { "is-enabled", MORE, 2, unit_is_enabled },
5837 { "reenable", MORE, 2, enable_unit },
5838 { "preset", MORE, 2, enable_unit },
5839 { "mask", MORE, 2, enable_unit },
5840 { "unmask", MORE, 2, enable_unit },
5841 { "link", MORE, 2, enable_unit },
5842 { "switch-root", MORE, 2, switch_root },
5843 { "list-dependencies", LESS, 2, list_dependencies },
5844 { "set-default", EQUAL, 2, enable_unit },
5845 { "get-default", LESS, 1, get_default },
5846 { "set-log-level", EQUAL, 2, set_log_level },
5847 { "set-property", MORE, 3, set_property },
5857 left = argc - optind;
5860 /* Special rule: no arguments means "list-units" */
5863 if (streq(argv[optind], "help") && !argv[optind+1]) {
5864 log_error("This command expects one or more "
5865 "unit names. Did you mean --help?");
5869 for (i = 0; i < ELEMENTSOF(verbs); i++)
5870 if (streq(argv[optind], verbs[i].verb))
5873 if (i >= ELEMENTSOF(verbs)) {
5874 log_error("Unknown operation '%s'.", argv[optind]);
5879 switch (verbs[i].argc_cmp) {
5882 if (left != verbs[i].argc) {
5883 log_error("Invalid number of arguments.");
5890 if (left < verbs[i].argc) {
5891 log_error("Too few arguments.");
5898 if (left > verbs[i].argc) {
5899 log_error("Too many arguments.");
5906 assert_not_reached("Unknown comparison operator.");
5909 /* Require a bus connection for all operations but
5911 if (!streq(verbs[i].verb, "enable") &&
5912 !streq(verbs[i].verb, "disable") &&
5913 !streq(verbs[i].verb, "is-enabled") &&
5914 !streq(verbs[i].verb, "list-unit-files") &&
5915 !streq(verbs[i].verb, "reenable") &&
5916 !streq(verbs[i].verb, "preset") &&
5917 !streq(verbs[i].verb, "mask") &&
5918 !streq(verbs[i].verb, "unmask") &&
5919 !streq(verbs[i].verb, "link") &&
5920 !streq(verbs[i].verb, "set-default") &&
5921 !streq(verbs[i].verb, "get-default")) {
5923 if (running_in_chroot() > 0) {
5924 log_info("Running in chroot, ignoring request.");
5928 if (((!streq(verbs[i].verb, "reboot") &&
5929 !streq(verbs[i].verb, "halt") &&
5930 !streq(verbs[i].verb, "poweroff")) || arg_force <= 0) && !bus) {
5931 log_error("Failed to get D-Bus connection: %s",
5932 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5938 if (!bus && !avoid_bus()) {
5939 log_error("Failed to get D-Bus connection: %s",
5940 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5945 return verbs[i].dispatch(bus, argv + optind);
5948 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
5949 _cleanup_close_ int fd;
5950 struct sd_shutdown_command c = {
5956 union sockaddr_union sockaddr = {
5957 .un.sun_family = AF_UNIX,
5958 .un.sun_path = "/run/systemd/shutdownd",
5960 struct iovec iovec[2] = {
5961 {.iov_base = (char*) &c,
5962 .iov_len = offsetof(struct sd_shutdown_command, wall_message),
5965 struct msghdr msghdr = {
5966 .msg_name = &sockaddr,
5967 .msg_namelen = offsetof(struct sockaddr_un, sun_path)
5968 + sizeof("/run/systemd/shutdownd") - 1,
5973 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
5977 if (!isempty(message)) {
5978 iovec[1].iov_base = (char*) message;
5979 iovec[1].iov_len = strlen(message);
5980 msghdr.msg_iovlen++;
5983 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0)
5989 static int reload_with_fallback(DBusConnection *bus) {
5992 /* First, try systemd via D-Bus. */
5993 if (daemon_reload(bus, NULL) >= 0)
5997 /* Nothing else worked, so let's try signals */
5998 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
6000 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
6001 log_error("kill() failed: %m");
6008 static int start_with_fallback(DBusConnection *bus) {
6011 /* First, try systemd via D-Bus. */
6012 if (start_unit(bus, NULL) >= 0)
6016 /* Hmm, talking to systemd via D-Bus didn't work. Then
6017 * let's try to talk to Upstart via D-Bus. */
6018 if (talk_upstart() > 0)
6021 /* Nothing else worked, so let's try
6023 if (talk_initctl() > 0)
6026 log_error("Failed to talk to init daemon.");
6030 warn_wall(arg_action);
6034 static _noreturn_ void halt_now(enum action a) {
6036 /* Make sure C-A-D is handled by the kernel from this
6038 reboot(RB_ENABLE_CAD);
6043 log_info("Halting.");
6044 reboot(RB_HALT_SYSTEM);
6047 case ACTION_POWEROFF:
6048 log_info("Powering off.");
6049 reboot(RB_POWER_OFF);
6053 log_info("Rebooting.");
6054 reboot(RB_AUTOBOOT);
6058 assert_not_reached("Unknown halt action.");
6061 assert_not_reached("Uh? This shouldn't happen.");
6064 static int halt_main(DBusConnection *bus) {
6067 r = check_inhibitors(bus, arg_action);
6071 if (geteuid() != 0) {
6072 /* Try logind if we are a normal user and no special
6073 * mode applies. Maybe PolicyKit allows us to shutdown
6076 if (arg_when <= 0 &&
6079 (arg_action == ACTION_POWEROFF ||
6080 arg_action == ACTION_REBOOT)) {
6081 r = reboot_with_logind(bus, arg_action);
6086 log_error("Must be root.");
6091 _cleanup_free_ char *m;
6093 m = strv_join(arg_wall, " ");
6094 r = send_shutdownd(arg_when,
6095 arg_action == ACTION_HALT ? 'H' :
6096 arg_action == ACTION_POWEROFF ? 'P' :
6097 arg_action == ACTION_KEXEC ? 'K' :
6104 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
6106 char date[FORMAT_TIMESTAMP_MAX];
6108 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
6109 format_timestamp(date, sizeof(date), arg_when));
6114 if (!arg_dry && !arg_force)
6115 return start_with_fallback(bus);
6118 if (sd_booted() > 0)
6119 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
6121 r = utmp_put_shutdown();
6123 log_warning("Failed to write utmp record: %s", strerror(-r));
6130 halt_now(arg_action);
6131 /* We should never reach this. */
6135 static int runlevel_main(void) {
6136 int r, runlevel, previous;
6138 r = utmp_get_runlevel(&runlevel, &previous);
6145 previous <= 0 ? 'N' : previous,
6146 runlevel <= 0 ? 'N' : runlevel);
6151 int main(int argc, char*argv[]) {
6152 int r, retval = EXIT_FAILURE;
6153 DBusConnection *bus = NULL;
6154 _cleanup_dbus_error_free_ DBusError error;
6156 dbus_error_init(&error);
6158 setlocale(LC_ALL, "");
6159 log_parse_environment();
6162 r = parse_argv(argc, argv);
6166 retval = EXIT_SUCCESS;
6170 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
6171 * let's shortcut this */
6172 if (arg_action == ACTION_RUNLEVEL) {
6173 r = runlevel_main();
6174 retval = r < 0 ? EXIT_FAILURE : r;
6178 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
6179 log_info("Running in chroot, ignoring request.");
6185 if (arg_transport == TRANSPORT_NORMAL)
6186 bus_connect(arg_scope == UNIT_FILE_SYSTEM ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &bus, &private_bus, &error);
6187 else if (arg_transport == TRANSPORT_POLKIT) {
6188 bus_connect_system_polkit(&bus, &error);
6189 private_bus = false;
6190 } else if (arg_transport == TRANSPORT_SSH) {
6191 bus_connect_system_ssh(arg_user, arg_host, &bus, &error);
6192 private_bus = false;
6194 assert_not_reached("Uh, invalid transport...");
6197 switch (arg_action) {
6199 case ACTION_SYSTEMCTL:
6200 r = systemctl_main(bus, argc, argv, &error);
6204 case ACTION_POWEROFF:
6210 case ACTION_RUNLEVEL2:
6211 case ACTION_RUNLEVEL3:
6212 case ACTION_RUNLEVEL4:
6213 case ACTION_RUNLEVEL5:
6215 case ACTION_EMERGENCY:
6216 case ACTION_DEFAULT:
6217 r = start_with_fallback(bus);
6222 r = reload_with_fallback(bus);
6225 case ACTION_CANCEL_SHUTDOWN: {
6229 m = strv_join(arg_wall, " ");
6231 retval = EXIT_FAILURE;
6235 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
6237 log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r));
6242 case ACTION_INVALID:
6243 case ACTION_RUNLEVEL:
6245 assert_not_reached("Unknown action");
6248 retval = r < 0 ? EXIT_FAILURE : r;
6252 dbus_connection_flush(bus);
6253 dbus_connection_close(bus);
6254 dbus_connection_unref(bus);
6259 strv_free(arg_types);
6260 strv_free(arg_load_states);
6261 strv_free(arg_properties);
6264 ask_password_agent_close();
6265 polkit_agent_close();