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>
28 #include <sys/ioctl.h>
32 #include <sys/socket.h>
35 #include <sys/prctl.h>
36 #include <dbus/dbus.h>
38 #include <systemd/sd-daemon.h>
39 #include <systemd/sd-shutdown.h>
45 #include "utmp-wtmp.h"
49 #include "dbus-common.h"
50 #include "cgroup-show.h"
51 #include "cgroup-util.h"
53 #include "path-lookup.h"
54 #include "conf-parser.h"
55 #include "exit-status.h"
56 #include "bus-errors.h"
58 #include "unit-name.h"
60 #include "spawn-ask-password-agent.h"
61 #include "spawn-polkit-agent.h"
63 #include "logs-show.h"
65 static const char *arg_type = NULL;
66 static char **arg_property = NULL;
67 static bool arg_all = false;
68 static const char *arg_job_mode = "replace";
69 static UnitFileScope arg_scope = UNIT_FILE_SYSTEM;
70 static bool arg_immediate = false;
71 static bool arg_no_block = false;
72 static bool arg_no_legend = false;
73 static bool arg_no_pager = false;
74 static bool arg_no_wtmp = false;
75 static bool arg_no_sync = false;
76 static bool arg_no_wall = false;
77 static bool arg_no_reload = false;
78 static bool arg_dry = false;
79 static bool arg_quiet = false;
80 static bool arg_full = false;
81 static int arg_force = 0;
82 static bool arg_ask_password = true;
83 static bool arg_failed = false;
84 static bool arg_runtime = false;
85 static char **arg_wall = NULL;
86 static const char *arg_kill_who = NULL;
87 static const char *arg_kill_mode = NULL;
88 static int arg_signal = SIGTERM;
89 static const char *arg_root = NULL;
90 static usec_t arg_when = 0;
109 ACTION_CANCEL_SHUTDOWN,
111 } arg_action = ACTION_SYSTEMCTL;
117 static enum transport {
121 } arg_transport = TRANSPORT_NORMAL;
122 static const char *arg_host = NULL;
123 static bool arg_follow = false;
124 static unsigned arg_lines = 10;
125 static OutputMode arg_output = OUTPUT_SHORT;
127 static bool private_bus = false;
129 static int daemon_reload(DBusConnection *bus, char **args);
130 static void halt_now(enum action a);
132 static bool on_tty(void) {
135 /* Note that this is invoked relatively early, before we start
136 * the pager. That means the value we return reflects whether
137 * we originally were started on a tty, not if we currently
138 * are. But this is intended, since we want colour and so on
139 * when run in our own pager. */
141 if (_unlikely_(t < 0))
142 t = isatty(STDOUT_FILENO) > 0;
147 static void pager_open_if_enabled(void) {
149 /* Cache result before we open the pager */
158 static void ask_password_agent_open_if_enabled(void) {
160 /* Open the password agent as a child process if necessary */
162 if (!arg_ask_password)
165 if (arg_scope != UNIT_FILE_SYSTEM)
168 ask_password_agent_open();
171 static void polkit_agent_open_if_enabled(void) {
173 /* Open the polkit agent as a child process if necessary */
175 if (!arg_ask_password)
178 if (arg_scope != UNIT_FILE_SYSTEM)
184 static const char *ansi_highlight_red(bool b) {
189 return b ? ANSI_HIGHLIGHT_RED_ON : ANSI_HIGHLIGHT_OFF;
192 static const char *ansi_highlight_green(bool b) {
197 return b ? ANSI_HIGHLIGHT_GREEN_ON : ANSI_HIGHLIGHT_OFF;
200 static bool error_is_no_service(const DBusError *error) {
203 if (!dbus_error_is_set(error))
206 if (dbus_error_has_name(error, DBUS_ERROR_NAME_HAS_NO_OWNER))
209 if (dbus_error_has_name(error, DBUS_ERROR_SERVICE_UNKNOWN))
212 return startswith(error->name, "org.freedesktop.DBus.Error.Spawn.");
215 static int translate_bus_error_to_exit_status(int r, const DBusError *error) {
218 if (!dbus_error_is_set(error))
221 if (dbus_error_has_name(error, DBUS_ERROR_ACCESS_DENIED) ||
222 dbus_error_has_name(error, BUS_ERROR_ONLY_BY_DEPENDENCY) ||
223 dbus_error_has_name(error, BUS_ERROR_NO_ISOLATION) ||
224 dbus_error_has_name(error, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE))
225 return EXIT_NOPERMISSION;
227 if (dbus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT))
228 return EXIT_NOTINSTALLED;
230 if (dbus_error_has_name(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE) ||
231 dbus_error_has_name(error, BUS_ERROR_NOT_SUPPORTED))
232 return EXIT_NOTIMPLEMENTED;
234 if (dbus_error_has_name(error, BUS_ERROR_LOAD_FAILED))
235 return EXIT_NOTCONFIGURED;
243 static void warn_wall(enum action a) {
244 static const char *table[_ACTION_MAX] = {
245 [ACTION_HALT] = "The system is going down for system halt NOW!",
246 [ACTION_REBOOT] = "The system is going down for reboot NOW!",
247 [ACTION_POWEROFF] = "The system is going down for power-off NOW!",
248 [ACTION_KEXEC] = "The system is going down for kexec reboot NOW!",
249 [ACTION_RESCUE] = "The system is going down to rescue mode NOW!",
250 [ACTION_EMERGENCY] = "The system is going down to emergency mode NOW!"
259 p = strv_join(arg_wall, " ");
261 log_error("Failed to join strings.");
277 utmp_wall(table[a], NULL);
280 static bool avoid_bus(void) {
282 if (running_in_chroot() > 0)
285 if (sd_booted() <= 0)
288 if (!isempty(arg_root))
291 if (arg_scope == UNIT_FILE_GLOBAL)
299 const char *description;
300 const char *load_state;
301 const char *active_state;
302 const char *sub_state;
303 const char *following;
304 const char *unit_path;
306 const char *job_type;
307 const char *job_path;
310 static int compare_unit_info(const void *a, const void *b) {
312 const struct unit_info *u = a, *v = b;
314 d1 = strrchr(u->id, '.');
315 d2 = strrchr(v->id, '.');
320 if ((r = strcasecmp(d1, d2)) != 0)
324 return strcasecmp(u->id, v->id);
327 static bool output_show_unit(const struct unit_info *u) {
331 return streq(u->active_state, "failed");
333 return (!arg_type || ((dot = strrchr(u->id, '.')) &&
334 streq(dot+1, arg_type))) &&
335 (arg_all || !(streq(u->active_state, "inactive") || u->following[0]) || u->job_id > 0);
338 static void output_units_list(const struct unit_info *unit_infos, unsigned c) {
339 unsigned id_len, max_id_len, active_len, sub_len, job_len, desc_len, n_shown = 0;
340 const struct unit_info *u;
342 max_id_len = sizeof("UNIT")-1;
343 active_len = sizeof("ACTIVE")-1;
344 sub_len = sizeof("SUB")-1;
345 job_len = sizeof("JOB")-1;
348 for (u = unit_infos; u < unit_infos + c; u++) {
349 if (!output_show_unit(u))
352 max_id_len = MAX(max_id_len, strlen(u->id));
353 active_len = MAX(active_len, strlen(u->active_state));
354 sub_len = MAX(sub_len, strlen(u->sub_state));
356 job_len = MAX(job_len, strlen(u->job_type));
361 id_len = MIN(max_id_len, 25);
362 basic_len = 5 + id_len + 6 + active_len + sub_len + job_len;
363 if (basic_len < (unsigned) columns()) {
364 unsigned extra_len, incr;
365 extra_len = columns() - basic_len;
366 /* Either UNIT already got 25, or is fully satisfied.
367 * Grant up to 25 to DESC now. */
368 incr = MIN(extra_len, 25);
371 /* split the remaining space between UNIT and DESC,
372 * but do not give UNIT more than it needs. */
374 incr = MIN(extra_len / 2, max_id_len - id_len);
376 desc_len += extra_len - incr;
382 if (!arg_no_legend) {
383 printf("%-*s %-6s %-*s %-*s %-*s ", id_len, "UNIT", "LOAD",
384 active_len, "ACTIVE", sub_len, "SUB", job_len, "JOB");
385 if (!arg_full && arg_no_pager)
386 printf("%.*s\n", desc_len, "DESCRIPTION");
388 printf("%s\n", "DESCRIPTION");
391 for (u = unit_infos; u < unit_infos + c; u++) {
393 const char *on_loaded, *off_loaded;
394 const char *on_active, *off_active;
396 if (!output_show_unit(u))
401 if (streq(u->load_state, "error")) {
402 on_loaded = ansi_highlight_red(true);
403 off_loaded = ansi_highlight_red(false);
405 on_loaded = off_loaded = "";
407 if (streq(u->active_state, "failed")) {
408 on_active = ansi_highlight_red(true);
409 off_active = ansi_highlight_red(false);
411 on_active = off_active = "";
413 e = arg_full ? NULL : ellipsize(u->id, id_len, 33);
415 printf("%-*s %s%-6s%s %s%-*s %-*s%s %-*s ",
416 id_len, e ? e : u->id,
417 on_loaded, u->load_state, off_loaded,
418 on_active, active_len, u->active_state,
419 sub_len, u->sub_state, off_active,
420 job_len, u->job_id ? u->job_type : "");
421 if (!arg_full && arg_no_pager)
422 printf("%.*s\n", desc_len, u->description);
424 printf("%s\n", u->description);
429 if (!arg_no_legend) {
430 printf("\nLOAD = Reflects whether the unit definition was properly loaded.\n"
431 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
432 "SUB = The low-level unit activation state, values depend on unit type.\n"
433 "JOB = Pending job for the unit.\n");
436 printf("\n%u units listed.\n", n_shown);
438 printf("\n%u units listed. Pass --all to see inactive units, too.\n", n_shown);
442 static int list_units(DBusConnection *bus, char **args) {
443 DBusMessage *m = NULL, *reply = NULL;
446 DBusMessageIter iter, sub, sub2;
447 unsigned c = 0, n_units = 0;
448 struct unit_info *unit_infos = NULL;
450 dbus_error_init(&error);
454 pager_open_if_enabled();
456 if (!(m = dbus_message_new_method_call(
457 "org.freedesktop.systemd1",
458 "/org/freedesktop/systemd1",
459 "org.freedesktop.systemd1.Manager",
461 log_error("Could not allocate message.");
465 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
466 log_error("Failed to issue method call: %s", bus_error_message(&error));
471 if (!dbus_message_iter_init(reply, &iter) ||
472 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
473 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
474 log_error("Failed to parse reply.");
479 dbus_message_iter_recurse(&iter, &sub);
481 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
484 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
485 log_error("Failed to parse reply.");
493 n_units = MAX(2*c, 16);
494 w = realloc(unit_infos, sizeof(struct unit_info) * n_units);
497 log_error("Failed to allocate unit array.");
507 dbus_message_iter_recurse(&sub, &sub2);
509 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->id, true) < 0 ||
510 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->description, true) < 0 ||
511 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->load_state, true) < 0 ||
512 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->active_state, true) < 0 ||
513 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->sub_state, true) < 0 ||
514 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->following, true) < 0 ||
515 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &u->unit_path, true) < 0 ||
516 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &u->job_id, true) < 0 ||
517 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->job_type, true) < 0 ||
518 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &u->job_path, false) < 0) {
519 log_error("Failed to parse reply.");
524 dbus_message_iter_next(&sub);
529 qsort(unit_infos, c, sizeof(struct unit_info), compare_unit_info);
530 output_units_list(unit_infos, c);
537 dbus_message_unref(m);
540 dbus_message_unref(reply);
544 dbus_error_free(&error);
549 static int compare_unit_file_list(const void *a, const void *b) {
551 const UnitFileList *u = a, *v = b;
553 d1 = strrchr(u->path, '.');
554 d2 = strrchr(v->path, '.');
559 r = strcasecmp(d1, d2);
564 return strcasecmp(file_name_from_path(u->path), file_name_from_path(v->path));
567 static bool output_show_unit_file(const UnitFileList *u) {
570 return !arg_type || ((dot = strrchr(u->path, '.')) && streq(dot+1, arg_type));
573 static void output_unit_file_list(const UnitFileList *units, unsigned c) {
574 unsigned max_id_len, id_cols, state_cols, n_shown = 0;
575 const UnitFileList *u;
577 max_id_len = sizeof("UNIT FILE")-1;
578 state_cols = sizeof("STATE")-1;
579 for (u = units; u < units + c; u++) {
580 if (!output_show_unit_file(u))
583 max_id_len = MAX(max_id_len, strlen(file_name_from_path(u->path)));
584 state_cols = MAX(state_cols, strlen(unit_file_state_to_string(u->state)));
589 id_cols = MIN(max_id_len, 25);
590 basic_cols = 1 + id_cols + state_cols;
591 if (basic_cols < (unsigned) columns())
592 id_cols += MIN(columns() - basic_cols, max_id_len - id_cols);
594 id_cols = max_id_len;
597 printf("%-*s %-*s\n", id_cols, "UNIT FILE", state_cols, "STATE");
599 for (u = units; u < units + c; u++) {
601 const char *on, *off;
604 if (!output_show_unit_file(u))
609 if (u->state == UNIT_FILE_MASKED ||
610 u->state == UNIT_FILE_MASKED_RUNTIME ||
611 u->state == UNIT_FILE_DISABLED) {
612 on = ansi_highlight_red(true);
613 off = ansi_highlight_red(false);
614 } else if (u->state == UNIT_FILE_ENABLED) {
615 on = ansi_highlight_green(true);
616 off = ansi_highlight_green(false);
620 id = file_name_from_path(u->path);
622 e = arg_full ? NULL : ellipsize(id, id_cols, 33);
624 printf("%-*s %s%-*s%s\n",
626 on, state_cols, unit_file_state_to_string(u->state), off);
632 printf("\n%u unit files listed.\n", n_shown);
635 static int list_unit_files(DBusConnection *bus, char **args) {
636 DBusMessage *m = NULL, *reply = NULL;
639 DBusMessageIter iter, sub, sub2;
640 unsigned c = 0, n_units = 0;
641 UnitFileList *units = NULL;
643 dbus_error_init(&error);
645 pager_open_if_enabled();
652 h = hashmap_new(string_hash_func, string_compare_func);
654 log_error("Out of memory");
658 r = unit_file_get_list(arg_scope, arg_root, h);
660 unit_file_list_free(h);
661 log_error("Failed to get unit file list: %s", strerror(-r));
665 n_units = hashmap_size(h);
666 units = new(UnitFileList, n_units);
668 unit_file_list_free(h);
669 log_error("Out of memory");
673 HASHMAP_FOREACH(u, h, i) {
674 memcpy(units + c++, u, sizeof(UnitFileList));
682 m = dbus_message_new_method_call(
683 "org.freedesktop.systemd1",
684 "/org/freedesktop/systemd1",
685 "org.freedesktop.systemd1.Manager",
688 log_error("Could not allocate message.");
692 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
694 log_error("Failed to issue method call: %s", bus_error_message(&error));
699 if (!dbus_message_iter_init(reply, &iter) ||
700 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
701 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
702 log_error("Failed to parse reply.");
707 dbus_message_iter_recurse(&iter, &sub);
709 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
713 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
714 log_error("Failed to parse reply.");
722 n_units = MAX(2*c, 16);
723 w = realloc(units, sizeof(struct UnitFileList) * n_units);
726 log_error("Failed to allocate unit array.");
736 dbus_message_iter_recurse(&sub, &sub2);
738 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->path, true) < 0 ||
739 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, false) < 0) {
740 log_error("Failed to parse reply.");
745 u->state = unit_file_state_from_string(state);
747 dbus_message_iter_next(&sub);
753 qsort(units, c, sizeof(UnitFileList), compare_unit_file_list);
754 output_unit_file_list(units, c);
761 dbus_message_unref(m);
764 dbus_message_unref(reply);
768 dbus_error_free(&error);
773 static int dot_one_property(const char *name, const char *prop, DBusMessageIter *iter) {
774 static const char * const colors[] = {
775 "Requires", "[color=\"black\"]",
776 "RequiresOverridable", "[color=\"black\"]",
777 "Requisite", "[color=\"darkblue\"]",
778 "RequisiteOverridable", "[color=\"darkblue\"]",
779 "Wants", "[color=\"darkgrey\"]",
780 "Conflicts", "[color=\"red\"]",
781 "ConflictedBy", "[color=\"red\"]",
782 "After", "[color=\"green\"]"
785 const char *c = NULL;
792 for (i = 0; i < ELEMENTSOF(colors); i += 2)
793 if (streq(colors[i], prop)) {
801 if (arg_dot != DOT_ALL)
802 if ((arg_dot == DOT_ORDER) != streq(prop, "After"))
805 switch (dbus_message_iter_get_arg_type(iter)) {
807 case DBUS_TYPE_ARRAY:
809 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING) {
812 dbus_message_iter_recurse(iter, &sub);
814 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
817 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING);
818 dbus_message_iter_get_basic(&sub, &s);
819 printf("\t\"%s\"->\"%s\" %s;\n", name, s, c);
821 dbus_message_iter_next(&sub);
831 static int dot_one(DBusConnection *bus, const char *name, const char *path) {
832 DBusMessage *m = NULL, *reply = NULL;
833 const char *interface = "org.freedesktop.systemd1.Unit";
836 DBusMessageIter iter, sub, sub2, sub3;
841 dbus_error_init(&error);
843 if (!(m = dbus_message_new_method_call(
844 "org.freedesktop.systemd1",
846 "org.freedesktop.DBus.Properties",
848 log_error("Could not allocate message.");
853 if (!dbus_message_append_args(m,
854 DBUS_TYPE_STRING, &interface,
855 DBUS_TYPE_INVALID)) {
856 log_error("Could not append arguments to message.");
861 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
862 log_error("Failed to issue method call: %s", bus_error_message(&error));
867 if (!dbus_message_iter_init(reply, &iter) ||
868 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
869 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
870 log_error("Failed to parse reply.");
875 dbus_message_iter_recurse(&iter, &sub);
877 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
880 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_DICT_ENTRY) {
881 log_error("Failed to parse reply.");
886 dbus_message_iter_recurse(&sub, &sub2);
888 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &prop, true) < 0) {
889 log_error("Failed to parse reply.");
894 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
895 log_error("Failed to parse reply.");
900 dbus_message_iter_recurse(&sub2, &sub3);
902 if (dot_one_property(name, prop, &sub3)) {
903 log_error("Failed to parse reply.");
908 dbus_message_iter_next(&sub);
915 dbus_message_unref(m);
918 dbus_message_unref(reply);
920 dbus_error_free(&error);
925 static int dot(DBusConnection *bus, char **args) {
926 DBusMessage *m = NULL, *reply = NULL;
929 DBusMessageIter iter, sub, sub2;
931 dbus_error_init(&error);
935 if (!(m = dbus_message_new_method_call(
936 "org.freedesktop.systemd1",
937 "/org/freedesktop/systemd1",
938 "org.freedesktop.systemd1.Manager",
940 log_error("Could not allocate message.");
944 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
945 log_error("Failed to issue method call: %s", bus_error_message(&error));
950 if (!dbus_message_iter_init(reply, &iter) ||
951 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
952 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
953 log_error("Failed to parse reply.");
958 printf("digraph systemd {\n");
960 dbus_message_iter_recurse(&iter, &sub);
961 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
962 const char *id, *description, *load_state, *active_state, *sub_state, *following, *unit_path;
964 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
965 log_error("Failed to parse reply.");
970 dbus_message_iter_recurse(&sub, &sub2);
972 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &id, true) < 0 ||
973 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &description, true) < 0 ||
974 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &load_state, true) < 0 ||
975 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &active_state, true) < 0 ||
976 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &sub_state, true) < 0 ||
977 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &following, true) < 0 ||
978 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, true) < 0) {
979 log_error("Failed to parse reply.");
984 if ((r = dot_one(bus, id, unit_path)) < 0)
987 /* printf("\t\"%s\";\n", id); */
988 dbus_message_iter_next(&sub);
993 log_info(" Color legend: black = Requires\n"
994 " dark blue = Requisite\n"
995 " dark grey = Wants\n"
1000 log_notice("-- You probably want to process this output with graphviz' dot tool.\n"
1001 "-- Try a shell pipeline like 'systemctl dot | dot -Tsvg > systemd.svg'!\n");
1007 dbus_message_unref(m);
1010 dbus_message_unref(reply);
1012 dbus_error_free(&error);
1017 static int list_jobs(DBusConnection *bus, char **args) {
1018 DBusMessage *m = NULL, *reply = NULL;
1021 DBusMessageIter iter, sub, sub2;
1024 dbus_error_init(&error);
1028 pager_open_if_enabled();
1030 if (!(m = dbus_message_new_method_call(
1031 "org.freedesktop.systemd1",
1032 "/org/freedesktop/systemd1",
1033 "org.freedesktop.systemd1.Manager",
1035 log_error("Could not allocate message.");
1039 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
1040 log_error("Failed to issue method call: %s", bus_error_message(&error));
1045 if (!dbus_message_iter_init(reply, &iter) ||
1046 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
1047 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
1048 log_error("Failed to parse reply.");
1053 dbus_message_iter_recurse(&iter, &sub);
1056 printf("%4s %-25s %-15s %-7s\n", "JOB", "UNIT", "TYPE", "STATE");
1058 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1059 const char *name, *type, *state, *job_path, *unit_path;
1063 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
1064 log_error("Failed to parse reply.");
1069 dbus_message_iter_recurse(&sub, &sub2);
1071 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &id, true) < 0 ||
1072 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
1073 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
1074 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, true) < 0 ||
1075 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &job_path, true) < 0 ||
1076 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, false) < 0) {
1077 log_error("Failed to parse reply.");
1082 e = arg_full ? NULL : ellipsize(name, 25, 33);
1083 printf("%4u %-25s %-15s %-7s\n", id, e ? e : name, type, state);
1088 dbus_message_iter_next(&sub);
1092 printf("\n%u jobs listed.\n", k);
1098 dbus_message_unref(m);
1101 dbus_message_unref(reply);
1103 dbus_error_free(&error);
1108 static int load_unit(DBusConnection *bus, char **args) {
1109 DBusMessage *m = NULL;
1114 dbus_error_init(&error);
1119 STRV_FOREACH(name, args+1) {
1122 if (!(m = dbus_message_new_method_call(
1123 "org.freedesktop.systemd1",
1124 "/org/freedesktop/systemd1",
1125 "org.freedesktop.systemd1.Manager",
1127 log_error("Could not allocate message.");
1132 if (!dbus_message_append_args(m,
1133 DBUS_TYPE_STRING, name,
1134 DBUS_TYPE_INVALID)) {
1135 log_error("Could not append arguments to message.");
1140 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
1141 log_error("Failed to issue method call: %s", bus_error_message(&error));
1146 dbus_message_unref(m);
1147 dbus_message_unref(reply);
1156 dbus_message_unref(m);
1158 dbus_error_free(&error);
1163 static int cancel_job(DBusConnection *bus, char **args) {
1164 DBusMessage *m = NULL, *reply = NULL;
1169 dbus_error_init(&error);
1174 if (strv_length(args) <= 1)
1175 return daemon_reload(bus, args);
1177 STRV_FOREACH(name, args+1) {
1181 if (!(m = dbus_message_new_method_call(
1182 "org.freedesktop.systemd1",
1183 "/org/freedesktop/systemd1",
1184 "org.freedesktop.systemd1.Manager",
1186 log_error("Could not allocate message.");
1191 if ((r = safe_atou(*name, &id)) < 0) {
1192 log_error("Failed to parse job id: %s", strerror(-r));
1196 assert_cc(sizeof(uint32_t) == sizeof(id));
1197 if (!dbus_message_append_args(m,
1198 DBUS_TYPE_UINT32, &id,
1199 DBUS_TYPE_INVALID)) {
1200 log_error("Could not append arguments to message.");
1205 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
1206 log_error("Failed to issue method call: %s", bus_error_message(&error));
1211 if (!dbus_message_get_args(reply, &error,
1212 DBUS_TYPE_OBJECT_PATH, &path,
1213 DBUS_TYPE_INVALID)) {
1214 log_error("Failed to parse reply: %s", bus_error_message(&error));
1219 dbus_message_unref(m);
1220 if (!(m = dbus_message_new_method_call(
1221 "org.freedesktop.systemd1",
1223 "org.freedesktop.systemd1.Job",
1225 log_error("Could not allocate message.");
1230 dbus_message_unref(reply);
1231 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
1232 log_error("Failed to issue method call: %s", bus_error_message(&error));
1237 dbus_message_unref(m);
1238 dbus_message_unref(reply);
1246 dbus_message_unref(m);
1249 dbus_message_unref(reply);
1251 dbus_error_free(&error);
1256 static bool need_daemon_reload(DBusConnection *bus, const char *unit) {
1257 DBusMessage *m = NULL, *reply = NULL;
1258 dbus_bool_t b = FALSE;
1259 DBusMessageIter iter, sub;
1261 *interface = "org.freedesktop.systemd1.Unit",
1262 *property = "NeedDaemonReload",
1265 /* We ignore all errors here, since this is used to show a warning only */
1267 if (!(m = dbus_message_new_method_call(
1268 "org.freedesktop.systemd1",
1269 "/org/freedesktop/systemd1",
1270 "org.freedesktop.systemd1.Manager",
1274 if (!dbus_message_append_args(m,
1275 DBUS_TYPE_STRING, &unit,
1279 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, NULL)))
1282 if (!dbus_message_get_args(reply, NULL,
1283 DBUS_TYPE_OBJECT_PATH, &path,
1287 dbus_message_unref(m);
1288 if (!(m = dbus_message_new_method_call(
1289 "org.freedesktop.systemd1",
1291 "org.freedesktop.DBus.Properties",
1295 if (!dbus_message_append_args(m,
1296 DBUS_TYPE_STRING, &interface,
1297 DBUS_TYPE_STRING, &property,
1298 DBUS_TYPE_INVALID)) {
1302 dbus_message_unref(reply);
1303 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, NULL)))
1306 if (!dbus_message_iter_init(reply, &iter) ||
1307 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
1310 dbus_message_iter_recurse(&iter, &sub);
1312 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_BOOLEAN)
1315 dbus_message_iter_get_basic(&sub, &b);
1319 dbus_message_unref(m);
1322 dbus_message_unref(reply);
1327 typedef struct WaitData {
1332 static DBusHandlerResult wait_filter(DBusConnection *connection, DBusMessage *message, void *data) {
1340 dbus_error_init(&error);
1342 log_debug("Got D-Bus request: %s.%s() on %s",
1343 dbus_message_get_interface(message),
1344 dbus_message_get_member(message),
1345 dbus_message_get_path(message));
1347 if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
1348 log_error("Warning! D-Bus connection terminated.");
1349 dbus_connection_close(connection);
1351 } else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
1353 const char *path, *result;
1354 dbus_bool_t success = true;
1356 if (dbus_message_get_args(message, &error,
1357 DBUS_TYPE_UINT32, &id,
1358 DBUS_TYPE_OBJECT_PATH, &path,
1359 DBUS_TYPE_STRING, &result,
1360 DBUS_TYPE_INVALID)) {
1363 if ((p = set_remove(d->set, (char*) path)))
1367 d->result = strdup(result);
1372 dbus_error_free(&error);
1374 if (dbus_message_get_args(message, &error,
1375 DBUS_TYPE_UINT32, &id,
1376 DBUS_TYPE_OBJECT_PATH, &path,
1377 DBUS_TYPE_BOOLEAN, &success,
1378 DBUS_TYPE_INVALID)) {
1381 /* Compatibility with older systemd versions <
1382 * 19 during upgrades. This should be dropped
1385 if ((p = set_remove(d->set, (char*) path)))
1389 d->result = strdup("failed");
1395 log_error("Failed to parse message: %s", bus_error_message(&error));
1399 dbus_error_free(&error);
1400 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1403 static int enable_wait_for_jobs(DBusConnection *bus) {
1411 dbus_error_init(&error);
1412 dbus_bus_add_match(bus,
1414 "sender='org.freedesktop.systemd1',"
1415 "interface='org.freedesktop.systemd1.Manager',"
1416 "member='JobRemoved',"
1417 "path='/org/freedesktop/systemd1'",
1420 if (dbus_error_is_set(&error)) {
1421 log_error("Failed to add match: %s", bus_error_message(&error));
1422 dbus_error_free(&error);
1426 /* This is slightly dirty, since we don't undo the match registrations. */
1430 static int wait_for_jobs(DBusConnection *bus, Set *s) {
1440 if (!dbus_connection_add_filter(bus, wait_filter, &d, NULL)) {
1441 log_error("Failed to add filter.");
1446 while (!set_isempty(s) &&
1447 dbus_connection_read_write_dispatch(bus, -1))
1450 if (!arg_quiet && d.result) {
1451 if (streq(d.result, "timeout"))
1452 log_error("Job timed out.");
1453 else if (streq(d.result, "canceled"))
1454 log_error("Job canceled.");
1455 else if (streq(d.result, "dependency"))
1456 log_error("A dependency job failed. See system journal for details.");
1457 else if (!streq(d.result, "done") && !streq(d.result, "skipped"))
1458 log_error("Job failed. See system journal and 'systemctl status' for details.");
1461 if (streq_ptr(d.result, "timeout"))
1463 else if (streq_ptr(d.result, "canceled"))
1465 else if (!streq_ptr(d.result, "done") && !streq_ptr(d.result, "skipped"))
1473 /* This is slightly dirty, since we don't undo the filter registration. */
1478 static int start_unit_one(
1479 DBusConnection *bus,
1486 DBusMessage *m = NULL, *reply = NULL;
1495 assert(arg_no_block || s);
1497 if (!(m = dbus_message_new_method_call(
1498 "org.freedesktop.systemd1",
1499 "/org/freedesktop/systemd1",
1500 "org.freedesktop.systemd1.Manager",
1502 log_error("Could not allocate message.");
1507 if (!dbus_message_append_args(m,
1508 DBUS_TYPE_STRING, &name,
1509 DBUS_TYPE_STRING, &mode,
1510 DBUS_TYPE_INVALID)) {
1511 log_error("Could not append arguments to message.");
1516 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, error))) {
1518 if (arg_action != ACTION_SYSTEMCTL && error_is_no_service(error)) {
1519 /* There's always a fallback possible for
1520 * legacy actions. */
1525 log_error("Failed to issue method call: %s", bus_error_message(error));
1530 if (!dbus_message_get_args(reply, error,
1531 DBUS_TYPE_OBJECT_PATH, &path,
1532 DBUS_TYPE_INVALID)) {
1533 log_error("Failed to parse reply: %s", bus_error_message(error));
1538 if (need_daemon_reload(bus, name))
1539 log_warning("Warning: Unit file of created job changed on disk, 'systemctl %s daemon-reload' recommended.",
1540 arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
1542 if (!arg_no_block) {
1545 if (!(p = strdup(path))) {
1546 log_error("Failed to duplicate path.");
1551 if ((r = set_put(s, p)) < 0) {
1553 log_error("Failed to add path to set.");
1562 dbus_message_unref(m);
1565 dbus_message_unref(reply);
1570 static enum action verb_to_action(const char *verb) {
1571 if (streq(verb, "halt"))
1573 else if (streq(verb, "poweroff"))
1574 return ACTION_POWEROFF;
1575 else if (streq(verb, "reboot"))
1576 return ACTION_REBOOT;
1577 else if (streq(verb, "kexec"))
1578 return ACTION_KEXEC;
1579 else if (streq(verb, "rescue"))
1580 return ACTION_RESCUE;
1581 else if (streq(verb, "emergency"))
1582 return ACTION_EMERGENCY;
1583 else if (streq(verb, "default"))
1584 return ACTION_DEFAULT;
1585 else if (streq(verb, "exit"))
1588 return ACTION_INVALID;
1591 static int start_unit(DBusConnection *bus, char **args) {
1593 static const char * const table[_ACTION_MAX] = {
1594 [ACTION_HALT] = SPECIAL_HALT_TARGET,
1595 [ACTION_POWEROFF] = SPECIAL_POWEROFF_TARGET,
1596 [ACTION_REBOOT] = SPECIAL_REBOOT_TARGET,
1597 [ACTION_KEXEC] = SPECIAL_KEXEC_TARGET,
1598 [ACTION_RUNLEVEL2] = SPECIAL_RUNLEVEL2_TARGET,
1599 [ACTION_RUNLEVEL3] = SPECIAL_RUNLEVEL3_TARGET,
1600 [ACTION_RUNLEVEL4] = SPECIAL_RUNLEVEL4_TARGET,
1601 [ACTION_RUNLEVEL5] = SPECIAL_RUNLEVEL5_TARGET,
1602 [ACTION_RESCUE] = SPECIAL_RESCUE_TARGET,
1603 [ACTION_EMERGENCY] = SPECIAL_EMERGENCY_TARGET,
1604 [ACTION_DEFAULT] = SPECIAL_DEFAULT_TARGET,
1605 [ACTION_EXIT] = SPECIAL_EXIT_TARGET
1609 const char *method, *mode, *one_name;
1614 dbus_error_init(&error);
1618 ask_password_agent_open_if_enabled();
1620 if (arg_action == ACTION_SYSTEMCTL) {
1622 streq(args[0], "stop") ||
1623 streq(args[0], "condstop") ? "StopUnit" :
1624 streq(args[0], "reload") ? "ReloadUnit" :
1625 streq(args[0], "restart") ? "RestartUnit" :
1627 streq(args[0], "try-restart") ||
1628 streq(args[0], "condrestart") ? "TryRestartUnit" :
1630 streq(args[0], "reload-or-restart") ? "ReloadOrRestartUnit" :
1632 streq(args[0], "reload-or-try-restart") ||
1633 streq(args[0], "condreload") ||
1635 streq(args[0], "force-reload") ? "ReloadOrTryRestartUnit" :
1639 (streq(args[0], "isolate") ||
1640 streq(args[0], "rescue") ||
1641 streq(args[0], "emergency")) ? "isolate" : arg_job_mode;
1643 one_name = table[verb_to_action(args[0])];
1646 assert(arg_action < ELEMENTSOF(table));
1647 assert(table[arg_action]);
1649 method = "StartUnit";
1651 mode = (arg_action == ACTION_EMERGENCY ||
1652 arg_action == ACTION_RESCUE ||
1653 arg_action == ACTION_RUNLEVEL2 ||
1654 arg_action == ACTION_RUNLEVEL3 ||
1655 arg_action == ACTION_RUNLEVEL4 ||
1656 arg_action == ACTION_RUNLEVEL5) ? "isolate" : "replace";
1658 one_name = table[arg_action];
1661 if (!arg_no_block) {
1662 if ((ret = enable_wait_for_jobs(bus)) < 0) {
1663 log_error("Could not watch jobs: %s", strerror(-ret));
1667 if (!(s = set_new(string_hash_func, string_compare_func))) {
1668 log_error("Failed to allocate set.");
1675 if ((ret = start_unit_one(bus, method, one_name, mode, &error, s)) <= 0)
1678 STRV_FOREACH(name, args+1)
1679 if ((r = start_unit_one(bus, method, *name, mode, &error, s)) != 0) {
1680 ret = translate_bus_error_to_exit_status(r, &error);
1681 dbus_error_free(&error);
1686 if ((r = wait_for_jobs(bus, s)) < 0) {
1695 dbus_error_free(&error);
1700 /* Ask systemd-logind, which might grant access to unprivileged users
1701 * through PolicyKit */
1702 static int reboot_with_logind(DBusConnection *bus, enum action a) {
1705 DBusMessage *m = NULL, *reply = NULL;
1707 dbus_bool_t interactive = true;
1710 dbus_error_init(&error);
1712 polkit_agent_open_if_enabled();
1720 case ACTION_POWEROFF:
1721 method = "PowerOff";
1728 m = dbus_message_new_method_call(
1729 "org.freedesktop.login1",
1730 "/org/freedesktop/login1",
1731 "org.freedesktop.login1.Manager",
1734 log_error("Could not allocate message.");
1739 if (!dbus_message_append_args(m,
1740 DBUS_TYPE_BOOLEAN, &interactive,
1741 DBUS_TYPE_INVALID)) {
1742 log_error("Could not append arguments to message.");
1747 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
1749 if (error_is_no_service(&error)) {
1750 log_debug("Failed to issue method call: %s", bus_error_message(&error));
1755 if (dbus_error_has_name(&error, DBUS_ERROR_ACCESS_DENIED)) {
1756 log_debug("Failed to issue method call: %s", bus_error_message(&error));
1761 log_info("Failed to issue method call: %s", bus_error_message(&error));
1770 dbus_message_unref(m);
1773 dbus_message_unref(reply);
1775 dbus_error_free(&error);
1783 static int start_special(DBusConnection *bus, char **args) {
1790 a = verb_to_action(args[0]);
1792 if (arg_force >= 2 &&
1793 (a == ACTION_HALT ||
1794 a == ACTION_POWEROFF ||
1795 a == ACTION_REBOOT))
1798 if (arg_force >= 1 &&
1799 (a == ACTION_HALT ||
1800 a == ACTION_POWEROFF ||
1801 a == ACTION_REBOOT ||
1802 a == ACTION_KEXEC ||
1804 return daemon_reload(bus, args);
1806 /* first try logind, to allow authentication with polkit */
1807 if (geteuid() != 0 &&
1808 (a == ACTION_POWEROFF ||
1809 a == ACTION_REBOOT)) {
1810 r = reboot_with_logind(bus, a);
1815 r = start_unit(bus, args);
1822 static int check_unit(DBusConnection *bus, char **args) {
1823 DBusMessage *m = NULL, *reply = NULL;
1825 *interface = "org.freedesktop.systemd1.Unit",
1826 *property = "ActiveState";
1827 int r = 3; /* According to LSB: "program is not running" */
1834 dbus_error_init(&error);
1836 STRV_FOREACH(name, args+1) {
1837 const char *path = NULL;
1839 DBusMessageIter iter, sub;
1841 if (!(m = dbus_message_new_method_call(
1842 "org.freedesktop.systemd1",
1843 "/org/freedesktop/systemd1",
1844 "org.freedesktop.systemd1.Manager",
1846 log_error("Could not allocate message.");
1851 if (!dbus_message_append_args(m,
1852 DBUS_TYPE_STRING, name,
1853 DBUS_TYPE_INVALID)) {
1854 log_error("Could not append arguments to message.");
1859 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
1861 /* Hmm, cannot figure out anything about this unit... */
1865 dbus_error_free(&error);
1866 dbus_message_unref(m);
1871 if (!dbus_message_get_args(reply, &error,
1872 DBUS_TYPE_OBJECT_PATH, &path,
1873 DBUS_TYPE_INVALID)) {
1874 log_error("Failed to parse reply: %s", bus_error_message(&error));
1879 dbus_message_unref(m);
1880 if (!(m = dbus_message_new_method_call(
1881 "org.freedesktop.systemd1",
1883 "org.freedesktop.DBus.Properties",
1885 log_error("Could not allocate message.");
1890 if (!dbus_message_append_args(m,
1891 DBUS_TYPE_STRING, &interface,
1892 DBUS_TYPE_STRING, &property,
1893 DBUS_TYPE_INVALID)) {
1894 log_error("Could not append arguments to message.");
1899 dbus_message_unref(reply);
1900 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
1901 log_error("Failed to issue method call: %s", bus_error_message(&error));
1906 if (!dbus_message_iter_init(reply, &iter) ||
1907 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1908 log_error("Failed to parse reply.");
1913 dbus_message_iter_recurse(&iter, &sub);
1915 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1916 log_error("Failed to parse reply.");
1921 dbus_message_iter_get_basic(&sub, &state);
1926 if (streq(state, "active") || streq(state, "reloading"))
1929 dbus_message_unref(m);
1930 dbus_message_unref(reply);
1936 dbus_message_unref(m);
1939 dbus_message_unref(reply);
1941 dbus_error_free(&error);
1946 static int kill_unit(DBusConnection *bus, char **args) {
1947 DBusMessage *m = NULL;
1955 dbus_error_init(&error);
1958 arg_kill_who = "all";
1961 arg_kill_mode = streq(arg_kill_who, "all") ? "control-group" : "process";
1963 STRV_FOREACH(name, args+1) {
1966 if (!(m = dbus_message_new_method_call(
1967 "org.freedesktop.systemd1",
1968 "/org/freedesktop/systemd1",
1969 "org.freedesktop.systemd1.Manager",
1971 log_error("Could not allocate message.");
1976 if (!dbus_message_append_args(m,
1977 DBUS_TYPE_STRING, name,
1978 DBUS_TYPE_STRING, &arg_kill_who,
1979 DBUS_TYPE_STRING, &arg_kill_mode,
1980 DBUS_TYPE_INT32, &arg_signal,
1981 DBUS_TYPE_INVALID)) {
1982 log_error("Could not append arguments to message.");
1987 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
1988 log_error("Failed to issue method call: %s", bus_error_message(&error));
1989 dbus_error_free(&error);
1993 dbus_message_unref(m);
1996 dbus_message_unref(reply);
2002 dbus_message_unref(m);
2004 dbus_error_free(&error);
2009 typedef struct ExecStatusInfo {
2017 usec_t start_timestamp;
2018 usec_t exit_timestamp;
2023 LIST_FIELDS(struct ExecStatusInfo, exec);
2026 static void exec_status_info_free(ExecStatusInfo *i) {
2035 static int exec_status_info_deserialize(DBusMessageIter *sub, ExecStatusInfo *i) {
2036 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
2037 DBusMessageIter sub2, sub3;
2041 int32_t code, status;
2047 if (dbus_message_iter_get_arg_type(sub) != DBUS_TYPE_STRUCT)
2050 dbus_message_iter_recurse(sub, &sub2);
2052 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0)
2055 if (!(i->path = strdup(path)))
2058 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_ARRAY ||
2059 dbus_message_iter_get_element_type(&sub2) != DBUS_TYPE_STRING)
2063 dbus_message_iter_recurse(&sub2, &sub3);
2064 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2065 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2066 dbus_message_iter_next(&sub3);
2071 if (!(i->argv = new0(char*, n+1)))
2075 dbus_message_iter_recurse(&sub2, &sub3);
2076 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2079 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2080 dbus_message_iter_get_basic(&sub3, &s);
2081 dbus_message_iter_next(&sub3);
2083 if (!(i->argv[n++] = strdup(s)))
2087 if (!dbus_message_iter_next(&sub2) ||
2088 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, true) < 0 ||
2089 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp, true) < 0 ||
2090 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp_monotonic, true) < 0 ||
2091 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp, true) < 0 ||
2092 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp_monotonic, true) < 0 ||
2093 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, true) < 0 ||
2094 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &code, true) < 0 ||
2095 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &status, false) < 0)
2099 i->start_timestamp = (usec_t) start_timestamp;
2100 i->exit_timestamp = (usec_t) exit_timestamp;
2101 i->pid = (pid_t) pid;
2108 typedef struct UnitStatusInfo {
2110 const char *load_state;
2111 const char *active_state;
2112 const char *sub_state;
2113 const char *unit_file_state;
2115 const char *description;
2116 const char *following;
2119 const char *default_control_group;
2121 const char *load_error;
2124 usec_t inactive_exit_timestamp;
2125 usec_t inactive_exit_timestamp_monotonic;
2126 usec_t active_enter_timestamp;
2127 usec_t active_exit_timestamp;
2128 usec_t inactive_enter_timestamp;
2130 bool need_daemon_reload;
2135 const char *status_text;
2137 #ifdef HAVE_SYSV_COMPAT
2141 usec_t start_timestamp;
2142 usec_t exit_timestamp;
2144 int exit_code, exit_status;
2146 usec_t condition_timestamp;
2147 bool condition_result;
2150 unsigned n_accepted;
2151 unsigned n_connections;
2155 const char *sysfs_path;
2157 /* Mount, Automount */
2163 LIST_HEAD(ExecStatusInfo, exec);
2166 static void print_status_info(UnitStatusInfo *i) {
2168 const char *on, *off, *ss;
2170 char since1[FORMAT_TIMESTAMP_PRETTY_MAX], *s1;
2171 char since2[FORMAT_TIMESTAMP_MAX], *s2;
2175 /* This shows pretty information about a unit. See
2176 * print_property() for a low-level property printer */
2178 printf("%s", strna(i->id));
2180 if (i->description && !streq_ptr(i->id, i->description))
2181 printf(" - %s", i->description);
2186 printf("\t Follow: unit currently follows state of %s\n", i->following);
2188 if (streq_ptr(i->load_state, "error")) {
2189 on = ansi_highlight_red(true);
2190 off = ansi_highlight_red(false);
2195 printf("\t Loaded: %s%s%s (Reason: %s)\n", on, strna(i->load_state), off, i->load_error);
2196 else if (i->path && i->unit_file_state)
2197 printf("\t Loaded: %s%s%s (%s; %s)\n", on, strna(i->load_state), off, i->path, i->unit_file_state);
2199 printf("\t Loaded: %s%s%s (%s)\n", on, strna(i->load_state), off, i->path);
2201 printf("\t Loaded: %s%s%s\n", on, strna(i->load_state), off);
2203 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
2205 if (streq_ptr(i->active_state, "failed")) {
2206 on = ansi_highlight_red(true);
2207 off = ansi_highlight_red(false);
2208 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
2209 on = ansi_highlight_green(true);
2210 off = ansi_highlight_green(false);
2215 printf("\t Active: %s%s (%s)%s",
2217 strna(i->active_state),
2221 printf("\t Active: %s%s%s",
2223 strna(i->active_state),
2226 if (!isempty(i->result) && !streq(i->result, "success"))
2227 printf(" (Result: %s)", i->result);
2229 timestamp = (streq_ptr(i->active_state, "active") ||
2230 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
2231 (streq_ptr(i->active_state, "inactive") ||
2232 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
2233 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
2234 i->active_exit_timestamp;
2236 s1 = format_timestamp_pretty(since1, sizeof(since1), timestamp);
2237 s2 = format_timestamp(since2, sizeof(since2), timestamp);
2240 printf(" since %s; %s\n", s2, s1);
2242 printf(" since %s\n", s2);
2246 if (!i->condition_result && i->condition_timestamp > 0) {
2247 s1 = format_timestamp_pretty(since1, sizeof(since1), i->condition_timestamp);
2248 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
2251 printf("\t start condition failed at %s; %s\n", s2, s1);
2253 printf("\t start condition failed at %s\n", s2);
2257 printf("\t Device: %s\n", i->sysfs_path);
2259 printf("\t Where: %s\n", i->where);
2261 printf("\t What: %s\n", i->what);
2264 printf("\tAccepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
2266 LIST_FOREACH(exec, p, i->exec) {
2270 /* Only show exited processes here */
2274 t = strv_join(p->argv, " ");
2275 printf("\t Process: %u %s=%s ", p->pid, p->name, strna(t));
2278 #ifdef HAVE_SYSV_COMPAT
2280 good = is_clean_exit_lsb(p->code, p->status);
2283 good = is_clean_exit(p->code, p->status);
2286 on = ansi_highlight_red(true);
2287 off = ansi_highlight_red(false);
2291 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
2293 if (p->code == CLD_EXITED) {
2296 printf("status=%i", p->status);
2298 #ifdef HAVE_SYSV_COMPAT
2299 if ((c = exit_status_to_string(p->status, i->is_sysv ? EXIT_STATUS_LSB : EXIT_STATUS_SYSTEMD)))
2301 if ((c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD)))
2306 printf("signal=%s", signal_to_string(p->status));
2308 printf(")%s\n", off);
2310 if (i->main_pid == p->pid &&
2311 i->start_timestamp == p->start_timestamp &&
2312 i->exit_timestamp == p->start_timestamp)
2313 /* Let's not show this twice */
2316 if (p->pid == i->control_pid)
2320 if (i->main_pid > 0 || i->control_pid > 0) {
2323 if (i->main_pid > 0) {
2324 printf("Main PID: %u", (unsigned) i->main_pid);
2328 get_process_comm(i->main_pid, &t);
2333 } else if (i->exit_code > 0) {
2334 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
2336 if (i->exit_code == CLD_EXITED) {
2339 printf("status=%i", i->exit_status);
2341 #ifdef HAVE_SYSV_COMPAT
2342 if ((c = exit_status_to_string(i->exit_status, i->is_sysv ? EXIT_STATUS_LSB : EXIT_STATUS_SYSTEMD)))
2344 if ((c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD)))
2349 printf("signal=%s", signal_to_string(i->exit_status));
2354 if (i->main_pid > 0 && i->control_pid > 0)
2357 if (i->control_pid > 0) {
2360 printf(" Control: %u", (unsigned) i->control_pid);
2362 get_process_comm(i->control_pid, &t);
2373 printf("\t Status: \"%s\"\n", i->status_text);
2375 if (i->default_control_group) {
2378 printf("\t CGroup: %s\n", i->default_control_group);
2380 if (arg_transport != TRANSPORT_SSH) {
2381 if ((c = columns()) > 18)
2386 show_cgroup_by_path(i->default_control_group, "\t\t ", c, false);
2390 if (i->id && arg_transport != TRANSPORT_SSH) {
2392 show_journal_by_unit(i->id, arg_output, 0, i->inactive_exit_timestamp_monotonic, arg_lines, arg_all, arg_follow);
2395 if (i->need_daemon_reload)
2396 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %s daemon-reload' recommended.\n",
2397 ansi_highlight_red(true),
2398 ansi_highlight_red(false),
2399 arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
2402 static int status_property(const char *name, DBusMessageIter *iter, UnitStatusInfo *i) {
2408 switch (dbus_message_iter_get_arg_type(iter)) {
2410 case DBUS_TYPE_STRING: {
2413 dbus_message_iter_get_basic(iter, &s);
2416 if (streq(name, "Id"))
2418 else if (streq(name, "LoadState"))
2420 else if (streq(name, "ActiveState"))
2421 i->active_state = s;
2422 else if (streq(name, "SubState"))
2424 else if (streq(name, "Description"))
2426 else if (streq(name, "FragmentPath"))
2428 #ifdef HAVE_SYSV_COMPAT
2429 else if (streq(name, "SysVPath")) {
2434 else if (streq(name, "DefaultControlGroup"))
2435 i->default_control_group = s;
2436 else if (streq(name, "StatusText"))
2438 else if (streq(name, "SysFSPath"))
2440 else if (streq(name, "Where"))
2442 else if (streq(name, "What"))
2444 else if (streq(name, "Following"))
2446 else if (streq(name, "UnitFileState"))
2447 i->unit_file_state = s;
2448 else if (streq(name, "Result"))
2455 case DBUS_TYPE_BOOLEAN: {
2458 dbus_message_iter_get_basic(iter, &b);
2460 if (streq(name, "Accept"))
2462 else if (streq(name, "NeedDaemonReload"))
2463 i->need_daemon_reload = b;
2464 else if (streq(name, "ConditionResult"))
2465 i->condition_result = b;
2470 case DBUS_TYPE_UINT32: {
2473 dbus_message_iter_get_basic(iter, &u);
2475 if (streq(name, "MainPID")) {
2477 i->main_pid = (pid_t) u;
2480 } else if (streq(name, "ControlPID"))
2481 i->control_pid = (pid_t) u;
2482 else if (streq(name, "ExecMainPID")) {
2484 i->main_pid = (pid_t) u;
2485 } else if (streq(name, "NAccepted"))
2487 else if (streq(name, "NConnections"))
2488 i->n_connections = u;
2493 case DBUS_TYPE_INT32: {
2496 dbus_message_iter_get_basic(iter, &j);
2498 if (streq(name, "ExecMainCode"))
2499 i->exit_code = (int) j;
2500 else if (streq(name, "ExecMainStatus"))
2501 i->exit_status = (int) j;
2506 case DBUS_TYPE_UINT64: {
2509 dbus_message_iter_get_basic(iter, &u);
2511 if (streq(name, "ExecMainStartTimestamp"))
2512 i->start_timestamp = (usec_t) u;
2513 else if (streq(name, "ExecMainExitTimestamp"))
2514 i->exit_timestamp = (usec_t) u;
2515 else if (streq(name, "ActiveEnterTimestamp"))
2516 i->active_enter_timestamp = (usec_t) u;
2517 else if (streq(name, "InactiveEnterTimestamp"))
2518 i->inactive_enter_timestamp = (usec_t) u;
2519 else if (streq(name, "InactiveExitTimestamp"))
2520 i->inactive_exit_timestamp = (usec_t) u;
2521 else if (streq(name, "InactiveExitTimestampMonotonic"))
2522 i->inactive_exit_timestamp_monotonic = (usec_t) u;
2523 else if (streq(name, "ActiveExitTimestamp"))
2524 i->active_exit_timestamp = (usec_t) u;
2525 else if (streq(name, "ConditionTimestamp"))
2526 i->condition_timestamp = (usec_t) u;
2531 case DBUS_TYPE_ARRAY: {
2533 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
2534 startswith(name, "Exec")) {
2535 DBusMessageIter sub;
2537 dbus_message_iter_recurse(iter, &sub);
2538 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2539 ExecStatusInfo *info;
2542 if (!(info = new0(ExecStatusInfo, 1)))
2545 if (!(info->name = strdup(name))) {
2550 if ((r = exec_status_info_deserialize(&sub, info)) < 0) {
2555 LIST_PREPEND(ExecStatusInfo, exec, i->exec, info);
2557 dbus_message_iter_next(&sub);
2564 case DBUS_TYPE_STRUCT: {
2566 if (streq(name, "LoadError")) {
2567 DBusMessageIter sub;
2568 const char *n, *message;
2571 dbus_message_iter_recurse(iter, &sub);
2573 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &n, true);
2577 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &message, false);
2581 if (!isempty(message))
2582 i->load_error = message;
2592 static int print_property(const char *name, DBusMessageIter *iter) {
2596 /* This is a low-level property printer, see
2597 * print_status_info() for the nicer output */
2599 if (arg_property && !strv_find(arg_property, name))
2602 switch (dbus_message_iter_get_arg_type(iter)) {
2604 case DBUS_TYPE_STRUCT: {
2605 DBusMessageIter sub;
2606 dbus_message_iter_recurse(iter, &sub);
2608 if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32 && streq(name, "Job")) {
2611 dbus_message_iter_get_basic(&sub, &u);
2614 printf("%s=%u\n", name, (unsigned) u);
2616 printf("%s=\n", name);
2619 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "Unit")) {
2622 dbus_message_iter_get_basic(&sub, &s);
2624 if (arg_all || s[0])
2625 printf("%s=%s\n", name, s);
2628 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "LoadError")) {
2629 const char *a = NULL, *b = NULL;
2631 if (bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &a, true) >= 0)
2632 bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &b, false);
2634 if (arg_all || !isempty(a) || !isempty(b))
2635 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
2643 case DBUS_TYPE_ARRAY:
2645 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "EnvironmentFiles")) {
2646 DBusMessageIter sub, sub2;
2648 dbus_message_iter_recurse(iter, &sub);
2649 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2653 dbus_message_iter_recurse(&sub, &sub2);
2655 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
2656 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) >= 0)
2657 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
2659 dbus_message_iter_next(&sub);
2664 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Paths")) {
2665 DBusMessageIter sub, sub2;
2667 dbus_message_iter_recurse(iter, &sub);
2668 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2669 const char *type, *path;
2671 dbus_message_iter_recurse(&sub, &sub2);
2673 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
2674 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
2675 printf("%s=%s\n", type, path);
2677 dbus_message_iter_next(&sub);
2682 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Timers")) {
2683 DBusMessageIter sub, sub2;
2685 dbus_message_iter_recurse(iter, &sub);
2686 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2688 uint64_t value, next_elapse;
2690 dbus_message_iter_recurse(&sub, &sub2);
2692 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &base, true) >= 0 &&
2693 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &value, true) >= 0 &&
2694 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &next_elapse, false) >= 0) {
2695 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
2697 printf("%s={ value=%s ; next_elapse=%s }\n",
2699 format_timespan(timespan1, sizeof(timespan1), value),
2700 format_timespan(timespan2, sizeof(timespan2), next_elapse));
2703 dbus_message_iter_next(&sub);
2708 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "ControlGroupAttributes")) {
2709 DBusMessageIter sub, sub2;
2711 dbus_message_iter_recurse(iter, &sub);
2712 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2713 const char *controller, *attr, *value;
2715 dbus_message_iter_recurse(&sub, &sub2);
2717 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &controller, true) >= 0 &&
2718 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &attr, true) >= 0 &&
2719 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &value, false) >= 0) {
2721 printf("ControlGroupAttribute={ controller=%s ; attribute=%s ; value=\"%s\" }\n",
2727 dbus_message_iter_next(&sub);
2732 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && startswith(name, "Exec")) {
2733 DBusMessageIter sub;
2735 dbus_message_iter_recurse(iter, &sub);
2736 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2737 ExecStatusInfo info;
2740 if (exec_status_info_deserialize(&sub, &info) >= 0) {
2741 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
2744 t = strv_join(info.argv, " ");
2746 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
2750 yes_no(info.ignore),
2751 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
2752 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
2753 (unsigned) info. pid,
2754 sigchld_code_to_string(info.code),
2756 info.code == CLD_EXITED ? "" : "/",
2757 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
2763 strv_free(info.argv);
2765 dbus_message_iter_next(&sub);
2774 if (generic_print_property(name, iter, arg_all) > 0)
2778 printf("%s=[unprintable]\n", name);
2783 static int show_one(const char *verb, DBusConnection *bus, const char *path, bool show_properties, bool *new_line) {
2784 DBusMessage *m = NULL, *reply = NULL;
2785 const char *interface = "";
2788 DBusMessageIter iter, sub, sub2, sub3;
2789 UnitStatusInfo info;
2797 dbus_error_init(&error);
2799 if (!(m = dbus_message_new_method_call(
2800 "org.freedesktop.systemd1",
2802 "org.freedesktop.DBus.Properties",
2804 log_error("Could not allocate message.");
2809 if (!dbus_message_append_args(m,
2810 DBUS_TYPE_STRING, &interface,
2811 DBUS_TYPE_INVALID)) {
2812 log_error("Could not append arguments to message.");
2817 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
2818 log_error("Failed to issue method call: %s", bus_error_message(&error));
2823 if (!dbus_message_iter_init(reply, &iter) ||
2824 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
2825 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
2826 log_error("Failed to parse reply.");
2831 dbus_message_iter_recurse(&iter, &sub);
2838 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
2841 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_DICT_ENTRY) {
2842 log_error("Failed to parse reply.");
2847 dbus_message_iter_recurse(&sub, &sub2);
2849 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0) {
2850 log_error("Failed to parse reply.");
2855 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
2856 log_error("Failed to parse reply.");
2861 dbus_message_iter_recurse(&sub2, &sub3);
2863 if (show_properties)
2864 r = print_property(name, &sub3);
2866 r = status_property(name, &sub3, &info);
2869 log_error("Failed to parse reply.");
2874 dbus_message_iter_next(&sub);
2879 if (!show_properties)
2880 print_status_info(&info);
2882 if (!streq_ptr(info.active_state, "active") &&
2883 !streq_ptr(info.active_state, "reloading") &&
2884 streq(verb, "status"))
2885 /* According to LSB: "program not running" */
2888 while ((p = info.exec)) {
2889 LIST_REMOVE(ExecStatusInfo, exec, info.exec, p);
2890 exec_status_info_free(p);
2895 dbus_message_unref(m);
2898 dbus_message_unref(reply);
2900 dbus_error_free(&error);
2905 static int show(DBusConnection *bus, char **args) {
2906 DBusMessage *m = NULL, *reply = NULL;
2909 bool show_properties, new_line = false;
2915 dbus_error_init(&error);
2917 show_properties = !streq(args[0], "status");
2919 if (show_properties)
2920 pager_open_if_enabled();
2922 if (show_properties && strv_length(args) <= 1) {
2923 /* If not argument is specified inspect the manager
2926 ret = show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line);
2930 STRV_FOREACH(name, args+1) {
2931 const char *path = NULL;
2934 if (safe_atou32(*name, &id) < 0) {
2936 /* Interpret as unit name */
2938 if (!(m = dbus_message_new_method_call(
2939 "org.freedesktop.systemd1",
2940 "/org/freedesktop/systemd1",
2941 "org.freedesktop.systemd1.Manager",
2943 log_error("Could not allocate message.");
2948 if (!dbus_message_append_args(m,
2949 DBUS_TYPE_STRING, name,
2950 DBUS_TYPE_INVALID)) {
2951 log_error("Could not append arguments to message.");
2956 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
2958 if (!dbus_error_has_name(&error, DBUS_ERROR_ACCESS_DENIED)) {
2959 log_error("Failed to issue method call: %s", bus_error_message(&error));
2964 dbus_error_free(&error);
2966 dbus_message_unref(m);
2967 if (!(m = dbus_message_new_method_call(
2968 "org.freedesktop.systemd1",
2969 "/org/freedesktop/systemd1",
2970 "org.freedesktop.systemd1.Manager",
2972 log_error("Could not allocate message.");
2977 if (!dbus_message_append_args(m,
2978 DBUS_TYPE_STRING, name,
2979 DBUS_TYPE_INVALID)) {
2980 log_error("Could not append arguments to message.");
2985 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
2986 log_error("Failed to issue method call: %s", bus_error_message(&error));
2988 if (dbus_error_has_name(&error, BUS_ERROR_NO_SUCH_UNIT))
2989 ret = 4; /* According to LSB: "program or service status is unknown" */
2996 } else if (show_properties) {
2998 /* Interpret as job id */
3000 if (!(m = dbus_message_new_method_call(
3001 "org.freedesktop.systemd1",
3002 "/org/freedesktop/systemd1",
3003 "org.freedesktop.systemd1.Manager",
3005 log_error("Could not allocate message.");
3010 if (!dbus_message_append_args(m,
3011 DBUS_TYPE_UINT32, &id,
3012 DBUS_TYPE_INVALID)) {
3013 log_error("Could not append arguments to message.");
3018 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3019 log_error("Failed to issue method call: %s", bus_error_message(&error));
3025 /* Interpret as PID */
3027 if (!(m = dbus_message_new_method_call(
3028 "org.freedesktop.systemd1",
3029 "/org/freedesktop/systemd1",
3030 "org.freedesktop.systemd1.Manager",
3032 log_error("Could not allocate message.");
3037 if (!dbus_message_append_args(m,
3038 DBUS_TYPE_UINT32, &id,
3039 DBUS_TYPE_INVALID)) {
3040 log_error("Could not append arguments to message.");
3045 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3046 log_error("Failed to issue method call: %s", bus_error_message(&error));
3052 if (!dbus_message_get_args(reply, &error,
3053 DBUS_TYPE_OBJECT_PATH, &path,
3054 DBUS_TYPE_INVALID)) {
3055 log_error("Failed to parse reply: %s", bus_error_message(&error));
3060 if ((r = show_one(args[0], bus, path, show_properties, &new_line)) != 0)
3063 dbus_message_unref(m);
3064 dbus_message_unref(reply);
3070 dbus_message_unref(m);
3073 dbus_message_unref(reply);
3075 dbus_error_free(&error);
3080 static int dump(DBusConnection *bus, char **args) {
3081 DBusMessage *m = NULL, *reply = NULL;
3086 dbus_error_init(&error);
3088 pager_open_if_enabled();
3090 if (!(m = dbus_message_new_method_call(
3091 "org.freedesktop.systemd1",
3092 "/org/freedesktop/systemd1",
3093 "org.freedesktop.systemd1.Manager",
3095 log_error("Could not allocate message.");
3099 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3100 log_error("Failed to issue method call: %s", bus_error_message(&error));
3105 if (!dbus_message_get_args(reply, &error,
3106 DBUS_TYPE_STRING, &text,
3107 DBUS_TYPE_INVALID)) {
3108 log_error("Failed to parse reply: %s", bus_error_message(&error));
3113 fputs(text, stdout);
3119 dbus_message_unref(m);
3122 dbus_message_unref(reply);
3124 dbus_error_free(&error);
3129 static int snapshot(DBusConnection *bus, char **args) {
3130 DBusMessage *m = NULL, *reply = NULL;
3133 const char *name = "", *path, *id;
3134 dbus_bool_t cleanup = FALSE;
3135 DBusMessageIter iter, sub;
3137 *interface = "org.freedesktop.systemd1.Unit",
3140 dbus_error_init(&error);
3142 if (!(m = dbus_message_new_method_call(
3143 "org.freedesktop.systemd1",
3144 "/org/freedesktop/systemd1",
3145 "org.freedesktop.systemd1.Manager",
3146 "CreateSnapshot"))) {
3147 log_error("Could not allocate message.");
3151 if (strv_length(args) > 1)
3154 if (!dbus_message_append_args(m,
3155 DBUS_TYPE_STRING, &name,
3156 DBUS_TYPE_BOOLEAN, &cleanup,
3157 DBUS_TYPE_INVALID)) {
3158 log_error("Could not append arguments to message.");
3163 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3164 log_error("Failed to issue method call: %s", bus_error_message(&error));
3169 if (!dbus_message_get_args(reply, &error,
3170 DBUS_TYPE_OBJECT_PATH, &path,
3171 DBUS_TYPE_INVALID)) {
3172 log_error("Failed to parse reply: %s", bus_error_message(&error));
3177 dbus_message_unref(m);
3178 if (!(m = dbus_message_new_method_call(
3179 "org.freedesktop.systemd1",
3181 "org.freedesktop.DBus.Properties",
3183 log_error("Could not allocate message.");
3187 if (!dbus_message_append_args(m,
3188 DBUS_TYPE_STRING, &interface,
3189 DBUS_TYPE_STRING, &property,
3190 DBUS_TYPE_INVALID)) {
3191 log_error("Could not append arguments to message.");
3196 dbus_message_unref(reply);
3197 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3198 log_error("Failed to issue method call: %s", bus_error_message(&error));
3203 if (!dbus_message_iter_init(reply, &iter) ||
3204 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3205 log_error("Failed to parse reply.");
3210 dbus_message_iter_recurse(&iter, &sub);
3212 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
3213 log_error("Failed to parse reply.");
3218 dbus_message_iter_get_basic(&sub, &id);
3226 dbus_message_unref(m);
3229 dbus_message_unref(reply);
3231 dbus_error_free(&error);
3236 static int delete_snapshot(DBusConnection *bus, char **args) {
3237 DBusMessage *m = NULL, *reply = NULL;
3245 dbus_error_init(&error);
3247 STRV_FOREACH(name, args+1) {
3248 const char *path = NULL;
3250 if (!(m = dbus_message_new_method_call(
3251 "org.freedesktop.systemd1",
3252 "/org/freedesktop/systemd1",
3253 "org.freedesktop.systemd1.Manager",
3255 log_error("Could not allocate message.");
3260 if (!dbus_message_append_args(m,
3261 DBUS_TYPE_STRING, name,
3262 DBUS_TYPE_INVALID)) {
3263 log_error("Could not append arguments to message.");
3268 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3269 log_error("Failed to issue method call: %s", bus_error_message(&error));
3274 if (!dbus_message_get_args(reply, &error,
3275 DBUS_TYPE_OBJECT_PATH, &path,
3276 DBUS_TYPE_INVALID)) {
3277 log_error("Failed to parse reply: %s", bus_error_message(&error));
3282 dbus_message_unref(m);
3283 if (!(m = dbus_message_new_method_call(
3284 "org.freedesktop.systemd1",
3286 "org.freedesktop.systemd1.Snapshot",
3288 log_error("Could not allocate message.");
3293 dbus_message_unref(reply);
3294 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3295 log_error("Failed to issue method call: %s", bus_error_message(&error));
3300 dbus_message_unref(m);
3301 dbus_message_unref(reply);
3309 dbus_message_unref(m);
3312 dbus_message_unref(reply);
3314 dbus_error_free(&error);
3319 static int daemon_reload(DBusConnection *bus, char **args) {
3320 DBusMessage *m = NULL, *reply = NULL;
3325 dbus_error_init(&error);
3327 if (arg_action == ACTION_RELOAD)
3329 else if (arg_action == ACTION_REEXEC)
3330 method = "Reexecute";
3332 assert(arg_action == ACTION_SYSTEMCTL);
3335 streq(args[0], "clear-jobs") ||
3336 streq(args[0], "cancel") ? "ClearJobs" :
3337 streq(args[0], "daemon-reexec") ? "Reexecute" :
3338 streq(args[0], "reset-failed") ? "ResetFailed" :
3339 streq(args[0], "halt") ? "Halt" :
3340 streq(args[0], "poweroff") ? "PowerOff" :
3341 streq(args[0], "reboot") ? "Reboot" :
3342 streq(args[0], "kexec") ? "KExec" :
3343 streq(args[0], "exit") ? "Exit" :
3344 /* "daemon-reload" */ "Reload";
3347 if (!(m = dbus_message_new_method_call(
3348 "org.freedesktop.systemd1",
3349 "/org/freedesktop/systemd1",
3350 "org.freedesktop.systemd1.Manager",
3352 log_error("Could not allocate message.");
3356 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3358 if (arg_action != ACTION_SYSTEMCTL && error_is_no_service(&error)) {
3359 /* There's always a fallback possible for
3360 * legacy actions. */
3365 if (streq(method, "Reexecute") && dbus_error_has_name(&error, DBUS_ERROR_NO_REPLY)) {
3366 /* On reexecution, we expect a disconnect, not
3372 log_error("Failed to issue method call: %s", bus_error_message(&error));
3381 dbus_message_unref(m);
3384 dbus_message_unref(reply);
3386 dbus_error_free(&error);
3391 static int reset_failed(DBusConnection *bus, char **args) {
3392 DBusMessage *m = NULL;
3398 dbus_error_init(&error);
3400 if (strv_length(args) <= 1)
3401 return daemon_reload(bus, args);
3403 STRV_FOREACH(name, args+1) {
3406 if (!(m = dbus_message_new_method_call(
3407 "org.freedesktop.systemd1",
3408 "/org/freedesktop/systemd1",
3409 "org.freedesktop.systemd1.Manager",
3410 "ResetFailedUnit"))) {
3411 log_error("Could not allocate message.");
3416 if (!dbus_message_append_args(m,
3417 DBUS_TYPE_STRING, name,
3418 DBUS_TYPE_INVALID)) {
3419 log_error("Could not append arguments to message.");
3424 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3425 log_error("Failed to issue method call: %s", bus_error_message(&error));
3430 dbus_message_unref(m);
3431 dbus_message_unref(reply);
3439 dbus_message_unref(m);
3441 dbus_error_free(&error);
3446 static int show_enviroment(DBusConnection *bus, char **args) {
3447 DBusMessage *m = NULL, *reply = NULL;
3449 DBusMessageIter iter, sub, sub2;
3452 *interface = "org.freedesktop.systemd1.Manager",
3453 *property = "Environment";
3455 dbus_error_init(&error);
3457 pager_open_if_enabled();
3459 if (!(m = dbus_message_new_method_call(
3460 "org.freedesktop.systemd1",
3461 "/org/freedesktop/systemd1",
3462 "org.freedesktop.DBus.Properties",
3464 log_error("Could not allocate message.");
3468 if (!dbus_message_append_args(m,
3469 DBUS_TYPE_STRING, &interface,
3470 DBUS_TYPE_STRING, &property,
3471 DBUS_TYPE_INVALID)) {
3472 log_error("Could not append arguments to message.");
3477 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3478 log_error("Failed to issue method call: %s", bus_error_message(&error));
3483 if (!dbus_message_iter_init(reply, &iter) ||
3484 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3485 log_error("Failed to parse reply.");
3490 dbus_message_iter_recurse(&iter, &sub);
3492 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_ARRAY ||
3493 dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_STRING) {
3494 log_error("Failed to parse reply.");
3499 dbus_message_iter_recurse(&sub, &sub2);
3501 while (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_INVALID) {
3504 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
3505 log_error("Failed to parse reply.");
3510 dbus_message_iter_get_basic(&sub2, &text);
3511 printf("%s\n", text);
3513 dbus_message_iter_next(&sub2);
3520 dbus_message_unref(m);
3523 dbus_message_unref(reply);
3525 dbus_error_free(&error);
3530 static int set_environment(DBusConnection *bus, char **args) {
3531 DBusMessage *m = NULL, *reply = NULL;
3535 DBusMessageIter iter, sub;
3538 dbus_error_init(&error);
3540 method = streq(args[0], "set-environment")
3542 : "UnsetEnvironment";
3544 if (!(m = dbus_message_new_method_call(
3545 "org.freedesktop.systemd1",
3546 "/org/freedesktop/systemd1",
3547 "org.freedesktop.systemd1.Manager",
3550 log_error("Could not allocate message.");
3554 dbus_message_iter_init_append(m, &iter);
3556 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub)) {
3557 log_error("Could not append arguments to message.");
3562 STRV_FOREACH(name, args+1)
3563 if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, name)) {
3564 log_error("Could not append arguments to message.");
3569 if (!dbus_message_iter_close_container(&iter, &sub)) {
3570 log_error("Could not append arguments to message.");
3575 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3576 log_error("Failed to issue method call: %s", bus_error_message(&error));
3585 dbus_message_unref(m);
3588 dbus_message_unref(reply);
3590 dbus_error_free(&error);
3595 static int enable_sysv_units(char **args) {
3598 #if defined (HAVE_SYSV_COMPAT) && (defined(TARGET_FEDORA) || defined(TARGET_MANDRIVA) || defined(TARGET_SUSE) || defined(TARGET_MEEGO) || defined(TARGET_ALTLINUX) || defined(TARGET_MAGEIA))
3599 const char *verb = args[0];
3600 unsigned f = 1, t = 1;
3603 if (arg_scope != UNIT_FILE_SYSTEM)
3606 if (!streq(verb, "enable") &&
3607 !streq(verb, "disable") &&
3608 !streq(verb, "is-enabled"))
3611 /* Processes all SysV units, and reshuffles the array so that
3612 * afterwards only the native units remain */
3615 r = lookup_paths_init(&paths, MANAGER_SYSTEM, false);
3621 for (f = 1; args[f]; f++) {
3624 bool found_native = false, found_sysv;
3626 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
3627 char **k, *l, *q = NULL;
3634 if (!endswith(name, ".service"))
3637 if (path_is_absolute(name))
3640 STRV_FOREACH(k, paths.unit_path) {
3643 if (!isempty(arg_root))
3644 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
3646 asprintf(&p, "%s/%s", *k, name);
3649 log_error("No memory");
3654 found_native = access(p, F_OK) >= 0;
3665 if (!isempty(arg_root))
3666 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
3668 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
3670 log_error("No memory");
3675 p[strlen(p) - sizeof(".service") + 1] = 0;
3676 found_sysv = access(p, F_OK) >= 0;
3683 /* Mark this entry, so that we don't try enabling it as native unit */
3684 args[f] = (char*) "";
3686 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
3688 if (!isempty(arg_root))
3689 argv[c++] = q = strappend("--root=", arg_root);
3691 argv[c++] = file_name_from_path(p);
3693 streq(verb, "enable") ? "on" :
3694 streq(verb, "disable") ? "off" : "--level=5";
3697 l = strv_join((char**)argv, " ");
3699 log_error("No memory.");
3706 log_info("Executing %s", l);
3711 log_error("Failed to fork: %m");
3716 } else if (pid == 0) {
3719 execv(argv[0], (char**) argv);
3720 _exit(EXIT_FAILURE);
3726 j = wait_for_terminate(pid, &status);
3728 log_error("Failed to wait for child: %s", strerror(-r));
3733 if (status.si_code == CLD_EXITED) {
3734 if (streq(verb, "is-enabled")) {
3735 if (status.si_status == 0) {
3744 } else if (status.si_status != 0) {
3755 lookup_paths_free(&paths);
3757 /* Drop all SysV units */
3758 for (f = 1, t = 1; args[f]; f++) {
3760 if (isempty(args[f]))
3763 args[t++] = args[f];
3772 static int enable_unit(DBusConnection *bus, char **args) {
3773 const char *verb = args[0];
3774 UnitFileChange *changes = NULL;
3775 unsigned n_changes = 0, i;
3776 int carries_install_info = -1;
3777 DBusMessage *m = NULL, *reply = NULL;
3781 r = enable_sysv_units(args);
3788 dbus_error_init(&error);
3790 if (!bus || avoid_bus()) {
3791 if (streq(verb, "enable")) {
3792 r = unit_file_enable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3793 carries_install_info = r;
3794 } else if (streq(verb, "disable"))
3795 r = unit_file_disable(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3796 else if (streq(verb, "reenable")) {
3797 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3798 carries_install_info = r;
3799 } else if (streq(verb, "link"))
3800 r = unit_file_link(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3801 else if (streq(verb, "preset")) {
3802 r = unit_file_preset(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3803 carries_install_info = r;
3804 } else if (streq(verb, "mask"))
3805 r = unit_file_mask(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3806 else if (streq(verb, "unmask"))
3807 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3809 assert_not_reached("Unknown verb");
3812 log_error("Operation failed: %s", strerror(-r));
3817 for (i = 0; i < n_changes; i++) {
3818 if (changes[i].type == UNIT_FILE_SYMLINK)
3819 log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
3821 log_info("rm '%s'", changes[i].path);
3827 bool send_force = true, expect_carries_install_info = false;
3829 DBusMessageIter iter, sub, sub2;
3831 if (streq(verb, "enable")) {
3832 method = "EnableUnitFiles";
3833 expect_carries_install_info = true;
3834 } else if (streq(verb, "disable")) {
3835 method = "DisableUnitFiles";
3837 } else if (streq(verb, "reenable")) {
3838 method = "ReenableUnitFiles";
3839 expect_carries_install_info = true;
3840 } else if (streq(verb, "link"))
3841 method = "LinkUnitFiles";
3842 else if (streq(verb, "preset")) {
3843 method = "PresetUnitFiles";
3844 expect_carries_install_info = true;
3845 } else if (streq(verb, "mask"))
3846 method = "MaskUnitFiles";
3847 else if (streq(verb, "unmask")) {
3848 method = "UnmaskUnitFiles";
3851 assert_not_reached("Unknown verb");
3853 m = dbus_message_new_method_call(
3854 "org.freedesktop.systemd1",
3855 "/org/freedesktop/systemd1",
3856 "org.freedesktop.systemd1.Manager",
3859 log_error("Out of memory");
3864 dbus_message_iter_init_append(m, &iter);
3866 r = bus_append_strv_iter(&iter, args+1);
3868 log_error("Failed to append unit files.");
3873 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &a)) {
3874 log_error("Failed to append runtime boolean.");
3882 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b)) {
3883 log_error("Failed to append force boolean.");
3889 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3891 log_error("Failed to issue method call: %s", bus_error_message(&error));
3896 if (!dbus_message_iter_init(reply, &iter)) {
3897 log_error("Failed to initialize iterator.");
3901 if (expect_carries_install_info) {
3902 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &b, true);
3904 log_error("Failed to parse reply.");
3908 carries_install_info = b;
3911 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3912 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
3913 log_error("Failed to parse reply.");
3918 dbus_message_iter_recurse(&iter, &sub);
3919 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
3920 const char *type, *path, *source;
3922 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
3923 log_error("Failed to parse reply.");
3928 dbus_message_iter_recurse(&sub, &sub2);
3930 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
3931 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
3932 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &source, false) < 0) {
3933 log_error("Failed to parse reply.");
3939 if (streq(type, "symlink"))
3940 log_info("ln -s '%s' '%s'", source, path);
3942 log_info("rm '%s'", path);
3945 dbus_message_iter_next(&sub);
3948 /* Try to reload if enabeld */
3950 r = daemon_reload(bus, args);
3953 if (carries_install_info == 0)
3954 log_warning("Warning: unit files do not carry install information. No operation executed.");
3958 dbus_message_unref(m);
3961 dbus_message_unref(reply);
3963 unit_file_changes_free(changes, n_changes);
3965 dbus_error_free(&error);
3969 static int unit_is_enabled(DBusConnection *bus, char **args) {
3972 DBusMessage *m = NULL, *reply = NULL;
3976 dbus_error_init(&error);
3978 r = enable_sysv_units(args);
3984 if (!bus || avoid_bus()) {
3986 STRV_FOREACH(name, args+1) {
3987 UnitFileState state;
3989 state = unit_file_get_state(arg_scope, arg_root, *name);
3995 if (state == UNIT_FILE_ENABLED ||
3996 state == UNIT_FILE_ENABLED_RUNTIME ||
3997 state == UNIT_FILE_STATIC)
4001 puts(unit_file_state_to_string(state));
4005 STRV_FOREACH(name, args+1) {
4008 m = dbus_message_new_method_call(
4009 "org.freedesktop.systemd1",
4010 "/org/freedesktop/systemd1",
4011 "org.freedesktop.systemd1.Manager",
4012 "GetUnitFileState");
4014 log_error("Out of memory");
4019 if (!dbus_message_append_args(m,
4020 DBUS_TYPE_STRING, name,
4021 DBUS_TYPE_INVALID)) {
4022 log_error("Could not append arguments to message.");
4027 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
4029 log_error("Failed to issue method call: %s", bus_error_message(&error));
4034 if (!dbus_message_get_args(reply, &error,
4035 DBUS_TYPE_STRING, &s,
4036 DBUS_TYPE_INVALID)) {
4037 log_error("Failed to parse reply: %s", bus_error_message(&error));
4042 dbus_message_unref(m);
4043 dbus_message_unref(reply);
4046 if (streq(s, "enabled") ||
4047 streq(s, "enabled-runtime") ||
4056 r = enabled ? 0 : 1;
4060 dbus_message_unref(m);
4063 dbus_message_unref(reply);
4065 dbus_error_free(&error);
4069 static int systemctl_help(void) {
4071 pager_open_if_enabled();
4073 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
4074 "Query or send control commands to the systemd manager.\n\n"
4075 " -h --help Show this help\n"
4076 " --version Show package version\n"
4077 " -t --type=TYPE List only units of a particular type\n"
4078 " -p --property=NAME Show only properties by this name\n"
4079 " -a --all Show all units/properties, including dead/empty ones\n"
4080 " --failed Show only failed units\n"
4081 " --full Don't ellipsize unit names on output\n"
4082 " --fail When queueing a new job, fail if conflicting jobs are\n"
4084 " --ignore-dependencies\n"
4085 " When queueing a new job, ignore all its dependencies\n"
4086 " --kill-who=WHO Who to send signal to\n"
4087 " -s --signal=SIGNAL Which signal to send\n"
4088 " -H --host=[USER@]HOST\n"
4089 " Show information for remote host\n"
4090 " -P --privileged Acquire privileges before execution\n"
4091 " -q --quiet Suppress output\n"
4092 " --no-block Do not wait until operation finished\n"
4093 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4094 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
4096 " --no-legend Do not print a legend (column headers and hints)\n"
4097 " --no-pager Do not pipe output into a pager\n"
4098 " --no-ask-password\n"
4099 " Do not ask for system passwords\n"
4100 " --order When generating graph for dot, show only order\n"
4101 " --require When generating graph for dot, show only requirement\n"
4102 " --system Connect to system manager\n"
4103 " --user Connect to user service manager\n"
4104 " --global Enable/disable unit files globally\n"
4105 " -f --force When enabling unit files, override existing symlinks\n"
4106 " When shutting down, execute action immediately\n"
4107 " --root=PATH Enable unit files in the specified root directory\n"
4108 " --runtime Enable unit files only temporarily until next reboot\n"
4109 " -n --lines=INTEGER Journal entries to show\n"
4110 " --follow Follow journal\n"
4111 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
4112 " verbose, export, json, cat)\n\n"
4114 " list-units List loaded units\n"
4115 " start [NAME...] Start (activate) one or more units\n"
4116 " stop [NAME...] Stop (deactivate) one or more units\n"
4117 " reload [NAME...] Reload one or more units\n"
4118 " restart [NAME...] Start or restart one or more units\n"
4119 " try-restart [NAME...] Restart one or more units if active\n"
4120 " reload-or-restart [NAME...] Reload one or more units is possible,\n"
4121 " otherwise start or restart\n"
4122 " reload-or-try-restart [NAME...] Reload one or more units is possible,\n"
4123 " otherwise restart if active\n"
4124 " isolate [NAME] Start one unit and stop all others\n"
4125 " kill [NAME...] Send signal to processes of a unit\n"
4126 " is-active [NAME...] Check whether units are active\n"
4127 " status [NAME...|PID...] Show runtime status of one or more units\n"
4128 " show [NAME...|JOB...] Show properties of one or more\n"
4129 " units/jobs or the manager\n"
4130 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
4132 " load [NAME...] Load one or more units\n\n"
4133 "Unit File Commands:\n"
4134 " list-unit-files List installed unit files\n"
4135 " enable [NAME...] Enable one or more unit files\n"
4136 " disable [NAME...] Disable one or more unit files\n"
4137 " reenable [NAME...] Reenable one or more unit files\n"
4138 " preset [NAME...] Enable/disable one or more unit files\n"
4139 " based on preset configuration\n"
4140 " mask [NAME...] Mask one or more units\n"
4141 " unmask [NAME...] Unmask one or more units\n"
4142 " link [PATH...] Link one or more units files into\n"
4143 " the search path\n"
4144 " is-enabled [NAME...] Check whether unit files are enabled\n\n"
4146 " list-jobs List jobs\n"
4147 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
4148 "Status Commands:\n"
4149 " dump Dump server status\n"
4150 " dot Dump dependency graph for dot(1)\n\n"
4151 "Snapshot Commands:\n"
4152 " snapshot [NAME] Create a snapshot\n"
4153 " delete [NAME...] Remove one or more snapshots\n\n"
4154 "Environment Commands:\n"
4155 " show-environment Dump environment\n"
4156 " set-environment [NAME=VALUE...] Set one or more environment variables\n"
4157 " unset-environment [NAME...] Unset one or more environment variables\n\n"
4158 "Manager Lifecycle Commands:\n"
4159 " daemon-reload Reload systemd manager configuration\n"
4160 " daemon-reexec Reexecute systemd manager\n\n"
4161 "System Commands:\n"
4162 " default Enter system default mode\n"
4163 " rescue Enter system rescue mode\n"
4164 " emergency Enter system emergency mode\n"
4165 " halt Shut down and halt the system\n"
4166 " poweroff Shut down and power-off the system\n"
4167 " reboot Shut down and reboot the system\n"
4168 " kexec Shut down and reboot the system with kexec\n"
4169 " exit Ask for user instance termination\n",
4170 program_invocation_short_name);
4175 static int halt_help(void) {
4177 printf("%s [OPTIONS...]\n\n"
4178 "%s the system.\n\n"
4179 " --help Show this help\n"
4180 " --halt Halt the machine\n"
4181 " -p --poweroff Switch off the machine\n"
4182 " --reboot Reboot the machine\n"
4183 " -f --force Force immediate halt/power-off/reboot\n"
4184 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
4185 " -d --no-wtmp Don't write wtmp record\n"
4186 " -n --no-sync Don't sync before halt/power-off/reboot\n"
4187 " --no-wall Don't send wall message before halt/power-off/reboot\n",
4188 program_invocation_short_name,
4189 arg_action == ACTION_REBOOT ? "Reboot" :
4190 arg_action == ACTION_POWEROFF ? "Power off" :
4196 static int shutdown_help(void) {
4198 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
4199 "Shut down the system.\n\n"
4200 " --help Show this help\n"
4201 " -H --halt Halt the machine\n"
4202 " -P --poweroff Power-off the machine\n"
4203 " -r --reboot Reboot the machine\n"
4204 " -h Equivalent to --poweroff, overriden by --halt\n"
4205 " -k Don't halt/power-off/reboot, just send warnings\n"
4206 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4207 " -c Cancel a pending shutdown\n",
4208 program_invocation_short_name);
4213 static int telinit_help(void) {
4215 printf("%s [OPTIONS...] {COMMAND}\n\n"
4216 "Send control commands to the init daemon.\n\n"
4217 " --help Show this help\n"
4218 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
4220 " 0 Power-off the machine\n"
4221 " 6 Reboot the machine\n"
4222 " 2, 3, 4, 5 Start runlevelX.target unit\n"
4223 " 1, s, S Enter rescue mode\n"
4224 " q, Q Reload init daemon configuration\n"
4225 " u, U Reexecute init daemon\n",
4226 program_invocation_short_name);
4231 static int runlevel_help(void) {
4233 printf("%s [OPTIONS...]\n\n"
4234 "Prints the previous and current runlevel of the init system.\n\n"
4235 " --help Show this help\n",
4236 program_invocation_short_name);
4241 static int systemctl_parse_argv(int argc, char *argv[]) {
4245 ARG_IGNORE_DEPENDENCIES,
4261 ARG_NO_ASK_PASSWORD,
4268 static const struct option options[] = {
4269 { "help", no_argument, NULL, 'h' },
4270 { "version", no_argument, NULL, ARG_VERSION },
4271 { "type", required_argument, NULL, 't' },
4272 { "property", required_argument, NULL, 'p' },
4273 { "all", no_argument, NULL, 'a' },
4274 { "failed", no_argument, NULL, ARG_FAILED },
4275 { "full", no_argument, NULL, ARG_FULL },
4276 { "fail", no_argument, NULL, ARG_FAIL },
4277 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
4278 { "user", no_argument, NULL, ARG_USER },
4279 { "system", no_argument, NULL, ARG_SYSTEM },
4280 { "global", no_argument, NULL, ARG_GLOBAL },
4281 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
4282 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
4283 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
4284 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4285 { "quiet", no_argument, NULL, 'q' },
4286 { "order", no_argument, NULL, ARG_ORDER },
4287 { "require", no_argument, NULL, ARG_REQUIRE },
4288 { "root", required_argument, NULL, ARG_ROOT },
4289 { "force", no_argument, NULL, ARG_FORCE },
4290 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
4291 { "kill-mode", required_argument, NULL, ARG_KILL_MODE }, /* undocumented on purpose */
4292 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
4293 { "signal", required_argument, NULL, 's' },
4294 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
4295 { "host", required_argument, NULL, 'H' },
4296 { "privileged",no_argument, NULL, 'P' },
4297 { "runtime", no_argument, NULL, ARG_RUNTIME },
4298 { "lines", required_argument, NULL, 'n' },
4299 { "follow", no_argument, NULL, ARG_FOLLOW },
4300 { "output", required_argument, NULL, 'o' },
4301 { NULL, 0, NULL, 0 }
4309 while ((c = getopt_long(argc, argv, "ht:p:aqfs:H:Pn:o:", options, NULL)) >= 0) {
4318 puts(PACKAGE_STRING);
4320 puts(SYSTEMD_FEATURES);
4330 if (!(l = strv_append(arg_property, optarg)))
4333 strv_free(arg_property);
4336 /* If the user asked for a particular
4337 * property, show it to him, even if it is
4348 arg_job_mode = "fail";
4351 case ARG_IGNORE_DEPENDENCIES:
4352 arg_job_mode = "ignore-dependencies";
4356 arg_scope = UNIT_FILE_USER;
4360 arg_scope = UNIT_FILE_SYSTEM;
4364 arg_scope = UNIT_FILE_GLOBAL;
4368 arg_no_block = true;
4372 arg_no_legend = true;
4376 arg_no_pager = true;
4384 arg_dot = DOT_ORDER;
4388 arg_dot = DOT_REQUIRE;
4416 /* -f is short for both --follow and --force! */
4422 arg_no_reload = true;
4426 arg_kill_who = optarg;
4430 arg_kill_mode = optarg;
4434 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
4435 log_error("Failed to parse signal string %s.", optarg);
4440 case ARG_NO_ASK_PASSWORD:
4441 arg_ask_password = false;
4445 arg_transport = TRANSPORT_POLKIT;
4449 arg_transport = TRANSPORT_SSH;
4458 if (safe_atou(optarg, &arg_lines) < 0) {
4459 log_error("Failed to parse lines '%s'", optarg);
4465 arg_output = output_mode_from_string(optarg);
4466 if (arg_output < 0) {
4467 log_error("Unknown output '%s'.", optarg);
4476 log_error("Unknown option code %c", c);
4481 if (arg_transport != TRANSPORT_NORMAL && arg_scope != UNIT_FILE_SYSTEM) {
4482 log_error("Cannot access user instance remotely.");
4489 static int halt_parse_argv(int argc, char *argv[]) {
4498 static const struct option options[] = {
4499 { "help", no_argument, NULL, ARG_HELP },
4500 { "halt", no_argument, NULL, ARG_HALT },
4501 { "poweroff", no_argument, NULL, 'p' },
4502 { "reboot", no_argument, NULL, ARG_REBOOT },
4503 { "force", no_argument, NULL, 'f' },
4504 { "wtmp-only", no_argument, NULL, 'w' },
4505 { "no-wtmp", no_argument, NULL, 'd' },
4506 { "no-sync", no_argument, NULL, 'n' },
4507 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4508 { NULL, 0, NULL, 0 }
4516 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
4517 if (runlevel == '0' || runlevel == '6')
4518 arg_immediate = true;
4520 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
4528 arg_action = ACTION_HALT;
4532 if (arg_action != ACTION_REBOOT)
4533 arg_action = ACTION_POWEROFF;
4537 arg_action = ACTION_REBOOT;
4541 arg_immediate = true;
4562 /* Compatibility nops */
4569 log_error("Unknown option code %c", c);
4574 if (optind < argc) {
4575 log_error("Too many arguments.");
4582 static int parse_time_spec(const char *t, usec_t *_u) {
4586 if (streq(t, "now"))
4588 else if (!strchr(t, ':')) {
4591 if (safe_atou64(t, &u) < 0)
4594 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
4603 hour = strtol(t, &e, 10);
4604 if (errno != 0 || *e != ':' || hour < 0 || hour > 23)
4607 minute = strtol(e+1, &e, 10);
4608 if (errno != 0 || *e != 0 || minute < 0 || minute > 59)
4611 n = now(CLOCK_REALTIME);
4612 s = (time_t) (n / USEC_PER_SEC);
4615 assert_se(localtime_r(&s, &tm));
4617 tm.tm_hour = (int) hour;
4618 tm.tm_min = (int) minute;
4621 assert_se(s = mktime(&tm));
4623 *_u = (usec_t) s * USEC_PER_SEC;
4626 *_u += USEC_PER_DAY;
4632 static int shutdown_parse_argv(int argc, char *argv[]) {
4639 static const struct option options[] = {
4640 { "help", no_argument, NULL, ARG_HELP },
4641 { "halt", no_argument, NULL, 'H' },
4642 { "poweroff", no_argument, NULL, 'P' },
4643 { "reboot", no_argument, NULL, 'r' },
4644 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
4645 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4646 { NULL, 0, NULL, 0 }
4654 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
4662 arg_action = ACTION_HALT;
4666 arg_action = ACTION_POWEROFF;
4671 arg_action = ACTION_KEXEC;
4673 arg_action = ACTION_REBOOT;
4677 arg_action = ACTION_KEXEC;
4681 if (arg_action != ACTION_HALT)
4682 arg_action = ACTION_POWEROFF;
4695 /* Compatibility nops */
4699 arg_action = ACTION_CANCEL_SHUTDOWN;
4706 log_error("Unknown option code %c", c);
4711 if (argc > optind) {
4712 r = parse_time_spec(argv[optind], &arg_when);
4714 log_error("Failed to parse time specification: %s", argv[optind]);
4718 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
4720 /* We skip the time argument */
4721 if (argc > optind + 1)
4722 arg_wall = argv + optind + 1;
4729 static int telinit_parse_argv(int argc, char *argv[]) {
4736 static const struct option options[] = {
4737 { "help", no_argument, NULL, ARG_HELP },
4738 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4739 { NULL, 0, NULL, 0 }
4742 static const struct {
4746 { '0', ACTION_POWEROFF },
4747 { '6', ACTION_REBOOT },
4748 { '1', ACTION_RESCUE },
4749 { '2', ACTION_RUNLEVEL2 },
4750 { '3', ACTION_RUNLEVEL3 },
4751 { '4', ACTION_RUNLEVEL4 },
4752 { '5', ACTION_RUNLEVEL5 },
4753 { 's', ACTION_RESCUE },
4754 { 'S', ACTION_RESCUE },
4755 { 'q', ACTION_RELOAD },
4756 { 'Q', ACTION_RELOAD },
4757 { 'u', ACTION_REEXEC },
4758 { 'U', ACTION_REEXEC }
4767 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4782 log_error("Unknown option code %c", c);
4787 if (optind >= argc) {
4792 if (optind + 1 < argc) {
4793 log_error("Too many arguments.");
4797 if (strlen(argv[optind]) != 1) {
4798 log_error("Expected single character argument.");
4802 for (i = 0; i < ELEMENTSOF(table); i++)
4803 if (table[i].from == argv[optind][0])
4806 if (i >= ELEMENTSOF(table)) {
4807 log_error("Unknown command %s.", argv[optind]);
4811 arg_action = table[i].to;
4818 static int runlevel_parse_argv(int argc, char *argv[]) {
4824 static const struct option options[] = {
4825 { "help", no_argument, NULL, ARG_HELP },
4826 { NULL, 0, NULL, 0 }
4834 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4845 log_error("Unknown option code %c", c);
4850 if (optind < argc) {
4851 log_error("Too many arguments.");
4858 static int parse_argv(int argc, char *argv[]) {
4862 if (program_invocation_short_name) {
4864 if (strstr(program_invocation_short_name, "halt")) {
4865 arg_action = ACTION_HALT;
4866 return halt_parse_argv(argc, argv);
4867 } else if (strstr(program_invocation_short_name, "poweroff")) {
4868 arg_action = ACTION_POWEROFF;
4869 return halt_parse_argv(argc, argv);
4870 } else if (strstr(program_invocation_short_name, "reboot")) {
4872 arg_action = ACTION_KEXEC;
4874 arg_action = ACTION_REBOOT;
4875 return halt_parse_argv(argc, argv);
4876 } else if (strstr(program_invocation_short_name, "shutdown")) {
4877 arg_action = ACTION_POWEROFF;
4878 return shutdown_parse_argv(argc, argv);
4879 } else if (strstr(program_invocation_short_name, "init")) {
4881 if (sd_booted() > 0) {
4882 arg_action = ACTION_INVALID;
4883 return telinit_parse_argv(argc, argv);
4885 /* Hmm, so some other init system is
4886 * running, we need to forward this
4887 * request to it. For now we simply
4888 * guess that it is Upstart. */
4890 execv("/lib/upstart/telinit", argv);
4892 log_error("Couldn't find an alternative telinit implementation to spawn.");
4896 } else if (strstr(program_invocation_short_name, "runlevel")) {
4897 arg_action = ACTION_RUNLEVEL;
4898 return runlevel_parse_argv(argc, argv);
4902 arg_action = ACTION_SYSTEMCTL;
4903 return systemctl_parse_argv(argc, argv);
4906 static int action_to_runlevel(void) {
4908 static const char table[_ACTION_MAX] = {
4909 [ACTION_HALT] = '0',
4910 [ACTION_POWEROFF] = '0',
4911 [ACTION_REBOOT] = '6',
4912 [ACTION_RUNLEVEL2] = '2',
4913 [ACTION_RUNLEVEL3] = '3',
4914 [ACTION_RUNLEVEL4] = '4',
4915 [ACTION_RUNLEVEL5] = '5',
4916 [ACTION_RESCUE] = '1'
4919 assert(arg_action < _ACTION_MAX);
4921 return table[arg_action];
4924 static int talk_upstart(void) {
4925 DBusMessage *m = NULL, *reply = NULL;
4927 int previous, rl, r;
4929 env1_buf[] = "RUNLEVEL=X",
4930 env2_buf[] = "PREVLEVEL=X";
4931 char *env1 = env1_buf, *env2 = env2_buf;
4932 const char *emit = "runlevel";
4933 dbus_bool_t b_false = FALSE;
4934 DBusMessageIter iter, sub;
4935 DBusConnection *bus;
4937 dbus_error_init(&error);
4939 if (!(rl = action_to_runlevel()))
4942 if (utmp_get_runlevel(&previous, NULL) < 0)
4945 if (!(bus = dbus_connection_open_private("unix:abstract=/com/ubuntu/upstart", &error))) {
4946 if (dbus_error_has_name(&error, DBUS_ERROR_NO_SERVER)) {
4951 log_error("Failed to connect to Upstart bus: %s", bus_error_message(&error));
4956 if ((r = bus_check_peercred(bus)) < 0) {
4957 log_error("Failed to verify owner of bus.");
4961 if (!(m = dbus_message_new_method_call(
4962 "com.ubuntu.Upstart",
4963 "/com/ubuntu/Upstart",
4964 "com.ubuntu.Upstart0_6",
4967 log_error("Could not allocate message.");
4972 dbus_message_iter_init_append(m, &iter);
4974 env1_buf[sizeof(env1_buf)-2] = rl;
4975 env2_buf[sizeof(env2_buf)-2] = previous;
4977 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &emit) ||
4978 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub) ||
4979 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env1) ||
4980 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env2) ||
4981 !dbus_message_iter_close_container(&iter, &sub) ||
4982 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b_false)) {
4983 log_error("Could not append arguments to message.");
4988 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
4990 if (error_is_no_service(&error)) {
4995 log_error("Failed to issue method call: %s", bus_error_message(&error));
5004 dbus_message_unref(m);
5007 dbus_message_unref(reply);
5010 dbus_connection_flush(bus);
5011 dbus_connection_close(bus);
5012 dbus_connection_unref(bus);
5015 dbus_error_free(&error);
5020 static int talk_initctl(void) {
5021 struct init_request request;
5025 if (!(rl = action_to_runlevel()))
5029 request.magic = INIT_MAGIC;
5030 request.sleeptime = 0;
5031 request.cmd = INIT_CMD_RUNLVL;
5032 request.runlevel = rl;
5034 if ((fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY)) < 0) {
5036 if (errno == ENOENT)
5039 log_error("Failed to open "INIT_FIFO": %m");
5044 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
5045 close_nointr_nofail(fd);
5048 log_error("Failed to write to "INIT_FIFO": %m");
5049 return errno ? -errno : -EIO;
5055 static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
5057 static const struct {
5065 int (* const dispatch)(DBusConnection *bus, char **args);
5067 { "list-units", LESS, 1, list_units },
5068 { "list-unit-files", EQUAL, 1, list_unit_files },
5069 { "list-jobs", EQUAL, 1, list_jobs },
5070 { "clear-jobs", EQUAL, 1, daemon_reload },
5071 { "load", MORE, 2, load_unit },
5072 { "cancel", MORE, 2, cancel_job },
5073 { "start", MORE, 2, start_unit },
5074 { "stop", MORE, 2, start_unit },
5075 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5076 { "reload", MORE, 2, start_unit },
5077 { "restart", MORE, 2, start_unit },
5078 { "try-restart", MORE, 2, start_unit },
5079 { "reload-or-restart", MORE, 2, start_unit },
5080 { "reload-or-try-restart", MORE, 2, start_unit },
5081 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
5082 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5083 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
5084 { "isolate", EQUAL, 2, start_unit },
5085 { "kill", MORE, 2, kill_unit },
5086 { "is-active", MORE, 2, check_unit },
5087 { "check", MORE, 2, check_unit },
5088 { "show", MORE, 1, show },
5089 { "status", MORE, 2, show },
5090 { "dump", EQUAL, 1, dump },
5091 { "dot", EQUAL, 1, dot },
5092 { "snapshot", LESS, 2, snapshot },
5093 { "delete", MORE, 2, delete_snapshot },
5094 { "daemon-reload", EQUAL, 1, daemon_reload },
5095 { "daemon-reexec", EQUAL, 1, daemon_reload },
5096 { "show-environment", EQUAL, 1, show_enviroment },
5097 { "set-environment", MORE, 2, set_environment },
5098 { "unset-environment", MORE, 2, set_environment },
5099 { "halt", EQUAL, 1, start_special },
5100 { "poweroff", EQUAL, 1, start_special },
5101 { "reboot", EQUAL, 1, start_special },
5102 { "kexec", EQUAL, 1, start_special },
5103 { "default", EQUAL, 1, start_special },
5104 { "rescue", EQUAL, 1, start_special },
5105 { "emergency", EQUAL, 1, start_special },
5106 { "exit", EQUAL, 1, start_special },
5107 { "reset-failed", MORE, 1, reset_failed },
5108 { "enable", MORE, 2, enable_unit },
5109 { "disable", MORE, 2, enable_unit },
5110 { "is-enabled", MORE, 2, unit_is_enabled },
5111 { "reenable", MORE, 2, enable_unit },
5112 { "preset", MORE, 2, enable_unit },
5113 { "mask", MORE, 2, enable_unit },
5114 { "unmask", MORE, 2, enable_unit },
5115 { "link", MORE, 2, enable_unit }
5125 left = argc - optind;
5128 /* Special rule: no arguments means "list-units" */
5131 if (streq(argv[optind], "help")) {
5136 for (i = 0; i < ELEMENTSOF(verbs); i++)
5137 if (streq(argv[optind], verbs[i].verb))
5140 if (i >= ELEMENTSOF(verbs)) {
5141 log_error("Unknown operation %s", argv[optind]);
5146 switch (verbs[i].argc_cmp) {
5149 if (left != verbs[i].argc) {
5150 log_error("Invalid number of arguments.");
5157 if (left < verbs[i].argc) {
5158 log_error("Too few arguments.");
5165 if (left > verbs[i].argc) {
5166 log_error("Too many arguments.");
5173 assert_not_reached("Unknown comparison operator.");
5176 /* Require a bus connection for all operations but
5178 if (!streq(verbs[i].verb, "enable") &&
5179 !streq(verbs[i].verb, "disable") &&
5180 !streq(verbs[i].verb, "is-enabled") &&
5181 !streq(verbs[i].verb, "list-unit-files") &&
5182 !streq(verbs[i].verb, "reenable") &&
5183 !streq(verbs[i].verb, "preset") &&
5184 !streq(verbs[i].verb, "mask") &&
5185 !streq(verbs[i].verb, "unmask") &&
5186 !streq(verbs[i].verb, "link")) {
5188 if (running_in_chroot() > 0) {
5189 log_info("Running in chroot, ignoring request.");
5194 log_error("Failed to get D-Bus connection: %s",
5195 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5201 if (!bus && !avoid_bus()) {
5202 log_error("Failed to get D-Bus connection: %s",
5203 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5208 return verbs[i].dispatch(bus, argv + optind);
5211 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
5213 struct msghdr msghdr;
5214 struct iovec iovec[2];
5215 union sockaddr_union sockaddr;
5216 struct sd_shutdown_command c;
5218 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
5225 c.dry_run = dry_run;
5229 sockaddr.sa.sa_family = AF_UNIX;
5230 strncpy(sockaddr.un.sun_path, "/run/systemd/shutdownd", sizeof(sockaddr.un.sun_path));
5233 msghdr.msg_name = &sockaddr;
5234 msghdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + sizeof("/run/systemd/shutdownd") - 1;
5237 iovec[0].iov_base = (char*) &c;
5238 iovec[0].iov_len = offsetof(struct sd_shutdown_command, wall_message);
5240 if (isempty(message))
5241 msghdr.msg_iovlen = 1;
5243 iovec[1].iov_base = (char*) message;
5244 iovec[1].iov_len = strlen(message);
5245 msghdr.msg_iovlen = 2;
5247 msghdr.msg_iov = iovec;
5249 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0) {
5250 close_nointr_nofail(fd);
5254 close_nointr_nofail(fd);
5258 static int reload_with_fallback(DBusConnection *bus) {
5261 /* First, try systemd via D-Bus. */
5262 if (daemon_reload(bus, NULL) >= 0)
5266 /* Nothing else worked, so let's try signals */
5267 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
5269 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
5270 log_error("kill() failed: %m");
5277 static int start_with_fallback(DBusConnection *bus) {
5280 /* First, try systemd via D-Bus. */
5281 if (start_unit(bus, NULL) >= 0)
5285 /* Hmm, talking to systemd via D-Bus didn't work. Then
5286 * let's try to talk to Upstart via D-Bus. */
5287 if (talk_upstart() > 0)
5290 /* Nothing else worked, so let's try
5292 if (talk_initctl() > 0)
5295 log_error("Failed to talk to init daemon.");
5299 warn_wall(arg_action);
5303 static void halt_now(enum action a) {
5305 /* Make sure C-A-D is handled by the kernel from this
5307 reboot(RB_ENABLE_CAD);
5312 log_info("Halting.");
5313 reboot(RB_HALT_SYSTEM);
5316 case ACTION_POWEROFF:
5317 log_info("Powering off.");
5318 reboot(RB_POWER_OFF);
5322 log_info("Rebooting.");
5323 reboot(RB_AUTOBOOT);
5327 assert_not_reached("Unknown halt action.");
5330 assert_not_reached("Uh? This shouldn't happen.");
5333 static int halt_main(DBusConnection *bus) {
5336 if (geteuid() != 0) {
5337 /* Try logind if we are a normal user and no special
5338 * mode applies. Maybe PolicyKit allows us to shutdown
5341 if (arg_when <= 0 &&
5344 (arg_action == ACTION_POWEROFF ||
5345 arg_action == ACTION_REBOOT)) {
5346 r = reboot_with_logind(bus, arg_action);
5351 log_error("Must be root.");
5358 m = strv_join(arg_wall, " ");
5359 r = send_shutdownd(arg_when,
5360 arg_action == ACTION_HALT ? 'H' :
5361 arg_action == ACTION_POWEROFF ? 'P' :
5362 arg_action == ACTION_KEXEC ? 'K' :
5370 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
5372 char date[FORMAT_TIMESTAMP_MAX];
5374 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
5375 format_timestamp(date, sizeof(date), arg_when));
5380 if (!arg_dry && !arg_immediate)
5381 return start_with_fallback(bus);
5384 if (sd_booted() > 0)
5385 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
5387 r = utmp_put_shutdown();
5389 log_warning("Failed to write utmp record: %s", strerror(-r));
5399 halt_now(arg_action);
5400 /* We should never reach this. */
5404 static int runlevel_main(void) {
5405 int r, runlevel, previous;
5407 r = utmp_get_runlevel(&runlevel, &previous);
5414 previous <= 0 ? 'N' : previous,
5415 runlevel <= 0 ? 'N' : runlevel);
5420 int main(int argc, char*argv[]) {
5421 int r, retval = EXIT_FAILURE;
5422 DBusConnection *bus = NULL;
5425 dbus_error_init(&error);
5427 log_parse_environment();
5430 r = parse_argv(argc, argv);
5434 retval = EXIT_SUCCESS;
5438 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
5439 * let's shortcut this */
5440 if (arg_action == ACTION_RUNLEVEL) {
5441 r = runlevel_main();
5442 retval = r < 0 ? EXIT_FAILURE : r;
5446 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
5447 log_info("Running in chroot, ignoring request.");
5453 if (arg_transport == TRANSPORT_NORMAL)
5454 bus_connect(arg_scope == UNIT_FILE_SYSTEM ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &bus, &private_bus, &error);
5455 else if (arg_transport == TRANSPORT_POLKIT) {
5456 bus_connect_system_polkit(&bus, &error);
5457 private_bus = false;
5458 } else if (arg_transport == TRANSPORT_SSH) {
5459 bus_connect_system_ssh(NULL, arg_host, &bus, &error);
5460 private_bus = false;
5462 assert_not_reached("Uh, invalid transport...");
5465 switch (arg_action) {
5467 case ACTION_SYSTEMCTL:
5468 r = systemctl_main(bus, argc, argv, &error);
5472 case ACTION_POWEROFF:
5478 case ACTION_RUNLEVEL2:
5479 case ACTION_RUNLEVEL3:
5480 case ACTION_RUNLEVEL4:
5481 case ACTION_RUNLEVEL5:
5483 case ACTION_EMERGENCY:
5484 case ACTION_DEFAULT:
5485 r = start_with_fallback(bus);
5490 r = reload_with_fallback(bus);
5493 case ACTION_CANCEL_SHUTDOWN:
5494 r = send_shutdownd(0, 0, false, false, NULL);
5497 case ACTION_INVALID:
5498 case ACTION_RUNLEVEL:
5500 assert_not_reached("Unknown action");
5503 retval = r < 0 ? EXIT_FAILURE : r;
5507 dbus_connection_flush(bus);
5508 dbus_connection_close(bus);
5509 dbus_connection_unref(bus);
5512 dbus_error_free(&error);
5516 strv_free(arg_property);
5519 ask_password_agent_close();
5520 polkit_agent_close();