1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
22 #include <sys/reboot.h>
28 #include <sys/ioctl.h>
32 #include <sys/socket.h>
35 #include <sys/prctl.h>
36 #include <dbus/dbus.h>
42 #include "utmp-wtmp.h"
46 #include "dbus-common.h"
47 #include "cgroup-show.h"
48 #include "cgroup-util.h"
50 #include "path-lookup.h"
51 #include "conf-parser.h"
52 #include "sd-daemon.h"
53 #include "shutdownd.h"
54 #include "exit-status.h"
55 #include "bus-errors.h"
57 #include "unit-name.h"
59 #include "spawn-agent.h"
62 static const char *arg_type = NULL;
63 static char **arg_property = NULL;
64 static bool arg_all = false;
65 static const char *arg_job_mode = "replace";
66 static UnitFileScope arg_scope = UNIT_FILE_SYSTEM;
67 static bool arg_immediate = false;
68 static bool arg_no_block = false;
69 static bool arg_no_legend = false;
70 static bool arg_no_pager = false;
71 static bool arg_no_wtmp = false;
72 static bool arg_no_sync = false;
73 static bool arg_no_wall = false;
74 static bool arg_no_reload = false;
75 static bool arg_dry = false;
76 static bool arg_quiet = false;
77 static bool arg_full = false;
78 static bool arg_force = false;
79 static bool arg_ask_password = false;
80 static bool arg_failed = false;
81 static bool arg_runtime = false;
82 static char **arg_wall = NULL;
83 static const char *arg_kill_who = NULL;
84 static const char *arg_kill_mode = NULL;
85 static int arg_signal = SIGTERM;
86 static const char *arg_root = NULL;
87 static usec_t arg_when = 0;
106 ACTION_CANCEL_SHUTDOWN,
108 } arg_action = ACTION_SYSTEMCTL;
114 static enum transport {
118 } arg_transport = TRANSPORT_NORMAL;
119 static const char *arg_host = NULL;
121 static bool private_bus = false;
123 static int daemon_reload(DBusConnection *bus, char **args);
125 static bool on_tty(void) {
128 /* Note that this is invoked relatively early, before we start
129 * the pager. That means the value we return reflects whether
130 * we originally were started on a tty, not if we currently
131 * are. But this is intended, since we want colour and so on
132 * when run in our own pager. */
134 if (_unlikely_(t < 0))
135 t = isatty(STDOUT_FILENO) > 0;
140 static void pager_open_if_enabled(void) {
142 /* Cache result before we open the pager */
151 static void agent_open_if_enabled(void) {
153 /* Open the password agent as a child process if necessary */
155 if (!arg_ask_password)
158 if (arg_scope != UNIT_FILE_SYSTEM)
164 static const char *ansi_highlight(bool b) {
169 return b ? ANSI_HIGHLIGHT_ON : ANSI_HIGHLIGHT_OFF;
172 static const char *ansi_highlight_green(bool b) {
177 return b ? ANSI_HIGHLIGHT_GREEN_ON : ANSI_HIGHLIGHT_OFF;
180 static bool error_is_no_service(const DBusError *error) {
183 if (!dbus_error_is_set(error))
186 if (dbus_error_has_name(error, DBUS_ERROR_NAME_HAS_NO_OWNER))
189 if (dbus_error_has_name(error, DBUS_ERROR_SERVICE_UNKNOWN))
192 return startswith(error->name, "org.freedesktop.DBus.Error.Spawn.");
195 static int translate_bus_error_to_exit_status(int r, const DBusError *error) {
198 if (!dbus_error_is_set(error))
201 if (dbus_error_has_name(error, DBUS_ERROR_ACCESS_DENIED) ||
202 dbus_error_has_name(error, BUS_ERROR_ONLY_BY_DEPENDENCY) ||
203 dbus_error_has_name(error, BUS_ERROR_NO_ISOLATION) ||
204 dbus_error_has_name(error, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE))
205 return EXIT_NOPERMISSION;
207 if (dbus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT))
208 return EXIT_NOTINSTALLED;
210 if (dbus_error_has_name(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE) ||
211 dbus_error_has_name(error, BUS_ERROR_NOT_SUPPORTED))
212 return EXIT_NOTIMPLEMENTED;
214 if (dbus_error_has_name(error, BUS_ERROR_LOAD_FAILED))
215 return EXIT_NOTCONFIGURED;
223 static void warn_wall(enum action action) {
224 static const char *table[_ACTION_MAX] = {
225 [ACTION_HALT] = "The system is going down for system halt NOW!",
226 [ACTION_REBOOT] = "The system is going down for reboot NOW!",
227 [ACTION_POWEROFF] = "The system is going down for power-off NOW!",
228 [ACTION_KEXEC] = "The system is going down for kexec reboot NOW!",
229 [ACTION_RESCUE] = "The system is going down to rescue mode NOW!",
230 [ACTION_EMERGENCY] = "The system is going down to emergency mode NOW!"
239 if (!(p = strv_join(arg_wall, " "))) {
240 log_error("Failed to join strings.");
256 utmp_wall(table[action], NULL);
259 static bool avoid_bus(void) {
261 if (running_in_chroot() > 0)
264 if (sd_booted() <= 0)
267 if (!isempty(arg_root))
270 if (arg_scope == UNIT_FILE_GLOBAL)
278 const char *description;
279 const char *load_state;
280 const char *active_state;
281 const char *sub_state;
282 const char *following;
283 const char *unit_path;
285 const char *job_type;
286 const char *job_path;
289 static int compare_unit_info(const void *a, const void *b) {
291 const struct unit_info *u = a, *v = b;
293 d1 = strrchr(u->id, '.');
294 d2 = strrchr(v->id, '.');
299 if ((r = strcasecmp(d1, d2)) != 0)
303 return strcasecmp(u->id, v->id);
306 static bool output_show_unit(const struct unit_info *u) {
310 return streq(u->active_state, "failed");
312 return (!arg_type || ((dot = strrchr(u->id, '.')) &&
313 streq(dot+1, arg_type))) &&
314 (arg_all || !(streq(u->active_state, "inactive") || u->following[0]) || u->job_id > 0);
317 static void output_units_list(const struct unit_info *unit_infos, unsigned c) {
318 unsigned id_len, max_id_len, active_len, sub_len, job_len, desc_len, n_shown = 0;
319 const struct unit_info *u;
321 max_id_len = sizeof("UNIT")-1;
322 active_len = sizeof("ACTIVE")-1;
323 sub_len = sizeof("SUB")-1;
324 job_len = sizeof("JOB")-1;
327 for (u = unit_infos; u < unit_infos + c; u++) {
328 if (!output_show_unit(u))
331 max_id_len = MAX(max_id_len, strlen(u->id));
332 active_len = MAX(active_len, strlen(u->active_state));
333 sub_len = MAX(sub_len, strlen(u->sub_state));
335 job_len = MAX(job_len, strlen(u->job_type));
340 id_len = MIN(max_id_len, 25);
341 basic_len = 5 + id_len + 6 + active_len + sub_len + job_len;
342 if (basic_len < (unsigned) columns()) {
343 unsigned extra_len, incr;
344 extra_len = columns() - basic_len;
345 /* Either UNIT already got 25, or is fully satisfied.
346 * Grant up to 25 to DESC now. */
347 incr = MIN(extra_len, 25);
350 /* split the remaining space between UNIT and DESC,
351 * but do not give UNIT more than it needs. */
353 incr = MIN(extra_len / 2, max_id_len - id_len);
355 desc_len += extra_len - incr;
361 if (!arg_no_legend) {
362 printf("%-*s %-6s %-*s %-*s %-*s ", id_len, "UNIT", "LOAD",
363 active_len, "ACTIVE", sub_len, "SUB", job_len, "JOB");
364 if (!arg_full && arg_no_pager)
365 printf("%.*s\n", desc_len, "DESCRIPTION");
367 printf("%s\n", "DESCRIPTION");
370 for (u = unit_infos; u < unit_infos + c; u++) {
372 const char *on_loaded, *off_loaded;
373 const char *on_active, *off_active;
375 if (!output_show_unit(u))
380 if (!streq(u->load_state, "loaded") &&
381 !streq(u->load_state, "banned")) {
382 on_loaded = ansi_highlight(true);
383 off_loaded = ansi_highlight(false);
385 on_loaded = off_loaded = "";
387 if (streq(u->active_state, "failed")) {
388 on_active = ansi_highlight(true);
389 off_active = ansi_highlight(false);
391 on_active = off_active = "";
393 e = arg_full ? NULL : ellipsize(u->id, id_len, 33);
395 printf("%-*s %s%-6s%s %s%-*s %-*s%s %-*s ",
396 id_len, e ? e : u->id,
397 on_loaded, u->load_state, off_loaded,
398 on_active, active_len, u->active_state,
399 sub_len, u->sub_state, off_active,
400 job_len, u->job_id ? u->job_type : "");
401 if (!arg_full && arg_no_pager)
402 printf("%.*s\n", desc_len, u->description);
404 printf("%s\n", u->description);
409 if (!arg_no_legend) {
410 printf("\nLOAD = Reflects whether the unit definition was properly loaded.\n"
411 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
412 "SUB = The low-level unit activation state, values depend on unit type.\n"
413 "JOB = Pending job for the unit.\n");
416 printf("\n%u units listed.\n", n_shown);
418 printf("\n%u units listed. Pass --all to see inactive units, too.\n", n_shown);
422 static int list_units(DBusConnection *bus, char **args) {
423 DBusMessage *m = NULL, *reply = NULL;
426 DBusMessageIter iter, sub, sub2;
427 unsigned c = 0, n_units = 0;
428 struct unit_info *unit_infos = NULL;
430 dbus_error_init(&error);
434 pager_open_if_enabled();
436 if (!(m = dbus_message_new_method_call(
437 "org.freedesktop.systemd1",
438 "/org/freedesktop/systemd1",
439 "org.freedesktop.systemd1.Manager",
441 log_error("Could not allocate message.");
445 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
446 log_error("Failed to issue method call: %s", bus_error_message(&error));
451 if (!dbus_message_iter_init(reply, &iter) ||
452 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
453 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
454 log_error("Failed to parse reply.");
459 dbus_message_iter_recurse(&iter, &sub);
461 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
464 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
465 log_error("Failed to parse reply.");
473 n_units = MAX(2*c, 16);
474 w = realloc(unit_infos, sizeof(struct unit_info) * n_units);
477 log_error("Failed to allocate unit array.");
487 dbus_message_iter_recurse(&sub, &sub2);
489 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->id, true) < 0 ||
490 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->description, true) < 0 ||
491 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->load_state, true) < 0 ||
492 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->active_state, true) < 0 ||
493 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->sub_state, true) < 0 ||
494 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->following, true) < 0 ||
495 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &u->unit_path, true) < 0 ||
496 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &u->job_id, true) < 0 ||
497 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->job_type, true) < 0 ||
498 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &u->job_path, false) < 0) {
499 log_error("Failed to parse reply.");
504 dbus_message_iter_next(&sub);
509 qsort(unit_infos, c, sizeof(struct unit_info), compare_unit_info);
510 output_units_list(unit_infos, c);
517 dbus_message_unref(m);
520 dbus_message_unref(reply);
524 dbus_error_free(&error);
529 static int compare_unit_file_list(const void *a, const void *b) {
531 const UnitFileList *u = a, *v = b;
533 d1 = strrchr(u->path, '.');
534 d2 = strrchr(v->path, '.');
539 r = strcasecmp(d1, d2);
544 return strcasecmp(file_name_from_path(u->path), file_name_from_path(v->path));
547 static bool output_show_unit_file(const UnitFileList *u) {
550 return !arg_type || ((dot = strrchr(u->path, '.')) && streq(dot+1, arg_type));
553 static void output_unit_file_list(const UnitFileList *units, unsigned c) {
554 unsigned n_shown = 0;
555 const UnitFileList *u;
558 printf("%-25s %-6s\n", "UNIT FILE", "STATE");
560 for (u = units; u < units + c; u++) {
562 const char *on, *off;
565 if (!output_show_unit_file(u))
570 if (u->state == UNIT_FILE_MASKED ||
571 u->state == UNIT_FILE_MASKED_RUNTIME ||
572 u->state == UNIT_FILE_DISABLED) {
573 on = ansi_highlight(true);
574 off = ansi_highlight(false);
575 } else if (u->state == UNIT_FILE_ENABLED) {
576 on = ansi_highlight_green(true);
577 off = ansi_highlight_green(false);
581 id = file_name_from_path(u->path);
583 e = arg_full ? NULL : ellipsize(id, 25, 33);
585 printf("%-25s %s%-6s%s\n",
587 on, unit_file_state_to_string(u->state), off);
593 printf("\n%u unit files listed.\n", n_shown);
596 static int list_unit_files(DBusConnection *bus, char **args) {
597 DBusMessage *m = NULL, *reply = NULL;
600 DBusMessageIter iter, sub, sub2;
601 unsigned c = 0, n_units = 0;
602 UnitFileList *units = NULL;
604 dbus_error_init(&error);
608 pager_open_if_enabled();
615 h = hashmap_new(string_hash_func, string_compare_func);
617 log_error("Out of memory");
621 r = unit_file_get_list(arg_scope, arg_root, h);
623 unit_file_list_free(h);
624 log_error("Failed to get unit file list: %s", strerror(-r));
628 n_units = hashmap_size(h);
629 units = new(UnitFileList, n_units);
631 unit_file_list_free(h);
632 log_error("Out of memory");
636 HASHMAP_FOREACH(u, h, i) {
637 memcpy(units + c++, u, sizeof(UnitFileList));
643 m = dbus_message_new_method_call(
644 "org.freedesktop.systemd1",
645 "/org/freedesktop/systemd1",
646 "org.freedesktop.systemd1.Manager",
649 log_error("Could not allocate message.");
653 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
655 log_error("Failed to issue method call: %s", bus_error_message(&error));
660 if (!dbus_message_iter_init(reply, &iter) ||
661 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
662 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
663 log_error("Failed to parse reply.");
668 dbus_message_iter_recurse(&iter, &sub);
670 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
674 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
675 log_error("Failed to parse reply.");
683 n_units = MAX(2*c, 16);
684 w = realloc(units, sizeof(struct UnitFileList) * n_units);
687 log_error("Failed to allocate unit array.");
697 dbus_message_iter_recurse(&sub, &sub2);
699 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->path, true) < 0 ||
700 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, false) < 0) {
701 log_error("Failed to parse reply.");
706 u->state = unit_file_state_from_string(state);
708 dbus_message_iter_next(&sub);
714 qsort(units, c, sizeof(UnitFileList), compare_unit_file_list);
715 output_unit_file_list(units, c);
722 dbus_message_unref(m);
725 dbus_message_unref(reply);
729 dbus_error_free(&error);
734 static int dot_one_property(const char *name, const char *prop, DBusMessageIter *iter) {
735 static const char * const colors[] = {
736 "Requires", "[color=\"black\"]",
737 "RequiresOverridable", "[color=\"black\"]",
738 "Requisite", "[color=\"darkblue\"]",
739 "RequisiteOverridable", "[color=\"darkblue\"]",
740 "Wants", "[color=\"darkgrey\"]",
741 "Conflicts", "[color=\"red\"]",
742 "ConflictedBy", "[color=\"red\"]",
743 "After", "[color=\"green\"]"
746 const char *c = NULL;
753 for (i = 0; i < ELEMENTSOF(colors); i += 2)
754 if (streq(colors[i], prop)) {
762 if (arg_dot != DOT_ALL)
763 if ((arg_dot == DOT_ORDER) != streq(prop, "After"))
766 switch (dbus_message_iter_get_arg_type(iter)) {
768 case DBUS_TYPE_ARRAY:
770 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING) {
773 dbus_message_iter_recurse(iter, &sub);
775 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
778 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING);
779 dbus_message_iter_get_basic(&sub, &s);
780 printf("\t\"%s\"->\"%s\" %s;\n", name, s, c);
782 dbus_message_iter_next(&sub);
792 static int dot_one(DBusConnection *bus, const char *name, const char *path) {
793 DBusMessage *m = NULL, *reply = NULL;
794 const char *interface = "org.freedesktop.systemd1.Unit";
797 DBusMessageIter iter, sub, sub2, sub3;
802 dbus_error_init(&error);
804 if (!(m = dbus_message_new_method_call(
805 "org.freedesktop.systemd1",
807 "org.freedesktop.DBus.Properties",
809 log_error("Could not allocate message.");
814 if (!dbus_message_append_args(m,
815 DBUS_TYPE_STRING, &interface,
816 DBUS_TYPE_INVALID)) {
817 log_error("Could not append arguments to message.");
822 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
823 log_error("Failed to issue method call: %s", bus_error_message(&error));
828 if (!dbus_message_iter_init(reply, &iter) ||
829 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
830 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
831 log_error("Failed to parse reply.");
836 dbus_message_iter_recurse(&iter, &sub);
838 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
841 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_DICT_ENTRY) {
842 log_error("Failed to parse reply.");
847 dbus_message_iter_recurse(&sub, &sub2);
849 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &prop, true) < 0) {
850 log_error("Failed to parse reply.");
855 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
856 log_error("Failed to parse reply.");
861 dbus_message_iter_recurse(&sub2, &sub3);
863 if (dot_one_property(name, prop, &sub3)) {
864 log_error("Failed to parse reply.");
869 dbus_message_iter_next(&sub);
876 dbus_message_unref(m);
879 dbus_message_unref(reply);
881 dbus_error_free(&error);
886 static int dot(DBusConnection *bus, char **args) {
887 DBusMessage *m = NULL, *reply = NULL;
890 DBusMessageIter iter, sub, sub2;
892 dbus_error_init(&error);
896 if (!(m = dbus_message_new_method_call(
897 "org.freedesktop.systemd1",
898 "/org/freedesktop/systemd1",
899 "org.freedesktop.systemd1.Manager",
901 log_error("Could not allocate message.");
905 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
906 log_error("Failed to issue method call: %s", bus_error_message(&error));
911 if (!dbus_message_iter_init(reply, &iter) ||
912 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
913 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
914 log_error("Failed to parse reply.");
919 printf("digraph systemd {\n");
921 dbus_message_iter_recurse(&iter, &sub);
922 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
923 const char *id, *description, *load_state, *active_state, *sub_state, *following, *unit_path;
925 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
926 log_error("Failed to parse reply.");
931 dbus_message_iter_recurse(&sub, &sub2);
933 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &id, true) < 0 ||
934 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &description, true) < 0 ||
935 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &load_state, true) < 0 ||
936 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &active_state, true) < 0 ||
937 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &sub_state, true) < 0 ||
938 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &following, true) < 0 ||
939 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, true) < 0) {
940 log_error("Failed to parse reply.");
945 if ((r = dot_one(bus, id, unit_path)) < 0)
948 /* printf("\t\"%s\";\n", id); */
949 dbus_message_iter_next(&sub);
954 log_info(" Color legend: black = Requires\n"
955 " dark blue = Requisite\n"
956 " dark grey = Wants\n"
961 log_notice("-- You probably want to process this output with graphviz' dot tool.\n"
962 "-- Try a shell pipeline like 'systemctl dot | dot -Tsvg > systemd.svg'!\n");
968 dbus_message_unref(m);
971 dbus_message_unref(reply);
973 dbus_error_free(&error);
978 static int list_jobs(DBusConnection *bus, char **args) {
979 DBusMessage *m = NULL, *reply = NULL;
982 DBusMessageIter iter, sub, sub2;
985 dbus_error_init(&error);
989 pager_open_if_enabled();
991 if (!(m = dbus_message_new_method_call(
992 "org.freedesktop.systemd1",
993 "/org/freedesktop/systemd1",
994 "org.freedesktop.systemd1.Manager",
996 log_error("Could not allocate message.");
1000 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
1001 log_error("Failed to issue method call: %s", bus_error_message(&error));
1006 if (!dbus_message_iter_init(reply, &iter) ||
1007 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
1008 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
1009 log_error("Failed to parse reply.");
1014 dbus_message_iter_recurse(&iter, &sub);
1017 printf("%4s %-25s %-15s %-7s\n", "JOB", "UNIT", "TYPE", "STATE");
1019 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1020 const char *name, *type, *state, *job_path, *unit_path;
1024 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
1025 log_error("Failed to parse reply.");
1030 dbus_message_iter_recurse(&sub, &sub2);
1032 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &id, true) < 0 ||
1033 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
1034 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
1035 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, true) < 0 ||
1036 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &job_path, true) < 0 ||
1037 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, false) < 0) {
1038 log_error("Failed to parse reply.");
1043 e = arg_full ? NULL : ellipsize(name, 25, 33);
1044 printf("%4u %-25s %-15s %-7s\n", id, e ? e : name, type, state);
1049 dbus_message_iter_next(&sub);
1053 printf("\n%u jobs listed.\n", k);
1059 dbus_message_unref(m);
1062 dbus_message_unref(reply);
1064 dbus_error_free(&error);
1069 static int load_unit(DBusConnection *bus, char **args) {
1070 DBusMessage *m = NULL;
1075 dbus_error_init(&error);
1080 STRV_FOREACH(name, args+1) {
1083 if (!(m = dbus_message_new_method_call(
1084 "org.freedesktop.systemd1",
1085 "/org/freedesktop/systemd1",
1086 "org.freedesktop.systemd1.Manager",
1088 log_error("Could not allocate message.");
1093 if (!dbus_message_append_args(m,
1094 DBUS_TYPE_STRING, name,
1095 DBUS_TYPE_INVALID)) {
1096 log_error("Could not append arguments to message.");
1101 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
1102 log_error("Failed to issue method call: %s", bus_error_message(&error));
1107 dbus_message_unref(m);
1108 dbus_message_unref(reply);
1117 dbus_message_unref(m);
1119 dbus_error_free(&error);
1124 static int cancel_job(DBusConnection *bus, char **args) {
1125 DBusMessage *m = NULL, *reply = NULL;
1130 dbus_error_init(&error);
1135 if (strv_length(args) <= 1)
1136 return daemon_reload(bus, args);
1138 STRV_FOREACH(name, args+1) {
1142 if (!(m = dbus_message_new_method_call(
1143 "org.freedesktop.systemd1",
1144 "/org/freedesktop/systemd1",
1145 "org.freedesktop.systemd1.Manager",
1147 log_error("Could not allocate message.");
1152 if ((r = safe_atou(*name, &id)) < 0) {
1153 log_error("Failed to parse job id: %s", strerror(-r));
1157 assert_cc(sizeof(uint32_t) == sizeof(id));
1158 if (!dbus_message_append_args(m,
1159 DBUS_TYPE_UINT32, &id,
1160 DBUS_TYPE_INVALID)) {
1161 log_error("Could not append arguments to message.");
1166 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
1167 log_error("Failed to issue method call: %s", bus_error_message(&error));
1172 if (!dbus_message_get_args(reply, &error,
1173 DBUS_TYPE_OBJECT_PATH, &path,
1174 DBUS_TYPE_INVALID)) {
1175 log_error("Failed to parse reply: %s", bus_error_message(&error));
1180 dbus_message_unref(m);
1181 if (!(m = dbus_message_new_method_call(
1182 "org.freedesktop.systemd1",
1184 "org.freedesktop.systemd1.Job",
1186 log_error("Could not allocate message.");
1191 dbus_message_unref(reply);
1192 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
1193 log_error("Failed to issue method call: %s", bus_error_message(&error));
1198 dbus_message_unref(m);
1199 dbus_message_unref(reply);
1207 dbus_message_unref(m);
1210 dbus_message_unref(reply);
1212 dbus_error_free(&error);
1217 static bool need_daemon_reload(DBusConnection *bus, const char *unit) {
1218 DBusMessage *m = NULL, *reply = NULL;
1219 dbus_bool_t b = FALSE;
1220 DBusMessageIter iter, sub;
1222 *interface = "org.freedesktop.systemd1.Unit",
1223 *property = "NeedDaemonReload",
1226 /* We ignore all errors here, since this is used to show a warning only */
1228 if (!(m = dbus_message_new_method_call(
1229 "org.freedesktop.systemd1",
1230 "/org/freedesktop/systemd1",
1231 "org.freedesktop.systemd1.Manager",
1235 if (!dbus_message_append_args(m,
1236 DBUS_TYPE_STRING, &unit,
1240 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, NULL)))
1243 if (!dbus_message_get_args(reply, NULL,
1244 DBUS_TYPE_OBJECT_PATH, &path,
1248 dbus_message_unref(m);
1249 if (!(m = dbus_message_new_method_call(
1250 "org.freedesktop.systemd1",
1252 "org.freedesktop.DBus.Properties",
1256 if (!dbus_message_append_args(m,
1257 DBUS_TYPE_STRING, &interface,
1258 DBUS_TYPE_STRING, &property,
1259 DBUS_TYPE_INVALID)) {
1263 dbus_message_unref(reply);
1264 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, NULL)))
1267 if (!dbus_message_iter_init(reply, &iter) ||
1268 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
1271 dbus_message_iter_recurse(&iter, &sub);
1273 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_BOOLEAN)
1276 dbus_message_iter_get_basic(&sub, &b);
1280 dbus_message_unref(m);
1283 dbus_message_unref(reply);
1288 typedef struct WaitData {
1293 static DBusHandlerResult wait_filter(DBusConnection *connection, DBusMessage *message, void *data) {
1301 dbus_error_init(&error);
1303 log_debug("Got D-Bus request: %s.%s() on %s",
1304 dbus_message_get_interface(message),
1305 dbus_message_get_member(message),
1306 dbus_message_get_path(message));
1308 if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
1309 log_error("Warning! D-Bus connection terminated.");
1310 dbus_connection_close(connection);
1312 } else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
1314 const char *path, *result;
1315 dbus_bool_t success = true;
1317 if (dbus_message_get_args(message, &error,
1318 DBUS_TYPE_UINT32, &id,
1319 DBUS_TYPE_OBJECT_PATH, &path,
1320 DBUS_TYPE_STRING, &result,
1321 DBUS_TYPE_INVALID)) {
1324 if ((p = set_remove(d->set, (char*) path)))
1328 d->result = strdup(result);
1333 dbus_error_free(&error);
1335 if (dbus_message_get_args(message, &error,
1336 DBUS_TYPE_UINT32, &id,
1337 DBUS_TYPE_OBJECT_PATH, &path,
1338 DBUS_TYPE_BOOLEAN, &success,
1339 DBUS_TYPE_INVALID)) {
1342 /* Compatibility with older systemd versions <
1343 * 19 during upgrades. This should be dropped
1346 if ((p = set_remove(d->set, (char*) path)))
1350 d->result = strdup("failed");
1356 log_error("Failed to parse message: %s", bus_error_message(&error));
1360 dbus_error_free(&error);
1361 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1364 static int enable_wait_for_jobs(DBusConnection *bus) {
1372 dbus_error_init(&error);
1373 dbus_bus_add_match(bus,
1375 "sender='org.freedesktop.systemd1',"
1376 "interface='org.freedesktop.systemd1.Manager',"
1377 "member='JobRemoved',"
1378 "path='/org/freedesktop/systemd1'",
1381 if (dbus_error_is_set(&error)) {
1382 log_error("Failed to add match: %s", bus_error_message(&error));
1383 dbus_error_free(&error);
1387 /* This is slightly dirty, since we don't undo the match registrations. */
1391 static int wait_for_jobs(DBusConnection *bus, Set *s) {
1401 if (!dbus_connection_add_filter(bus, wait_filter, &d, NULL)) {
1402 log_error("Failed to add filter.");
1407 while (!set_isempty(s) &&
1408 dbus_connection_read_write_dispatch(bus, -1))
1411 if (!arg_quiet && d.result) {
1412 if (streq(d.result, "timeout"))
1413 log_error("Job timed out.");
1414 else if (streq(d.result, "canceled"))
1415 log_error("Job canceled.");
1416 else if (streq(d.result, "dependency"))
1417 log_error("A dependency job failed. See system logs for details.");
1418 else if (!streq(d.result, "done") && !streq(d.result, "skipped"))
1419 log_error("Job failed. See system logs and 'systemctl status' for details.");
1422 if (streq_ptr(d.result, "timeout"))
1424 else if (streq_ptr(d.result, "canceled"))
1426 else if (!streq_ptr(d.result, "done") && !streq_ptr(d.result, "skipped"))
1434 /* This is slightly dirty, since we don't undo the filter registration. */
1439 static int start_unit_one(
1440 DBusConnection *bus,
1447 DBusMessage *m = NULL, *reply = NULL;
1456 assert(arg_no_block || s);
1458 if (!(m = dbus_message_new_method_call(
1459 "org.freedesktop.systemd1",
1460 "/org/freedesktop/systemd1",
1461 "org.freedesktop.systemd1.Manager",
1463 log_error("Could not allocate message.");
1468 if (!dbus_message_append_args(m,
1469 DBUS_TYPE_STRING, &name,
1470 DBUS_TYPE_STRING, &mode,
1471 DBUS_TYPE_INVALID)) {
1472 log_error("Could not append arguments to message.");
1477 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, error))) {
1479 if (arg_action != ACTION_SYSTEMCTL && error_is_no_service(error)) {
1480 /* There's always a fallback possible for
1481 * legacy actions. */
1486 log_error("Failed to issue method call: %s", bus_error_message(error));
1491 if (!dbus_message_get_args(reply, error,
1492 DBUS_TYPE_OBJECT_PATH, &path,
1493 DBUS_TYPE_INVALID)) {
1494 log_error("Failed to parse reply: %s", bus_error_message(error));
1499 if (need_daemon_reload(bus, name))
1500 log_warning("Warning: Unit file of created job changed on disk, 'systemctl %s daemon-reload' recommended.",
1501 arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
1503 if (!arg_no_block) {
1506 if (!(p = strdup(path))) {
1507 log_error("Failed to duplicate path.");
1512 if ((r = set_put(s, p)) < 0) {
1514 log_error("Failed to add path to set.");
1523 dbus_message_unref(m);
1526 dbus_message_unref(reply);
1531 static enum action verb_to_action(const char *verb) {
1532 if (streq(verb, "halt"))
1534 else if (streq(verb, "poweroff"))
1535 return ACTION_POWEROFF;
1536 else if (streq(verb, "reboot"))
1537 return ACTION_REBOOT;
1538 else if (streq(verb, "kexec"))
1539 return ACTION_KEXEC;
1540 else if (streq(verb, "rescue"))
1541 return ACTION_RESCUE;
1542 else if (streq(verb, "emergency"))
1543 return ACTION_EMERGENCY;
1544 else if (streq(verb, "default"))
1545 return ACTION_DEFAULT;
1546 else if (streq(verb, "exit"))
1549 return ACTION_INVALID;
1552 static int start_unit(DBusConnection *bus, char **args) {
1554 static const char * const table[_ACTION_MAX] = {
1555 [ACTION_HALT] = SPECIAL_HALT_TARGET,
1556 [ACTION_POWEROFF] = SPECIAL_POWEROFF_TARGET,
1557 [ACTION_REBOOT] = SPECIAL_REBOOT_TARGET,
1558 [ACTION_KEXEC] = SPECIAL_KEXEC_TARGET,
1559 [ACTION_RUNLEVEL2] = SPECIAL_RUNLEVEL2_TARGET,
1560 [ACTION_RUNLEVEL3] = SPECIAL_RUNLEVEL3_TARGET,
1561 [ACTION_RUNLEVEL4] = SPECIAL_RUNLEVEL4_TARGET,
1562 [ACTION_RUNLEVEL5] = SPECIAL_RUNLEVEL5_TARGET,
1563 [ACTION_RESCUE] = SPECIAL_RESCUE_TARGET,
1564 [ACTION_EMERGENCY] = SPECIAL_EMERGENCY_TARGET,
1565 [ACTION_DEFAULT] = SPECIAL_DEFAULT_TARGET,
1566 [ACTION_EXIT] = SPECIAL_EXIT_TARGET
1570 const char *method, *mode, *one_name;
1575 dbus_error_init(&error);
1579 agent_open_if_enabled();
1581 if (arg_action == ACTION_SYSTEMCTL) {
1583 streq(args[0], "stop") ||
1584 streq(args[0], "condstop") ? "StopUnit" :
1585 streq(args[0], "reload") ? "ReloadUnit" :
1586 streq(args[0], "restart") ? "RestartUnit" :
1588 streq(args[0], "try-restart") ||
1589 streq(args[0], "condrestart") ? "TryRestartUnit" :
1591 streq(args[0], "reload-or-restart") ? "ReloadOrRestartUnit" :
1593 streq(args[0], "reload-or-try-restart") ||
1594 streq(args[0], "condreload") ||
1596 streq(args[0], "force-reload") ? "ReloadOrTryRestartUnit" :
1600 (streq(args[0], "isolate") ||
1601 streq(args[0], "rescue") ||
1602 streq(args[0], "emergency")) ? "isolate" : arg_job_mode;
1604 one_name = table[verb_to_action(args[0])];
1607 assert(arg_action < ELEMENTSOF(table));
1608 assert(table[arg_action]);
1610 method = "StartUnit";
1612 mode = (arg_action == ACTION_EMERGENCY ||
1613 arg_action == ACTION_RESCUE ||
1614 arg_action == ACTION_RUNLEVEL2 ||
1615 arg_action == ACTION_RUNLEVEL3 ||
1616 arg_action == ACTION_RUNLEVEL4 ||
1617 arg_action == ACTION_RUNLEVEL5) ? "isolate" : "replace";
1619 one_name = table[arg_action];
1622 if (!arg_no_block) {
1623 if ((ret = enable_wait_for_jobs(bus)) < 0) {
1624 log_error("Could not watch jobs: %s", strerror(-ret));
1628 if (!(s = set_new(string_hash_func, string_compare_func))) {
1629 log_error("Failed to allocate set.");
1636 if ((ret = start_unit_one(bus, method, one_name, mode, &error, s)) <= 0)
1639 STRV_FOREACH(name, args+1)
1640 if ((r = start_unit_one(bus, method, *name, mode, &error, s)) != 0) {
1641 ret = translate_bus_error_to_exit_status(r, &error);
1642 dbus_error_free(&error);
1647 if ((r = wait_for_jobs(bus, s)) < 0) {
1656 dbus_error_free(&error);
1661 static int start_special(DBusConnection *bus, char **args) {
1668 (streq(args[0], "halt") ||
1669 streq(args[0], "poweroff") ||
1670 streq(args[0], "reboot") ||
1671 streq(args[0], "kexec") ||
1672 streq(args[0], "exit")))
1673 return daemon_reload(bus, args);
1675 r = start_unit(bus, args);
1678 warn_wall(verb_to_action(args[0]));
1683 static int check_unit(DBusConnection *bus, char **args) {
1684 DBusMessage *m = NULL, *reply = NULL;
1686 *interface = "org.freedesktop.systemd1.Unit",
1687 *property = "ActiveState";
1688 int r = 3; /* According to LSB: "program is not running" */
1695 dbus_error_init(&error);
1697 STRV_FOREACH(name, args+1) {
1698 const char *path = NULL;
1700 DBusMessageIter iter, sub;
1702 if (!(m = dbus_message_new_method_call(
1703 "org.freedesktop.systemd1",
1704 "/org/freedesktop/systemd1",
1705 "org.freedesktop.systemd1.Manager",
1707 log_error("Could not allocate message.");
1712 if (!dbus_message_append_args(m,
1713 DBUS_TYPE_STRING, name,
1714 DBUS_TYPE_INVALID)) {
1715 log_error("Could not append arguments to message.");
1720 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
1722 /* Hmm, cannot figure out anything about this unit... */
1726 dbus_error_free(&error);
1727 dbus_message_unref(m);
1732 if (!dbus_message_get_args(reply, &error,
1733 DBUS_TYPE_OBJECT_PATH, &path,
1734 DBUS_TYPE_INVALID)) {
1735 log_error("Failed to parse reply: %s", bus_error_message(&error));
1740 dbus_message_unref(m);
1741 if (!(m = dbus_message_new_method_call(
1742 "org.freedesktop.systemd1",
1744 "org.freedesktop.DBus.Properties",
1746 log_error("Could not allocate message.");
1751 if (!dbus_message_append_args(m,
1752 DBUS_TYPE_STRING, &interface,
1753 DBUS_TYPE_STRING, &property,
1754 DBUS_TYPE_INVALID)) {
1755 log_error("Could not append arguments to message.");
1760 dbus_message_unref(reply);
1761 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
1762 log_error("Failed to issue method call: %s", bus_error_message(&error));
1767 if (!dbus_message_iter_init(reply, &iter) ||
1768 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1769 log_error("Failed to parse reply.");
1774 dbus_message_iter_recurse(&iter, &sub);
1776 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1777 log_error("Failed to parse reply.");
1782 dbus_message_iter_get_basic(&sub, &state);
1787 if (streq(state, "active") || streq(state, "reloading"))
1790 dbus_message_unref(m);
1791 dbus_message_unref(reply);
1797 dbus_message_unref(m);
1800 dbus_message_unref(reply);
1802 dbus_error_free(&error);
1807 static int kill_unit(DBusConnection *bus, char **args) {
1808 DBusMessage *m = NULL;
1816 dbus_error_init(&error);
1819 arg_kill_who = "all";
1822 arg_kill_mode = streq(arg_kill_who, "all") ? "control-group" : "process";
1824 STRV_FOREACH(name, args+1) {
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_STRING, &arg_kill_who,
1840 DBUS_TYPE_STRING, &arg_kill_mode,
1841 DBUS_TYPE_INT32, &arg_signal,
1842 DBUS_TYPE_INVALID)) {
1843 log_error("Could not append arguments to message.");
1848 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
1849 log_error("Failed to issue method call: %s", bus_error_message(&error));
1850 dbus_error_free(&error);
1854 dbus_message_unref(m);
1857 dbus_message_unref(reply);
1863 dbus_message_unref(m);
1865 dbus_error_free(&error);
1870 typedef struct ExecStatusInfo {
1878 usec_t start_timestamp;
1879 usec_t exit_timestamp;
1884 LIST_FIELDS(struct ExecStatusInfo, exec);
1887 static void exec_status_info_free(ExecStatusInfo *i) {
1896 static int exec_status_info_deserialize(DBusMessageIter *sub, ExecStatusInfo *i) {
1897 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
1898 DBusMessageIter sub2, sub3;
1902 int32_t code, status;
1908 if (dbus_message_iter_get_arg_type(sub) != DBUS_TYPE_STRUCT)
1911 dbus_message_iter_recurse(sub, &sub2);
1913 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0)
1916 if (!(i->path = strdup(path)))
1919 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_ARRAY ||
1920 dbus_message_iter_get_element_type(&sub2) != DBUS_TYPE_STRING)
1924 dbus_message_iter_recurse(&sub2, &sub3);
1925 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
1926 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
1927 dbus_message_iter_next(&sub3);
1932 if (!(i->argv = new0(char*, n+1)))
1936 dbus_message_iter_recurse(&sub2, &sub3);
1937 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
1940 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
1941 dbus_message_iter_get_basic(&sub3, &s);
1942 dbus_message_iter_next(&sub3);
1944 if (!(i->argv[n++] = strdup(s)))
1948 if (!dbus_message_iter_next(&sub2) ||
1949 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, true) < 0 ||
1950 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp, true) < 0 ||
1951 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp_monotonic, true) < 0 ||
1952 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp, true) < 0 ||
1953 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp_monotonic, true) < 0 ||
1954 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, true) < 0 ||
1955 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &code, true) < 0 ||
1956 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &status, false) < 0)
1960 i->start_timestamp = (usec_t) start_timestamp;
1961 i->exit_timestamp = (usec_t) exit_timestamp;
1962 i->pid = (pid_t) pid;
1969 typedef struct UnitStatusInfo {
1971 const char *load_state;
1972 const char *active_state;
1973 const char *sub_state;
1974 const char *unit_file_state;
1976 const char *description;
1977 const char *following;
1980 const char *default_control_group;
1982 const char *load_error;
1984 usec_t inactive_exit_timestamp;
1985 usec_t active_enter_timestamp;
1986 usec_t active_exit_timestamp;
1987 usec_t inactive_enter_timestamp;
1989 bool need_daemon_reload;
1994 const char *status_text;
1996 #ifdef HAVE_SYSV_COMPAT
2000 usec_t start_timestamp;
2001 usec_t exit_timestamp;
2003 int exit_code, exit_status;
2005 usec_t condition_timestamp;
2006 bool condition_result;
2009 unsigned n_accepted;
2010 unsigned n_connections;
2014 const char *sysfs_path;
2016 /* Mount, Automount */
2022 LIST_HEAD(ExecStatusInfo, exec);
2025 static void print_status_info(UnitStatusInfo *i) {
2027 const char *on, *off, *ss;
2029 char since1[FORMAT_TIMESTAMP_PRETTY_MAX], *s1;
2030 char since2[FORMAT_TIMESTAMP_MAX], *s2;
2034 /* This shows pretty information about a unit. See
2035 * print_property() for a low-level property printer */
2037 printf("%s", strna(i->id));
2039 if (i->description && !streq_ptr(i->id, i->description))
2040 printf(" - %s", i->description);
2045 printf("\t Follow: unit currently follows state of %s\n", i->following);
2047 if (streq_ptr(i->load_state, "failed") ||
2048 streq_ptr(i->load_state, "banned")) {
2049 on = ansi_highlight(true);
2050 off = ansi_highlight(false);
2055 printf("\t Loaded: %s%s%s (Reason: %s)\n", on, strna(i->load_state), off, i->load_error);
2056 else if (i->path && i->unit_file_state)
2057 printf("\t Loaded: %s%s%s (%s; %s)\n", on, strna(i->load_state), off, i->path, i->unit_file_state);
2059 printf("\t Loaded: %s%s%s (%s)\n", on, strna(i->load_state), off, i->path);
2061 printf("\t Loaded: %s%s%s\n", on, strna(i->load_state), off);
2063 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
2065 if (streq_ptr(i->active_state, "failed")) {
2066 on = ansi_highlight(true);
2067 off = ansi_highlight(false);
2068 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
2069 on = ansi_highlight_green(true);
2070 off = ansi_highlight_green(false);
2075 printf("\t Active: %s%s (%s)%s",
2077 strna(i->active_state),
2081 printf("\t Active: %s%s%s",
2083 strna(i->active_state),
2086 timestamp = (streq_ptr(i->active_state, "active") ||
2087 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
2088 (streq_ptr(i->active_state, "inactive") ||
2089 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
2090 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
2091 i->active_exit_timestamp;
2093 s1 = format_timestamp_pretty(since1, sizeof(since1), timestamp);
2094 s2 = format_timestamp(since2, sizeof(since2), timestamp);
2097 printf(" since %s; %s\n", s2, s1);
2099 printf(" since %s\n", s2);
2103 if (!i->condition_result && i->condition_timestamp > 0) {
2104 s1 = format_timestamp_pretty(since1, sizeof(since1), i->condition_timestamp);
2105 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
2108 printf("\t start condition failed at %s; %s\n", s2, s1);
2110 printf("\t start condition failed at %s\n", s2);
2114 printf("\t Device: %s\n", i->sysfs_path);
2116 printf("\t Where: %s\n", i->where);
2118 printf("\t What: %s\n", i->what);
2121 printf("\tAccepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
2123 LIST_FOREACH(exec, p, i->exec) {
2127 /* Only show exited processes here */
2131 t = strv_join(p->argv, " ");
2132 printf("\t Process: %u %s=%s ", p->pid, p->name, strna(t));
2135 #ifdef HAVE_SYSV_COMPAT
2137 good = is_clean_exit_lsb(p->code, p->status);
2140 good = is_clean_exit(p->code, p->status);
2143 on = ansi_highlight(true);
2144 off = ansi_highlight(false);
2148 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
2150 if (p->code == CLD_EXITED) {
2153 printf("status=%i", p->status);
2155 #ifdef HAVE_SYSV_COMPAT
2156 if ((c = exit_status_to_string(p->status, i->is_sysv ? EXIT_STATUS_LSB : EXIT_STATUS_SYSTEMD)))
2158 if ((c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD)))
2163 printf("signal=%s", signal_to_string(p->status));
2165 printf(")%s\n", off);
2167 if (i->main_pid == p->pid &&
2168 i->start_timestamp == p->start_timestamp &&
2169 i->exit_timestamp == p->start_timestamp)
2170 /* Let's not show this twice */
2173 if (p->pid == i->control_pid)
2177 if (i->main_pid > 0 || i->control_pid > 0) {
2180 if (i->main_pid > 0) {
2181 printf("Main PID: %u", (unsigned) i->main_pid);
2185 get_process_comm(i->main_pid, &t);
2190 } else if (i->exit_code > 0) {
2191 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
2193 if (i->exit_code == CLD_EXITED) {
2196 printf("status=%i", i->exit_status);
2198 #ifdef HAVE_SYSV_COMPAT
2199 if ((c = exit_status_to_string(i->exit_status, i->is_sysv ? EXIT_STATUS_LSB : EXIT_STATUS_SYSTEMD)))
2201 if ((c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD)))
2206 printf("signal=%s", signal_to_string(i->exit_status));
2211 if (i->main_pid > 0 && i->control_pid > 0)
2214 if (i->control_pid > 0) {
2217 printf(" Control: %u", (unsigned) i->control_pid);
2219 get_process_comm(i->control_pid, &t);
2230 printf("\t Status: \"%s\"\n", i->status_text);
2232 if (i->default_control_group) {
2235 printf("\t CGroup: %s\n", i->default_control_group);
2237 if (arg_transport != TRANSPORT_SSH) {
2238 if ((c = columns()) > 18)
2243 show_cgroup_by_path(i->default_control_group, "\t\t ", c);
2247 if (i->need_daemon_reload)
2248 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %s daemon-reload' recommended.\n",
2249 ansi_highlight(true),
2250 ansi_highlight(false),
2251 arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
2254 static int status_property(const char *name, DBusMessageIter *iter, UnitStatusInfo *i) {
2260 switch (dbus_message_iter_get_arg_type(iter)) {
2262 case DBUS_TYPE_STRING: {
2265 dbus_message_iter_get_basic(iter, &s);
2268 if (streq(name, "Id"))
2270 else if (streq(name, "LoadState"))
2272 else if (streq(name, "ActiveState"))
2273 i->active_state = s;
2274 else if (streq(name, "SubState"))
2276 else if (streq(name, "Description"))
2278 else if (streq(name, "FragmentPath"))
2280 #ifdef HAVE_SYSV_COMPAT
2281 else if (streq(name, "SysVPath")) {
2286 else if (streq(name, "DefaultControlGroup"))
2287 i->default_control_group = s;
2288 else if (streq(name, "StatusText"))
2290 else if (streq(name, "SysFSPath"))
2292 else if (streq(name, "Where"))
2294 else if (streq(name, "What"))
2296 else if (streq(name, "Following"))
2298 else if (streq(name, "UnitFileState"))
2299 i->unit_file_state = s;
2305 case DBUS_TYPE_BOOLEAN: {
2308 dbus_message_iter_get_basic(iter, &b);
2310 if (streq(name, "Accept"))
2312 else if (streq(name, "NeedDaemonReload"))
2313 i->need_daemon_reload = b;
2314 else if (streq(name, "ConditionResult"))
2315 i->condition_result = b;
2320 case DBUS_TYPE_UINT32: {
2323 dbus_message_iter_get_basic(iter, &u);
2325 if (streq(name, "MainPID")) {
2327 i->main_pid = (pid_t) u;
2330 } else if (streq(name, "ControlPID"))
2331 i->control_pid = (pid_t) u;
2332 else if (streq(name, "ExecMainPID")) {
2334 i->main_pid = (pid_t) u;
2335 } else if (streq(name, "NAccepted"))
2337 else if (streq(name, "NConnections"))
2338 i->n_connections = u;
2343 case DBUS_TYPE_INT32: {
2346 dbus_message_iter_get_basic(iter, &j);
2348 if (streq(name, "ExecMainCode"))
2349 i->exit_code = (int) j;
2350 else if (streq(name, "ExecMainStatus"))
2351 i->exit_status = (int) j;
2356 case DBUS_TYPE_UINT64: {
2359 dbus_message_iter_get_basic(iter, &u);
2361 if (streq(name, "ExecMainStartTimestamp"))
2362 i->start_timestamp = (usec_t) u;
2363 else if (streq(name, "ExecMainExitTimestamp"))
2364 i->exit_timestamp = (usec_t) u;
2365 else if (streq(name, "ActiveEnterTimestamp"))
2366 i->active_enter_timestamp = (usec_t) u;
2367 else if (streq(name, "InactiveEnterTimestamp"))
2368 i->inactive_enter_timestamp = (usec_t) u;
2369 else if (streq(name, "InactiveExitTimestamp"))
2370 i->inactive_exit_timestamp = (usec_t) u;
2371 else if (streq(name, "ActiveExitTimestamp"))
2372 i->active_exit_timestamp = (usec_t) u;
2373 else if (streq(name, "ConditionTimestamp"))
2374 i->condition_timestamp = (usec_t) u;
2379 case DBUS_TYPE_ARRAY: {
2381 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
2382 startswith(name, "Exec")) {
2383 DBusMessageIter sub;
2385 dbus_message_iter_recurse(iter, &sub);
2386 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2387 ExecStatusInfo *info;
2390 if (!(info = new0(ExecStatusInfo, 1)))
2393 if (!(info->name = strdup(name))) {
2398 if ((r = exec_status_info_deserialize(&sub, info)) < 0) {
2403 LIST_PREPEND(ExecStatusInfo, exec, i->exec, info);
2405 dbus_message_iter_next(&sub);
2412 case DBUS_TYPE_STRUCT: {
2414 if (streq(name, "LoadError")) {
2415 DBusMessageIter sub;
2416 const char *n, *message;
2419 dbus_message_iter_recurse(iter, &sub);
2421 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &n, true);
2425 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &message, false);
2429 if (!isempty(message))
2430 i->load_error = message;
2440 static int print_property(const char *name, DBusMessageIter *iter) {
2444 /* This is a low-level property printer, see
2445 * print_status_info() for the nicer output */
2447 if (arg_property && !strv_find(arg_property, name))
2450 switch (dbus_message_iter_get_arg_type(iter)) {
2452 case DBUS_TYPE_STRUCT: {
2453 DBusMessageIter sub;
2454 dbus_message_iter_recurse(iter, &sub);
2456 if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32 && streq(name, "Job")) {
2459 dbus_message_iter_get_basic(&sub, &u);
2462 printf("%s=%u\n", name, (unsigned) u);
2464 printf("%s=\n", name);
2467 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "Unit")) {
2470 dbus_message_iter_get_basic(&sub, &s);
2472 if (arg_all || s[0])
2473 printf("%s=%s\n", name, s);
2476 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "LoadError")) {
2477 const char *a = NULL, *b = NULL;
2479 if (bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &a, true) >= 0)
2480 bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &b, false);
2482 if (arg_all || !isempty(a) || !isempty(b))
2483 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
2491 case DBUS_TYPE_ARRAY:
2493 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "EnvironmentFiles")) {
2494 DBusMessageIter sub, sub2;
2496 dbus_message_iter_recurse(iter, &sub);
2497 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2501 dbus_message_iter_recurse(&sub, &sub2);
2503 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
2504 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) >= 0)
2505 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
2507 dbus_message_iter_next(&sub);
2512 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Paths")) {
2513 DBusMessageIter sub, sub2;
2515 dbus_message_iter_recurse(iter, &sub);
2516 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2517 const char *type, *path;
2519 dbus_message_iter_recurse(&sub, &sub2);
2521 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
2522 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
2523 printf("%s=%s\n", type, path);
2525 dbus_message_iter_next(&sub);
2530 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Timers")) {
2531 DBusMessageIter sub, sub2;
2533 dbus_message_iter_recurse(iter, &sub);
2534 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2536 uint64_t value, next_elapse;
2538 dbus_message_iter_recurse(&sub, &sub2);
2540 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &base, true) >= 0 &&
2541 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &value, true) >= 0 &&
2542 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &next_elapse, false) >= 0) {
2543 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
2545 printf("%s={ value=%s ; next_elapse=%s }\n",
2547 format_timespan(timespan1, sizeof(timespan1), value),
2548 format_timespan(timespan2, sizeof(timespan2), next_elapse));
2551 dbus_message_iter_next(&sub);
2556 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "ControlGroupAttributes")) {
2557 DBusMessageIter sub, sub2;
2559 dbus_message_iter_recurse(iter, &sub);
2560 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2561 const char *controller, *attr, *value;
2563 dbus_message_iter_recurse(&sub, &sub2);
2565 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &controller, true) >= 0 &&
2566 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &attr, true) >= 0 &&
2567 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &value, false) >= 0) {
2569 printf("ControlGroupAttribute={ controller=%s ; attribute=%s ; value=\"%s\" }\n",
2575 dbus_message_iter_next(&sub);
2580 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && startswith(name, "Exec")) {
2581 DBusMessageIter sub;
2583 dbus_message_iter_recurse(iter, &sub);
2584 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2585 ExecStatusInfo info;
2588 if (exec_status_info_deserialize(&sub, &info) >= 0) {
2589 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
2592 t = strv_join(info.argv, " ");
2594 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
2598 yes_no(info.ignore),
2599 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
2600 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
2601 (unsigned) info. pid,
2602 sigchld_code_to_string(info.code),
2604 info.code == CLD_EXITED ? "" : "/",
2605 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
2611 strv_free(info.argv);
2613 dbus_message_iter_next(&sub);
2622 if (generic_print_property(name, iter, arg_all) > 0)
2626 printf("%s=[unprintable]\n", name);
2631 static int show_one(const char *verb, DBusConnection *bus, const char *path, bool show_properties, bool *new_line) {
2632 DBusMessage *m = NULL, *reply = NULL;
2633 const char *interface = "";
2636 DBusMessageIter iter, sub, sub2, sub3;
2637 UnitStatusInfo info;
2645 dbus_error_init(&error);
2647 if (!(m = dbus_message_new_method_call(
2648 "org.freedesktop.systemd1",
2650 "org.freedesktop.DBus.Properties",
2652 log_error("Could not allocate message.");
2657 if (!dbus_message_append_args(m,
2658 DBUS_TYPE_STRING, &interface,
2659 DBUS_TYPE_INVALID)) {
2660 log_error("Could not append arguments to message.");
2665 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
2666 log_error("Failed to issue method call: %s", bus_error_message(&error));
2671 if (!dbus_message_iter_init(reply, &iter) ||
2672 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
2673 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
2674 log_error("Failed to parse reply.");
2679 dbus_message_iter_recurse(&iter, &sub);
2686 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
2689 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_DICT_ENTRY) {
2690 log_error("Failed to parse reply.");
2695 dbus_message_iter_recurse(&sub, &sub2);
2697 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0) {
2698 log_error("Failed to parse reply.");
2703 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
2704 log_error("Failed to parse reply.");
2709 dbus_message_iter_recurse(&sub2, &sub3);
2711 if (show_properties)
2712 r = print_property(name, &sub3);
2714 r = status_property(name, &sub3, &info);
2717 log_error("Failed to parse reply.");
2722 dbus_message_iter_next(&sub);
2727 if (!show_properties)
2728 print_status_info(&info);
2730 if (!streq_ptr(info.active_state, "active") &&
2731 !streq_ptr(info.active_state, "reloading") &&
2732 streq(verb, "status"))
2733 /* According to LSB: "program not running" */
2736 while ((p = info.exec)) {
2737 LIST_REMOVE(ExecStatusInfo, exec, info.exec, p);
2738 exec_status_info_free(p);
2743 dbus_message_unref(m);
2746 dbus_message_unref(reply);
2748 dbus_error_free(&error);
2753 static int show(DBusConnection *bus, char **args) {
2754 DBusMessage *m = NULL, *reply = NULL;
2757 bool show_properties, new_line = false;
2763 dbus_error_init(&error);
2765 show_properties = !streq(args[0], "status");
2767 if (show_properties)
2768 pager_open_if_enabled();
2770 if (show_properties && strv_length(args) <= 1) {
2771 /* If not argument is specified inspect the manager
2774 ret = show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line);
2778 STRV_FOREACH(name, args+1) {
2779 const char *path = NULL;
2782 if (safe_atou32(*name, &id) < 0) {
2784 /* Interpret as unit name */
2786 if (!(m = dbus_message_new_method_call(
2787 "org.freedesktop.systemd1",
2788 "/org/freedesktop/systemd1",
2789 "org.freedesktop.systemd1.Manager",
2791 log_error("Could not allocate message.");
2796 if (!dbus_message_append_args(m,
2797 DBUS_TYPE_STRING, name,
2798 DBUS_TYPE_INVALID)) {
2799 log_error("Could not append arguments to message.");
2804 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
2806 if (!dbus_error_has_name(&error, DBUS_ERROR_ACCESS_DENIED)) {
2807 log_error("Failed to issue method call: %s", bus_error_message(&error));
2812 dbus_error_free(&error);
2814 dbus_message_unref(m);
2815 if (!(m = dbus_message_new_method_call(
2816 "org.freedesktop.systemd1",
2817 "/org/freedesktop/systemd1",
2818 "org.freedesktop.systemd1.Manager",
2820 log_error("Could not allocate message.");
2825 if (!dbus_message_append_args(m,
2826 DBUS_TYPE_STRING, name,
2827 DBUS_TYPE_INVALID)) {
2828 log_error("Could not append arguments to message.");
2833 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
2834 log_error("Failed to issue method call: %s", bus_error_message(&error));
2836 if (dbus_error_has_name(&error, BUS_ERROR_NO_SUCH_UNIT))
2837 ret = 4; /* According to LSB: "program or service status is unknown" */
2844 } else if (show_properties) {
2846 /* Interpret as job id */
2848 if (!(m = dbus_message_new_method_call(
2849 "org.freedesktop.systemd1",
2850 "/org/freedesktop/systemd1",
2851 "org.freedesktop.systemd1.Manager",
2853 log_error("Could not allocate message.");
2858 if (!dbus_message_append_args(m,
2859 DBUS_TYPE_UINT32, &id,
2860 DBUS_TYPE_INVALID)) {
2861 log_error("Could not append arguments to message.");
2866 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
2867 log_error("Failed to issue method call: %s", bus_error_message(&error));
2873 /* Interpret as PID */
2875 if (!(m = dbus_message_new_method_call(
2876 "org.freedesktop.systemd1",
2877 "/org/freedesktop/systemd1",
2878 "org.freedesktop.systemd1.Manager",
2880 log_error("Could not allocate message.");
2885 if (!dbus_message_append_args(m,
2886 DBUS_TYPE_UINT32, &id,
2887 DBUS_TYPE_INVALID)) {
2888 log_error("Could not append arguments to message.");
2893 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
2894 log_error("Failed to issue method call: %s", bus_error_message(&error));
2900 if (!dbus_message_get_args(reply, &error,
2901 DBUS_TYPE_OBJECT_PATH, &path,
2902 DBUS_TYPE_INVALID)) {
2903 log_error("Failed to parse reply: %s", bus_error_message(&error));
2908 if ((r = show_one(args[0], bus, path, show_properties, &new_line)) != 0)
2911 dbus_message_unref(m);
2912 dbus_message_unref(reply);
2918 dbus_message_unref(m);
2921 dbus_message_unref(reply);
2923 dbus_error_free(&error);
2928 static int dump(DBusConnection *bus, char **args) {
2929 DBusMessage *m = NULL, *reply = NULL;
2934 dbus_error_init(&error);
2936 pager_open_if_enabled();
2938 if (!(m = dbus_message_new_method_call(
2939 "org.freedesktop.systemd1",
2940 "/org/freedesktop/systemd1",
2941 "org.freedesktop.systemd1.Manager",
2943 log_error("Could not allocate message.");
2947 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
2948 log_error("Failed to issue method call: %s", bus_error_message(&error));
2953 if (!dbus_message_get_args(reply, &error,
2954 DBUS_TYPE_STRING, &text,
2955 DBUS_TYPE_INVALID)) {
2956 log_error("Failed to parse reply: %s", bus_error_message(&error));
2961 fputs(text, stdout);
2967 dbus_message_unref(m);
2970 dbus_message_unref(reply);
2972 dbus_error_free(&error);
2977 static int snapshot(DBusConnection *bus, char **args) {
2978 DBusMessage *m = NULL, *reply = NULL;
2981 const char *name = "", *path, *id;
2982 dbus_bool_t cleanup = FALSE;
2983 DBusMessageIter iter, sub;
2985 *interface = "org.freedesktop.systemd1.Unit",
2988 dbus_error_init(&error);
2990 if (!(m = dbus_message_new_method_call(
2991 "org.freedesktop.systemd1",
2992 "/org/freedesktop/systemd1",
2993 "org.freedesktop.systemd1.Manager",
2994 "CreateSnapshot"))) {
2995 log_error("Could not allocate message.");
2999 if (strv_length(args) > 1)
3002 if (!dbus_message_append_args(m,
3003 DBUS_TYPE_STRING, &name,
3004 DBUS_TYPE_BOOLEAN, &cleanup,
3005 DBUS_TYPE_INVALID)) {
3006 log_error("Could not append arguments to message.");
3011 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3012 log_error("Failed to issue method call: %s", bus_error_message(&error));
3017 if (!dbus_message_get_args(reply, &error,
3018 DBUS_TYPE_OBJECT_PATH, &path,
3019 DBUS_TYPE_INVALID)) {
3020 log_error("Failed to parse reply: %s", bus_error_message(&error));
3025 dbus_message_unref(m);
3026 if (!(m = dbus_message_new_method_call(
3027 "org.freedesktop.systemd1",
3029 "org.freedesktop.DBus.Properties",
3031 log_error("Could not allocate message.");
3035 if (!dbus_message_append_args(m,
3036 DBUS_TYPE_STRING, &interface,
3037 DBUS_TYPE_STRING, &property,
3038 DBUS_TYPE_INVALID)) {
3039 log_error("Could not append arguments to message.");
3044 dbus_message_unref(reply);
3045 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3046 log_error("Failed to issue method call: %s", bus_error_message(&error));
3051 if (!dbus_message_iter_init(reply, &iter) ||
3052 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3053 log_error("Failed to parse reply.");
3058 dbus_message_iter_recurse(&iter, &sub);
3060 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
3061 log_error("Failed to parse reply.");
3066 dbus_message_iter_get_basic(&sub, &id);
3074 dbus_message_unref(m);
3077 dbus_message_unref(reply);
3079 dbus_error_free(&error);
3084 static int delete_snapshot(DBusConnection *bus, char **args) {
3085 DBusMessage *m = NULL, *reply = NULL;
3093 dbus_error_init(&error);
3095 STRV_FOREACH(name, args+1) {
3096 const char *path = NULL;
3098 if (!(m = dbus_message_new_method_call(
3099 "org.freedesktop.systemd1",
3100 "/org/freedesktop/systemd1",
3101 "org.freedesktop.systemd1.Manager",
3103 log_error("Could not allocate message.");
3108 if (!dbus_message_append_args(m,
3109 DBUS_TYPE_STRING, name,
3110 DBUS_TYPE_INVALID)) {
3111 log_error("Could not append arguments to message.");
3116 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3117 log_error("Failed to issue method call: %s", bus_error_message(&error));
3122 if (!dbus_message_get_args(reply, &error,
3123 DBUS_TYPE_OBJECT_PATH, &path,
3124 DBUS_TYPE_INVALID)) {
3125 log_error("Failed to parse reply: %s", bus_error_message(&error));
3130 dbus_message_unref(m);
3131 if (!(m = dbus_message_new_method_call(
3132 "org.freedesktop.systemd1",
3134 "org.freedesktop.systemd1.Snapshot",
3136 log_error("Could not allocate message.");
3141 dbus_message_unref(reply);
3142 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3143 log_error("Failed to issue method call: %s", bus_error_message(&error));
3148 dbus_message_unref(m);
3149 dbus_message_unref(reply);
3157 dbus_message_unref(m);
3160 dbus_message_unref(reply);
3162 dbus_error_free(&error);
3167 static int daemon_reload(DBusConnection *bus, char **args) {
3168 DBusMessage *m = NULL, *reply = NULL;
3173 dbus_error_init(&error);
3175 if (arg_action == ACTION_RELOAD)
3177 else if (arg_action == ACTION_REEXEC)
3178 method = "Reexecute";
3180 assert(arg_action == ACTION_SYSTEMCTL);
3183 streq(args[0], "clear-jobs") ||
3184 streq(args[0], "cancel") ? "ClearJobs" :
3185 streq(args[0], "daemon-reexec") ? "Reexecute" :
3186 streq(args[0], "reset-failed") ? "ResetFailed" :
3187 streq(args[0], "halt") ? "Halt" :
3188 streq(args[0], "poweroff") ? "PowerOff" :
3189 streq(args[0], "reboot") ? "Reboot" :
3190 streq(args[0], "kexec") ? "KExec" :
3191 streq(args[0], "exit") ? "Exit" :
3192 /* "daemon-reload" */ "Reload";
3195 if (!(m = dbus_message_new_method_call(
3196 "org.freedesktop.systemd1",
3197 "/org/freedesktop/systemd1",
3198 "org.freedesktop.systemd1.Manager",
3200 log_error("Could not allocate message.");
3204 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3206 if (arg_action != ACTION_SYSTEMCTL && error_is_no_service(&error)) {
3207 /* There's always a fallback possible for
3208 * legacy actions. */
3213 if (streq(method, "Reexecute") && dbus_error_has_name(&error, DBUS_ERROR_NO_REPLY)) {
3214 /* On reexecution, we expect a disconnect, not
3220 log_error("Failed to issue method call: %s", bus_error_message(&error));
3229 dbus_message_unref(m);
3232 dbus_message_unref(reply);
3234 dbus_error_free(&error);
3239 static int reset_failed(DBusConnection *bus, char **args) {
3240 DBusMessage *m = NULL;
3246 dbus_error_init(&error);
3248 if (strv_length(args) <= 1)
3249 return daemon_reload(bus, args);
3251 STRV_FOREACH(name, args+1) {
3254 if (!(m = dbus_message_new_method_call(
3255 "org.freedesktop.systemd1",
3256 "/org/freedesktop/systemd1",
3257 "org.freedesktop.systemd1.Manager",
3258 "ResetFailedUnit"))) {
3259 log_error("Could not allocate message.");
3264 if (!dbus_message_append_args(m,
3265 DBUS_TYPE_STRING, name,
3266 DBUS_TYPE_INVALID)) {
3267 log_error("Could not append arguments to message.");
3272 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3273 log_error("Failed to issue method call: %s", bus_error_message(&error));
3278 dbus_message_unref(m);
3279 dbus_message_unref(reply);
3287 dbus_message_unref(m);
3289 dbus_error_free(&error);
3294 static int show_enviroment(DBusConnection *bus, char **args) {
3295 DBusMessage *m = NULL, *reply = NULL;
3297 DBusMessageIter iter, sub, sub2;
3300 *interface = "org.freedesktop.systemd1.Manager",
3301 *property = "Environment";
3303 dbus_error_init(&error);
3305 pager_open_if_enabled();
3307 if (!(m = dbus_message_new_method_call(
3308 "org.freedesktop.systemd1",
3309 "/org/freedesktop/systemd1",
3310 "org.freedesktop.DBus.Properties",
3312 log_error("Could not allocate message.");
3316 if (!dbus_message_append_args(m,
3317 DBUS_TYPE_STRING, &interface,
3318 DBUS_TYPE_STRING, &property,
3319 DBUS_TYPE_INVALID)) {
3320 log_error("Could not append arguments to message.");
3325 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3326 log_error("Failed to issue method call: %s", bus_error_message(&error));
3331 if (!dbus_message_iter_init(reply, &iter) ||
3332 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3333 log_error("Failed to parse reply.");
3338 dbus_message_iter_recurse(&iter, &sub);
3340 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_ARRAY ||
3341 dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_STRING) {
3342 log_error("Failed to parse reply.");
3347 dbus_message_iter_recurse(&sub, &sub2);
3349 while (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_INVALID) {
3352 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
3353 log_error("Failed to parse reply.");
3358 dbus_message_iter_get_basic(&sub2, &text);
3359 printf("%s\n", text);
3361 dbus_message_iter_next(&sub2);
3368 dbus_message_unref(m);
3371 dbus_message_unref(reply);
3373 dbus_error_free(&error);
3378 static int set_environment(DBusConnection *bus, char **args) {
3379 DBusMessage *m = NULL, *reply = NULL;
3383 DBusMessageIter iter, sub;
3386 dbus_error_init(&error);
3388 method = streq(args[0], "set-environment")
3390 : "UnsetEnvironment";
3392 if (!(m = dbus_message_new_method_call(
3393 "org.freedesktop.systemd1",
3394 "/org/freedesktop/systemd1",
3395 "org.freedesktop.systemd1.Manager",
3398 log_error("Could not allocate message.");
3402 dbus_message_iter_init_append(m, &iter);
3404 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub)) {
3405 log_error("Could not append arguments to message.");
3410 STRV_FOREACH(name, args+1)
3411 if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, name)) {
3412 log_error("Could not append arguments to message.");
3417 if (!dbus_message_iter_close_container(&iter, &sub)) {
3418 log_error("Could not append arguments to message.");
3423 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3424 log_error("Failed to issue method call: %s", bus_error_message(&error));
3433 dbus_message_unref(m);
3436 dbus_message_unref(reply);
3438 dbus_error_free(&error);
3443 static int enable_sysv_units(char **args) {
3446 #if defined (HAVE_SYSV_COMPAT) && (defined(TARGET_FEDORA) || defined(TARGET_MANDRIVA) || defined(TARGET_SUSE) || defined(TARGET_MEEGO) || defined(TARGET_ALTLINUX))
3447 const char *verb = args[0];
3448 unsigned f = 1, t = 1;
3451 if (arg_scope != UNIT_FILE_SYSTEM)
3454 if (!streq(verb, "enable") &&
3455 !streq(verb, "disable") &&
3456 !streq(verb, "is-enabled"))
3459 /* Processes all SysV units, and reshuffles the array so that
3460 * afterwards only the native units remain */
3463 r = lookup_paths_init(&paths, MANAGER_SYSTEM, false);
3469 for (f = 1; args[f]; f++) {
3472 bool found_native = false, found_sysv;
3474 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
3475 char **k, *l, *q = NULL;
3482 if (!endswith(name, ".service"))
3485 if (path_is_absolute(name))
3488 STRV_FOREACH(k, paths.unit_path) {
3491 if (!isempty(arg_root))
3492 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
3494 asprintf(&p, "%s/%s", *k, name);
3497 log_error("No memory");
3502 found_native = access(p, F_OK) >= 0;
3513 if (!isempty(arg_root))
3514 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
3516 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
3518 log_error("No memory");
3523 p[strlen(p) - sizeof(".service") + 1] = 0;
3524 found_sysv = access(p, F_OK) >= 0;
3531 /* Mark this entry, so that we don't try enabling it as native unit */
3532 args[f] = (char*) "";
3534 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
3536 if (!isempty(arg_root))
3537 argv[c++] = q = strappend("--root=", arg_root);
3539 argv[c++] = file_name_from_path(p);
3541 streq(verb, "enable") ? "on" :
3542 streq(verb, "disable") ? "off" : "--level=5";
3545 l = strv_join((char**)argv, " ");
3547 log_error("No memory.");
3554 log_info("Executing %s", l);
3559 log_error("Failed to fork: %m");
3564 } else if (pid == 0) {
3567 execv(argv[0], (char**) argv);
3568 _exit(EXIT_FAILURE);
3574 j = wait_for_terminate(pid, &status);
3576 log_error("Failed to wait for child: %s", strerror(-r));
3581 if (status.si_code == CLD_EXITED) {
3582 if (streq(verb, "is-enabled")) {
3583 if (status.si_status == 0) {
3592 } else if (status.si_status != 0) {
3603 lookup_paths_free(&paths);
3605 /* Drop all SysV units */
3606 for (f = 1, t = 1; args[f]; f++) {
3608 if (isempty(args[f]))
3611 args[t++] = args[f];
3620 static int enable_unit(DBusConnection *bus, char **args) {
3621 const char *verb = args[0];
3622 UnitFileChange *changes = NULL;
3623 unsigned n_changes = 0, i;
3624 int carries_install_info = -1;
3625 DBusMessage *m = NULL, *reply = NULL;
3629 dbus_error_init(&error);
3631 r = enable_sysv_units(args);
3635 if (!bus || avoid_bus()) {
3636 if (streq(verb, "enable")) {
3637 r = unit_file_enable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3638 carries_install_info = r;
3639 } else if (streq(verb, "disable"))
3640 r = unit_file_disable(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3641 else if (streq(verb, "reenable")) {
3642 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3643 carries_install_info = r;
3644 } else if (streq(verb, "link"))
3645 r = unit_file_link(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3646 else if (streq(verb, "preset")) {
3647 r = unit_file_preset(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3648 carries_install_info = r;
3649 } else if (streq(verb, "mask"))
3650 r = unit_file_mask(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3651 else if (streq(verb, "unmask"))
3652 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3654 assert_not_reached("Unknown verb");
3657 log_error("Operation failed: %s", strerror(-r));
3661 for (i = 0; i < n_changes; i++) {
3662 if (changes[i].type == UNIT_FILE_SYMLINK)
3663 log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
3665 log_info("rm '%s'", changes[i].path);
3670 bool send_force = true, expect_carries_install_info = false;
3672 DBusMessageIter iter, sub, sub2;
3674 if (streq(verb, "enable")) {
3675 method = "EnableUnitFiles";
3676 expect_carries_install_info = true;
3677 } else if (streq(verb, "disable")) {
3678 method = "DisableUnitFiles";
3680 } else if (streq(verb, "reenable")) {
3681 method = "ReenableUnitFiles";
3682 expect_carries_install_info = true;
3683 } else if (streq(verb, "link"))
3684 method = "LinkUnitFiles";
3685 else if (streq(verb, "preset")) {
3686 method = "PresetUnitFiles";
3687 expect_carries_install_info = true;
3688 } else if (streq(verb, "mask"))
3689 method = "MaskUnitFiles";
3690 else if (streq(verb, "unmask")) {
3691 method = "UnmaskUnitFiles";
3694 assert_not_reached("Unknown verb");
3696 m = dbus_message_new_method_call(
3697 "org.freedesktop.systemd1",
3698 "/org/freedesktop/systemd1",
3699 "org.freedesktop.systemd1.Manager",
3702 log_error("Out of memory");
3707 dbus_message_iter_init_append(m, &iter);
3709 r = bus_append_strv_iter(&iter, args+1);
3711 log_error("Failed to append unit files.");
3716 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &a)) {
3717 log_error("Failed to append runtime boolean.");
3725 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b)) {
3726 log_error("Failed to append force boolean.");
3732 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3734 log_error("Failed to issue method call: %s", bus_error_message(&error));
3739 if (!dbus_message_iter_init(reply, &iter)) {
3740 log_error("Failed to initialize iterator.");
3744 if (expect_carries_install_info) {
3745 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &b, true);
3747 log_error("Failed to parse reply.");
3751 carries_install_info = b;
3754 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3755 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
3756 log_error("Failed to parse reply.");
3761 dbus_message_iter_recurse(&iter, &sub);
3762 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
3763 const char *type, *path, *source;
3765 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
3766 log_error("Failed to parse reply.");
3771 dbus_message_iter_recurse(&sub, &sub2);
3773 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
3774 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
3775 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &source, false) < 0) {
3776 log_error("Failed to parse reply.");
3781 if (streq(type, "symlink"))
3782 log_info("ln -s '%s' '%s'", source, path);
3784 log_info("rm '%s'", path);
3786 dbus_message_iter_next(&sub);
3789 /* Try to reload if enabeld */
3791 r = daemon_reload(bus, args);
3794 if (carries_install_info == 0)
3795 log_warning("Warning: unit files do not carry install information. No operation executed.");
3799 dbus_message_unref(m);
3802 dbus_message_unref(reply);
3804 unit_file_changes_free(changes, n_changes);
3806 dbus_error_free(&error);
3810 static int unit_is_enabled(DBusConnection *bus, char **args) {
3813 DBusMessage *m = NULL, *reply = NULL;
3817 dbus_error_init(&error);
3819 r = enable_sysv_units(args);
3825 if (!bus || avoid_bus()) {
3827 STRV_FOREACH(name, args+1) {
3828 UnitFileState state;
3830 state = unit_file_get_state(arg_scope, arg_root, *name);
3836 if (state == UNIT_FILE_ENABLED ||
3837 state == UNIT_FILE_ENABLED_RUNTIME ||
3838 state == UNIT_FILE_STATIC)
3842 puts(unit_file_state_to_string(state));
3846 STRV_FOREACH(name, args+1) {
3849 m = dbus_message_new_method_call(
3850 "org.freedesktop.systemd1",
3851 "/org/freedesktop/systemd1",
3852 "org.freedesktop.systemd1.Manager",
3853 "GetUnitFileState");
3855 log_error("Out of memory");
3860 if (!dbus_message_append_args(m,
3861 DBUS_TYPE_STRING, name,
3862 DBUS_TYPE_INVALID)) {
3863 log_error("Could not append arguments to message.");
3868 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3870 log_error("Failed to issue method call: %s", bus_error_message(&error));
3875 if (!dbus_message_get_args(reply, &error,
3876 DBUS_TYPE_STRING, &s,
3877 DBUS_TYPE_INVALID)) {
3878 log_error("Failed to parse reply: %s", bus_error_message(&error));
3883 dbus_message_unref(m);
3884 dbus_message_unref(reply);
3887 if (streq(s, "enabled") ||
3888 streq(s, "enabled-runtime") ||
3897 r = enabled ? 0 : 1;
3901 dbus_message_unref(m);
3904 dbus_message_unref(reply);
3906 dbus_error_free(&error);
3910 static int systemctl_help(void) {
3912 pager_open_if_enabled();
3914 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
3915 "Query or send control commands to the systemd manager.\n\n"
3916 " -h --help Show this help\n"
3917 " --version Show package version\n"
3918 " -t --type=TYPE List only units of a particular type\n"
3919 " -p --property=NAME Show only properties by this name\n"
3920 " -a --all Show all units/properties, including dead/empty ones\n"
3921 " --failed Show only failed units\n"
3922 " --full Don't ellipsize unit names on output\n"
3923 " --fail When queueing a new job, fail if conflicting jobs are\n"
3925 " --ignore-dependencies\n"
3926 " When queueing a new job, ignore all its dependencies\n"
3927 " --kill-who=WHO Who to send signal to\n"
3928 " -s --signal=SIGNAL Which signal to send\n"
3929 " -H --host=[USER@]HOST\n"
3930 " Show information for remote host\n"
3931 " -P --privileged Acquire privileges before execution\n"
3932 " -q --quiet Suppress output\n"
3933 " --no-block Do not wait until operation finished\n"
3934 " --no-wall Don't send wall message before halt/power-off/reboot\n"
3935 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
3937 " --no-legend Do not print a legend (column headers and hints)\n"
3938 " --no-pager Do not pipe output into a pager\n"
3939 " --no-ask-password\n"
3940 " Do not ask for system passwords\n"
3941 " --order When generating graph for dot, show only order\n"
3942 " --require When generating graph for dot, show only requirement\n"
3943 " --system Connect to system manager\n"
3944 " --user Connect to user service manager\n"
3945 " --global Enable/disable unit files globally\n"
3946 " -f --force When enabling unit files, override existing symlinks\n"
3947 " When shutting down, execute action immediately\n"
3948 " --root=PATH Enable unit files in the specified root directory\n"
3949 " --runtime Enable unit files only temporarily until next reboot\n\n"
3951 " list-units List loaded units\n"
3952 " start [NAME...] Start (activate) one or more units\n"
3953 " stop [NAME...] Stop (deactivate) one or more units\n"
3954 " reload [NAME...] Reload one or more units\n"
3955 " restart [NAME...] Start or restart one or more units\n"
3956 " try-restart [NAME...] Restart one or more units if active\n"
3957 " reload-or-restart [NAME...] Reload one or more units is possible,\n"
3958 " otherwise start or restart\n"
3959 " reload-or-try-restart [NAME...] Reload one or more units is possible,\n"
3960 " otherwise restart if active\n"
3961 " isolate [NAME] Start one unit and stop all others\n"
3962 " kill [NAME...] Send signal to processes of a unit\n"
3963 " is-active [NAME...] Check whether units are active\n"
3964 " status [NAME...|PID...] Show runtime status of one or more units\n"
3965 " show [NAME...|JOB...] Show properties of one or more\n"
3966 " units/jobs or the manager\n"
3967 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
3969 " load [NAME...] Load one or more units\n\n"
3970 "Unit File Commands:\n"
3971 " list-unit-files List installed unit files\n"
3972 " enable [NAME...] Enable one or more unit files\n"
3973 " disable [NAME...] Disable one or more unit files\n"
3974 " reenable [NAME...] Reenable one or more unit files\n"
3975 " preset [NAME...] Enable/disable one or more unit files\n"
3976 " based on preset configuration\n"
3977 " mask [NAME...] Mask one or more units\n"
3978 " unmask [NAME...] Unmask one or more units\n"
3979 " link [PATH...] Link one or more units files into\n"
3980 " the search path\n"
3981 " is-enabled [NAME...] Check whether unit files are enabled\n\n"
3983 " list-jobs List jobs\n"
3984 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
3985 "Status Commands:\n"
3986 " dump Dump server status\n"
3987 " dot Dump dependency graph for dot(1)\n\n"
3988 "Snapshot Commands:\n"
3989 " snapshot [NAME] Create a snapshot\n"
3990 " delete [NAME...] Remove one or more snapshots\n\n"
3991 "Environment Commands:\n"
3992 " show-environment Dump environment\n"
3993 " set-environment [NAME=VALUE...] Set one or more environment variables\n"
3994 " unset-environment [NAME...] Unset one or more environment variables\n\n"
3995 "Manager Lifecycle Commands:\n"
3996 " daemon-reload Reload systemd manager configuration\n"
3997 " daemon-reexec Reexecute systemd manager\n\n"
3998 "System Commands:\n"
3999 " default Enter system default mode\n"
4000 " rescue Enter system rescue mode\n"
4001 " emergency Enter system emergency mode\n"
4002 " halt Shut down and halt the system\n"
4003 " poweroff Shut down and power-off the system\n"
4004 " reboot Shut down and reboot the system\n"
4005 " kexec Shut down and reboot the system with kexec\n"
4006 " exit Ask for user instance termination\n",
4007 program_invocation_short_name);
4012 static int halt_help(void) {
4014 printf("%s [OPTIONS...]\n\n"
4015 "%s the system.\n\n"
4016 " --help Show this help\n"
4017 " --halt Halt the machine\n"
4018 " -p --poweroff Switch off the machine\n"
4019 " --reboot Reboot the machine\n"
4020 " -f --force Force immediate halt/power-off/reboot\n"
4021 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
4022 " -d --no-wtmp Don't write wtmp record\n"
4023 " -n --no-sync Don't sync before halt/power-off/reboot\n"
4024 " --no-wall Don't send wall message before halt/power-off/reboot\n",
4025 program_invocation_short_name,
4026 arg_action == ACTION_REBOOT ? "Reboot" :
4027 arg_action == ACTION_POWEROFF ? "Power off" :
4033 static int shutdown_help(void) {
4035 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
4036 "Shut down the system.\n\n"
4037 " --help Show this help\n"
4038 " -H --halt Halt the machine\n"
4039 " -P --poweroff Power-off the machine\n"
4040 " -r --reboot Reboot the machine\n"
4041 " -h Equivalent to --poweroff, overriden by --halt\n"
4042 " -k Don't halt/power-off/reboot, just send warnings\n"
4043 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4044 " -c Cancel a pending shutdown\n",
4045 program_invocation_short_name);
4050 static int telinit_help(void) {
4052 printf("%s [OPTIONS...] {COMMAND}\n\n"
4053 "Send control commands to the init daemon.\n\n"
4054 " --help Show this help\n"
4055 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
4057 " 0 Power-off the machine\n"
4058 " 6 Reboot the machine\n"
4059 " 2, 3, 4, 5 Start runlevelX.target unit\n"
4060 " 1, s, S Enter rescue mode\n"
4061 " q, Q Reload init daemon configuration\n"
4062 " u, U Reexecute init daemon\n",
4063 program_invocation_short_name);
4068 static int runlevel_help(void) {
4070 printf("%s [OPTIONS...]\n\n"
4071 "Prints the previous and current runlevel of the init system.\n\n"
4072 " --help Show this help\n",
4073 program_invocation_short_name);
4078 static int systemctl_parse_argv(int argc, char *argv[]) {
4082 ARG_IGNORE_DEPENDENCIES,
4098 ARG_NO_ASK_PASSWORD,
4103 static const struct option options[] = {
4104 { "help", no_argument, NULL, 'h' },
4105 { "version", no_argument, NULL, ARG_VERSION },
4106 { "type", required_argument, NULL, 't' },
4107 { "property", required_argument, NULL, 'p' },
4108 { "all", no_argument, NULL, 'a' },
4109 { "failed", no_argument, NULL, ARG_FAILED },
4110 { "full", no_argument, NULL, ARG_FULL },
4111 { "fail", no_argument, NULL, ARG_FAIL },
4112 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
4113 { "user", no_argument, NULL, ARG_USER },
4114 { "system", no_argument, NULL, ARG_SYSTEM },
4115 { "global", no_argument, NULL, ARG_GLOBAL },
4116 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
4117 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
4118 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
4119 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4120 { "quiet", no_argument, NULL, 'q' },
4121 { "order", no_argument, NULL, ARG_ORDER },
4122 { "require", no_argument, NULL, ARG_REQUIRE },
4123 { "root", required_argument, NULL, ARG_ROOT },
4124 { "force", no_argument, NULL, 'f' },
4125 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
4126 { "kill-mode", required_argument, NULL, ARG_KILL_MODE }, /* undocumented on purpose */
4127 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
4128 { "signal", required_argument, NULL, 's' },
4129 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
4130 { "host", required_argument, NULL, 'H' },
4131 { "privileged",no_argument, NULL, 'P' },
4132 { "runtime", no_argument, NULL, ARG_RUNTIME },
4133 { NULL, 0, NULL, 0 }
4141 /* Only when running as systemctl we ask for passwords */
4142 arg_ask_password = true;
4144 while ((c = getopt_long(argc, argv, "ht:p:aqfs:H:P", options, NULL)) >= 0) {
4153 puts(PACKAGE_STRING);
4155 puts(SYSTEMD_FEATURES);
4165 if (!(l = strv_append(arg_property, optarg)))
4168 strv_free(arg_property);
4171 /* If the user asked for a particular
4172 * property, show it to him, even if it is
4183 arg_job_mode = "fail";
4186 case ARG_IGNORE_DEPENDENCIES:
4187 arg_job_mode = "ignore-dependencies";
4191 arg_scope = UNIT_FILE_USER;
4195 arg_scope = UNIT_FILE_SYSTEM;
4199 arg_scope = UNIT_FILE_GLOBAL;
4203 arg_no_block = true;
4207 arg_no_legend = true;
4211 arg_no_pager = true;
4219 arg_dot = DOT_ORDER;
4223 arg_dot = DOT_REQUIRE;
4247 arg_no_reload = true;
4251 arg_kill_who = optarg;
4255 arg_kill_mode = optarg;
4259 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
4260 log_error("Failed to parse signal string %s.", optarg);
4265 case ARG_NO_ASK_PASSWORD:
4266 arg_ask_password = false;
4270 arg_transport = TRANSPORT_POLKIT;
4274 arg_transport = TRANSPORT_SSH;
4286 log_error("Unknown option code %c", c);
4291 if (arg_transport != TRANSPORT_NORMAL && arg_scope != UNIT_FILE_SYSTEM) {
4292 log_error("Cannot access user instance remotely.");
4299 static int halt_parse_argv(int argc, char *argv[]) {
4308 static const struct option options[] = {
4309 { "help", no_argument, NULL, ARG_HELP },
4310 { "halt", no_argument, NULL, ARG_HALT },
4311 { "poweroff", no_argument, NULL, 'p' },
4312 { "reboot", no_argument, NULL, ARG_REBOOT },
4313 { "force", no_argument, NULL, 'f' },
4314 { "wtmp-only", no_argument, NULL, 'w' },
4315 { "no-wtmp", no_argument, NULL, 'd' },
4316 { "no-sync", no_argument, NULL, 'n' },
4317 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4318 { NULL, 0, NULL, 0 }
4326 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
4327 if (runlevel == '0' || runlevel == '6')
4328 arg_immediate = true;
4330 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
4338 arg_action = ACTION_HALT;
4342 if (arg_action != ACTION_REBOOT)
4343 arg_action = ACTION_POWEROFF;
4347 arg_action = ACTION_REBOOT;
4351 arg_immediate = true;
4372 /* Compatibility nops */
4379 log_error("Unknown option code %c", c);
4384 if (optind < argc) {
4385 log_error("Too many arguments.");
4392 static int parse_time_spec(const char *t, usec_t *_u) {
4396 if (streq(t, "now"))
4398 else if (!strchr(t, ':')) {
4401 if (safe_atou64(t, &u) < 0)
4404 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
4413 hour = strtol(t, &e, 10);
4414 if (errno != 0 || *e != ':' || hour < 0 || hour > 23)
4417 minute = strtol(e+1, &e, 10);
4418 if (errno != 0 || *e != 0 || minute < 0 || minute > 59)
4421 n = now(CLOCK_REALTIME);
4422 s = (time_t) (n / USEC_PER_SEC);
4425 assert_se(localtime_r(&s, &tm));
4427 tm.tm_hour = (int) hour;
4428 tm.tm_min = (int) minute;
4431 assert_se(s = mktime(&tm));
4433 *_u = (usec_t) s * USEC_PER_SEC;
4436 *_u += USEC_PER_DAY;
4442 static int shutdown_parse_argv(int argc, char *argv[]) {
4449 static const struct option options[] = {
4450 { "help", no_argument, NULL, ARG_HELP },
4451 { "halt", no_argument, NULL, 'H' },
4452 { "poweroff", no_argument, NULL, 'P' },
4453 { "reboot", no_argument, NULL, 'r' },
4454 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4455 { NULL, 0, NULL, 0 }
4463 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
4471 arg_action = ACTION_HALT;
4475 arg_action = ACTION_POWEROFF;
4480 arg_action = ACTION_KEXEC;
4482 arg_action = ACTION_REBOOT;
4486 if (arg_action != ACTION_HALT)
4487 arg_action = ACTION_POWEROFF;
4500 /* Compatibility nops */
4504 arg_action = ACTION_CANCEL_SHUTDOWN;
4511 log_error("Unknown option code %c", c);
4516 if (argc > optind) {
4517 if ((r = parse_time_spec(argv[optind], &arg_when)) < 0) {
4518 log_error("Failed to parse time specification: %s", argv[optind]);
4522 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
4524 /* We skip the time argument */
4525 if (argc > optind + 1)
4526 arg_wall = argv + optind + 1;
4533 static int telinit_parse_argv(int argc, char *argv[]) {
4540 static const struct option options[] = {
4541 { "help", no_argument, NULL, ARG_HELP },
4542 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4543 { NULL, 0, NULL, 0 }
4546 static const struct {
4550 { '0', ACTION_POWEROFF },
4551 { '6', ACTION_REBOOT },
4552 { '1', ACTION_RESCUE },
4553 { '2', ACTION_RUNLEVEL2 },
4554 { '3', ACTION_RUNLEVEL3 },
4555 { '4', ACTION_RUNLEVEL4 },
4556 { '5', ACTION_RUNLEVEL5 },
4557 { 's', ACTION_RESCUE },
4558 { 'S', ACTION_RESCUE },
4559 { 'q', ACTION_RELOAD },
4560 { 'Q', ACTION_RELOAD },
4561 { 'u', ACTION_REEXEC },
4562 { 'U', ACTION_REEXEC }
4571 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4586 log_error("Unknown option code %c", c);
4591 if (optind >= argc) {
4596 if (optind + 1 < argc) {
4597 log_error("Too many arguments.");
4601 if (strlen(argv[optind]) != 1) {
4602 log_error("Expected single character argument.");
4606 for (i = 0; i < ELEMENTSOF(table); i++)
4607 if (table[i].from == argv[optind][0])
4610 if (i >= ELEMENTSOF(table)) {
4611 log_error("Unknown command %s.", argv[optind]);
4615 arg_action = table[i].to;
4622 static int runlevel_parse_argv(int argc, char *argv[]) {
4628 static const struct option options[] = {
4629 { "help", no_argument, NULL, ARG_HELP },
4630 { NULL, 0, NULL, 0 }
4638 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4649 log_error("Unknown option code %c", c);
4654 if (optind < argc) {
4655 log_error("Too many arguments.");
4662 static int parse_argv(int argc, char *argv[]) {
4666 if (program_invocation_short_name) {
4668 if (strstr(program_invocation_short_name, "halt")) {
4669 arg_action = ACTION_HALT;
4670 return halt_parse_argv(argc, argv);
4671 } else if (strstr(program_invocation_short_name, "poweroff")) {
4672 arg_action = ACTION_POWEROFF;
4673 return halt_parse_argv(argc, argv);
4674 } else if (strstr(program_invocation_short_name, "reboot")) {
4676 arg_action = ACTION_KEXEC;
4678 arg_action = ACTION_REBOOT;
4679 return halt_parse_argv(argc, argv);
4680 } else if (strstr(program_invocation_short_name, "shutdown")) {
4681 arg_action = ACTION_POWEROFF;
4682 return shutdown_parse_argv(argc, argv);
4683 } else if (strstr(program_invocation_short_name, "init")) {
4685 if (sd_booted() > 0) {
4686 arg_action = ACTION_INVALID;
4687 return telinit_parse_argv(argc, argv);
4689 /* Hmm, so some other init system is
4690 * running, we need to forward this
4691 * request to it. For now we simply
4692 * guess that it is Upstart. */
4694 execv("/lib/upstart/telinit", argv);
4696 log_error("Couldn't find an alternative telinit implementation to spawn.");
4700 } else if (strstr(program_invocation_short_name, "runlevel")) {
4701 arg_action = ACTION_RUNLEVEL;
4702 return runlevel_parse_argv(argc, argv);
4706 arg_action = ACTION_SYSTEMCTL;
4707 return systemctl_parse_argv(argc, argv);
4710 static int action_to_runlevel(void) {
4712 static const char table[_ACTION_MAX] = {
4713 [ACTION_HALT] = '0',
4714 [ACTION_POWEROFF] = '0',
4715 [ACTION_REBOOT] = '6',
4716 [ACTION_RUNLEVEL2] = '2',
4717 [ACTION_RUNLEVEL3] = '3',
4718 [ACTION_RUNLEVEL4] = '4',
4719 [ACTION_RUNLEVEL5] = '5',
4720 [ACTION_RESCUE] = '1'
4723 assert(arg_action < _ACTION_MAX);
4725 return table[arg_action];
4728 static int talk_upstart(void) {
4729 DBusMessage *m = NULL, *reply = NULL;
4731 int previous, rl, r;
4733 env1_buf[] = "RUNLEVEL=X",
4734 env2_buf[] = "PREVLEVEL=X";
4735 char *env1 = env1_buf, *env2 = env2_buf;
4736 const char *emit = "runlevel";
4737 dbus_bool_t b_false = FALSE;
4738 DBusMessageIter iter, sub;
4739 DBusConnection *bus;
4741 dbus_error_init(&error);
4743 if (!(rl = action_to_runlevel()))
4746 if (utmp_get_runlevel(&previous, NULL) < 0)
4749 if (!(bus = dbus_connection_open_private("unix:abstract=/com/ubuntu/upstart", &error))) {
4750 if (dbus_error_has_name(&error, DBUS_ERROR_NO_SERVER)) {
4755 log_error("Failed to connect to Upstart bus: %s", bus_error_message(&error));
4760 if ((r = bus_check_peercred(bus)) < 0) {
4761 log_error("Failed to verify owner of bus.");
4765 if (!(m = dbus_message_new_method_call(
4766 "com.ubuntu.Upstart",
4767 "/com/ubuntu/Upstart",
4768 "com.ubuntu.Upstart0_6",
4771 log_error("Could not allocate message.");
4776 dbus_message_iter_init_append(m, &iter);
4778 env1_buf[sizeof(env1_buf)-2] = rl;
4779 env2_buf[sizeof(env2_buf)-2] = previous;
4781 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &emit) ||
4782 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub) ||
4783 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env1) ||
4784 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env2) ||
4785 !dbus_message_iter_close_container(&iter, &sub) ||
4786 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b_false)) {
4787 log_error("Could not append arguments to message.");
4792 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
4794 if (error_is_no_service(&error)) {
4799 log_error("Failed to issue method call: %s", bus_error_message(&error));
4808 dbus_message_unref(m);
4811 dbus_message_unref(reply);
4814 dbus_connection_flush(bus);
4815 dbus_connection_close(bus);
4816 dbus_connection_unref(bus);
4819 dbus_error_free(&error);
4824 static int talk_initctl(void) {
4825 struct init_request request;
4829 if (!(rl = action_to_runlevel()))
4833 request.magic = INIT_MAGIC;
4834 request.sleeptime = 0;
4835 request.cmd = INIT_CMD_RUNLVL;
4836 request.runlevel = rl;
4838 if ((fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY)) < 0) {
4840 if (errno == ENOENT)
4843 log_error("Failed to open "INIT_FIFO": %m");
4848 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
4849 close_nointr_nofail(fd);
4852 log_error("Failed to write to "INIT_FIFO": %m");
4853 return errno ? -errno : -EIO;
4859 static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
4861 static const struct {
4869 int (* const dispatch)(DBusConnection *bus, char **args);
4871 { "list-units", LESS, 1, list_units },
4872 { "list-unit-files", EQUAL, 1, list_unit_files },
4873 { "list-jobs", EQUAL, 1, list_jobs },
4874 { "clear-jobs", EQUAL, 1, daemon_reload },
4875 { "load", MORE, 2, load_unit },
4876 { "cancel", MORE, 2, cancel_job },
4877 { "start", MORE, 2, start_unit },
4878 { "stop", MORE, 2, start_unit },
4879 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
4880 { "reload", MORE, 2, start_unit },
4881 { "restart", MORE, 2, start_unit },
4882 { "try-restart", MORE, 2, start_unit },
4883 { "reload-or-restart", MORE, 2, start_unit },
4884 { "reload-or-try-restart", MORE, 2, start_unit },
4885 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
4886 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
4887 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
4888 { "isolate", EQUAL, 2, start_unit },
4889 { "kill", MORE, 2, kill_unit },
4890 { "is-active", MORE, 2, check_unit },
4891 { "check", MORE, 2, check_unit },
4892 { "show", MORE, 1, show },
4893 { "status", MORE, 2, show },
4894 { "dump", EQUAL, 1, dump },
4895 { "dot", EQUAL, 1, dot },
4896 { "snapshot", LESS, 2, snapshot },
4897 { "delete", MORE, 2, delete_snapshot },
4898 { "daemon-reload", EQUAL, 1, daemon_reload },
4899 { "daemon-reexec", EQUAL, 1, daemon_reload },
4900 { "show-environment", EQUAL, 1, show_enviroment },
4901 { "set-environment", MORE, 2, set_environment },
4902 { "unset-environment", MORE, 2, set_environment },
4903 { "halt", EQUAL, 1, start_special },
4904 { "poweroff", EQUAL, 1, start_special },
4905 { "reboot", EQUAL, 1, start_special },
4906 { "kexec", EQUAL, 1, start_special },
4907 { "default", EQUAL, 1, start_special },
4908 { "rescue", EQUAL, 1, start_special },
4909 { "emergency", EQUAL, 1, start_special },
4910 { "exit", EQUAL, 1, start_special },
4911 { "reset-failed", MORE, 1, reset_failed },
4912 { "enable", MORE, 2, enable_unit },
4913 { "disable", MORE, 2, enable_unit },
4914 { "is-enabled", MORE, 2, unit_is_enabled },
4915 { "reenable", MORE, 2, enable_unit },
4916 { "preset", MORE, 2, enable_unit },
4917 { "mask", MORE, 2, enable_unit },
4918 { "unmask", MORE, 2, enable_unit },
4919 { "link", MORE, 2, enable_unit }
4929 left = argc - optind;
4932 /* Special rule: no arguments means "list-units" */
4935 if (streq(argv[optind], "help")) {
4940 for (i = 0; i < ELEMENTSOF(verbs); i++)
4941 if (streq(argv[optind], verbs[i].verb))
4944 if (i >= ELEMENTSOF(verbs)) {
4945 log_error("Unknown operation %s", argv[optind]);
4950 switch (verbs[i].argc_cmp) {
4953 if (left != verbs[i].argc) {
4954 log_error("Invalid number of arguments.");
4961 if (left < verbs[i].argc) {
4962 log_error("Too few arguments.");
4969 if (left > verbs[i].argc) {
4970 log_error("Too many arguments.");
4977 assert_not_reached("Unknown comparison operator.");
4980 /* Require a bus connection for all operations but
4982 if (!streq(verbs[i].verb, "enable") &&
4983 !streq(verbs[i].verb, "disable") &&
4984 !streq(verbs[i].verb, "is-enable") &&
4985 !streq(verbs[i].verb, "reenable") &&
4986 !streq(verbs[i].verb, "preset") &&
4987 !streq(verbs[i].verb, "mask") &&
4988 !streq(verbs[i].verb, "unmask") &&
4989 !streq(verbs[i].verb, "link")) {
4991 if (running_in_chroot() > 0) {
4992 log_info("Running in chroot, ignoring request.");
4997 log_error("Failed to get D-Bus connection: %s",
4998 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5004 if (!bus && !avoid_bus()) {
5005 log_error("Failed to get D-Bus connection: %s",
5006 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5011 return verbs[i].dispatch(bus, argv + optind);
5014 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
5016 struct msghdr msghdr;
5018 union sockaddr_union sockaddr;
5019 struct shutdownd_command c;
5024 c.dry_run = dry_run;
5028 strncpy(c.wall_message, message, sizeof(c.wall_message));
5030 if ((fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0)) < 0)
5034 sockaddr.sa.sa_family = AF_UNIX;
5035 sockaddr.un.sun_path[0] = 0;
5036 strncpy(sockaddr.un.sun_path, "/run/systemd/shutdownd", sizeof(sockaddr.un.sun_path));
5039 iovec.iov_base = (char*) &c;
5040 iovec.iov_len = sizeof(c);
5043 msghdr.msg_name = &sockaddr;
5044 msghdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + sizeof("/run/systemd/shutdownd") - 1;
5046 msghdr.msg_iov = &iovec;
5047 msghdr.msg_iovlen = 1;
5049 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0) {
5050 close_nointr_nofail(fd);
5054 close_nointr_nofail(fd);
5058 static int reload_with_fallback(DBusConnection *bus) {
5061 /* First, try systemd via D-Bus. */
5062 if (daemon_reload(bus, NULL) >= 0)
5066 /* Nothing else worked, so let's try signals */
5067 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
5069 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
5070 log_error("kill() failed: %m");
5077 static int start_with_fallback(DBusConnection *bus) {
5080 /* First, try systemd via D-Bus. */
5081 if (start_unit(bus, NULL) >= 0)
5085 /* Hmm, talking to systemd via D-Bus didn't work. Then
5086 * let's try to talk to Upstart via D-Bus. */
5087 if (talk_upstart() > 0)
5090 /* Nothing else worked, so let's try
5092 if (talk_initctl() > 0)
5095 log_error("Failed to talk to init daemon.");
5099 warn_wall(arg_action);
5103 static int halt_main(DBusConnection *bus) {
5106 if (geteuid() != 0) {
5107 log_error("Must be root.");
5113 char date[FORMAT_TIMESTAMP_MAX];
5115 m = strv_join(arg_wall, " ");
5116 r = send_shutdownd(arg_when,
5117 arg_action == ACTION_HALT ? 'H' :
5118 arg_action == ACTION_POWEROFF ? 'P' :
5126 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
5128 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
5129 format_timestamp(date, sizeof(date), arg_when));
5134 if (!arg_dry && !arg_immediate)
5135 return start_with_fallback(bus);
5138 if (sd_booted() > 0)
5139 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
5140 else if ((r = utmp_put_shutdown(0)) < 0)
5141 log_warning("Failed to write utmp record: %s", strerror(-r));
5150 /* Make sure C-A-D is handled by the kernel from this
5152 reboot(RB_ENABLE_CAD);
5154 switch (arg_action) {
5157 log_info("Halting.");
5158 reboot(RB_HALT_SYSTEM);
5161 case ACTION_POWEROFF:
5162 log_info("Powering off.");
5163 reboot(RB_POWER_OFF);
5167 log_info("Rebooting.");
5168 reboot(RB_AUTOBOOT);
5172 assert_not_reached("Unknown halt action.");
5175 /* We should never reach this. */
5179 static int runlevel_main(void) {
5180 int r, runlevel, previous;
5182 r = utmp_get_runlevel(&runlevel, &previous);
5189 previous <= 0 ? 'N' : previous,
5190 runlevel <= 0 ? 'N' : runlevel);
5195 int main(int argc, char*argv[]) {
5196 int r, retval = EXIT_FAILURE;
5197 DBusConnection *bus = NULL;
5200 dbus_error_init(&error);
5202 log_parse_environment();
5205 if ((r = parse_argv(argc, argv)) < 0)
5208 retval = EXIT_SUCCESS;
5212 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
5213 * let's shortcut this */
5214 if (arg_action == ACTION_RUNLEVEL) {
5215 r = runlevel_main();
5216 retval = r < 0 ? EXIT_FAILURE : r;
5220 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
5221 log_info("Running in chroot, ignoring request.");
5227 if (arg_transport == TRANSPORT_NORMAL)
5228 bus_connect(arg_scope == UNIT_FILE_SYSTEM ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &bus, &private_bus, &error);
5229 else if (arg_transport == TRANSPORT_POLKIT) {
5230 bus_connect_system_polkit(&bus, &error);
5231 private_bus = false;
5232 } else if (arg_transport == TRANSPORT_SSH) {
5233 bus_connect_system_ssh(NULL, arg_host, &bus, &error);
5234 private_bus = false;
5236 assert_not_reached("Uh, invalid transport...");
5239 switch (arg_action) {
5241 case ACTION_SYSTEMCTL:
5242 r = systemctl_main(bus, argc, argv, &error);
5246 case ACTION_POWEROFF:
5252 case ACTION_RUNLEVEL2:
5253 case ACTION_RUNLEVEL3:
5254 case ACTION_RUNLEVEL4:
5255 case ACTION_RUNLEVEL5:
5257 case ACTION_EMERGENCY:
5258 case ACTION_DEFAULT:
5259 r = start_with_fallback(bus);
5264 r = reload_with_fallback(bus);
5267 case ACTION_CANCEL_SHUTDOWN:
5268 r = send_shutdownd(0, 0, false, false, NULL);
5271 case ACTION_INVALID:
5272 case ACTION_RUNLEVEL:
5274 assert_not_reached("Unknown action");
5277 retval = r < 0 ? EXIT_FAILURE : r;
5281 dbus_connection_flush(bus);
5282 dbus_connection_close(bus);
5283 dbus_connection_unref(bus);
5286 dbus_error_free(&error);
5290 strv_free(arg_property);