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, "error")) {
381 on_loaded = ansi_highlight(true);
382 off_loaded = ansi_highlight(false);
384 on_loaded = off_loaded = "";
386 if (streq(u->active_state, "failed")) {
387 on_active = ansi_highlight(true);
388 off_active = ansi_highlight(false);
390 on_active = off_active = "";
392 e = arg_full ? NULL : ellipsize(u->id, id_len, 33);
394 printf("%-*s %s%-6s%s %s%-*s %-*s%s %-*s ",
395 id_len, e ? e : u->id,
396 on_loaded, u->load_state, off_loaded,
397 on_active, active_len, u->active_state,
398 sub_len, u->sub_state, off_active,
399 job_len, u->job_id ? u->job_type : "");
400 if (!arg_full && arg_no_pager)
401 printf("%.*s\n", desc_len, u->description);
403 printf("%s\n", u->description);
408 if (!arg_no_legend) {
409 printf("\nLOAD = Reflects whether the unit definition was properly loaded.\n"
410 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
411 "SUB = The low-level unit activation state, values depend on unit type.\n"
412 "JOB = Pending job for the unit.\n");
415 printf("\n%u units listed.\n", n_shown);
417 printf("\n%u units listed. Pass --all to see inactive units, too.\n", n_shown);
421 static int list_units(DBusConnection *bus, char **args) {
422 DBusMessage *m = NULL, *reply = NULL;
425 DBusMessageIter iter, sub, sub2;
426 unsigned c = 0, n_units = 0;
427 struct unit_info *unit_infos = NULL;
429 dbus_error_init(&error);
433 pager_open_if_enabled();
435 if (!(m = dbus_message_new_method_call(
436 "org.freedesktop.systemd1",
437 "/org/freedesktop/systemd1",
438 "org.freedesktop.systemd1.Manager",
440 log_error("Could not allocate message.");
444 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
445 log_error("Failed to issue method call: %s", bus_error_message(&error));
450 if (!dbus_message_iter_init(reply, &iter) ||
451 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
452 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
453 log_error("Failed to parse reply.");
458 dbus_message_iter_recurse(&iter, &sub);
460 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
463 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
464 log_error("Failed to parse reply.");
472 n_units = MAX(2*c, 16);
473 w = realloc(unit_infos, sizeof(struct unit_info) * n_units);
476 log_error("Failed to allocate unit array.");
486 dbus_message_iter_recurse(&sub, &sub2);
488 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->id, true) < 0 ||
489 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->description, true) < 0 ||
490 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->load_state, true) < 0 ||
491 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->active_state, true) < 0 ||
492 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->sub_state, true) < 0 ||
493 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->following, true) < 0 ||
494 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &u->unit_path, true) < 0 ||
495 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &u->job_id, true) < 0 ||
496 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->job_type, true) < 0 ||
497 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &u->job_path, false) < 0) {
498 log_error("Failed to parse reply.");
503 dbus_message_iter_next(&sub);
508 qsort(unit_infos, c, sizeof(struct unit_info), compare_unit_info);
509 output_units_list(unit_infos, c);
516 dbus_message_unref(m);
519 dbus_message_unref(reply);
523 dbus_error_free(&error);
528 static int compare_unit_file_list(const void *a, const void *b) {
530 const UnitFileList *u = a, *v = b;
532 d1 = strrchr(u->path, '.');
533 d2 = strrchr(v->path, '.');
538 r = strcasecmp(d1, d2);
543 return strcasecmp(file_name_from_path(u->path), file_name_from_path(v->path));
546 static bool output_show_unit_file(const UnitFileList *u) {
549 return !arg_type || ((dot = strrchr(u->path, '.')) && streq(dot+1, arg_type));
552 static void output_unit_file_list(const UnitFileList *units, unsigned c) {
553 unsigned max_id_len, id_cols, state_cols, n_shown = 0;
554 const UnitFileList *u;
556 max_id_len = sizeof("UNIT FILE")-1;
557 state_cols = sizeof("STATE")-1;
558 for (u = units; u < units + c; u++) {
559 if (!output_show_unit_file(u))
562 max_id_len = MAX(max_id_len, strlen(file_name_from_path(u->path)));
563 state_cols = MAX(state_cols, strlen(unit_file_state_to_string(u->state)));
568 id_cols = MIN(max_id_len, 25);
569 basic_cols = 1 + id_cols + state_cols;
570 if (basic_cols < (unsigned) columns())
571 id_cols += MIN(columns() - basic_cols, max_id_len - id_cols);
573 id_cols = max_id_len;
576 printf("%-*s %-*s\n", id_cols, "UNIT FILE", state_cols, "STATE");
578 for (u = units; u < units + c; u++) {
580 const char *on, *off;
583 if (!output_show_unit_file(u))
588 if (u->state == UNIT_FILE_MASKED ||
589 u->state == UNIT_FILE_MASKED_RUNTIME ||
590 u->state == UNIT_FILE_DISABLED) {
591 on = ansi_highlight(true);
592 off = ansi_highlight(false);
593 } else if (u->state == UNIT_FILE_ENABLED) {
594 on = ansi_highlight_green(true);
595 off = ansi_highlight_green(false);
599 id = file_name_from_path(u->path);
601 e = arg_full ? NULL : ellipsize(id, id_cols, 33);
603 printf("%-*s %s%-*s%s\n",
605 on, state_cols, unit_file_state_to_string(u->state), off);
611 printf("\n%u unit files listed.\n", n_shown);
614 static int list_unit_files(DBusConnection *bus, char **args) {
615 DBusMessage *m = NULL, *reply = NULL;
618 DBusMessageIter iter, sub, sub2;
619 unsigned c = 0, n_units = 0;
620 UnitFileList *units = NULL;
622 dbus_error_init(&error);
624 pager_open_if_enabled();
631 h = hashmap_new(string_hash_func, string_compare_func);
633 log_error("Out of memory");
637 r = unit_file_get_list(arg_scope, arg_root, h);
639 unit_file_list_free(h);
640 log_error("Failed to get unit file list: %s", strerror(-r));
644 n_units = hashmap_size(h);
645 units = new(UnitFileList, n_units);
647 unit_file_list_free(h);
648 log_error("Out of memory");
652 HASHMAP_FOREACH(u, h, i) {
653 memcpy(units + c++, u, sizeof(UnitFileList));
661 m = dbus_message_new_method_call(
662 "org.freedesktop.systemd1",
663 "/org/freedesktop/systemd1",
664 "org.freedesktop.systemd1.Manager",
667 log_error("Could not allocate message.");
671 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
673 log_error("Failed to issue method call: %s", bus_error_message(&error));
678 if (!dbus_message_iter_init(reply, &iter) ||
679 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
680 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
681 log_error("Failed to parse reply.");
686 dbus_message_iter_recurse(&iter, &sub);
688 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
692 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
693 log_error("Failed to parse reply.");
701 n_units = MAX(2*c, 16);
702 w = realloc(units, sizeof(struct UnitFileList) * n_units);
705 log_error("Failed to allocate unit array.");
715 dbus_message_iter_recurse(&sub, &sub2);
717 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->path, true) < 0 ||
718 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, false) < 0) {
719 log_error("Failed to parse reply.");
724 u->state = unit_file_state_from_string(state);
726 dbus_message_iter_next(&sub);
732 qsort(units, c, sizeof(UnitFileList), compare_unit_file_list);
733 output_unit_file_list(units, c);
740 dbus_message_unref(m);
743 dbus_message_unref(reply);
747 dbus_error_free(&error);
752 static int dot_one_property(const char *name, const char *prop, DBusMessageIter *iter) {
753 static const char * const colors[] = {
754 "Requires", "[color=\"black\"]",
755 "RequiresOverridable", "[color=\"black\"]",
756 "Requisite", "[color=\"darkblue\"]",
757 "RequisiteOverridable", "[color=\"darkblue\"]",
758 "Wants", "[color=\"darkgrey\"]",
759 "Conflicts", "[color=\"red\"]",
760 "ConflictedBy", "[color=\"red\"]",
761 "After", "[color=\"green\"]"
764 const char *c = NULL;
771 for (i = 0; i < ELEMENTSOF(colors); i += 2)
772 if (streq(colors[i], prop)) {
780 if (arg_dot != DOT_ALL)
781 if ((arg_dot == DOT_ORDER) != streq(prop, "After"))
784 switch (dbus_message_iter_get_arg_type(iter)) {
786 case DBUS_TYPE_ARRAY:
788 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING) {
791 dbus_message_iter_recurse(iter, &sub);
793 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
796 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING);
797 dbus_message_iter_get_basic(&sub, &s);
798 printf("\t\"%s\"->\"%s\" %s;\n", name, s, c);
800 dbus_message_iter_next(&sub);
810 static int dot_one(DBusConnection *bus, const char *name, const char *path) {
811 DBusMessage *m = NULL, *reply = NULL;
812 const char *interface = "org.freedesktop.systemd1.Unit";
815 DBusMessageIter iter, sub, sub2, sub3;
820 dbus_error_init(&error);
822 if (!(m = dbus_message_new_method_call(
823 "org.freedesktop.systemd1",
825 "org.freedesktop.DBus.Properties",
827 log_error("Could not allocate message.");
832 if (!dbus_message_append_args(m,
833 DBUS_TYPE_STRING, &interface,
834 DBUS_TYPE_INVALID)) {
835 log_error("Could not append arguments to message.");
840 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
841 log_error("Failed to issue method call: %s", bus_error_message(&error));
846 if (!dbus_message_iter_init(reply, &iter) ||
847 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
848 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
849 log_error("Failed to parse reply.");
854 dbus_message_iter_recurse(&iter, &sub);
856 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
859 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_DICT_ENTRY) {
860 log_error("Failed to parse reply.");
865 dbus_message_iter_recurse(&sub, &sub2);
867 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &prop, true) < 0) {
868 log_error("Failed to parse reply.");
873 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
874 log_error("Failed to parse reply.");
879 dbus_message_iter_recurse(&sub2, &sub3);
881 if (dot_one_property(name, prop, &sub3)) {
882 log_error("Failed to parse reply.");
887 dbus_message_iter_next(&sub);
894 dbus_message_unref(m);
897 dbus_message_unref(reply);
899 dbus_error_free(&error);
904 static int dot(DBusConnection *bus, char **args) {
905 DBusMessage *m = NULL, *reply = NULL;
908 DBusMessageIter iter, sub, sub2;
910 dbus_error_init(&error);
914 if (!(m = dbus_message_new_method_call(
915 "org.freedesktop.systemd1",
916 "/org/freedesktop/systemd1",
917 "org.freedesktop.systemd1.Manager",
919 log_error("Could not allocate message.");
923 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
924 log_error("Failed to issue method call: %s", bus_error_message(&error));
929 if (!dbus_message_iter_init(reply, &iter) ||
930 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
931 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
932 log_error("Failed to parse reply.");
937 printf("digraph systemd {\n");
939 dbus_message_iter_recurse(&iter, &sub);
940 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
941 const char *id, *description, *load_state, *active_state, *sub_state, *following, *unit_path;
943 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
944 log_error("Failed to parse reply.");
949 dbus_message_iter_recurse(&sub, &sub2);
951 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &id, true) < 0 ||
952 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &description, true) < 0 ||
953 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &load_state, true) < 0 ||
954 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &active_state, true) < 0 ||
955 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &sub_state, true) < 0 ||
956 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &following, true) < 0 ||
957 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, true) < 0) {
958 log_error("Failed to parse reply.");
963 if ((r = dot_one(bus, id, unit_path)) < 0)
966 /* printf("\t\"%s\";\n", id); */
967 dbus_message_iter_next(&sub);
972 log_info(" Color legend: black = Requires\n"
973 " dark blue = Requisite\n"
974 " dark grey = Wants\n"
979 log_notice("-- You probably want to process this output with graphviz' dot tool.\n"
980 "-- Try a shell pipeline like 'systemctl dot | dot -Tsvg > systemd.svg'!\n");
986 dbus_message_unref(m);
989 dbus_message_unref(reply);
991 dbus_error_free(&error);
996 static int list_jobs(DBusConnection *bus, char **args) {
997 DBusMessage *m = NULL, *reply = NULL;
1000 DBusMessageIter iter, sub, sub2;
1003 dbus_error_init(&error);
1007 pager_open_if_enabled();
1009 if (!(m = dbus_message_new_method_call(
1010 "org.freedesktop.systemd1",
1011 "/org/freedesktop/systemd1",
1012 "org.freedesktop.systemd1.Manager",
1014 log_error("Could not allocate message.");
1018 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
1019 log_error("Failed to issue method call: %s", bus_error_message(&error));
1024 if (!dbus_message_iter_init(reply, &iter) ||
1025 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
1026 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
1027 log_error("Failed to parse reply.");
1032 dbus_message_iter_recurse(&iter, &sub);
1035 printf("%4s %-25s %-15s %-7s\n", "JOB", "UNIT", "TYPE", "STATE");
1037 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1038 const char *name, *type, *state, *job_path, *unit_path;
1042 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
1043 log_error("Failed to parse reply.");
1048 dbus_message_iter_recurse(&sub, &sub2);
1050 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &id, true) < 0 ||
1051 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
1052 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
1053 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, true) < 0 ||
1054 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &job_path, true) < 0 ||
1055 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, false) < 0) {
1056 log_error("Failed to parse reply.");
1061 e = arg_full ? NULL : ellipsize(name, 25, 33);
1062 printf("%4u %-25s %-15s %-7s\n", id, e ? e : name, type, state);
1067 dbus_message_iter_next(&sub);
1071 printf("\n%u jobs listed.\n", k);
1077 dbus_message_unref(m);
1080 dbus_message_unref(reply);
1082 dbus_error_free(&error);
1087 static int load_unit(DBusConnection *bus, char **args) {
1088 DBusMessage *m = NULL;
1093 dbus_error_init(&error);
1098 STRV_FOREACH(name, args+1) {
1101 if (!(m = dbus_message_new_method_call(
1102 "org.freedesktop.systemd1",
1103 "/org/freedesktop/systemd1",
1104 "org.freedesktop.systemd1.Manager",
1106 log_error("Could not allocate message.");
1111 if (!dbus_message_append_args(m,
1112 DBUS_TYPE_STRING, name,
1113 DBUS_TYPE_INVALID)) {
1114 log_error("Could not append arguments to message.");
1119 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
1120 log_error("Failed to issue method call: %s", bus_error_message(&error));
1125 dbus_message_unref(m);
1126 dbus_message_unref(reply);
1135 dbus_message_unref(m);
1137 dbus_error_free(&error);
1142 static int cancel_job(DBusConnection *bus, char **args) {
1143 DBusMessage *m = NULL, *reply = NULL;
1148 dbus_error_init(&error);
1153 if (strv_length(args) <= 1)
1154 return daemon_reload(bus, args);
1156 STRV_FOREACH(name, args+1) {
1160 if (!(m = dbus_message_new_method_call(
1161 "org.freedesktop.systemd1",
1162 "/org/freedesktop/systemd1",
1163 "org.freedesktop.systemd1.Manager",
1165 log_error("Could not allocate message.");
1170 if ((r = safe_atou(*name, &id)) < 0) {
1171 log_error("Failed to parse job id: %s", strerror(-r));
1175 assert_cc(sizeof(uint32_t) == sizeof(id));
1176 if (!dbus_message_append_args(m,
1177 DBUS_TYPE_UINT32, &id,
1178 DBUS_TYPE_INVALID)) {
1179 log_error("Could not append arguments to message.");
1184 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
1185 log_error("Failed to issue method call: %s", bus_error_message(&error));
1190 if (!dbus_message_get_args(reply, &error,
1191 DBUS_TYPE_OBJECT_PATH, &path,
1192 DBUS_TYPE_INVALID)) {
1193 log_error("Failed to parse reply: %s", bus_error_message(&error));
1198 dbus_message_unref(m);
1199 if (!(m = dbus_message_new_method_call(
1200 "org.freedesktop.systemd1",
1202 "org.freedesktop.systemd1.Job",
1204 log_error("Could not allocate message.");
1209 dbus_message_unref(reply);
1210 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
1211 log_error("Failed to issue method call: %s", bus_error_message(&error));
1216 dbus_message_unref(m);
1217 dbus_message_unref(reply);
1225 dbus_message_unref(m);
1228 dbus_message_unref(reply);
1230 dbus_error_free(&error);
1235 static bool need_daemon_reload(DBusConnection *bus, const char *unit) {
1236 DBusMessage *m = NULL, *reply = NULL;
1237 dbus_bool_t b = FALSE;
1238 DBusMessageIter iter, sub;
1240 *interface = "org.freedesktop.systemd1.Unit",
1241 *property = "NeedDaemonReload",
1244 /* We ignore all errors here, since this is used to show a warning only */
1246 if (!(m = dbus_message_new_method_call(
1247 "org.freedesktop.systemd1",
1248 "/org/freedesktop/systemd1",
1249 "org.freedesktop.systemd1.Manager",
1253 if (!dbus_message_append_args(m,
1254 DBUS_TYPE_STRING, &unit,
1258 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, NULL)))
1261 if (!dbus_message_get_args(reply, NULL,
1262 DBUS_TYPE_OBJECT_PATH, &path,
1266 dbus_message_unref(m);
1267 if (!(m = dbus_message_new_method_call(
1268 "org.freedesktop.systemd1",
1270 "org.freedesktop.DBus.Properties",
1274 if (!dbus_message_append_args(m,
1275 DBUS_TYPE_STRING, &interface,
1276 DBUS_TYPE_STRING, &property,
1277 DBUS_TYPE_INVALID)) {
1281 dbus_message_unref(reply);
1282 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, NULL)))
1285 if (!dbus_message_iter_init(reply, &iter) ||
1286 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
1289 dbus_message_iter_recurse(&iter, &sub);
1291 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_BOOLEAN)
1294 dbus_message_iter_get_basic(&sub, &b);
1298 dbus_message_unref(m);
1301 dbus_message_unref(reply);
1306 typedef struct WaitData {
1311 static DBusHandlerResult wait_filter(DBusConnection *connection, DBusMessage *message, void *data) {
1319 dbus_error_init(&error);
1321 log_debug("Got D-Bus request: %s.%s() on %s",
1322 dbus_message_get_interface(message),
1323 dbus_message_get_member(message),
1324 dbus_message_get_path(message));
1326 if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
1327 log_error("Warning! D-Bus connection terminated.");
1328 dbus_connection_close(connection);
1330 } else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
1332 const char *path, *result;
1333 dbus_bool_t success = true;
1335 if (dbus_message_get_args(message, &error,
1336 DBUS_TYPE_UINT32, &id,
1337 DBUS_TYPE_OBJECT_PATH, &path,
1338 DBUS_TYPE_STRING, &result,
1339 DBUS_TYPE_INVALID)) {
1342 if ((p = set_remove(d->set, (char*) path)))
1346 d->result = strdup(result);
1351 dbus_error_free(&error);
1353 if (dbus_message_get_args(message, &error,
1354 DBUS_TYPE_UINT32, &id,
1355 DBUS_TYPE_OBJECT_PATH, &path,
1356 DBUS_TYPE_BOOLEAN, &success,
1357 DBUS_TYPE_INVALID)) {
1360 /* Compatibility with older systemd versions <
1361 * 19 during upgrades. This should be dropped
1364 if ((p = set_remove(d->set, (char*) path)))
1368 d->result = strdup("failed");
1374 log_error("Failed to parse message: %s", bus_error_message(&error));
1378 dbus_error_free(&error);
1379 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1382 static int enable_wait_for_jobs(DBusConnection *bus) {
1390 dbus_error_init(&error);
1391 dbus_bus_add_match(bus,
1393 "sender='org.freedesktop.systemd1',"
1394 "interface='org.freedesktop.systemd1.Manager',"
1395 "member='JobRemoved',"
1396 "path='/org/freedesktop/systemd1'",
1399 if (dbus_error_is_set(&error)) {
1400 log_error("Failed to add match: %s", bus_error_message(&error));
1401 dbus_error_free(&error);
1405 /* This is slightly dirty, since we don't undo the match registrations. */
1409 static int wait_for_jobs(DBusConnection *bus, Set *s) {
1419 if (!dbus_connection_add_filter(bus, wait_filter, &d, NULL)) {
1420 log_error("Failed to add filter.");
1425 while (!set_isempty(s) &&
1426 dbus_connection_read_write_dispatch(bus, -1))
1429 if (!arg_quiet && d.result) {
1430 if (streq(d.result, "timeout"))
1431 log_error("Job timed out.");
1432 else if (streq(d.result, "canceled"))
1433 log_error("Job canceled.");
1434 else if (streq(d.result, "dependency"))
1435 log_error("A dependency job failed. See system logs for details.");
1436 else if (!streq(d.result, "done") && !streq(d.result, "skipped"))
1437 log_error("Job failed. See system logs and 'systemctl status' for details.");
1440 if (streq_ptr(d.result, "timeout"))
1442 else if (streq_ptr(d.result, "canceled"))
1444 else if (!streq_ptr(d.result, "done") && !streq_ptr(d.result, "skipped"))
1452 /* This is slightly dirty, since we don't undo the filter registration. */
1457 static int start_unit_one(
1458 DBusConnection *bus,
1465 DBusMessage *m = NULL, *reply = NULL;
1474 assert(arg_no_block || s);
1476 if (!(m = dbus_message_new_method_call(
1477 "org.freedesktop.systemd1",
1478 "/org/freedesktop/systemd1",
1479 "org.freedesktop.systemd1.Manager",
1481 log_error("Could not allocate message.");
1486 if (!dbus_message_append_args(m,
1487 DBUS_TYPE_STRING, &name,
1488 DBUS_TYPE_STRING, &mode,
1489 DBUS_TYPE_INVALID)) {
1490 log_error("Could not append arguments to message.");
1495 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, error))) {
1497 if (arg_action != ACTION_SYSTEMCTL && error_is_no_service(error)) {
1498 /* There's always a fallback possible for
1499 * legacy actions. */
1504 log_error("Failed to issue method call: %s", bus_error_message(error));
1509 if (!dbus_message_get_args(reply, error,
1510 DBUS_TYPE_OBJECT_PATH, &path,
1511 DBUS_TYPE_INVALID)) {
1512 log_error("Failed to parse reply: %s", bus_error_message(error));
1517 if (need_daemon_reload(bus, name))
1518 log_warning("Warning: Unit file of created job changed on disk, 'systemctl %s daemon-reload' recommended.",
1519 arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
1521 if (!arg_no_block) {
1524 if (!(p = strdup(path))) {
1525 log_error("Failed to duplicate path.");
1530 if ((r = set_put(s, p)) < 0) {
1532 log_error("Failed to add path to set.");
1541 dbus_message_unref(m);
1544 dbus_message_unref(reply);
1549 static enum action verb_to_action(const char *verb) {
1550 if (streq(verb, "halt"))
1552 else if (streq(verb, "poweroff"))
1553 return ACTION_POWEROFF;
1554 else if (streq(verb, "reboot"))
1555 return ACTION_REBOOT;
1556 else if (streq(verb, "kexec"))
1557 return ACTION_KEXEC;
1558 else if (streq(verb, "rescue"))
1559 return ACTION_RESCUE;
1560 else if (streq(verb, "emergency"))
1561 return ACTION_EMERGENCY;
1562 else if (streq(verb, "default"))
1563 return ACTION_DEFAULT;
1564 else if (streq(verb, "exit"))
1567 return ACTION_INVALID;
1570 static int start_unit(DBusConnection *bus, char **args) {
1572 static const char * const table[_ACTION_MAX] = {
1573 [ACTION_HALT] = SPECIAL_HALT_TARGET,
1574 [ACTION_POWEROFF] = SPECIAL_POWEROFF_TARGET,
1575 [ACTION_REBOOT] = SPECIAL_REBOOT_TARGET,
1576 [ACTION_KEXEC] = SPECIAL_KEXEC_TARGET,
1577 [ACTION_RUNLEVEL2] = SPECIAL_RUNLEVEL2_TARGET,
1578 [ACTION_RUNLEVEL3] = SPECIAL_RUNLEVEL3_TARGET,
1579 [ACTION_RUNLEVEL4] = SPECIAL_RUNLEVEL4_TARGET,
1580 [ACTION_RUNLEVEL5] = SPECIAL_RUNLEVEL5_TARGET,
1581 [ACTION_RESCUE] = SPECIAL_RESCUE_TARGET,
1582 [ACTION_EMERGENCY] = SPECIAL_EMERGENCY_TARGET,
1583 [ACTION_DEFAULT] = SPECIAL_DEFAULT_TARGET,
1584 [ACTION_EXIT] = SPECIAL_EXIT_TARGET
1588 const char *method, *mode, *one_name;
1593 dbus_error_init(&error);
1597 agent_open_if_enabled();
1599 if (arg_action == ACTION_SYSTEMCTL) {
1601 streq(args[0], "stop") ||
1602 streq(args[0], "condstop") ? "StopUnit" :
1603 streq(args[0], "reload") ? "ReloadUnit" :
1604 streq(args[0], "restart") ? "RestartUnit" :
1606 streq(args[0], "try-restart") ||
1607 streq(args[0], "condrestart") ? "TryRestartUnit" :
1609 streq(args[0], "reload-or-restart") ? "ReloadOrRestartUnit" :
1611 streq(args[0], "reload-or-try-restart") ||
1612 streq(args[0], "condreload") ||
1614 streq(args[0], "force-reload") ? "ReloadOrTryRestartUnit" :
1618 (streq(args[0], "isolate") ||
1619 streq(args[0], "rescue") ||
1620 streq(args[0], "emergency")) ? "isolate" : arg_job_mode;
1622 one_name = table[verb_to_action(args[0])];
1625 assert(arg_action < ELEMENTSOF(table));
1626 assert(table[arg_action]);
1628 method = "StartUnit";
1630 mode = (arg_action == ACTION_EMERGENCY ||
1631 arg_action == ACTION_RESCUE ||
1632 arg_action == ACTION_RUNLEVEL2 ||
1633 arg_action == ACTION_RUNLEVEL3 ||
1634 arg_action == ACTION_RUNLEVEL4 ||
1635 arg_action == ACTION_RUNLEVEL5) ? "isolate" : "replace";
1637 one_name = table[arg_action];
1640 if (!arg_no_block) {
1641 if ((ret = enable_wait_for_jobs(bus)) < 0) {
1642 log_error("Could not watch jobs: %s", strerror(-ret));
1646 if (!(s = set_new(string_hash_func, string_compare_func))) {
1647 log_error("Failed to allocate set.");
1654 if ((ret = start_unit_one(bus, method, one_name, mode, &error, s)) <= 0)
1657 STRV_FOREACH(name, args+1)
1658 if ((r = start_unit_one(bus, method, *name, mode, &error, s)) != 0) {
1659 ret = translate_bus_error_to_exit_status(r, &error);
1660 dbus_error_free(&error);
1665 if ((r = wait_for_jobs(bus, s)) < 0) {
1674 dbus_error_free(&error);
1679 static int start_special(DBusConnection *bus, char **args) {
1686 (streq(args[0], "halt") ||
1687 streq(args[0], "poweroff") ||
1688 streq(args[0], "reboot") ||
1689 streq(args[0], "kexec") ||
1690 streq(args[0], "exit")))
1691 return daemon_reload(bus, args);
1693 r = start_unit(bus, args);
1696 warn_wall(verb_to_action(args[0]));
1701 static int check_unit(DBusConnection *bus, char **args) {
1702 DBusMessage *m = NULL, *reply = NULL;
1704 *interface = "org.freedesktop.systemd1.Unit",
1705 *property = "ActiveState";
1706 int r = 3; /* According to LSB: "program is not running" */
1713 dbus_error_init(&error);
1715 STRV_FOREACH(name, args+1) {
1716 const char *path = NULL;
1718 DBusMessageIter iter, sub;
1720 if (!(m = dbus_message_new_method_call(
1721 "org.freedesktop.systemd1",
1722 "/org/freedesktop/systemd1",
1723 "org.freedesktop.systemd1.Manager",
1725 log_error("Could not allocate message.");
1730 if (!dbus_message_append_args(m,
1731 DBUS_TYPE_STRING, name,
1732 DBUS_TYPE_INVALID)) {
1733 log_error("Could not append arguments to message.");
1738 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
1740 /* Hmm, cannot figure out anything about this unit... */
1744 dbus_error_free(&error);
1745 dbus_message_unref(m);
1750 if (!dbus_message_get_args(reply, &error,
1751 DBUS_TYPE_OBJECT_PATH, &path,
1752 DBUS_TYPE_INVALID)) {
1753 log_error("Failed to parse reply: %s", bus_error_message(&error));
1758 dbus_message_unref(m);
1759 if (!(m = dbus_message_new_method_call(
1760 "org.freedesktop.systemd1",
1762 "org.freedesktop.DBus.Properties",
1764 log_error("Could not allocate message.");
1769 if (!dbus_message_append_args(m,
1770 DBUS_TYPE_STRING, &interface,
1771 DBUS_TYPE_STRING, &property,
1772 DBUS_TYPE_INVALID)) {
1773 log_error("Could not append arguments to message.");
1778 dbus_message_unref(reply);
1779 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
1780 log_error("Failed to issue method call: %s", bus_error_message(&error));
1785 if (!dbus_message_iter_init(reply, &iter) ||
1786 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1787 log_error("Failed to parse reply.");
1792 dbus_message_iter_recurse(&iter, &sub);
1794 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1795 log_error("Failed to parse reply.");
1800 dbus_message_iter_get_basic(&sub, &state);
1805 if (streq(state, "active") || streq(state, "reloading"))
1808 dbus_message_unref(m);
1809 dbus_message_unref(reply);
1815 dbus_message_unref(m);
1818 dbus_message_unref(reply);
1820 dbus_error_free(&error);
1825 static int kill_unit(DBusConnection *bus, char **args) {
1826 DBusMessage *m = NULL;
1834 dbus_error_init(&error);
1837 arg_kill_who = "all";
1840 arg_kill_mode = streq(arg_kill_who, "all") ? "control-group" : "process";
1842 STRV_FOREACH(name, args+1) {
1845 if (!(m = dbus_message_new_method_call(
1846 "org.freedesktop.systemd1",
1847 "/org/freedesktop/systemd1",
1848 "org.freedesktop.systemd1.Manager",
1850 log_error("Could not allocate message.");
1855 if (!dbus_message_append_args(m,
1856 DBUS_TYPE_STRING, name,
1857 DBUS_TYPE_STRING, &arg_kill_who,
1858 DBUS_TYPE_STRING, &arg_kill_mode,
1859 DBUS_TYPE_INT32, &arg_signal,
1860 DBUS_TYPE_INVALID)) {
1861 log_error("Could not append arguments to message.");
1866 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
1867 log_error("Failed to issue method call: %s", bus_error_message(&error));
1868 dbus_error_free(&error);
1872 dbus_message_unref(m);
1875 dbus_message_unref(reply);
1881 dbus_message_unref(m);
1883 dbus_error_free(&error);
1888 typedef struct ExecStatusInfo {
1896 usec_t start_timestamp;
1897 usec_t exit_timestamp;
1902 LIST_FIELDS(struct ExecStatusInfo, exec);
1905 static void exec_status_info_free(ExecStatusInfo *i) {
1914 static int exec_status_info_deserialize(DBusMessageIter *sub, ExecStatusInfo *i) {
1915 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
1916 DBusMessageIter sub2, sub3;
1920 int32_t code, status;
1926 if (dbus_message_iter_get_arg_type(sub) != DBUS_TYPE_STRUCT)
1929 dbus_message_iter_recurse(sub, &sub2);
1931 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0)
1934 if (!(i->path = strdup(path)))
1937 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_ARRAY ||
1938 dbus_message_iter_get_element_type(&sub2) != DBUS_TYPE_STRING)
1942 dbus_message_iter_recurse(&sub2, &sub3);
1943 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
1944 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
1945 dbus_message_iter_next(&sub3);
1950 if (!(i->argv = new0(char*, n+1)))
1954 dbus_message_iter_recurse(&sub2, &sub3);
1955 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
1958 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
1959 dbus_message_iter_get_basic(&sub3, &s);
1960 dbus_message_iter_next(&sub3);
1962 if (!(i->argv[n++] = strdup(s)))
1966 if (!dbus_message_iter_next(&sub2) ||
1967 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, true) < 0 ||
1968 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp, true) < 0 ||
1969 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp_monotonic, true) < 0 ||
1970 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp, true) < 0 ||
1971 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp_monotonic, true) < 0 ||
1972 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, true) < 0 ||
1973 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &code, true) < 0 ||
1974 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &status, false) < 0)
1978 i->start_timestamp = (usec_t) start_timestamp;
1979 i->exit_timestamp = (usec_t) exit_timestamp;
1980 i->pid = (pid_t) pid;
1987 typedef struct UnitStatusInfo {
1989 const char *load_state;
1990 const char *active_state;
1991 const char *sub_state;
1992 const char *unit_file_state;
1994 const char *description;
1995 const char *following;
1998 const char *default_control_group;
2000 const char *load_error;
2002 usec_t inactive_exit_timestamp;
2003 usec_t active_enter_timestamp;
2004 usec_t active_exit_timestamp;
2005 usec_t inactive_enter_timestamp;
2007 bool need_daemon_reload;
2012 const char *status_text;
2014 #ifdef HAVE_SYSV_COMPAT
2018 usec_t start_timestamp;
2019 usec_t exit_timestamp;
2021 int exit_code, exit_status;
2023 usec_t condition_timestamp;
2024 bool condition_result;
2027 unsigned n_accepted;
2028 unsigned n_connections;
2032 const char *sysfs_path;
2034 /* Mount, Automount */
2040 LIST_HEAD(ExecStatusInfo, exec);
2043 static void print_status_info(UnitStatusInfo *i) {
2045 const char *on, *off, *ss;
2047 char since1[FORMAT_TIMESTAMP_PRETTY_MAX], *s1;
2048 char since2[FORMAT_TIMESTAMP_MAX], *s2;
2052 /* This shows pretty information about a unit. See
2053 * print_property() for a low-level property printer */
2055 printf("%s", strna(i->id));
2057 if (i->description && !streq_ptr(i->id, i->description))
2058 printf(" - %s", i->description);
2063 printf("\t Follow: unit currently follows state of %s\n", i->following);
2065 if (streq_ptr(i->load_state, "error")) {
2066 on = ansi_highlight(true);
2067 off = ansi_highlight(false);
2072 printf("\t Loaded: %s%s%s (Reason: %s)\n", on, strna(i->load_state), off, i->load_error);
2073 else if (i->path && i->unit_file_state)
2074 printf("\t Loaded: %s%s%s (%s; %s)\n", on, strna(i->load_state), off, i->path, i->unit_file_state);
2076 printf("\t Loaded: %s%s%s (%s)\n", on, strna(i->load_state), off, i->path);
2078 printf("\t Loaded: %s%s%s\n", on, strna(i->load_state), off);
2080 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
2082 if (streq_ptr(i->active_state, "failed")) {
2083 on = ansi_highlight(true);
2084 off = ansi_highlight(false);
2085 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
2086 on = ansi_highlight_green(true);
2087 off = ansi_highlight_green(false);
2092 printf("\t Active: %s%s (%s)%s",
2094 strna(i->active_state),
2098 printf("\t Active: %s%s%s",
2100 strna(i->active_state),
2103 timestamp = (streq_ptr(i->active_state, "active") ||
2104 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
2105 (streq_ptr(i->active_state, "inactive") ||
2106 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
2107 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
2108 i->active_exit_timestamp;
2110 s1 = format_timestamp_pretty(since1, sizeof(since1), timestamp);
2111 s2 = format_timestamp(since2, sizeof(since2), timestamp);
2114 printf(" since %s; %s\n", s2, s1);
2116 printf(" since %s\n", s2);
2120 if (!i->condition_result && i->condition_timestamp > 0) {
2121 s1 = format_timestamp_pretty(since1, sizeof(since1), i->condition_timestamp);
2122 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
2125 printf("\t start condition failed at %s; %s\n", s2, s1);
2127 printf("\t start condition failed at %s\n", s2);
2131 printf("\t Device: %s\n", i->sysfs_path);
2133 printf("\t Where: %s\n", i->where);
2135 printf("\t What: %s\n", i->what);
2138 printf("\tAccepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
2140 LIST_FOREACH(exec, p, i->exec) {
2144 /* Only show exited processes here */
2148 t = strv_join(p->argv, " ");
2149 printf("\t Process: %u %s=%s ", p->pid, p->name, strna(t));
2152 #ifdef HAVE_SYSV_COMPAT
2154 good = is_clean_exit_lsb(p->code, p->status);
2157 good = is_clean_exit(p->code, p->status);
2160 on = ansi_highlight(true);
2161 off = ansi_highlight(false);
2165 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
2167 if (p->code == CLD_EXITED) {
2170 printf("status=%i", p->status);
2172 #ifdef HAVE_SYSV_COMPAT
2173 if ((c = exit_status_to_string(p->status, i->is_sysv ? EXIT_STATUS_LSB : EXIT_STATUS_SYSTEMD)))
2175 if ((c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD)))
2180 printf("signal=%s", signal_to_string(p->status));
2182 printf(")%s\n", off);
2184 if (i->main_pid == p->pid &&
2185 i->start_timestamp == p->start_timestamp &&
2186 i->exit_timestamp == p->start_timestamp)
2187 /* Let's not show this twice */
2190 if (p->pid == i->control_pid)
2194 if (i->main_pid > 0 || i->control_pid > 0) {
2197 if (i->main_pid > 0) {
2198 printf("Main PID: %u", (unsigned) i->main_pid);
2202 get_process_name(i->main_pid, &t);
2207 } else if (i->exit_code > 0) {
2208 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
2210 if (i->exit_code == CLD_EXITED) {
2213 printf("status=%i", i->exit_status);
2215 #ifdef HAVE_SYSV_COMPAT
2216 if ((c = exit_status_to_string(i->exit_status, i->is_sysv ? EXIT_STATUS_LSB : EXIT_STATUS_SYSTEMD)))
2218 if ((c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD)))
2223 printf("signal=%s", signal_to_string(i->exit_status));
2228 if (i->main_pid > 0 && i->control_pid > 0)
2231 if (i->control_pid > 0) {
2234 printf(" Control: %u", (unsigned) i->control_pid);
2236 get_process_name(i->control_pid, &t);
2247 printf("\t Status: \"%s\"\n", i->status_text);
2249 if (i->default_control_group) {
2252 printf("\t CGroup: %s\n", i->default_control_group);
2254 if (arg_transport != TRANSPORT_SSH) {
2255 if ((c = columns()) > 18)
2260 show_cgroup_by_path(i->default_control_group, "\t\t ", c);
2264 if (i->need_daemon_reload)
2265 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %s daemon-reload' recommended.\n",
2266 ansi_highlight(true),
2267 ansi_highlight(false),
2268 arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
2271 static int status_property(const char *name, DBusMessageIter *iter, UnitStatusInfo *i) {
2277 switch (dbus_message_iter_get_arg_type(iter)) {
2279 case DBUS_TYPE_STRING: {
2282 dbus_message_iter_get_basic(iter, &s);
2285 if (streq(name, "Id"))
2287 else if (streq(name, "LoadState"))
2289 else if (streq(name, "ActiveState"))
2290 i->active_state = s;
2291 else if (streq(name, "SubState"))
2293 else if (streq(name, "Description"))
2295 else if (streq(name, "FragmentPath"))
2297 #ifdef HAVE_SYSV_COMPAT
2298 else if (streq(name, "SysVPath")) {
2303 else if (streq(name, "DefaultControlGroup"))
2304 i->default_control_group = s;
2305 else if (streq(name, "StatusText"))
2307 else if (streq(name, "SysFSPath"))
2309 else if (streq(name, "Where"))
2311 else if (streq(name, "What"))
2313 else if (streq(name, "Following"))
2315 else if (streq(name, "UnitFileState"))
2316 i->unit_file_state = s;
2322 case DBUS_TYPE_BOOLEAN: {
2325 dbus_message_iter_get_basic(iter, &b);
2327 if (streq(name, "Accept"))
2329 else if (streq(name, "NeedDaemonReload"))
2330 i->need_daemon_reload = b;
2331 else if (streq(name, "ConditionResult"))
2332 i->condition_result = b;
2337 case DBUS_TYPE_UINT32: {
2340 dbus_message_iter_get_basic(iter, &u);
2342 if (streq(name, "MainPID")) {
2344 i->main_pid = (pid_t) u;
2347 } else if (streq(name, "ControlPID"))
2348 i->control_pid = (pid_t) u;
2349 else if (streq(name, "ExecMainPID")) {
2351 i->main_pid = (pid_t) u;
2352 } else if (streq(name, "NAccepted"))
2354 else if (streq(name, "NConnections"))
2355 i->n_connections = u;
2360 case DBUS_TYPE_INT32: {
2363 dbus_message_iter_get_basic(iter, &j);
2365 if (streq(name, "ExecMainCode"))
2366 i->exit_code = (int) j;
2367 else if (streq(name, "ExecMainStatus"))
2368 i->exit_status = (int) j;
2373 case DBUS_TYPE_UINT64: {
2376 dbus_message_iter_get_basic(iter, &u);
2378 if (streq(name, "ExecMainStartTimestamp"))
2379 i->start_timestamp = (usec_t) u;
2380 else if (streq(name, "ExecMainExitTimestamp"))
2381 i->exit_timestamp = (usec_t) u;
2382 else if (streq(name, "ActiveEnterTimestamp"))
2383 i->active_enter_timestamp = (usec_t) u;
2384 else if (streq(name, "InactiveEnterTimestamp"))
2385 i->inactive_enter_timestamp = (usec_t) u;
2386 else if (streq(name, "InactiveExitTimestamp"))
2387 i->inactive_exit_timestamp = (usec_t) u;
2388 else if (streq(name, "ActiveExitTimestamp"))
2389 i->active_exit_timestamp = (usec_t) u;
2390 else if (streq(name, "ConditionTimestamp"))
2391 i->condition_timestamp = (usec_t) u;
2396 case DBUS_TYPE_ARRAY: {
2398 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
2399 startswith(name, "Exec")) {
2400 DBusMessageIter sub;
2402 dbus_message_iter_recurse(iter, &sub);
2403 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2404 ExecStatusInfo *info;
2407 if (!(info = new0(ExecStatusInfo, 1)))
2410 if (!(info->name = strdup(name))) {
2415 if ((r = exec_status_info_deserialize(&sub, info)) < 0) {
2420 LIST_PREPEND(ExecStatusInfo, exec, i->exec, info);
2422 dbus_message_iter_next(&sub);
2429 case DBUS_TYPE_STRUCT: {
2431 if (streq(name, "LoadError")) {
2432 DBusMessageIter sub;
2433 const char *n, *message;
2436 dbus_message_iter_recurse(iter, &sub);
2438 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &n, true);
2442 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &message, false);
2446 if (!isempty(message))
2447 i->load_error = message;
2457 static int print_property(const char *name, DBusMessageIter *iter) {
2461 /* This is a low-level property printer, see
2462 * print_status_info() for the nicer output */
2464 if (arg_property && !strv_find(arg_property, name))
2467 switch (dbus_message_iter_get_arg_type(iter)) {
2469 case DBUS_TYPE_STRUCT: {
2470 DBusMessageIter sub;
2471 dbus_message_iter_recurse(iter, &sub);
2473 if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32 && streq(name, "Job")) {
2476 dbus_message_iter_get_basic(&sub, &u);
2479 printf("%s=%u\n", name, (unsigned) u);
2481 printf("%s=\n", name);
2484 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "Unit")) {
2487 dbus_message_iter_get_basic(&sub, &s);
2489 if (arg_all || s[0])
2490 printf("%s=%s\n", name, s);
2493 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "LoadError")) {
2494 const char *a = NULL, *b = NULL;
2496 if (bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &a, true) >= 0)
2497 bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &b, false);
2499 if (arg_all || !isempty(a) || !isempty(b))
2500 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
2508 case DBUS_TYPE_ARRAY:
2510 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "EnvironmentFiles")) {
2511 DBusMessageIter sub, sub2;
2513 dbus_message_iter_recurse(iter, &sub);
2514 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2518 dbus_message_iter_recurse(&sub, &sub2);
2520 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
2521 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) >= 0)
2522 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
2524 dbus_message_iter_next(&sub);
2529 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Paths")) {
2530 DBusMessageIter sub, sub2;
2532 dbus_message_iter_recurse(iter, &sub);
2533 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2534 const char *type, *path;
2536 dbus_message_iter_recurse(&sub, &sub2);
2538 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
2539 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
2540 printf("%s=%s\n", type, path);
2542 dbus_message_iter_next(&sub);
2547 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Timers")) {
2548 DBusMessageIter sub, sub2;
2550 dbus_message_iter_recurse(iter, &sub);
2551 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2553 uint64_t value, next_elapse;
2555 dbus_message_iter_recurse(&sub, &sub2);
2557 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &base, true) >= 0 &&
2558 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &value, true) >= 0 &&
2559 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &next_elapse, false) >= 0) {
2560 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
2562 printf("%s={ value=%s ; next_elapse=%s }\n",
2564 format_timespan(timespan1, sizeof(timespan1), value),
2565 format_timespan(timespan2, sizeof(timespan2), next_elapse));
2568 dbus_message_iter_next(&sub);
2573 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "ControlGroupAttributes")) {
2574 DBusMessageIter sub, sub2;
2576 dbus_message_iter_recurse(iter, &sub);
2577 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2578 const char *controller, *attr, *value;
2580 dbus_message_iter_recurse(&sub, &sub2);
2582 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &controller, true) >= 0 &&
2583 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &attr, true) >= 0 &&
2584 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &value, false) >= 0) {
2586 printf("ControlGroupAttribute={ controller=%s ; attribute=%s ; value=\"%s\" }\n",
2592 dbus_message_iter_next(&sub);
2597 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && startswith(name, "Exec")) {
2598 DBusMessageIter sub;
2600 dbus_message_iter_recurse(iter, &sub);
2601 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2602 ExecStatusInfo info;
2605 if (exec_status_info_deserialize(&sub, &info) >= 0) {
2606 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
2609 t = strv_join(info.argv, " ");
2611 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
2615 yes_no(info.ignore),
2616 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
2617 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
2618 (unsigned) info. pid,
2619 sigchld_code_to_string(info.code),
2621 info.code == CLD_EXITED ? "" : "/",
2622 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
2628 strv_free(info.argv);
2630 dbus_message_iter_next(&sub);
2639 if (generic_print_property(name, iter, arg_all) > 0)
2643 printf("%s=[unprintable]\n", name);
2648 static int show_one(const char *verb, DBusConnection *bus, const char *path, bool show_properties, bool *new_line) {
2649 DBusMessage *m = NULL, *reply = NULL;
2650 const char *interface = "";
2653 DBusMessageIter iter, sub, sub2, sub3;
2654 UnitStatusInfo info;
2662 dbus_error_init(&error);
2664 if (!(m = dbus_message_new_method_call(
2665 "org.freedesktop.systemd1",
2667 "org.freedesktop.DBus.Properties",
2669 log_error("Could not allocate message.");
2674 if (!dbus_message_append_args(m,
2675 DBUS_TYPE_STRING, &interface,
2676 DBUS_TYPE_INVALID)) {
2677 log_error("Could not append arguments to message.");
2682 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
2683 log_error("Failed to issue method call: %s", bus_error_message(&error));
2688 if (!dbus_message_iter_init(reply, &iter) ||
2689 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
2690 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
2691 log_error("Failed to parse reply.");
2696 dbus_message_iter_recurse(&iter, &sub);
2703 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
2706 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_DICT_ENTRY) {
2707 log_error("Failed to parse reply.");
2712 dbus_message_iter_recurse(&sub, &sub2);
2714 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0) {
2715 log_error("Failed to parse reply.");
2720 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
2721 log_error("Failed to parse reply.");
2726 dbus_message_iter_recurse(&sub2, &sub3);
2728 if (show_properties)
2729 r = print_property(name, &sub3);
2731 r = status_property(name, &sub3, &info);
2734 log_error("Failed to parse reply.");
2739 dbus_message_iter_next(&sub);
2744 if (!show_properties)
2745 print_status_info(&info);
2747 if (!streq_ptr(info.active_state, "active") &&
2748 !streq_ptr(info.active_state, "reloading") &&
2749 streq(verb, "status"))
2750 /* According to LSB: "program not running" */
2753 while ((p = info.exec)) {
2754 LIST_REMOVE(ExecStatusInfo, exec, info.exec, p);
2755 exec_status_info_free(p);
2760 dbus_message_unref(m);
2763 dbus_message_unref(reply);
2765 dbus_error_free(&error);
2770 static int show(DBusConnection *bus, char **args) {
2771 DBusMessage *m = NULL, *reply = NULL;
2774 bool show_properties, new_line = false;
2780 dbus_error_init(&error);
2782 show_properties = !streq(args[0], "status");
2784 if (show_properties)
2785 pager_open_if_enabled();
2787 if (show_properties && strv_length(args) <= 1) {
2788 /* If not argument is specified inspect the manager
2791 ret = show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line);
2795 STRV_FOREACH(name, args+1) {
2796 const char *path = NULL;
2799 if (safe_atou32(*name, &id) < 0) {
2801 /* Interpret as unit name */
2803 if (!(m = dbus_message_new_method_call(
2804 "org.freedesktop.systemd1",
2805 "/org/freedesktop/systemd1",
2806 "org.freedesktop.systemd1.Manager",
2808 log_error("Could not allocate message.");
2813 if (!dbus_message_append_args(m,
2814 DBUS_TYPE_STRING, name,
2815 DBUS_TYPE_INVALID)) {
2816 log_error("Could not append arguments to message.");
2821 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
2823 if (!dbus_error_has_name(&error, DBUS_ERROR_ACCESS_DENIED)) {
2824 log_error("Failed to issue method call: %s", bus_error_message(&error));
2829 dbus_error_free(&error);
2831 dbus_message_unref(m);
2832 if (!(m = dbus_message_new_method_call(
2833 "org.freedesktop.systemd1",
2834 "/org/freedesktop/systemd1",
2835 "org.freedesktop.systemd1.Manager",
2837 log_error("Could not allocate message.");
2842 if (!dbus_message_append_args(m,
2843 DBUS_TYPE_STRING, name,
2844 DBUS_TYPE_INVALID)) {
2845 log_error("Could not append arguments to message.");
2850 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
2851 log_error("Failed to issue method call: %s", bus_error_message(&error));
2853 if (dbus_error_has_name(&error, BUS_ERROR_NO_SUCH_UNIT))
2854 ret = 4; /* According to LSB: "program or service status is unknown" */
2861 } else if (show_properties) {
2863 /* Interpret as job id */
2865 if (!(m = dbus_message_new_method_call(
2866 "org.freedesktop.systemd1",
2867 "/org/freedesktop/systemd1",
2868 "org.freedesktop.systemd1.Manager",
2870 log_error("Could not allocate message.");
2875 if (!dbus_message_append_args(m,
2876 DBUS_TYPE_UINT32, &id,
2877 DBUS_TYPE_INVALID)) {
2878 log_error("Could not append arguments to message.");
2883 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
2884 log_error("Failed to issue method call: %s", bus_error_message(&error));
2890 /* Interpret as PID */
2892 if (!(m = dbus_message_new_method_call(
2893 "org.freedesktop.systemd1",
2894 "/org/freedesktop/systemd1",
2895 "org.freedesktop.systemd1.Manager",
2897 log_error("Could not allocate message.");
2902 if (!dbus_message_append_args(m,
2903 DBUS_TYPE_UINT32, &id,
2904 DBUS_TYPE_INVALID)) {
2905 log_error("Could not append arguments to message.");
2910 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
2911 log_error("Failed to issue method call: %s", bus_error_message(&error));
2917 if (!dbus_message_get_args(reply, &error,
2918 DBUS_TYPE_OBJECT_PATH, &path,
2919 DBUS_TYPE_INVALID)) {
2920 log_error("Failed to parse reply: %s", bus_error_message(&error));
2925 if ((r = show_one(args[0], bus, path, show_properties, &new_line)) != 0)
2928 dbus_message_unref(m);
2929 dbus_message_unref(reply);
2935 dbus_message_unref(m);
2938 dbus_message_unref(reply);
2940 dbus_error_free(&error);
2945 static int dump(DBusConnection *bus, char **args) {
2946 DBusMessage *m = NULL, *reply = NULL;
2951 dbus_error_init(&error);
2953 pager_open_if_enabled();
2955 if (!(m = dbus_message_new_method_call(
2956 "org.freedesktop.systemd1",
2957 "/org/freedesktop/systemd1",
2958 "org.freedesktop.systemd1.Manager",
2960 log_error("Could not allocate message.");
2964 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
2965 log_error("Failed to issue method call: %s", bus_error_message(&error));
2970 if (!dbus_message_get_args(reply, &error,
2971 DBUS_TYPE_STRING, &text,
2972 DBUS_TYPE_INVALID)) {
2973 log_error("Failed to parse reply: %s", bus_error_message(&error));
2978 fputs(text, stdout);
2984 dbus_message_unref(m);
2987 dbus_message_unref(reply);
2989 dbus_error_free(&error);
2994 static int snapshot(DBusConnection *bus, char **args) {
2995 DBusMessage *m = NULL, *reply = NULL;
2998 const char *name = "", *path, *id;
2999 dbus_bool_t cleanup = FALSE;
3000 DBusMessageIter iter, sub;
3002 *interface = "org.freedesktop.systemd1.Unit",
3005 dbus_error_init(&error);
3007 if (!(m = dbus_message_new_method_call(
3008 "org.freedesktop.systemd1",
3009 "/org/freedesktop/systemd1",
3010 "org.freedesktop.systemd1.Manager",
3011 "CreateSnapshot"))) {
3012 log_error("Could not allocate message.");
3016 if (strv_length(args) > 1)
3019 if (!dbus_message_append_args(m,
3020 DBUS_TYPE_STRING, &name,
3021 DBUS_TYPE_BOOLEAN, &cleanup,
3022 DBUS_TYPE_INVALID)) {
3023 log_error("Could not append arguments to message.");
3028 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3029 log_error("Failed to issue method call: %s", bus_error_message(&error));
3034 if (!dbus_message_get_args(reply, &error,
3035 DBUS_TYPE_OBJECT_PATH, &path,
3036 DBUS_TYPE_INVALID)) {
3037 log_error("Failed to parse reply: %s", bus_error_message(&error));
3042 dbus_message_unref(m);
3043 if (!(m = dbus_message_new_method_call(
3044 "org.freedesktop.systemd1",
3046 "org.freedesktop.DBus.Properties",
3048 log_error("Could not allocate message.");
3052 if (!dbus_message_append_args(m,
3053 DBUS_TYPE_STRING, &interface,
3054 DBUS_TYPE_STRING, &property,
3055 DBUS_TYPE_INVALID)) {
3056 log_error("Could not append arguments to message.");
3061 dbus_message_unref(reply);
3062 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3063 log_error("Failed to issue method call: %s", bus_error_message(&error));
3068 if (!dbus_message_iter_init(reply, &iter) ||
3069 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3070 log_error("Failed to parse reply.");
3075 dbus_message_iter_recurse(&iter, &sub);
3077 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
3078 log_error("Failed to parse reply.");
3083 dbus_message_iter_get_basic(&sub, &id);
3091 dbus_message_unref(m);
3094 dbus_message_unref(reply);
3096 dbus_error_free(&error);
3101 static int delete_snapshot(DBusConnection *bus, char **args) {
3102 DBusMessage *m = NULL, *reply = NULL;
3110 dbus_error_init(&error);
3112 STRV_FOREACH(name, args+1) {
3113 const char *path = NULL;
3115 if (!(m = dbus_message_new_method_call(
3116 "org.freedesktop.systemd1",
3117 "/org/freedesktop/systemd1",
3118 "org.freedesktop.systemd1.Manager",
3120 log_error("Could not allocate message.");
3125 if (!dbus_message_append_args(m,
3126 DBUS_TYPE_STRING, name,
3127 DBUS_TYPE_INVALID)) {
3128 log_error("Could not append arguments to message.");
3133 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3134 log_error("Failed to issue method call: %s", bus_error_message(&error));
3139 if (!dbus_message_get_args(reply, &error,
3140 DBUS_TYPE_OBJECT_PATH, &path,
3141 DBUS_TYPE_INVALID)) {
3142 log_error("Failed to parse reply: %s", bus_error_message(&error));
3147 dbus_message_unref(m);
3148 if (!(m = dbus_message_new_method_call(
3149 "org.freedesktop.systemd1",
3151 "org.freedesktop.systemd1.Snapshot",
3153 log_error("Could not allocate message.");
3158 dbus_message_unref(reply);
3159 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3160 log_error("Failed to issue method call: %s", bus_error_message(&error));
3165 dbus_message_unref(m);
3166 dbus_message_unref(reply);
3174 dbus_message_unref(m);
3177 dbus_message_unref(reply);
3179 dbus_error_free(&error);
3184 static int daemon_reload(DBusConnection *bus, char **args) {
3185 DBusMessage *m = NULL, *reply = NULL;
3190 dbus_error_init(&error);
3192 if (arg_action == ACTION_RELOAD)
3194 else if (arg_action == ACTION_REEXEC)
3195 method = "Reexecute";
3197 assert(arg_action == ACTION_SYSTEMCTL);
3200 streq(args[0], "clear-jobs") ||
3201 streq(args[0], "cancel") ? "ClearJobs" :
3202 streq(args[0], "daemon-reexec") ? "Reexecute" :
3203 streq(args[0], "reset-failed") ? "ResetFailed" :
3204 streq(args[0], "halt") ? "Halt" :
3205 streq(args[0], "poweroff") ? "PowerOff" :
3206 streq(args[0], "reboot") ? "Reboot" :
3207 streq(args[0], "kexec") ? "KExec" :
3208 streq(args[0], "exit") ? "Exit" :
3209 /* "daemon-reload" */ "Reload";
3212 if (!(m = dbus_message_new_method_call(
3213 "org.freedesktop.systemd1",
3214 "/org/freedesktop/systemd1",
3215 "org.freedesktop.systemd1.Manager",
3217 log_error("Could not allocate message.");
3221 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3223 if (arg_action != ACTION_SYSTEMCTL && error_is_no_service(&error)) {
3224 /* There's always a fallback possible for
3225 * legacy actions. */
3230 if (streq(method, "Reexecute") && dbus_error_has_name(&error, DBUS_ERROR_NO_REPLY)) {
3231 /* On reexecution, we expect a disconnect, not
3237 log_error("Failed to issue method call: %s", bus_error_message(&error));
3246 dbus_message_unref(m);
3249 dbus_message_unref(reply);
3251 dbus_error_free(&error);
3256 static int reset_failed(DBusConnection *bus, char **args) {
3257 DBusMessage *m = NULL;
3263 dbus_error_init(&error);
3265 if (strv_length(args) <= 1)
3266 return daemon_reload(bus, args);
3268 STRV_FOREACH(name, args+1) {
3271 if (!(m = dbus_message_new_method_call(
3272 "org.freedesktop.systemd1",
3273 "/org/freedesktop/systemd1",
3274 "org.freedesktop.systemd1.Manager",
3275 "ResetFailedUnit"))) {
3276 log_error("Could not allocate message.");
3281 if (!dbus_message_append_args(m,
3282 DBUS_TYPE_STRING, name,
3283 DBUS_TYPE_INVALID)) {
3284 log_error("Could not append arguments to message.");
3289 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3290 log_error("Failed to issue method call: %s", bus_error_message(&error));
3295 dbus_message_unref(m);
3296 dbus_message_unref(reply);
3304 dbus_message_unref(m);
3306 dbus_error_free(&error);
3311 static int show_enviroment(DBusConnection *bus, char **args) {
3312 DBusMessage *m = NULL, *reply = NULL;
3314 DBusMessageIter iter, sub, sub2;
3317 *interface = "org.freedesktop.systemd1.Manager",
3318 *property = "Environment";
3320 dbus_error_init(&error);
3322 pager_open_if_enabled();
3324 if (!(m = dbus_message_new_method_call(
3325 "org.freedesktop.systemd1",
3326 "/org/freedesktop/systemd1",
3327 "org.freedesktop.DBus.Properties",
3329 log_error("Could not allocate message.");
3333 if (!dbus_message_append_args(m,
3334 DBUS_TYPE_STRING, &interface,
3335 DBUS_TYPE_STRING, &property,
3336 DBUS_TYPE_INVALID)) {
3337 log_error("Could not append arguments to message.");
3342 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3343 log_error("Failed to issue method call: %s", bus_error_message(&error));
3348 if (!dbus_message_iter_init(reply, &iter) ||
3349 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3350 log_error("Failed to parse reply.");
3355 dbus_message_iter_recurse(&iter, &sub);
3357 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_ARRAY ||
3358 dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_STRING) {
3359 log_error("Failed to parse reply.");
3364 dbus_message_iter_recurse(&sub, &sub2);
3366 while (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_INVALID) {
3369 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
3370 log_error("Failed to parse reply.");
3375 dbus_message_iter_get_basic(&sub2, &text);
3376 printf("%s\n", text);
3378 dbus_message_iter_next(&sub2);
3385 dbus_message_unref(m);
3388 dbus_message_unref(reply);
3390 dbus_error_free(&error);
3395 static int set_environment(DBusConnection *bus, char **args) {
3396 DBusMessage *m = NULL, *reply = NULL;
3400 DBusMessageIter iter, sub;
3403 dbus_error_init(&error);
3405 method = streq(args[0], "set-environment")
3407 : "UnsetEnvironment";
3409 if (!(m = dbus_message_new_method_call(
3410 "org.freedesktop.systemd1",
3411 "/org/freedesktop/systemd1",
3412 "org.freedesktop.systemd1.Manager",
3415 log_error("Could not allocate message.");
3419 dbus_message_iter_init_append(m, &iter);
3421 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub)) {
3422 log_error("Could not append arguments to message.");
3427 STRV_FOREACH(name, args+1)
3428 if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, name)) {
3429 log_error("Could not append arguments to message.");
3434 if (!dbus_message_iter_close_container(&iter, &sub)) {
3435 log_error("Could not append arguments to message.");
3440 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3441 log_error("Failed to issue method call: %s", bus_error_message(&error));
3450 dbus_message_unref(m);
3453 dbus_message_unref(reply);
3455 dbus_error_free(&error);
3460 static int enable_sysv_units(char **args) {
3463 #if defined (HAVE_SYSV_COMPAT) && (defined(TARGET_FEDORA) || defined(TARGET_MANDRIVA) || defined(TARGET_SUSE) || defined(TARGET_MEEGO) || defined(TARGET_ALTLINUX) || defined(TARGET_MAGEIA))
3464 const char *verb = args[0];
3465 unsigned f = 1, t = 1;
3468 if (arg_scope != UNIT_FILE_SYSTEM)
3471 if (!streq(verb, "enable") &&
3472 !streq(verb, "disable") &&
3473 !streq(verb, "is-enabled"))
3476 /* Processes all SysV units, and reshuffles the array so that
3477 * afterwards only the native units remain */
3480 r = lookup_paths_init(&paths, MANAGER_SYSTEM, false);
3486 for (f = 1; args[f]; f++) {
3489 bool found_native = false, found_sysv;
3491 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
3492 char **k, *l, *q = NULL;
3499 if (!endswith(name, ".service"))
3502 if (path_is_absolute(name))
3505 STRV_FOREACH(k, paths.unit_path) {
3508 if (!isempty(arg_root))
3509 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
3511 asprintf(&p, "%s/%s", *k, name);
3514 log_error("No memory");
3519 found_native = access(p, F_OK) >= 0;
3530 if (!isempty(arg_root))
3531 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
3533 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
3535 log_error("No memory");
3540 p[strlen(p) - sizeof(".service") + 1] = 0;
3541 found_sysv = access(p, F_OK) >= 0;
3548 /* Mark this entry, so that we don't try enabling it as native unit */
3549 args[f] = (char*) "";
3551 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
3553 if (!isempty(arg_root))
3554 argv[c++] = q = strappend("--root=", arg_root);
3556 argv[c++] = file_name_from_path(p);
3558 streq(verb, "enable") ? "on" :
3559 streq(verb, "disable") ? "off" : "--level=5";
3562 l = strv_join((char**)argv, " ");
3564 log_error("No memory.");
3571 log_info("Executing %s", l);
3576 log_error("Failed to fork: %m");
3581 } else if (pid == 0) {
3584 execv(argv[0], (char**) argv);
3585 _exit(EXIT_FAILURE);
3591 j = wait_for_terminate(pid, &status);
3593 log_error("Failed to wait for child: %s", strerror(-r));
3598 if (status.si_code == CLD_EXITED) {
3599 if (streq(verb, "is-enabled")) {
3600 if (status.si_status == 0) {
3609 } else if (status.si_status != 0) {
3620 lookup_paths_free(&paths);
3622 /* Drop all SysV units */
3623 for (f = 1, t = 1; args[f]; f++) {
3625 if (isempty(args[f]))
3628 args[t++] = args[f];
3637 static int enable_unit(DBusConnection *bus, char **args) {
3638 const char *verb = args[0];
3639 UnitFileChange *changes = NULL;
3640 unsigned n_changes = 0, i;
3641 int carries_install_info = -1;
3642 DBusMessage *m = NULL, *reply = NULL;
3646 dbus_error_init(&error);
3648 r = enable_sysv_units(args);
3652 if (!bus || avoid_bus()) {
3653 if (streq(verb, "enable")) {
3654 r = unit_file_enable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3655 carries_install_info = r;
3656 } else if (streq(verb, "disable"))
3657 r = unit_file_disable(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3658 else if (streq(verb, "reenable")) {
3659 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3660 carries_install_info = r;
3661 } else if (streq(verb, "link"))
3662 r = unit_file_link(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3663 else if (streq(verb, "preset")) {
3664 r = unit_file_preset(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3665 carries_install_info = r;
3666 } else if (streq(verb, "mask"))
3667 r = unit_file_mask(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3668 else if (streq(verb, "unmask"))
3669 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3671 assert_not_reached("Unknown verb");
3674 log_error("Operation failed: %s", strerror(-r));
3678 for (i = 0; i < n_changes; i++) {
3679 if (changes[i].type == UNIT_FILE_SYMLINK)
3680 log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
3682 log_info("rm '%s'", changes[i].path);
3687 bool send_force = true, expect_carries_install_info = false;
3689 DBusMessageIter iter, sub, sub2;
3691 if (streq(verb, "enable")) {
3692 method = "EnableUnitFiles";
3693 expect_carries_install_info = true;
3694 } else if (streq(verb, "disable")) {
3695 method = "DisableUnitFiles";
3697 } else if (streq(verb, "reenable")) {
3698 method = "ReenableUnitFiles";
3699 expect_carries_install_info = true;
3700 } else if (streq(verb, "link"))
3701 method = "LinkUnitFiles";
3702 else if (streq(verb, "preset")) {
3703 method = "PresetUnitFiles";
3704 expect_carries_install_info = true;
3705 } else if (streq(verb, "mask"))
3706 method = "MaskUnitFiles";
3707 else if (streq(verb, "unmask")) {
3708 method = "UnmaskUnitFiles";
3711 assert_not_reached("Unknown verb");
3713 m = dbus_message_new_method_call(
3714 "org.freedesktop.systemd1",
3715 "/org/freedesktop/systemd1",
3716 "org.freedesktop.systemd1.Manager",
3719 log_error("Out of memory");
3724 dbus_message_iter_init_append(m, &iter);
3726 r = bus_append_strv_iter(&iter, args+1);
3728 log_error("Failed to append unit files.");
3733 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &a)) {
3734 log_error("Failed to append runtime boolean.");
3742 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b)) {
3743 log_error("Failed to append force boolean.");
3749 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3751 log_error("Failed to issue method call: %s", bus_error_message(&error));
3756 if (!dbus_message_iter_init(reply, &iter)) {
3757 log_error("Failed to initialize iterator.");
3761 if (expect_carries_install_info) {
3762 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &b, true);
3764 log_error("Failed to parse reply.");
3768 carries_install_info = b;
3771 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3772 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
3773 log_error("Failed to parse reply.");
3778 dbus_message_iter_recurse(&iter, &sub);
3779 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
3780 const char *type, *path, *source;
3782 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
3783 log_error("Failed to parse reply.");
3788 dbus_message_iter_recurse(&sub, &sub2);
3790 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
3791 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
3792 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &source, false) < 0) {
3793 log_error("Failed to parse reply.");
3798 if (streq(type, "symlink"))
3799 log_info("ln -s '%s' '%s'", source, path);
3801 log_info("rm '%s'", path);
3803 dbus_message_iter_next(&sub);
3806 /* Try to reload if enabeld */
3808 r = daemon_reload(bus, args);
3811 if (carries_install_info == 0)
3812 log_warning("Warning: unit files do not carry install information. No operation executed.");
3816 dbus_message_unref(m);
3819 dbus_message_unref(reply);
3821 unit_file_changes_free(changes, n_changes);
3823 dbus_error_free(&error);
3827 static int unit_is_enabled(DBusConnection *bus, char **args) {
3830 DBusMessage *m = NULL, *reply = NULL;
3834 dbus_error_init(&error);
3836 r = enable_sysv_units(args);
3842 if (!bus || avoid_bus()) {
3844 STRV_FOREACH(name, args+1) {
3845 UnitFileState state;
3847 state = unit_file_get_state(arg_scope, arg_root, *name);
3853 if (state == UNIT_FILE_ENABLED ||
3854 state == UNIT_FILE_ENABLED_RUNTIME ||
3855 state == UNIT_FILE_STATIC)
3859 puts(unit_file_state_to_string(state));
3863 STRV_FOREACH(name, args+1) {
3866 m = dbus_message_new_method_call(
3867 "org.freedesktop.systemd1",
3868 "/org/freedesktop/systemd1",
3869 "org.freedesktop.systemd1.Manager",
3870 "GetUnitFileState");
3872 log_error("Out of memory");
3877 if (!dbus_message_append_args(m,
3878 DBUS_TYPE_STRING, name,
3879 DBUS_TYPE_INVALID)) {
3880 log_error("Could not append arguments to message.");
3885 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3887 log_error("Failed to issue method call: %s", bus_error_message(&error));
3892 if (!dbus_message_get_args(reply, &error,
3893 DBUS_TYPE_STRING, &s,
3894 DBUS_TYPE_INVALID)) {
3895 log_error("Failed to parse reply: %s", bus_error_message(&error));
3900 dbus_message_unref(m);
3901 dbus_message_unref(reply);
3904 if (streq(s, "enabled") ||
3905 streq(s, "enabled-runtime") ||
3914 r = enabled ? 0 : 1;
3918 dbus_message_unref(m);
3921 dbus_message_unref(reply);
3923 dbus_error_free(&error);
3927 static int systemctl_help(void) {
3929 pager_open_if_enabled();
3931 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
3932 "Query or send control commands to the systemd manager.\n\n"
3933 " -h --help Show this help\n"
3934 " --version Show package version\n"
3935 " -t --type=TYPE List only units of a particular type\n"
3936 " -p --property=NAME Show only properties by this name\n"
3937 " -a --all Show all units/properties, including dead/empty ones\n"
3938 " --failed Show only failed units\n"
3939 " --full Don't ellipsize unit names on output\n"
3940 " --fail When queueing a new job, fail if conflicting jobs are\n"
3942 " --ignore-dependencies\n"
3943 " When queueing a new job, ignore all its dependencies\n"
3944 " --kill-who=WHO Who to send signal to\n"
3945 " -s --signal=SIGNAL Which signal to send\n"
3946 " -H --host=[USER@]HOST\n"
3947 " Show information for remote host\n"
3948 " -P --privileged Acquire privileges before execution\n"
3949 " -q --quiet Suppress output\n"
3950 " --no-block Do not wait until operation finished\n"
3951 " --no-wall Don't send wall message before halt/power-off/reboot\n"
3952 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
3954 " --no-legend Do not print a legend (column headers and hints)\n"
3955 " --no-pager Do not pipe output into a pager\n"
3956 " --no-ask-password\n"
3957 " Do not ask for system passwords\n"
3958 " --order When generating graph for dot, show only order\n"
3959 " --require When generating graph for dot, show only requirement\n"
3960 " --system Connect to system manager\n"
3961 " --user Connect to user service manager\n"
3962 " --global Enable/disable unit files globally\n"
3963 " -f --force When enabling unit files, override existing symlinks\n"
3964 " When shutting down, execute action immediately\n"
3965 " --root=PATH Enable unit files in the specified root directory\n"
3966 " --runtime Enable unit files only temporarily until next reboot\n\n"
3968 " list-units List loaded units\n"
3969 " start [NAME...] Start (activate) one or more units\n"
3970 " stop [NAME...] Stop (deactivate) one or more units\n"
3971 " reload [NAME...] Reload one or more units\n"
3972 " restart [NAME...] Start or restart one or more units\n"
3973 " try-restart [NAME...] Restart one or more units if active\n"
3974 " reload-or-restart [NAME...] Reload one or more units is possible,\n"
3975 " otherwise start or restart\n"
3976 " reload-or-try-restart [NAME...] Reload one or more units is possible,\n"
3977 " otherwise restart if active\n"
3978 " isolate [NAME] Start one unit and stop all others\n"
3979 " kill [NAME...] Send signal to processes of a unit\n"
3980 " is-active [NAME...] Check whether units are active\n"
3981 " status [NAME...|PID...] Show runtime status of one or more units\n"
3982 " show [NAME...|JOB...] Show properties of one or more\n"
3983 " units/jobs or the manager\n"
3984 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
3986 " load [NAME...] Load one or more units\n\n"
3987 "Unit File Commands:\n"
3988 " list-unit-files List installed unit files\n"
3989 " enable [NAME...] Enable one or more unit files\n"
3990 " disable [NAME...] Disable one or more unit files\n"
3991 " reenable [NAME...] Reenable one or more unit files\n"
3992 " preset [NAME...] Enable/disable one or more unit files\n"
3993 " based on preset configuration\n"
3994 " mask [NAME...] Mask one or more units\n"
3995 " unmask [NAME...] Unmask one or more units\n"
3996 " link [PATH...] Link one or more units files into\n"
3997 " the search path\n"
3998 " is-enabled [NAME...] Check whether unit files are enabled\n\n"
4000 " list-jobs List jobs\n"
4001 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
4002 "Status Commands:\n"
4003 " dump Dump server status\n"
4004 " dot Dump dependency graph for dot(1)\n\n"
4005 "Snapshot Commands:\n"
4006 " snapshot [NAME] Create a snapshot\n"
4007 " delete [NAME...] Remove one or more snapshots\n\n"
4008 "Environment Commands:\n"
4009 " show-environment Dump environment\n"
4010 " set-environment [NAME=VALUE...] Set one or more environment variables\n"
4011 " unset-environment [NAME...] Unset one or more environment variables\n\n"
4012 "Manager Lifecycle Commands:\n"
4013 " daemon-reload Reload systemd manager configuration\n"
4014 " daemon-reexec Reexecute systemd manager\n\n"
4015 "System Commands:\n"
4016 " default Enter system default mode\n"
4017 " rescue Enter system rescue mode\n"
4018 " emergency Enter system emergency mode\n"
4019 " halt Shut down and halt the system\n"
4020 " poweroff Shut down and power-off the system\n"
4021 " reboot Shut down and reboot the system\n"
4022 " kexec Shut down and reboot the system with kexec\n"
4023 " exit Ask for user instance termination\n",
4024 program_invocation_short_name);
4029 static int halt_help(void) {
4031 printf("%s [OPTIONS...]\n\n"
4032 "%s the system.\n\n"
4033 " --help Show this help\n"
4034 " --halt Halt the machine\n"
4035 " -p --poweroff Switch off the machine\n"
4036 " --reboot Reboot the machine\n"
4037 " -f --force Force immediate halt/power-off/reboot\n"
4038 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
4039 " -d --no-wtmp Don't write wtmp record\n"
4040 " -n --no-sync Don't sync before halt/power-off/reboot\n"
4041 " --no-wall Don't send wall message before halt/power-off/reboot\n",
4042 program_invocation_short_name,
4043 arg_action == ACTION_REBOOT ? "Reboot" :
4044 arg_action == ACTION_POWEROFF ? "Power off" :
4050 static int shutdown_help(void) {
4052 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
4053 "Shut down the system.\n\n"
4054 " --help Show this help\n"
4055 " -H --halt Halt the machine\n"
4056 " -P --poweroff Power-off the machine\n"
4057 " -r --reboot Reboot the machine\n"
4058 " -h Equivalent to --poweroff, overriden by --halt\n"
4059 " -k Don't halt/power-off/reboot, just send warnings\n"
4060 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4061 " -c Cancel a pending shutdown\n",
4062 program_invocation_short_name);
4067 static int telinit_help(void) {
4069 printf("%s [OPTIONS...] {COMMAND}\n\n"
4070 "Send control commands to the init daemon.\n\n"
4071 " --help Show this help\n"
4072 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
4074 " 0 Power-off the machine\n"
4075 " 6 Reboot the machine\n"
4076 " 2, 3, 4, 5 Start runlevelX.target unit\n"
4077 " 1, s, S Enter rescue mode\n"
4078 " q, Q Reload init daemon configuration\n"
4079 " u, U Reexecute init daemon\n",
4080 program_invocation_short_name);
4085 static int runlevel_help(void) {
4087 printf("%s [OPTIONS...]\n\n"
4088 "Prints the previous and current runlevel of the init system.\n\n"
4089 " --help Show this help\n",
4090 program_invocation_short_name);
4095 static int systemctl_parse_argv(int argc, char *argv[]) {
4099 ARG_IGNORE_DEPENDENCIES,
4115 ARG_NO_ASK_PASSWORD,
4120 static const struct option options[] = {
4121 { "help", no_argument, NULL, 'h' },
4122 { "version", no_argument, NULL, ARG_VERSION },
4123 { "type", required_argument, NULL, 't' },
4124 { "property", required_argument, NULL, 'p' },
4125 { "all", no_argument, NULL, 'a' },
4126 { "failed", no_argument, NULL, ARG_FAILED },
4127 { "full", no_argument, NULL, ARG_FULL },
4128 { "fail", no_argument, NULL, ARG_FAIL },
4129 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
4130 { "user", no_argument, NULL, ARG_USER },
4131 { "system", no_argument, NULL, ARG_SYSTEM },
4132 { "global", no_argument, NULL, ARG_GLOBAL },
4133 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
4134 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
4135 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
4136 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4137 { "quiet", no_argument, NULL, 'q' },
4138 { "order", no_argument, NULL, ARG_ORDER },
4139 { "require", no_argument, NULL, ARG_REQUIRE },
4140 { "root", required_argument, NULL, ARG_ROOT },
4141 { "force", no_argument, NULL, 'f' },
4142 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
4143 { "kill-mode", required_argument, NULL, ARG_KILL_MODE }, /* undocumented on purpose */
4144 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
4145 { "signal", required_argument, NULL, 's' },
4146 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
4147 { "host", required_argument, NULL, 'H' },
4148 { "privileged",no_argument, NULL, 'P' },
4149 { "runtime", no_argument, NULL, ARG_RUNTIME },
4150 { NULL, 0, NULL, 0 }
4158 /* Only when running as systemctl we ask for passwords */
4159 arg_ask_password = true;
4161 while ((c = getopt_long(argc, argv, "ht:p:aqfs:H:P", options, NULL)) >= 0) {
4170 puts(PACKAGE_STRING);
4172 puts(SYSTEMD_FEATURES);
4182 if (!(l = strv_append(arg_property, optarg)))
4185 strv_free(arg_property);
4188 /* If the user asked for a particular
4189 * property, show it to him, even if it is
4200 arg_job_mode = "fail";
4203 case ARG_IGNORE_DEPENDENCIES:
4204 arg_job_mode = "ignore-dependencies";
4208 arg_scope = UNIT_FILE_USER;
4212 arg_scope = UNIT_FILE_SYSTEM;
4216 arg_scope = UNIT_FILE_GLOBAL;
4220 arg_no_block = true;
4224 arg_no_legend = true;
4228 arg_no_pager = true;
4236 arg_dot = DOT_ORDER;
4240 arg_dot = DOT_REQUIRE;
4264 arg_no_reload = true;
4268 arg_kill_who = optarg;
4272 arg_kill_mode = optarg;
4276 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
4277 log_error("Failed to parse signal string %s.", optarg);
4282 case ARG_NO_ASK_PASSWORD:
4283 arg_ask_password = false;
4287 arg_transport = TRANSPORT_POLKIT;
4291 arg_transport = TRANSPORT_SSH;
4303 log_error("Unknown option code %c", c);
4308 if (arg_transport != TRANSPORT_NORMAL && arg_scope != UNIT_FILE_SYSTEM) {
4309 log_error("Cannot access user instance remotely.");
4316 static int halt_parse_argv(int argc, char *argv[]) {
4325 static const struct option options[] = {
4326 { "help", no_argument, NULL, ARG_HELP },
4327 { "halt", no_argument, NULL, ARG_HALT },
4328 { "poweroff", no_argument, NULL, 'p' },
4329 { "reboot", no_argument, NULL, ARG_REBOOT },
4330 { "force", no_argument, NULL, 'f' },
4331 { "wtmp-only", no_argument, NULL, 'w' },
4332 { "no-wtmp", no_argument, NULL, 'd' },
4333 { "no-sync", no_argument, NULL, 'n' },
4334 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4335 { NULL, 0, NULL, 0 }
4343 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
4344 if (runlevel == '0' || runlevel == '6')
4345 arg_immediate = true;
4347 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
4355 arg_action = ACTION_HALT;
4359 if (arg_action != ACTION_REBOOT)
4360 arg_action = ACTION_POWEROFF;
4364 arg_action = ACTION_REBOOT;
4368 arg_immediate = true;
4389 /* Compatibility nops */
4396 log_error("Unknown option code %c", c);
4401 if (optind < argc) {
4402 log_error("Too many arguments.");
4409 static int parse_time_spec(const char *t, usec_t *_u) {
4413 if (streq(t, "now"))
4415 else if (!strchr(t, ':')) {
4418 if (safe_atou64(t, &u) < 0)
4421 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
4430 hour = strtol(t, &e, 10);
4431 if (errno != 0 || *e != ':' || hour < 0 || hour > 23)
4434 minute = strtol(e+1, &e, 10);
4435 if (errno != 0 || *e != 0 || minute < 0 || minute > 59)
4438 n = now(CLOCK_REALTIME);
4439 s = (time_t) (n / USEC_PER_SEC);
4442 assert_se(localtime_r(&s, &tm));
4444 tm.tm_hour = (int) hour;
4445 tm.tm_min = (int) minute;
4448 assert_se(s = mktime(&tm));
4450 *_u = (usec_t) s * USEC_PER_SEC;
4453 *_u += USEC_PER_DAY;
4459 static int shutdown_parse_argv(int argc, char *argv[]) {
4466 static const struct option options[] = {
4467 { "help", no_argument, NULL, ARG_HELP },
4468 { "halt", no_argument, NULL, 'H' },
4469 { "poweroff", no_argument, NULL, 'P' },
4470 { "reboot", no_argument, NULL, 'r' },
4471 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4472 { NULL, 0, NULL, 0 }
4480 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
4488 arg_action = ACTION_HALT;
4492 arg_action = ACTION_POWEROFF;
4497 arg_action = ACTION_KEXEC;
4499 arg_action = ACTION_REBOOT;
4503 if (arg_action != ACTION_HALT)
4504 arg_action = ACTION_POWEROFF;
4517 /* Compatibility nops */
4521 arg_action = ACTION_CANCEL_SHUTDOWN;
4528 log_error("Unknown option code %c", c);
4533 if (argc > optind) {
4534 if ((r = parse_time_spec(argv[optind], &arg_when)) < 0) {
4535 log_error("Failed to parse time specification: %s", argv[optind]);
4539 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
4541 /* We skip the time argument */
4542 if (argc > optind + 1)
4543 arg_wall = argv + optind + 1;
4550 static int telinit_parse_argv(int argc, char *argv[]) {
4557 static const struct option options[] = {
4558 { "help", no_argument, NULL, ARG_HELP },
4559 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4560 { NULL, 0, NULL, 0 }
4563 static const struct {
4567 { '0', ACTION_POWEROFF },
4568 { '6', ACTION_REBOOT },
4569 { '1', ACTION_RESCUE },
4570 { '2', ACTION_RUNLEVEL2 },
4571 { '3', ACTION_RUNLEVEL3 },
4572 { '4', ACTION_RUNLEVEL4 },
4573 { '5', ACTION_RUNLEVEL5 },
4574 { 's', ACTION_RESCUE },
4575 { 'S', ACTION_RESCUE },
4576 { 'q', ACTION_RELOAD },
4577 { 'Q', ACTION_RELOAD },
4578 { 'u', ACTION_REEXEC },
4579 { 'U', ACTION_REEXEC }
4588 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4603 log_error("Unknown option code %c", c);
4608 if (optind >= argc) {
4613 if (optind + 1 < argc) {
4614 log_error("Too many arguments.");
4618 if (strlen(argv[optind]) != 1) {
4619 log_error("Expected single character argument.");
4623 for (i = 0; i < ELEMENTSOF(table); i++)
4624 if (table[i].from == argv[optind][0])
4627 if (i >= ELEMENTSOF(table)) {
4628 log_error("Unknown command %s.", argv[optind]);
4632 arg_action = table[i].to;
4639 static int runlevel_parse_argv(int argc, char *argv[]) {
4645 static const struct option options[] = {
4646 { "help", no_argument, NULL, ARG_HELP },
4647 { NULL, 0, NULL, 0 }
4655 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4666 log_error("Unknown option code %c", c);
4671 if (optind < argc) {
4672 log_error("Too many arguments.");
4679 static int parse_argv(int argc, char *argv[]) {
4683 if (program_invocation_short_name) {
4685 if (strstr(program_invocation_short_name, "halt")) {
4686 arg_action = ACTION_HALT;
4687 return halt_parse_argv(argc, argv);
4688 } else if (strstr(program_invocation_short_name, "poweroff")) {
4689 arg_action = ACTION_POWEROFF;
4690 return halt_parse_argv(argc, argv);
4691 } else if (strstr(program_invocation_short_name, "reboot")) {
4693 arg_action = ACTION_KEXEC;
4695 arg_action = ACTION_REBOOT;
4696 return halt_parse_argv(argc, argv);
4697 } else if (strstr(program_invocation_short_name, "shutdown")) {
4698 arg_action = ACTION_POWEROFF;
4699 return shutdown_parse_argv(argc, argv);
4700 } else if (strstr(program_invocation_short_name, "init")) {
4702 if (sd_booted() > 0) {
4703 arg_action = ACTION_INVALID;
4704 return telinit_parse_argv(argc, argv);
4706 /* Hmm, so some other init system is
4707 * running, we need to forward this
4708 * request to it. For now we simply
4709 * guess that it is Upstart. */
4711 execv("/lib/upstart/telinit", argv);
4713 log_error("Couldn't find an alternative telinit implementation to spawn.");
4717 } else if (strstr(program_invocation_short_name, "runlevel")) {
4718 arg_action = ACTION_RUNLEVEL;
4719 return runlevel_parse_argv(argc, argv);
4723 arg_action = ACTION_SYSTEMCTL;
4724 return systemctl_parse_argv(argc, argv);
4727 static int action_to_runlevel(void) {
4729 static const char table[_ACTION_MAX] = {
4730 [ACTION_HALT] = '0',
4731 [ACTION_POWEROFF] = '0',
4732 [ACTION_REBOOT] = '6',
4733 [ACTION_RUNLEVEL2] = '2',
4734 [ACTION_RUNLEVEL3] = '3',
4735 [ACTION_RUNLEVEL4] = '4',
4736 [ACTION_RUNLEVEL5] = '5',
4737 [ACTION_RESCUE] = '1'
4740 assert(arg_action < _ACTION_MAX);
4742 return table[arg_action];
4745 static int talk_upstart(void) {
4746 DBusMessage *m = NULL, *reply = NULL;
4748 int previous, rl, r;
4750 env1_buf[] = "RUNLEVEL=X",
4751 env2_buf[] = "PREVLEVEL=X";
4752 char *env1 = env1_buf, *env2 = env2_buf;
4753 const char *emit = "runlevel";
4754 dbus_bool_t b_false = FALSE;
4755 DBusMessageIter iter, sub;
4756 DBusConnection *bus;
4758 dbus_error_init(&error);
4760 if (!(rl = action_to_runlevel()))
4763 if (utmp_get_runlevel(&previous, NULL) < 0)
4766 if (!(bus = dbus_connection_open_private("unix:abstract=/com/ubuntu/upstart", &error))) {
4767 if (dbus_error_has_name(&error, DBUS_ERROR_NO_SERVER)) {
4772 log_error("Failed to connect to Upstart bus: %s", bus_error_message(&error));
4777 if ((r = bus_check_peercred(bus)) < 0) {
4778 log_error("Failed to verify owner of bus.");
4782 if (!(m = dbus_message_new_method_call(
4783 "com.ubuntu.Upstart",
4784 "/com/ubuntu/Upstart",
4785 "com.ubuntu.Upstart0_6",
4788 log_error("Could not allocate message.");
4793 dbus_message_iter_init_append(m, &iter);
4795 env1_buf[sizeof(env1_buf)-2] = rl;
4796 env2_buf[sizeof(env2_buf)-2] = previous;
4798 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &emit) ||
4799 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub) ||
4800 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env1) ||
4801 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env2) ||
4802 !dbus_message_iter_close_container(&iter, &sub) ||
4803 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b_false)) {
4804 log_error("Could not append arguments to message.");
4809 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
4811 if (error_is_no_service(&error)) {
4816 log_error("Failed to issue method call: %s", bus_error_message(&error));
4825 dbus_message_unref(m);
4828 dbus_message_unref(reply);
4831 dbus_connection_flush(bus);
4832 dbus_connection_close(bus);
4833 dbus_connection_unref(bus);
4836 dbus_error_free(&error);
4841 static int talk_initctl(void) {
4842 struct init_request request;
4846 if (!(rl = action_to_runlevel()))
4850 request.magic = INIT_MAGIC;
4851 request.sleeptime = 0;
4852 request.cmd = INIT_CMD_RUNLVL;
4853 request.runlevel = rl;
4855 if ((fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY)) < 0) {
4857 if (errno == ENOENT)
4860 log_error("Failed to open "INIT_FIFO": %m");
4865 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
4866 close_nointr_nofail(fd);
4869 log_error("Failed to write to "INIT_FIFO": %m");
4870 return errno ? -errno : -EIO;
4876 static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
4878 static const struct {
4886 int (* const dispatch)(DBusConnection *bus, char **args);
4888 { "list-units", LESS, 1, list_units },
4889 { "list-unit-files", EQUAL, 1, list_unit_files },
4890 { "list-jobs", EQUAL, 1, list_jobs },
4891 { "clear-jobs", EQUAL, 1, daemon_reload },
4892 { "load", MORE, 2, load_unit },
4893 { "cancel", MORE, 2, cancel_job },
4894 { "start", MORE, 2, start_unit },
4895 { "stop", MORE, 2, start_unit },
4896 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
4897 { "reload", MORE, 2, start_unit },
4898 { "restart", MORE, 2, start_unit },
4899 { "try-restart", MORE, 2, start_unit },
4900 { "reload-or-restart", MORE, 2, start_unit },
4901 { "reload-or-try-restart", MORE, 2, start_unit },
4902 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
4903 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
4904 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
4905 { "isolate", EQUAL, 2, start_unit },
4906 { "kill", MORE, 2, kill_unit },
4907 { "is-active", MORE, 2, check_unit },
4908 { "check", MORE, 2, check_unit },
4909 { "show", MORE, 1, show },
4910 { "status", MORE, 2, show },
4911 { "dump", EQUAL, 1, dump },
4912 { "dot", EQUAL, 1, dot },
4913 { "snapshot", LESS, 2, snapshot },
4914 { "delete", MORE, 2, delete_snapshot },
4915 { "daemon-reload", EQUAL, 1, daemon_reload },
4916 { "daemon-reexec", EQUAL, 1, daemon_reload },
4917 { "show-environment", EQUAL, 1, show_enviroment },
4918 { "set-environment", MORE, 2, set_environment },
4919 { "unset-environment", MORE, 2, set_environment },
4920 { "halt", EQUAL, 1, start_special },
4921 { "poweroff", EQUAL, 1, start_special },
4922 { "reboot", EQUAL, 1, start_special },
4923 { "kexec", EQUAL, 1, start_special },
4924 { "default", EQUAL, 1, start_special },
4925 { "rescue", EQUAL, 1, start_special },
4926 { "emergency", EQUAL, 1, start_special },
4927 { "exit", EQUAL, 1, start_special },
4928 { "reset-failed", MORE, 1, reset_failed },
4929 { "enable", MORE, 2, enable_unit },
4930 { "disable", MORE, 2, enable_unit },
4931 { "is-enabled", MORE, 2, unit_is_enabled },
4932 { "reenable", MORE, 2, enable_unit },
4933 { "preset", MORE, 2, enable_unit },
4934 { "mask", MORE, 2, enable_unit },
4935 { "unmask", MORE, 2, enable_unit },
4936 { "link", MORE, 2, enable_unit }
4946 left = argc - optind;
4949 /* Special rule: no arguments means "list-units" */
4952 if (streq(argv[optind], "help")) {
4957 for (i = 0; i < ELEMENTSOF(verbs); i++)
4958 if (streq(argv[optind], verbs[i].verb))
4961 if (i >= ELEMENTSOF(verbs)) {
4962 log_error("Unknown operation %s", argv[optind]);
4967 switch (verbs[i].argc_cmp) {
4970 if (left != verbs[i].argc) {
4971 log_error("Invalid number of arguments.");
4978 if (left < verbs[i].argc) {
4979 log_error("Too few arguments.");
4986 if (left > verbs[i].argc) {
4987 log_error("Too many arguments.");
4994 assert_not_reached("Unknown comparison operator.");
4997 /* Require a bus connection for all operations but
4999 if (!streq(verbs[i].verb, "enable") &&
5000 !streq(verbs[i].verb, "disable") &&
5001 !streq(verbs[i].verb, "is-enabled") &&
5002 !streq(verbs[i].verb, "list-unit-files") &&
5003 !streq(verbs[i].verb, "reenable") &&
5004 !streq(verbs[i].verb, "preset") &&
5005 !streq(verbs[i].verb, "mask") &&
5006 !streq(verbs[i].verb, "unmask") &&
5007 !streq(verbs[i].verb, "link")) {
5009 if (running_in_chroot() > 0) {
5010 log_info("Running in chroot, ignoring request.");
5015 log_error("Failed to get D-Bus connection: %s",
5016 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5022 if (!bus && !avoid_bus()) {
5023 log_error("Failed to get D-Bus connection: %s",
5024 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5029 return verbs[i].dispatch(bus, argv + optind);
5032 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
5034 struct msghdr msghdr;
5036 union sockaddr_union sockaddr;
5037 struct shutdownd_command c;
5042 c.dry_run = dry_run;
5046 strncpy(c.wall_message, message, sizeof(c.wall_message));
5048 if ((fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0)) < 0)
5052 sockaddr.sa.sa_family = AF_UNIX;
5053 sockaddr.un.sun_path[0] = 0;
5054 strncpy(sockaddr.un.sun_path, "/run/systemd/shutdownd", sizeof(sockaddr.un.sun_path));
5057 iovec.iov_base = (char*) &c;
5058 iovec.iov_len = sizeof(c);
5061 msghdr.msg_name = &sockaddr;
5062 msghdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + sizeof("/run/systemd/shutdownd") - 1;
5064 msghdr.msg_iov = &iovec;
5065 msghdr.msg_iovlen = 1;
5067 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0) {
5068 close_nointr_nofail(fd);
5072 close_nointr_nofail(fd);
5076 static int reload_with_fallback(DBusConnection *bus) {
5079 /* First, try systemd via D-Bus. */
5080 if (daemon_reload(bus, NULL) >= 0)
5084 /* Nothing else worked, so let's try signals */
5085 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
5087 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
5088 log_error("kill() failed: %m");
5095 static int start_with_fallback(DBusConnection *bus) {
5098 /* First, try systemd via D-Bus. */
5099 if (start_unit(bus, NULL) >= 0)
5103 /* Hmm, talking to systemd via D-Bus didn't work. Then
5104 * let's try to talk to Upstart via D-Bus. */
5105 if (talk_upstart() > 0)
5108 /* Nothing else worked, so let's try
5110 if (talk_initctl() > 0)
5113 log_error("Failed to talk to init daemon.");
5117 warn_wall(arg_action);
5121 static int halt_main(DBusConnection *bus) {
5124 if (geteuid() != 0) {
5125 log_error("Must be root.");
5131 char date[FORMAT_TIMESTAMP_MAX];
5133 m = strv_join(arg_wall, " ");
5134 r = send_shutdownd(arg_when,
5135 arg_action == ACTION_HALT ? 'H' :
5136 arg_action == ACTION_POWEROFF ? 'P' :
5144 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
5146 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
5147 format_timestamp(date, sizeof(date), arg_when));
5152 if (!arg_dry && !arg_immediate)
5153 return start_with_fallback(bus);
5156 if (sd_booted() > 0)
5157 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
5158 else if ((r = utmp_put_shutdown()) < 0)
5159 log_warning("Failed to write utmp record: %s", strerror(-r));
5168 /* Make sure C-A-D is handled by the kernel from this
5170 reboot(RB_ENABLE_CAD);
5172 switch (arg_action) {
5175 log_info("Halting.");
5176 reboot(RB_HALT_SYSTEM);
5179 case ACTION_POWEROFF:
5180 log_info("Powering off.");
5181 reboot(RB_POWER_OFF);
5185 log_info("Rebooting.");
5186 reboot(RB_AUTOBOOT);
5190 assert_not_reached("Unknown halt action.");
5193 /* We should never reach this. */
5197 static int runlevel_main(void) {
5198 int r, runlevel, previous;
5200 r = utmp_get_runlevel(&runlevel, &previous);
5207 previous <= 0 ? 'N' : previous,
5208 runlevel <= 0 ? 'N' : runlevel);
5213 int main(int argc, char*argv[]) {
5214 int r, retval = EXIT_FAILURE;
5215 DBusConnection *bus = NULL;
5218 dbus_error_init(&error);
5220 log_parse_environment();
5223 if ((r = parse_argv(argc, argv)) < 0)
5226 retval = EXIT_SUCCESS;
5230 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
5231 * let's shortcut this */
5232 if (arg_action == ACTION_RUNLEVEL) {
5233 r = runlevel_main();
5234 retval = r < 0 ? EXIT_FAILURE : r;
5238 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
5239 log_info("Running in chroot, ignoring request.");
5245 if (arg_transport == TRANSPORT_NORMAL)
5246 bus_connect(arg_scope == UNIT_FILE_SYSTEM ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &bus, &private_bus, &error);
5247 else if (arg_transport == TRANSPORT_POLKIT) {
5248 bus_connect_system_polkit(&bus, &error);
5249 private_bus = false;
5250 } else if (arg_transport == TRANSPORT_SSH) {
5251 bus_connect_system_ssh(NULL, arg_host, &bus, &error);
5252 private_bus = false;
5254 assert_not_reached("Uh, invalid transport...");
5257 switch (arg_action) {
5259 case ACTION_SYSTEMCTL:
5260 r = systemctl_main(bus, argc, argv, &error);
5264 case ACTION_POWEROFF:
5270 case ACTION_RUNLEVEL2:
5271 case ACTION_RUNLEVEL3:
5272 case ACTION_RUNLEVEL4:
5273 case ACTION_RUNLEVEL5:
5275 case ACTION_EMERGENCY:
5276 case ACTION_DEFAULT:
5277 r = start_with_fallback(bus);
5282 r = reload_with_fallback(bus);
5285 case ACTION_CANCEL_SHUTDOWN:
5286 r = send_shutdownd(0, 0, false, false, NULL);
5289 case ACTION_INVALID:
5290 case ACTION_RUNLEVEL:
5292 assert_not_reached("Unknown action");
5295 retval = r < 0 ? EXIT_FAILURE : r;
5299 dbus_connection_flush(bus);
5300 dbus_connection_close(bus);
5301 dbus_connection_unref(bus);
5304 dbus_error_free(&error);
5308 strv_free(arg_property);