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>
38 #include <systemd/sd-daemon.h>
44 #include "utmp-wtmp.h"
48 #include "dbus-common.h"
49 #include "cgroup-show.h"
50 #include "cgroup-util.h"
52 #include "path-lookup.h"
53 #include "conf-parser.h"
54 #include "shutdownd.h"
55 #include "exit-status.h"
56 #include "bus-errors.h"
58 #include "unit-name.h"
60 #include "spawn-agent.h"
62 #include "logs-show.h"
64 static const char *arg_type = NULL;
65 static char **arg_property = NULL;
66 static bool arg_all = false;
67 static const char *arg_job_mode = "replace";
68 static UnitFileScope arg_scope = UNIT_FILE_SYSTEM;
69 static bool arg_immediate = false;
70 static bool arg_no_block = false;
71 static bool arg_no_legend = false;
72 static bool arg_no_pager = false;
73 static bool arg_no_wtmp = false;
74 static bool arg_no_sync = false;
75 static bool arg_no_wall = false;
76 static bool arg_no_reload = false;
77 static bool arg_dry = false;
78 static bool arg_quiet = false;
79 static bool arg_full = false;
80 static int arg_force = 0;
81 static bool arg_ask_password = false;
82 static bool arg_failed = false;
83 static bool arg_runtime = false;
84 static char **arg_wall = NULL;
85 static const char *arg_kill_who = NULL;
86 static const char *arg_kill_mode = NULL;
87 static int arg_signal = SIGTERM;
88 static const char *arg_root = NULL;
89 static usec_t arg_when = 0;
108 ACTION_CANCEL_SHUTDOWN,
110 } arg_action = ACTION_SYSTEMCTL;
116 static enum transport {
120 } arg_transport = TRANSPORT_NORMAL;
121 static const char *arg_host = NULL;
122 static bool arg_follow = false;
123 static unsigned arg_lines = 10;
124 static OutputMode arg_output = OUTPUT_SHORT;
126 static bool private_bus = false;
128 static int daemon_reload(DBusConnection *bus, char **args);
129 static void halt_now(int action);
131 static bool on_tty(void) {
134 /* Note that this is invoked relatively early, before we start
135 * the pager. That means the value we return reflects whether
136 * we originally were started on a tty, not if we currently
137 * are. But this is intended, since we want colour and so on
138 * when run in our own pager. */
140 if (_unlikely_(t < 0))
141 t = isatty(STDOUT_FILENO) > 0;
146 static void pager_open_if_enabled(void) {
148 /* Cache result before we open the pager */
157 static void agent_open_if_enabled(void) {
159 /* Open the password agent as a child process if necessary */
161 if (!arg_ask_password)
164 if (arg_scope != UNIT_FILE_SYSTEM)
170 static const char *ansi_highlight_red(bool b) {
175 return b ? ANSI_HIGHLIGHT_RED_ON : ANSI_HIGHLIGHT_OFF;
178 static const char *ansi_highlight_green(bool b) {
183 return b ? ANSI_HIGHLIGHT_GREEN_ON : ANSI_HIGHLIGHT_OFF;
186 static bool error_is_no_service(const DBusError *error) {
189 if (!dbus_error_is_set(error))
192 if (dbus_error_has_name(error, DBUS_ERROR_NAME_HAS_NO_OWNER))
195 if (dbus_error_has_name(error, DBUS_ERROR_SERVICE_UNKNOWN))
198 return startswith(error->name, "org.freedesktop.DBus.Error.Spawn.");
201 static int translate_bus_error_to_exit_status(int r, const DBusError *error) {
204 if (!dbus_error_is_set(error))
207 if (dbus_error_has_name(error, DBUS_ERROR_ACCESS_DENIED) ||
208 dbus_error_has_name(error, BUS_ERROR_ONLY_BY_DEPENDENCY) ||
209 dbus_error_has_name(error, BUS_ERROR_NO_ISOLATION) ||
210 dbus_error_has_name(error, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE))
211 return EXIT_NOPERMISSION;
213 if (dbus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT))
214 return EXIT_NOTINSTALLED;
216 if (dbus_error_has_name(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE) ||
217 dbus_error_has_name(error, BUS_ERROR_NOT_SUPPORTED))
218 return EXIT_NOTIMPLEMENTED;
220 if (dbus_error_has_name(error, BUS_ERROR_LOAD_FAILED))
221 return EXIT_NOTCONFIGURED;
229 static void warn_wall(enum action action) {
230 static const char *table[_ACTION_MAX] = {
231 [ACTION_HALT] = "The system is going down for system halt NOW!",
232 [ACTION_REBOOT] = "The system is going down for reboot NOW!",
233 [ACTION_POWEROFF] = "The system is going down for power-off NOW!",
234 [ACTION_KEXEC] = "The system is going down for kexec reboot NOW!",
235 [ACTION_RESCUE] = "The system is going down to rescue mode NOW!",
236 [ACTION_EMERGENCY] = "The system is going down to emergency mode NOW!"
245 if (!(p = strv_join(arg_wall, " "))) {
246 log_error("Failed to join strings.");
262 utmp_wall(table[action], NULL);
265 static bool avoid_bus(void) {
267 if (running_in_chroot() > 0)
270 if (sd_booted() <= 0)
273 if (!isempty(arg_root))
276 if (arg_scope == UNIT_FILE_GLOBAL)
284 const char *description;
285 const char *load_state;
286 const char *active_state;
287 const char *sub_state;
288 const char *following;
289 const char *unit_path;
291 const char *job_type;
292 const char *job_path;
295 static int compare_unit_info(const void *a, const void *b) {
297 const struct unit_info *u = a, *v = b;
299 d1 = strrchr(u->id, '.');
300 d2 = strrchr(v->id, '.');
305 if ((r = strcasecmp(d1, d2)) != 0)
309 return strcasecmp(u->id, v->id);
312 static bool output_show_unit(const struct unit_info *u) {
316 return streq(u->active_state, "failed");
318 return (!arg_type || ((dot = strrchr(u->id, '.')) &&
319 streq(dot+1, arg_type))) &&
320 (arg_all || !(streq(u->active_state, "inactive") || u->following[0]) || u->job_id > 0);
323 static void output_units_list(const struct unit_info *unit_infos, unsigned c) {
324 unsigned id_len, max_id_len, active_len, sub_len, job_len, desc_len, n_shown = 0;
325 const struct unit_info *u;
327 max_id_len = sizeof("UNIT")-1;
328 active_len = sizeof("ACTIVE")-1;
329 sub_len = sizeof("SUB")-1;
330 job_len = sizeof("JOB")-1;
333 for (u = unit_infos; u < unit_infos + c; u++) {
334 if (!output_show_unit(u))
337 max_id_len = MAX(max_id_len, strlen(u->id));
338 active_len = MAX(active_len, strlen(u->active_state));
339 sub_len = MAX(sub_len, strlen(u->sub_state));
341 job_len = MAX(job_len, strlen(u->job_type));
346 id_len = MIN(max_id_len, 25);
347 basic_len = 5 + id_len + 6 + active_len + sub_len + job_len;
348 if (basic_len < (unsigned) columns()) {
349 unsigned extra_len, incr;
350 extra_len = columns() - basic_len;
351 /* Either UNIT already got 25, or is fully satisfied.
352 * Grant up to 25 to DESC now. */
353 incr = MIN(extra_len, 25);
356 /* split the remaining space between UNIT and DESC,
357 * but do not give UNIT more than it needs. */
359 incr = MIN(extra_len / 2, max_id_len - id_len);
361 desc_len += extra_len - incr;
367 if (!arg_no_legend) {
368 printf("%-*s %-6s %-*s %-*s %-*s ", id_len, "UNIT", "LOAD",
369 active_len, "ACTIVE", sub_len, "SUB", job_len, "JOB");
370 if (!arg_full && arg_no_pager)
371 printf("%.*s\n", desc_len, "DESCRIPTION");
373 printf("%s\n", "DESCRIPTION");
376 for (u = unit_infos; u < unit_infos + c; u++) {
378 const char *on_loaded, *off_loaded;
379 const char *on_active, *off_active;
381 if (!output_show_unit(u))
386 if (streq(u->load_state, "error")) {
387 on_loaded = ansi_highlight_red(true);
388 off_loaded = ansi_highlight_red(false);
390 on_loaded = off_loaded = "";
392 if (streq(u->active_state, "failed")) {
393 on_active = ansi_highlight_red(true);
394 off_active = ansi_highlight_red(false);
396 on_active = off_active = "";
398 e = arg_full ? NULL : ellipsize(u->id, id_len, 33);
400 printf("%-*s %s%-6s%s %s%-*s %-*s%s %-*s ",
401 id_len, e ? e : u->id,
402 on_loaded, u->load_state, off_loaded,
403 on_active, active_len, u->active_state,
404 sub_len, u->sub_state, off_active,
405 job_len, u->job_id ? u->job_type : "");
406 if (!arg_full && arg_no_pager)
407 printf("%.*s\n", desc_len, u->description);
409 printf("%s\n", u->description);
414 if (!arg_no_legend) {
415 printf("\nLOAD = Reflects whether the unit definition was properly loaded.\n"
416 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
417 "SUB = The low-level unit activation state, values depend on unit type.\n"
418 "JOB = Pending job for the unit.\n");
421 printf("\n%u units listed.\n", n_shown);
423 printf("\n%u units listed. Pass --all to see inactive units, too.\n", n_shown);
427 static int list_units(DBusConnection *bus, char **args) {
428 DBusMessage *m = NULL, *reply = NULL;
431 DBusMessageIter iter, sub, sub2;
432 unsigned c = 0, n_units = 0;
433 struct unit_info *unit_infos = NULL;
435 dbus_error_init(&error);
439 pager_open_if_enabled();
441 if (!(m = dbus_message_new_method_call(
442 "org.freedesktop.systemd1",
443 "/org/freedesktop/systemd1",
444 "org.freedesktop.systemd1.Manager",
446 log_error("Could not allocate message.");
450 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
451 log_error("Failed to issue method call: %s", bus_error_message(&error));
456 if (!dbus_message_iter_init(reply, &iter) ||
457 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
458 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
459 log_error("Failed to parse reply.");
464 dbus_message_iter_recurse(&iter, &sub);
466 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
469 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
470 log_error("Failed to parse reply.");
478 n_units = MAX(2*c, 16);
479 w = realloc(unit_infos, sizeof(struct unit_info) * n_units);
482 log_error("Failed to allocate unit array.");
492 dbus_message_iter_recurse(&sub, &sub2);
494 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->id, true) < 0 ||
495 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->description, true) < 0 ||
496 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->load_state, true) < 0 ||
497 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->active_state, true) < 0 ||
498 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->sub_state, true) < 0 ||
499 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->following, true) < 0 ||
500 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &u->unit_path, true) < 0 ||
501 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &u->job_id, true) < 0 ||
502 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->job_type, true) < 0 ||
503 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &u->job_path, false) < 0) {
504 log_error("Failed to parse reply.");
509 dbus_message_iter_next(&sub);
514 qsort(unit_infos, c, sizeof(struct unit_info), compare_unit_info);
515 output_units_list(unit_infos, c);
522 dbus_message_unref(m);
525 dbus_message_unref(reply);
529 dbus_error_free(&error);
534 static int compare_unit_file_list(const void *a, const void *b) {
536 const UnitFileList *u = a, *v = b;
538 d1 = strrchr(u->path, '.');
539 d2 = strrchr(v->path, '.');
544 r = strcasecmp(d1, d2);
549 return strcasecmp(file_name_from_path(u->path), file_name_from_path(v->path));
552 static bool output_show_unit_file(const UnitFileList *u) {
555 return !arg_type || ((dot = strrchr(u->path, '.')) && streq(dot+1, arg_type));
558 static void output_unit_file_list(const UnitFileList *units, unsigned c) {
559 unsigned max_id_len, id_cols, state_cols, n_shown = 0;
560 const UnitFileList *u;
562 max_id_len = sizeof("UNIT FILE")-1;
563 state_cols = sizeof("STATE")-1;
564 for (u = units; u < units + c; u++) {
565 if (!output_show_unit_file(u))
568 max_id_len = MAX(max_id_len, strlen(file_name_from_path(u->path)));
569 state_cols = MAX(state_cols, strlen(unit_file_state_to_string(u->state)));
574 id_cols = MIN(max_id_len, 25);
575 basic_cols = 1 + id_cols + state_cols;
576 if (basic_cols < (unsigned) columns())
577 id_cols += MIN(columns() - basic_cols, max_id_len - id_cols);
579 id_cols = max_id_len;
582 printf("%-*s %-*s\n", id_cols, "UNIT FILE", state_cols, "STATE");
584 for (u = units; u < units + c; u++) {
586 const char *on, *off;
589 if (!output_show_unit_file(u))
594 if (u->state == UNIT_FILE_MASKED ||
595 u->state == UNIT_FILE_MASKED_RUNTIME ||
596 u->state == UNIT_FILE_DISABLED) {
597 on = ansi_highlight_red(true);
598 off = ansi_highlight_red(false);
599 } else if (u->state == UNIT_FILE_ENABLED) {
600 on = ansi_highlight_green(true);
601 off = ansi_highlight_green(false);
605 id = file_name_from_path(u->path);
607 e = arg_full ? NULL : ellipsize(id, id_cols, 33);
609 printf("%-*s %s%-*s%s\n",
611 on, state_cols, unit_file_state_to_string(u->state), off);
617 printf("\n%u unit files listed.\n", n_shown);
620 static int list_unit_files(DBusConnection *bus, char **args) {
621 DBusMessage *m = NULL, *reply = NULL;
624 DBusMessageIter iter, sub, sub2;
625 unsigned c = 0, n_units = 0;
626 UnitFileList *units = NULL;
628 dbus_error_init(&error);
630 pager_open_if_enabled();
637 h = hashmap_new(string_hash_func, string_compare_func);
639 log_error("Out of memory");
643 r = unit_file_get_list(arg_scope, arg_root, h);
645 unit_file_list_free(h);
646 log_error("Failed to get unit file list: %s", strerror(-r));
650 n_units = hashmap_size(h);
651 units = new(UnitFileList, n_units);
653 unit_file_list_free(h);
654 log_error("Out of memory");
658 HASHMAP_FOREACH(u, h, i) {
659 memcpy(units + c++, u, sizeof(UnitFileList));
667 m = dbus_message_new_method_call(
668 "org.freedesktop.systemd1",
669 "/org/freedesktop/systemd1",
670 "org.freedesktop.systemd1.Manager",
673 log_error("Could not allocate message.");
677 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
679 log_error("Failed to issue method call: %s", bus_error_message(&error));
684 if (!dbus_message_iter_init(reply, &iter) ||
685 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
686 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
687 log_error("Failed to parse reply.");
692 dbus_message_iter_recurse(&iter, &sub);
694 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
698 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
699 log_error("Failed to parse reply.");
707 n_units = MAX(2*c, 16);
708 w = realloc(units, sizeof(struct UnitFileList) * n_units);
711 log_error("Failed to allocate unit array.");
721 dbus_message_iter_recurse(&sub, &sub2);
723 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->path, true) < 0 ||
724 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, false) < 0) {
725 log_error("Failed to parse reply.");
730 u->state = unit_file_state_from_string(state);
732 dbus_message_iter_next(&sub);
738 qsort(units, c, sizeof(UnitFileList), compare_unit_file_list);
739 output_unit_file_list(units, c);
746 dbus_message_unref(m);
749 dbus_message_unref(reply);
753 dbus_error_free(&error);
758 static int dot_one_property(const char *name, const char *prop, DBusMessageIter *iter) {
759 static const char * const colors[] = {
760 "Requires", "[color=\"black\"]",
761 "RequiresOverridable", "[color=\"black\"]",
762 "Requisite", "[color=\"darkblue\"]",
763 "RequisiteOverridable", "[color=\"darkblue\"]",
764 "Wants", "[color=\"darkgrey\"]",
765 "Conflicts", "[color=\"red\"]",
766 "ConflictedBy", "[color=\"red\"]",
767 "After", "[color=\"green\"]"
770 const char *c = NULL;
777 for (i = 0; i < ELEMENTSOF(colors); i += 2)
778 if (streq(colors[i], prop)) {
786 if (arg_dot != DOT_ALL)
787 if ((arg_dot == DOT_ORDER) != streq(prop, "After"))
790 switch (dbus_message_iter_get_arg_type(iter)) {
792 case DBUS_TYPE_ARRAY:
794 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING) {
797 dbus_message_iter_recurse(iter, &sub);
799 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
802 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING);
803 dbus_message_iter_get_basic(&sub, &s);
804 printf("\t\"%s\"->\"%s\" %s;\n", name, s, c);
806 dbus_message_iter_next(&sub);
816 static int dot_one(DBusConnection *bus, const char *name, const char *path) {
817 DBusMessage *m = NULL, *reply = NULL;
818 const char *interface = "org.freedesktop.systemd1.Unit";
821 DBusMessageIter iter, sub, sub2, sub3;
826 dbus_error_init(&error);
828 if (!(m = dbus_message_new_method_call(
829 "org.freedesktop.systemd1",
831 "org.freedesktop.DBus.Properties",
833 log_error("Could not allocate message.");
838 if (!dbus_message_append_args(m,
839 DBUS_TYPE_STRING, &interface,
840 DBUS_TYPE_INVALID)) {
841 log_error("Could not append arguments to message.");
846 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
847 log_error("Failed to issue method call: %s", bus_error_message(&error));
852 if (!dbus_message_iter_init(reply, &iter) ||
853 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
854 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
855 log_error("Failed to parse reply.");
860 dbus_message_iter_recurse(&iter, &sub);
862 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
865 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_DICT_ENTRY) {
866 log_error("Failed to parse reply.");
871 dbus_message_iter_recurse(&sub, &sub2);
873 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &prop, true) < 0) {
874 log_error("Failed to parse reply.");
879 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
880 log_error("Failed to parse reply.");
885 dbus_message_iter_recurse(&sub2, &sub3);
887 if (dot_one_property(name, prop, &sub3)) {
888 log_error("Failed to parse reply.");
893 dbus_message_iter_next(&sub);
900 dbus_message_unref(m);
903 dbus_message_unref(reply);
905 dbus_error_free(&error);
910 static int dot(DBusConnection *bus, char **args) {
911 DBusMessage *m = NULL, *reply = NULL;
914 DBusMessageIter iter, sub, sub2;
916 dbus_error_init(&error);
920 if (!(m = dbus_message_new_method_call(
921 "org.freedesktop.systemd1",
922 "/org/freedesktop/systemd1",
923 "org.freedesktop.systemd1.Manager",
925 log_error("Could not allocate message.");
929 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
930 log_error("Failed to issue method call: %s", bus_error_message(&error));
935 if (!dbus_message_iter_init(reply, &iter) ||
936 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
937 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
938 log_error("Failed to parse reply.");
943 printf("digraph systemd {\n");
945 dbus_message_iter_recurse(&iter, &sub);
946 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
947 const char *id, *description, *load_state, *active_state, *sub_state, *following, *unit_path;
949 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
950 log_error("Failed to parse reply.");
955 dbus_message_iter_recurse(&sub, &sub2);
957 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &id, true) < 0 ||
958 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &description, true) < 0 ||
959 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &load_state, true) < 0 ||
960 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &active_state, true) < 0 ||
961 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &sub_state, true) < 0 ||
962 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &following, true) < 0 ||
963 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, true) < 0) {
964 log_error("Failed to parse reply.");
969 if ((r = dot_one(bus, id, unit_path)) < 0)
972 /* printf("\t\"%s\";\n", id); */
973 dbus_message_iter_next(&sub);
978 log_info(" Color legend: black = Requires\n"
979 " dark blue = Requisite\n"
980 " dark grey = Wants\n"
985 log_notice("-- You probably want to process this output with graphviz' dot tool.\n"
986 "-- Try a shell pipeline like 'systemctl dot | dot -Tsvg > systemd.svg'!\n");
992 dbus_message_unref(m);
995 dbus_message_unref(reply);
997 dbus_error_free(&error);
1002 static int list_jobs(DBusConnection *bus, char **args) {
1003 DBusMessage *m = NULL, *reply = NULL;
1006 DBusMessageIter iter, sub, sub2;
1009 dbus_error_init(&error);
1013 pager_open_if_enabled();
1015 if (!(m = dbus_message_new_method_call(
1016 "org.freedesktop.systemd1",
1017 "/org/freedesktop/systemd1",
1018 "org.freedesktop.systemd1.Manager",
1020 log_error("Could not allocate message.");
1024 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
1025 log_error("Failed to issue method call: %s", bus_error_message(&error));
1030 if (!dbus_message_iter_init(reply, &iter) ||
1031 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
1032 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
1033 log_error("Failed to parse reply.");
1038 dbus_message_iter_recurse(&iter, &sub);
1041 printf("%4s %-25s %-15s %-7s\n", "JOB", "UNIT", "TYPE", "STATE");
1043 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1044 const char *name, *type, *state, *job_path, *unit_path;
1048 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
1049 log_error("Failed to parse reply.");
1054 dbus_message_iter_recurse(&sub, &sub2);
1056 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &id, true) < 0 ||
1057 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
1058 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
1059 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, true) < 0 ||
1060 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &job_path, true) < 0 ||
1061 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, false) < 0) {
1062 log_error("Failed to parse reply.");
1067 e = arg_full ? NULL : ellipsize(name, 25, 33);
1068 printf("%4u %-25s %-15s %-7s\n", id, e ? e : name, type, state);
1073 dbus_message_iter_next(&sub);
1077 printf("\n%u jobs listed.\n", k);
1083 dbus_message_unref(m);
1086 dbus_message_unref(reply);
1088 dbus_error_free(&error);
1093 static int load_unit(DBusConnection *bus, char **args) {
1094 DBusMessage *m = NULL;
1099 dbus_error_init(&error);
1104 STRV_FOREACH(name, args+1) {
1107 if (!(m = dbus_message_new_method_call(
1108 "org.freedesktop.systemd1",
1109 "/org/freedesktop/systemd1",
1110 "org.freedesktop.systemd1.Manager",
1112 log_error("Could not allocate message.");
1117 if (!dbus_message_append_args(m,
1118 DBUS_TYPE_STRING, name,
1119 DBUS_TYPE_INVALID)) {
1120 log_error("Could not append arguments to message.");
1125 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
1126 log_error("Failed to issue method call: %s", bus_error_message(&error));
1131 dbus_message_unref(m);
1132 dbus_message_unref(reply);
1141 dbus_message_unref(m);
1143 dbus_error_free(&error);
1148 static int cancel_job(DBusConnection *bus, char **args) {
1149 DBusMessage *m = NULL, *reply = NULL;
1154 dbus_error_init(&error);
1159 if (strv_length(args) <= 1)
1160 return daemon_reload(bus, args);
1162 STRV_FOREACH(name, args+1) {
1166 if (!(m = dbus_message_new_method_call(
1167 "org.freedesktop.systemd1",
1168 "/org/freedesktop/systemd1",
1169 "org.freedesktop.systemd1.Manager",
1171 log_error("Could not allocate message.");
1176 if ((r = safe_atou(*name, &id)) < 0) {
1177 log_error("Failed to parse job id: %s", strerror(-r));
1181 assert_cc(sizeof(uint32_t) == sizeof(id));
1182 if (!dbus_message_append_args(m,
1183 DBUS_TYPE_UINT32, &id,
1184 DBUS_TYPE_INVALID)) {
1185 log_error("Could not append arguments to message.");
1190 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
1191 log_error("Failed to issue method call: %s", bus_error_message(&error));
1196 if (!dbus_message_get_args(reply, &error,
1197 DBUS_TYPE_OBJECT_PATH, &path,
1198 DBUS_TYPE_INVALID)) {
1199 log_error("Failed to parse reply: %s", bus_error_message(&error));
1204 dbus_message_unref(m);
1205 if (!(m = dbus_message_new_method_call(
1206 "org.freedesktop.systemd1",
1208 "org.freedesktop.systemd1.Job",
1210 log_error("Could not allocate message.");
1215 dbus_message_unref(reply);
1216 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
1217 log_error("Failed to issue method call: %s", bus_error_message(&error));
1222 dbus_message_unref(m);
1223 dbus_message_unref(reply);
1231 dbus_message_unref(m);
1234 dbus_message_unref(reply);
1236 dbus_error_free(&error);
1241 static bool need_daemon_reload(DBusConnection *bus, const char *unit) {
1242 DBusMessage *m = NULL, *reply = NULL;
1243 dbus_bool_t b = FALSE;
1244 DBusMessageIter iter, sub;
1246 *interface = "org.freedesktop.systemd1.Unit",
1247 *property = "NeedDaemonReload",
1250 /* We ignore all errors here, since this is used to show a warning only */
1252 if (!(m = dbus_message_new_method_call(
1253 "org.freedesktop.systemd1",
1254 "/org/freedesktop/systemd1",
1255 "org.freedesktop.systemd1.Manager",
1259 if (!dbus_message_append_args(m,
1260 DBUS_TYPE_STRING, &unit,
1264 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, NULL)))
1267 if (!dbus_message_get_args(reply, NULL,
1268 DBUS_TYPE_OBJECT_PATH, &path,
1272 dbus_message_unref(m);
1273 if (!(m = dbus_message_new_method_call(
1274 "org.freedesktop.systemd1",
1276 "org.freedesktop.DBus.Properties",
1280 if (!dbus_message_append_args(m,
1281 DBUS_TYPE_STRING, &interface,
1282 DBUS_TYPE_STRING, &property,
1283 DBUS_TYPE_INVALID)) {
1287 dbus_message_unref(reply);
1288 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, NULL)))
1291 if (!dbus_message_iter_init(reply, &iter) ||
1292 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
1295 dbus_message_iter_recurse(&iter, &sub);
1297 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_BOOLEAN)
1300 dbus_message_iter_get_basic(&sub, &b);
1304 dbus_message_unref(m);
1307 dbus_message_unref(reply);
1312 typedef struct WaitData {
1317 static DBusHandlerResult wait_filter(DBusConnection *connection, DBusMessage *message, void *data) {
1325 dbus_error_init(&error);
1327 log_debug("Got D-Bus request: %s.%s() on %s",
1328 dbus_message_get_interface(message),
1329 dbus_message_get_member(message),
1330 dbus_message_get_path(message));
1332 if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
1333 log_error("Warning! D-Bus connection terminated.");
1334 dbus_connection_close(connection);
1336 } else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
1338 const char *path, *result;
1339 dbus_bool_t success = true;
1341 if (dbus_message_get_args(message, &error,
1342 DBUS_TYPE_UINT32, &id,
1343 DBUS_TYPE_OBJECT_PATH, &path,
1344 DBUS_TYPE_STRING, &result,
1345 DBUS_TYPE_INVALID)) {
1348 if ((p = set_remove(d->set, (char*) path)))
1352 d->result = strdup(result);
1357 dbus_error_free(&error);
1359 if (dbus_message_get_args(message, &error,
1360 DBUS_TYPE_UINT32, &id,
1361 DBUS_TYPE_OBJECT_PATH, &path,
1362 DBUS_TYPE_BOOLEAN, &success,
1363 DBUS_TYPE_INVALID)) {
1366 /* Compatibility with older systemd versions <
1367 * 19 during upgrades. This should be dropped
1370 if ((p = set_remove(d->set, (char*) path)))
1374 d->result = strdup("failed");
1380 log_error("Failed to parse message: %s", bus_error_message(&error));
1384 dbus_error_free(&error);
1385 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1388 static int enable_wait_for_jobs(DBusConnection *bus) {
1396 dbus_error_init(&error);
1397 dbus_bus_add_match(bus,
1399 "sender='org.freedesktop.systemd1',"
1400 "interface='org.freedesktop.systemd1.Manager',"
1401 "member='JobRemoved',"
1402 "path='/org/freedesktop/systemd1'",
1405 if (dbus_error_is_set(&error)) {
1406 log_error("Failed to add match: %s", bus_error_message(&error));
1407 dbus_error_free(&error);
1411 /* This is slightly dirty, since we don't undo the match registrations. */
1415 static int wait_for_jobs(DBusConnection *bus, Set *s) {
1425 if (!dbus_connection_add_filter(bus, wait_filter, &d, NULL)) {
1426 log_error("Failed to add filter.");
1431 while (!set_isempty(s) &&
1432 dbus_connection_read_write_dispatch(bus, -1))
1435 if (!arg_quiet && d.result) {
1436 if (streq(d.result, "timeout"))
1437 log_error("Job timed out.");
1438 else if (streq(d.result, "canceled"))
1439 log_error("Job canceled.");
1440 else if (streq(d.result, "dependency"))
1441 log_error("A dependency job failed. See system journal for details.");
1442 else if (!streq(d.result, "done") && !streq(d.result, "skipped"))
1443 log_error("Job failed. See system journal and 'systemctl status' for details.");
1446 if (streq_ptr(d.result, "timeout"))
1448 else if (streq_ptr(d.result, "canceled"))
1450 else if (!streq_ptr(d.result, "done") && !streq_ptr(d.result, "skipped"))
1458 /* This is slightly dirty, since we don't undo the filter registration. */
1463 static int start_unit_one(
1464 DBusConnection *bus,
1471 DBusMessage *m = NULL, *reply = NULL;
1480 assert(arg_no_block || s);
1482 if (!(m = dbus_message_new_method_call(
1483 "org.freedesktop.systemd1",
1484 "/org/freedesktop/systemd1",
1485 "org.freedesktop.systemd1.Manager",
1487 log_error("Could not allocate message.");
1492 if (!dbus_message_append_args(m,
1493 DBUS_TYPE_STRING, &name,
1494 DBUS_TYPE_STRING, &mode,
1495 DBUS_TYPE_INVALID)) {
1496 log_error("Could not append arguments to message.");
1501 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, error))) {
1503 if (arg_action != ACTION_SYSTEMCTL && error_is_no_service(error)) {
1504 /* There's always a fallback possible for
1505 * legacy actions. */
1510 log_error("Failed to issue method call: %s", bus_error_message(error));
1515 if (!dbus_message_get_args(reply, error,
1516 DBUS_TYPE_OBJECT_PATH, &path,
1517 DBUS_TYPE_INVALID)) {
1518 log_error("Failed to parse reply: %s", bus_error_message(error));
1523 if (need_daemon_reload(bus, name))
1524 log_warning("Warning: Unit file of created job changed on disk, 'systemctl %s daemon-reload' recommended.",
1525 arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
1527 if (!arg_no_block) {
1530 if (!(p = strdup(path))) {
1531 log_error("Failed to duplicate path.");
1536 if ((r = set_put(s, p)) < 0) {
1538 log_error("Failed to add path to set.");
1547 dbus_message_unref(m);
1550 dbus_message_unref(reply);
1555 static enum action verb_to_action(const char *verb) {
1556 if (streq(verb, "halt"))
1558 else if (streq(verb, "poweroff"))
1559 return ACTION_POWEROFF;
1560 else if (streq(verb, "reboot"))
1561 return ACTION_REBOOT;
1562 else if (streq(verb, "kexec"))
1563 return ACTION_KEXEC;
1564 else if (streq(verb, "rescue"))
1565 return ACTION_RESCUE;
1566 else if (streq(verb, "emergency"))
1567 return ACTION_EMERGENCY;
1568 else if (streq(verb, "default"))
1569 return ACTION_DEFAULT;
1570 else if (streq(verb, "exit"))
1573 return ACTION_INVALID;
1576 static int start_unit(DBusConnection *bus, char **args) {
1578 static const char * const table[_ACTION_MAX] = {
1579 [ACTION_HALT] = SPECIAL_HALT_TARGET,
1580 [ACTION_POWEROFF] = SPECIAL_POWEROFF_TARGET,
1581 [ACTION_REBOOT] = SPECIAL_REBOOT_TARGET,
1582 [ACTION_KEXEC] = SPECIAL_KEXEC_TARGET,
1583 [ACTION_RUNLEVEL2] = SPECIAL_RUNLEVEL2_TARGET,
1584 [ACTION_RUNLEVEL3] = SPECIAL_RUNLEVEL3_TARGET,
1585 [ACTION_RUNLEVEL4] = SPECIAL_RUNLEVEL4_TARGET,
1586 [ACTION_RUNLEVEL5] = SPECIAL_RUNLEVEL5_TARGET,
1587 [ACTION_RESCUE] = SPECIAL_RESCUE_TARGET,
1588 [ACTION_EMERGENCY] = SPECIAL_EMERGENCY_TARGET,
1589 [ACTION_DEFAULT] = SPECIAL_DEFAULT_TARGET,
1590 [ACTION_EXIT] = SPECIAL_EXIT_TARGET
1594 const char *method, *mode, *one_name;
1599 dbus_error_init(&error);
1603 agent_open_if_enabled();
1605 if (arg_action == ACTION_SYSTEMCTL) {
1607 streq(args[0], "stop") ||
1608 streq(args[0], "condstop") ? "StopUnit" :
1609 streq(args[0], "reload") ? "ReloadUnit" :
1610 streq(args[0], "restart") ? "RestartUnit" :
1612 streq(args[0], "try-restart") ||
1613 streq(args[0], "condrestart") ? "TryRestartUnit" :
1615 streq(args[0], "reload-or-restart") ? "ReloadOrRestartUnit" :
1617 streq(args[0], "reload-or-try-restart") ||
1618 streq(args[0], "condreload") ||
1620 streq(args[0], "force-reload") ? "ReloadOrTryRestartUnit" :
1624 (streq(args[0], "isolate") ||
1625 streq(args[0], "rescue") ||
1626 streq(args[0], "emergency")) ? "isolate" : arg_job_mode;
1628 one_name = table[verb_to_action(args[0])];
1631 assert(arg_action < ELEMENTSOF(table));
1632 assert(table[arg_action]);
1634 method = "StartUnit";
1636 mode = (arg_action == ACTION_EMERGENCY ||
1637 arg_action == ACTION_RESCUE ||
1638 arg_action == ACTION_RUNLEVEL2 ||
1639 arg_action == ACTION_RUNLEVEL3 ||
1640 arg_action == ACTION_RUNLEVEL4 ||
1641 arg_action == ACTION_RUNLEVEL5) ? "isolate" : "replace";
1643 one_name = table[arg_action];
1646 if (!arg_no_block) {
1647 if ((ret = enable_wait_for_jobs(bus)) < 0) {
1648 log_error("Could not watch jobs: %s", strerror(-ret));
1652 if (!(s = set_new(string_hash_func, string_compare_func))) {
1653 log_error("Failed to allocate set.");
1660 if ((ret = start_unit_one(bus, method, one_name, mode, &error, s)) <= 0)
1663 STRV_FOREACH(name, args+1)
1664 if ((r = start_unit_one(bus, method, *name, mode, &error, s)) != 0) {
1665 ret = translate_bus_error_to_exit_status(r, &error);
1666 dbus_error_free(&error);
1671 if ((r = wait_for_jobs(bus, s)) < 0) {
1680 dbus_error_free(&error);
1685 static int start_special(DBusConnection *bus, char **args) {
1691 if (arg_force >= 2 && streq(args[0], "halt"))
1692 halt_now(ACTION_HALT);
1694 if (arg_force >= 2 && streq(args[0], "poweroff"))
1695 halt_now(ACTION_POWEROFF);
1697 if (arg_force >= 2 && streq(args[0], "reboot"))
1698 halt_now(ACTION_POWEROFF);
1701 (streq(args[0], "halt") ||
1702 streq(args[0], "poweroff") ||
1703 streq(args[0], "reboot") ||
1704 streq(args[0], "kexec") ||
1705 streq(args[0], "exit")))
1706 return daemon_reload(bus, args);
1708 r = start_unit(bus, args);
1711 warn_wall(verb_to_action(args[0]));
1716 static int check_unit(DBusConnection *bus, char **args) {
1717 DBusMessage *m = NULL, *reply = NULL;
1719 *interface = "org.freedesktop.systemd1.Unit",
1720 *property = "ActiveState";
1721 int r = 3; /* According to LSB: "program is not running" */
1728 dbus_error_init(&error);
1730 STRV_FOREACH(name, args+1) {
1731 const char *path = NULL;
1733 DBusMessageIter iter, sub;
1735 if (!(m = dbus_message_new_method_call(
1736 "org.freedesktop.systemd1",
1737 "/org/freedesktop/systemd1",
1738 "org.freedesktop.systemd1.Manager",
1740 log_error("Could not allocate message.");
1745 if (!dbus_message_append_args(m,
1746 DBUS_TYPE_STRING, name,
1747 DBUS_TYPE_INVALID)) {
1748 log_error("Could not append arguments to message.");
1753 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
1755 /* Hmm, cannot figure out anything about this unit... */
1759 dbus_error_free(&error);
1760 dbus_message_unref(m);
1765 if (!dbus_message_get_args(reply, &error,
1766 DBUS_TYPE_OBJECT_PATH, &path,
1767 DBUS_TYPE_INVALID)) {
1768 log_error("Failed to parse reply: %s", bus_error_message(&error));
1773 dbus_message_unref(m);
1774 if (!(m = dbus_message_new_method_call(
1775 "org.freedesktop.systemd1",
1777 "org.freedesktop.DBus.Properties",
1779 log_error("Could not allocate message.");
1784 if (!dbus_message_append_args(m,
1785 DBUS_TYPE_STRING, &interface,
1786 DBUS_TYPE_STRING, &property,
1787 DBUS_TYPE_INVALID)) {
1788 log_error("Could not append arguments to message.");
1793 dbus_message_unref(reply);
1794 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
1795 log_error("Failed to issue method call: %s", bus_error_message(&error));
1800 if (!dbus_message_iter_init(reply, &iter) ||
1801 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1802 log_error("Failed to parse reply.");
1807 dbus_message_iter_recurse(&iter, &sub);
1809 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1810 log_error("Failed to parse reply.");
1815 dbus_message_iter_get_basic(&sub, &state);
1820 if (streq(state, "active") || streq(state, "reloading"))
1823 dbus_message_unref(m);
1824 dbus_message_unref(reply);
1830 dbus_message_unref(m);
1833 dbus_message_unref(reply);
1835 dbus_error_free(&error);
1840 static int kill_unit(DBusConnection *bus, char **args) {
1841 DBusMessage *m = NULL;
1849 dbus_error_init(&error);
1852 arg_kill_who = "all";
1855 arg_kill_mode = streq(arg_kill_who, "all") ? "control-group" : "process";
1857 STRV_FOREACH(name, args+1) {
1860 if (!(m = dbus_message_new_method_call(
1861 "org.freedesktop.systemd1",
1862 "/org/freedesktop/systemd1",
1863 "org.freedesktop.systemd1.Manager",
1865 log_error("Could not allocate message.");
1870 if (!dbus_message_append_args(m,
1871 DBUS_TYPE_STRING, name,
1872 DBUS_TYPE_STRING, &arg_kill_who,
1873 DBUS_TYPE_STRING, &arg_kill_mode,
1874 DBUS_TYPE_INT32, &arg_signal,
1875 DBUS_TYPE_INVALID)) {
1876 log_error("Could not append arguments to message.");
1881 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
1882 log_error("Failed to issue method call: %s", bus_error_message(&error));
1883 dbus_error_free(&error);
1887 dbus_message_unref(m);
1890 dbus_message_unref(reply);
1896 dbus_message_unref(m);
1898 dbus_error_free(&error);
1903 typedef struct ExecStatusInfo {
1911 usec_t start_timestamp;
1912 usec_t exit_timestamp;
1917 LIST_FIELDS(struct ExecStatusInfo, exec);
1920 static void exec_status_info_free(ExecStatusInfo *i) {
1929 static int exec_status_info_deserialize(DBusMessageIter *sub, ExecStatusInfo *i) {
1930 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
1931 DBusMessageIter sub2, sub3;
1935 int32_t code, status;
1941 if (dbus_message_iter_get_arg_type(sub) != DBUS_TYPE_STRUCT)
1944 dbus_message_iter_recurse(sub, &sub2);
1946 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0)
1949 if (!(i->path = strdup(path)))
1952 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_ARRAY ||
1953 dbus_message_iter_get_element_type(&sub2) != DBUS_TYPE_STRING)
1957 dbus_message_iter_recurse(&sub2, &sub3);
1958 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
1959 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
1960 dbus_message_iter_next(&sub3);
1965 if (!(i->argv = new0(char*, n+1)))
1969 dbus_message_iter_recurse(&sub2, &sub3);
1970 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
1973 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
1974 dbus_message_iter_get_basic(&sub3, &s);
1975 dbus_message_iter_next(&sub3);
1977 if (!(i->argv[n++] = strdup(s)))
1981 if (!dbus_message_iter_next(&sub2) ||
1982 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, true) < 0 ||
1983 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp, true) < 0 ||
1984 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp_monotonic, true) < 0 ||
1985 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp, true) < 0 ||
1986 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp_monotonic, true) < 0 ||
1987 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, true) < 0 ||
1988 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &code, true) < 0 ||
1989 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &status, false) < 0)
1993 i->start_timestamp = (usec_t) start_timestamp;
1994 i->exit_timestamp = (usec_t) exit_timestamp;
1995 i->pid = (pid_t) pid;
2002 typedef struct UnitStatusInfo {
2004 const char *load_state;
2005 const char *active_state;
2006 const char *sub_state;
2007 const char *unit_file_state;
2009 const char *description;
2010 const char *following;
2013 const char *default_control_group;
2015 const char *load_error;
2018 usec_t inactive_exit_timestamp;
2019 usec_t inactive_exit_timestamp_monotonic;
2020 usec_t active_enter_timestamp;
2021 usec_t active_exit_timestamp;
2022 usec_t inactive_enter_timestamp;
2024 bool need_daemon_reload;
2029 const char *status_text;
2031 #ifdef HAVE_SYSV_COMPAT
2035 usec_t start_timestamp;
2036 usec_t exit_timestamp;
2038 int exit_code, exit_status;
2040 usec_t condition_timestamp;
2041 bool condition_result;
2044 unsigned n_accepted;
2045 unsigned n_connections;
2049 const char *sysfs_path;
2051 /* Mount, Automount */
2057 LIST_HEAD(ExecStatusInfo, exec);
2060 static void print_status_info(UnitStatusInfo *i) {
2062 const char *on, *off, *ss;
2064 char since1[FORMAT_TIMESTAMP_PRETTY_MAX], *s1;
2065 char since2[FORMAT_TIMESTAMP_MAX], *s2;
2069 /* This shows pretty information about a unit. See
2070 * print_property() for a low-level property printer */
2072 printf("%s", strna(i->id));
2074 if (i->description && !streq_ptr(i->id, i->description))
2075 printf(" - %s", i->description);
2080 printf("\t Follow: unit currently follows state of %s\n", i->following);
2082 if (streq_ptr(i->load_state, "error")) {
2083 on = ansi_highlight_red(true);
2084 off = ansi_highlight_red(false);
2089 printf("\t Loaded: %s%s%s (Reason: %s)\n", on, strna(i->load_state), off, i->load_error);
2090 else if (i->path && i->unit_file_state)
2091 printf("\t Loaded: %s%s%s (%s; %s)\n", on, strna(i->load_state), off, i->path, i->unit_file_state);
2093 printf("\t Loaded: %s%s%s (%s)\n", on, strna(i->load_state), off, i->path);
2095 printf("\t Loaded: %s%s%s\n", on, strna(i->load_state), off);
2097 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
2099 if (streq_ptr(i->active_state, "failed")) {
2100 on = ansi_highlight_red(true);
2101 off = ansi_highlight_red(false);
2102 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
2103 on = ansi_highlight_green(true);
2104 off = ansi_highlight_green(false);
2109 printf("\t Active: %s%s (%s)%s",
2111 strna(i->active_state),
2115 printf("\t Active: %s%s%s",
2117 strna(i->active_state),
2120 if (!isempty(i->result) && !streq(i->result, "success"))
2121 printf(" (Result: %s)", i->result);
2123 timestamp = (streq_ptr(i->active_state, "active") ||
2124 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
2125 (streq_ptr(i->active_state, "inactive") ||
2126 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
2127 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
2128 i->active_exit_timestamp;
2130 s1 = format_timestamp_pretty(since1, sizeof(since1), timestamp);
2131 s2 = format_timestamp(since2, sizeof(since2), timestamp);
2134 printf(" since %s; %s\n", s2, s1);
2136 printf(" since %s\n", s2);
2140 if (!i->condition_result && i->condition_timestamp > 0) {
2141 s1 = format_timestamp_pretty(since1, sizeof(since1), i->condition_timestamp);
2142 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
2145 printf("\t start condition failed at %s; %s\n", s2, s1);
2147 printf("\t start condition failed at %s\n", s2);
2151 printf("\t Device: %s\n", i->sysfs_path);
2153 printf("\t Where: %s\n", i->where);
2155 printf("\t What: %s\n", i->what);
2158 printf("\tAccepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
2160 LIST_FOREACH(exec, p, i->exec) {
2164 /* Only show exited processes here */
2168 t = strv_join(p->argv, " ");
2169 printf("\t Process: %u %s=%s ", p->pid, p->name, strna(t));
2172 #ifdef HAVE_SYSV_COMPAT
2174 good = is_clean_exit_lsb(p->code, p->status);
2177 good = is_clean_exit(p->code, p->status);
2180 on = ansi_highlight_red(true);
2181 off = ansi_highlight_red(false);
2185 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
2187 if (p->code == CLD_EXITED) {
2190 printf("status=%i", p->status);
2192 #ifdef HAVE_SYSV_COMPAT
2193 if ((c = exit_status_to_string(p->status, i->is_sysv ? EXIT_STATUS_LSB : EXIT_STATUS_SYSTEMD)))
2195 if ((c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD)))
2200 printf("signal=%s", signal_to_string(p->status));
2202 printf(")%s\n", off);
2204 if (i->main_pid == p->pid &&
2205 i->start_timestamp == p->start_timestamp &&
2206 i->exit_timestamp == p->start_timestamp)
2207 /* Let's not show this twice */
2210 if (p->pid == i->control_pid)
2214 if (i->main_pid > 0 || i->control_pid > 0) {
2217 if (i->main_pid > 0) {
2218 printf("Main PID: %u", (unsigned) i->main_pid);
2222 get_process_comm(i->main_pid, &t);
2227 } else if (i->exit_code > 0) {
2228 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
2230 if (i->exit_code == CLD_EXITED) {
2233 printf("status=%i", i->exit_status);
2235 #ifdef HAVE_SYSV_COMPAT
2236 if ((c = exit_status_to_string(i->exit_status, i->is_sysv ? EXIT_STATUS_LSB : EXIT_STATUS_SYSTEMD)))
2238 if ((c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD)))
2243 printf("signal=%s", signal_to_string(i->exit_status));
2248 if (i->main_pid > 0 && i->control_pid > 0)
2251 if (i->control_pid > 0) {
2254 printf(" Control: %u", (unsigned) i->control_pid);
2256 get_process_comm(i->control_pid, &t);
2267 printf("\t Status: \"%s\"\n", i->status_text);
2269 if (i->default_control_group) {
2272 printf("\t CGroup: %s\n", i->default_control_group);
2274 if (arg_transport != TRANSPORT_SSH) {
2275 if ((c = columns()) > 18)
2280 show_cgroup_by_path(i->default_control_group, "\t\t ", c, false);
2284 if (i->id && arg_transport != TRANSPORT_SSH) {
2286 show_journal_by_unit(i->id, arg_output, NULL, 0, i->inactive_exit_timestamp_monotonic, arg_lines, arg_all, arg_follow);
2289 if (i->need_daemon_reload)
2290 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %s daemon-reload' recommended.\n",
2291 ansi_highlight_red(true),
2292 ansi_highlight_red(false),
2293 arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
2296 static int status_property(const char *name, DBusMessageIter *iter, UnitStatusInfo *i) {
2302 switch (dbus_message_iter_get_arg_type(iter)) {
2304 case DBUS_TYPE_STRING: {
2307 dbus_message_iter_get_basic(iter, &s);
2310 if (streq(name, "Id"))
2312 else if (streq(name, "LoadState"))
2314 else if (streq(name, "ActiveState"))
2315 i->active_state = s;
2316 else if (streq(name, "SubState"))
2318 else if (streq(name, "Description"))
2320 else if (streq(name, "FragmentPath"))
2322 #ifdef HAVE_SYSV_COMPAT
2323 else if (streq(name, "SysVPath")) {
2328 else if (streq(name, "DefaultControlGroup"))
2329 i->default_control_group = s;
2330 else if (streq(name, "StatusText"))
2332 else if (streq(name, "SysFSPath"))
2334 else if (streq(name, "Where"))
2336 else if (streq(name, "What"))
2338 else if (streq(name, "Following"))
2340 else if (streq(name, "UnitFileState"))
2341 i->unit_file_state = s;
2342 else if (streq(name, "Result"))
2349 case DBUS_TYPE_BOOLEAN: {
2352 dbus_message_iter_get_basic(iter, &b);
2354 if (streq(name, "Accept"))
2356 else if (streq(name, "NeedDaemonReload"))
2357 i->need_daemon_reload = b;
2358 else if (streq(name, "ConditionResult"))
2359 i->condition_result = b;
2364 case DBUS_TYPE_UINT32: {
2367 dbus_message_iter_get_basic(iter, &u);
2369 if (streq(name, "MainPID")) {
2371 i->main_pid = (pid_t) u;
2374 } else if (streq(name, "ControlPID"))
2375 i->control_pid = (pid_t) u;
2376 else if (streq(name, "ExecMainPID")) {
2378 i->main_pid = (pid_t) u;
2379 } else if (streq(name, "NAccepted"))
2381 else if (streq(name, "NConnections"))
2382 i->n_connections = u;
2387 case DBUS_TYPE_INT32: {
2390 dbus_message_iter_get_basic(iter, &j);
2392 if (streq(name, "ExecMainCode"))
2393 i->exit_code = (int) j;
2394 else if (streq(name, "ExecMainStatus"))
2395 i->exit_status = (int) j;
2400 case DBUS_TYPE_UINT64: {
2403 dbus_message_iter_get_basic(iter, &u);
2405 if (streq(name, "ExecMainStartTimestamp"))
2406 i->start_timestamp = (usec_t) u;
2407 else if (streq(name, "ExecMainExitTimestamp"))
2408 i->exit_timestamp = (usec_t) u;
2409 else if (streq(name, "ActiveEnterTimestamp"))
2410 i->active_enter_timestamp = (usec_t) u;
2411 else if (streq(name, "InactiveEnterTimestamp"))
2412 i->inactive_enter_timestamp = (usec_t) u;
2413 else if (streq(name, "InactiveExitTimestamp"))
2414 i->inactive_exit_timestamp = (usec_t) u;
2415 else if (streq(name, "InactiveExitTimestampMonotonic"))
2416 i->inactive_exit_timestamp_monotonic = (usec_t) u;
2417 else if (streq(name, "ActiveExitTimestamp"))
2418 i->active_exit_timestamp = (usec_t) u;
2419 else if (streq(name, "ConditionTimestamp"))
2420 i->condition_timestamp = (usec_t) u;
2425 case DBUS_TYPE_ARRAY: {
2427 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
2428 startswith(name, "Exec")) {
2429 DBusMessageIter sub;
2431 dbus_message_iter_recurse(iter, &sub);
2432 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2433 ExecStatusInfo *info;
2436 if (!(info = new0(ExecStatusInfo, 1)))
2439 if (!(info->name = strdup(name))) {
2444 if ((r = exec_status_info_deserialize(&sub, info)) < 0) {
2449 LIST_PREPEND(ExecStatusInfo, exec, i->exec, info);
2451 dbus_message_iter_next(&sub);
2458 case DBUS_TYPE_STRUCT: {
2460 if (streq(name, "LoadError")) {
2461 DBusMessageIter sub;
2462 const char *n, *message;
2465 dbus_message_iter_recurse(iter, &sub);
2467 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &n, true);
2471 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &message, false);
2475 if (!isempty(message))
2476 i->load_error = message;
2486 static int print_property(const char *name, DBusMessageIter *iter) {
2490 /* This is a low-level property printer, see
2491 * print_status_info() for the nicer output */
2493 if (arg_property && !strv_find(arg_property, name))
2496 switch (dbus_message_iter_get_arg_type(iter)) {
2498 case DBUS_TYPE_STRUCT: {
2499 DBusMessageIter sub;
2500 dbus_message_iter_recurse(iter, &sub);
2502 if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32 && streq(name, "Job")) {
2505 dbus_message_iter_get_basic(&sub, &u);
2508 printf("%s=%u\n", name, (unsigned) u);
2510 printf("%s=\n", name);
2513 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "Unit")) {
2516 dbus_message_iter_get_basic(&sub, &s);
2518 if (arg_all || s[0])
2519 printf("%s=%s\n", name, s);
2522 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "LoadError")) {
2523 const char *a = NULL, *b = NULL;
2525 if (bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &a, true) >= 0)
2526 bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &b, false);
2528 if (arg_all || !isempty(a) || !isempty(b))
2529 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
2537 case DBUS_TYPE_ARRAY:
2539 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "EnvironmentFiles")) {
2540 DBusMessageIter sub, sub2;
2542 dbus_message_iter_recurse(iter, &sub);
2543 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2547 dbus_message_iter_recurse(&sub, &sub2);
2549 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
2550 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) >= 0)
2551 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
2553 dbus_message_iter_next(&sub);
2558 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Paths")) {
2559 DBusMessageIter sub, sub2;
2561 dbus_message_iter_recurse(iter, &sub);
2562 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2563 const char *type, *path;
2565 dbus_message_iter_recurse(&sub, &sub2);
2567 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
2568 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
2569 printf("%s=%s\n", type, path);
2571 dbus_message_iter_next(&sub);
2576 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Timers")) {
2577 DBusMessageIter sub, sub2;
2579 dbus_message_iter_recurse(iter, &sub);
2580 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2582 uint64_t value, next_elapse;
2584 dbus_message_iter_recurse(&sub, &sub2);
2586 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &base, true) >= 0 &&
2587 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &value, true) >= 0 &&
2588 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &next_elapse, false) >= 0) {
2589 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
2591 printf("%s={ value=%s ; next_elapse=%s }\n",
2593 format_timespan(timespan1, sizeof(timespan1), value),
2594 format_timespan(timespan2, sizeof(timespan2), next_elapse));
2597 dbus_message_iter_next(&sub);
2602 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "ControlGroupAttributes")) {
2603 DBusMessageIter sub, sub2;
2605 dbus_message_iter_recurse(iter, &sub);
2606 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2607 const char *controller, *attr, *value;
2609 dbus_message_iter_recurse(&sub, &sub2);
2611 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &controller, true) >= 0 &&
2612 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &attr, true) >= 0 &&
2613 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &value, false) >= 0) {
2615 printf("ControlGroupAttribute={ controller=%s ; attribute=%s ; value=\"%s\" }\n",
2621 dbus_message_iter_next(&sub);
2626 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && startswith(name, "Exec")) {
2627 DBusMessageIter sub;
2629 dbus_message_iter_recurse(iter, &sub);
2630 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2631 ExecStatusInfo info;
2634 if (exec_status_info_deserialize(&sub, &info) >= 0) {
2635 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
2638 t = strv_join(info.argv, " ");
2640 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
2644 yes_no(info.ignore),
2645 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
2646 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
2647 (unsigned) info. pid,
2648 sigchld_code_to_string(info.code),
2650 info.code == CLD_EXITED ? "" : "/",
2651 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
2657 strv_free(info.argv);
2659 dbus_message_iter_next(&sub);
2668 if (generic_print_property(name, iter, arg_all) > 0)
2672 printf("%s=[unprintable]\n", name);
2677 static int show_one(const char *verb, DBusConnection *bus, const char *path, bool show_properties, bool *new_line) {
2678 DBusMessage *m = NULL, *reply = NULL;
2679 const char *interface = "";
2682 DBusMessageIter iter, sub, sub2, sub3;
2683 UnitStatusInfo info;
2691 dbus_error_init(&error);
2693 if (!(m = dbus_message_new_method_call(
2694 "org.freedesktop.systemd1",
2696 "org.freedesktop.DBus.Properties",
2698 log_error("Could not allocate message.");
2703 if (!dbus_message_append_args(m,
2704 DBUS_TYPE_STRING, &interface,
2705 DBUS_TYPE_INVALID)) {
2706 log_error("Could not append arguments to message.");
2711 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
2712 log_error("Failed to issue method call: %s", bus_error_message(&error));
2717 if (!dbus_message_iter_init(reply, &iter) ||
2718 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
2719 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
2720 log_error("Failed to parse reply.");
2725 dbus_message_iter_recurse(&iter, &sub);
2732 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
2735 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_DICT_ENTRY) {
2736 log_error("Failed to parse reply.");
2741 dbus_message_iter_recurse(&sub, &sub2);
2743 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0) {
2744 log_error("Failed to parse reply.");
2749 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
2750 log_error("Failed to parse reply.");
2755 dbus_message_iter_recurse(&sub2, &sub3);
2757 if (show_properties)
2758 r = print_property(name, &sub3);
2760 r = status_property(name, &sub3, &info);
2763 log_error("Failed to parse reply.");
2768 dbus_message_iter_next(&sub);
2773 if (!show_properties)
2774 print_status_info(&info);
2776 if (!streq_ptr(info.active_state, "active") &&
2777 !streq_ptr(info.active_state, "reloading") &&
2778 streq(verb, "status"))
2779 /* According to LSB: "program not running" */
2782 while ((p = info.exec)) {
2783 LIST_REMOVE(ExecStatusInfo, exec, info.exec, p);
2784 exec_status_info_free(p);
2789 dbus_message_unref(m);
2792 dbus_message_unref(reply);
2794 dbus_error_free(&error);
2799 static int show(DBusConnection *bus, char **args) {
2800 DBusMessage *m = NULL, *reply = NULL;
2803 bool show_properties, new_line = false;
2809 dbus_error_init(&error);
2811 show_properties = !streq(args[0], "status");
2813 if (show_properties)
2814 pager_open_if_enabled();
2816 if (show_properties && strv_length(args) <= 1) {
2817 /* If not argument is specified inspect the manager
2820 ret = show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line);
2824 STRV_FOREACH(name, args+1) {
2825 const char *path = NULL;
2828 if (safe_atou32(*name, &id) < 0) {
2830 /* Interpret as unit name */
2832 if (!(m = dbus_message_new_method_call(
2833 "org.freedesktop.systemd1",
2834 "/org/freedesktop/systemd1",
2835 "org.freedesktop.systemd1.Manager",
2837 log_error("Could not allocate message.");
2842 if (!dbus_message_append_args(m,
2843 DBUS_TYPE_STRING, name,
2844 DBUS_TYPE_INVALID)) {
2845 log_error("Could not append arguments to message.");
2850 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
2852 if (!dbus_error_has_name(&error, DBUS_ERROR_ACCESS_DENIED)) {
2853 log_error("Failed to issue method call: %s", bus_error_message(&error));
2858 dbus_error_free(&error);
2860 dbus_message_unref(m);
2861 if (!(m = dbus_message_new_method_call(
2862 "org.freedesktop.systemd1",
2863 "/org/freedesktop/systemd1",
2864 "org.freedesktop.systemd1.Manager",
2866 log_error("Could not allocate message.");
2871 if (!dbus_message_append_args(m,
2872 DBUS_TYPE_STRING, name,
2873 DBUS_TYPE_INVALID)) {
2874 log_error("Could not append arguments to message.");
2879 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
2880 log_error("Failed to issue method call: %s", bus_error_message(&error));
2882 if (dbus_error_has_name(&error, BUS_ERROR_NO_SUCH_UNIT))
2883 ret = 4; /* According to LSB: "program or service status is unknown" */
2890 } else if (show_properties) {
2892 /* Interpret as job id */
2894 if (!(m = dbus_message_new_method_call(
2895 "org.freedesktop.systemd1",
2896 "/org/freedesktop/systemd1",
2897 "org.freedesktop.systemd1.Manager",
2899 log_error("Could not allocate message.");
2904 if (!dbus_message_append_args(m,
2905 DBUS_TYPE_UINT32, &id,
2906 DBUS_TYPE_INVALID)) {
2907 log_error("Could not append arguments to message.");
2912 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
2913 log_error("Failed to issue method call: %s", bus_error_message(&error));
2919 /* Interpret as PID */
2921 if (!(m = dbus_message_new_method_call(
2922 "org.freedesktop.systemd1",
2923 "/org/freedesktop/systemd1",
2924 "org.freedesktop.systemd1.Manager",
2926 log_error("Could not allocate message.");
2931 if (!dbus_message_append_args(m,
2932 DBUS_TYPE_UINT32, &id,
2933 DBUS_TYPE_INVALID)) {
2934 log_error("Could not append arguments to message.");
2939 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
2940 log_error("Failed to issue method call: %s", bus_error_message(&error));
2946 if (!dbus_message_get_args(reply, &error,
2947 DBUS_TYPE_OBJECT_PATH, &path,
2948 DBUS_TYPE_INVALID)) {
2949 log_error("Failed to parse reply: %s", bus_error_message(&error));
2954 if ((r = show_one(args[0], bus, path, show_properties, &new_line)) != 0)
2957 dbus_message_unref(m);
2958 dbus_message_unref(reply);
2964 dbus_message_unref(m);
2967 dbus_message_unref(reply);
2969 dbus_error_free(&error);
2974 static int dump(DBusConnection *bus, char **args) {
2975 DBusMessage *m = NULL, *reply = NULL;
2980 dbus_error_init(&error);
2982 pager_open_if_enabled();
2984 if (!(m = dbus_message_new_method_call(
2985 "org.freedesktop.systemd1",
2986 "/org/freedesktop/systemd1",
2987 "org.freedesktop.systemd1.Manager",
2989 log_error("Could not allocate message.");
2993 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
2994 log_error("Failed to issue method call: %s", bus_error_message(&error));
2999 if (!dbus_message_get_args(reply, &error,
3000 DBUS_TYPE_STRING, &text,
3001 DBUS_TYPE_INVALID)) {
3002 log_error("Failed to parse reply: %s", bus_error_message(&error));
3007 fputs(text, stdout);
3013 dbus_message_unref(m);
3016 dbus_message_unref(reply);
3018 dbus_error_free(&error);
3023 static int snapshot(DBusConnection *bus, char **args) {
3024 DBusMessage *m = NULL, *reply = NULL;
3027 const char *name = "", *path, *id;
3028 dbus_bool_t cleanup = FALSE;
3029 DBusMessageIter iter, sub;
3031 *interface = "org.freedesktop.systemd1.Unit",
3034 dbus_error_init(&error);
3036 if (!(m = dbus_message_new_method_call(
3037 "org.freedesktop.systemd1",
3038 "/org/freedesktop/systemd1",
3039 "org.freedesktop.systemd1.Manager",
3040 "CreateSnapshot"))) {
3041 log_error("Could not allocate message.");
3045 if (strv_length(args) > 1)
3048 if (!dbus_message_append_args(m,
3049 DBUS_TYPE_STRING, &name,
3050 DBUS_TYPE_BOOLEAN, &cleanup,
3051 DBUS_TYPE_INVALID)) {
3052 log_error("Could not append arguments to message.");
3057 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3058 log_error("Failed to issue method call: %s", bus_error_message(&error));
3063 if (!dbus_message_get_args(reply, &error,
3064 DBUS_TYPE_OBJECT_PATH, &path,
3065 DBUS_TYPE_INVALID)) {
3066 log_error("Failed to parse reply: %s", bus_error_message(&error));
3071 dbus_message_unref(m);
3072 if (!(m = dbus_message_new_method_call(
3073 "org.freedesktop.systemd1",
3075 "org.freedesktop.DBus.Properties",
3077 log_error("Could not allocate message.");
3081 if (!dbus_message_append_args(m,
3082 DBUS_TYPE_STRING, &interface,
3083 DBUS_TYPE_STRING, &property,
3084 DBUS_TYPE_INVALID)) {
3085 log_error("Could not append arguments to message.");
3090 dbus_message_unref(reply);
3091 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3092 log_error("Failed to issue method call: %s", bus_error_message(&error));
3097 if (!dbus_message_iter_init(reply, &iter) ||
3098 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3099 log_error("Failed to parse reply.");
3104 dbus_message_iter_recurse(&iter, &sub);
3106 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
3107 log_error("Failed to parse reply.");
3112 dbus_message_iter_get_basic(&sub, &id);
3120 dbus_message_unref(m);
3123 dbus_message_unref(reply);
3125 dbus_error_free(&error);
3130 static int delete_snapshot(DBusConnection *bus, char **args) {
3131 DBusMessage *m = NULL, *reply = NULL;
3139 dbus_error_init(&error);
3141 STRV_FOREACH(name, args+1) {
3142 const char *path = NULL;
3144 if (!(m = dbus_message_new_method_call(
3145 "org.freedesktop.systemd1",
3146 "/org/freedesktop/systemd1",
3147 "org.freedesktop.systemd1.Manager",
3149 log_error("Could not allocate message.");
3154 if (!dbus_message_append_args(m,
3155 DBUS_TYPE_STRING, name,
3156 DBUS_TYPE_INVALID)) {
3157 log_error("Could not append arguments to message.");
3162 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3163 log_error("Failed to issue method call: %s", bus_error_message(&error));
3168 if (!dbus_message_get_args(reply, &error,
3169 DBUS_TYPE_OBJECT_PATH, &path,
3170 DBUS_TYPE_INVALID)) {
3171 log_error("Failed to parse reply: %s", bus_error_message(&error));
3176 dbus_message_unref(m);
3177 if (!(m = dbus_message_new_method_call(
3178 "org.freedesktop.systemd1",
3180 "org.freedesktop.systemd1.Snapshot",
3182 log_error("Could not allocate message.");
3187 dbus_message_unref(reply);
3188 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3189 log_error("Failed to issue method call: %s", bus_error_message(&error));
3194 dbus_message_unref(m);
3195 dbus_message_unref(reply);
3203 dbus_message_unref(m);
3206 dbus_message_unref(reply);
3208 dbus_error_free(&error);
3213 static int daemon_reload(DBusConnection *bus, char **args) {
3214 DBusMessage *m = NULL, *reply = NULL;
3219 dbus_error_init(&error);
3221 if (arg_action == ACTION_RELOAD)
3223 else if (arg_action == ACTION_REEXEC)
3224 method = "Reexecute";
3226 assert(arg_action == ACTION_SYSTEMCTL);
3229 streq(args[0], "clear-jobs") ||
3230 streq(args[0], "cancel") ? "ClearJobs" :
3231 streq(args[0], "daemon-reexec") ? "Reexecute" :
3232 streq(args[0], "reset-failed") ? "ResetFailed" :
3233 streq(args[0], "halt") ? "Halt" :
3234 streq(args[0], "poweroff") ? "PowerOff" :
3235 streq(args[0], "reboot") ? "Reboot" :
3236 streq(args[0], "kexec") ? "KExec" :
3237 streq(args[0], "exit") ? "Exit" :
3238 /* "daemon-reload" */ "Reload";
3241 if (!(m = dbus_message_new_method_call(
3242 "org.freedesktop.systemd1",
3243 "/org/freedesktop/systemd1",
3244 "org.freedesktop.systemd1.Manager",
3246 log_error("Could not allocate message.");
3250 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3252 if (arg_action != ACTION_SYSTEMCTL && error_is_no_service(&error)) {
3253 /* There's always a fallback possible for
3254 * legacy actions. */
3259 if (streq(method, "Reexecute") && dbus_error_has_name(&error, DBUS_ERROR_NO_REPLY)) {
3260 /* On reexecution, we expect a disconnect, not
3266 log_error("Failed to issue method call: %s", bus_error_message(&error));
3275 dbus_message_unref(m);
3278 dbus_message_unref(reply);
3280 dbus_error_free(&error);
3285 static int reset_failed(DBusConnection *bus, char **args) {
3286 DBusMessage *m = NULL;
3292 dbus_error_init(&error);
3294 if (strv_length(args) <= 1)
3295 return daemon_reload(bus, args);
3297 STRV_FOREACH(name, args+1) {
3300 if (!(m = dbus_message_new_method_call(
3301 "org.freedesktop.systemd1",
3302 "/org/freedesktop/systemd1",
3303 "org.freedesktop.systemd1.Manager",
3304 "ResetFailedUnit"))) {
3305 log_error("Could not allocate message.");
3310 if (!dbus_message_append_args(m,
3311 DBUS_TYPE_STRING, name,
3312 DBUS_TYPE_INVALID)) {
3313 log_error("Could not append arguments to message.");
3318 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3319 log_error("Failed to issue method call: %s", bus_error_message(&error));
3324 dbus_message_unref(m);
3325 dbus_message_unref(reply);
3333 dbus_message_unref(m);
3335 dbus_error_free(&error);
3340 static int show_enviroment(DBusConnection *bus, char **args) {
3341 DBusMessage *m = NULL, *reply = NULL;
3343 DBusMessageIter iter, sub, sub2;
3346 *interface = "org.freedesktop.systemd1.Manager",
3347 *property = "Environment";
3349 dbus_error_init(&error);
3351 pager_open_if_enabled();
3353 if (!(m = dbus_message_new_method_call(
3354 "org.freedesktop.systemd1",
3355 "/org/freedesktop/systemd1",
3356 "org.freedesktop.DBus.Properties",
3358 log_error("Could not allocate message.");
3362 if (!dbus_message_append_args(m,
3363 DBUS_TYPE_STRING, &interface,
3364 DBUS_TYPE_STRING, &property,
3365 DBUS_TYPE_INVALID)) {
3366 log_error("Could not append arguments to message.");
3371 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3372 log_error("Failed to issue method call: %s", bus_error_message(&error));
3377 if (!dbus_message_iter_init(reply, &iter) ||
3378 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3379 log_error("Failed to parse reply.");
3384 dbus_message_iter_recurse(&iter, &sub);
3386 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_ARRAY ||
3387 dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_STRING) {
3388 log_error("Failed to parse reply.");
3393 dbus_message_iter_recurse(&sub, &sub2);
3395 while (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_INVALID) {
3398 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
3399 log_error("Failed to parse reply.");
3404 dbus_message_iter_get_basic(&sub2, &text);
3405 printf("%s\n", text);
3407 dbus_message_iter_next(&sub2);
3414 dbus_message_unref(m);
3417 dbus_message_unref(reply);
3419 dbus_error_free(&error);
3424 static int set_environment(DBusConnection *bus, char **args) {
3425 DBusMessage *m = NULL, *reply = NULL;
3429 DBusMessageIter iter, sub;
3432 dbus_error_init(&error);
3434 method = streq(args[0], "set-environment")
3436 : "UnsetEnvironment";
3438 if (!(m = dbus_message_new_method_call(
3439 "org.freedesktop.systemd1",
3440 "/org/freedesktop/systemd1",
3441 "org.freedesktop.systemd1.Manager",
3444 log_error("Could not allocate message.");
3448 dbus_message_iter_init_append(m, &iter);
3450 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub)) {
3451 log_error("Could not append arguments to message.");
3456 STRV_FOREACH(name, args+1)
3457 if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, name)) {
3458 log_error("Could not append arguments to message.");
3463 if (!dbus_message_iter_close_container(&iter, &sub)) {
3464 log_error("Could not append arguments to message.");
3469 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3470 log_error("Failed to issue method call: %s", bus_error_message(&error));
3479 dbus_message_unref(m);
3482 dbus_message_unref(reply);
3484 dbus_error_free(&error);
3489 static int enable_sysv_units(char **args) {
3492 #if defined (HAVE_SYSV_COMPAT) && (defined(TARGET_FEDORA) || defined(TARGET_MANDRIVA) || defined(TARGET_SUSE) || defined(TARGET_MEEGO) || defined(TARGET_ALTLINUX) || defined(TARGET_MAGEIA))
3493 const char *verb = args[0];
3494 unsigned f = 1, t = 1;
3497 if (arg_scope != UNIT_FILE_SYSTEM)
3500 if (!streq(verb, "enable") &&
3501 !streq(verb, "disable") &&
3502 !streq(verb, "is-enabled"))
3505 /* Processes all SysV units, and reshuffles the array so that
3506 * afterwards only the native units remain */
3509 r = lookup_paths_init(&paths, MANAGER_SYSTEM, false);
3515 for (f = 1; args[f]; f++) {
3518 bool found_native = false, found_sysv;
3520 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
3521 char **k, *l, *q = NULL;
3528 if (!endswith(name, ".service"))
3531 if (path_is_absolute(name))
3534 STRV_FOREACH(k, paths.unit_path) {
3537 if (!isempty(arg_root))
3538 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
3540 asprintf(&p, "%s/%s", *k, name);
3543 log_error("No memory");
3548 found_native = access(p, F_OK) >= 0;
3559 if (!isempty(arg_root))
3560 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
3562 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
3564 log_error("No memory");
3569 p[strlen(p) - sizeof(".service") + 1] = 0;
3570 found_sysv = access(p, F_OK) >= 0;
3577 /* Mark this entry, so that we don't try enabling it as native unit */
3578 args[f] = (char*) "";
3580 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
3582 if (!isempty(arg_root))
3583 argv[c++] = q = strappend("--root=", arg_root);
3585 argv[c++] = file_name_from_path(p);
3587 streq(verb, "enable") ? "on" :
3588 streq(verb, "disable") ? "off" : "--level=5";
3591 l = strv_join((char**)argv, " ");
3593 log_error("No memory.");
3600 log_info("Executing %s", l);
3605 log_error("Failed to fork: %m");
3610 } else if (pid == 0) {
3613 execv(argv[0], (char**) argv);
3614 _exit(EXIT_FAILURE);
3620 j = wait_for_terminate(pid, &status);
3622 log_error("Failed to wait for child: %s", strerror(-r));
3627 if (status.si_code == CLD_EXITED) {
3628 if (streq(verb, "is-enabled")) {
3629 if (status.si_status == 0) {
3638 } else if (status.si_status != 0) {
3649 lookup_paths_free(&paths);
3651 /* Drop all SysV units */
3652 for (f = 1, t = 1; args[f]; f++) {
3654 if (isempty(args[f]))
3657 args[t++] = args[f];
3666 static int enable_unit(DBusConnection *bus, char **args) {
3667 const char *verb = args[0];
3668 UnitFileChange *changes = NULL;
3669 unsigned n_changes = 0, i;
3670 int carries_install_info = -1;
3671 DBusMessage *m = NULL, *reply = NULL;
3675 r = enable_sysv_units(args);
3682 dbus_error_init(&error);
3684 if (!bus || avoid_bus()) {
3685 if (streq(verb, "enable")) {
3686 r = unit_file_enable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3687 carries_install_info = r;
3688 } else if (streq(verb, "disable"))
3689 r = unit_file_disable(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3690 else if (streq(verb, "reenable")) {
3691 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3692 carries_install_info = r;
3693 } else if (streq(verb, "link"))
3694 r = unit_file_link(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3695 else if (streq(verb, "preset")) {
3696 r = unit_file_preset(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3697 carries_install_info = r;
3698 } else if (streq(verb, "mask"))
3699 r = unit_file_mask(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3700 else if (streq(verb, "unmask"))
3701 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3703 assert_not_reached("Unknown verb");
3706 log_error("Operation failed: %s", strerror(-r));
3711 for (i = 0; i < n_changes; i++) {
3712 if (changes[i].type == UNIT_FILE_SYMLINK)
3713 log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
3715 log_info("rm '%s'", changes[i].path);
3721 bool send_force = true, expect_carries_install_info = false;
3723 DBusMessageIter iter, sub, sub2;
3725 if (streq(verb, "enable")) {
3726 method = "EnableUnitFiles";
3727 expect_carries_install_info = true;
3728 } else if (streq(verb, "disable")) {
3729 method = "DisableUnitFiles";
3731 } else if (streq(verb, "reenable")) {
3732 method = "ReenableUnitFiles";
3733 expect_carries_install_info = true;
3734 } else if (streq(verb, "link"))
3735 method = "LinkUnitFiles";
3736 else if (streq(verb, "preset")) {
3737 method = "PresetUnitFiles";
3738 expect_carries_install_info = true;
3739 } else if (streq(verb, "mask"))
3740 method = "MaskUnitFiles";
3741 else if (streq(verb, "unmask")) {
3742 method = "UnmaskUnitFiles";
3745 assert_not_reached("Unknown verb");
3747 m = dbus_message_new_method_call(
3748 "org.freedesktop.systemd1",
3749 "/org/freedesktop/systemd1",
3750 "org.freedesktop.systemd1.Manager",
3753 log_error("Out of memory");
3758 dbus_message_iter_init_append(m, &iter);
3760 r = bus_append_strv_iter(&iter, args+1);
3762 log_error("Failed to append unit files.");
3767 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &a)) {
3768 log_error("Failed to append runtime boolean.");
3776 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b)) {
3777 log_error("Failed to append force boolean.");
3783 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3785 log_error("Failed to issue method call: %s", bus_error_message(&error));
3790 if (!dbus_message_iter_init(reply, &iter)) {
3791 log_error("Failed to initialize iterator.");
3795 if (expect_carries_install_info) {
3796 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &b, true);
3798 log_error("Failed to parse reply.");
3802 carries_install_info = b;
3805 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3806 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
3807 log_error("Failed to parse reply.");
3812 dbus_message_iter_recurse(&iter, &sub);
3813 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
3814 const char *type, *path, *source;
3816 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
3817 log_error("Failed to parse reply.");
3822 dbus_message_iter_recurse(&sub, &sub2);
3824 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
3825 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
3826 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &source, false) < 0) {
3827 log_error("Failed to parse reply.");
3833 if (streq(type, "symlink"))
3834 log_info("ln -s '%s' '%s'", source, path);
3836 log_info("rm '%s'", path);
3839 dbus_message_iter_next(&sub);
3842 /* Try to reload if enabeld */
3844 r = daemon_reload(bus, args);
3847 if (carries_install_info == 0)
3848 log_warning("Warning: unit files do not carry install information. No operation executed.");
3852 dbus_message_unref(m);
3855 dbus_message_unref(reply);
3857 unit_file_changes_free(changes, n_changes);
3859 dbus_error_free(&error);
3863 static int unit_is_enabled(DBusConnection *bus, char **args) {
3866 DBusMessage *m = NULL, *reply = NULL;
3870 dbus_error_init(&error);
3872 r = enable_sysv_units(args);
3878 if (!bus || avoid_bus()) {
3880 STRV_FOREACH(name, args+1) {
3881 UnitFileState state;
3883 state = unit_file_get_state(arg_scope, arg_root, *name);
3889 if (state == UNIT_FILE_ENABLED ||
3890 state == UNIT_FILE_ENABLED_RUNTIME ||
3891 state == UNIT_FILE_STATIC)
3895 puts(unit_file_state_to_string(state));
3899 STRV_FOREACH(name, args+1) {
3902 m = dbus_message_new_method_call(
3903 "org.freedesktop.systemd1",
3904 "/org/freedesktop/systemd1",
3905 "org.freedesktop.systemd1.Manager",
3906 "GetUnitFileState");
3908 log_error("Out of memory");
3913 if (!dbus_message_append_args(m,
3914 DBUS_TYPE_STRING, name,
3915 DBUS_TYPE_INVALID)) {
3916 log_error("Could not append arguments to message.");
3921 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3923 log_error("Failed to issue method call: %s", bus_error_message(&error));
3928 if (!dbus_message_get_args(reply, &error,
3929 DBUS_TYPE_STRING, &s,
3930 DBUS_TYPE_INVALID)) {
3931 log_error("Failed to parse reply: %s", bus_error_message(&error));
3936 dbus_message_unref(m);
3937 dbus_message_unref(reply);
3940 if (streq(s, "enabled") ||
3941 streq(s, "enabled-runtime") ||
3950 r = enabled ? 0 : 1;
3954 dbus_message_unref(m);
3957 dbus_message_unref(reply);
3959 dbus_error_free(&error);
3963 static int systemctl_help(void) {
3965 pager_open_if_enabled();
3967 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
3968 "Query or send control commands to the systemd manager.\n\n"
3969 " -h --help Show this help\n"
3970 " --version Show package version\n"
3971 " -t --type=TYPE List only units of a particular type\n"
3972 " -p --property=NAME Show only properties by this name\n"
3973 " -a --all Show all units/properties, including dead/empty ones\n"
3974 " --failed Show only failed units\n"
3975 " --full Don't ellipsize unit names on output\n"
3976 " --fail When queueing a new job, fail if conflicting jobs are\n"
3978 " --ignore-dependencies\n"
3979 " When queueing a new job, ignore all its dependencies\n"
3980 " --kill-who=WHO Who to send signal to\n"
3981 " -s --signal=SIGNAL Which signal to send\n"
3982 " -H --host=[USER@]HOST\n"
3983 " Show information for remote host\n"
3984 " -P --privileged Acquire privileges before execution\n"
3985 " -q --quiet Suppress output\n"
3986 " --no-block Do not wait until operation finished\n"
3987 " --no-wall Don't send wall message before halt/power-off/reboot\n"
3988 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
3990 " --no-legend Do not print a legend (column headers and hints)\n"
3991 " --no-pager Do not pipe output into a pager\n"
3992 " --no-ask-password\n"
3993 " Do not ask for system passwords\n"
3994 " --order When generating graph for dot, show only order\n"
3995 " --require When generating graph for dot, show only requirement\n"
3996 " --system Connect to system manager\n"
3997 " --user Connect to user service manager\n"
3998 " --global Enable/disable unit files globally\n"
3999 " -f --force When enabling unit files, override existing symlinks\n"
4000 " When shutting down, execute action immediately\n"
4001 " --root=PATH Enable unit files in the specified root directory\n"
4002 " --runtime Enable unit files only temporarily until next reboot\n"
4003 " -n --lines=INTEGER Journal entries to show\n"
4004 " --follow Follow journal\n"
4005 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
4006 " verbose, export, json, cat)\n\n"
4008 " list-units List loaded units\n"
4009 " start [NAME...] Start (activate) one or more units\n"
4010 " stop [NAME...] Stop (deactivate) one or more units\n"
4011 " reload [NAME...] Reload one or more units\n"
4012 " restart [NAME...] Start or restart one or more units\n"
4013 " try-restart [NAME...] Restart one or more units if active\n"
4014 " reload-or-restart [NAME...] Reload one or more units is possible,\n"
4015 " otherwise start or restart\n"
4016 " reload-or-try-restart [NAME...] Reload one or more units is possible,\n"
4017 " otherwise restart if active\n"
4018 " isolate [NAME] Start one unit and stop all others\n"
4019 " kill [NAME...] Send signal to processes of a unit\n"
4020 " is-active [NAME...] Check whether units are active\n"
4021 " status [NAME...|PID...] Show runtime status of one or more units\n"
4022 " show [NAME...|JOB...] Show properties of one or more\n"
4023 " units/jobs or the manager\n"
4024 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
4026 " load [NAME...] Load one or more units\n\n"
4027 "Unit File Commands:\n"
4028 " list-unit-files List installed unit files\n"
4029 " enable [NAME...] Enable one or more unit files\n"
4030 " disable [NAME...] Disable one or more unit files\n"
4031 " reenable [NAME...] Reenable one or more unit files\n"
4032 " preset [NAME...] Enable/disable one or more unit files\n"
4033 " based on preset configuration\n"
4034 " mask [NAME...] Mask one or more units\n"
4035 " unmask [NAME...] Unmask one or more units\n"
4036 " link [PATH...] Link one or more units files into\n"
4037 " the search path\n"
4038 " is-enabled [NAME...] Check whether unit files are enabled\n\n"
4040 " list-jobs List jobs\n"
4041 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
4042 "Status Commands:\n"
4043 " dump Dump server status\n"
4044 " dot Dump dependency graph for dot(1)\n\n"
4045 "Snapshot Commands:\n"
4046 " snapshot [NAME] Create a snapshot\n"
4047 " delete [NAME...] Remove one or more snapshots\n\n"
4048 "Environment Commands:\n"
4049 " show-environment Dump environment\n"
4050 " set-environment [NAME=VALUE...] Set one or more environment variables\n"
4051 " unset-environment [NAME...] Unset one or more environment variables\n\n"
4052 "Manager Lifecycle Commands:\n"
4053 " daemon-reload Reload systemd manager configuration\n"
4054 " daemon-reexec Reexecute systemd manager\n\n"
4055 "System Commands:\n"
4056 " default Enter system default mode\n"
4057 " rescue Enter system rescue mode\n"
4058 " emergency Enter system emergency mode\n"
4059 " halt Shut down and halt the system\n"
4060 " poweroff Shut down and power-off the system\n"
4061 " reboot Shut down and reboot the system\n"
4062 " kexec Shut down and reboot the system with kexec\n"
4063 " exit Ask for user instance termination\n",
4064 program_invocation_short_name);
4069 static int halt_help(void) {
4071 printf("%s [OPTIONS...]\n\n"
4072 "%s the system.\n\n"
4073 " --help Show this help\n"
4074 " --halt Halt the machine\n"
4075 " -p --poweroff Switch off the machine\n"
4076 " --reboot Reboot the machine\n"
4077 " -f --force Force immediate halt/power-off/reboot\n"
4078 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
4079 " -d --no-wtmp Don't write wtmp record\n"
4080 " -n --no-sync Don't sync before halt/power-off/reboot\n"
4081 " --no-wall Don't send wall message before halt/power-off/reboot\n",
4082 program_invocation_short_name,
4083 arg_action == ACTION_REBOOT ? "Reboot" :
4084 arg_action == ACTION_POWEROFF ? "Power off" :
4090 static int shutdown_help(void) {
4092 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
4093 "Shut down the system.\n\n"
4094 " --help Show this help\n"
4095 " -H --halt Halt the machine\n"
4096 " -P --poweroff Power-off the machine\n"
4097 " -r --reboot Reboot the machine\n"
4098 " -h Equivalent to --poweroff, overriden by --halt\n"
4099 " -k Don't halt/power-off/reboot, just send warnings\n"
4100 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4101 " -c Cancel a pending shutdown\n",
4102 program_invocation_short_name);
4107 static int telinit_help(void) {
4109 printf("%s [OPTIONS...] {COMMAND}\n\n"
4110 "Send control commands to the init daemon.\n\n"
4111 " --help Show this help\n"
4112 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
4114 " 0 Power-off the machine\n"
4115 " 6 Reboot the machine\n"
4116 " 2, 3, 4, 5 Start runlevelX.target unit\n"
4117 " 1, s, S Enter rescue mode\n"
4118 " q, Q Reload init daemon configuration\n"
4119 " u, U Reexecute init daemon\n",
4120 program_invocation_short_name);
4125 static int runlevel_help(void) {
4127 printf("%s [OPTIONS...]\n\n"
4128 "Prints the previous and current runlevel of the init system.\n\n"
4129 " --help Show this help\n",
4130 program_invocation_short_name);
4135 static int systemctl_parse_argv(int argc, char *argv[]) {
4139 ARG_IGNORE_DEPENDENCIES,
4155 ARG_NO_ASK_PASSWORD,
4161 static const struct option options[] = {
4162 { "help", no_argument, NULL, 'h' },
4163 { "version", no_argument, NULL, ARG_VERSION },
4164 { "type", required_argument, NULL, 't' },
4165 { "property", required_argument, NULL, 'p' },
4166 { "all", no_argument, NULL, 'a' },
4167 { "failed", no_argument, NULL, ARG_FAILED },
4168 { "full", no_argument, NULL, ARG_FULL },
4169 { "fail", no_argument, NULL, ARG_FAIL },
4170 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
4171 { "user", no_argument, NULL, ARG_USER },
4172 { "system", no_argument, NULL, ARG_SYSTEM },
4173 { "global", no_argument, NULL, ARG_GLOBAL },
4174 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
4175 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
4176 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
4177 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4178 { "quiet", no_argument, NULL, 'q' },
4179 { "order", no_argument, NULL, ARG_ORDER },
4180 { "require", no_argument, NULL, ARG_REQUIRE },
4181 { "root", required_argument, NULL, ARG_ROOT },
4182 { "force", no_argument, NULL, 'f' },
4183 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
4184 { "kill-mode", required_argument, NULL, ARG_KILL_MODE }, /* undocumented on purpose */
4185 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
4186 { "signal", required_argument, NULL, 's' },
4187 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
4188 { "host", required_argument, NULL, 'H' },
4189 { "privileged",no_argument, NULL, 'P' },
4190 { "runtime", no_argument, NULL, ARG_RUNTIME },
4191 { "lines", required_argument, NULL, 'n' },
4192 { "follow", no_argument, NULL, ARG_FOLLOW },
4193 { "output", required_argument, NULL, 'o' },
4194 { NULL, 0, NULL, 0 }
4202 /* Only when running as systemctl we ask for passwords */
4203 arg_ask_password = true;
4205 while ((c = getopt_long(argc, argv, "ht:p:aqfs:H:Pn:o:", options, NULL)) >= 0) {
4214 puts(PACKAGE_STRING);
4216 puts(SYSTEMD_FEATURES);
4226 if (!(l = strv_append(arg_property, optarg)))
4229 strv_free(arg_property);
4232 /* If the user asked for a particular
4233 * property, show it to him, even if it is
4244 arg_job_mode = "fail";
4247 case ARG_IGNORE_DEPENDENCIES:
4248 arg_job_mode = "ignore-dependencies";
4252 arg_scope = UNIT_FILE_USER;
4256 arg_scope = UNIT_FILE_SYSTEM;
4260 arg_scope = UNIT_FILE_GLOBAL;
4264 arg_no_block = true;
4268 arg_no_legend = true;
4272 arg_no_pager = true;
4280 arg_dot = DOT_ORDER;
4284 arg_dot = DOT_REQUIRE;
4308 arg_no_reload = true;
4312 arg_kill_who = optarg;
4316 arg_kill_mode = optarg;
4320 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
4321 log_error("Failed to parse signal string %s.", optarg);
4326 case ARG_NO_ASK_PASSWORD:
4327 arg_ask_password = false;
4331 arg_transport = TRANSPORT_POLKIT;
4335 arg_transport = TRANSPORT_SSH;
4344 if (safe_atou(optarg, &arg_lines) < 0) {
4345 log_error("Failed to parse lines '%s'", optarg);
4355 arg_output = output_mode_from_string(optarg);
4356 if (arg_output < 0) {
4357 log_error("Unknown output '%s'.", optarg);
4366 log_error("Unknown option code %c", c);
4371 if (arg_transport != TRANSPORT_NORMAL && arg_scope != UNIT_FILE_SYSTEM) {
4372 log_error("Cannot access user instance remotely.");
4379 static int halt_parse_argv(int argc, char *argv[]) {
4388 static const struct option options[] = {
4389 { "help", no_argument, NULL, ARG_HELP },
4390 { "halt", no_argument, NULL, ARG_HALT },
4391 { "poweroff", no_argument, NULL, 'p' },
4392 { "reboot", no_argument, NULL, ARG_REBOOT },
4393 { "force", no_argument, NULL, 'f' },
4394 { "wtmp-only", no_argument, NULL, 'w' },
4395 { "no-wtmp", no_argument, NULL, 'd' },
4396 { "no-sync", no_argument, NULL, 'n' },
4397 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4398 { NULL, 0, NULL, 0 }
4406 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
4407 if (runlevel == '0' || runlevel == '6')
4408 arg_immediate = true;
4410 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
4418 arg_action = ACTION_HALT;
4422 if (arg_action != ACTION_REBOOT)
4423 arg_action = ACTION_POWEROFF;
4427 arg_action = ACTION_REBOOT;
4431 arg_immediate = true;
4452 /* Compatibility nops */
4459 log_error("Unknown option code %c", c);
4464 if (optind < argc) {
4465 log_error("Too many arguments.");
4472 static int parse_time_spec(const char *t, usec_t *_u) {
4476 if (streq(t, "now"))
4478 else if (!strchr(t, ':')) {
4481 if (safe_atou64(t, &u) < 0)
4484 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
4493 hour = strtol(t, &e, 10);
4494 if (errno != 0 || *e != ':' || hour < 0 || hour > 23)
4497 minute = strtol(e+1, &e, 10);
4498 if (errno != 0 || *e != 0 || minute < 0 || minute > 59)
4501 n = now(CLOCK_REALTIME);
4502 s = (time_t) (n / USEC_PER_SEC);
4505 assert_se(localtime_r(&s, &tm));
4507 tm.tm_hour = (int) hour;
4508 tm.tm_min = (int) minute;
4511 assert_se(s = mktime(&tm));
4513 *_u = (usec_t) s * USEC_PER_SEC;
4516 *_u += USEC_PER_DAY;
4522 static int shutdown_parse_argv(int argc, char *argv[]) {
4529 static const struct option options[] = {
4530 { "help", no_argument, NULL, ARG_HELP },
4531 { "halt", no_argument, NULL, 'H' },
4532 { "poweroff", no_argument, NULL, 'P' },
4533 { "reboot", no_argument, NULL, 'r' },
4534 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4535 { NULL, 0, NULL, 0 }
4543 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
4551 arg_action = ACTION_HALT;
4555 arg_action = ACTION_POWEROFF;
4560 arg_action = ACTION_KEXEC;
4562 arg_action = ACTION_REBOOT;
4566 if (arg_action != ACTION_HALT)
4567 arg_action = ACTION_POWEROFF;
4580 /* Compatibility nops */
4584 arg_action = ACTION_CANCEL_SHUTDOWN;
4591 log_error("Unknown option code %c", c);
4596 if (argc > optind) {
4597 if ((r = parse_time_spec(argv[optind], &arg_when)) < 0) {
4598 log_error("Failed to parse time specification: %s", argv[optind]);
4602 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
4604 /* We skip the time argument */
4605 if (argc > optind + 1)
4606 arg_wall = argv + optind + 1;
4613 static int telinit_parse_argv(int argc, char *argv[]) {
4620 static const struct option options[] = {
4621 { "help", no_argument, NULL, ARG_HELP },
4622 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4623 { NULL, 0, NULL, 0 }
4626 static const struct {
4630 { '0', ACTION_POWEROFF },
4631 { '6', ACTION_REBOOT },
4632 { '1', ACTION_RESCUE },
4633 { '2', ACTION_RUNLEVEL2 },
4634 { '3', ACTION_RUNLEVEL3 },
4635 { '4', ACTION_RUNLEVEL4 },
4636 { '5', ACTION_RUNLEVEL5 },
4637 { 's', ACTION_RESCUE },
4638 { 'S', ACTION_RESCUE },
4639 { 'q', ACTION_RELOAD },
4640 { 'Q', ACTION_RELOAD },
4641 { 'u', ACTION_REEXEC },
4642 { 'U', ACTION_REEXEC }
4651 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4666 log_error("Unknown option code %c", c);
4671 if (optind >= argc) {
4676 if (optind + 1 < argc) {
4677 log_error("Too many arguments.");
4681 if (strlen(argv[optind]) != 1) {
4682 log_error("Expected single character argument.");
4686 for (i = 0; i < ELEMENTSOF(table); i++)
4687 if (table[i].from == argv[optind][0])
4690 if (i >= ELEMENTSOF(table)) {
4691 log_error("Unknown command %s.", argv[optind]);
4695 arg_action = table[i].to;
4702 static int runlevel_parse_argv(int argc, char *argv[]) {
4708 static const struct option options[] = {
4709 { "help", no_argument, NULL, ARG_HELP },
4710 { NULL, 0, NULL, 0 }
4718 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4729 log_error("Unknown option code %c", c);
4734 if (optind < argc) {
4735 log_error("Too many arguments.");
4742 static int parse_argv(int argc, char *argv[]) {
4746 if (program_invocation_short_name) {
4748 if (strstr(program_invocation_short_name, "halt")) {
4749 arg_action = ACTION_HALT;
4750 return halt_parse_argv(argc, argv);
4751 } else if (strstr(program_invocation_short_name, "poweroff")) {
4752 arg_action = ACTION_POWEROFF;
4753 return halt_parse_argv(argc, argv);
4754 } else if (strstr(program_invocation_short_name, "reboot")) {
4756 arg_action = ACTION_KEXEC;
4758 arg_action = ACTION_REBOOT;
4759 return halt_parse_argv(argc, argv);
4760 } else if (strstr(program_invocation_short_name, "shutdown")) {
4761 arg_action = ACTION_POWEROFF;
4762 return shutdown_parse_argv(argc, argv);
4763 } else if (strstr(program_invocation_short_name, "init")) {
4765 if (sd_booted() > 0) {
4766 arg_action = ACTION_INVALID;
4767 return telinit_parse_argv(argc, argv);
4769 /* Hmm, so some other init system is
4770 * running, we need to forward this
4771 * request to it. For now we simply
4772 * guess that it is Upstart. */
4774 execv("/lib/upstart/telinit", argv);
4776 log_error("Couldn't find an alternative telinit implementation to spawn.");
4780 } else if (strstr(program_invocation_short_name, "runlevel")) {
4781 arg_action = ACTION_RUNLEVEL;
4782 return runlevel_parse_argv(argc, argv);
4786 arg_action = ACTION_SYSTEMCTL;
4787 return systemctl_parse_argv(argc, argv);
4790 static int action_to_runlevel(void) {
4792 static const char table[_ACTION_MAX] = {
4793 [ACTION_HALT] = '0',
4794 [ACTION_POWEROFF] = '0',
4795 [ACTION_REBOOT] = '6',
4796 [ACTION_RUNLEVEL2] = '2',
4797 [ACTION_RUNLEVEL3] = '3',
4798 [ACTION_RUNLEVEL4] = '4',
4799 [ACTION_RUNLEVEL5] = '5',
4800 [ACTION_RESCUE] = '1'
4803 assert(arg_action < _ACTION_MAX);
4805 return table[arg_action];
4808 static int talk_upstart(void) {
4809 DBusMessage *m = NULL, *reply = NULL;
4811 int previous, rl, r;
4813 env1_buf[] = "RUNLEVEL=X",
4814 env2_buf[] = "PREVLEVEL=X";
4815 char *env1 = env1_buf, *env2 = env2_buf;
4816 const char *emit = "runlevel";
4817 dbus_bool_t b_false = FALSE;
4818 DBusMessageIter iter, sub;
4819 DBusConnection *bus;
4821 dbus_error_init(&error);
4823 if (!(rl = action_to_runlevel()))
4826 if (utmp_get_runlevel(&previous, NULL) < 0)
4829 if (!(bus = dbus_connection_open_private("unix:abstract=/com/ubuntu/upstart", &error))) {
4830 if (dbus_error_has_name(&error, DBUS_ERROR_NO_SERVER)) {
4835 log_error("Failed to connect to Upstart bus: %s", bus_error_message(&error));
4840 if ((r = bus_check_peercred(bus)) < 0) {
4841 log_error("Failed to verify owner of bus.");
4845 if (!(m = dbus_message_new_method_call(
4846 "com.ubuntu.Upstart",
4847 "/com/ubuntu/Upstart",
4848 "com.ubuntu.Upstart0_6",
4851 log_error("Could not allocate message.");
4856 dbus_message_iter_init_append(m, &iter);
4858 env1_buf[sizeof(env1_buf)-2] = rl;
4859 env2_buf[sizeof(env2_buf)-2] = previous;
4861 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &emit) ||
4862 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub) ||
4863 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env1) ||
4864 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env2) ||
4865 !dbus_message_iter_close_container(&iter, &sub) ||
4866 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b_false)) {
4867 log_error("Could not append arguments to message.");
4872 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
4874 if (error_is_no_service(&error)) {
4879 log_error("Failed to issue method call: %s", bus_error_message(&error));
4888 dbus_message_unref(m);
4891 dbus_message_unref(reply);
4894 dbus_connection_flush(bus);
4895 dbus_connection_close(bus);
4896 dbus_connection_unref(bus);
4899 dbus_error_free(&error);
4904 static int talk_initctl(void) {
4905 struct init_request request;
4909 if (!(rl = action_to_runlevel()))
4913 request.magic = INIT_MAGIC;
4914 request.sleeptime = 0;
4915 request.cmd = INIT_CMD_RUNLVL;
4916 request.runlevel = rl;
4918 if ((fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY)) < 0) {
4920 if (errno == ENOENT)
4923 log_error("Failed to open "INIT_FIFO": %m");
4928 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
4929 close_nointr_nofail(fd);
4932 log_error("Failed to write to "INIT_FIFO": %m");
4933 return errno ? -errno : -EIO;
4939 static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
4941 static const struct {
4949 int (* const dispatch)(DBusConnection *bus, char **args);
4951 { "list-units", LESS, 1, list_units },
4952 { "list-unit-files", EQUAL, 1, list_unit_files },
4953 { "list-jobs", EQUAL, 1, list_jobs },
4954 { "clear-jobs", EQUAL, 1, daemon_reload },
4955 { "load", MORE, 2, load_unit },
4956 { "cancel", MORE, 2, cancel_job },
4957 { "start", MORE, 2, start_unit },
4958 { "stop", MORE, 2, start_unit },
4959 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
4960 { "reload", MORE, 2, start_unit },
4961 { "restart", MORE, 2, start_unit },
4962 { "try-restart", MORE, 2, start_unit },
4963 { "reload-or-restart", MORE, 2, start_unit },
4964 { "reload-or-try-restart", MORE, 2, start_unit },
4965 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
4966 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
4967 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
4968 { "isolate", EQUAL, 2, start_unit },
4969 { "kill", MORE, 2, kill_unit },
4970 { "is-active", MORE, 2, check_unit },
4971 { "check", MORE, 2, check_unit },
4972 { "show", MORE, 1, show },
4973 { "status", MORE, 2, show },
4974 { "dump", EQUAL, 1, dump },
4975 { "dot", EQUAL, 1, dot },
4976 { "snapshot", LESS, 2, snapshot },
4977 { "delete", MORE, 2, delete_snapshot },
4978 { "daemon-reload", EQUAL, 1, daemon_reload },
4979 { "daemon-reexec", EQUAL, 1, daemon_reload },
4980 { "show-environment", EQUAL, 1, show_enviroment },
4981 { "set-environment", MORE, 2, set_environment },
4982 { "unset-environment", MORE, 2, set_environment },
4983 { "halt", EQUAL, 1, start_special },
4984 { "poweroff", EQUAL, 1, start_special },
4985 { "reboot", EQUAL, 1, start_special },
4986 { "kexec", EQUAL, 1, start_special },
4987 { "default", EQUAL, 1, start_special },
4988 { "rescue", EQUAL, 1, start_special },
4989 { "emergency", EQUAL, 1, start_special },
4990 { "exit", EQUAL, 1, start_special },
4991 { "reset-failed", MORE, 1, reset_failed },
4992 { "enable", MORE, 2, enable_unit },
4993 { "disable", MORE, 2, enable_unit },
4994 { "is-enabled", MORE, 2, unit_is_enabled },
4995 { "reenable", MORE, 2, enable_unit },
4996 { "preset", MORE, 2, enable_unit },
4997 { "mask", MORE, 2, enable_unit },
4998 { "unmask", MORE, 2, enable_unit },
4999 { "link", MORE, 2, enable_unit }
5009 left = argc - optind;
5012 /* Special rule: no arguments means "list-units" */
5015 if (streq(argv[optind], "help")) {
5020 for (i = 0; i < ELEMENTSOF(verbs); i++)
5021 if (streq(argv[optind], verbs[i].verb))
5024 if (i >= ELEMENTSOF(verbs)) {
5025 log_error("Unknown operation %s", argv[optind]);
5030 switch (verbs[i].argc_cmp) {
5033 if (left != verbs[i].argc) {
5034 log_error("Invalid number of arguments.");
5041 if (left < verbs[i].argc) {
5042 log_error("Too few arguments.");
5049 if (left > verbs[i].argc) {
5050 log_error("Too many arguments.");
5057 assert_not_reached("Unknown comparison operator.");
5060 /* Require a bus connection for all operations but
5062 if (!streq(verbs[i].verb, "enable") &&
5063 !streq(verbs[i].verb, "disable") &&
5064 !streq(verbs[i].verb, "is-enabled") &&
5065 !streq(verbs[i].verb, "list-unit-files") &&
5066 !streq(verbs[i].verb, "reenable") &&
5067 !streq(verbs[i].verb, "preset") &&
5068 !streq(verbs[i].verb, "mask") &&
5069 !streq(verbs[i].verb, "unmask") &&
5070 !streq(verbs[i].verb, "link")) {
5072 if (running_in_chroot() > 0) {
5073 log_info("Running in chroot, ignoring request.");
5078 log_error("Failed to get D-Bus connection: %s",
5079 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5085 if (!bus && !avoid_bus()) {
5086 log_error("Failed to get D-Bus connection: %s",
5087 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5092 return verbs[i].dispatch(bus, argv + optind);
5095 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
5097 struct msghdr msghdr;
5099 union sockaddr_union sockaddr;
5100 struct shutdownd_command c;
5105 c.dry_run = dry_run;
5109 strncpy(c.wall_message, message, sizeof(c.wall_message));
5111 if ((fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0)) < 0)
5115 sockaddr.sa.sa_family = AF_UNIX;
5116 sockaddr.un.sun_path[0] = 0;
5117 strncpy(sockaddr.un.sun_path, "/run/systemd/shutdownd", sizeof(sockaddr.un.sun_path));
5120 iovec.iov_base = (char*) &c;
5121 iovec.iov_len = sizeof(c);
5124 msghdr.msg_name = &sockaddr;
5125 msghdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + sizeof("/run/systemd/shutdownd") - 1;
5127 msghdr.msg_iov = &iovec;
5128 msghdr.msg_iovlen = 1;
5130 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0) {
5131 close_nointr_nofail(fd);
5135 close_nointr_nofail(fd);
5139 static int reload_with_fallback(DBusConnection *bus) {
5142 /* First, try systemd via D-Bus. */
5143 if (daemon_reload(bus, NULL) >= 0)
5147 /* Nothing else worked, so let's try signals */
5148 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
5150 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
5151 log_error("kill() failed: %m");
5158 static int start_with_fallback(DBusConnection *bus) {
5161 /* First, try systemd via D-Bus. */
5162 if (start_unit(bus, NULL) >= 0)
5166 /* Hmm, talking to systemd via D-Bus didn't work. Then
5167 * let's try to talk to Upstart via D-Bus. */
5168 if (talk_upstart() > 0)
5171 /* Nothing else worked, so let's try
5173 if (talk_initctl() > 0)
5176 log_error("Failed to talk to init daemon.");
5180 warn_wall(arg_action);
5184 static void halt_now(int action) {
5186 /* Make sure C-A-D is handled by the kernel from this
5188 reboot(RB_ENABLE_CAD);
5193 log_info("Halting.");
5194 reboot(RB_HALT_SYSTEM);
5197 case ACTION_POWEROFF:
5198 log_info("Powering off.");
5199 reboot(RB_POWER_OFF);
5203 log_info("Rebooting.");
5204 reboot(RB_AUTOBOOT);
5208 assert_not_reached("Unknown halt action.");
5211 assert_not_reached("Uh? This shouldn't happen.");
5214 static int halt_main(DBusConnection *bus) {
5217 if (geteuid() != 0) {
5218 log_error("Must be root.");
5224 char date[FORMAT_TIMESTAMP_MAX];
5226 m = strv_join(arg_wall, " ");
5227 r = send_shutdownd(arg_when,
5228 arg_action == ACTION_HALT ? 'H' :
5229 arg_action == ACTION_POWEROFF ? 'P' :
5237 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
5239 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
5240 format_timestamp(date, sizeof(date), arg_when));
5245 if (!arg_dry && !arg_immediate)
5246 return start_with_fallback(bus);
5249 if (sd_booted() > 0)
5250 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
5251 else if ((r = utmp_put_shutdown()) < 0)
5252 log_warning("Failed to write utmp record: %s", strerror(-r));
5261 halt_now(arg_action);
5262 /* We should never reach this. */
5266 static int runlevel_main(void) {
5267 int r, runlevel, previous;
5269 r = utmp_get_runlevel(&runlevel, &previous);
5276 previous <= 0 ? 'N' : previous,
5277 runlevel <= 0 ? 'N' : runlevel);
5282 int main(int argc, char*argv[]) {
5283 int r, retval = EXIT_FAILURE;
5284 DBusConnection *bus = NULL;
5287 dbus_error_init(&error);
5289 log_parse_environment();
5292 if ((r = parse_argv(argc, argv)) < 0)
5295 retval = EXIT_SUCCESS;
5299 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
5300 * let's shortcut this */
5301 if (arg_action == ACTION_RUNLEVEL) {
5302 r = runlevel_main();
5303 retval = r < 0 ? EXIT_FAILURE : r;
5307 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
5308 log_info("Running in chroot, ignoring request.");
5314 if (arg_transport == TRANSPORT_NORMAL)
5315 bus_connect(arg_scope == UNIT_FILE_SYSTEM ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &bus, &private_bus, &error);
5316 else if (arg_transport == TRANSPORT_POLKIT) {
5317 bus_connect_system_polkit(&bus, &error);
5318 private_bus = false;
5319 } else if (arg_transport == TRANSPORT_SSH) {
5320 bus_connect_system_ssh(NULL, arg_host, &bus, &error);
5321 private_bus = false;
5323 assert_not_reached("Uh, invalid transport...");
5326 switch (arg_action) {
5328 case ACTION_SYSTEMCTL:
5329 r = systemctl_main(bus, argc, argv, &error);
5333 case ACTION_POWEROFF:
5339 case ACTION_RUNLEVEL2:
5340 case ACTION_RUNLEVEL3:
5341 case ACTION_RUNLEVEL4:
5342 case ACTION_RUNLEVEL5:
5344 case ACTION_EMERGENCY:
5345 case ACTION_DEFAULT:
5346 r = start_with_fallback(bus);
5351 r = reload_with_fallback(bus);
5354 case ACTION_CANCEL_SHUTDOWN:
5355 r = send_shutdownd(0, 0, false, false, NULL);
5358 case ACTION_INVALID:
5359 case ACTION_RUNLEVEL:
5361 assert_not_reached("Unknown action");
5364 retval = r < 0 ? EXIT_FAILURE : r;
5368 dbus_connection_flush(bus);
5369 dbus_connection_close(bus);
5370 dbus_connection_unref(bus);
5373 dbus_error_free(&error);
5377 strv_free(arg_property);