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(enum action a);
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 a) {
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[a], 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 /* ask systemd-logind, which might grant access to unprivileged users through polkit */
1686 static int reboot_with_logind(DBusConnection *bus, enum action a) {
1689 DBusMessage *m = NULL, *reply = NULL;
1691 dbus_bool_t interactive = true;
1694 dbus_error_init(&error);
1702 case ACTION_POWEROFF:
1703 method = "PowerOff";
1710 m = dbus_message_new_method_call(
1711 "org.freedesktop.login1",
1712 "/org/freedesktop/login1",
1713 "org.freedesktop.login1.Manager",
1716 log_error("Could not allocate message.");
1721 if (!dbus_message_append_args(m,
1722 DBUS_TYPE_BOOLEAN, &interactive,
1723 DBUS_TYPE_INVALID)) {
1724 log_error("Could not append arguments to message.");
1729 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
1731 if (error_is_no_service(&error)) {
1732 log_debug("Failed to issue method call: %s", bus_error_message(&error));
1737 if (dbus_error_has_name(&error, DBUS_ERROR_ACCESS_DENIED)) {
1738 log_debug("Failed to issue method call: %s", bus_error_message(&error));
1743 log_info("Failed to issue method call: %s", bus_error_message(&error));
1752 dbus_message_unref(m);
1755 dbus_message_unref(reply);
1757 dbus_error_free(&error);
1765 static int start_special(DBusConnection *bus, char **args) {
1772 a = verb_to_action(args[0]);
1774 if (arg_force >= 2 && a == ACTION_HALT)
1775 halt_now(ACTION_HALT);
1777 if (arg_force >= 2 && a == ACTION_POWEROFF)
1778 halt_now(ACTION_POWEROFF);
1780 if (arg_force >= 2 && a == ACTION_REBOOT)
1781 halt_now(ACTION_REBOOT);
1784 (a == ACTION_HALT ||
1785 a == ACTION_POWEROFF ||
1786 a == ACTION_REBOOT ||
1787 a == ACTION_KEXEC ||
1789 return daemon_reload(bus, args);
1791 if (geteuid() != 0) {
1792 /* first try logind, to allow authentication with polkit */
1793 if (a == ACTION_POWEROFF ||
1794 a == ACTION_REBOOT) {
1795 r = reboot_with_logind(bus, a);
1801 r = start_unit(bus, args);
1808 static int check_unit(DBusConnection *bus, char **args) {
1809 DBusMessage *m = NULL, *reply = NULL;
1811 *interface = "org.freedesktop.systemd1.Unit",
1812 *property = "ActiveState";
1813 int r = 3; /* According to LSB: "program is not running" */
1820 dbus_error_init(&error);
1822 STRV_FOREACH(name, args+1) {
1823 const char *path = NULL;
1825 DBusMessageIter iter, sub;
1827 if (!(m = dbus_message_new_method_call(
1828 "org.freedesktop.systemd1",
1829 "/org/freedesktop/systemd1",
1830 "org.freedesktop.systemd1.Manager",
1832 log_error("Could not allocate message.");
1837 if (!dbus_message_append_args(m,
1838 DBUS_TYPE_STRING, name,
1839 DBUS_TYPE_INVALID)) {
1840 log_error("Could not append arguments to message.");
1845 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
1847 /* Hmm, cannot figure out anything about this unit... */
1851 dbus_error_free(&error);
1852 dbus_message_unref(m);
1857 if (!dbus_message_get_args(reply, &error,
1858 DBUS_TYPE_OBJECT_PATH, &path,
1859 DBUS_TYPE_INVALID)) {
1860 log_error("Failed to parse reply: %s", bus_error_message(&error));
1865 dbus_message_unref(m);
1866 if (!(m = dbus_message_new_method_call(
1867 "org.freedesktop.systemd1",
1869 "org.freedesktop.DBus.Properties",
1871 log_error("Could not allocate message.");
1876 if (!dbus_message_append_args(m,
1877 DBUS_TYPE_STRING, &interface,
1878 DBUS_TYPE_STRING, &property,
1879 DBUS_TYPE_INVALID)) {
1880 log_error("Could not append arguments to message.");
1885 dbus_message_unref(reply);
1886 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
1887 log_error("Failed to issue method call: %s", bus_error_message(&error));
1892 if (!dbus_message_iter_init(reply, &iter) ||
1893 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1894 log_error("Failed to parse reply.");
1899 dbus_message_iter_recurse(&iter, &sub);
1901 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1902 log_error("Failed to parse reply.");
1907 dbus_message_iter_get_basic(&sub, &state);
1912 if (streq(state, "active") || streq(state, "reloading"))
1915 dbus_message_unref(m);
1916 dbus_message_unref(reply);
1922 dbus_message_unref(m);
1925 dbus_message_unref(reply);
1927 dbus_error_free(&error);
1932 static int kill_unit(DBusConnection *bus, char **args) {
1933 DBusMessage *m = NULL;
1941 dbus_error_init(&error);
1944 arg_kill_who = "all";
1947 arg_kill_mode = streq(arg_kill_who, "all") ? "control-group" : "process";
1949 STRV_FOREACH(name, args+1) {
1952 if (!(m = dbus_message_new_method_call(
1953 "org.freedesktop.systemd1",
1954 "/org/freedesktop/systemd1",
1955 "org.freedesktop.systemd1.Manager",
1957 log_error("Could not allocate message.");
1962 if (!dbus_message_append_args(m,
1963 DBUS_TYPE_STRING, name,
1964 DBUS_TYPE_STRING, &arg_kill_who,
1965 DBUS_TYPE_STRING, &arg_kill_mode,
1966 DBUS_TYPE_INT32, &arg_signal,
1967 DBUS_TYPE_INVALID)) {
1968 log_error("Could not append arguments to message.");
1973 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
1974 log_error("Failed to issue method call: %s", bus_error_message(&error));
1975 dbus_error_free(&error);
1979 dbus_message_unref(m);
1982 dbus_message_unref(reply);
1988 dbus_message_unref(m);
1990 dbus_error_free(&error);
1995 typedef struct ExecStatusInfo {
2003 usec_t start_timestamp;
2004 usec_t exit_timestamp;
2009 LIST_FIELDS(struct ExecStatusInfo, exec);
2012 static void exec_status_info_free(ExecStatusInfo *i) {
2021 static int exec_status_info_deserialize(DBusMessageIter *sub, ExecStatusInfo *i) {
2022 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
2023 DBusMessageIter sub2, sub3;
2027 int32_t code, status;
2033 if (dbus_message_iter_get_arg_type(sub) != DBUS_TYPE_STRUCT)
2036 dbus_message_iter_recurse(sub, &sub2);
2038 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0)
2041 if (!(i->path = strdup(path)))
2044 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_ARRAY ||
2045 dbus_message_iter_get_element_type(&sub2) != DBUS_TYPE_STRING)
2049 dbus_message_iter_recurse(&sub2, &sub3);
2050 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2051 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2052 dbus_message_iter_next(&sub3);
2057 if (!(i->argv = new0(char*, n+1)))
2061 dbus_message_iter_recurse(&sub2, &sub3);
2062 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2065 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2066 dbus_message_iter_get_basic(&sub3, &s);
2067 dbus_message_iter_next(&sub3);
2069 if (!(i->argv[n++] = strdup(s)))
2073 if (!dbus_message_iter_next(&sub2) ||
2074 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, true) < 0 ||
2075 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp, true) < 0 ||
2076 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp_monotonic, true) < 0 ||
2077 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp, true) < 0 ||
2078 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp_monotonic, true) < 0 ||
2079 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, true) < 0 ||
2080 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &code, true) < 0 ||
2081 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &status, false) < 0)
2085 i->start_timestamp = (usec_t) start_timestamp;
2086 i->exit_timestamp = (usec_t) exit_timestamp;
2087 i->pid = (pid_t) pid;
2094 typedef struct UnitStatusInfo {
2096 const char *load_state;
2097 const char *active_state;
2098 const char *sub_state;
2099 const char *unit_file_state;
2101 const char *description;
2102 const char *following;
2105 const char *default_control_group;
2107 const char *load_error;
2110 usec_t inactive_exit_timestamp;
2111 usec_t inactive_exit_timestamp_monotonic;
2112 usec_t active_enter_timestamp;
2113 usec_t active_exit_timestamp;
2114 usec_t inactive_enter_timestamp;
2116 bool need_daemon_reload;
2121 const char *status_text;
2123 #ifdef HAVE_SYSV_COMPAT
2127 usec_t start_timestamp;
2128 usec_t exit_timestamp;
2130 int exit_code, exit_status;
2132 usec_t condition_timestamp;
2133 bool condition_result;
2136 unsigned n_accepted;
2137 unsigned n_connections;
2141 const char *sysfs_path;
2143 /* Mount, Automount */
2149 LIST_HEAD(ExecStatusInfo, exec);
2152 static void print_status_info(UnitStatusInfo *i) {
2154 const char *on, *off, *ss;
2156 char since1[FORMAT_TIMESTAMP_PRETTY_MAX], *s1;
2157 char since2[FORMAT_TIMESTAMP_MAX], *s2;
2161 /* This shows pretty information about a unit. See
2162 * print_property() for a low-level property printer */
2164 printf("%s", strna(i->id));
2166 if (i->description && !streq_ptr(i->id, i->description))
2167 printf(" - %s", i->description);
2172 printf("\t Follow: unit currently follows state of %s\n", i->following);
2174 if (streq_ptr(i->load_state, "error")) {
2175 on = ansi_highlight_red(true);
2176 off = ansi_highlight_red(false);
2181 printf("\t Loaded: %s%s%s (Reason: %s)\n", on, strna(i->load_state), off, i->load_error);
2182 else if (i->path && i->unit_file_state)
2183 printf("\t Loaded: %s%s%s (%s; %s)\n", on, strna(i->load_state), off, i->path, i->unit_file_state);
2185 printf("\t Loaded: %s%s%s (%s)\n", on, strna(i->load_state), off, i->path);
2187 printf("\t Loaded: %s%s%s\n", on, strna(i->load_state), off);
2189 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
2191 if (streq_ptr(i->active_state, "failed")) {
2192 on = ansi_highlight_red(true);
2193 off = ansi_highlight_red(false);
2194 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
2195 on = ansi_highlight_green(true);
2196 off = ansi_highlight_green(false);
2201 printf("\t Active: %s%s (%s)%s",
2203 strna(i->active_state),
2207 printf("\t Active: %s%s%s",
2209 strna(i->active_state),
2212 if (!isempty(i->result) && !streq(i->result, "success"))
2213 printf(" (Result: %s)", i->result);
2215 timestamp = (streq_ptr(i->active_state, "active") ||
2216 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
2217 (streq_ptr(i->active_state, "inactive") ||
2218 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
2219 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
2220 i->active_exit_timestamp;
2222 s1 = format_timestamp_pretty(since1, sizeof(since1), timestamp);
2223 s2 = format_timestamp(since2, sizeof(since2), timestamp);
2226 printf(" since %s; %s\n", s2, s1);
2228 printf(" since %s\n", s2);
2232 if (!i->condition_result && i->condition_timestamp > 0) {
2233 s1 = format_timestamp_pretty(since1, sizeof(since1), i->condition_timestamp);
2234 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
2237 printf("\t start condition failed at %s; %s\n", s2, s1);
2239 printf("\t start condition failed at %s\n", s2);
2243 printf("\t Device: %s\n", i->sysfs_path);
2245 printf("\t Where: %s\n", i->where);
2247 printf("\t What: %s\n", i->what);
2250 printf("\tAccepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
2252 LIST_FOREACH(exec, p, i->exec) {
2256 /* Only show exited processes here */
2260 t = strv_join(p->argv, " ");
2261 printf("\t Process: %u %s=%s ", p->pid, p->name, strna(t));
2264 #ifdef HAVE_SYSV_COMPAT
2266 good = is_clean_exit_lsb(p->code, p->status);
2269 good = is_clean_exit(p->code, p->status);
2272 on = ansi_highlight_red(true);
2273 off = ansi_highlight_red(false);
2277 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
2279 if (p->code == CLD_EXITED) {
2282 printf("status=%i", p->status);
2284 #ifdef HAVE_SYSV_COMPAT
2285 if ((c = exit_status_to_string(p->status, i->is_sysv ? EXIT_STATUS_LSB : EXIT_STATUS_SYSTEMD)))
2287 if ((c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD)))
2292 printf("signal=%s", signal_to_string(p->status));
2294 printf(")%s\n", off);
2296 if (i->main_pid == p->pid &&
2297 i->start_timestamp == p->start_timestamp &&
2298 i->exit_timestamp == p->start_timestamp)
2299 /* Let's not show this twice */
2302 if (p->pid == i->control_pid)
2306 if (i->main_pid > 0 || i->control_pid > 0) {
2309 if (i->main_pid > 0) {
2310 printf("Main PID: %u", (unsigned) i->main_pid);
2314 get_process_comm(i->main_pid, &t);
2319 } else if (i->exit_code > 0) {
2320 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
2322 if (i->exit_code == CLD_EXITED) {
2325 printf("status=%i", i->exit_status);
2327 #ifdef HAVE_SYSV_COMPAT
2328 if ((c = exit_status_to_string(i->exit_status, i->is_sysv ? EXIT_STATUS_LSB : EXIT_STATUS_SYSTEMD)))
2330 if ((c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD)))
2335 printf("signal=%s", signal_to_string(i->exit_status));
2340 if (i->main_pid > 0 && i->control_pid > 0)
2343 if (i->control_pid > 0) {
2346 printf(" Control: %u", (unsigned) i->control_pid);
2348 get_process_comm(i->control_pid, &t);
2359 printf("\t Status: \"%s\"\n", i->status_text);
2361 if (i->default_control_group) {
2364 printf("\t CGroup: %s\n", i->default_control_group);
2366 if (arg_transport != TRANSPORT_SSH) {
2367 if ((c = columns()) > 18)
2372 show_cgroup_by_path(i->default_control_group, "\t\t ", c, false);
2376 if (i->id && arg_transport != TRANSPORT_SSH) {
2378 show_journal_by_unit(i->id, arg_output, 0, i->inactive_exit_timestamp_monotonic, arg_lines, arg_all, arg_follow);
2381 if (i->need_daemon_reload)
2382 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %s daemon-reload' recommended.\n",
2383 ansi_highlight_red(true),
2384 ansi_highlight_red(false),
2385 arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
2388 static int status_property(const char *name, DBusMessageIter *iter, UnitStatusInfo *i) {
2394 switch (dbus_message_iter_get_arg_type(iter)) {
2396 case DBUS_TYPE_STRING: {
2399 dbus_message_iter_get_basic(iter, &s);
2402 if (streq(name, "Id"))
2404 else if (streq(name, "LoadState"))
2406 else if (streq(name, "ActiveState"))
2407 i->active_state = s;
2408 else if (streq(name, "SubState"))
2410 else if (streq(name, "Description"))
2412 else if (streq(name, "FragmentPath"))
2414 #ifdef HAVE_SYSV_COMPAT
2415 else if (streq(name, "SysVPath")) {
2420 else if (streq(name, "DefaultControlGroup"))
2421 i->default_control_group = s;
2422 else if (streq(name, "StatusText"))
2424 else if (streq(name, "SysFSPath"))
2426 else if (streq(name, "Where"))
2428 else if (streq(name, "What"))
2430 else if (streq(name, "Following"))
2432 else if (streq(name, "UnitFileState"))
2433 i->unit_file_state = s;
2434 else if (streq(name, "Result"))
2441 case DBUS_TYPE_BOOLEAN: {
2444 dbus_message_iter_get_basic(iter, &b);
2446 if (streq(name, "Accept"))
2448 else if (streq(name, "NeedDaemonReload"))
2449 i->need_daemon_reload = b;
2450 else if (streq(name, "ConditionResult"))
2451 i->condition_result = b;
2456 case DBUS_TYPE_UINT32: {
2459 dbus_message_iter_get_basic(iter, &u);
2461 if (streq(name, "MainPID")) {
2463 i->main_pid = (pid_t) u;
2466 } else if (streq(name, "ControlPID"))
2467 i->control_pid = (pid_t) u;
2468 else if (streq(name, "ExecMainPID")) {
2470 i->main_pid = (pid_t) u;
2471 } else if (streq(name, "NAccepted"))
2473 else if (streq(name, "NConnections"))
2474 i->n_connections = u;
2479 case DBUS_TYPE_INT32: {
2482 dbus_message_iter_get_basic(iter, &j);
2484 if (streq(name, "ExecMainCode"))
2485 i->exit_code = (int) j;
2486 else if (streq(name, "ExecMainStatus"))
2487 i->exit_status = (int) j;
2492 case DBUS_TYPE_UINT64: {
2495 dbus_message_iter_get_basic(iter, &u);
2497 if (streq(name, "ExecMainStartTimestamp"))
2498 i->start_timestamp = (usec_t) u;
2499 else if (streq(name, "ExecMainExitTimestamp"))
2500 i->exit_timestamp = (usec_t) u;
2501 else if (streq(name, "ActiveEnterTimestamp"))
2502 i->active_enter_timestamp = (usec_t) u;
2503 else if (streq(name, "InactiveEnterTimestamp"))
2504 i->inactive_enter_timestamp = (usec_t) u;
2505 else if (streq(name, "InactiveExitTimestamp"))
2506 i->inactive_exit_timestamp = (usec_t) u;
2507 else if (streq(name, "InactiveExitTimestampMonotonic"))
2508 i->inactive_exit_timestamp_monotonic = (usec_t) u;
2509 else if (streq(name, "ActiveExitTimestamp"))
2510 i->active_exit_timestamp = (usec_t) u;
2511 else if (streq(name, "ConditionTimestamp"))
2512 i->condition_timestamp = (usec_t) u;
2517 case DBUS_TYPE_ARRAY: {
2519 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
2520 startswith(name, "Exec")) {
2521 DBusMessageIter sub;
2523 dbus_message_iter_recurse(iter, &sub);
2524 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2525 ExecStatusInfo *info;
2528 if (!(info = new0(ExecStatusInfo, 1)))
2531 if (!(info->name = strdup(name))) {
2536 if ((r = exec_status_info_deserialize(&sub, info)) < 0) {
2541 LIST_PREPEND(ExecStatusInfo, exec, i->exec, info);
2543 dbus_message_iter_next(&sub);
2550 case DBUS_TYPE_STRUCT: {
2552 if (streq(name, "LoadError")) {
2553 DBusMessageIter sub;
2554 const char *n, *message;
2557 dbus_message_iter_recurse(iter, &sub);
2559 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &n, true);
2563 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &message, false);
2567 if (!isempty(message))
2568 i->load_error = message;
2578 static int print_property(const char *name, DBusMessageIter *iter) {
2582 /* This is a low-level property printer, see
2583 * print_status_info() for the nicer output */
2585 if (arg_property && !strv_find(arg_property, name))
2588 switch (dbus_message_iter_get_arg_type(iter)) {
2590 case DBUS_TYPE_STRUCT: {
2591 DBusMessageIter sub;
2592 dbus_message_iter_recurse(iter, &sub);
2594 if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32 && streq(name, "Job")) {
2597 dbus_message_iter_get_basic(&sub, &u);
2600 printf("%s=%u\n", name, (unsigned) u);
2602 printf("%s=\n", name);
2605 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "Unit")) {
2608 dbus_message_iter_get_basic(&sub, &s);
2610 if (arg_all || s[0])
2611 printf("%s=%s\n", name, s);
2614 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "LoadError")) {
2615 const char *a = NULL, *b = NULL;
2617 if (bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &a, true) >= 0)
2618 bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &b, false);
2620 if (arg_all || !isempty(a) || !isempty(b))
2621 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
2629 case DBUS_TYPE_ARRAY:
2631 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "EnvironmentFiles")) {
2632 DBusMessageIter sub, sub2;
2634 dbus_message_iter_recurse(iter, &sub);
2635 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2639 dbus_message_iter_recurse(&sub, &sub2);
2641 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
2642 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) >= 0)
2643 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
2645 dbus_message_iter_next(&sub);
2650 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Paths")) {
2651 DBusMessageIter sub, sub2;
2653 dbus_message_iter_recurse(iter, &sub);
2654 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2655 const char *type, *path;
2657 dbus_message_iter_recurse(&sub, &sub2);
2659 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
2660 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
2661 printf("%s=%s\n", type, path);
2663 dbus_message_iter_next(&sub);
2668 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Timers")) {
2669 DBusMessageIter sub, sub2;
2671 dbus_message_iter_recurse(iter, &sub);
2672 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2674 uint64_t value, next_elapse;
2676 dbus_message_iter_recurse(&sub, &sub2);
2678 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &base, true) >= 0 &&
2679 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &value, true) >= 0 &&
2680 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &next_elapse, false) >= 0) {
2681 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
2683 printf("%s={ value=%s ; next_elapse=%s }\n",
2685 format_timespan(timespan1, sizeof(timespan1), value),
2686 format_timespan(timespan2, sizeof(timespan2), next_elapse));
2689 dbus_message_iter_next(&sub);
2694 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "ControlGroupAttributes")) {
2695 DBusMessageIter sub, sub2;
2697 dbus_message_iter_recurse(iter, &sub);
2698 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2699 const char *controller, *attr, *value;
2701 dbus_message_iter_recurse(&sub, &sub2);
2703 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &controller, true) >= 0 &&
2704 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &attr, true) >= 0 &&
2705 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &value, false) >= 0) {
2707 printf("ControlGroupAttribute={ controller=%s ; attribute=%s ; value=\"%s\" }\n",
2713 dbus_message_iter_next(&sub);
2718 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && startswith(name, "Exec")) {
2719 DBusMessageIter sub;
2721 dbus_message_iter_recurse(iter, &sub);
2722 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2723 ExecStatusInfo info;
2726 if (exec_status_info_deserialize(&sub, &info) >= 0) {
2727 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
2730 t = strv_join(info.argv, " ");
2732 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
2736 yes_no(info.ignore),
2737 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
2738 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
2739 (unsigned) info. pid,
2740 sigchld_code_to_string(info.code),
2742 info.code == CLD_EXITED ? "" : "/",
2743 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
2749 strv_free(info.argv);
2751 dbus_message_iter_next(&sub);
2760 if (generic_print_property(name, iter, arg_all) > 0)
2764 printf("%s=[unprintable]\n", name);
2769 static int show_one(const char *verb, DBusConnection *bus, const char *path, bool show_properties, bool *new_line) {
2770 DBusMessage *m = NULL, *reply = NULL;
2771 const char *interface = "";
2774 DBusMessageIter iter, sub, sub2, sub3;
2775 UnitStatusInfo info;
2783 dbus_error_init(&error);
2785 if (!(m = dbus_message_new_method_call(
2786 "org.freedesktop.systemd1",
2788 "org.freedesktop.DBus.Properties",
2790 log_error("Could not allocate message.");
2795 if (!dbus_message_append_args(m,
2796 DBUS_TYPE_STRING, &interface,
2797 DBUS_TYPE_INVALID)) {
2798 log_error("Could not append arguments to message.");
2803 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
2804 log_error("Failed to issue method call: %s", bus_error_message(&error));
2809 if (!dbus_message_iter_init(reply, &iter) ||
2810 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
2811 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
2812 log_error("Failed to parse reply.");
2817 dbus_message_iter_recurse(&iter, &sub);
2824 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
2827 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_DICT_ENTRY) {
2828 log_error("Failed to parse reply.");
2833 dbus_message_iter_recurse(&sub, &sub2);
2835 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0) {
2836 log_error("Failed to parse reply.");
2841 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
2842 log_error("Failed to parse reply.");
2847 dbus_message_iter_recurse(&sub2, &sub3);
2849 if (show_properties)
2850 r = print_property(name, &sub3);
2852 r = status_property(name, &sub3, &info);
2855 log_error("Failed to parse reply.");
2860 dbus_message_iter_next(&sub);
2865 if (!show_properties)
2866 print_status_info(&info);
2868 if (!streq_ptr(info.active_state, "active") &&
2869 !streq_ptr(info.active_state, "reloading") &&
2870 streq(verb, "status"))
2871 /* According to LSB: "program not running" */
2874 while ((p = info.exec)) {
2875 LIST_REMOVE(ExecStatusInfo, exec, info.exec, p);
2876 exec_status_info_free(p);
2881 dbus_message_unref(m);
2884 dbus_message_unref(reply);
2886 dbus_error_free(&error);
2891 static int show(DBusConnection *bus, char **args) {
2892 DBusMessage *m = NULL, *reply = NULL;
2895 bool show_properties, new_line = false;
2901 dbus_error_init(&error);
2903 show_properties = !streq(args[0], "status");
2905 if (show_properties)
2906 pager_open_if_enabled();
2908 if (show_properties && strv_length(args) <= 1) {
2909 /* If not argument is specified inspect the manager
2912 ret = show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line);
2916 STRV_FOREACH(name, args+1) {
2917 const char *path = NULL;
2920 if (safe_atou32(*name, &id) < 0) {
2922 /* Interpret as unit name */
2924 if (!(m = dbus_message_new_method_call(
2925 "org.freedesktop.systemd1",
2926 "/org/freedesktop/systemd1",
2927 "org.freedesktop.systemd1.Manager",
2929 log_error("Could not allocate message.");
2934 if (!dbus_message_append_args(m,
2935 DBUS_TYPE_STRING, name,
2936 DBUS_TYPE_INVALID)) {
2937 log_error("Could not append arguments to message.");
2942 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
2944 if (!dbus_error_has_name(&error, DBUS_ERROR_ACCESS_DENIED)) {
2945 log_error("Failed to issue method call: %s", bus_error_message(&error));
2950 dbus_error_free(&error);
2952 dbus_message_unref(m);
2953 if (!(m = dbus_message_new_method_call(
2954 "org.freedesktop.systemd1",
2955 "/org/freedesktop/systemd1",
2956 "org.freedesktop.systemd1.Manager",
2958 log_error("Could not allocate message.");
2963 if (!dbus_message_append_args(m,
2964 DBUS_TYPE_STRING, name,
2965 DBUS_TYPE_INVALID)) {
2966 log_error("Could not append arguments to message.");
2971 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
2972 log_error("Failed to issue method call: %s", bus_error_message(&error));
2974 if (dbus_error_has_name(&error, BUS_ERROR_NO_SUCH_UNIT))
2975 ret = 4; /* According to LSB: "program or service status is unknown" */
2982 } else if (show_properties) {
2984 /* Interpret as job id */
2986 if (!(m = dbus_message_new_method_call(
2987 "org.freedesktop.systemd1",
2988 "/org/freedesktop/systemd1",
2989 "org.freedesktop.systemd1.Manager",
2991 log_error("Could not allocate message.");
2996 if (!dbus_message_append_args(m,
2997 DBUS_TYPE_UINT32, &id,
2998 DBUS_TYPE_INVALID)) {
2999 log_error("Could not append arguments to message.");
3004 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3005 log_error("Failed to issue method call: %s", bus_error_message(&error));
3011 /* Interpret as PID */
3013 if (!(m = dbus_message_new_method_call(
3014 "org.freedesktop.systemd1",
3015 "/org/freedesktop/systemd1",
3016 "org.freedesktop.systemd1.Manager",
3018 log_error("Could not allocate message.");
3023 if (!dbus_message_append_args(m,
3024 DBUS_TYPE_UINT32, &id,
3025 DBUS_TYPE_INVALID)) {
3026 log_error("Could not append arguments to message.");
3031 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3032 log_error("Failed to issue method call: %s", bus_error_message(&error));
3038 if (!dbus_message_get_args(reply, &error,
3039 DBUS_TYPE_OBJECT_PATH, &path,
3040 DBUS_TYPE_INVALID)) {
3041 log_error("Failed to parse reply: %s", bus_error_message(&error));
3046 if ((r = show_one(args[0], bus, path, show_properties, &new_line)) != 0)
3049 dbus_message_unref(m);
3050 dbus_message_unref(reply);
3056 dbus_message_unref(m);
3059 dbus_message_unref(reply);
3061 dbus_error_free(&error);
3066 static int dump(DBusConnection *bus, char **args) {
3067 DBusMessage *m = NULL, *reply = NULL;
3072 dbus_error_init(&error);
3074 pager_open_if_enabled();
3076 if (!(m = dbus_message_new_method_call(
3077 "org.freedesktop.systemd1",
3078 "/org/freedesktop/systemd1",
3079 "org.freedesktop.systemd1.Manager",
3081 log_error("Could not allocate message.");
3085 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3086 log_error("Failed to issue method call: %s", bus_error_message(&error));
3091 if (!dbus_message_get_args(reply, &error,
3092 DBUS_TYPE_STRING, &text,
3093 DBUS_TYPE_INVALID)) {
3094 log_error("Failed to parse reply: %s", bus_error_message(&error));
3099 fputs(text, stdout);
3105 dbus_message_unref(m);
3108 dbus_message_unref(reply);
3110 dbus_error_free(&error);
3115 static int snapshot(DBusConnection *bus, char **args) {
3116 DBusMessage *m = NULL, *reply = NULL;
3119 const char *name = "", *path, *id;
3120 dbus_bool_t cleanup = FALSE;
3121 DBusMessageIter iter, sub;
3123 *interface = "org.freedesktop.systemd1.Unit",
3126 dbus_error_init(&error);
3128 if (!(m = dbus_message_new_method_call(
3129 "org.freedesktop.systemd1",
3130 "/org/freedesktop/systemd1",
3131 "org.freedesktop.systemd1.Manager",
3132 "CreateSnapshot"))) {
3133 log_error("Could not allocate message.");
3137 if (strv_length(args) > 1)
3140 if (!dbus_message_append_args(m,
3141 DBUS_TYPE_STRING, &name,
3142 DBUS_TYPE_BOOLEAN, &cleanup,
3143 DBUS_TYPE_INVALID)) {
3144 log_error("Could not append arguments to message.");
3149 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3150 log_error("Failed to issue method call: %s", bus_error_message(&error));
3155 if (!dbus_message_get_args(reply, &error,
3156 DBUS_TYPE_OBJECT_PATH, &path,
3157 DBUS_TYPE_INVALID)) {
3158 log_error("Failed to parse reply: %s", bus_error_message(&error));
3163 dbus_message_unref(m);
3164 if (!(m = dbus_message_new_method_call(
3165 "org.freedesktop.systemd1",
3167 "org.freedesktop.DBus.Properties",
3169 log_error("Could not allocate message.");
3173 if (!dbus_message_append_args(m,
3174 DBUS_TYPE_STRING, &interface,
3175 DBUS_TYPE_STRING, &property,
3176 DBUS_TYPE_INVALID)) {
3177 log_error("Could not append arguments to message.");
3182 dbus_message_unref(reply);
3183 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3184 log_error("Failed to issue method call: %s", bus_error_message(&error));
3189 if (!dbus_message_iter_init(reply, &iter) ||
3190 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3191 log_error("Failed to parse reply.");
3196 dbus_message_iter_recurse(&iter, &sub);
3198 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
3199 log_error("Failed to parse reply.");
3204 dbus_message_iter_get_basic(&sub, &id);
3212 dbus_message_unref(m);
3215 dbus_message_unref(reply);
3217 dbus_error_free(&error);
3222 static int delete_snapshot(DBusConnection *bus, char **args) {
3223 DBusMessage *m = NULL, *reply = NULL;
3231 dbus_error_init(&error);
3233 STRV_FOREACH(name, args+1) {
3234 const char *path = NULL;
3236 if (!(m = dbus_message_new_method_call(
3237 "org.freedesktop.systemd1",
3238 "/org/freedesktop/systemd1",
3239 "org.freedesktop.systemd1.Manager",
3241 log_error("Could not allocate message.");
3246 if (!dbus_message_append_args(m,
3247 DBUS_TYPE_STRING, name,
3248 DBUS_TYPE_INVALID)) {
3249 log_error("Could not append arguments to message.");
3254 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3255 log_error("Failed to issue method call: %s", bus_error_message(&error));
3260 if (!dbus_message_get_args(reply, &error,
3261 DBUS_TYPE_OBJECT_PATH, &path,
3262 DBUS_TYPE_INVALID)) {
3263 log_error("Failed to parse reply: %s", bus_error_message(&error));
3268 dbus_message_unref(m);
3269 if (!(m = dbus_message_new_method_call(
3270 "org.freedesktop.systemd1",
3272 "org.freedesktop.systemd1.Snapshot",
3274 log_error("Could not allocate message.");
3279 dbus_message_unref(reply);
3280 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3281 log_error("Failed to issue method call: %s", bus_error_message(&error));
3286 dbus_message_unref(m);
3287 dbus_message_unref(reply);
3295 dbus_message_unref(m);
3298 dbus_message_unref(reply);
3300 dbus_error_free(&error);
3305 static int daemon_reload(DBusConnection *bus, char **args) {
3306 DBusMessage *m = NULL, *reply = NULL;
3311 dbus_error_init(&error);
3313 if (arg_action == ACTION_RELOAD)
3315 else if (arg_action == ACTION_REEXEC)
3316 method = "Reexecute";
3318 assert(arg_action == ACTION_SYSTEMCTL);
3321 streq(args[0], "clear-jobs") ||
3322 streq(args[0], "cancel") ? "ClearJobs" :
3323 streq(args[0], "daemon-reexec") ? "Reexecute" :
3324 streq(args[0], "reset-failed") ? "ResetFailed" :
3325 streq(args[0], "halt") ? "Halt" :
3326 streq(args[0], "poweroff") ? "PowerOff" :
3327 streq(args[0], "reboot") ? "Reboot" :
3328 streq(args[0], "kexec") ? "KExec" :
3329 streq(args[0], "exit") ? "Exit" :
3330 /* "daemon-reload" */ "Reload";
3333 if (!(m = dbus_message_new_method_call(
3334 "org.freedesktop.systemd1",
3335 "/org/freedesktop/systemd1",
3336 "org.freedesktop.systemd1.Manager",
3338 log_error("Could not allocate message.");
3342 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3344 if (arg_action != ACTION_SYSTEMCTL && error_is_no_service(&error)) {
3345 /* There's always a fallback possible for
3346 * legacy actions. */
3351 if (streq(method, "Reexecute") && dbus_error_has_name(&error, DBUS_ERROR_NO_REPLY)) {
3352 /* On reexecution, we expect a disconnect, not
3358 log_error("Failed to issue method call: %s", bus_error_message(&error));
3367 dbus_message_unref(m);
3370 dbus_message_unref(reply);
3372 dbus_error_free(&error);
3377 static int reset_failed(DBusConnection *bus, char **args) {
3378 DBusMessage *m = NULL;
3384 dbus_error_init(&error);
3386 if (strv_length(args) <= 1)
3387 return daemon_reload(bus, args);
3389 STRV_FOREACH(name, args+1) {
3392 if (!(m = dbus_message_new_method_call(
3393 "org.freedesktop.systemd1",
3394 "/org/freedesktop/systemd1",
3395 "org.freedesktop.systemd1.Manager",
3396 "ResetFailedUnit"))) {
3397 log_error("Could not allocate message.");
3402 if (!dbus_message_append_args(m,
3403 DBUS_TYPE_STRING, name,
3404 DBUS_TYPE_INVALID)) {
3405 log_error("Could not append arguments to message.");
3410 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3411 log_error("Failed to issue method call: %s", bus_error_message(&error));
3416 dbus_message_unref(m);
3417 dbus_message_unref(reply);
3425 dbus_message_unref(m);
3427 dbus_error_free(&error);
3432 static int show_enviroment(DBusConnection *bus, char **args) {
3433 DBusMessage *m = NULL, *reply = NULL;
3435 DBusMessageIter iter, sub, sub2;
3438 *interface = "org.freedesktop.systemd1.Manager",
3439 *property = "Environment";
3441 dbus_error_init(&error);
3443 pager_open_if_enabled();
3445 if (!(m = dbus_message_new_method_call(
3446 "org.freedesktop.systemd1",
3447 "/org/freedesktop/systemd1",
3448 "org.freedesktop.DBus.Properties",
3450 log_error("Could not allocate message.");
3454 if (!dbus_message_append_args(m,
3455 DBUS_TYPE_STRING, &interface,
3456 DBUS_TYPE_STRING, &property,
3457 DBUS_TYPE_INVALID)) {
3458 log_error("Could not append arguments to message.");
3463 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3464 log_error("Failed to issue method call: %s", bus_error_message(&error));
3469 if (!dbus_message_iter_init(reply, &iter) ||
3470 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3471 log_error("Failed to parse reply.");
3476 dbus_message_iter_recurse(&iter, &sub);
3478 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_ARRAY ||
3479 dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_STRING) {
3480 log_error("Failed to parse reply.");
3485 dbus_message_iter_recurse(&sub, &sub2);
3487 while (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_INVALID) {
3490 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
3491 log_error("Failed to parse reply.");
3496 dbus_message_iter_get_basic(&sub2, &text);
3497 printf("%s\n", text);
3499 dbus_message_iter_next(&sub2);
3506 dbus_message_unref(m);
3509 dbus_message_unref(reply);
3511 dbus_error_free(&error);
3516 static int set_environment(DBusConnection *bus, char **args) {
3517 DBusMessage *m = NULL, *reply = NULL;
3521 DBusMessageIter iter, sub;
3524 dbus_error_init(&error);
3526 method = streq(args[0], "set-environment")
3528 : "UnsetEnvironment";
3530 if (!(m = dbus_message_new_method_call(
3531 "org.freedesktop.systemd1",
3532 "/org/freedesktop/systemd1",
3533 "org.freedesktop.systemd1.Manager",
3536 log_error("Could not allocate message.");
3540 dbus_message_iter_init_append(m, &iter);
3542 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub)) {
3543 log_error("Could not append arguments to message.");
3548 STRV_FOREACH(name, args+1)
3549 if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, name)) {
3550 log_error("Could not append arguments to message.");
3555 if (!dbus_message_iter_close_container(&iter, &sub)) {
3556 log_error("Could not append arguments to message.");
3561 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3562 log_error("Failed to issue method call: %s", bus_error_message(&error));
3571 dbus_message_unref(m);
3574 dbus_message_unref(reply);
3576 dbus_error_free(&error);
3581 static int enable_sysv_units(char **args) {
3584 #if defined (HAVE_SYSV_COMPAT) && (defined(TARGET_FEDORA) || defined(TARGET_MANDRIVA) || defined(TARGET_SUSE) || defined(TARGET_MEEGO) || defined(TARGET_ALTLINUX) || defined(TARGET_MAGEIA))
3585 const char *verb = args[0];
3586 unsigned f = 1, t = 1;
3589 if (arg_scope != UNIT_FILE_SYSTEM)
3592 if (!streq(verb, "enable") &&
3593 !streq(verb, "disable") &&
3594 !streq(verb, "is-enabled"))
3597 /* Processes all SysV units, and reshuffles the array so that
3598 * afterwards only the native units remain */
3601 r = lookup_paths_init(&paths, MANAGER_SYSTEM, false);
3607 for (f = 1; args[f]; f++) {
3610 bool found_native = false, found_sysv;
3612 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
3613 char **k, *l, *q = NULL;
3620 if (!endswith(name, ".service"))
3623 if (path_is_absolute(name))
3626 STRV_FOREACH(k, paths.unit_path) {
3629 if (!isempty(arg_root))
3630 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
3632 asprintf(&p, "%s/%s", *k, name);
3635 log_error("No memory");
3640 found_native = access(p, F_OK) >= 0;
3651 if (!isempty(arg_root))
3652 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
3654 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
3656 log_error("No memory");
3661 p[strlen(p) - sizeof(".service") + 1] = 0;
3662 found_sysv = access(p, F_OK) >= 0;
3669 /* Mark this entry, so that we don't try enabling it as native unit */
3670 args[f] = (char*) "";
3672 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
3674 if (!isempty(arg_root))
3675 argv[c++] = q = strappend("--root=", arg_root);
3677 argv[c++] = file_name_from_path(p);
3679 streq(verb, "enable") ? "on" :
3680 streq(verb, "disable") ? "off" : "--level=5";
3683 l = strv_join((char**)argv, " ");
3685 log_error("No memory.");
3692 log_info("Executing %s", l);
3697 log_error("Failed to fork: %m");
3702 } else if (pid == 0) {
3705 execv(argv[0], (char**) argv);
3706 _exit(EXIT_FAILURE);
3712 j = wait_for_terminate(pid, &status);
3714 log_error("Failed to wait for child: %s", strerror(-r));
3719 if (status.si_code == CLD_EXITED) {
3720 if (streq(verb, "is-enabled")) {
3721 if (status.si_status == 0) {
3730 } else if (status.si_status != 0) {
3741 lookup_paths_free(&paths);
3743 /* Drop all SysV units */
3744 for (f = 1, t = 1; args[f]; f++) {
3746 if (isempty(args[f]))
3749 args[t++] = args[f];
3758 static int enable_unit(DBusConnection *bus, char **args) {
3759 const char *verb = args[0];
3760 UnitFileChange *changes = NULL;
3761 unsigned n_changes = 0, i;
3762 int carries_install_info = -1;
3763 DBusMessage *m = NULL, *reply = NULL;
3767 r = enable_sysv_units(args);
3774 dbus_error_init(&error);
3776 if (!bus || avoid_bus()) {
3777 if (streq(verb, "enable")) {
3778 r = unit_file_enable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3779 carries_install_info = r;
3780 } else if (streq(verb, "disable"))
3781 r = unit_file_disable(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3782 else if (streq(verb, "reenable")) {
3783 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3784 carries_install_info = r;
3785 } else if (streq(verb, "link"))
3786 r = unit_file_link(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3787 else if (streq(verb, "preset")) {
3788 r = unit_file_preset(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3789 carries_install_info = r;
3790 } else if (streq(verb, "mask"))
3791 r = unit_file_mask(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3792 else if (streq(verb, "unmask"))
3793 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3795 assert_not_reached("Unknown verb");
3798 log_error("Operation failed: %s", strerror(-r));
3803 for (i = 0; i < n_changes; i++) {
3804 if (changes[i].type == UNIT_FILE_SYMLINK)
3805 log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
3807 log_info("rm '%s'", changes[i].path);
3813 bool send_force = true, expect_carries_install_info = false;
3815 DBusMessageIter iter, sub, sub2;
3817 if (streq(verb, "enable")) {
3818 method = "EnableUnitFiles";
3819 expect_carries_install_info = true;
3820 } else if (streq(verb, "disable")) {
3821 method = "DisableUnitFiles";
3823 } else if (streq(verb, "reenable")) {
3824 method = "ReenableUnitFiles";
3825 expect_carries_install_info = true;
3826 } else if (streq(verb, "link"))
3827 method = "LinkUnitFiles";
3828 else if (streq(verb, "preset")) {
3829 method = "PresetUnitFiles";
3830 expect_carries_install_info = true;
3831 } else if (streq(verb, "mask"))
3832 method = "MaskUnitFiles";
3833 else if (streq(verb, "unmask")) {
3834 method = "UnmaskUnitFiles";
3837 assert_not_reached("Unknown verb");
3839 m = dbus_message_new_method_call(
3840 "org.freedesktop.systemd1",
3841 "/org/freedesktop/systemd1",
3842 "org.freedesktop.systemd1.Manager",
3845 log_error("Out of memory");
3850 dbus_message_iter_init_append(m, &iter);
3852 r = bus_append_strv_iter(&iter, args+1);
3854 log_error("Failed to append unit files.");
3859 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &a)) {
3860 log_error("Failed to append runtime boolean.");
3868 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b)) {
3869 log_error("Failed to append force boolean.");
3875 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3877 log_error("Failed to issue method call: %s", bus_error_message(&error));
3882 if (!dbus_message_iter_init(reply, &iter)) {
3883 log_error("Failed to initialize iterator.");
3887 if (expect_carries_install_info) {
3888 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &b, true);
3890 log_error("Failed to parse reply.");
3894 carries_install_info = b;
3897 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3898 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
3899 log_error("Failed to parse reply.");
3904 dbus_message_iter_recurse(&iter, &sub);
3905 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
3906 const char *type, *path, *source;
3908 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
3909 log_error("Failed to parse reply.");
3914 dbus_message_iter_recurse(&sub, &sub2);
3916 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
3917 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
3918 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &source, false) < 0) {
3919 log_error("Failed to parse reply.");
3925 if (streq(type, "symlink"))
3926 log_info("ln -s '%s' '%s'", source, path);
3928 log_info("rm '%s'", path);
3931 dbus_message_iter_next(&sub);
3934 /* Try to reload if enabeld */
3936 r = daemon_reload(bus, args);
3939 if (carries_install_info == 0)
3940 log_warning("Warning: unit files do not carry install information. No operation executed.");
3944 dbus_message_unref(m);
3947 dbus_message_unref(reply);
3949 unit_file_changes_free(changes, n_changes);
3951 dbus_error_free(&error);
3955 static int unit_is_enabled(DBusConnection *bus, char **args) {
3958 DBusMessage *m = NULL, *reply = NULL;
3962 dbus_error_init(&error);
3964 r = enable_sysv_units(args);
3970 if (!bus || avoid_bus()) {
3972 STRV_FOREACH(name, args+1) {
3973 UnitFileState state;
3975 state = unit_file_get_state(arg_scope, arg_root, *name);
3981 if (state == UNIT_FILE_ENABLED ||
3982 state == UNIT_FILE_ENABLED_RUNTIME ||
3983 state == UNIT_FILE_STATIC)
3987 puts(unit_file_state_to_string(state));
3991 STRV_FOREACH(name, args+1) {
3994 m = dbus_message_new_method_call(
3995 "org.freedesktop.systemd1",
3996 "/org/freedesktop/systemd1",
3997 "org.freedesktop.systemd1.Manager",
3998 "GetUnitFileState");
4000 log_error("Out of memory");
4005 if (!dbus_message_append_args(m,
4006 DBUS_TYPE_STRING, name,
4007 DBUS_TYPE_INVALID)) {
4008 log_error("Could not append arguments to message.");
4013 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
4015 log_error("Failed to issue method call: %s", bus_error_message(&error));
4020 if (!dbus_message_get_args(reply, &error,
4021 DBUS_TYPE_STRING, &s,
4022 DBUS_TYPE_INVALID)) {
4023 log_error("Failed to parse reply: %s", bus_error_message(&error));
4028 dbus_message_unref(m);
4029 dbus_message_unref(reply);
4032 if (streq(s, "enabled") ||
4033 streq(s, "enabled-runtime") ||
4042 r = enabled ? 0 : 1;
4046 dbus_message_unref(m);
4049 dbus_message_unref(reply);
4051 dbus_error_free(&error);
4055 static int systemctl_help(void) {
4057 pager_open_if_enabled();
4059 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
4060 "Query or send control commands to the systemd manager.\n\n"
4061 " -h --help Show this help\n"
4062 " --version Show package version\n"
4063 " -t --type=TYPE List only units of a particular type\n"
4064 " -p --property=NAME Show only properties by this name\n"
4065 " -a --all Show all units/properties, including dead/empty ones\n"
4066 " --failed Show only failed units\n"
4067 " --full Don't ellipsize unit names on output\n"
4068 " --fail When queueing a new job, fail if conflicting jobs are\n"
4070 " --ignore-dependencies\n"
4071 " When queueing a new job, ignore all its dependencies\n"
4072 " --kill-who=WHO Who to send signal to\n"
4073 " -s --signal=SIGNAL Which signal to send\n"
4074 " -H --host=[USER@]HOST\n"
4075 " Show information for remote host\n"
4076 " -P --privileged Acquire privileges before execution\n"
4077 " -q --quiet Suppress output\n"
4078 " --no-block Do not wait until operation finished\n"
4079 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4080 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
4082 " --no-legend Do not print a legend (column headers and hints)\n"
4083 " --no-pager Do not pipe output into a pager\n"
4084 " --no-ask-password\n"
4085 " Do not ask for system passwords\n"
4086 " --order When generating graph for dot, show only order\n"
4087 " --require When generating graph for dot, show only requirement\n"
4088 " --system Connect to system manager\n"
4089 " --user Connect to user service manager\n"
4090 " --global Enable/disable unit files globally\n"
4091 " -f --force When enabling unit files, override existing symlinks\n"
4092 " When shutting down, execute action immediately\n"
4093 " --root=PATH Enable unit files in the specified root directory\n"
4094 " --runtime Enable unit files only temporarily until next reboot\n"
4095 " -n --lines=INTEGER Journal entries to show\n"
4096 " --follow Follow journal\n"
4097 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
4098 " verbose, export, json, cat)\n\n"
4100 " list-units List loaded units\n"
4101 " start [NAME...] Start (activate) one or more units\n"
4102 " stop [NAME...] Stop (deactivate) one or more units\n"
4103 " reload [NAME...] Reload one or more units\n"
4104 " restart [NAME...] Start or restart one or more units\n"
4105 " try-restart [NAME...] Restart one or more units if active\n"
4106 " reload-or-restart [NAME...] Reload one or more units is possible,\n"
4107 " otherwise start or restart\n"
4108 " reload-or-try-restart [NAME...] Reload one or more units is possible,\n"
4109 " otherwise restart if active\n"
4110 " isolate [NAME] Start one unit and stop all others\n"
4111 " kill [NAME...] Send signal to processes of a unit\n"
4112 " is-active [NAME...] Check whether units are active\n"
4113 " status [NAME...|PID...] Show runtime status of one or more units\n"
4114 " show [NAME...|JOB...] Show properties of one or more\n"
4115 " units/jobs or the manager\n"
4116 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
4118 " load [NAME...] Load one or more units\n\n"
4119 "Unit File Commands:\n"
4120 " list-unit-files List installed unit files\n"
4121 " enable [NAME...] Enable one or more unit files\n"
4122 " disable [NAME...] Disable one or more unit files\n"
4123 " reenable [NAME...] Reenable one or more unit files\n"
4124 " preset [NAME...] Enable/disable one or more unit files\n"
4125 " based on preset configuration\n"
4126 " mask [NAME...] Mask one or more units\n"
4127 " unmask [NAME...] Unmask one or more units\n"
4128 " link [PATH...] Link one or more units files into\n"
4129 " the search path\n"
4130 " is-enabled [NAME...] Check whether unit files are enabled\n\n"
4132 " list-jobs List jobs\n"
4133 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
4134 "Status Commands:\n"
4135 " dump Dump server status\n"
4136 " dot Dump dependency graph for dot(1)\n\n"
4137 "Snapshot Commands:\n"
4138 " snapshot [NAME] Create a snapshot\n"
4139 " delete [NAME...] Remove one or more snapshots\n\n"
4140 "Environment Commands:\n"
4141 " show-environment Dump environment\n"
4142 " set-environment [NAME=VALUE...] Set one or more environment variables\n"
4143 " unset-environment [NAME...] Unset one or more environment variables\n\n"
4144 "Manager Lifecycle Commands:\n"
4145 " daemon-reload Reload systemd manager configuration\n"
4146 " daemon-reexec Reexecute systemd manager\n\n"
4147 "System Commands:\n"
4148 " default Enter system default mode\n"
4149 " rescue Enter system rescue mode\n"
4150 " emergency Enter system emergency mode\n"
4151 " halt Shut down and halt the system\n"
4152 " poweroff Shut down and power-off the system\n"
4153 " reboot Shut down and reboot the system\n"
4154 " kexec Shut down and reboot the system with kexec\n"
4155 " exit Ask for user instance termination\n",
4156 program_invocation_short_name);
4161 static int halt_help(void) {
4163 printf("%s [OPTIONS...]\n\n"
4164 "%s the system.\n\n"
4165 " --help Show this help\n"
4166 " --halt Halt the machine\n"
4167 " -p --poweroff Switch off the machine\n"
4168 " --reboot Reboot the machine\n"
4169 " -f --force Force immediate halt/power-off/reboot\n"
4170 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
4171 " -d --no-wtmp Don't write wtmp record\n"
4172 " -n --no-sync Don't sync before halt/power-off/reboot\n"
4173 " --no-wall Don't send wall message before halt/power-off/reboot\n",
4174 program_invocation_short_name,
4175 arg_action == ACTION_REBOOT ? "Reboot" :
4176 arg_action == ACTION_POWEROFF ? "Power off" :
4182 static int shutdown_help(void) {
4184 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
4185 "Shut down the system.\n\n"
4186 " --help Show this help\n"
4187 " -H --halt Halt the machine\n"
4188 " -P --poweroff Power-off the machine\n"
4189 " -r --reboot Reboot the machine\n"
4190 " -h Equivalent to --poweroff, overriden by --halt\n"
4191 " -k Don't halt/power-off/reboot, just send warnings\n"
4192 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4193 " -c Cancel a pending shutdown\n",
4194 program_invocation_short_name);
4199 static int telinit_help(void) {
4201 printf("%s [OPTIONS...] {COMMAND}\n\n"
4202 "Send control commands to the init daemon.\n\n"
4203 " --help Show this help\n"
4204 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
4206 " 0 Power-off the machine\n"
4207 " 6 Reboot the machine\n"
4208 " 2, 3, 4, 5 Start runlevelX.target unit\n"
4209 " 1, s, S Enter rescue mode\n"
4210 " q, Q Reload init daemon configuration\n"
4211 " u, U Reexecute init daemon\n",
4212 program_invocation_short_name);
4217 static int runlevel_help(void) {
4219 printf("%s [OPTIONS...]\n\n"
4220 "Prints the previous and current runlevel of the init system.\n\n"
4221 " --help Show this help\n",
4222 program_invocation_short_name);
4227 static int systemctl_parse_argv(int argc, char *argv[]) {
4231 ARG_IGNORE_DEPENDENCIES,
4247 ARG_NO_ASK_PASSWORD,
4254 static const struct option options[] = {
4255 { "help", no_argument, NULL, 'h' },
4256 { "version", no_argument, NULL, ARG_VERSION },
4257 { "type", required_argument, NULL, 't' },
4258 { "property", required_argument, NULL, 'p' },
4259 { "all", no_argument, NULL, 'a' },
4260 { "failed", no_argument, NULL, ARG_FAILED },
4261 { "full", no_argument, NULL, ARG_FULL },
4262 { "fail", no_argument, NULL, ARG_FAIL },
4263 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
4264 { "user", no_argument, NULL, ARG_USER },
4265 { "system", no_argument, NULL, ARG_SYSTEM },
4266 { "global", no_argument, NULL, ARG_GLOBAL },
4267 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
4268 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
4269 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
4270 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4271 { "quiet", no_argument, NULL, 'q' },
4272 { "order", no_argument, NULL, ARG_ORDER },
4273 { "require", no_argument, NULL, ARG_REQUIRE },
4274 { "root", required_argument, NULL, ARG_ROOT },
4275 { "force", no_argument, NULL, ARG_FORCE },
4276 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
4277 { "kill-mode", required_argument, NULL, ARG_KILL_MODE }, /* undocumented on purpose */
4278 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
4279 { "signal", required_argument, NULL, 's' },
4280 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
4281 { "host", required_argument, NULL, 'H' },
4282 { "privileged",no_argument, NULL, 'P' },
4283 { "runtime", no_argument, NULL, ARG_RUNTIME },
4284 { "lines", required_argument, NULL, 'n' },
4285 { "follow", no_argument, NULL, ARG_FOLLOW },
4286 { "output", required_argument, NULL, 'o' },
4287 { NULL, 0, NULL, 0 }
4295 /* Only when running as systemctl we ask for passwords */
4296 arg_ask_password = true;
4298 while ((c = getopt_long(argc, argv, "ht:p:aqfs:H:Pn:o:", options, NULL)) >= 0) {
4307 puts(PACKAGE_STRING);
4309 puts(SYSTEMD_FEATURES);
4319 if (!(l = strv_append(arg_property, optarg)))
4322 strv_free(arg_property);
4325 /* If the user asked for a particular
4326 * property, show it to him, even if it is
4337 arg_job_mode = "fail";
4340 case ARG_IGNORE_DEPENDENCIES:
4341 arg_job_mode = "ignore-dependencies";
4345 arg_scope = UNIT_FILE_USER;
4349 arg_scope = UNIT_FILE_SYSTEM;
4353 arg_scope = UNIT_FILE_GLOBAL;
4357 arg_no_block = true;
4361 arg_no_legend = true;
4365 arg_no_pager = true;
4373 arg_dot = DOT_ORDER;
4377 arg_dot = DOT_REQUIRE;
4405 /* -f is short for both --follow and --force! */
4411 arg_no_reload = true;
4415 arg_kill_who = optarg;
4419 arg_kill_mode = optarg;
4423 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
4424 log_error("Failed to parse signal string %s.", optarg);
4429 case ARG_NO_ASK_PASSWORD:
4430 arg_ask_password = false;
4434 arg_transport = TRANSPORT_POLKIT;
4438 arg_transport = TRANSPORT_SSH;
4447 if (safe_atou(optarg, &arg_lines) < 0) {
4448 log_error("Failed to parse lines '%s'", optarg);
4454 arg_output = output_mode_from_string(optarg);
4455 if (arg_output < 0) {
4456 log_error("Unknown output '%s'.", optarg);
4465 log_error("Unknown option code %c", c);
4470 if (arg_transport != TRANSPORT_NORMAL && arg_scope != UNIT_FILE_SYSTEM) {
4471 log_error("Cannot access user instance remotely.");
4478 static int halt_parse_argv(int argc, char *argv[]) {
4487 static const struct option options[] = {
4488 { "help", no_argument, NULL, ARG_HELP },
4489 { "halt", no_argument, NULL, ARG_HALT },
4490 { "poweroff", no_argument, NULL, 'p' },
4491 { "reboot", no_argument, NULL, ARG_REBOOT },
4492 { "force", no_argument, NULL, 'f' },
4493 { "wtmp-only", no_argument, NULL, 'w' },
4494 { "no-wtmp", no_argument, NULL, 'd' },
4495 { "no-sync", no_argument, NULL, 'n' },
4496 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4497 { NULL, 0, NULL, 0 }
4505 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
4506 if (runlevel == '0' || runlevel == '6')
4507 arg_immediate = true;
4509 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
4517 arg_action = ACTION_HALT;
4521 if (arg_action != ACTION_REBOOT)
4522 arg_action = ACTION_POWEROFF;
4526 arg_action = ACTION_REBOOT;
4530 arg_immediate = true;
4551 /* Compatibility nops */
4558 log_error("Unknown option code %c", c);
4563 if (optind < argc) {
4564 log_error("Too many arguments.");
4571 static int parse_time_spec(const char *t, usec_t *_u) {
4575 if (streq(t, "now"))
4577 else if (!strchr(t, ':')) {
4580 if (safe_atou64(t, &u) < 0)
4583 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
4592 hour = strtol(t, &e, 10);
4593 if (errno != 0 || *e != ':' || hour < 0 || hour > 23)
4596 minute = strtol(e+1, &e, 10);
4597 if (errno != 0 || *e != 0 || minute < 0 || minute > 59)
4600 n = now(CLOCK_REALTIME);
4601 s = (time_t) (n / USEC_PER_SEC);
4604 assert_se(localtime_r(&s, &tm));
4606 tm.tm_hour = (int) hour;
4607 tm.tm_min = (int) minute;
4610 assert_se(s = mktime(&tm));
4612 *_u = (usec_t) s * USEC_PER_SEC;
4615 *_u += USEC_PER_DAY;
4621 static int shutdown_parse_argv(int argc, char *argv[]) {
4628 static const struct option options[] = {
4629 { "help", no_argument, NULL, ARG_HELP },
4630 { "halt", no_argument, NULL, 'H' },
4631 { "poweroff", no_argument, NULL, 'P' },
4632 { "reboot", no_argument, NULL, 'r' },
4633 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4634 { NULL, 0, NULL, 0 }
4642 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
4650 arg_action = ACTION_HALT;
4654 arg_action = ACTION_POWEROFF;
4659 arg_action = ACTION_KEXEC;
4661 arg_action = ACTION_REBOOT;
4665 if (arg_action != ACTION_HALT)
4666 arg_action = ACTION_POWEROFF;
4679 /* Compatibility nops */
4683 arg_action = ACTION_CANCEL_SHUTDOWN;
4690 log_error("Unknown option code %c", c);
4695 if (argc > optind) {
4696 if ((r = parse_time_spec(argv[optind], &arg_when)) < 0) {
4697 log_error("Failed to parse time specification: %s", argv[optind]);
4701 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
4703 /* We skip the time argument */
4704 if (argc > optind + 1)
4705 arg_wall = argv + optind + 1;
4712 static int telinit_parse_argv(int argc, char *argv[]) {
4719 static const struct option options[] = {
4720 { "help", no_argument, NULL, ARG_HELP },
4721 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4722 { NULL, 0, NULL, 0 }
4725 static const struct {
4729 { '0', ACTION_POWEROFF },
4730 { '6', ACTION_REBOOT },
4731 { '1', ACTION_RESCUE },
4732 { '2', ACTION_RUNLEVEL2 },
4733 { '3', ACTION_RUNLEVEL3 },
4734 { '4', ACTION_RUNLEVEL4 },
4735 { '5', ACTION_RUNLEVEL5 },
4736 { 's', ACTION_RESCUE },
4737 { 'S', ACTION_RESCUE },
4738 { 'q', ACTION_RELOAD },
4739 { 'Q', ACTION_RELOAD },
4740 { 'u', ACTION_REEXEC },
4741 { 'U', ACTION_REEXEC }
4750 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4765 log_error("Unknown option code %c", c);
4770 if (optind >= argc) {
4775 if (optind + 1 < argc) {
4776 log_error("Too many arguments.");
4780 if (strlen(argv[optind]) != 1) {
4781 log_error("Expected single character argument.");
4785 for (i = 0; i < ELEMENTSOF(table); i++)
4786 if (table[i].from == argv[optind][0])
4789 if (i >= ELEMENTSOF(table)) {
4790 log_error("Unknown command %s.", argv[optind]);
4794 arg_action = table[i].to;
4801 static int runlevel_parse_argv(int argc, char *argv[]) {
4807 static const struct option options[] = {
4808 { "help", no_argument, NULL, ARG_HELP },
4809 { NULL, 0, NULL, 0 }
4817 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4828 log_error("Unknown option code %c", c);
4833 if (optind < argc) {
4834 log_error("Too many arguments.");
4841 static int parse_argv(int argc, char *argv[]) {
4845 if (program_invocation_short_name) {
4847 if (strstr(program_invocation_short_name, "halt")) {
4848 arg_action = ACTION_HALT;
4849 return halt_parse_argv(argc, argv);
4850 } else if (strstr(program_invocation_short_name, "poweroff")) {
4851 arg_action = ACTION_POWEROFF;
4852 return halt_parse_argv(argc, argv);
4853 } else if (strstr(program_invocation_short_name, "reboot")) {
4855 arg_action = ACTION_KEXEC;
4857 arg_action = ACTION_REBOOT;
4858 return halt_parse_argv(argc, argv);
4859 } else if (strstr(program_invocation_short_name, "shutdown")) {
4860 arg_action = ACTION_POWEROFF;
4861 return shutdown_parse_argv(argc, argv);
4862 } else if (strstr(program_invocation_short_name, "init")) {
4864 if (sd_booted() > 0) {
4865 arg_action = ACTION_INVALID;
4866 return telinit_parse_argv(argc, argv);
4868 /* Hmm, so some other init system is
4869 * running, we need to forward this
4870 * request to it. For now we simply
4871 * guess that it is Upstart. */
4873 execv("/lib/upstart/telinit", argv);
4875 log_error("Couldn't find an alternative telinit implementation to spawn.");
4879 } else if (strstr(program_invocation_short_name, "runlevel")) {
4880 arg_action = ACTION_RUNLEVEL;
4881 return runlevel_parse_argv(argc, argv);
4885 arg_action = ACTION_SYSTEMCTL;
4886 return systemctl_parse_argv(argc, argv);
4889 static int action_to_runlevel(void) {
4891 static const char table[_ACTION_MAX] = {
4892 [ACTION_HALT] = '0',
4893 [ACTION_POWEROFF] = '0',
4894 [ACTION_REBOOT] = '6',
4895 [ACTION_RUNLEVEL2] = '2',
4896 [ACTION_RUNLEVEL3] = '3',
4897 [ACTION_RUNLEVEL4] = '4',
4898 [ACTION_RUNLEVEL5] = '5',
4899 [ACTION_RESCUE] = '1'
4902 assert(arg_action < _ACTION_MAX);
4904 return table[arg_action];
4907 static int talk_upstart(void) {
4908 DBusMessage *m = NULL, *reply = NULL;
4910 int previous, rl, r;
4912 env1_buf[] = "RUNLEVEL=X",
4913 env2_buf[] = "PREVLEVEL=X";
4914 char *env1 = env1_buf, *env2 = env2_buf;
4915 const char *emit = "runlevel";
4916 dbus_bool_t b_false = FALSE;
4917 DBusMessageIter iter, sub;
4918 DBusConnection *bus;
4920 dbus_error_init(&error);
4922 if (!(rl = action_to_runlevel()))
4925 if (utmp_get_runlevel(&previous, NULL) < 0)
4928 if (!(bus = dbus_connection_open_private("unix:abstract=/com/ubuntu/upstart", &error))) {
4929 if (dbus_error_has_name(&error, DBUS_ERROR_NO_SERVER)) {
4934 log_error("Failed to connect to Upstart bus: %s", bus_error_message(&error));
4939 if ((r = bus_check_peercred(bus)) < 0) {
4940 log_error("Failed to verify owner of bus.");
4944 if (!(m = dbus_message_new_method_call(
4945 "com.ubuntu.Upstart",
4946 "/com/ubuntu/Upstart",
4947 "com.ubuntu.Upstart0_6",
4950 log_error("Could not allocate message.");
4955 dbus_message_iter_init_append(m, &iter);
4957 env1_buf[sizeof(env1_buf)-2] = rl;
4958 env2_buf[sizeof(env2_buf)-2] = previous;
4960 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &emit) ||
4961 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub) ||
4962 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env1) ||
4963 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env2) ||
4964 !dbus_message_iter_close_container(&iter, &sub) ||
4965 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b_false)) {
4966 log_error("Could not append arguments to message.");
4971 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
4973 if (error_is_no_service(&error)) {
4978 log_error("Failed to issue method call: %s", bus_error_message(&error));
4987 dbus_message_unref(m);
4990 dbus_message_unref(reply);
4993 dbus_connection_flush(bus);
4994 dbus_connection_close(bus);
4995 dbus_connection_unref(bus);
4998 dbus_error_free(&error);
5003 static int talk_initctl(void) {
5004 struct init_request request;
5008 if (!(rl = action_to_runlevel()))
5012 request.magic = INIT_MAGIC;
5013 request.sleeptime = 0;
5014 request.cmd = INIT_CMD_RUNLVL;
5015 request.runlevel = rl;
5017 if ((fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY)) < 0) {
5019 if (errno == ENOENT)
5022 log_error("Failed to open "INIT_FIFO": %m");
5027 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
5028 close_nointr_nofail(fd);
5031 log_error("Failed to write to "INIT_FIFO": %m");
5032 return errno ? -errno : -EIO;
5038 static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
5040 static const struct {
5048 int (* const dispatch)(DBusConnection *bus, char **args);
5050 { "list-units", LESS, 1, list_units },
5051 { "list-unit-files", EQUAL, 1, list_unit_files },
5052 { "list-jobs", EQUAL, 1, list_jobs },
5053 { "clear-jobs", EQUAL, 1, daemon_reload },
5054 { "load", MORE, 2, load_unit },
5055 { "cancel", MORE, 2, cancel_job },
5056 { "start", MORE, 2, start_unit },
5057 { "stop", MORE, 2, start_unit },
5058 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5059 { "reload", MORE, 2, start_unit },
5060 { "restart", MORE, 2, start_unit },
5061 { "try-restart", MORE, 2, start_unit },
5062 { "reload-or-restart", MORE, 2, start_unit },
5063 { "reload-or-try-restart", MORE, 2, start_unit },
5064 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
5065 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5066 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
5067 { "isolate", EQUAL, 2, start_unit },
5068 { "kill", MORE, 2, kill_unit },
5069 { "is-active", MORE, 2, check_unit },
5070 { "check", MORE, 2, check_unit },
5071 { "show", MORE, 1, show },
5072 { "status", MORE, 2, show },
5073 { "dump", EQUAL, 1, dump },
5074 { "dot", EQUAL, 1, dot },
5075 { "snapshot", LESS, 2, snapshot },
5076 { "delete", MORE, 2, delete_snapshot },
5077 { "daemon-reload", EQUAL, 1, daemon_reload },
5078 { "daemon-reexec", EQUAL, 1, daemon_reload },
5079 { "show-environment", EQUAL, 1, show_enviroment },
5080 { "set-environment", MORE, 2, set_environment },
5081 { "unset-environment", MORE, 2, set_environment },
5082 { "halt", EQUAL, 1, start_special },
5083 { "poweroff", EQUAL, 1, start_special },
5084 { "reboot", EQUAL, 1, start_special },
5085 { "kexec", EQUAL, 1, start_special },
5086 { "default", EQUAL, 1, start_special },
5087 { "rescue", EQUAL, 1, start_special },
5088 { "emergency", EQUAL, 1, start_special },
5089 { "exit", EQUAL, 1, start_special },
5090 { "reset-failed", MORE, 1, reset_failed },
5091 { "enable", MORE, 2, enable_unit },
5092 { "disable", MORE, 2, enable_unit },
5093 { "is-enabled", MORE, 2, unit_is_enabled },
5094 { "reenable", MORE, 2, enable_unit },
5095 { "preset", MORE, 2, enable_unit },
5096 { "mask", MORE, 2, enable_unit },
5097 { "unmask", MORE, 2, enable_unit },
5098 { "link", MORE, 2, enable_unit }
5108 left = argc - optind;
5111 /* Special rule: no arguments means "list-units" */
5114 if (streq(argv[optind], "help")) {
5119 for (i = 0; i < ELEMENTSOF(verbs); i++)
5120 if (streq(argv[optind], verbs[i].verb))
5123 if (i >= ELEMENTSOF(verbs)) {
5124 log_error("Unknown operation %s", argv[optind]);
5129 switch (verbs[i].argc_cmp) {
5132 if (left != verbs[i].argc) {
5133 log_error("Invalid number of arguments.");
5140 if (left < verbs[i].argc) {
5141 log_error("Too few arguments.");
5148 if (left > verbs[i].argc) {
5149 log_error("Too many arguments.");
5156 assert_not_reached("Unknown comparison operator.");
5159 /* Require a bus connection for all operations but
5161 if (!streq(verbs[i].verb, "enable") &&
5162 !streq(verbs[i].verb, "disable") &&
5163 !streq(verbs[i].verb, "is-enabled") &&
5164 !streq(verbs[i].verb, "list-unit-files") &&
5165 !streq(verbs[i].verb, "reenable") &&
5166 !streq(verbs[i].verb, "preset") &&
5167 !streq(verbs[i].verb, "mask") &&
5168 !streq(verbs[i].verb, "unmask") &&
5169 !streq(verbs[i].verb, "link")) {
5171 if (running_in_chroot() > 0) {
5172 log_info("Running in chroot, ignoring request.");
5177 log_error("Failed to get D-Bus connection: %s",
5178 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5184 if (!bus && !avoid_bus()) {
5185 log_error("Failed to get D-Bus connection: %s",
5186 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5191 return verbs[i].dispatch(bus, argv + optind);
5194 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
5196 struct msghdr msghdr;
5198 union sockaddr_union sockaddr;
5199 struct shutdownd_command c;
5204 c.dry_run = dry_run;
5208 strncpy(c.wall_message, message, sizeof(c.wall_message));
5210 if ((fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0)) < 0)
5214 sockaddr.sa.sa_family = AF_UNIX;
5215 sockaddr.un.sun_path[0] = 0;
5216 strncpy(sockaddr.un.sun_path, "/run/systemd/shutdownd", sizeof(sockaddr.un.sun_path));
5219 iovec.iov_base = (char*) &c;
5220 iovec.iov_len = sizeof(c);
5223 msghdr.msg_name = &sockaddr;
5224 msghdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + sizeof("/run/systemd/shutdownd") - 1;
5226 msghdr.msg_iov = &iovec;
5227 msghdr.msg_iovlen = 1;
5229 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0) {
5230 close_nointr_nofail(fd);
5234 close_nointr_nofail(fd);
5238 static int reload_with_fallback(DBusConnection *bus) {
5241 /* First, try systemd via D-Bus. */
5242 if (daemon_reload(bus, NULL) >= 0)
5246 /* Nothing else worked, so let's try signals */
5247 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
5249 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
5250 log_error("kill() failed: %m");
5257 static int start_with_fallback(DBusConnection *bus) {
5260 /* First, try systemd via D-Bus. */
5261 if (start_unit(bus, NULL) >= 0)
5265 /* Hmm, talking to systemd via D-Bus didn't work. Then
5266 * let's try to talk to Upstart via D-Bus. */
5267 if (talk_upstart() > 0)
5270 /* Nothing else worked, so let's try
5272 if (talk_initctl() > 0)
5275 log_error("Failed to talk to init daemon.");
5279 warn_wall(arg_action);
5283 static void halt_now(enum action a) {
5285 /* Make sure C-A-D is handled by the kernel from this
5287 reboot(RB_ENABLE_CAD);
5292 log_info("Halting.");
5293 reboot(RB_HALT_SYSTEM);
5296 case ACTION_POWEROFF:
5297 log_info("Powering off.");
5298 reboot(RB_POWER_OFF);
5302 log_info("Rebooting.");
5303 reboot(RB_AUTOBOOT);
5307 assert_not_reached("Unknown halt action.");
5310 assert_not_reached("Uh? This shouldn't happen.");
5313 static int halt_main(DBusConnection *bus) {
5316 if (geteuid() != 0) {
5317 if (arg_action == ACTION_POWEROFF ||
5318 arg_action == ACTION_REBOOT) {
5319 r = reboot_with_logind(bus, arg_action);
5324 log_error("Must be root.");
5330 char date[FORMAT_TIMESTAMP_MAX];
5332 m = strv_join(arg_wall, " ");
5333 r = send_shutdownd(arg_when,
5334 arg_action == ACTION_HALT ? 'H' :
5335 arg_action == ACTION_POWEROFF ? 'P' :
5343 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
5345 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
5346 format_timestamp(date, sizeof(date), arg_when));
5351 if (!arg_dry && !arg_immediate)
5352 return start_with_fallback(bus);
5355 if (sd_booted() > 0)
5356 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
5357 else if ((r = utmp_put_shutdown()) < 0)
5358 log_warning("Failed to write utmp record: %s", strerror(-r));
5367 halt_now(arg_action);
5368 /* We should never reach this. */
5372 static int runlevel_main(void) {
5373 int r, runlevel, previous;
5375 r = utmp_get_runlevel(&runlevel, &previous);
5382 previous <= 0 ? 'N' : previous,
5383 runlevel <= 0 ? 'N' : runlevel);
5388 int main(int argc, char*argv[]) {
5389 int r, retval = EXIT_FAILURE;
5390 DBusConnection *bus = NULL;
5393 dbus_error_init(&error);
5395 log_parse_environment();
5398 if ((r = parse_argv(argc, argv)) < 0)
5401 retval = EXIT_SUCCESS;
5405 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
5406 * let's shortcut this */
5407 if (arg_action == ACTION_RUNLEVEL) {
5408 r = runlevel_main();
5409 retval = r < 0 ? EXIT_FAILURE : r;
5413 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
5414 log_info("Running in chroot, ignoring request.");
5420 if (arg_transport == TRANSPORT_NORMAL)
5421 bus_connect(arg_scope == UNIT_FILE_SYSTEM ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &bus, &private_bus, &error);
5422 else if (arg_transport == TRANSPORT_POLKIT) {
5423 bus_connect_system_polkit(&bus, &error);
5424 private_bus = false;
5425 } else if (arg_transport == TRANSPORT_SSH) {
5426 bus_connect_system_ssh(NULL, arg_host, &bus, &error);
5427 private_bus = false;
5429 assert_not_reached("Uh, invalid transport...");
5432 switch (arg_action) {
5434 case ACTION_SYSTEMCTL:
5435 r = systemctl_main(bus, argc, argv, &error);
5439 case ACTION_POWEROFF:
5445 case ACTION_RUNLEVEL2:
5446 case ACTION_RUNLEVEL3:
5447 case ACTION_RUNLEVEL4:
5448 case ACTION_RUNLEVEL5:
5450 case ACTION_EMERGENCY:
5451 case ACTION_DEFAULT:
5452 r = start_with_fallback(bus);
5457 r = reload_with_fallback(bus);
5460 case ACTION_CANCEL_SHUTDOWN:
5461 r = send_shutdownd(0, 0, false, false, NULL);
5464 case ACTION_INVALID:
5465 case ACTION_RUNLEVEL:
5467 assert_not_reached("Unknown action");
5470 retval = r < 0 ? EXIT_FAILURE : r;
5474 dbus_connection_flush(bus);
5475 dbus_connection_close(bus);
5476 dbus_connection_unref(bus);
5479 dbus_error_free(&error);
5483 strv_free(arg_property);