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 General Public License as published by
10 the Free Software Foundation; either version 2 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 General Public License for more details.
18 You should have received a copy of the GNU 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>
42 #include "utmp-wtmp.h"
46 #include "dbus-common.h"
47 #include "cgroup-show.h"
48 #include "cgroup-util.h"
50 #include "path-lookup.h"
51 #include "conf-parser.h"
52 #include "sd-daemon.h"
53 #include "shutdownd.h"
54 #include "exit-status.h"
55 #include "bus-errors.h"
57 #include "unit-name.h"
59 #include "spawn-agent.h"
61 #include "logs-show.h"
63 static const char *arg_type = NULL;
64 static char **arg_property = NULL;
65 static bool arg_all = false;
66 static const char *arg_job_mode = "replace";
67 static UnitFileScope arg_scope = UNIT_FILE_SYSTEM;
68 static bool arg_immediate = false;
69 static bool arg_no_block = false;
70 static bool arg_no_legend = false;
71 static bool arg_no_pager = false;
72 static bool arg_no_wtmp = false;
73 static bool arg_no_sync = false;
74 static bool arg_no_wall = false;
75 static bool arg_no_reload = false;
76 static bool arg_dry = false;
77 static bool arg_quiet = false;
78 static bool arg_full = false;
79 static bool arg_force = false;
80 static bool arg_ask_password = false;
81 static bool arg_failed = false;
82 static bool arg_runtime = false;
83 static char **arg_wall = NULL;
84 static const char *arg_kill_who = NULL;
85 static const char *arg_kill_mode = NULL;
86 static int arg_signal = SIGTERM;
87 static const char *arg_root = NULL;
88 static usec_t arg_when = 0;
107 ACTION_CANCEL_SHUTDOWN,
109 } arg_action = ACTION_SYSTEMCTL;
115 static enum transport {
119 } arg_transport = TRANSPORT_NORMAL;
120 static const char *arg_host = NULL;
121 static bool arg_follow = false;
122 static unsigned arg_lines = 10;
123 static OutputMode arg_output = OUTPUT_SHORT;
125 static bool private_bus = false;
127 static int daemon_reload(DBusConnection *bus, char **args);
129 static bool on_tty(void) {
132 /* Note that this is invoked relatively early, before we start
133 * the pager. That means the value we return reflects whether
134 * we originally were started on a tty, not if we currently
135 * are. But this is intended, since we want colour and so on
136 * when run in our own pager. */
138 if (_unlikely_(t < 0))
139 t = isatty(STDOUT_FILENO) > 0;
144 static void pager_open_if_enabled(void) {
146 /* Cache result before we open the pager */
155 static void agent_open_if_enabled(void) {
157 /* Open the password agent as a child process if necessary */
159 if (!arg_ask_password)
162 if (arg_scope != UNIT_FILE_SYSTEM)
168 static const char *ansi_highlight(bool b) {
173 return b ? ANSI_HIGHLIGHT_ON : ANSI_HIGHLIGHT_OFF;
176 static const char *ansi_highlight_green(bool b) {
181 return b ? ANSI_HIGHLIGHT_GREEN_ON : ANSI_HIGHLIGHT_OFF;
184 static bool error_is_no_service(const DBusError *error) {
187 if (!dbus_error_is_set(error))
190 if (dbus_error_has_name(error, DBUS_ERROR_NAME_HAS_NO_OWNER))
193 if (dbus_error_has_name(error, DBUS_ERROR_SERVICE_UNKNOWN))
196 return startswith(error->name, "org.freedesktop.DBus.Error.Spawn.");
199 static int translate_bus_error_to_exit_status(int r, const DBusError *error) {
202 if (!dbus_error_is_set(error))
205 if (dbus_error_has_name(error, DBUS_ERROR_ACCESS_DENIED) ||
206 dbus_error_has_name(error, BUS_ERROR_ONLY_BY_DEPENDENCY) ||
207 dbus_error_has_name(error, BUS_ERROR_NO_ISOLATION) ||
208 dbus_error_has_name(error, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE))
209 return EXIT_NOPERMISSION;
211 if (dbus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT))
212 return EXIT_NOTINSTALLED;
214 if (dbus_error_has_name(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE) ||
215 dbus_error_has_name(error, BUS_ERROR_NOT_SUPPORTED))
216 return EXIT_NOTIMPLEMENTED;
218 if (dbus_error_has_name(error, BUS_ERROR_LOAD_FAILED))
219 return EXIT_NOTCONFIGURED;
227 static void warn_wall(enum action action) {
228 static const char *table[_ACTION_MAX] = {
229 [ACTION_HALT] = "The system is going down for system halt NOW!",
230 [ACTION_REBOOT] = "The system is going down for reboot NOW!",
231 [ACTION_POWEROFF] = "The system is going down for power-off NOW!",
232 [ACTION_KEXEC] = "The system is going down for kexec reboot NOW!",
233 [ACTION_RESCUE] = "The system is going down to rescue mode NOW!",
234 [ACTION_EMERGENCY] = "The system is going down to emergency mode NOW!"
243 if (!(p = strv_join(arg_wall, " "))) {
244 log_error("Failed to join strings.");
260 utmp_wall(table[action], NULL);
263 static bool avoid_bus(void) {
265 if (running_in_chroot() > 0)
268 if (sd_booted() <= 0)
271 if (!isempty(arg_root))
274 if (arg_scope == UNIT_FILE_GLOBAL)
282 const char *description;
283 const char *load_state;
284 const char *active_state;
285 const char *sub_state;
286 const char *following;
287 const char *unit_path;
289 const char *job_type;
290 const char *job_path;
293 static int compare_unit_info(const void *a, const void *b) {
295 const struct unit_info *u = a, *v = b;
297 d1 = strrchr(u->id, '.');
298 d2 = strrchr(v->id, '.');
303 if ((r = strcasecmp(d1, d2)) != 0)
307 return strcasecmp(u->id, v->id);
310 static bool output_show_unit(const struct unit_info *u) {
314 return streq(u->active_state, "failed");
316 return (!arg_type || ((dot = strrchr(u->id, '.')) &&
317 streq(dot+1, arg_type))) &&
318 (arg_all || !(streq(u->active_state, "inactive") || u->following[0]) || u->job_id > 0);
321 static void output_units_list(const struct unit_info *unit_infos, unsigned c) {
322 unsigned id_len, max_id_len, active_len, sub_len, job_len, desc_len, n_shown = 0;
323 const struct unit_info *u;
325 max_id_len = sizeof("UNIT")-1;
326 active_len = sizeof("ACTIVE")-1;
327 sub_len = sizeof("SUB")-1;
328 job_len = sizeof("JOB")-1;
331 for (u = unit_infos; u < unit_infos + c; u++) {
332 if (!output_show_unit(u))
335 max_id_len = MAX(max_id_len, strlen(u->id));
336 active_len = MAX(active_len, strlen(u->active_state));
337 sub_len = MAX(sub_len, strlen(u->sub_state));
339 job_len = MAX(job_len, strlen(u->job_type));
344 id_len = MIN(max_id_len, 25);
345 basic_len = 5 + id_len + 6 + active_len + sub_len + job_len;
346 if (basic_len < (unsigned) columns()) {
347 unsigned extra_len, incr;
348 extra_len = columns() - basic_len;
349 /* Either UNIT already got 25, or is fully satisfied.
350 * Grant up to 25 to DESC now. */
351 incr = MIN(extra_len, 25);
354 /* split the remaining space between UNIT and DESC,
355 * but do not give UNIT more than it needs. */
357 incr = MIN(extra_len / 2, max_id_len - id_len);
359 desc_len += extra_len - incr;
365 if (!arg_no_legend) {
366 printf("%-*s %-6s %-*s %-*s %-*s ", id_len, "UNIT", "LOAD",
367 active_len, "ACTIVE", sub_len, "SUB", job_len, "JOB");
368 if (!arg_full && arg_no_pager)
369 printf("%.*s\n", desc_len, "DESCRIPTION");
371 printf("%s\n", "DESCRIPTION");
374 for (u = unit_infos; u < unit_infos + c; u++) {
376 const char *on_loaded, *off_loaded;
377 const char *on_active, *off_active;
379 if (!output_show_unit(u))
384 if (streq(u->load_state, "error")) {
385 on_loaded = ansi_highlight(true);
386 off_loaded = ansi_highlight(false);
388 on_loaded = off_loaded = "";
390 if (streq(u->active_state, "failed")) {
391 on_active = ansi_highlight(true);
392 off_active = ansi_highlight(false);
394 on_active = off_active = "";
396 e = arg_full ? NULL : ellipsize(u->id, id_len, 33);
398 printf("%-*s %s%-6s%s %s%-*s %-*s%s %-*s ",
399 id_len, e ? e : u->id,
400 on_loaded, u->load_state, off_loaded,
401 on_active, active_len, u->active_state,
402 sub_len, u->sub_state, off_active,
403 job_len, u->job_id ? u->job_type : "");
404 if (!arg_full && arg_no_pager)
405 printf("%.*s\n", desc_len, u->description);
407 printf("%s\n", u->description);
412 if (!arg_no_legend) {
413 printf("\nLOAD = Reflects whether the unit definition was properly loaded.\n"
414 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
415 "SUB = The low-level unit activation state, values depend on unit type.\n"
416 "JOB = Pending job for the unit.\n");
419 printf("\n%u units listed.\n", n_shown);
421 printf("\n%u units listed. Pass --all to see inactive units, too.\n", n_shown);
425 static int list_units(DBusConnection *bus, char **args) {
426 DBusMessage *m = NULL, *reply = NULL;
429 DBusMessageIter iter, sub, sub2;
430 unsigned c = 0, n_units = 0;
431 struct unit_info *unit_infos = NULL;
433 dbus_error_init(&error);
437 pager_open_if_enabled();
439 if (!(m = dbus_message_new_method_call(
440 "org.freedesktop.systemd1",
441 "/org/freedesktop/systemd1",
442 "org.freedesktop.systemd1.Manager",
444 log_error("Could not allocate message.");
448 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
449 log_error("Failed to issue method call: %s", bus_error_message(&error));
454 if (!dbus_message_iter_init(reply, &iter) ||
455 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
456 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
457 log_error("Failed to parse reply.");
462 dbus_message_iter_recurse(&iter, &sub);
464 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
467 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
468 log_error("Failed to parse reply.");
476 n_units = MAX(2*c, 16);
477 w = realloc(unit_infos, sizeof(struct unit_info) * n_units);
480 log_error("Failed to allocate unit array.");
490 dbus_message_iter_recurse(&sub, &sub2);
492 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->id, true) < 0 ||
493 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->description, true) < 0 ||
494 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->load_state, true) < 0 ||
495 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->active_state, true) < 0 ||
496 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->sub_state, true) < 0 ||
497 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->following, true) < 0 ||
498 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &u->unit_path, true) < 0 ||
499 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &u->job_id, true) < 0 ||
500 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->job_type, true) < 0 ||
501 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &u->job_path, false) < 0) {
502 log_error("Failed to parse reply.");
507 dbus_message_iter_next(&sub);
512 qsort(unit_infos, c, sizeof(struct unit_info), compare_unit_info);
513 output_units_list(unit_infos, c);
520 dbus_message_unref(m);
523 dbus_message_unref(reply);
527 dbus_error_free(&error);
532 static int compare_unit_file_list(const void *a, const void *b) {
534 const UnitFileList *u = a, *v = b;
536 d1 = strrchr(u->path, '.');
537 d2 = strrchr(v->path, '.');
542 r = strcasecmp(d1, d2);
547 return strcasecmp(file_name_from_path(u->path), file_name_from_path(v->path));
550 static bool output_show_unit_file(const UnitFileList *u) {
553 return !arg_type || ((dot = strrchr(u->path, '.')) && streq(dot+1, arg_type));
556 static void output_unit_file_list(const UnitFileList *units, unsigned c) {
557 unsigned max_id_len, id_cols, state_cols, n_shown = 0;
558 const UnitFileList *u;
560 max_id_len = sizeof("UNIT FILE")-1;
561 state_cols = sizeof("STATE")-1;
562 for (u = units; u < units + c; u++) {
563 if (!output_show_unit_file(u))
566 max_id_len = MAX(max_id_len, strlen(file_name_from_path(u->path)));
567 state_cols = MAX(state_cols, strlen(unit_file_state_to_string(u->state)));
572 id_cols = MIN(max_id_len, 25);
573 basic_cols = 1 + id_cols + state_cols;
574 if (basic_cols < (unsigned) columns())
575 id_cols += MIN(columns() - basic_cols, max_id_len - id_cols);
577 id_cols = max_id_len;
580 printf("%-*s %-*s\n", id_cols, "UNIT FILE", state_cols, "STATE");
582 for (u = units; u < units + c; u++) {
584 const char *on, *off;
587 if (!output_show_unit_file(u))
592 if (u->state == UNIT_FILE_MASKED ||
593 u->state == UNIT_FILE_MASKED_RUNTIME ||
594 u->state == UNIT_FILE_DISABLED) {
595 on = ansi_highlight(true);
596 off = ansi_highlight(false);
597 } else if (u->state == UNIT_FILE_ENABLED) {
598 on = ansi_highlight_green(true);
599 off = ansi_highlight_green(false);
603 id = file_name_from_path(u->path);
605 e = arg_full ? NULL : ellipsize(id, id_cols, 33);
607 printf("%-*s %s%-*s%s\n",
609 on, state_cols, unit_file_state_to_string(u->state), off);
615 printf("\n%u unit files listed.\n", n_shown);
618 static int list_unit_files(DBusConnection *bus, char **args) {
619 DBusMessage *m = NULL, *reply = NULL;
622 DBusMessageIter iter, sub, sub2;
623 unsigned c = 0, n_units = 0;
624 UnitFileList *units = NULL;
626 dbus_error_init(&error);
628 pager_open_if_enabled();
635 h = hashmap_new(string_hash_func, string_compare_func);
637 log_error("Out of memory");
641 r = unit_file_get_list(arg_scope, arg_root, h);
643 unit_file_list_free(h);
644 log_error("Failed to get unit file list: %s", strerror(-r));
648 n_units = hashmap_size(h);
649 units = new(UnitFileList, n_units);
651 unit_file_list_free(h);
652 log_error("Out of memory");
656 HASHMAP_FOREACH(u, h, i) {
657 memcpy(units + c++, u, sizeof(UnitFileList));
665 m = dbus_message_new_method_call(
666 "org.freedesktop.systemd1",
667 "/org/freedesktop/systemd1",
668 "org.freedesktop.systemd1.Manager",
671 log_error("Could not allocate message.");
675 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
677 log_error("Failed to issue method call: %s", bus_error_message(&error));
682 if (!dbus_message_iter_init(reply, &iter) ||
683 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
684 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
685 log_error("Failed to parse reply.");
690 dbus_message_iter_recurse(&iter, &sub);
692 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
696 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
697 log_error("Failed to parse reply.");
705 n_units = MAX(2*c, 16);
706 w = realloc(units, sizeof(struct UnitFileList) * n_units);
709 log_error("Failed to allocate unit array.");
719 dbus_message_iter_recurse(&sub, &sub2);
721 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->path, true) < 0 ||
722 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, false) < 0) {
723 log_error("Failed to parse reply.");
728 u->state = unit_file_state_from_string(state);
730 dbus_message_iter_next(&sub);
736 qsort(units, c, sizeof(UnitFileList), compare_unit_file_list);
737 output_unit_file_list(units, c);
744 dbus_message_unref(m);
747 dbus_message_unref(reply);
751 dbus_error_free(&error);
756 static int dot_one_property(const char *name, const char *prop, DBusMessageIter *iter) {
757 static const char * const colors[] = {
758 "Requires", "[color=\"black\"]",
759 "RequiresOverridable", "[color=\"black\"]",
760 "Requisite", "[color=\"darkblue\"]",
761 "RequisiteOverridable", "[color=\"darkblue\"]",
762 "Wants", "[color=\"darkgrey\"]",
763 "Conflicts", "[color=\"red\"]",
764 "ConflictedBy", "[color=\"red\"]",
765 "After", "[color=\"green\"]"
768 const char *c = NULL;
775 for (i = 0; i < ELEMENTSOF(colors); i += 2)
776 if (streq(colors[i], prop)) {
784 if (arg_dot != DOT_ALL)
785 if ((arg_dot == DOT_ORDER) != streq(prop, "After"))
788 switch (dbus_message_iter_get_arg_type(iter)) {
790 case DBUS_TYPE_ARRAY:
792 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING) {
795 dbus_message_iter_recurse(iter, &sub);
797 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
800 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING);
801 dbus_message_iter_get_basic(&sub, &s);
802 printf("\t\"%s\"->\"%s\" %s;\n", name, s, c);
804 dbus_message_iter_next(&sub);
814 static int dot_one(DBusConnection *bus, const char *name, const char *path) {
815 DBusMessage *m = NULL, *reply = NULL;
816 const char *interface = "org.freedesktop.systemd1.Unit";
819 DBusMessageIter iter, sub, sub2, sub3;
824 dbus_error_init(&error);
826 if (!(m = dbus_message_new_method_call(
827 "org.freedesktop.systemd1",
829 "org.freedesktop.DBus.Properties",
831 log_error("Could not allocate message.");
836 if (!dbus_message_append_args(m,
837 DBUS_TYPE_STRING, &interface,
838 DBUS_TYPE_INVALID)) {
839 log_error("Could not append arguments to message.");
844 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
845 log_error("Failed to issue method call: %s", bus_error_message(&error));
850 if (!dbus_message_iter_init(reply, &iter) ||
851 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
852 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
853 log_error("Failed to parse reply.");
858 dbus_message_iter_recurse(&iter, &sub);
860 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
863 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_DICT_ENTRY) {
864 log_error("Failed to parse reply.");
869 dbus_message_iter_recurse(&sub, &sub2);
871 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &prop, true) < 0) {
872 log_error("Failed to parse reply.");
877 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
878 log_error("Failed to parse reply.");
883 dbus_message_iter_recurse(&sub2, &sub3);
885 if (dot_one_property(name, prop, &sub3)) {
886 log_error("Failed to parse reply.");
891 dbus_message_iter_next(&sub);
898 dbus_message_unref(m);
901 dbus_message_unref(reply);
903 dbus_error_free(&error);
908 static int dot(DBusConnection *bus, char **args) {
909 DBusMessage *m = NULL, *reply = NULL;
912 DBusMessageIter iter, sub, sub2;
914 dbus_error_init(&error);
918 if (!(m = dbus_message_new_method_call(
919 "org.freedesktop.systemd1",
920 "/org/freedesktop/systemd1",
921 "org.freedesktop.systemd1.Manager",
923 log_error("Could not allocate message.");
927 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
928 log_error("Failed to issue method call: %s", bus_error_message(&error));
933 if (!dbus_message_iter_init(reply, &iter) ||
934 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
935 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
936 log_error("Failed to parse reply.");
941 printf("digraph systemd {\n");
943 dbus_message_iter_recurse(&iter, &sub);
944 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
945 const char *id, *description, *load_state, *active_state, *sub_state, *following, *unit_path;
947 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
948 log_error("Failed to parse reply.");
953 dbus_message_iter_recurse(&sub, &sub2);
955 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &id, true) < 0 ||
956 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &description, true) < 0 ||
957 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &load_state, true) < 0 ||
958 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &active_state, true) < 0 ||
959 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &sub_state, true) < 0 ||
960 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &following, true) < 0 ||
961 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, true) < 0) {
962 log_error("Failed to parse reply.");
967 if ((r = dot_one(bus, id, unit_path)) < 0)
970 /* printf("\t\"%s\";\n", id); */
971 dbus_message_iter_next(&sub);
976 log_info(" Color legend: black = Requires\n"
977 " dark blue = Requisite\n"
978 " dark grey = Wants\n"
983 log_notice("-- You probably want to process this output with graphviz' dot tool.\n"
984 "-- Try a shell pipeline like 'systemctl dot | dot -Tsvg > systemd.svg'!\n");
990 dbus_message_unref(m);
993 dbus_message_unref(reply);
995 dbus_error_free(&error);
1000 static int list_jobs(DBusConnection *bus, char **args) {
1001 DBusMessage *m = NULL, *reply = NULL;
1004 DBusMessageIter iter, sub, sub2;
1007 dbus_error_init(&error);
1011 pager_open_if_enabled();
1013 if (!(m = dbus_message_new_method_call(
1014 "org.freedesktop.systemd1",
1015 "/org/freedesktop/systemd1",
1016 "org.freedesktop.systemd1.Manager",
1018 log_error("Could not allocate message.");
1022 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
1023 log_error("Failed to issue method call: %s", bus_error_message(&error));
1028 if (!dbus_message_iter_init(reply, &iter) ||
1029 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
1030 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
1031 log_error("Failed to parse reply.");
1036 dbus_message_iter_recurse(&iter, &sub);
1039 printf("%4s %-25s %-15s %-7s\n", "JOB", "UNIT", "TYPE", "STATE");
1041 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1042 const char *name, *type, *state, *job_path, *unit_path;
1046 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
1047 log_error("Failed to parse reply.");
1052 dbus_message_iter_recurse(&sub, &sub2);
1054 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &id, true) < 0 ||
1055 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
1056 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
1057 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, true) < 0 ||
1058 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &job_path, true) < 0 ||
1059 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, false) < 0) {
1060 log_error("Failed to parse reply.");
1065 e = arg_full ? NULL : ellipsize(name, 25, 33);
1066 printf("%4u %-25s %-15s %-7s\n", id, e ? e : name, type, state);
1071 dbus_message_iter_next(&sub);
1075 printf("\n%u jobs listed.\n", k);
1081 dbus_message_unref(m);
1084 dbus_message_unref(reply);
1086 dbus_error_free(&error);
1091 static int load_unit(DBusConnection *bus, char **args) {
1092 DBusMessage *m = NULL;
1097 dbus_error_init(&error);
1102 STRV_FOREACH(name, args+1) {
1105 if (!(m = dbus_message_new_method_call(
1106 "org.freedesktop.systemd1",
1107 "/org/freedesktop/systemd1",
1108 "org.freedesktop.systemd1.Manager",
1110 log_error("Could not allocate message.");
1115 if (!dbus_message_append_args(m,
1116 DBUS_TYPE_STRING, name,
1117 DBUS_TYPE_INVALID)) {
1118 log_error("Could not append arguments to message.");
1123 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
1124 log_error("Failed to issue method call: %s", bus_error_message(&error));
1129 dbus_message_unref(m);
1130 dbus_message_unref(reply);
1139 dbus_message_unref(m);
1141 dbus_error_free(&error);
1146 static int cancel_job(DBusConnection *bus, char **args) {
1147 DBusMessage *m = NULL, *reply = NULL;
1152 dbus_error_init(&error);
1157 if (strv_length(args) <= 1)
1158 return daemon_reload(bus, args);
1160 STRV_FOREACH(name, args+1) {
1164 if (!(m = dbus_message_new_method_call(
1165 "org.freedesktop.systemd1",
1166 "/org/freedesktop/systemd1",
1167 "org.freedesktop.systemd1.Manager",
1169 log_error("Could not allocate message.");
1174 if ((r = safe_atou(*name, &id)) < 0) {
1175 log_error("Failed to parse job id: %s", strerror(-r));
1179 assert_cc(sizeof(uint32_t) == sizeof(id));
1180 if (!dbus_message_append_args(m,
1181 DBUS_TYPE_UINT32, &id,
1182 DBUS_TYPE_INVALID)) {
1183 log_error("Could not append arguments to message.");
1188 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
1189 log_error("Failed to issue method call: %s", bus_error_message(&error));
1194 if (!dbus_message_get_args(reply, &error,
1195 DBUS_TYPE_OBJECT_PATH, &path,
1196 DBUS_TYPE_INVALID)) {
1197 log_error("Failed to parse reply: %s", bus_error_message(&error));
1202 dbus_message_unref(m);
1203 if (!(m = dbus_message_new_method_call(
1204 "org.freedesktop.systemd1",
1206 "org.freedesktop.systemd1.Job",
1208 log_error("Could not allocate message.");
1213 dbus_message_unref(reply);
1214 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
1215 log_error("Failed to issue method call: %s", bus_error_message(&error));
1220 dbus_message_unref(m);
1221 dbus_message_unref(reply);
1229 dbus_message_unref(m);
1232 dbus_message_unref(reply);
1234 dbus_error_free(&error);
1239 static bool need_daemon_reload(DBusConnection *bus, const char *unit) {
1240 DBusMessage *m = NULL, *reply = NULL;
1241 dbus_bool_t b = FALSE;
1242 DBusMessageIter iter, sub;
1244 *interface = "org.freedesktop.systemd1.Unit",
1245 *property = "NeedDaemonReload",
1248 /* We ignore all errors here, since this is used to show a warning only */
1250 if (!(m = dbus_message_new_method_call(
1251 "org.freedesktop.systemd1",
1252 "/org/freedesktop/systemd1",
1253 "org.freedesktop.systemd1.Manager",
1257 if (!dbus_message_append_args(m,
1258 DBUS_TYPE_STRING, &unit,
1262 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, NULL)))
1265 if (!dbus_message_get_args(reply, NULL,
1266 DBUS_TYPE_OBJECT_PATH, &path,
1270 dbus_message_unref(m);
1271 if (!(m = dbus_message_new_method_call(
1272 "org.freedesktop.systemd1",
1274 "org.freedesktop.DBus.Properties",
1278 if (!dbus_message_append_args(m,
1279 DBUS_TYPE_STRING, &interface,
1280 DBUS_TYPE_STRING, &property,
1281 DBUS_TYPE_INVALID)) {
1285 dbus_message_unref(reply);
1286 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, NULL)))
1289 if (!dbus_message_iter_init(reply, &iter) ||
1290 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
1293 dbus_message_iter_recurse(&iter, &sub);
1295 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_BOOLEAN)
1298 dbus_message_iter_get_basic(&sub, &b);
1302 dbus_message_unref(m);
1305 dbus_message_unref(reply);
1310 typedef struct WaitData {
1315 static DBusHandlerResult wait_filter(DBusConnection *connection, DBusMessage *message, void *data) {
1323 dbus_error_init(&error);
1325 log_debug("Got D-Bus request: %s.%s() on %s",
1326 dbus_message_get_interface(message),
1327 dbus_message_get_member(message),
1328 dbus_message_get_path(message));
1330 if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
1331 log_error("Warning! D-Bus connection terminated.");
1332 dbus_connection_close(connection);
1334 } else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
1336 const char *path, *result;
1337 dbus_bool_t success = true;
1339 if (dbus_message_get_args(message, &error,
1340 DBUS_TYPE_UINT32, &id,
1341 DBUS_TYPE_OBJECT_PATH, &path,
1342 DBUS_TYPE_STRING, &result,
1343 DBUS_TYPE_INVALID)) {
1346 if ((p = set_remove(d->set, (char*) path)))
1350 d->result = strdup(result);
1355 dbus_error_free(&error);
1357 if (dbus_message_get_args(message, &error,
1358 DBUS_TYPE_UINT32, &id,
1359 DBUS_TYPE_OBJECT_PATH, &path,
1360 DBUS_TYPE_BOOLEAN, &success,
1361 DBUS_TYPE_INVALID)) {
1364 /* Compatibility with older systemd versions <
1365 * 19 during upgrades. This should be dropped
1368 if ((p = set_remove(d->set, (char*) path)))
1372 d->result = strdup("failed");
1378 log_error("Failed to parse message: %s", bus_error_message(&error));
1382 dbus_error_free(&error);
1383 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1386 static int enable_wait_for_jobs(DBusConnection *bus) {
1394 dbus_error_init(&error);
1395 dbus_bus_add_match(bus,
1397 "sender='org.freedesktop.systemd1',"
1398 "interface='org.freedesktop.systemd1.Manager',"
1399 "member='JobRemoved',"
1400 "path='/org/freedesktop/systemd1'",
1403 if (dbus_error_is_set(&error)) {
1404 log_error("Failed to add match: %s", bus_error_message(&error));
1405 dbus_error_free(&error);
1409 /* This is slightly dirty, since we don't undo the match registrations. */
1413 static int wait_for_jobs(DBusConnection *bus, Set *s) {
1423 if (!dbus_connection_add_filter(bus, wait_filter, &d, NULL)) {
1424 log_error("Failed to add filter.");
1429 while (!set_isempty(s) &&
1430 dbus_connection_read_write_dispatch(bus, -1))
1433 if (!arg_quiet && d.result) {
1434 if (streq(d.result, "timeout"))
1435 log_error("Job timed out.");
1436 else if (streq(d.result, "canceled"))
1437 log_error("Job canceled.");
1438 else if (streq(d.result, "dependency"))
1439 log_error("A dependency job failed. See system logs for details.");
1440 else if (!streq(d.result, "done") && !streq(d.result, "skipped"))
1441 log_error("Job failed. See system logs and 'systemctl status' for details.");
1444 if (streq_ptr(d.result, "timeout"))
1446 else if (streq_ptr(d.result, "canceled"))
1448 else if (!streq_ptr(d.result, "done") && !streq_ptr(d.result, "skipped"))
1456 /* This is slightly dirty, since we don't undo the filter registration. */
1461 static int start_unit_one(
1462 DBusConnection *bus,
1469 DBusMessage *m = NULL, *reply = NULL;
1478 assert(arg_no_block || s);
1480 if (!(m = dbus_message_new_method_call(
1481 "org.freedesktop.systemd1",
1482 "/org/freedesktop/systemd1",
1483 "org.freedesktop.systemd1.Manager",
1485 log_error("Could not allocate message.");
1490 if (!dbus_message_append_args(m,
1491 DBUS_TYPE_STRING, &name,
1492 DBUS_TYPE_STRING, &mode,
1493 DBUS_TYPE_INVALID)) {
1494 log_error("Could not append arguments to message.");
1499 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, error))) {
1501 if (arg_action != ACTION_SYSTEMCTL && error_is_no_service(error)) {
1502 /* There's always a fallback possible for
1503 * legacy actions. */
1508 log_error("Failed to issue method call: %s", bus_error_message(error));
1513 if (!dbus_message_get_args(reply, error,
1514 DBUS_TYPE_OBJECT_PATH, &path,
1515 DBUS_TYPE_INVALID)) {
1516 log_error("Failed to parse reply: %s", bus_error_message(error));
1521 if (need_daemon_reload(bus, name))
1522 log_warning("Warning: Unit file of created job changed on disk, 'systemctl %s daemon-reload' recommended.",
1523 arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
1525 if (!arg_no_block) {
1528 if (!(p = strdup(path))) {
1529 log_error("Failed to duplicate path.");
1534 if ((r = set_put(s, p)) < 0) {
1536 log_error("Failed to add path to set.");
1545 dbus_message_unref(m);
1548 dbus_message_unref(reply);
1553 static enum action verb_to_action(const char *verb) {
1554 if (streq(verb, "halt"))
1556 else if (streq(verb, "poweroff"))
1557 return ACTION_POWEROFF;
1558 else if (streq(verb, "reboot"))
1559 return ACTION_REBOOT;
1560 else if (streq(verb, "kexec"))
1561 return ACTION_KEXEC;
1562 else if (streq(verb, "rescue"))
1563 return ACTION_RESCUE;
1564 else if (streq(verb, "emergency"))
1565 return ACTION_EMERGENCY;
1566 else if (streq(verb, "default"))
1567 return ACTION_DEFAULT;
1568 else if (streq(verb, "exit"))
1571 return ACTION_INVALID;
1574 static int start_unit(DBusConnection *bus, char **args) {
1576 static const char * const table[_ACTION_MAX] = {
1577 [ACTION_HALT] = SPECIAL_HALT_TARGET,
1578 [ACTION_POWEROFF] = SPECIAL_POWEROFF_TARGET,
1579 [ACTION_REBOOT] = SPECIAL_REBOOT_TARGET,
1580 [ACTION_KEXEC] = SPECIAL_KEXEC_TARGET,
1581 [ACTION_RUNLEVEL2] = SPECIAL_RUNLEVEL2_TARGET,
1582 [ACTION_RUNLEVEL3] = SPECIAL_RUNLEVEL3_TARGET,
1583 [ACTION_RUNLEVEL4] = SPECIAL_RUNLEVEL4_TARGET,
1584 [ACTION_RUNLEVEL5] = SPECIAL_RUNLEVEL5_TARGET,
1585 [ACTION_RESCUE] = SPECIAL_RESCUE_TARGET,
1586 [ACTION_EMERGENCY] = SPECIAL_EMERGENCY_TARGET,
1587 [ACTION_DEFAULT] = SPECIAL_DEFAULT_TARGET,
1588 [ACTION_EXIT] = SPECIAL_EXIT_TARGET
1592 const char *method, *mode, *one_name;
1597 dbus_error_init(&error);
1601 agent_open_if_enabled();
1603 if (arg_action == ACTION_SYSTEMCTL) {
1605 streq(args[0], "stop") ||
1606 streq(args[0], "condstop") ? "StopUnit" :
1607 streq(args[0], "reload") ? "ReloadUnit" :
1608 streq(args[0], "restart") ? "RestartUnit" :
1610 streq(args[0], "try-restart") ||
1611 streq(args[0], "condrestart") ? "TryRestartUnit" :
1613 streq(args[0], "reload-or-restart") ? "ReloadOrRestartUnit" :
1615 streq(args[0], "reload-or-try-restart") ||
1616 streq(args[0], "condreload") ||
1618 streq(args[0], "force-reload") ? "ReloadOrTryRestartUnit" :
1622 (streq(args[0], "isolate") ||
1623 streq(args[0], "rescue") ||
1624 streq(args[0], "emergency")) ? "isolate" : arg_job_mode;
1626 one_name = table[verb_to_action(args[0])];
1629 assert(arg_action < ELEMENTSOF(table));
1630 assert(table[arg_action]);
1632 method = "StartUnit";
1634 mode = (arg_action == ACTION_EMERGENCY ||
1635 arg_action == ACTION_RESCUE ||
1636 arg_action == ACTION_RUNLEVEL2 ||
1637 arg_action == ACTION_RUNLEVEL3 ||
1638 arg_action == ACTION_RUNLEVEL4 ||
1639 arg_action == ACTION_RUNLEVEL5) ? "isolate" : "replace";
1641 one_name = table[arg_action];
1644 if (!arg_no_block) {
1645 if ((ret = enable_wait_for_jobs(bus)) < 0) {
1646 log_error("Could not watch jobs: %s", strerror(-ret));
1650 if (!(s = set_new(string_hash_func, string_compare_func))) {
1651 log_error("Failed to allocate set.");
1658 if ((ret = start_unit_one(bus, method, one_name, mode, &error, s)) <= 0)
1661 STRV_FOREACH(name, args+1)
1662 if ((r = start_unit_one(bus, method, *name, mode, &error, s)) != 0) {
1663 ret = translate_bus_error_to_exit_status(r, &error);
1664 dbus_error_free(&error);
1669 if ((r = wait_for_jobs(bus, s)) < 0) {
1678 dbus_error_free(&error);
1683 static int start_special(DBusConnection *bus, char **args) {
1690 (streq(args[0], "halt") ||
1691 streq(args[0], "poweroff") ||
1692 streq(args[0], "reboot") ||
1693 streq(args[0], "kexec") ||
1694 streq(args[0], "exit")))
1695 return daemon_reload(bus, args);
1697 r = start_unit(bus, args);
1700 warn_wall(verb_to_action(args[0]));
1705 static int check_unit(DBusConnection *bus, char **args) {
1706 DBusMessage *m = NULL, *reply = NULL;
1708 *interface = "org.freedesktop.systemd1.Unit",
1709 *property = "ActiveState";
1710 int r = 3; /* According to LSB: "program is not running" */
1717 dbus_error_init(&error);
1719 STRV_FOREACH(name, args+1) {
1720 const char *path = NULL;
1722 DBusMessageIter iter, sub;
1724 if (!(m = dbus_message_new_method_call(
1725 "org.freedesktop.systemd1",
1726 "/org/freedesktop/systemd1",
1727 "org.freedesktop.systemd1.Manager",
1729 log_error("Could not allocate message.");
1734 if (!dbus_message_append_args(m,
1735 DBUS_TYPE_STRING, name,
1736 DBUS_TYPE_INVALID)) {
1737 log_error("Could not append arguments to message.");
1742 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
1744 /* Hmm, cannot figure out anything about this unit... */
1748 dbus_error_free(&error);
1749 dbus_message_unref(m);
1754 if (!dbus_message_get_args(reply, &error,
1755 DBUS_TYPE_OBJECT_PATH, &path,
1756 DBUS_TYPE_INVALID)) {
1757 log_error("Failed to parse reply: %s", bus_error_message(&error));
1762 dbus_message_unref(m);
1763 if (!(m = dbus_message_new_method_call(
1764 "org.freedesktop.systemd1",
1766 "org.freedesktop.DBus.Properties",
1768 log_error("Could not allocate message.");
1773 if (!dbus_message_append_args(m,
1774 DBUS_TYPE_STRING, &interface,
1775 DBUS_TYPE_STRING, &property,
1776 DBUS_TYPE_INVALID)) {
1777 log_error("Could not append arguments to message.");
1782 dbus_message_unref(reply);
1783 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
1784 log_error("Failed to issue method call: %s", bus_error_message(&error));
1789 if (!dbus_message_iter_init(reply, &iter) ||
1790 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1791 log_error("Failed to parse reply.");
1796 dbus_message_iter_recurse(&iter, &sub);
1798 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1799 log_error("Failed to parse reply.");
1804 dbus_message_iter_get_basic(&sub, &state);
1809 if (streq(state, "active") || streq(state, "reloading"))
1812 dbus_message_unref(m);
1813 dbus_message_unref(reply);
1819 dbus_message_unref(m);
1822 dbus_message_unref(reply);
1824 dbus_error_free(&error);
1829 static int kill_unit(DBusConnection *bus, char **args) {
1830 DBusMessage *m = NULL;
1838 dbus_error_init(&error);
1841 arg_kill_who = "all";
1844 arg_kill_mode = streq(arg_kill_who, "all") ? "control-group" : "process";
1846 STRV_FOREACH(name, args+1) {
1849 if (!(m = dbus_message_new_method_call(
1850 "org.freedesktop.systemd1",
1851 "/org/freedesktop/systemd1",
1852 "org.freedesktop.systemd1.Manager",
1854 log_error("Could not allocate message.");
1859 if (!dbus_message_append_args(m,
1860 DBUS_TYPE_STRING, name,
1861 DBUS_TYPE_STRING, &arg_kill_who,
1862 DBUS_TYPE_STRING, &arg_kill_mode,
1863 DBUS_TYPE_INT32, &arg_signal,
1864 DBUS_TYPE_INVALID)) {
1865 log_error("Could not append arguments to message.");
1870 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
1871 log_error("Failed to issue method call: %s", bus_error_message(&error));
1872 dbus_error_free(&error);
1876 dbus_message_unref(m);
1879 dbus_message_unref(reply);
1885 dbus_message_unref(m);
1887 dbus_error_free(&error);
1892 typedef struct ExecStatusInfo {
1900 usec_t start_timestamp;
1901 usec_t exit_timestamp;
1906 LIST_FIELDS(struct ExecStatusInfo, exec);
1909 static void exec_status_info_free(ExecStatusInfo *i) {
1918 static int exec_status_info_deserialize(DBusMessageIter *sub, ExecStatusInfo *i) {
1919 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
1920 DBusMessageIter sub2, sub3;
1924 int32_t code, status;
1930 if (dbus_message_iter_get_arg_type(sub) != DBUS_TYPE_STRUCT)
1933 dbus_message_iter_recurse(sub, &sub2);
1935 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0)
1938 if (!(i->path = strdup(path)))
1941 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_ARRAY ||
1942 dbus_message_iter_get_element_type(&sub2) != DBUS_TYPE_STRING)
1946 dbus_message_iter_recurse(&sub2, &sub3);
1947 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
1948 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
1949 dbus_message_iter_next(&sub3);
1954 if (!(i->argv = new0(char*, n+1)))
1958 dbus_message_iter_recurse(&sub2, &sub3);
1959 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
1962 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
1963 dbus_message_iter_get_basic(&sub3, &s);
1964 dbus_message_iter_next(&sub3);
1966 if (!(i->argv[n++] = strdup(s)))
1970 if (!dbus_message_iter_next(&sub2) ||
1971 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, true) < 0 ||
1972 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp, true) < 0 ||
1973 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp_monotonic, true) < 0 ||
1974 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp, true) < 0 ||
1975 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp_monotonic, true) < 0 ||
1976 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, true) < 0 ||
1977 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &code, true) < 0 ||
1978 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &status, false) < 0)
1982 i->start_timestamp = (usec_t) start_timestamp;
1983 i->exit_timestamp = (usec_t) exit_timestamp;
1984 i->pid = (pid_t) pid;
1991 typedef struct UnitStatusInfo {
1993 const char *load_state;
1994 const char *active_state;
1995 const char *sub_state;
1996 const char *unit_file_state;
1998 const char *description;
1999 const char *following;
2002 const char *default_control_group;
2004 const char *load_error;
2006 usec_t inactive_exit_timestamp;
2007 usec_t inactive_exit_timestamp_monotonic;
2008 usec_t active_enter_timestamp;
2009 usec_t active_exit_timestamp;
2010 usec_t inactive_enter_timestamp;
2012 bool need_daemon_reload;
2017 const char *status_text;
2019 #ifdef HAVE_SYSV_COMPAT
2023 usec_t start_timestamp;
2024 usec_t exit_timestamp;
2026 int exit_code, exit_status;
2028 usec_t condition_timestamp;
2029 bool condition_result;
2032 unsigned n_accepted;
2033 unsigned n_connections;
2037 const char *sysfs_path;
2039 /* Mount, Automount */
2045 LIST_HEAD(ExecStatusInfo, exec);
2048 static void print_status_info(UnitStatusInfo *i) {
2050 const char *on, *off, *ss;
2052 char since1[FORMAT_TIMESTAMP_PRETTY_MAX], *s1;
2053 char since2[FORMAT_TIMESTAMP_MAX], *s2;
2057 /* This shows pretty information about a unit. See
2058 * print_property() for a low-level property printer */
2060 printf("%s", strna(i->id));
2062 if (i->description && !streq_ptr(i->id, i->description))
2063 printf(" - %s", i->description);
2068 printf("\t Follow: unit currently follows state of %s\n", i->following);
2070 if (streq_ptr(i->load_state, "error")) {
2071 on = ansi_highlight(true);
2072 off = ansi_highlight(false);
2077 printf("\t Loaded: %s%s%s (Reason: %s)\n", on, strna(i->load_state), off, i->load_error);
2078 else if (i->path && i->unit_file_state)
2079 printf("\t Loaded: %s%s%s (%s; %s)\n", on, strna(i->load_state), off, i->path, i->unit_file_state);
2081 printf("\t Loaded: %s%s%s (%s)\n", on, strna(i->load_state), off, i->path);
2083 printf("\t Loaded: %s%s%s\n", on, strna(i->load_state), off);
2085 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
2087 if (streq_ptr(i->active_state, "failed")) {
2088 on = ansi_highlight(true);
2089 off = ansi_highlight(false);
2090 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
2091 on = ansi_highlight_green(true);
2092 off = ansi_highlight_green(false);
2097 printf("\t Active: %s%s (%s)%s",
2099 strna(i->active_state),
2103 printf("\t Active: %s%s%s",
2105 strna(i->active_state),
2108 timestamp = (streq_ptr(i->active_state, "active") ||
2109 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
2110 (streq_ptr(i->active_state, "inactive") ||
2111 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
2112 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
2113 i->active_exit_timestamp;
2115 s1 = format_timestamp_pretty(since1, sizeof(since1), timestamp);
2116 s2 = format_timestamp(since2, sizeof(since2), timestamp);
2119 printf(" since %s; %s\n", s2, s1);
2121 printf(" since %s\n", s2);
2125 if (!i->condition_result && i->condition_timestamp > 0) {
2126 s1 = format_timestamp_pretty(since1, sizeof(since1), i->condition_timestamp);
2127 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
2130 printf("\t start condition failed at %s; %s\n", s2, s1);
2132 printf("\t start condition failed at %s\n", s2);
2136 printf("\t Device: %s\n", i->sysfs_path);
2138 printf("\t Where: %s\n", i->where);
2140 printf("\t What: %s\n", i->what);
2143 printf("\tAccepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
2145 LIST_FOREACH(exec, p, i->exec) {
2149 /* Only show exited processes here */
2153 t = strv_join(p->argv, " ");
2154 printf("\t Process: %u %s=%s ", p->pid, p->name, strna(t));
2157 #ifdef HAVE_SYSV_COMPAT
2159 good = is_clean_exit_lsb(p->code, p->status);
2162 good = is_clean_exit(p->code, p->status);
2165 on = ansi_highlight(true);
2166 off = ansi_highlight(false);
2170 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
2172 if (p->code == CLD_EXITED) {
2175 printf("status=%i", p->status);
2177 #ifdef HAVE_SYSV_COMPAT
2178 if ((c = exit_status_to_string(p->status, i->is_sysv ? EXIT_STATUS_LSB : EXIT_STATUS_SYSTEMD)))
2180 if ((c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD)))
2185 printf("signal=%s", signal_to_string(p->status));
2187 printf(")%s\n", off);
2189 if (i->main_pid == p->pid &&
2190 i->start_timestamp == p->start_timestamp &&
2191 i->exit_timestamp == p->start_timestamp)
2192 /* Let's not show this twice */
2195 if (p->pid == i->control_pid)
2199 if (i->main_pid > 0 || i->control_pid > 0) {
2202 if (i->main_pid > 0) {
2203 printf("Main PID: %u", (unsigned) i->main_pid);
2207 get_process_comm(i->main_pid, &t);
2212 } else if (i->exit_code > 0) {
2213 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
2215 if (i->exit_code == CLD_EXITED) {
2218 printf("status=%i", i->exit_status);
2220 #ifdef HAVE_SYSV_COMPAT
2221 if ((c = exit_status_to_string(i->exit_status, i->is_sysv ? EXIT_STATUS_LSB : EXIT_STATUS_SYSTEMD)))
2223 if ((c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD)))
2228 printf("signal=%s", signal_to_string(i->exit_status));
2233 if (i->main_pid > 0 && i->control_pid > 0)
2236 if (i->control_pid > 0) {
2239 printf(" Control: %u", (unsigned) i->control_pid);
2241 get_process_comm(i->control_pid, &t);
2252 printf("\t Status: \"%s\"\n", i->status_text);
2254 if (i->default_control_group) {
2257 printf("\t CGroup: %s\n", i->default_control_group);
2259 if (arg_transport != TRANSPORT_SSH) {
2260 if ((c = columns()) > 18)
2265 show_cgroup_by_path(i->default_control_group, "\t\t ", c);
2269 if (i->id && arg_transport != TRANSPORT_SSH) {
2271 show_journal_by_unit(i->id, arg_output, NULL, 0, i->inactive_exit_timestamp_monotonic, arg_lines, arg_all, arg_follow);
2274 if (i->need_daemon_reload)
2275 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %s daemon-reload' recommended.\n",
2276 ansi_highlight(true),
2277 ansi_highlight(false),
2278 arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
2281 static int status_property(const char *name, DBusMessageIter *iter, UnitStatusInfo *i) {
2287 switch (dbus_message_iter_get_arg_type(iter)) {
2289 case DBUS_TYPE_STRING: {
2292 dbus_message_iter_get_basic(iter, &s);
2295 if (streq(name, "Id"))
2297 else if (streq(name, "LoadState"))
2299 else if (streq(name, "ActiveState"))
2300 i->active_state = s;
2301 else if (streq(name, "SubState"))
2303 else if (streq(name, "Description"))
2305 else if (streq(name, "FragmentPath"))
2307 #ifdef HAVE_SYSV_COMPAT
2308 else if (streq(name, "SysVPath")) {
2313 else if (streq(name, "DefaultControlGroup"))
2314 i->default_control_group = s;
2315 else if (streq(name, "StatusText"))
2317 else if (streq(name, "SysFSPath"))
2319 else if (streq(name, "Where"))
2321 else if (streq(name, "What"))
2323 else if (streq(name, "Following"))
2325 else if (streq(name, "UnitFileState"))
2326 i->unit_file_state = s;
2332 case DBUS_TYPE_BOOLEAN: {
2335 dbus_message_iter_get_basic(iter, &b);
2337 if (streq(name, "Accept"))
2339 else if (streq(name, "NeedDaemonReload"))
2340 i->need_daemon_reload = b;
2341 else if (streq(name, "ConditionResult"))
2342 i->condition_result = b;
2347 case DBUS_TYPE_UINT32: {
2350 dbus_message_iter_get_basic(iter, &u);
2352 if (streq(name, "MainPID")) {
2354 i->main_pid = (pid_t) u;
2357 } else if (streq(name, "ControlPID"))
2358 i->control_pid = (pid_t) u;
2359 else if (streq(name, "ExecMainPID")) {
2361 i->main_pid = (pid_t) u;
2362 } else if (streq(name, "NAccepted"))
2364 else if (streq(name, "NConnections"))
2365 i->n_connections = u;
2370 case DBUS_TYPE_INT32: {
2373 dbus_message_iter_get_basic(iter, &j);
2375 if (streq(name, "ExecMainCode"))
2376 i->exit_code = (int) j;
2377 else if (streq(name, "ExecMainStatus"))
2378 i->exit_status = (int) j;
2383 case DBUS_TYPE_UINT64: {
2386 dbus_message_iter_get_basic(iter, &u);
2388 if (streq(name, "ExecMainStartTimestamp"))
2389 i->start_timestamp = (usec_t) u;
2390 else if (streq(name, "ExecMainExitTimestamp"))
2391 i->exit_timestamp = (usec_t) u;
2392 else if (streq(name, "ActiveEnterTimestamp"))
2393 i->active_enter_timestamp = (usec_t) u;
2394 else if (streq(name, "InactiveEnterTimestamp"))
2395 i->inactive_enter_timestamp = (usec_t) u;
2396 else if (streq(name, "InactiveExitTimestamp"))
2397 i->inactive_exit_timestamp = (usec_t) u;
2398 else if (streq(name, "InactiveExitTimestampMonotonic"))
2399 i->inactive_exit_timestamp_monotonic = (usec_t) u;
2400 else if (streq(name, "ActiveExitTimestamp"))
2401 i->active_exit_timestamp = (usec_t) u;
2402 else if (streq(name, "ConditionTimestamp"))
2403 i->condition_timestamp = (usec_t) u;
2408 case DBUS_TYPE_ARRAY: {
2410 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
2411 startswith(name, "Exec")) {
2412 DBusMessageIter sub;
2414 dbus_message_iter_recurse(iter, &sub);
2415 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2416 ExecStatusInfo *info;
2419 if (!(info = new0(ExecStatusInfo, 1)))
2422 if (!(info->name = strdup(name))) {
2427 if ((r = exec_status_info_deserialize(&sub, info)) < 0) {
2432 LIST_PREPEND(ExecStatusInfo, exec, i->exec, info);
2434 dbus_message_iter_next(&sub);
2441 case DBUS_TYPE_STRUCT: {
2443 if (streq(name, "LoadError")) {
2444 DBusMessageIter sub;
2445 const char *n, *message;
2448 dbus_message_iter_recurse(iter, &sub);
2450 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &n, true);
2454 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &message, false);
2458 if (!isempty(message))
2459 i->load_error = message;
2469 static int print_property(const char *name, DBusMessageIter *iter) {
2473 /* This is a low-level property printer, see
2474 * print_status_info() for the nicer output */
2476 if (arg_property && !strv_find(arg_property, name))
2479 switch (dbus_message_iter_get_arg_type(iter)) {
2481 case DBUS_TYPE_STRUCT: {
2482 DBusMessageIter sub;
2483 dbus_message_iter_recurse(iter, &sub);
2485 if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32 && streq(name, "Job")) {
2488 dbus_message_iter_get_basic(&sub, &u);
2491 printf("%s=%u\n", name, (unsigned) u);
2493 printf("%s=\n", name);
2496 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "Unit")) {
2499 dbus_message_iter_get_basic(&sub, &s);
2501 if (arg_all || s[0])
2502 printf("%s=%s\n", name, s);
2505 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "LoadError")) {
2506 const char *a = NULL, *b = NULL;
2508 if (bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &a, true) >= 0)
2509 bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &b, false);
2511 if (arg_all || !isempty(a) || !isempty(b))
2512 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
2520 case DBUS_TYPE_ARRAY:
2522 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "EnvironmentFiles")) {
2523 DBusMessageIter sub, sub2;
2525 dbus_message_iter_recurse(iter, &sub);
2526 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2530 dbus_message_iter_recurse(&sub, &sub2);
2532 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
2533 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) >= 0)
2534 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
2536 dbus_message_iter_next(&sub);
2541 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Paths")) {
2542 DBusMessageIter sub, sub2;
2544 dbus_message_iter_recurse(iter, &sub);
2545 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2546 const char *type, *path;
2548 dbus_message_iter_recurse(&sub, &sub2);
2550 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
2551 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
2552 printf("%s=%s\n", type, path);
2554 dbus_message_iter_next(&sub);
2559 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Timers")) {
2560 DBusMessageIter sub, sub2;
2562 dbus_message_iter_recurse(iter, &sub);
2563 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2565 uint64_t value, next_elapse;
2567 dbus_message_iter_recurse(&sub, &sub2);
2569 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &base, true) >= 0 &&
2570 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &value, true) >= 0 &&
2571 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &next_elapse, false) >= 0) {
2572 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
2574 printf("%s={ value=%s ; next_elapse=%s }\n",
2576 format_timespan(timespan1, sizeof(timespan1), value),
2577 format_timespan(timespan2, sizeof(timespan2), next_elapse));
2580 dbus_message_iter_next(&sub);
2585 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "ControlGroupAttributes")) {
2586 DBusMessageIter sub, sub2;
2588 dbus_message_iter_recurse(iter, &sub);
2589 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2590 const char *controller, *attr, *value;
2592 dbus_message_iter_recurse(&sub, &sub2);
2594 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &controller, true) >= 0 &&
2595 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &attr, true) >= 0 &&
2596 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &value, false) >= 0) {
2598 printf("ControlGroupAttribute={ controller=%s ; attribute=%s ; value=\"%s\" }\n",
2604 dbus_message_iter_next(&sub);
2609 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && startswith(name, "Exec")) {
2610 DBusMessageIter sub;
2612 dbus_message_iter_recurse(iter, &sub);
2613 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2614 ExecStatusInfo info;
2617 if (exec_status_info_deserialize(&sub, &info) >= 0) {
2618 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
2621 t = strv_join(info.argv, " ");
2623 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
2627 yes_no(info.ignore),
2628 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
2629 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
2630 (unsigned) info. pid,
2631 sigchld_code_to_string(info.code),
2633 info.code == CLD_EXITED ? "" : "/",
2634 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
2640 strv_free(info.argv);
2642 dbus_message_iter_next(&sub);
2651 if (generic_print_property(name, iter, arg_all) > 0)
2655 printf("%s=[unprintable]\n", name);
2660 static int show_one(const char *verb, DBusConnection *bus, const char *path, bool show_properties, bool *new_line) {
2661 DBusMessage *m = NULL, *reply = NULL;
2662 const char *interface = "";
2665 DBusMessageIter iter, sub, sub2, sub3;
2666 UnitStatusInfo info;
2674 dbus_error_init(&error);
2676 if (!(m = dbus_message_new_method_call(
2677 "org.freedesktop.systemd1",
2679 "org.freedesktop.DBus.Properties",
2681 log_error("Could not allocate message.");
2686 if (!dbus_message_append_args(m,
2687 DBUS_TYPE_STRING, &interface,
2688 DBUS_TYPE_INVALID)) {
2689 log_error("Could not append arguments to message.");
2694 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
2695 log_error("Failed to issue method call: %s", bus_error_message(&error));
2700 if (!dbus_message_iter_init(reply, &iter) ||
2701 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
2702 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
2703 log_error("Failed to parse reply.");
2708 dbus_message_iter_recurse(&iter, &sub);
2715 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
2718 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_DICT_ENTRY) {
2719 log_error("Failed to parse reply.");
2724 dbus_message_iter_recurse(&sub, &sub2);
2726 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0) {
2727 log_error("Failed to parse reply.");
2732 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
2733 log_error("Failed to parse reply.");
2738 dbus_message_iter_recurse(&sub2, &sub3);
2740 if (show_properties)
2741 r = print_property(name, &sub3);
2743 r = status_property(name, &sub3, &info);
2746 log_error("Failed to parse reply.");
2751 dbus_message_iter_next(&sub);
2756 if (!show_properties)
2757 print_status_info(&info);
2759 if (!streq_ptr(info.active_state, "active") &&
2760 !streq_ptr(info.active_state, "reloading") &&
2761 streq(verb, "status"))
2762 /* According to LSB: "program not running" */
2765 while ((p = info.exec)) {
2766 LIST_REMOVE(ExecStatusInfo, exec, info.exec, p);
2767 exec_status_info_free(p);
2772 dbus_message_unref(m);
2775 dbus_message_unref(reply);
2777 dbus_error_free(&error);
2782 static int show(DBusConnection *bus, char **args) {
2783 DBusMessage *m = NULL, *reply = NULL;
2786 bool show_properties, new_line = false;
2792 dbus_error_init(&error);
2794 show_properties = !streq(args[0], "status");
2796 if (show_properties)
2797 pager_open_if_enabled();
2799 if (show_properties && strv_length(args) <= 1) {
2800 /* If not argument is specified inspect the manager
2803 ret = show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line);
2807 STRV_FOREACH(name, args+1) {
2808 const char *path = NULL;
2811 if (safe_atou32(*name, &id) < 0) {
2813 /* Interpret as unit name */
2815 if (!(m = dbus_message_new_method_call(
2816 "org.freedesktop.systemd1",
2817 "/org/freedesktop/systemd1",
2818 "org.freedesktop.systemd1.Manager",
2820 log_error("Could not allocate message.");
2825 if (!dbus_message_append_args(m,
2826 DBUS_TYPE_STRING, name,
2827 DBUS_TYPE_INVALID)) {
2828 log_error("Could not append arguments to message.");
2833 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
2835 if (!dbus_error_has_name(&error, DBUS_ERROR_ACCESS_DENIED)) {
2836 log_error("Failed to issue method call: %s", bus_error_message(&error));
2841 dbus_error_free(&error);
2843 dbus_message_unref(m);
2844 if (!(m = dbus_message_new_method_call(
2845 "org.freedesktop.systemd1",
2846 "/org/freedesktop/systemd1",
2847 "org.freedesktop.systemd1.Manager",
2849 log_error("Could not allocate message.");
2854 if (!dbus_message_append_args(m,
2855 DBUS_TYPE_STRING, name,
2856 DBUS_TYPE_INVALID)) {
2857 log_error("Could not append arguments to message.");
2862 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
2863 log_error("Failed to issue method call: %s", bus_error_message(&error));
2865 if (dbus_error_has_name(&error, BUS_ERROR_NO_SUCH_UNIT))
2866 ret = 4; /* According to LSB: "program or service status is unknown" */
2873 } else if (show_properties) {
2875 /* Interpret as job id */
2877 if (!(m = dbus_message_new_method_call(
2878 "org.freedesktop.systemd1",
2879 "/org/freedesktop/systemd1",
2880 "org.freedesktop.systemd1.Manager",
2882 log_error("Could not allocate message.");
2887 if (!dbus_message_append_args(m,
2888 DBUS_TYPE_UINT32, &id,
2889 DBUS_TYPE_INVALID)) {
2890 log_error("Could not append arguments to message.");
2895 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
2896 log_error("Failed to issue method call: %s", bus_error_message(&error));
2902 /* Interpret as PID */
2904 if (!(m = dbus_message_new_method_call(
2905 "org.freedesktop.systemd1",
2906 "/org/freedesktop/systemd1",
2907 "org.freedesktop.systemd1.Manager",
2909 log_error("Could not allocate message.");
2914 if (!dbus_message_append_args(m,
2915 DBUS_TYPE_UINT32, &id,
2916 DBUS_TYPE_INVALID)) {
2917 log_error("Could not append arguments to message.");
2922 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
2923 log_error("Failed to issue method call: %s", bus_error_message(&error));
2929 if (!dbus_message_get_args(reply, &error,
2930 DBUS_TYPE_OBJECT_PATH, &path,
2931 DBUS_TYPE_INVALID)) {
2932 log_error("Failed to parse reply: %s", bus_error_message(&error));
2937 if ((r = show_one(args[0], bus, path, show_properties, &new_line)) != 0)
2940 dbus_message_unref(m);
2941 dbus_message_unref(reply);
2947 dbus_message_unref(m);
2950 dbus_message_unref(reply);
2952 dbus_error_free(&error);
2957 static int dump(DBusConnection *bus, char **args) {
2958 DBusMessage *m = NULL, *reply = NULL;
2963 dbus_error_init(&error);
2965 pager_open_if_enabled();
2967 if (!(m = dbus_message_new_method_call(
2968 "org.freedesktop.systemd1",
2969 "/org/freedesktop/systemd1",
2970 "org.freedesktop.systemd1.Manager",
2972 log_error("Could not allocate message.");
2976 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
2977 log_error("Failed to issue method call: %s", bus_error_message(&error));
2982 if (!dbus_message_get_args(reply, &error,
2983 DBUS_TYPE_STRING, &text,
2984 DBUS_TYPE_INVALID)) {
2985 log_error("Failed to parse reply: %s", bus_error_message(&error));
2990 fputs(text, stdout);
2996 dbus_message_unref(m);
2999 dbus_message_unref(reply);
3001 dbus_error_free(&error);
3006 static int snapshot(DBusConnection *bus, char **args) {
3007 DBusMessage *m = NULL, *reply = NULL;
3010 const char *name = "", *path, *id;
3011 dbus_bool_t cleanup = FALSE;
3012 DBusMessageIter iter, sub;
3014 *interface = "org.freedesktop.systemd1.Unit",
3017 dbus_error_init(&error);
3019 if (!(m = dbus_message_new_method_call(
3020 "org.freedesktop.systemd1",
3021 "/org/freedesktop/systemd1",
3022 "org.freedesktop.systemd1.Manager",
3023 "CreateSnapshot"))) {
3024 log_error("Could not allocate message.");
3028 if (strv_length(args) > 1)
3031 if (!dbus_message_append_args(m,
3032 DBUS_TYPE_STRING, &name,
3033 DBUS_TYPE_BOOLEAN, &cleanup,
3034 DBUS_TYPE_INVALID)) {
3035 log_error("Could not append arguments to message.");
3040 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3041 log_error("Failed to issue method call: %s", bus_error_message(&error));
3046 if (!dbus_message_get_args(reply, &error,
3047 DBUS_TYPE_OBJECT_PATH, &path,
3048 DBUS_TYPE_INVALID)) {
3049 log_error("Failed to parse reply: %s", bus_error_message(&error));
3054 dbus_message_unref(m);
3055 if (!(m = dbus_message_new_method_call(
3056 "org.freedesktop.systemd1",
3058 "org.freedesktop.DBus.Properties",
3060 log_error("Could not allocate message.");
3064 if (!dbus_message_append_args(m,
3065 DBUS_TYPE_STRING, &interface,
3066 DBUS_TYPE_STRING, &property,
3067 DBUS_TYPE_INVALID)) {
3068 log_error("Could not append arguments to message.");
3073 dbus_message_unref(reply);
3074 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3075 log_error("Failed to issue method call: %s", bus_error_message(&error));
3080 if (!dbus_message_iter_init(reply, &iter) ||
3081 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3082 log_error("Failed to parse reply.");
3087 dbus_message_iter_recurse(&iter, &sub);
3089 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
3090 log_error("Failed to parse reply.");
3095 dbus_message_iter_get_basic(&sub, &id);
3103 dbus_message_unref(m);
3106 dbus_message_unref(reply);
3108 dbus_error_free(&error);
3113 static int delete_snapshot(DBusConnection *bus, char **args) {
3114 DBusMessage *m = NULL, *reply = NULL;
3122 dbus_error_init(&error);
3124 STRV_FOREACH(name, args+1) {
3125 const char *path = NULL;
3127 if (!(m = dbus_message_new_method_call(
3128 "org.freedesktop.systemd1",
3129 "/org/freedesktop/systemd1",
3130 "org.freedesktop.systemd1.Manager",
3132 log_error("Could not allocate message.");
3137 if (!dbus_message_append_args(m,
3138 DBUS_TYPE_STRING, name,
3139 DBUS_TYPE_INVALID)) {
3140 log_error("Could not append arguments to message.");
3145 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3146 log_error("Failed to issue method call: %s", bus_error_message(&error));
3151 if (!dbus_message_get_args(reply, &error,
3152 DBUS_TYPE_OBJECT_PATH, &path,
3153 DBUS_TYPE_INVALID)) {
3154 log_error("Failed to parse reply: %s", bus_error_message(&error));
3159 dbus_message_unref(m);
3160 if (!(m = dbus_message_new_method_call(
3161 "org.freedesktop.systemd1",
3163 "org.freedesktop.systemd1.Snapshot",
3165 log_error("Could not allocate message.");
3170 dbus_message_unref(reply);
3171 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3172 log_error("Failed to issue method call: %s", bus_error_message(&error));
3177 dbus_message_unref(m);
3178 dbus_message_unref(reply);
3186 dbus_message_unref(m);
3189 dbus_message_unref(reply);
3191 dbus_error_free(&error);
3196 static int daemon_reload(DBusConnection *bus, char **args) {
3197 DBusMessage *m = NULL, *reply = NULL;
3202 dbus_error_init(&error);
3204 if (arg_action == ACTION_RELOAD)
3206 else if (arg_action == ACTION_REEXEC)
3207 method = "Reexecute";
3209 assert(arg_action == ACTION_SYSTEMCTL);
3212 streq(args[0], "clear-jobs") ||
3213 streq(args[0], "cancel") ? "ClearJobs" :
3214 streq(args[0], "daemon-reexec") ? "Reexecute" :
3215 streq(args[0], "reset-failed") ? "ResetFailed" :
3216 streq(args[0], "halt") ? "Halt" :
3217 streq(args[0], "poweroff") ? "PowerOff" :
3218 streq(args[0], "reboot") ? "Reboot" :
3219 streq(args[0], "kexec") ? "KExec" :
3220 streq(args[0], "exit") ? "Exit" :
3221 /* "daemon-reload" */ "Reload";
3224 if (!(m = dbus_message_new_method_call(
3225 "org.freedesktop.systemd1",
3226 "/org/freedesktop/systemd1",
3227 "org.freedesktop.systemd1.Manager",
3229 log_error("Could not allocate message.");
3233 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3235 if (arg_action != ACTION_SYSTEMCTL && error_is_no_service(&error)) {
3236 /* There's always a fallback possible for
3237 * legacy actions. */
3242 if (streq(method, "Reexecute") && dbus_error_has_name(&error, DBUS_ERROR_NO_REPLY)) {
3243 /* On reexecution, we expect a disconnect, not
3249 log_error("Failed to issue method call: %s", bus_error_message(&error));
3258 dbus_message_unref(m);
3261 dbus_message_unref(reply);
3263 dbus_error_free(&error);
3268 static int reset_failed(DBusConnection *bus, char **args) {
3269 DBusMessage *m = NULL;
3275 dbus_error_init(&error);
3277 if (strv_length(args) <= 1)
3278 return daemon_reload(bus, args);
3280 STRV_FOREACH(name, args+1) {
3283 if (!(m = dbus_message_new_method_call(
3284 "org.freedesktop.systemd1",
3285 "/org/freedesktop/systemd1",
3286 "org.freedesktop.systemd1.Manager",
3287 "ResetFailedUnit"))) {
3288 log_error("Could not allocate message.");
3293 if (!dbus_message_append_args(m,
3294 DBUS_TYPE_STRING, name,
3295 DBUS_TYPE_INVALID)) {
3296 log_error("Could not append arguments to message.");
3301 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3302 log_error("Failed to issue method call: %s", bus_error_message(&error));
3307 dbus_message_unref(m);
3308 dbus_message_unref(reply);
3316 dbus_message_unref(m);
3318 dbus_error_free(&error);
3323 static int show_enviroment(DBusConnection *bus, char **args) {
3324 DBusMessage *m = NULL, *reply = NULL;
3326 DBusMessageIter iter, sub, sub2;
3329 *interface = "org.freedesktop.systemd1.Manager",
3330 *property = "Environment";
3332 dbus_error_init(&error);
3334 pager_open_if_enabled();
3336 if (!(m = dbus_message_new_method_call(
3337 "org.freedesktop.systemd1",
3338 "/org/freedesktop/systemd1",
3339 "org.freedesktop.DBus.Properties",
3341 log_error("Could not allocate message.");
3345 if (!dbus_message_append_args(m,
3346 DBUS_TYPE_STRING, &interface,
3347 DBUS_TYPE_STRING, &property,
3348 DBUS_TYPE_INVALID)) {
3349 log_error("Could not append arguments to message.");
3354 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3355 log_error("Failed to issue method call: %s", bus_error_message(&error));
3360 if (!dbus_message_iter_init(reply, &iter) ||
3361 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3362 log_error("Failed to parse reply.");
3367 dbus_message_iter_recurse(&iter, &sub);
3369 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_ARRAY ||
3370 dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_STRING) {
3371 log_error("Failed to parse reply.");
3376 dbus_message_iter_recurse(&sub, &sub2);
3378 while (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_INVALID) {
3381 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
3382 log_error("Failed to parse reply.");
3387 dbus_message_iter_get_basic(&sub2, &text);
3388 printf("%s\n", text);
3390 dbus_message_iter_next(&sub2);
3397 dbus_message_unref(m);
3400 dbus_message_unref(reply);
3402 dbus_error_free(&error);
3407 static int set_environment(DBusConnection *bus, char **args) {
3408 DBusMessage *m = NULL, *reply = NULL;
3412 DBusMessageIter iter, sub;
3415 dbus_error_init(&error);
3417 method = streq(args[0], "set-environment")
3419 : "UnsetEnvironment";
3421 if (!(m = dbus_message_new_method_call(
3422 "org.freedesktop.systemd1",
3423 "/org/freedesktop/systemd1",
3424 "org.freedesktop.systemd1.Manager",
3427 log_error("Could not allocate message.");
3431 dbus_message_iter_init_append(m, &iter);
3433 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub)) {
3434 log_error("Could not append arguments to message.");
3439 STRV_FOREACH(name, args+1)
3440 if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, name)) {
3441 log_error("Could not append arguments to message.");
3446 if (!dbus_message_iter_close_container(&iter, &sub)) {
3447 log_error("Could not append arguments to message.");
3452 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3453 log_error("Failed to issue method call: %s", bus_error_message(&error));
3462 dbus_message_unref(m);
3465 dbus_message_unref(reply);
3467 dbus_error_free(&error);
3472 static int enable_sysv_units(char **args) {
3475 #if defined (HAVE_SYSV_COMPAT) && (defined(TARGET_FEDORA) || defined(TARGET_MANDRIVA) || defined(TARGET_SUSE) || defined(TARGET_MEEGO) || defined(TARGET_ALTLINUX) || defined(TARGET_MAGEIA))
3476 const char *verb = args[0];
3477 unsigned f = 1, t = 1;
3480 if (arg_scope != UNIT_FILE_SYSTEM)
3483 if (!streq(verb, "enable") &&
3484 !streq(verb, "disable") &&
3485 !streq(verb, "is-enabled"))
3488 /* Processes all SysV units, and reshuffles the array so that
3489 * afterwards only the native units remain */
3492 r = lookup_paths_init(&paths, MANAGER_SYSTEM, false);
3498 for (f = 1; args[f]; f++) {
3501 bool found_native = false, found_sysv;
3503 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
3504 char **k, *l, *q = NULL;
3511 if (!endswith(name, ".service"))
3514 if (path_is_absolute(name))
3517 STRV_FOREACH(k, paths.unit_path) {
3520 if (!isempty(arg_root))
3521 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
3523 asprintf(&p, "%s/%s", *k, name);
3526 log_error("No memory");
3531 found_native = access(p, F_OK) >= 0;
3542 if (!isempty(arg_root))
3543 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
3545 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
3547 log_error("No memory");
3552 p[strlen(p) - sizeof(".service") + 1] = 0;
3553 found_sysv = access(p, F_OK) >= 0;
3560 /* Mark this entry, so that we don't try enabling it as native unit */
3561 args[f] = (char*) "";
3563 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
3565 if (!isempty(arg_root))
3566 argv[c++] = q = strappend("--root=", arg_root);
3568 argv[c++] = file_name_from_path(p);
3570 streq(verb, "enable") ? "on" :
3571 streq(verb, "disable") ? "off" : "--level=5";
3574 l = strv_join((char**)argv, " ");
3576 log_error("No memory.");
3583 log_info("Executing %s", l);
3588 log_error("Failed to fork: %m");
3593 } else if (pid == 0) {
3596 execv(argv[0], (char**) argv);
3597 _exit(EXIT_FAILURE);
3603 j = wait_for_terminate(pid, &status);
3605 log_error("Failed to wait for child: %s", strerror(-r));
3610 if (status.si_code == CLD_EXITED) {
3611 if (streq(verb, "is-enabled")) {
3612 if (status.si_status == 0) {
3621 } else if (status.si_status != 0) {
3632 lookup_paths_free(&paths);
3634 /* Drop all SysV units */
3635 for (f = 1, t = 1; args[f]; f++) {
3637 if (isempty(args[f]))
3640 args[t++] = args[f];
3649 static int enable_unit(DBusConnection *bus, char **args) {
3650 const char *verb = args[0];
3651 UnitFileChange *changes = NULL;
3652 unsigned n_changes = 0, i;
3653 int carries_install_info = -1;
3654 DBusMessage *m = NULL, *reply = NULL;
3658 dbus_error_init(&error);
3660 r = enable_sysv_units(args);
3664 if (!bus || avoid_bus()) {
3665 if (streq(verb, "enable")) {
3666 r = unit_file_enable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3667 carries_install_info = r;
3668 } else if (streq(verb, "disable"))
3669 r = unit_file_disable(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3670 else if (streq(verb, "reenable")) {
3671 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3672 carries_install_info = r;
3673 } else if (streq(verb, "link"))
3674 r = unit_file_link(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3675 else if (streq(verb, "preset")) {
3676 r = unit_file_preset(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3677 carries_install_info = r;
3678 } else if (streq(verb, "mask"))
3679 r = unit_file_mask(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3680 else if (streq(verb, "unmask"))
3681 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3683 assert_not_reached("Unknown verb");
3686 log_error("Operation failed: %s", strerror(-r));
3690 for (i = 0; i < n_changes; i++) {
3691 if (changes[i].type == UNIT_FILE_SYMLINK)
3692 log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
3694 log_info("rm '%s'", changes[i].path);
3699 bool send_force = true, expect_carries_install_info = false;
3701 DBusMessageIter iter, sub, sub2;
3703 if (streq(verb, "enable")) {
3704 method = "EnableUnitFiles";
3705 expect_carries_install_info = true;
3706 } else if (streq(verb, "disable")) {
3707 method = "DisableUnitFiles";
3709 } else if (streq(verb, "reenable")) {
3710 method = "ReenableUnitFiles";
3711 expect_carries_install_info = true;
3712 } else if (streq(verb, "link"))
3713 method = "LinkUnitFiles";
3714 else if (streq(verb, "preset")) {
3715 method = "PresetUnitFiles";
3716 expect_carries_install_info = true;
3717 } else if (streq(verb, "mask"))
3718 method = "MaskUnitFiles";
3719 else if (streq(verb, "unmask")) {
3720 method = "UnmaskUnitFiles";
3723 assert_not_reached("Unknown verb");
3725 m = dbus_message_new_method_call(
3726 "org.freedesktop.systemd1",
3727 "/org/freedesktop/systemd1",
3728 "org.freedesktop.systemd1.Manager",
3731 log_error("Out of memory");
3736 dbus_message_iter_init_append(m, &iter);
3738 r = bus_append_strv_iter(&iter, args+1);
3740 log_error("Failed to append unit files.");
3745 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &a)) {
3746 log_error("Failed to append runtime boolean.");
3754 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b)) {
3755 log_error("Failed to append force boolean.");
3761 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3763 log_error("Failed to issue method call: %s", bus_error_message(&error));
3768 if (!dbus_message_iter_init(reply, &iter)) {
3769 log_error("Failed to initialize iterator.");
3773 if (expect_carries_install_info) {
3774 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &b, true);
3776 log_error("Failed to parse reply.");
3780 carries_install_info = b;
3783 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3784 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
3785 log_error("Failed to parse reply.");
3790 dbus_message_iter_recurse(&iter, &sub);
3791 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
3792 const char *type, *path, *source;
3794 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
3795 log_error("Failed to parse reply.");
3800 dbus_message_iter_recurse(&sub, &sub2);
3802 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
3803 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
3804 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &source, false) < 0) {
3805 log_error("Failed to parse reply.");
3810 if (streq(type, "symlink"))
3811 log_info("ln -s '%s' '%s'", source, path);
3813 log_info("rm '%s'", path);
3815 dbus_message_iter_next(&sub);
3818 /* Try to reload if enabeld */
3820 r = daemon_reload(bus, args);
3823 if (carries_install_info == 0)
3824 log_warning("Warning: unit files do not carry install information. No operation executed.");
3828 dbus_message_unref(m);
3831 dbus_message_unref(reply);
3833 unit_file_changes_free(changes, n_changes);
3835 dbus_error_free(&error);
3839 static int unit_is_enabled(DBusConnection *bus, char **args) {
3842 DBusMessage *m = NULL, *reply = NULL;
3846 dbus_error_init(&error);
3848 r = enable_sysv_units(args);
3854 if (!bus || avoid_bus()) {
3856 STRV_FOREACH(name, args+1) {
3857 UnitFileState state;
3859 state = unit_file_get_state(arg_scope, arg_root, *name);
3865 if (state == UNIT_FILE_ENABLED ||
3866 state == UNIT_FILE_ENABLED_RUNTIME ||
3867 state == UNIT_FILE_STATIC)
3871 puts(unit_file_state_to_string(state));
3875 STRV_FOREACH(name, args+1) {
3878 m = dbus_message_new_method_call(
3879 "org.freedesktop.systemd1",
3880 "/org/freedesktop/systemd1",
3881 "org.freedesktop.systemd1.Manager",
3882 "GetUnitFileState");
3884 log_error("Out of memory");
3889 if (!dbus_message_append_args(m,
3890 DBUS_TYPE_STRING, name,
3891 DBUS_TYPE_INVALID)) {
3892 log_error("Could not append arguments to message.");
3897 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3899 log_error("Failed to issue method call: %s", bus_error_message(&error));
3904 if (!dbus_message_get_args(reply, &error,
3905 DBUS_TYPE_STRING, &s,
3906 DBUS_TYPE_INVALID)) {
3907 log_error("Failed to parse reply: %s", bus_error_message(&error));
3912 dbus_message_unref(m);
3913 dbus_message_unref(reply);
3916 if (streq(s, "enabled") ||
3917 streq(s, "enabled-runtime") ||
3926 r = enabled ? 0 : 1;
3930 dbus_message_unref(m);
3933 dbus_message_unref(reply);
3935 dbus_error_free(&error);
3939 static int systemctl_help(void) {
3941 pager_open_if_enabled();
3943 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
3944 "Query or send control commands to the systemd manager.\n\n"
3945 " -h --help Show this help\n"
3946 " --version Show package version\n"
3947 " -t --type=TYPE List only units of a particular type\n"
3948 " -p --property=NAME Show only properties by this name\n"
3949 " -a --all Show all units/properties, including dead/empty ones\n"
3950 " --failed Show only failed units\n"
3951 " --full Don't ellipsize unit names on output\n"
3952 " --fail When queueing a new job, fail if conflicting jobs are\n"
3954 " --ignore-dependencies\n"
3955 " When queueing a new job, ignore all its dependencies\n"
3956 " --kill-who=WHO Who to send signal to\n"
3957 " -s --signal=SIGNAL Which signal to send\n"
3958 " -H --host=[USER@]HOST\n"
3959 " Show information for remote host\n"
3960 " -P --privileged Acquire privileges before execution\n"
3961 " -q --quiet Suppress output\n"
3962 " --no-block Do not wait until operation finished\n"
3963 " --no-wall Don't send wall message before halt/power-off/reboot\n"
3964 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
3966 " --no-legend Do not print a legend (column headers and hints)\n"
3967 " --no-pager Do not pipe output into a pager\n"
3968 " --no-ask-password\n"
3969 " Do not ask for system passwords\n"
3970 " --order When generating graph for dot, show only order\n"
3971 " --require When generating graph for dot, show only requirement\n"
3972 " --system Connect to system manager\n"
3973 " --user Connect to user service manager\n"
3974 " --global Enable/disable unit files globally\n"
3975 " -f --force When enabling unit files, override existing symlinks\n"
3976 " When shutting down, execute action immediately\n"
3977 " --root=PATH Enable unit files in the specified root directory\n"
3978 " --runtime Enable unit files only temporarily until next reboot\n"
3979 " -n --lines=INTEGER Journal entries to show\n"
3980 " --follow Follow journal\n"
3981 " -o --output=STRING Change journal output mode (short, verbose, export, json)\n\n"
3983 " list-units List loaded units\n"
3984 " start [NAME...] Start (activate) one or more units\n"
3985 " stop [NAME...] Stop (deactivate) one or more units\n"
3986 " reload [NAME...] Reload one or more units\n"
3987 " restart [NAME...] Start or restart one or more units\n"
3988 " try-restart [NAME...] Restart one or more units if active\n"
3989 " reload-or-restart [NAME...] Reload one or more units is possible,\n"
3990 " otherwise start or restart\n"
3991 " reload-or-try-restart [NAME...] Reload one or more units is possible,\n"
3992 " otherwise restart if active\n"
3993 " isolate [NAME] Start one unit and stop all others\n"
3994 " kill [NAME...] Send signal to processes of a unit\n"
3995 " is-active [NAME...] Check whether units are active\n"
3996 " status [NAME...|PID...] Show runtime status of one or more units\n"
3997 " show [NAME...|JOB...] Show properties of one or more\n"
3998 " units/jobs or the manager\n"
3999 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
4001 " load [NAME...] Load one or more units\n\n"
4002 "Unit File Commands:\n"
4003 " list-unit-files List installed unit files\n"
4004 " enable [NAME...] Enable one or more unit files\n"
4005 " disable [NAME...] Disable one or more unit files\n"
4006 " reenable [NAME...] Reenable one or more unit files\n"
4007 " preset [NAME...] Enable/disable one or more unit files\n"
4008 " based on preset configuration\n"
4009 " mask [NAME...] Mask one or more units\n"
4010 " unmask [NAME...] Unmask one or more units\n"
4011 " link [PATH...] Link one or more units files into\n"
4012 " the search path\n"
4013 " is-enabled [NAME...] Check whether unit files are enabled\n\n"
4015 " list-jobs List jobs\n"
4016 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
4017 "Status Commands:\n"
4018 " dump Dump server status\n"
4019 " dot Dump dependency graph for dot(1)\n\n"
4020 "Snapshot Commands:\n"
4021 " snapshot [NAME] Create a snapshot\n"
4022 " delete [NAME...] Remove one or more snapshots\n\n"
4023 "Environment Commands:\n"
4024 " show-environment Dump environment\n"
4025 " set-environment [NAME=VALUE...] Set one or more environment variables\n"
4026 " unset-environment [NAME...] Unset one or more environment variables\n\n"
4027 "Manager Lifecycle Commands:\n"
4028 " daemon-reload Reload systemd manager configuration\n"
4029 " daemon-reexec Reexecute systemd manager\n\n"
4030 "System Commands:\n"
4031 " default Enter system default mode\n"
4032 " rescue Enter system rescue mode\n"
4033 " emergency Enter system emergency mode\n"
4034 " halt Shut down and halt the system\n"
4035 " poweroff Shut down and power-off the system\n"
4036 " reboot Shut down and reboot the system\n"
4037 " kexec Shut down and reboot the system with kexec\n"
4038 " exit Ask for user instance termination\n",
4039 program_invocation_short_name);
4044 static int halt_help(void) {
4046 printf("%s [OPTIONS...]\n\n"
4047 "%s the system.\n\n"
4048 " --help Show this help\n"
4049 " --halt Halt the machine\n"
4050 " -p --poweroff Switch off the machine\n"
4051 " --reboot Reboot the machine\n"
4052 " -f --force Force immediate halt/power-off/reboot\n"
4053 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
4054 " -d --no-wtmp Don't write wtmp record\n"
4055 " -n --no-sync Don't sync before halt/power-off/reboot\n"
4056 " --no-wall Don't send wall message before halt/power-off/reboot\n",
4057 program_invocation_short_name,
4058 arg_action == ACTION_REBOOT ? "Reboot" :
4059 arg_action == ACTION_POWEROFF ? "Power off" :
4065 static int shutdown_help(void) {
4067 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
4068 "Shut down the system.\n\n"
4069 " --help Show this help\n"
4070 " -H --halt Halt the machine\n"
4071 " -P --poweroff Power-off the machine\n"
4072 " -r --reboot Reboot the machine\n"
4073 " -h Equivalent to --poweroff, overriden by --halt\n"
4074 " -k Don't halt/power-off/reboot, just send warnings\n"
4075 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4076 " -c Cancel a pending shutdown\n",
4077 program_invocation_short_name);
4082 static int telinit_help(void) {
4084 printf("%s [OPTIONS...] {COMMAND}\n\n"
4085 "Send control commands to the init daemon.\n\n"
4086 " --help Show this help\n"
4087 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
4089 " 0 Power-off the machine\n"
4090 " 6 Reboot the machine\n"
4091 " 2, 3, 4, 5 Start runlevelX.target unit\n"
4092 " 1, s, S Enter rescue mode\n"
4093 " q, Q Reload init daemon configuration\n"
4094 " u, U Reexecute init daemon\n",
4095 program_invocation_short_name);
4100 static int runlevel_help(void) {
4102 printf("%s [OPTIONS...]\n\n"
4103 "Prints the previous and current runlevel of the init system.\n\n"
4104 " --help Show this help\n",
4105 program_invocation_short_name);
4110 static int systemctl_parse_argv(int argc, char *argv[]) {
4114 ARG_IGNORE_DEPENDENCIES,
4130 ARG_NO_ASK_PASSWORD,
4136 static const struct option options[] = {
4137 { "help", no_argument, NULL, 'h' },
4138 { "version", no_argument, NULL, ARG_VERSION },
4139 { "type", required_argument, NULL, 't' },
4140 { "property", required_argument, NULL, 'p' },
4141 { "all", no_argument, NULL, 'a' },
4142 { "failed", no_argument, NULL, ARG_FAILED },
4143 { "full", no_argument, NULL, ARG_FULL },
4144 { "fail", no_argument, NULL, ARG_FAIL },
4145 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
4146 { "user", no_argument, NULL, ARG_USER },
4147 { "system", no_argument, NULL, ARG_SYSTEM },
4148 { "global", no_argument, NULL, ARG_GLOBAL },
4149 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
4150 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
4151 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
4152 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4153 { "quiet", no_argument, NULL, 'q' },
4154 { "order", no_argument, NULL, ARG_ORDER },
4155 { "require", no_argument, NULL, ARG_REQUIRE },
4156 { "root", required_argument, NULL, ARG_ROOT },
4157 { "force", no_argument, NULL, 'f' },
4158 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
4159 { "kill-mode", required_argument, NULL, ARG_KILL_MODE }, /* undocumented on purpose */
4160 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
4161 { "signal", required_argument, NULL, 's' },
4162 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
4163 { "host", required_argument, NULL, 'H' },
4164 { "privileged",no_argument, NULL, 'P' },
4165 { "runtime", no_argument, NULL, ARG_RUNTIME },
4166 { "lines", required_argument, NULL, 'n' },
4167 { "follow", no_argument, NULL, ARG_FOLLOW },
4168 { "output", required_argument, NULL, 'o' },
4169 { NULL, 0, NULL, 0 }
4177 /* Only when running as systemctl we ask for passwords */
4178 arg_ask_password = true;
4180 while ((c = getopt_long(argc, argv, "ht:p:aqfs:H:Pn:o:", options, NULL)) >= 0) {
4189 puts(PACKAGE_STRING);
4191 puts(SYSTEMD_FEATURES);
4201 if (!(l = strv_append(arg_property, optarg)))
4204 strv_free(arg_property);
4207 /* If the user asked for a particular
4208 * property, show it to him, even if it is
4219 arg_job_mode = "fail";
4222 case ARG_IGNORE_DEPENDENCIES:
4223 arg_job_mode = "ignore-dependencies";
4227 arg_scope = UNIT_FILE_USER;
4231 arg_scope = UNIT_FILE_SYSTEM;
4235 arg_scope = UNIT_FILE_GLOBAL;
4239 arg_no_block = true;
4243 arg_no_legend = true;
4247 arg_no_pager = true;
4255 arg_dot = DOT_ORDER;
4259 arg_dot = DOT_REQUIRE;
4283 arg_no_reload = true;
4287 arg_kill_who = optarg;
4291 arg_kill_mode = optarg;
4295 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
4296 log_error("Failed to parse signal string %s.", optarg);
4301 case ARG_NO_ASK_PASSWORD:
4302 arg_ask_password = false;
4306 arg_transport = TRANSPORT_POLKIT;
4310 arg_transport = TRANSPORT_SSH;
4319 if (safe_atou(optarg, &arg_lines) < 0) {
4320 log_error("Failed to parse lines '%s'", optarg);
4330 arg_output = output_mode_from_string(optarg);
4331 if (arg_output < 0) {
4332 log_error("Unknown output '%s'.", optarg);
4341 log_error("Unknown option code %c", c);
4346 if (arg_transport != TRANSPORT_NORMAL && arg_scope != UNIT_FILE_SYSTEM) {
4347 log_error("Cannot access user instance remotely.");
4354 static int halt_parse_argv(int argc, char *argv[]) {
4363 static const struct option options[] = {
4364 { "help", no_argument, NULL, ARG_HELP },
4365 { "halt", no_argument, NULL, ARG_HALT },
4366 { "poweroff", no_argument, NULL, 'p' },
4367 { "reboot", no_argument, NULL, ARG_REBOOT },
4368 { "force", no_argument, NULL, 'f' },
4369 { "wtmp-only", no_argument, NULL, 'w' },
4370 { "no-wtmp", no_argument, NULL, 'd' },
4371 { "no-sync", no_argument, NULL, 'n' },
4372 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4373 { NULL, 0, NULL, 0 }
4381 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
4382 if (runlevel == '0' || runlevel == '6')
4383 arg_immediate = true;
4385 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
4393 arg_action = ACTION_HALT;
4397 if (arg_action != ACTION_REBOOT)
4398 arg_action = ACTION_POWEROFF;
4402 arg_action = ACTION_REBOOT;
4406 arg_immediate = true;
4427 /* Compatibility nops */
4434 log_error("Unknown option code %c", c);
4439 if (optind < argc) {
4440 log_error("Too many arguments.");
4447 static int parse_time_spec(const char *t, usec_t *_u) {
4451 if (streq(t, "now"))
4453 else if (!strchr(t, ':')) {
4456 if (safe_atou64(t, &u) < 0)
4459 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
4468 hour = strtol(t, &e, 10);
4469 if (errno != 0 || *e != ':' || hour < 0 || hour > 23)
4472 minute = strtol(e+1, &e, 10);
4473 if (errno != 0 || *e != 0 || minute < 0 || minute > 59)
4476 n = now(CLOCK_REALTIME);
4477 s = (time_t) (n / USEC_PER_SEC);
4480 assert_se(localtime_r(&s, &tm));
4482 tm.tm_hour = (int) hour;
4483 tm.tm_min = (int) minute;
4486 assert_se(s = mktime(&tm));
4488 *_u = (usec_t) s * USEC_PER_SEC;
4491 *_u += USEC_PER_DAY;
4497 static int shutdown_parse_argv(int argc, char *argv[]) {
4504 static const struct option options[] = {
4505 { "help", no_argument, NULL, ARG_HELP },
4506 { "halt", no_argument, NULL, 'H' },
4507 { "poweroff", no_argument, NULL, 'P' },
4508 { "reboot", no_argument, NULL, 'r' },
4509 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4510 { NULL, 0, NULL, 0 }
4518 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
4526 arg_action = ACTION_HALT;
4530 arg_action = ACTION_POWEROFF;
4535 arg_action = ACTION_KEXEC;
4537 arg_action = ACTION_REBOOT;
4541 if (arg_action != ACTION_HALT)
4542 arg_action = ACTION_POWEROFF;
4555 /* Compatibility nops */
4559 arg_action = ACTION_CANCEL_SHUTDOWN;
4566 log_error("Unknown option code %c", c);
4571 if (argc > optind) {
4572 if ((r = parse_time_spec(argv[optind], &arg_when)) < 0) {
4573 log_error("Failed to parse time specification: %s", argv[optind]);
4577 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
4579 /* We skip the time argument */
4580 if (argc > optind + 1)
4581 arg_wall = argv + optind + 1;
4588 static int telinit_parse_argv(int argc, char *argv[]) {
4595 static const struct option options[] = {
4596 { "help", no_argument, NULL, ARG_HELP },
4597 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4598 { NULL, 0, NULL, 0 }
4601 static const struct {
4605 { '0', ACTION_POWEROFF },
4606 { '6', ACTION_REBOOT },
4607 { '1', ACTION_RESCUE },
4608 { '2', ACTION_RUNLEVEL2 },
4609 { '3', ACTION_RUNLEVEL3 },
4610 { '4', ACTION_RUNLEVEL4 },
4611 { '5', ACTION_RUNLEVEL5 },
4612 { 's', ACTION_RESCUE },
4613 { 'S', ACTION_RESCUE },
4614 { 'q', ACTION_RELOAD },
4615 { 'Q', ACTION_RELOAD },
4616 { 'u', ACTION_REEXEC },
4617 { 'U', ACTION_REEXEC }
4626 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4641 log_error("Unknown option code %c", c);
4646 if (optind >= argc) {
4651 if (optind + 1 < argc) {
4652 log_error("Too many arguments.");
4656 if (strlen(argv[optind]) != 1) {
4657 log_error("Expected single character argument.");
4661 for (i = 0; i < ELEMENTSOF(table); i++)
4662 if (table[i].from == argv[optind][0])
4665 if (i >= ELEMENTSOF(table)) {
4666 log_error("Unknown command %s.", argv[optind]);
4670 arg_action = table[i].to;
4677 static int runlevel_parse_argv(int argc, char *argv[]) {
4683 static const struct option options[] = {
4684 { "help", no_argument, NULL, ARG_HELP },
4685 { NULL, 0, NULL, 0 }
4693 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4704 log_error("Unknown option code %c", c);
4709 if (optind < argc) {
4710 log_error("Too many arguments.");
4717 static int parse_argv(int argc, char *argv[]) {
4721 if (program_invocation_short_name) {
4723 if (strstr(program_invocation_short_name, "halt")) {
4724 arg_action = ACTION_HALT;
4725 return halt_parse_argv(argc, argv);
4726 } else if (strstr(program_invocation_short_name, "poweroff")) {
4727 arg_action = ACTION_POWEROFF;
4728 return halt_parse_argv(argc, argv);
4729 } else if (strstr(program_invocation_short_name, "reboot")) {
4731 arg_action = ACTION_KEXEC;
4733 arg_action = ACTION_REBOOT;
4734 return halt_parse_argv(argc, argv);
4735 } else if (strstr(program_invocation_short_name, "shutdown")) {
4736 arg_action = ACTION_POWEROFF;
4737 return shutdown_parse_argv(argc, argv);
4738 } else if (strstr(program_invocation_short_name, "init")) {
4740 if (sd_booted() > 0) {
4741 arg_action = ACTION_INVALID;
4742 return telinit_parse_argv(argc, argv);
4744 /* Hmm, so some other init system is
4745 * running, we need to forward this
4746 * request to it. For now we simply
4747 * guess that it is Upstart. */
4749 execv("/lib/upstart/telinit", argv);
4751 log_error("Couldn't find an alternative telinit implementation to spawn.");
4755 } else if (strstr(program_invocation_short_name, "runlevel")) {
4756 arg_action = ACTION_RUNLEVEL;
4757 return runlevel_parse_argv(argc, argv);
4761 arg_action = ACTION_SYSTEMCTL;
4762 return systemctl_parse_argv(argc, argv);
4765 static int action_to_runlevel(void) {
4767 static const char table[_ACTION_MAX] = {
4768 [ACTION_HALT] = '0',
4769 [ACTION_POWEROFF] = '0',
4770 [ACTION_REBOOT] = '6',
4771 [ACTION_RUNLEVEL2] = '2',
4772 [ACTION_RUNLEVEL3] = '3',
4773 [ACTION_RUNLEVEL4] = '4',
4774 [ACTION_RUNLEVEL5] = '5',
4775 [ACTION_RESCUE] = '1'
4778 assert(arg_action < _ACTION_MAX);
4780 return table[arg_action];
4783 static int talk_upstart(void) {
4784 DBusMessage *m = NULL, *reply = NULL;
4786 int previous, rl, r;
4788 env1_buf[] = "RUNLEVEL=X",
4789 env2_buf[] = "PREVLEVEL=X";
4790 char *env1 = env1_buf, *env2 = env2_buf;
4791 const char *emit = "runlevel";
4792 dbus_bool_t b_false = FALSE;
4793 DBusMessageIter iter, sub;
4794 DBusConnection *bus;
4796 dbus_error_init(&error);
4798 if (!(rl = action_to_runlevel()))
4801 if (utmp_get_runlevel(&previous, NULL) < 0)
4804 if (!(bus = dbus_connection_open_private("unix:abstract=/com/ubuntu/upstart", &error))) {
4805 if (dbus_error_has_name(&error, DBUS_ERROR_NO_SERVER)) {
4810 log_error("Failed to connect to Upstart bus: %s", bus_error_message(&error));
4815 if ((r = bus_check_peercred(bus)) < 0) {
4816 log_error("Failed to verify owner of bus.");
4820 if (!(m = dbus_message_new_method_call(
4821 "com.ubuntu.Upstart",
4822 "/com/ubuntu/Upstart",
4823 "com.ubuntu.Upstart0_6",
4826 log_error("Could not allocate message.");
4831 dbus_message_iter_init_append(m, &iter);
4833 env1_buf[sizeof(env1_buf)-2] = rl;
4834 env2_buf[sizeof(env2_buf)-2] = previous;
4836 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &emit) ||
4837 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub) ||
4838 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env1) ||
4839 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env2) ||
4840 !dbus_message_iter_close_container(&iter, &sub) ||
4841 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b_false)) {
4842 log_error("Could not append arguments to message.");
4847 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
4849 if (error_is_no_service(&error)) {
4854 log_error("Failed to issue method call: %s", bus_error_message(&error));
4863 dbus_message_unref(m);
4866 dbus_message_unref(reply);
4869 dbus_connection_flush(bus);
4870 dbus_connection_close(bus);
4871 dbus_connection_unref(bus);
4874 dbus_error_free(&error);
4879 static int talk_initctl(void) {
4880 struct init_request request;
4884 if (!(rl = action_to_runlevel()))
4888 request.magic = INIT_MAGIC;
4889 request.sleeptime = 0;
4890 request.cmd = INIT_CMD_RUNLVL;
4891 request.runlevel = rl;
4893 if ((fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY)) < 0) {
4895 if (errno == ENOENT)
4898 log_error("Failed to open "INIT_FIFO": %m");
4903 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
4904 close_nointr_nofail(fd);
4907 log_error("Failed to write to "INIT_FIFO": %m");
4908 return errno ? -errno : -EIO;
4914 static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
4916 static const struct {
4924 int (* const dispatch)(DBusConnection *bus, char **args);
4926 { "list-units", LESS, 1, list_units },
4927 { "list-unit-files", EQUAL, 1, list_unit_files },
4928 { "list-jobs", EQUAL, 1, list_jobs },
4929 { "clear-jobs", EQUAL, 1, daemon_reload },
4930 { "load", MORE, 2, load_unit },
4931 { "cancel", MORE, 2, cancel_job },
4932 { "start", MORE, 2, start_unit },
4933 { "stop", MORE, 2, start_unit },
4934 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
4935 { "reload", MORE, 2, start_unit },
4936 { "restart", MORE, 2, start_unit },
4937 { "try-restart", MORE, 2, start_unit },
4938 { "reload-or-restart", MORE, 2, start_unit },
4939 { "reload-or-try-restart", MORE, 2, start_unit },
4940 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
4941 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
4942 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
4943 { "isolate", EQUAL, 2, start_unit },
4944 { "kill", MORE, 2, kill_unit },
4945 { "is-active", MORE, 2, check_unit },
4946 { "check", MORE, 2, check_unit },
4947 { "show", MORE, 1, show },
4948 { "status", MORE, 2, show },
4949 { "dump", EQUAL, 1, dump },
4950 { "dot", EQUAL, 1, dot },
4951 { "snapshot", LESS, 2, snapshot },
4952 { "delete", MORE, 2, delete_snapshot },
4953 { "daemon-reload", EQUAL, 1, daemon_reload },
4954 { "daemon-reexec", EQUAL, 1, daemon_reload },
4955 { "show-environment", EQUAL, 1, show_enviroment },
4956 { "set-environment", MORE, 2, set_environment },
4957 { "unset-environment", MORE, 2, set_environment },
4958 { "halt", EQUAL, 1, start_special },
4959 { "poweroff", EQUAL, 1, start_special },
4960 { "reboot", EQUAL, 1, start_special },
4961 { "kexec", EQUAL, 1, start_special },
4962 { "default", EQUAL, 1, start_special },
4963 { "rescue", EQUAL, 1, start_special },
4964 { "emergency", EQUAL, 1, start_special },
4965 { "exit", EQUAL, 1, start_special },
4966 { "reset-failed", MORE, 1, reset_failed },
4967 { "enable", MORE, 2, enable_unit },
4968 { "disable", MORE, 2, enable_unit },
4969 { "is-enabled", MORE, 2, unit_is_enabled },
4970 { "reenable", MORE, 2, enable_unit },
4971 { "preset", MORE, 2, enable_unit },
4972 { "mask", MORE, 2, enable_unit },
4973 { "unmask", MORE, 2, enable_unit },
4974 { "link", MORE, 2, enable_unit }
4984 left = argc - optind;
4987 /* Special rule: no arguments means "list-units" */
4990 if (streq(argv[optind], "help")) {
4995 for (i = 0; i < ELEMENTSOF(verbs); i++)
4996 if (streq(argv[optind], verbs[i].verb))
4999 if (i >= ELEMENTSOF(verbs)) {
5000 log_error("Unknown operation %s", argv[optind]);
5005 switch (verbs[i].argc_cmp) {
5008 if (left != verbs[i].argc) {
5009 log_error("Invalid number of arguments.");
5016 if (left < verbs[i].argc) {
5017 log_error("Too few arguments.");
5024 if (left > verbs[i].argc) {
5025 log_error("Too many arguments.");
5032 assert_not_reached("Unknown comparison operator.");
5035 /* Require a bus connection for all operations but
5037 if (!streq(verbs[i].verb, "enable") &&
5038 !streq(verbs[i].verb, "disable") &&
5039 !streq(verbs[i].verb, "is-enabled") &&
5040 !streq(verbs[i].verb, "list-unit-files") &&
5041 !streq(verbs[i].verb, "reenable") &&
5042 !streq(verbs[i].verb, "preset") &&
5043 !streq(verbs[i].verb, "mask") &&
5044 !streq(verbs[i].verb, "unmask") &&
5045 !streq(verbs[i].verb, "link")) {
5047 if (running_in_chroot() > 0) {
5048 log_info("Running in chroot, ignoring request.");
5053 log_error("Failed to get D-Bus connection: %s",
5054 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5060 if (!bus && !avoid_bus()) {
5061 log_error("Failed to get D-Bus connection: %s",
5062 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5067 return verbs[i].dispatch(bus, argv + optind);
5070 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
5072 struct msghdr msghdr;
5074 union sockaddr_union sockaddr;
5075 struct shutdownd_command c;
5080 c.dry_run = dry_run;
5084 strncpy(c.wall_message, message, sizeof(c.wall_message));
5086 if ((fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0)) < 0)
5090 sockaddr.sa.sa_family = AF_UNIX;
5091 sockaddr.un.sun_path[0] = 0;
5092 strncpy(sockaddr.un.sun_path, "/run/systemd/shutdownd", sizeof(sockaddr.un.sun_path));
5095 iovec.iov_base = (char*) &c;
5096 iovec.iov_len = sizeof(c);
5099 msghdr.msg_name = &sockaddr;
5100 msghdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + sizeof("/run/systemd/shutdownd") - 1;
5102 msghdr.msg_iov = &iovec;
5103 msghdr.msg_iovlen = 1;
5105 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0) {
5106 close_nointr_nofail(fd);
5110 close_nointr_nofail(fd);
5114 static int reload_with_fallback(DBusConnection *bus) {
5117 /* First, try systemd via D-Bus. */
5118 if (daemon_reload(bus, NULL) >= 0)
5122 /* Nothing else worked, so let's try signals */
5123 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
5125 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
5126 log_error("kill() failed: %m");
5133 static int start_with_fallback(DBusConnection *bus) {
5136 /* First, try systemd via D-Bus. */
5137 if (start_unit(bus, NULL) >= 0)
5141 /* Hmm, talking to systemd via D-Bus didn't work. Then
5142 * let's try to talk to Upstart via D-Bus. */
5143 if (talk_upstart() > 0)
5146 /* Nothing else worked, so let's try
5148 if (talk_initctl() > 0)
5151 log_error("Failed to talk to init daemon.");
5155 warn_wall(arg_action);
5159 static int halt_main(DBusConnection *bus) {
5162 if (geteuid() != 0) {
5163 log_error("Must be root.");
5169 char date[FORMAT_TIMESTAMP_MAX];
5171 m = strv_join(arg_wall, " ");
5172 r = send_shutdownd(arg_when,
5173 arg_action == ACTION_HALT ? 'H' :
5174 arg_action == ACTION_POWEROFF ? 'P' :
5182 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
5184 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
5185 format_timestamp(date, sizeof(date), arg_when));
5190 if (!arg_dry && !arg_immediate)
5191 return start_with_fallback(bus);
5194 if (sd_booted() > 0)
5195 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
5196 else if ((r = utmp_put_shutdown()) < 0)
5197 log_warning("Failed to write utmp record: %s", strerror(-r));
5206 /* Make sure C-A-D is handled by the kernel from this
5208 reboot(RB_ENABLE_CAD);
5210 switch (arg_action) {
5213 log_info("Halting.");
5214 reboot(RB_HALT_SYSTEM);
5217 case ACTION_POWEROFF:
5218 log_info("Powering off.");
5219 reboot(RB_POWER_OFF);
5223 log_info("Rebooting.");
5224 reboot(RB_AUTOBOOT);
5228 assert_not_reached("Unknown halt action.");
5231 /* We should never reach this. */
5235 static int runlevel_main(void) {
5236 int r, runlevel, previous;
5238 r = utmp_get_runlevel(&runlevel, &previous);
5245 previous <= 0 ? 'N' : previous,
5246 runlevel <= 0 ? 'N' : runlevel);
5251 int main(int argc, char*argv[]) {
5252 int r, retval = EXIT_FAILURE;
5253 DBusConnection *bus = NULL;
5256 dbus_error_init(&error);
5258 log_parse_environment();
5261 if ((r = parse_argv(argc, argv)) < 0)
5264 retval = EXIT_SUCCESS;
5268 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
5269 * let's shortcut this */
5270 if (arg_action == ACTION_RUNLEVEL) {
5271 r = runlevel_main();
5272 retval = r < 0 ? EXIT_FAILURE : r;
5276 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
5277 log_info("Running in chroot, ignoring request.");
5283 if (arg_transport == TRANSPORT_NORMAL)
5284 bus_connect(arg_scope == UNIT_FILE_SYSTEM ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &bus, &private_bus, &error);
5285 else if (arg_transport == TRANSPORT_POLKIT) {
5286 bus_connect_system_polkit(&bus, &error);
5287 private_bus = false;
5288 } else if (arg_transport == TRANSPORT_SSH) {
5289 bus_connect_system_ssh(NULL, arg_host, &bus, &error);
5290 private_bus = false;
5292 assert_not_reached("Uh, invalid transport...");
5295 switch (arg_action) {
5297 case ACTION_SYSTEMCTL:
5298 r = systemctl_main(bus, argc, argv, &error);
5302 case ACTION_POWEROFF:
5308 case ACTION_RUNLEVEL2:
5309 case ACTION_RUNLEVEL3:
5310 case ACTION_RUNLEVEL4:
5311 case ACTION_RUNLEVEL5:
5313 case ACTION_EMERGENCY:
5314 case ACTION_DEFAULT:
5315 r = start_with_fallback(bus);
5320 r = reload_with_fallback(bus);
5323 case ACTION_CANCEL_SHUTDOWN:
5324 r = send_shutdownd(0, 0, false, false, NULL);
5327 case ACTION_INVALID:
5328 case ACTION_RUNLEVEL:
5330 assert_not_reached("Unknown action");
5333 retval = r < 0 ? EXIT_FAILURE : r;
5337 dbus_connection_flush(bus);
5338 dbus_connection_close(bus);
5339 dbus_connection_unref(bus);
5342 dbus_error_free(&error);
5346 strv_free(arg_property);