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) {
2390 if (i->main_pid > 0)
2391 extra[k++] = i->main_pid;
2393 if (i->control_pid > 0)
2394 extra[k++] = i->control_pid;
2396 show_cgroup_and_extra_by_spec(i->default_control_group, "\t\t ", c, false, arg_all, extra, k);
2400 if (i->id && arg_transport != TRANSPORT_SSH) {
2402 show_journal_by_unit(i->id, arg_output, 0, i->inactive_exit_timestamp_monotonic, arg_lines, arg_all, arg_follow);
2405 if (i->need_daemon_reload)
2406 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %s daemon-reload' recommended.\n",
2407 ansi_highlight_red(true),
2408 ansi_highlight_red(false),
2409 arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
2412 static int status_property(const char *name, DBusMessageIter *iter, UnitStatusInfo *i) {
2418 switch (dbus_message_iter_get_arg_type(iter)) {
2420 case DBUS_TYPE_STRING: {
2423 dbus_message_iter_get_basic(iter, &s);
2426 if (streq(name, "Id"))
2428 else if (streq(name, "LoadState"))
2430 else if (streq(name, "ActiveState"))
2431 i->active_state = s;
2432 else if (streq(name, "SubState"))
2434 else if (streq(name, "Description"))
2436 else if (streq(name, "FragmentPath"))
2438 #ifdef HAVE_SYSV_COMPAT
2439 else if (streq(name, "SysVPath")) {
2444 else if (streq(name, "DefaultControlGroup"))
2445 i->default_control_group = s;
2446 else if (streq(name, "StatusText"))
2448 else if (streq(name, "SysFSPath"))
2450 else if (streq(name, "Where"))
2452 else if (streq(name, "What"))
2454 else if (streq(name, "Following"))
2456 else if (streq(name, "UnitFileState"))
2457 i->unit_file_state = s;
2458 else if (streq(name, "Result"))
2465 case DBUS_TYPE_BOOLEAN: {
2468 dbus_message_iter_get_basic(iter, &b);
2470 if (streq(name, "Accept"))
2472 else if (streq(name, "NeedDaemonReload"))
2473 i->need_daemon_reload = b;
2474 else if (streq(name, "ConditionResult"))
2475 i->condition_result = b;
2480 case DBUS_TYPE_UINT32: {
2483 dbus_message_iter_get_basic(iter, &u);
2485 if (streq(name, "MainPID")) {
2487 i->main_pid = (pid_t) u;
2490 } else if (streq(name, "ControlPID"))
2491 i->control_pid = (pid_t) u;
2492 else if (streq(name, "ExecMainPID")) {
2494 i->main_pid = (pid_t) u;
2495 } else if (streq(name, "NAccepted"))
2497 else if (streq(name, "NConnections"))
2498 i->n_connections = u;
2503 case DBUS_TYPE_INT32: {
2506 dbus_message_iter_get_basic(iter, &j);
2508 if (streq(name, "ExecMainCode"))
2509 i->exit_code = (int) j;
2510 else if (streq(name, "ExecMainStatus"))
2511 i->exit_status = (int) j;
2516 case DBUS_TYPE_UINT64: {
2519 dbus_message_iter_get_basic(iter, &u);
2521 if (streq(name, "ExecMainStartTimestamp"))
2522 i->start_timestamp = (usec_t) u;
2523 else if (streq(name, "ExecMainExitTimestamp"))
2524 i->exit_timestamp = (usec_t) u;
2525 else if (streq(name, "ActiveEnterTimestamp"))
2526 i->active_enter_timestamp = (usec_t) u;
2527 else if (streq(name, "InactiveEnterTimestamp"))
2528 i->inactive_enter_timestamp = (usec_t) u;
2529 else if (streq(name, "InactiveExitTimestamp"))
2530 i->inactive_exit_timestamp = (usec_t) u;
2531 else if (streq(name, "InactiveExitTimestampMonotonic"))
2532 i->inactive_exit_timestamp_monotonic = (usec_t) u;
2533 else if (streq(name, "ActiveExitTimestamp"))
2534 i->active_exit_timestamp = (usec_t) u;
2535 else if (streq(name, "ConditionTimestamp"))
2536 i->condition_timestamp = (usec_t) u;
2541 case DBUS_TYPE_ARRAY: {
2543 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
2544 startswith(name, "Exec")) {
2545 DBusMessageIter sub;
2547 dbus_message_iter_recurse(iter, &sub);
2548 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2549 ExecStatusInfo *info;
2552 if (!(info = new0(ExecStatusInfo, 1)))
2555 if (!(info->name = strdup(name))) {
2560 if ((r = exec_status_info_deserialize(&sub, info)) < 0) {
2565 LIST_PREPEND(ExecStatusInfo, exec, i->exec, info);
2567 dbus_message_iter_next(&sub);
2574 case DBUS_TYPE_STRUCT: {
2576 if (streq(name, "LoadError")) {
2577 DBusMessageIter sub;
2578 const char *n, *message;
2581 dbus_message_iter_recurse(iter, &sub);
2583 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &n, true);
2587 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &message, false);
2591 if (!isempty(message))
2592 i->load_error = message;
2602 static int print_property(const char *name, DBusMessageIter *iter) {
2606 /* This is a low-level property printer, see
2607 * print_status_info() for the nicer output */
2609 if (arg_property && !strv_find(arg_property, name))
2612 switch (dbus_message_iter_get_arg_type(iter)) {
2614 case DBUS_TYPE_STRUCT: {
2615 DBusMessageIter sub;
2616 dbus_message_iter_recurse(iter, &sub);
2618 if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32 && streq(name, "Job")) {
2621 dbus_message_iter_get_basic(&sub, &u);
2624 printf("%s=%u\n", name, (unsigned) u);
2626 printf("%s=\n", name);
2629 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "Unit")) {
2632 dbus_message_iter_get_basic(&sub, &s);
2634 if (arg_all || s[0])
2635 printf("%s=%s\n", name, s);
2638 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "LoadError")) {
2639 const char *a = NULL, *b = NULL;
2641 if (bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &a, true) >= 0)
2642 bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &b, false);
2644 if (arg_all || !isempty(a) || !isempty(b))
2645 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
2653 case DBUS_TYPE_ARRAY:
2655 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "EnvironmentFiles")) {
2656 DBusMessageIter sub, sub2;
2658 dbus_message_iter_recurse(iter, &sub);
2659 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2663 dbus_message_iter_recurse(&sub, &sub2);
2665 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
2666 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) >= 0)
2667 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
2669 dbus_message_iter_next(&sub);
2674 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Paths")) {
2675 DBusMessageIter sub, sub2;
2677 dbus_message_iter_recurse(iter, &sub);
2678 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2679 const char *type, *path;
2681 dbus_message_iter_recurse(&sub, &sub2);
2683 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
2684 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
2685 printf("%s=%s\n", type, path);
2687 dbus_message_iter_next(&sub);
2692 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Timers")) {
2693 DBusMessageIter sub, sub2;
2695 dbus_message_iter_recurse(iter, &sub);
2696 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2698 uint64_t value, next_elapse;
2700 dbus_message_iter_recurse(&sub, &sub2);
2702 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &base, true) >= 0 &&
2703 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &value, true) >= 0 &&
2704 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &next_elapse, false) >= 0) {
2705 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
2707 printf("%s={ value=%s ; next_elapse=%s }\n",
2709 format_timespan(timespan1, sizeof(timespan1), value),
2710 format_timespan(timespan2, sizeof(timespan2), next_elapse));
2713 dbus_message_iter_next(&sub);
2718 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "ControlGroupAttributes")) {
2719 DBusMessageIter sub, sub2;
2721 dbus_message_iter_recurse(iter, &sub);
2722 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2723 const char *controller, *attr, *value;
2725 dbus_message_iter_recurse(&sub, &sub2);
2727 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &controller, true) >= 0 &&
2728 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &attr, true) >= 0 &&
2729 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &value, false) >= 0) {
2731 printf("ControlGroupAttribute={ controller=%s ; attribute=%s ; value=\"%s\" }\n",
2737 dbus_message_iter_next(&sub);
2742 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && startswith(name, "Exec")) {
2743 DBusMessageIter sub;
2745 dbus_message_iter_recurse(iter, &sub);
2746 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2747 ExecStatusInfo info;
2750 if (exec_status_info_deserialize(&sub, &info) >= 0) {
2751 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
2754 t = strv_join(info.argv, " ");
2756 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
2760 yes_no(info.ignore),
2761 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
2762 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
2763 (unsigned) info. pid,
2764 sigchld_code_to_string(info.code),
2766 info.code == CLD_EXITED ? "" : "/",
2767 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
2773 strv_free(info.argv);
2775 dbus_message_iter_next(&sub);
2784 if (generic_print_property(name, iter, arg_all) > 0)
2788 printf("%s=[unprintable]\n", name);
2793 static int show_one(const char *verb, DBusConnection *bus, const char *path, bool show_properties, bool *new_line) {
2794 DBusMessage *m = NULL, *reply = NULL;
2795 const char *interface = "";
2798 DBusMessageIter iter, sub, sub2, sub3;
2799 UnitStatusInfo info;
2807 dbus_error_init(&error);
2809 if (!(m = dbus_message_new_method_call(
2810 "org.freedesktop.systemd1",
2812 "org.freedesktop.DBus.Properties",
2814 log_error("Could not allocate message.");
2819 if (!dbus_message_append_args(m,
2820 DBUS_TYPE_STRING, &interface,
2821 DBUS_TYPE_INVALID)) {
2822 log_error("Could not append arguments to message.");
2827 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
2828 log_error("Failed to issue method call: %s", bus_error_message(&error));
2833 if (!dbus_message_iter_init(reply, &iter) ||
2834 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
2835 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
2836 log_error("Failed to parse reply.");
2841 dbus_message_iter_recurse(&iter, &sub);
2848 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
2851 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_DICT_ENTRY) {
2852 log_error("Failed to parse reply.");
2857 dbus_message_iter_recurse(&sub, &sub2);
2859 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0) {
2860 log_error("Failed to parse reply.");
2865 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
2866 log_error("Failed to parse reply.");
2871 dbus_message_iter_recurse(&sub2, &sub3);
2873 if (show_properties)
2874 r = print_property(name, &sub3);
2876 r = status_property(name, &sub3, &info);
2879 log_error("Failed to parse reply.");
2884 dbus_message_iter_next(&sub);
2889 if (!show_properties)
2890 print_status_info(&info);
2892 if (!streq_ptr(info.active_state, "active") &&
2893 !streq_ptr(info.active_state, "reloading") &&
2894 streq(verb, "status"))
2895 /* According to LSB: "program not running" */
2898 while ((p = info.exec)) {
2899 LIST_REMOVE(ExecStatusInfo, exec, info.exec, p);
2900 exec_status_info_free(p);
2905 dbus_message_unref(m);
2908 dbus_message_unref(reply);
2910 dbus_error_free(&error);
2915 static int show(DBusConnection *bus, char **args) {
2916 DBusMessage *m = NULL, *reply = NULL;
2919 bool show_properties, new_line = false;
2925 dbus_error_init(&error);
2927 show_properties = !streq(args[0], "status");
2929 if (show_properties)
2930 pager_open_if_enabled();
2932 if (show_properties && strv_length(args) <= 1) {
2933 /* If not argument is specified inspect the manager
2936 ret = show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line);
2940 STRV_FOREACH(name, args+1) {
2941 const char *path = NULL;
2944 if (safe_atou32(*name, &id) < 0) {
2946 /* Interpret as unit name */
2948 if (!(m = dbus_message_new_method_call(
2949 "org.freedesktop.systemd1",
2950 "/org/freedesktop/systemd1",
2951 "org.freedesktop.systemd1.Manager",
2953 log_error("Could not allocate message.");
2958 if (!dbus_message_append_args(m,
2959 DBUS_TYPE_STRING, name,
2960 DBUS_TYPE_INVALID)) {
2961 log_error("Could not append arguments to message.");
2966 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
2968 if (!dbus_error_has_name(&error, DBUS_ERROR_ACCESS_DENIED)) {
2969 log_error("Failed to issue method call: %s", bus_error_message(&error));
2974 dbus_error_free(&error);
2976 dbus_message_unref(m);
2977 if (!(m = dbus_message_new_method_call(
2978 "org.freedesktop.systemd1",
2979 "/org/freedesktop/systemd1",
2980 "org.freedesktop.systemd1.Manager",
2982 log_error("Could not allocate message.");
2987 if (!dbus_message_append_args(m,
2988 DBUS_TYPE_STRING, name,
2989 DBUS_TYPE_INVALID)) {
2990 log_error("Could not append arguments to message.");
2995 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
2996 log_error("Failed to issue method call: %s", bus_error_message(&error));
2998 if (dbus_error_has_name(&error, BUS_ERROR_NO_SUCH_UNIT))
2999 ret = 4; /* According to LSB: "program or service status is unknown" */
3006 } else if (show_properties) {
3008 /* Interpret as job id */
3010 if (!(m = dbus_message_new_method_call(
3011 "org.freedesktop.systemd1",
3012 "/org/freedesktop/systemd1",
3013 "org.freedesktop.systemd1.Manager",
3015 log_error("Could not allocate message.");
3020 if (!dbus_message_append_args(m,
3021 DBUS_TYPE_UINT32, &id,
3022 DBUS_TYPE_INVALID)) {
3023 log_error("Could not append arguments to message.");
3028 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3029 log_error("Failed to issue method call: %s", bus_error_message(&error));
3035 /* Interpret as PID */
3037 if (!(m = dbus_message_new_method_call(
3038 "org.freedesktop.systemd1",
3039 "/org/freedesktop/systemd1",
3040 "org.freedesktop.systemd1.Manager",
3042 log_error("Could not allocate message.");
3047 if (!dbus_message_append_args(m,
3048 DBUS_TYPE_UINT32, &id,
3049 DBUS_TYPE_INVALID)) {
3050 log_error("Could not append arguments to message.");
3055 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3056 log_error("Failed to issue method call: %s", bus_error_message(&error));
3062 if (!dbus_message_get_args(reply, &error,
3063 DBUS_TYPE_OBJECT_PATH, &path,
3064 DBUS_TYPE_INVALID)) {
3065 log_error("Failed to parse reply: %s", bus_error_message(&error));
3070 if ((r = show_one(args[0], bus, path, show_properties, &new_line)) != 0)
3073 dbus_message_unref(m);
3074 dbus_message_unref(reply);
3080 dbus_message_unref(m);
3083 dbus_message_unref(reply);
3085 dbus_error_free(&error);
3090 static int dump(DBusConnection *bus, char **args) {
3091 DBusMessage *m = NULL, *reply = NULL;
3096 dbus_error_init(&error);
3098 pager_open_if_enabled();
3100 if (!(m = dbus_message_new_method_call(
3101 "org.freedesktop.systemd1",
3102 "/org/freedesktop/systemd1",
3103 "org.freedesktop.systemd1.Manager",
3105 log_error("Could not allocate message.");
3109 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3110 log_error("Failed to issue method call: %s", bus_error_message(&error));
3115 if (!dbus_message_get_args(reply, &error,
3116 DBUS_TYPE_STRING, &text,
3117 DBUS_TYPE_INVALID)) {
3118 log_error("Failed to parse reply: %s", bus_error_message(&error));
3123 fputs(text, stdout);
3129 dbus_message_unref(m);
3132 dbus_message_unref(reply);
3134 dbus_error_free(&error);
3139 static int snapshot(DBusConnection *bus, char **args) {
3140 DBusMessage *m = NULL, *reply = NULL;
3143 const char *name = "", *path, *id;
3144 dbus_bool_t cleanup = FALSE;
3145 DBusMessageIter iter, sub;
3147 *interface = "org.freedesktop.systemd1.Unit",
3150 dbus_error_init(&error);
3152 if (!(m = dbus_message_new_method_call(
3153 "org.freedesktop.systemd1",
3154 "/org/freedesktop/systemd1",
3155 "org.freedesktop.systemd1.Manager",
3156 "CreateSnapshot"))) {
3157 log_error("Could not allocate message.");
3161 if (strv_length(args) > 1)
3164 if (!dbus_message_append_args(m,
3165 DBUS_TYPE_STRING, &name,
3166 DBUS_TYPE_BOOLEAN, &cleanup,
3167 DBUS_TYPE_INVALID)) {
3168 log_error("Could not append arguments to message.");
3173 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3174 log_error("Failed to issue method call: %s", bus_error_message(&error));
3179 if (!dbus_message_get_args(reply, &error,
3180 DBUS_TYPE_OBJECT_PATH, &path,
3181 DBUS_TYPE_INVALID)) {
3182 log_error("Failed to parse reply: %s", bus_error_message(&error));
3187 dbus_message_unref(m);
3188 if (!(m = dbus_message_new_method_call(
3189 "org.freedesktop.systemd1",
3191 "org.freedesktop.DBus.Properties",
3193 log_error("Could not allocate message.");
3197 if (!dbus_message_append_args(m,
3198 DBUS_TYPE_STRING, &interface,
3199 DBUS_TYPE_STRING, &property,
3200 DBUS_TYPE_INVALID)) {
3201 log_error("Could not append arguments to message.");
3206 dbus_message_unref(reply);
3207 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3208 log_error("Failed to issue method call: %s", bus_error_message(&error));
3213 if (!dbus_message_iter_init(reply, &iter) ||
3214 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3215 log_error("Failed to parse reply.");
3220 dbus_message_iter_recurse(&iter, &sub);
3222 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
3223 log_error("Failed to parse reply.");
3228 dbus_message_iter_get_basic(&sub, &id);
3236 dbus_message_unref(m);
3239 dbus_message_unref(reply);
3241 dbus_error_free(&error);
3246 static int delete_snapshot(DBusConnection *bus, char **args) {
3247 DBusMessage *m = NULL, *reply = NULL;
3255 dbus_error_init(&error);
3257 STRV_FOREACH(name, args+1) {
3258 const char *path = NULL;
3260 if (!(m = dbus_message_new_method_call(
3261 "org.freedesktop.systemd1",
3262 "/org/freedesktop/systemd1",
3263 "org.freedesktop.systemd1.Manager",
3265 log_error("Could not allocate message.");
3270 if (!dbus_message_append_args(m,
3271 DBUS_TYPE_STRING, name,
3272 DBUS_TYPE_INVALID)) {
3273 log_error("Could not append arguments to message.");
3278 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3279 log_error("Failed to issue method call: %s", bus_error_message(&error));
3284 if (!dbus_message_get_args(reply, &error,
3285 DBUS_TYPE_OBJECT_PATH, &path,
3286 DBUS_TYPE_INVALID)) {
3287 log_error("Failed to parse reply: %s", bus_error_message(&error));
3292 dbus_message_unref(m);
3293 if (!(m = dbus_message_new_method_call(
3294 "org.freedesktop.systemd1",
3296 "org.freedesktop.systemd1.Snapshot",
3298 log_error("Could not allocate message.");
3303 dbus_message_unref(reply);
3304 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3305 log_error("Failed to issue method call: %s", bus_error_message(&error));
3310 dbus_message_unref(m);
3311 dbus_message_unref(reply);
3319 dbus_message_unref(m);
3322 dbus_message_unref(reply);
3324 dbus_error_free(&error);
3329 static int daemon_reload(DBusConnection *bus, char **args) {
3330 DBusMessage *m = NULL, *reply = NULL;
3335 dbus_error_init(&error);
3337 if (arg_action == ACTION_RELOAD)
3339 else if (arg_action == ACTION_REEXEC)
3340 method = "Reexecute";
3342 assert(arg_action == ACTION_SYSTEMCTL);
3345 streq(args[0], "clear-jobs") ||
3346 streq(args[0], "cancel") ? "ClearJobs" :
3347 streq(args[0], "daemon-reexec") ? "Reexecute" :
3348 streq(args[0], "reset-failed") ? "ResetFailed" :
3349 streq(args[0], "halt") ? "Halt" :
3350 streq(args[0], "poweroff") ? "PowerOff" :
3351 streq(args[0], "reboot") ? "Reboot" :
3352 streq(args[0], "kexec") ? "KExec" :
3353 streq(args[0], "exit") ? "Exit" :
3354 /* "daemon-reload" */ "Reload";
3357 if (!(m = dbus_message_new_method_call(
3358 "org.freedesktop.systemd1",
3359 "/org/freedesktop/systemd1",
3360 "org.freedesktop.systemd1.Manager",
3362 log_error("Could not allocate message.");
3366 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3368 if (arg_action != ACTION_SYSTEMCTL && error_is_no_service(&error)) {
3369 /* There's always a fallback possible for
3370 * legacy actions. */
3375 if (streq(method, "Reexecute") && dbus_error_has_name(&error, DBUS_ERROR_NO_REPLY)) {
3376 /* On reexecution, we expect a disconnect, not
3382 log_error("Failed to issue method call: %s", bus_error_message(&error));
3391 dbus_message_unref(m);
3394 dbus_message_unref(reply);
3396 dbus_error_free(&error);
3401 static int reset_failed(DBusConnection *bus, char **args) {
3402 DBusMessage *m = NULL;
3408 dbus_error_init(&error);
3410 if (strv_length(args) <= 1)
3411 return daemon_reload(bus, args);
3413 STRV_FOREACH(name, args+1) {
3416 if (!(m = dbus_message_new_method_call(
3417 "org.freedesktop.systemd1",
3418 "/org/freedesktop/systemd1",
3419 "org.freedesktop.systemd1.Manager",
3420 "ResetFailedUnit"))) {
3421 log_error("Could not allocate message.");
3426 if (!dbus_message_append_args(m,
3427 DBUS_TYPE_STRING, name,
3428 DBUS_TYPE_INVALID)) {
3429 log_error("Could not append arguments to message.");
3434 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3435 log_error("Failed to issue method call: %s", bus_error_message(&error));
3440 dbus_message_unref(m);
3441 dbus_message_unref(reply);
3449 dbus_message_unref(m);
3451 dbus_error_free(&error);
3456 static int show_enviroment(DBusConnection *bus, char **args) {
3457 DBusMessage *m = NULL, *reply = NULL;
3459 DBusMessageIter iter, sub, sub2;
3462 *interface = "org.freedesktop.systemd1.Manager",
3463 *property = "Environment";
3465 dbus_error_init(&error);
3467 pager_open_if_enabled();
3469 if (!(m = dbus_message_new_method_call(
3470 "org.freedesktop.systemd1",
3471 "/org/freedesktop/systemd1",
3472 "org.freedesktop.DBus.Properties",
3474 log_error("Could not allocate message.");
3478 if (!dbus_message_append_args(m,
3479 DBUS_TYPE_STRING, &interface,
3480 DBUS_TYPE_STRING, &property,
3481 DBUS_TYPE_INVALID)) {
3482 log_error("Could not append arguments to message.");
3487 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3488 log_error("Failed to issue method call: %s", bus_error_message(&error));
3493 if (!dbus_message_iter_init(reply, &iter) ||
3494 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3495 log_error("Failed to parse reply.");
3500 dbus_message_iter_recurse(&iter, &sub);
3502 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_ARRAY ||
3503 dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_STRING) {
3504 log_error("Failed to parse reply.");
3509 dbus_message_iter_recurse(&sub, &sub2);
3511 while (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_INVALID) {
3514 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
3515 log_error("Failed to parse reply.");
3520 dbus_message_iter_get_basic(&sub2, &text);
3521 printf("%s\n", text);
3523 dbus_message_iter_next(&sub2);
3530 dbus_message_unref(m);
3533 dbus_message_unref(reply);
3535 dbus_error_free(&error);
3540 static int set_environment(DBusConnection *bus, char **args) {
3541 DBusMessage *m = NULL, *reply = NULL;
3545 DBusMessageIter iter, sub;
3548 dbus_error_init(&error);
3550 method = streq(args[0], "set-environment")
3552 : "UnsetEnvironment";
3554 if (!(m = dbus_message_new_method_call(
3555 "org.freedesktop.systemd1",
3556 "/org/freedesktop/systemd1",
3557 "org.freedesktop.systemd1.Manager",
3560 log_error("Could not allocate message.");
3564 dbus_message_iter_init_append(m, &iter);
3566 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub)) {
3567 log_error("Could not append arguments to message.");
3572 STRV_FOREACH(name, args+1)
3573 if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, name)) {
3574 log_error("Could not append arguments to message.");
3579 if (!dbus_message_iter_close_container(&iter, &sub)) {
3580 log_error("Could not append arguments to message.");
3585 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3586 log_error("Failed to issue method call: %s", bus_error_message(&error));
3595 dbus_message_unref(m);
3598 dbus_message_unref(reply);
3600 dbus_error_free(&error);
3605 static int enable_sysv_units(char **args) {
3608 #if defined (HAVE_SYSV_COMPAT) && (defined(TARGET_FEDORA) || defined(TARGET_MANDRIVA) || defined(TARGET_SUSE) || defined(TARGET_MEEGO) || defined(TARGET_ALTLINUX) || defined(TARGET_MAGEIA))
3609 const char *verb = args[0];
3610 unsigned f = 1, t = 1;
3613 if (arg_scope != UNIT_FILE_SYSTEM)
3616 if (!streq(verb, "enable") &&
3617 !streq(verb, "disable") &&
3618 !streq(verb, "is-enabled"))
3621 /* Processes all SysV units, and reshuffles the array so that
3622 * afterwards only the native units remain */
3625 r = lookup_paths_init(&paths, MANAGER_SYSTEM, false);
3631 for (f = 1; args[f]; f++) {
3634 bool found_native = false, found_sysv;
3636 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
3637 char **k, *l, *q = NULL;
3644 if (!endswith(name, ".service"))
3647 if (path_is_absolute(name))
3650 STRV_FOREACH(k, paths.unit_path) {
3653 if (!isempty(arg_root))
3654 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
3656 asprintf(&p, "%s/%s", *k, name);
3659 log_error("No memory");
3664 found_native = access(p, F_OK) >= 0;
3675 if (!isempty(arg_root))
3676 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
3678 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
3680 log_error("No memory");
3685 p[strlen(p) - sizeof(".service") + 1] = 0;
3686 found_sysv = access(p, F_OK) >= 0;
3693 /* Mark this entry, so that we don't try enabling it as native unit */
3694 args[f] = (char*) "";
3696 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
3698 if (!isempty(arg_root))
3699 argv[c++] = q = strappend("--root=", arg_root);
3701 argv[c++] = file_name_from_path(p);
3703 streq(verb, "enable") ? "on" :
3704 streq(verb, "disable") ? "off" : "--level=5";
3707 l = strv_join((char**)argv, " ");
3709 log_error("No memory.");
3716 log_info("Executing %s", l);
3721 log_error("Failed to fork: %m");
3726 } else if (pid == 0) {
3729 execv(argv[0], (char**) argv);
3730 _exit(EXIT_FAILURE);
3736 j = wait_for_terminate(pid, &status);
3738 log_error("Failed to wait for child: %s", strerror(-r));
3743 if (status.si_code == CLD_EXITED) {
3744 if (streq(verb, "is-enabled")) {
3745 if (status.si_status == 0) {
3754 } else if (status.si_status != 0) {
3765 lookup_paths_free(&paths);
3767 /* Drop all SysV units */
3768 for (f = 1, t = 1; args[f]; f++) {
3770 if (isempty(args[f]))
3773 args[t++] = args[f];
3782 static int enable_unit(DBusConnection *bus, char **args) {
3783 const char *verb = args[0];
3784 UnitFileChange *changes = NULL;
3785 unsigned n_changes = 0, i;
3786 int carries_install_info = -1;
3787 DBusMessage *m = NULL, *reply = NULL;
3791 r = enable_sysv_units(args);
3798 dbus_error_init(&error);
3800 if (!bus || avoid_bus()) {
3801 if (streq(verb, "enable")) {
3802 r = unit_file_enable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3803 carries_install_info = r;
3804 } else if (streq(verb, "disable"))
3805 r = unit_file_disable(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3806 else if (streq(verb, "reenable")) {
3807 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3808 carries_install_info = r;
3809 } else if (streq(verb, "link"))
3810 r = unit_file_link(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3811 else if (streq(verb, "preset")) {
3812 r = unit_file_preset(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3813 carries_install_info = r;
3814 } else if (streq(verb, "mask"))
3815 r = unit_file_mask(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3816 else if (streq(verb, "unmask"))
3817 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3819 assert_not_reached("Unknown verb");
3822 log_error("Operation failed: %s", strerror(-r));
3827 for (i = 0; i < n_changes; i++) {
3828 if (changes[i].type == UNIT_FILE_SYMLINK)
3829 log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
3831 log_info("rm '%s'", changes[i].path);
3837 bool send_force = true, expect_carries_install_info = false;
3839 DBusMessageIter iter, sub, sub2;
3841 if (streq(verb, "enable")) {
3842 method = "EnableUnitFiles";
3843 expect_carries_install_info = true;
3844 } else if (streq(verb, "disable")) {
3845 method = "DisableUnitFiles";
3847 } else if (streq(verb, "reenable")) {
3848 method = "ReenableUnitFiles";
3849 expect_carries_install_info = true;
3850 } else if (streq(verb, "link"))
3851 method = "LinkUnitFiles";
3852 else if (streq(verb, "preset")) {
3853 method = "PresetUnitFiles";
3854 expect_carries_install_info = true;
3855 } else if (streq(verb, "mask"))
3856 method = "MaskUnitFiles";
3857 else if (streq(verb, "unmask")) {
3858 method = "UnmaskUnitFiles";
3861 assert_not_reached("Unknown verb");
3863 m = dbus_message_new_method_call(
3864 "org.freedesktop.systemd1",
3865 "/org/freedesktop/systemd1",
3866 "org.freedesktop.systemd1.Manager",
3869 log_error("Out of memory");
3874 dbus_message_iter_init_append(m, &iter);
3876 r = bus_append_strv_iter(&iter, args+1);
3878 log_error("Failed to append unit files.");
3883 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &a)) {
3884 log_error("Failed to append runtime boolean.");
3892 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b)) {
3893 log_error("Failed to append force boolean.");
3899 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3901 log_error("Failed to issue method call: %s", bus_error_message(&error));
3906 if (!dbus_message_iter_init(reply, &iter)) {
3907 log_error("Failed to initialize iterator.");
3911 if (expect_carries_install_info) {
3912 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &b, true);
3914 log_error("Failed to parse reply.");
3918 carries_install_info = b;
3921 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3922 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
3923 log_error("Failed to parse reply.");
3928 dbus_message_iter_recurse(&iter, &sub);
3929 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
3930 const char *type, *path, *source;
3932 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
3933 log_error("Failed to parse reply.");
3938 dbus_message_iter_recurse(&sub, &sub2);
3940 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
3941 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
3942 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &source, false) < 0) {
3943 log_error("Failed to parse reply.");
3949 if (streq(type, "symlink"))
3950 log_info("ln -s '%s' '%s'", source, path);
3952 log_info("rm '%s'", path);
3955 dbus_message_iter_next(&sub);
3958 /* Try to reload if enabeld */
3960 r = daemon_reload(bus, args);
3963 if (carries_install_info == 0)
3964 log_warning("Warning: unit files do not carry install information. No operation executed.");
3968 dbus_message_unref(m);
3971 dbus_message_unref(reply);
3973 unit_file_changes_free(changes, n_changes);
3975 dbus_error_free(&error);
3979 static int unit_is_enabled(DBusConnection *bus, char **args) {
3982 DBusMessage *m = NULL, *reply = NULL;
3986 dbus_error_init(&error);
3988 r = enable_sysv_units(args);
3994 if (!bus || avoid_bus()) {
3996 STRV_FOREACH(name, args+1) {
3997 UnitFileState state;
3999 state = unit_file_get_state(arg_scope, arg_root, *name);
4005 if (state == UNIT_FILE_ENABLED ||
4006 state == UNIT_FILE_ENABLED_RUNTIME ||
4007 state == UNIT_FILE_STATIC)
4011 puts(unit_file_state_to_string(state));
4015 STRV_FOREACH(name, args+1) {
4018 m = dbus_message_new_method_call(
4019 "org.freedesktop.systemd1",
4020 "/org/freedesktop/systemd1",
4021 "org.freedesktop.systemd1.Manager",
4022 "GetUnitFileState");
4024 log_error("Out of memory");
4029 if (!dbus_message_append_args(m,
4030 DBUS_TYPE_STRING, name,
4031 DBUS_TYPE_INVALID)) {
4032 log_error("Could not append arguments to message.");
4037 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
4039 log_error("Failed to issue method call: %s", bus_error_message(&error));
4044 if (!dbus_message_get_args(reply, &error,
4045 DBUS_TYPE_STRING, &s,
4046 DBUS_TYPE_INVALID)) {
4047 log_error("Failed to parse reply: %s", bus_error_message(&error));
4052 dbus_message_unref(m);
4053 dbus_message_unref(reply);
4056 if (streq(s, "enabled") ||
4057 streq(s, "enabled-runtime") ||
4066 r = enabled ? 0 : 1;
4070 dbus_message_unref(m);
4073 dbus_message_unref(reply);
4075 dbus_error_free(&error);
4079 static int systemctl_help(void) {
4081 pager_open_if_enabled();
4083 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
4084 "Query or send control commands to the systemd manager.\n\n"
4085 " -h --help Show this help\n"
4086 " --version Show package version\n"
4087 " -t --type=TYPE List only units of a particular type\n"
4088 " -p --property=NAME Show only properties by this name\n"
4089 " -a --all Show all units/properties, including dead/empty ones\n"
4090 " --failed Show only failed units\n"
4091 " --full Don't ellipsize unit names on output\n"
4092 " --fail When queueing a new job, fail if conflicting jobs are\n"
4094 " --ignore-dependencies\n"
4095 " When queueing a new job, ignore all its dependencies\n"
4096 " --kill-who=WHO Who to send signal to\n"
4097 " -s --signal=SIGNAL Which signal to send\n"
4098 " -H --host=[USER@]HOST\n"
4099 " Show information for remote host\n"
4100 " -P --privileged Acquire privileges before execution\n"
4101 " -q --quiet Suppress output\n"
4102 " --no-block Do not wait until operation finished\n"
4103 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4104 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
4106 " --no-legend Do not print a legend (column headers and hints)\n"
4107 " --no-pager Do not pipe output into a pager\n"
4108 " --no-ask-password\n"
4109 " Do not ask for system passwords\n"
4110 " --order When generating graph for dot, show only order\n"
4111 " --require When generating graph for dot, show only requirement\n"
4112 " --system Connect to system manager\n"
4113 " --user Connect to user service manager\n"
4114 " --global Enable/disable unit files globally\n"
4115 " -f --force When enabling unit files, override existing symlinks\n"
4116 " When shutting down, execute action immediately\n"
4117 " --root=PATH Enable unit files in the specified root directory\n"
4118 " --runtime Enable unit files only temporarily until next reboot\n"
4119 " -n --lines=INTEGER Journal entries to show\n"
4120 " --follow Follow journal\n"
4121 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
4122 " verbose, export, json, cat)\n\n"
4124 " list-units List loaded units\n"
4125 " start [NAME...] Start (activate) one or more units\n"
4126 " stop [NAME...] Stop (deactivate) one or more units\n"
4127 " reload [NAME...] Reload one or more units\n"
4128 " restart [NAME...] Start or restart one or more units\n"
4129 " try-restart [NAME...] Restart one or more units if active\n"
4130 " reload-or-restart [NAME...] Reload one or more units is possible,\n"
4131 " otherwise start or restart\n"
4132 " reload-or-try-restart [NAME...] Reload one or more units is possible,\n"
4133 " otherwise restart if active\n"
4134 " isolate [NAME] Start one unit and stop all others\n"
4135 " kill [NAME...] Send signal to processes of a unit\n"
4136 " is-active [NAME...] Check whether units are active\n"
4137 " status [NAME...|PID...] Show runtime status of one or more units\n"
4138 " show [NAME...|JOB...] Show properties of one or more\n"
4139 " units/jobs or the manager\n"
4140 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
4142 " load [NAME...] Load one or more units\n\n"
4143 "Unit File Commands:\n"
4144 " list-unit-files List installed unit files\n"
4145 " enable [NAME...] Enable one or more unit files\n"
4146 " disable [NAME...] Disable one or more unit files\n"
4147 " reenable [NAME...] Reenable one or more unit files\n"
4148 " preset [NAME...] Enable/disable one or more unit files\n"
4149 " based on preset configuration\n"
4150 " mask [NAME...] Mask one or more units\n"
4151 " unmask [NAME...] Unmask one or more units\n"
4152 " link [PATH...] Link one or more units files into\n"
4153 " the search path\n"
4154 " is-enabled [NAME...] Check whether unit files are enabled\n\n"
4156 " list-jobs List jobs\n"
4157 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
4158 "Status Commands:\n"
4159 " dump Dump server status\n"
4160 " dot Dump dependency graph for dot(1)\n\n"
4161 "Snapshot Commands:\n"
4162 " snapshot [NAME] Create a snapshot\n"
4163 " delete [NAME...] Remove one or more snapshots\n\n"
4164 "Environment Commands:\n"
4165 " show-environment Dump environment\n"
4166 " set-environment [NAME=VALUE...] Set one or more environment variables\n"
4167 " unset-environment [NAME...] Unset one or more environment variables\n\n"
4168 "Manager Lifecycle Commands:\n"
4169 " daemon-reload Reload systemd manager configuration\n"
4170 " daemon-reexec Reexecute systemd manager\n\n"
4171 "System Commands:\n"
4172 " default Enter system default mode\n"
4173 " rescue Enter system rescue mode\n"
4174 " emergency Enter system emergency mode\n"
4175 " halt Shut down and halt the system\n"
4176 " poweroff Shut down and power-off the system\n"
4177 " reboot Shut down and reboot the system\n"
4178 " kexec Shut down and reboot the system with kexec\n"
4179 " exit Ask for user instance termination\n",
4180 program_invocation_short_name);
4185 static int halt_help(void) {
4187 printf("%s [OPTIONS...]\n\n"
4188 "%s the system.\n\n"
4189 " --help Show this help\n"
4190 " --halt Halt the machine\n"
4191 " -p --poweroff Switch off the machine\n"
4192 " --reboot Reboot the machine\n"
4193 " -f --force Force immediate halt/power-off/reboot\n"
4194 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
4195 " -d --no-wtmp Don't write wtmp record\n"
4196 " -n --no-sync Don't sync before halt/power-off/reboot\n"
4197 " --no-wall Don't send wall message before halt/power-off/reboot\n",
4198 program_invocation_short_name,
4199 arg_action == ACTION_REBOOT ? "Reboot" :
4200 arg_action == ACTION_POWEROFF ? "Power off" :
4206 static int shutdown_help(void) {
4208 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
4209 "Shut down the system.\n\n"
4210 " --help Show this help\n"
4211 " -H --halt Halt the machine\n"
4212 " -P --poweroff Power-off the machine\n"
4213 " -r --reboot Reboot the machine\n"
4214 " -h Equivalent to --poweroff, overriden by --halt\n"
4215 " -k Don't halt/power-off/reboot, just send warnings\n"
4216 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4217 " -c Cancel a pending shutdown\n",
4218 program_invocation_short_name);
4223 static int telinit_help(void) {
4225 printf("%s [OPTIONS...] {COMMAND}\n\n"
4226 "Send control commands to the init daemon.\n\n"
4227 " --help Show this help\n"
4228 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
4230 " 0 Power-off the machine\n"
4231 " 6 Reboot the machine\n"
4232 " 2, 3, 4, 5 Start runlevelX.target unit\n"
4233 " 1, s, S Enter rescue mode\n"
4234 " q, Q Reload init daemon configuration\n"
4235 " u, U Reexecute init daemon\n",
4236 program_invocation_short_name);
4241 static int runlevel_help(void) {
4243 printf("%s [OPTIONS...]\n\n"
4244 "Prints the previous and current runlevel of the init system.\n\n"
4245 " --help Show this help\n",
4246 program_invocation_short_name);
4251 static int systemctl_parse_argv(int argc, char *argv[]) {
4255 ARG_IGNORE_DEPENDENCIES,
4271 ARG_NO_ASK_PASSWORD,
4278 static const struct option options[] = {
4279 { "help", no_argument, NULL, 'h' },
4280 { "version", no_argument, NULL, ARG_VERSION },
4281 { "type", required_argument, NULL, 't' },
4282 { "property", required_argument, NULL, 'p' },
4283 { "all", no_argument, NULL, 'a' },
4284 { "failed", no_argument, NULL, ARG_FAILED },
4285 { "full", no_argument, NULL, ARG_FULL },
4286 { "fail", no_argument, NULL, ARG_FAIL },
4287 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
4288 { "user", no_argument, NULL, ARG_USER },
4289 { "system", no_argument, NULL, ARG_SYSTEM },
4290 { "global", no_argument, NULL, ARG_GLOBAL },
4291 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
4292 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
4293 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
4294 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4295 { "quiet", no_argument, NULL, 'q' },
4296 { "order", no_argument, NULL, ARG_ORDER },
4297 { "require", no_argument, NULL, ARG_REQUIRE },
4298 { "root", required_argument, NULL, ARG_ROOT },
4299 { "force", no_argument, NULL, ARG_FORCE },
4300 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
4301 { "kill-mode", required_argument, NULL, ARG_KILL_MODE }, /* undocumented on purpose */
4302 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
4303 { "signal", required_argument, NULL, 's' },
4304 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
4305 { "host", required_argument, NULL, 'H' },
4306 { "privileged",no_argument, NULL, 'P' },
4307 { "runtime", no_argument, NULL, ARG_RUNTIME },
4308 { "lines", required_argument, NULL, 'n' },
4309 { "follow", no_argument, NULL, ARG_FOLLOW },
4310 { "output", required_argument, NULL, 'o' },
4311 { NULL, 0, NULL, 0 }
4319 while ((c = getopt_long(argc, argv, "ht:p:aqfs:H:Pn:o:", options, NULL)) >= 0) {
4328 puts(PACKAGE_STRING);
4330 puts(SYSTEMD_FEATURES);
4340 if (!(l = strv_append(arg_property, optarg)))
4343 strv_free(arg_property);
4346 /* If the user asked for a particular
4347 * property, show it to him, even if it is
4358 arg_job_mode = "fail";
4361 case ARG_IGNORE_DEPENDENCIES:
4362 arg_job_mode = "ignore-dependencies";
4366 arg_scope = UNIT_FILE_USER;
4370 arg_scope = UNIT_FILE_SYSTEM;
4374 arg_scope = UNIT_FILE_GLOBAL;
4378 arg_no_block = true;
4382 arg_no_legend = true;
4386 arg_no_pager = true;
4394 arg_dot = DOT_ORDER;
4398 arg_dot = DOT_REQUIRE;
4426 /* -f is short for both --follow and --force! */
4432 arg_no_reload = true;
4436 arg_kill_who = optarg;
4440 arg_kill_mode = optarg;
4444 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
4445 log_error("Failed to parse signal string %s.", optarg);
4450 case ARG_NO_ASK_PASSWORD:
4451 arg_ask_password = false;
4455 arg_transport = TRANSPORT_POLKIT;
4459 arg_transport = TRANSPORT_SSH;
4468 if (safe_atou(optarg, &arg_lines) < 0) {
4469 log_error("Failed to parse lines '%s'", optarg);
4475 arg_output = output_mode_from_string(optarg);
4476 if (arg_output < 0) {
4477 log_error("Unknown output '%s'.", optarg);
4486 log_error("Unknown option code %c", c);
4491 if (arg_transport != TRANSPORT_NORMAL && arg_scope != UNIT_FILE_SYSTEM) {
4492 log_error("Cannot access user instance remotely.");
4499 static int halt_parse_argv(int argc, char *argv[]) {
4508 static const struct option options[] = {
4509 { "help", no_argument, NULL, ARG_HELP },
4510 { "halt", no_argument, NULL, ARG_HALT },
4511 { "poweroff", no_argument, NULL, 'p' },
4512 { "reboot", no_argument, NULL, ARG_REBOOT },
4513 { "force", no_argument, NULL, 'f' },
4514 { "wtmp-only", no_argument, NULL, 'w' },
4515 { "no-wtmp", no_argument, NULL, 'd' },
4516 { "no-sync", no_argument, NULL, 'n' },
4517 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4518 { NULL, 0, NULL, 0 }
4526 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
4527 if (runlevel == '0' || runlevel == '6')
4528 arg_immediate = true;
4530 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
4538 arg_action = ACTION_HALT;
4542 if (arg_action != ACTION_REBOOT)
4543 arg_action = ACTION_POWEROFF;
4547 arg_action = ACTION_REBOOT;
4551 arg_immediate = true;
4572 /* Compatibility nops */
4579 log_error("Unknown option code %c", c);
4584 if (optind < argc) {
4585 log_error("Too many arguments.");
4592 static int parse_time_spec(const char *t, usec_t *_u) {
4596 if (streq(t, "now"))
4598 else if (!strchr(t, ':')) {
4601 if (safe_atou64(t, &u) < 0)
4604 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
4613 hour = strtol(t, &e, 10);
4614 if (errno != 0 || *e != ':' || hour < 0 || hour > 23)
4617 minute = strtol(e+1, &e, 10);
4618 if (errno != 0 || *e != 0 || minute < 0 || minute > 59)
4621 n = now(CLOCK_REALTIME);
4622 s = (time_t) (n / USEC_PER_SEC);
4625 assert_se(localtime_r(&s, &tm));
4627 tm.tm_hour = (int) hour;
4628 tm.tm_min = (int) minute;
4631 assert_se(s = mktime(&tm));
4633 *_u = (usec_t) s * USEC_PER_SEC;
4636 *_u += USEC_PER_DAY;
4642 static int shutdown_parse_argv(int argc, char *argv[]) {
4649 static const struct option options[] = {
4650 { "help", no_argument, NULL, ARG_HELP },
4651 { "halt", no_argument, NULL, 'H' },
4652 { "poweroff", no_argument, NULL, 'P' },
4653 { "reboot", no_argument, NULL, 'r' },
4654 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
4655 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4656 { NULL, 0, NULL, 0 }
4664 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
4672 arg_action = ACTION_HALT;
4676 arg_action = ACTION_POWEROFF;
4681 arg_action = ACTION_KEXEC;
4683 arg_action = ACTION_REBOOT;
4687 arg_action = ACTION_KEXEC;
4691 if (arg_action != ACTION_HALT)
4692 arg_action = ACTION_POWEROFF;
4705 /* Compatibility nops */
4709 arg_action = ACTION_CANCEL_SHUTDOWN;
4716 log_error("Unknown option code %c", c);
4721 if (argc > optind) {
4722 r = parse_time_spec(argv[optind], &arg_when);
4724 log_error("Failed to parse time specification: %s", argv[optind]);
4728 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
4730 /* We skip the time argument */
4731 if (argc > optind + 1)
4732 arg_wall = argv + optind + 1;
4739 static int telinit_parse_argv(int argc, char *argv[]) {
4746 static const struct option options[] = {
4747 { "help", no_argument, NULL, ARG_HELP },
4748 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4749 { NULL, 0, NULL, 0 }
4752 static const struct {
4756 { '0', ACTION_POWEROFF },
4757 { '6', ACTION_REBOOT },
4758 { '1', ACTION_RESCUE },
4759 { '2', ACTION_RUNLEVEL2 },
4760 { '3', ACTION_RUNLEVEL3 },
4761 { '4', ACTION_RUNLEVEL4 },
4762 { '5', ACTION_RUNLEVEL5 },
4763 { 's', ACTION_RESCUE },
4764 { 'S', ACTION_RESCUE },
4765 { 'q', ACTION_RELOAD },
4766 { 'Q', ACTION_RELOAD },
4767 { 'u', ACTION_REEXEC },
4768 { 'U', ACTION_REEXEC }
4777 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4792 log_error("Unknown option code %c", c);
4797 if (optind >= argc) {
4802 if (optind + 1 < argc) {
4803 log_error("Too many arguments.");
4807 if (strlen(argv[optind]) != 1) {
4808 log_error("Expected single character argument.");
4812 for (i = 0; i < ELEMENTSOF(table); i++)
4813 if (table[i].from == argv[optind][0])
4816 if (i >= ELEMENTSOF(table)) {
4817 log_error("Unknown command %s.", argv[optind]);
4821 arg_action = table[i].to;
4828 static int runlevel_parse_argv(int argc, char *argv[]) {
4834 static const struct option options[] = {
4835 { "help", no_argument, NULL, ARG_HELP },
4836 { NULL, 0, NULL, 0 }
4844 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4855 log_error("Unknown option code %c", c);
4860 if (optind < argc) {
4861 log_error("Too many arguments.");
4868 static int parse_argv(int argc, char *argv[]) {
4872 if (program_invocation_short_name) {
4874 if (strstr(program_invocation_short_name, "halt")) {
4875 arg_action = ACTION_HALT;
4876 return halt_parse_argv(argc, argv);
4877 } else if (strstr(program_invocation_short_name, "poweroff")) {
4878 arg_action = ACTION_POWEROFF;
4879 return halt_parse_argv(argc, argv);
4880 } else if (strstr(program_invocation_short_name, "reboot")) {
4882 arg_action = ACTION_KEXEC;
4884 arg_action = ACTION_REBOOT;
4885 return halt_parse_argv(argc, argv);
4886 } else if (strstr(program_invocation_short_name, "shutdown")) {
4887 arg_action = ACTION_POWEROFF;
4888 return shutdown_parse_argv(argc, argv);
4889 } else if (strstr(program_invocation_short_name, "init")) {
4891 if (sd_booted() > 0) {
4892 arg_action = ACTION_INVALID;
4893 return telinit_parse_argv(argc, argv);
4895 /* Hmm, so some other init system is
4896 * running, we need to forward this
4897 * request to it. For now we simply
4898 * guess that it is Upstart. */
4900 execv("/lib/upstart/telinit", argv);
4902 log_error("Couldn't find an alternative telinit implementation to spawn.");
4906 } else if (strstr(program_invocation_short_name, "runlevel")) {
4907 arg_action = ACTION_RUNLEVEL;
4908 return runlevel_parse_argv(argc, argv);
4912 arg_action = ACTION_SYSTEMCTL;
4913 return systemctl_parse_argv(argc, argv);
4916 static int action_to_runlevel(void) {
4918 static const char table[_ACTION_MAX] = {
4919 [ACTION_HALT] = '0',
4920 [ACTION_POWEROFF] = '0',
4921 [ACTION_REBOOT] = '6',
4922 [ACTION_RUNLEVEL2] = '2',
4923 [ACTION_RUNLEVEL3] = '3',
4924 [ACTION_RUNLEVEL4] = '4',
4925 [ACTION_RUNLEVEL5] = '5',
4926 [ACTION_RESCUE] = '1'
4929 assert(arg_action < _ACTION_MAX);
4931 return table[arg_action];
4934 static int talk_upstart(void) {
4935 DBusMessage *m = NULL, *reply = NULL;
4937 int previous, rl, r;
4939 env1_buf[] = "RUNLEVEL=X",
4940 env2_buf[] = "PREVLEVEL=X";
4941 char *env1 = env1_buf, *env2 = env2_buf;
4942 const char *emit = "runlevel";
4943 dbus_bool_t b_false = FALSE;
4944 DBusMessageIter iter, sub;
4945 DBusConnection *bus;
4947 dbus_error_init(&error);
4949 if (!(rl = action_to_runlevel()))
4952 if (utmp_get_runlevel(&previous, NULL) < 0)
4955 if (!(bus = dbus_connection_open_private("unix:abstract=/com/ubuntu/upstart", &error))) {
4956 if (dbus_error_has_name(&error, DBUS_ERROR_NO_SERVER)) {
4961 log_error("Failed to connect to Upstart bus: %s", bus_error_message(&error));
4966 if ((r = bus_check_peercred(bus)) < 0) {
4967 log_error("Failed to verify owner of bus.");
4971 if (!(m = dbus_message_new_method_call(
4972 "com.ubuntu.Upstart",
4973 "/com/ubuntu/Upstart",
4974 "com.ubuntu.Upstart0_6",
4977 log_error("Could not allocate message.");
4982 dbus_message_iter_init_append(m, &iter);
4984 env1_buf[sizeof(env1_buf)-2] = rl;
4985 env2_buf[sizeof(env2_buf)-2] = previous;
4987 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &emit) ||
4988 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub) ||
4989 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env1) ||
4990 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env2) ||
4991 !dbus_message_iter_close_container(&iter, &sub) ||
4992 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b_false)) {
4993 log_error("Could not append arguments to message.");
4998 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
5000 if (error_is_no_service(&error)) {
5005 log_error("Failed to issue method call: %s", bus_error_message(&error));
5014 dbus_message_unref(m);
5017 dbus_message_unref(reply);
5020 dbus_connection_flush(bus);
5021 dbus_connection_close(bus);
5022 dbus_connection_unref(bus);
5025 dbus_error_free(&error);
5030 static int talk_initctl(void) {
5031 struct init_request request;
5035 if (!(rl = action_to_runlevel()))
5039 request.magic = INIT_MAGIC;
5040 request.sleeptime = 0;
5041 request.cmd = INIT_CMD_RUNLVL;
5042 request.runlevel = rl;
5044 if ((fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY)) < 0) {
5046 if (errno == ENOENT)
5049 log_error("Failed to open "INIT_FIFO": %m");
5054 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
5055 close_nointr_nofail(fd);
5058 log_error("Failed to write to "INIT_FIFO": %m");
5059 return errno ? -errno : -EIO;
5065 static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
5067 static const struct {
5075 int (* const dispatch)(DBusConnection *bus, char **args);
5077 { "list-units", LESS, 1, list_units },
5078 { "list-unit-files", EQUAL, 1, list_unit_files },
5079 { "list-jobs", EQUAL, 1, list_jobs },
5080 { "clear-jobs", EQUAL, 1, daemon_reload },
5081 { "load", MORE, 2, load_unit },
5082 { "cancel", MORE, 2, cancel_job },
5083 { "start", MORE, 2, start_unit },
5084 { "stop", MORE, 2, start_unit },
5085 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5086 { "reload", MORE, 2, start_unit },
5087 { "restart", MORE, 2, start_unit },
5088 { "try-restart", MORE, 2, start_unit },
5089 { "reload-or-restart", MORE, 2, start_unit },
5090 { "reload-or-try-restart", MORE, 2, start_unit },
5091 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
5092 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5093 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
5094 { "isolate", EQUAL, 2, start_unit },
5095 { "kill", MORE, 2, kill_unit },
5096 { "is-active", MORE, 2, check_unit },
5097 { "check", MORE, 2, check_unit },
5098 { "show", MORE, 1, show },
5099 { "status", MORE, 2, show },
5100 { "dump", EQUAL, 1, dump },
5101 { "dot", EQUAL, 1, dot },
5102 { "snapshot", LESS, 2, snapshot },
5103 { "delete", MORE, 2, delete_snapshot },
5104 { "daemon-reload", EQUAL, 1, daemon_reload },
5105 { "daemon-reexec", EQUAL, 1, daemon_reload },
5106 { "show-environment", EQUAL, 1, show_enviroment },
5107 { "set-environment", MORE, 2, set_environment },
5108 { "unset-environment", MORE, 2, set_environment },
5109 { "halt", EQUAL, 1, start_special },
5110 { "poweroff", EQUAL, 1, start_special },
5111 { "reboot", EQUAL, 1, start_special },
5112 { "kexec", EQUAL, 1, start_special },
5113 { "default", EQUAL, 1, start_special },
5114 { "rescue", EQUAL, 1, start_special },
5115 { "emergency", EQUAL, 1, start_special },
5116 { "exit", EQUAL, 1, start_special },
5117 { "reset-failed", MORE, 1, reset_failed },
5118 { "enable", MORE, 2, enable_unit },
5119 { "disable", MORE, 2, enable_unit },
5120 { "is-enabled", MORE, 2, unit_is_enabled },
5121 { "reenable", MORE, 2, enable_unit },
5122 { "preset", MORE, 2, enable_unit },
5123 { "mask", MORE, 2, enable_unit },
5124 { "unmask", MORE, 2, enable_unit },
5125 { "link", MORE, 2, enable_unit }
5135 left = argc - optind;
5138 /* Special rule: no arguments means "list-units" */
5141 if (streq(argv[optind], "help")) {
5146 for (i = 0; i < ELEMENTSOF(verbs); i++)
5147 if (streq(argv[optind], verbs[i].verb))
5150 if (i >= ELEMENTSOF(verbs)) {
5151 log_error("Unknown operation %s", argv[optind]);
5156 switch (verbs[i].argc_cmp) {
5159 if (left != verbs[i].argc) {
5160 log_error("Invalid number of arguments.");
5167 if (left < verbs[i].argc) {
5168 log_error("Too few arguments.");
5175 if (left > verbs[i].argc) {
5176 log_error("Too many arguments.");
5183 assert_not_reached("Unknown comparison operator.");
5186 /* Require a bus connection for all operations but
5188 if (!streq(verbs[i].verb, "enable") &&
5189 !streq(verbs[i].verb, "disable") &&
5190 !streq(verbs[i].verb, "is-enabled") &&
5191 !streq(verbs[i].verb, "list-unit-files") &&
5192 !streq(verbs[i].verb, "reenable") &&
5193 !streq(verbs[i].verb, "preset") &&
5194 !streq(verbs[i].verb, "mask") &&
5195 !streq(verbs[i].verb, "unmask") &&
5196 !streq(verbs[i].verb, "link")) {
5198 if (running_in_chroot() > 0) {
5199 log_info("Running in chroot, ignoring request.");
5204 log_error("Failed to get D-Bus connection: %s",
5205 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5211 if (!bus && !avoid_bus()) {
5212 log_error("Failed to get D-Bus connection: %s",
5213 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5218 return verbs[i].dispatch(bus, argv + optind);
5221 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
5223 struct msghdr msghdr;
5224 struct iovec iovec[2];
5225 union sockaddr_union sockaddr;
5226 struct sd_shutdown_command c;
5228 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
5235 c.dry_run = dry_run;
5239 sockaddr.sa.sa_family = AF_UNIX;
5240 strncpy(sockaddr.un.sun_path, "/run/systemd/shutdownd", sizeof(sockaddr.un.sun_path));
5243 msghdr.msg_name = &sockaddr;
5244 msghdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + sizeof("/run/systemd/shutdownd") - 1;
5247 iovec[0].iov_base = (char*) &c;
5248 iovec[0].iov_len = offsetof(struct sd_shutdown_command, wall_message);
5250 if (isempty(message))
5251 msghdr.msg_iovlen = 1;
5253 iovec[1].iov_base = (char*) message;
5254 iovec[1].iov_len = strlen(message);
5255 msghdr.msg_iovlen = 2;
5257 msghdr.msg_iov = iovec;
5259 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0) {
5260 close_nointr_nofail(fd);
5264 close_nointr_nofail(fd);
5268 static int reload_with_fallback(DBusConnection *bus) {
5271 /* First, try systemd via D-Bus. */
5272 if (daemon_reload(bus, NULL) >= 0)
5276 /* Nothing else worked, so let's try signals */
5277 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
5279 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
5280 log_error("kill() failed: %m");
5287 static int start_with_fallback(DBusConnection *bus) {
5290 /* First, try systemd via D-Bus. */
5291 if (start_unit(bus, NULL) >= 0)
5295 /* Hmm, talking to systemd via D-Bus didn't work. Then
5296 * let's try to talk to Upstart via D-Bus. */
5297 if (talk_upstart() > 0)
5300 /* Nothing else worked, so let's try
5302 if (talk_initctl() > 0)
5305 log_error("Failed to talk to init daemon.");
5309 warn_wall(arg_action);
5313 static void halt_now(enum action a) {
5315 /* Make sure C-A-D is handled by the kernel from this
5317 reboot(RB_ENABLE_CAD);
5322 log_info("Halting.");
5323 reboot(RB_HALT_SYSTEM);
5326 case ACTION_POWEROFF:
5327 log_info("Powering off.");
5328 reboot(RB_POWER_OFF);
5332 log_info("Rebooting.");
5333 reboot(RB_AUTOBOOT);
5337 assert_not_reached("Unknown halt action.");
5340 assert_not_reached("Uh? This shouldn't happen.");
5343 static int halt_main(DBusConnection *bus) {
5346 if (geteuid() != 0) {
5347 /* Try logind if we are a normal user and no special
5348 * mode applies. Maybe PolicyKit allows us to shutdown
5351 if (arg_when <= 0 &&
5354 (arg_action == ACTION_POWEROFF ||
5355 arg_action == ACTION_REBOOT)) {
5356 r = reboot_with_logind(bus, arg_action);
5361 log_error("Must be root.");
5368 m = strv_join(arg_wall, " ");
5369 r = send_shutdownd(arg_when,
5370 arg_action == ACTION_HALT ? 'H' :
5371 arg_action == ACTION_POWEROFF ? 'P' :
5372 arg_action == ACTION_KEXEC ? 'K' :
5380 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
5382 char date[FORMAT_TIMESTAMP_MAX];
5384 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
5385 format_timestamp(date, sizeof(date), arg_when));
5390 if (!arg_dry && !arg_immediate)
5391 return start_with_fallback(bus);
5394 if (sd_booted() > 0)
5395 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
5397 r = utmp_put_shutdown();
5399 log_warning("Failed to write utmp record: %s", strerror(-r));
5409 halt_now(arg_action);
5410 /* We should never reach this. */
5414 static int runlevel_main(void) {
5415 int r, runlevel, previous;
5417 r = utmp_get_runlevel(&runlevel, &previous);
5424 previous <= 0 ? 'N' : previous,
5425 runlevel <= 0 ? 'N' : runlevel);
5430 int main(int argc, char*argv[]) {
5431 int r, retval = EXIT_FAILURE;
5432 DBusConnection *bus = NULL;
5435 dbus_error_init(&error);
5437 log_parse_environment();
5440 r = parse_argv(argc, argv);
5444 retval = EXIT_SUCCESS;
5448 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
5449 * let's shortcut this */
5450 if (arg_action == ACTION_RUNLEVEL) {
5451 r = runlevel_main();
5452 retval = r < 0 ? EXIT_FAILURE : r;
5456 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
5457 log_info("Running in chroot, ignoring request.");
5463 if (arg_transport == TRANSPORT_NORMAL)
5464 bus_connect(arg_scope == UNIT_FILE_SYSTEM ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &bus, &private_bus, &error);
5465 else if (arg_transport == TRANSPORT_POLKIT) {
5466 bus_connect_system_polkit(&bus, &error);
5467 private_bus = false;
5468 } else if (arg_transport == TRANSPORT_SSH) {
5469 bus_connect_system_ssh(NULL, arg_host, &bus, &error);
5470 private_bus = false;
5472 assert_not_reached("Uh, invalid transport...");
5475 switch (arg_action) {
5477 case ACTION_SYSTEMCTL:
5478 r = systemctl_main(bus, argc, argv, &error);
5482 case ACTION_POWEROFF:
5488 case ACTION_RUNLEVEL2:
5489 case ACTION_RUNLEVEL3:
5490 case ACTION_RUNLEVEL4:
5491 case ACTION_RUNLEVEL5:
5493 case ACTION_EMERGENCY:
5494 case ACTION_DEFAULT:
5495 r = start_with_fallback(bus);
5500 r = reload_with_fallback(bus);
5503 case ACTION_CANCEL_SHUTDOWN:
5504 r = send_shutdownd(0, 0, false, false, NULL);
5507 case ACTION_INVALID:
5508 case ACTION_RUNLEVEL:
5510 assert_not_reached("Unknown action");
5513 retval = r < 0 ? EXIT_FAILURE : r;
5517 dbus_connection_flush(bus);
5518 dbus_connection_close(bus);
5519 dbus_connection_unref(bus);
5522 dbus_error_free(&error);
5526 strv_free(arg_property);
5529 ask_password_agent_close();
5530 polkit_agent_close();