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_full || !arg_no_pager)
365 printf("%-*s %-6s %-*s %-*s %-*s %.*s\n", id_len, "UNIT", "LOAD",
366 active_len, "ACTIVE", sub_len, "SUB", job_len, "JOB",
367 desc_len, "DESCRIPTION");
369 for (u = unit_infos; u < unit_infos + c; u++) {
371 const char *on_loaded, *off_loaded;
372 const char *on_active, *off_active;
374 if (!output_show_unit(u))
379 if (!streq(u->load_state, "loaded") &&
380 !streq(u->load_state, "banned")) {
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 %.*s\n",
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 desc_len, u->description);
405 if (!arg_no_legend) {
406 printf("\nLOAD = Reflects whether the unit definition was properly loaded.\n"
407 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
408 "SUB = The low-level unit activation state, values depend on unit type.\n"
409 "JOB = Pending job for the unit.\n");
412 printf("\n%u units listed.\n", n_shown);
414 printf("\n%u units listed. Pass --all to see inactive units, too.\n", n_shown);
418 static int list_units(DBusConnection *bus, char **args) {
419 DBusMessage *m = NULL, *reply = NULL;
422 DBusMessageIter iter, sub, sub2;
423 unsigned c = 0, n_units = 0;
424 struct unit_info *unit_infos = NULL;
426 dbus_error_init(&error);
430 pager_open_if_enabled();
432 if (!(m = dbus_message_new_method_call(
433 "org.freedesktop.systemd1",
434 "/org/freedesktop/systemd1",
435 "org.freedesktop.systemd1.Manager",
437 log_error("Could not allocate message.");
441 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
442 log_error("Failed to issue method call: %s", bus_error_message(&error));
447 if (!dbus_message_iter_init(reply, &iter) ||
448 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
449 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
450 log_error("Failed to parse reply.");
455 dbus_message_iter_recurse(&iter, &sub);
457 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
460 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
461 log_error("Failed to parse reply.");
469 n_units = MAX(2*c, 16);
470 w = realloc(unit_infos, sizeof(struct unit_info) * n_units);
473 log_error("Failed to allocate unit array.");
483 dbus_message_iter_recurse(&sub, &sub2);
485 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->id, true) < 0 ||
486 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->description, true) < 0 ||
487 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->load_state, true) < 0 ||
488 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->active_state, true) < 0 ||
489 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->sub_state, true) < 0 ||
490 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->following, true) < 0 ||
491 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &u->unit_path, true) < 0 ||
492 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &u->job_id, true) < 0 ||
493 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->job_type, true) < 0 ||
494 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &u->job_path, false) < 0) {
495 log_error("Failed to parse reply.");
500 dbus_message_iter_next(&sub);
505 qsort(unit_infos, c, sizeof(struct unit_info), compare_unit_info);
506 output_units_list(unit_infos, c);
513 dbus_message_unref(m);
516 dbus_message_unref(reply);
520 dbus_error_free(&error);
525 static int compare_unit_file_list(const void *a, const void *b) {
527 const UnitFileList *u = a, *v = b;
529 d1 = strrchr(u->path, '.');
530 d2 = strrchr(v->path, '.');
535 r = strcasecmp(d1, d2);
540 return strcasecmp(file_name_from_path(u->path), file_name_from_path(v->path));
543 static bool output_show_unit_file(const UnitFileList *u) {
546 return !arg_type || ((dot = strrchr(u->path, '.')) && streq(dot+1, arg_type));
549 static void output_unit_file_list(const UnitFileList *units, unsigned c) {
550 unsigned n_shown = 0;
551 const UnitFileList *u;
554 printf("%-25s %-6s\n", "UNIT FILE", "STATE");
556 for (u = units; u < units + c; u++) {
558 const char *on, *off;
561 if (!output_show_unit_file(u))
566 if (u->state == UNIT_FILE_MASKED ||
567 u->state == UNIT_FILE_MASKED_RUNTIME ||
568 u->state == UNIT_FILE_DISABLED) {
569 on = ansi_highlight(true);
570 off = ansi_highlight(false);
571 } else if (u->state == UNIT_FILE_ENABLED) {
572 on = ansi_highlight_green(true);
573 off = ansi_highlight_green(false);
577 id = file_name_from_path(u->path);
579 e = arg_full ? NULL : ellipsize(id, 25, 33);
581 printf("%-25s %s%-6s%s\n",
583 on, unit_file_state_to_string(u->state), off);
589 printf("\n%u unit files listed.\n", n_shown);
592 static int list_unit_files(DBusConnection *bus, char **args) {
593 DBusMessage *m = NULL, *reply = NULL;
596 DBusMessageIter iter, sub, sub2;
597 unsigned c = 0, n_units = 0;
598 UnitFileList *units = NULL;
600 dbus_error_init(&error);
604 pager_open_if_enabled();
611 h = hashmap_new(string_hash_func, string_compare_func);
613 log_error("Out of memory");
617 r = unit_file_get_list(arg_scope, arg_root, h);
619 unit_file_list_free(h);
620 log_error("Failed to get unit file list: %s", strerror(-r));
624 n_units = hashmap_size(h);
625 units = new(UnitFileList, n_units);
627 unit_file_list_free(h);
628 log_error("Out of memory");
632 HASHMAP_FOREACH(u, h, i) {
633 memcpy(units + c++, u, sizeof(UnitFileList));
639 m = dbus_message_new_method_call(
640 "org.freedesktop.systemd1",
641 "/org/freedesktop/systemd1",
642 "org.freedesktop.systemd1.Manager",
645 log_error("Could not allocate message.");
649 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
651 log_error("Failed to issue method call: %s", bus_error_message(&error));
656 if (!dbus_message_iter_init(reply, &iter) ||
657 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
658 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
659 log_error("Failed to parse reply.");
664 dbus_message_iter_recurse(&iter, &sub);
666 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
670 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
671 log_error("Failed to parse reply.");
679 n_units = MAX(2*c, 16);
680 w = realloc(units, sizeof(struct UnitFileList) * n_units);
683 log_error("Failed to allocate unit array.");
693 dbus_message_iter_recurse(&sub, &sub2);
695 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->path, true) < 0 ||
696 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, false) < 0) {
697 log_error("Failed to parse reply.");
702 u->state = unit_file_state_from_string(state);
704 dbus_message_iter_next(&sub);
710 qsort(units, c, sizeof(UnitFileList), compare_unit_file_list);
711 output_unit_file_list(units, c);
718 dbus_message_unref(m);
721 dbus_message_unref(reply);
725 dbus_error_free(&error);
730 static int dot_one_property(const char *name, const char *prop, DBusMessageIter *iter) {
731 static const char * const colors[] = {
732 "Requires", "[color=\"black\"]",
733 "RequiresOverridable", "[color=\"black\"]",
734 "Requisite", "[color=\"darkblue\"]",
735 "RequisiteOverridable", "[color=\"darkblue\"]",
736 "Wants", "[color=\"darkgrey\"]",
737 "Conflicts", "[color=\"red\"]",
738 "ConflictedBy", "[color=\"red\"]",
739 "After", "[color=\"green\"]"
742 const char *c = NULL;
749 for (i = 0; i < ELEMENTSOF(colors); i += 2)
750 if (streq(colors[i], prop)) {
758 if (arg_dot != DOT_ALL)
759 if ((arg_dot == DOT_ORDER) != streq(prop, "After"))
762 switch (dbus_message_iter_get_arg_type(iter)) {
764 case DBUS_TYPE_ARRAY:
766 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING) {
769 dbus_message_iter_recurse(iter, &sub);
771 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
774 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING);
775 dbus_message_iter_get_basic(&sub, &s);
776 printf("\t\"%s\"->\"%s\" %s;\n", name, s, c);
778 dbus_message_iter_next(&sub);
788 static int dot_one(DBusConnection *bus, const char *name, const char *path) {
789 DBusMessage *m = NULL, *reply = NULL;
790 const char *interface = "org.freedesktop.systemd1.Unit";
793 DBusMessageIter iter, sub, sub2, sub3;
798 dbus_error_init(&error);
800 if (!(m = dbus_message_new_method_call(
801 "org.freedesktop.systemd1",
803 "org.freedesktop.DBus.Properties",
805 log_error("Could not allocate message.");
810 if (!dbus_message_append_args(m,
811 DBUS_TYPE_STRING, &interface,
812 DBUS_TYPE_INVALID)) {
813 log_error("Could not append arguments to message.");
818 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
819 log_error("Failed to issue method call: %s", bus_error_message(&error));
824 if (!dbus_message_iter_init(reply, &iter) ||
825 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
826 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
827 log_error("Failed to parse reply.");
832 dbus_message_iter_recurse(&iter, &sub);
834 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
837 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_DICT_ENTRY) {
838 log_error("Failed to parse reply.");
843 dbus_message_iter_recurse(&sub, &sub2);
845 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &prop, true) < 0) {
846 log_error("Failed to parse reply.");
851 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
852 log_error("Failed to parse reply.");
857 dbus_message_iter_recurse(&sub2, &sub3);
859 if (dot_one_property(name, prop, &sub3)) {
860 log_error("Failed to parse reply.");
865 dbus_message_iter_next(&sub);
872 dbus_message_unref(m);
875 dbus_message_unref(reply);
877 dbus_error_free(&error);
882 static int dot(DBusConnection *bus, char **args) {
883 DBusMessage *m = NULL, *reply = NULL;
886 DBusMessageIter iter, sub, sub2;
888 dbus_error_init(&error);
892 if (!(m = dbus_message_new_method_call(
893 "org.freedesktop.systemd1",
894 "/org/freedesktop/systemd1",
895 "org.freedesktop.systemd1.Manager",
897 log_error("Could not allocate message.");
901 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
902 log_error("Failed to issue method call: %s", bus_error_message(&error));
907 if (!dbus_message_iter_init(reply, &iter) ||
908 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
909 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
910 log_error("Failed to parse reply.");
915 printf("digraph systemd {\n");
917 dbus_message_iter_recurse(&iter, &sub);
918 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
919 const char *id, *description, *load_state, *active_state, *sub_state, *following, *unit_path;
921 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
922 log_error("Failed to parse reply.");
927 dbus_message_iter_recurse(&sub, &sub2);
929 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &id, true) < 0 ||
930 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &description, true) < 0 ||
931 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &load_state, true) < 0 ||
932 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &active_state, true) < 0 ||
933 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &sub_state, true) < 0 ||
934 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &following, true) < 0 ||
935 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, true) < 0) {
936 log_error("Failed to parse reply.");
941 if ((r = dot_one(bus, id, unit_path)) < 0)
944 /* printf("\t\"%s\";\n", id); */
945 dbus_message_iter_next(&sub);
950 log_info(" Color legend: black = Requires\n"
951 " dark blue = Requisite\n"
952 " dark grey = Wants\n"
957 log_notice("-- You probably want to process this output with graphviz' dot tool.\n"
958 "-- Try a shell pipeline like 'systemctl dot | dot -Tsvg > systemd.svg'!\n");
964 dbus_message_unref(m);
967 dbus_message_unref(reply);
969 dbus_error_free(&error);
974 static int list_jobs(DBusConnection *bus, char **args) {
975 DBusMessage *m = NULL, *reply = NULL;
978 DBusMessageIter iter, sub, sub2;
981 dbus_error_init(&error);
985 pager_open_if_enabled();
987 if (!(m = dbus_message_new_method_call(
988 "org.freedesktop.systemd1",
989 "/org/freedesktop/systemd1",
990 "org.freedesktop.systemd1.Manager",
992 log_error("Could not allocate message.");
996 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
997 log_error("Failed to issue method call: %s", bus_error_message(&error));
1002 if (!dbus_message_iter_init(reply, &iter) ||
1003 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
1004 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
1005 log_error("Failed to parse reply.");
1010 dbus_message_iter_recurse(&iter, &sub);
1013 printf("%4s %-25s %-15s %-7s\n", "JOB", "UNIT", "TYPE", "STATE");
1015 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1016 const char *name, *type, *state, *job_path, *unit_path;
1020 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
1021 log_error("Failed to parse reply.");
1026 dbus_message_iter_recurse(&sub, &sub2);
1028 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &id, true) < 0 ||
1029 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
1030 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
1031 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, true) < 0 ||
1032 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &job_path, true) < 0 ||
1033 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, false) < 0) {
1034 log_error("Failed to parse reply.");
1039 e = arg_full ? NULL : ellipsize(name, 25, 33);
1040 printf("%4u %-25s %-15s %-7s\n", id, e ? e : name, type, state);
1045 dbus_message_iter_next(&sub);
1049 printf("\n%u jobs listed.\n", k);
1055 dbus_message_unref(m);
1058 dbus_message_unref(reply);
1060 dbus_error_free(&error);
1065 static int load_unit(DBusConnection *bus, char **args) {
1066 DBusMessage *m = NULL;
1071 dbus_error_init(&error);
1076 STRV_FOREACH(name, args+1) {
1079 if (!(m = dbus_message_new_method_call(
1080 "org.freedesktop.systemd1",
1081 "/org/freedesktop/systemd1",
1082 "org.freedesktop.systemd1.Manager",
1084 log_error("Could not allocate message.");
1089 if (!dbus_message_append_args(m,
1090 DBUS_TYPE_STRING, name,
1091 DBUS_TYPE_INVALID)) {
1092 log_error("Could not append arguments to message.");
1097 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
1098 log_error("Failed to issue method call: %s", bus_error_message(&error));
1103 dbus_message_unref(m);
1104 dbus_message_unref(reply);
1113 dbus_message_unref(m);
1115 dbus_error_free(&error);
1120 static int cancel_job(DBusConnection *bus, char **args) {
1121 DBusMessage *m = NULL, *reply = NULL;
1126 dbus_error_init(&error);
1131 if (strv_length(args) <= 1)
1132 return daemon_reload(bus, args);
1134 STRV_FOREACH(name, args+1) {
1138 if (!(m = dbus_message_new_method_call(
1139 "org.freedesktop.systemd1",
1140 "/org/freedesktop/systemd1",
1141 "org.freedesktop.systemd1.Manager",
1143 log_error("Could not allocate message.");
1148 if ((r = safe_atou(*name, &id)) < 0) {
1149 log_error("Failed to parse job id: %s", strerror(-r));
1153 assert_cc(sizeof(uint32_t) == sizeof(id));
1154 if (!dbus_message_append_args(m,
1155 DBUS_TYPE_UINT32, &id,
1156 DBUS_TYPE_INVALID)) {
1157 log_error("Could not append arguments to message.");
1162 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
1163 log_error("Failed to issue method call: %s", bus_error_message(&error));
1168 if (!dbus_message_get_args(reply, &error,
1169 DBUS_TYPE_OBJECT_PATH, &path,
1170 DBUS_TYPE_INVALID)) {
1171 log_error("Failed to parse reply: %s", bus_error_message(&error));
1176 dbus_message_unref(m);
1177 if (!(m = dbus_message_new_method_call(
1178 "org.freedesktop.systemd1",
1180 "org.freedesktop.systemd1.Job",
1182 log_error("Could not allocate message.");
1187 dbus_message_unref(reply);
1188 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
1189 log_error("Failed to issue method call: %s", bus_error_message(&error));
1194 dbus_message_unref(m);
1195 dbus_message_unref(reply);
1203 dbus_message_unref(m);
1206 dbus_message_unref(reply);
1208 dbus_error_free(&error);
1213 static bool need_daemon_reload(DBusConnection *bus, const char *unit) {
1214 DBusMessage *m = NULL, *reply = NULL;
1215 dbus_bool_t b = FALSE;
1216 DBusMessageIter iter, sub;
1218 *interface = "org.freedesktop.systemd1.Unit",
1219 *property = "NeedDaemonReload",
1222 /* We ignore all errors here, since this is used to show a warning only */
1224 if (!(m = dbus_message_new_method_call(
1225 "org.freedesktop.systemd1",
1226 "/org/freedesktop/systemd1",
1227 "org.freedesktop.systemd1.Manager",
1231 if (!dbus_message_append_args(m,
1232 DBUS_TYPE_STRING, &unit,
1236 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, NULL)))
1239 if (!dbus_message_get_args(reply, NULL,
1240 DBUS_TYPE_OBJECT_PATH, &path,
1244 dbus_message_unref(m);
1245 if (!(m = dbus_message_new_method_call(
1246 "org.freedesktop.systemd1",
1248 "org.freedesktop.DBus.Properties",
1252 if (!dbus_message_append_args(m,
1253 DBUS_TYPE_STRING, &interface,
1254 DBUS_TYPE_STRING, &property,
1255 DBUS_TYPE_INVALID)) {
1259 dbus_message_unref(reply);
1260 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, NULL)))
1263 if (!dbus_message_iter_init(reply, &iter) ||
1264 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
1267 dbus_message_iter_recurse(&iter, &sub);
1269 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_BOOLEAN)
1272 dbus_message_iter_get_basic(&sub, &b);
1276 dbus_message_unref(m);
1279 dbus_message_unref(reply);
1284 typedef struct WaitData {
1289 static DBusHandlerResult wait_filter(DBusConnection *connection, DBusMessage *message, void *data) {
1297 dbus_error_init(&error);
1299 log_debug("Got D-Bus request: %s.%s() on %s",
1300 dbus_message_get_interface(message),
1301 dbus_message_get_member(message),
1302 dbus_message_get_path(message));
1304 if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
1305 log_error("Warning! D-Bus connection terminated.");
1306 dbus_connection_close(connection);
1308 } else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
1310 const char *path, *result;
1311 dbus_bool_t success = true;
1313 if (dbus_message_get_args(message, &error,
1314 DBUS_TYPE_UINT32, &id,
1315 DBUS_TYPE_OBJECT_PATH, &path,
1316 DBUS_TYPE_STRING, &result,
1317 DBUS_TYPE_INVALID)) {
1320 if ((p = set_remove(d->set, (char*) path)))
1324 d->result = strdup(result);
1329 dbus_error_free(&error);
1331 if (dbus_message_get_args(message, &error,
1332 DBUS_TYPE_UINT32, &id,
1333 DBUS_TYPE_OBJECT_PATH, &path,
1334 DBUS_TYPE_BOOLEAN, &success,
1335 DBUS_TYPE_INVALID)) {
1338 /* Compatibility with older systemd versions <
1339 * 19 during upgrades. This should be dropped
1342 if ((p = set_remove(d->set, (char*) path)))
1346 d->result = strdup("failed");
1352 log_error("Failed to parse message: %s", bus_error_message(&error));
1356 dbus_error_free(&error);
1357 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1360 static int enable_wait_for_jobs(DBusConnection *bus) {
1368 dbus_error_init(&error);
1369 dbus_bus_add_match(bus,
1371 "sender='org.freedesktop.systemd1',"
1372 "interface='org.freedesktop.systemd1.Manager',"
1373 "member='JobRemoved',"
1374 "path='/org/freedesktop/systemd1'",
1377 if (dbus_error_is_set(&error)) {
1378 log_error("Failed to add match: %s", bus_error_message(&error));
1379 dbus_error_free(&error);
1383 /* This is slightly dirty, since we don't undo the match registrations. */
1387 static int wait_for_jobs(DBusConnection *bus, Set *s) {
1397 if (!dbus_connection_add_filter(bus, wait_filter, &d, NULL)) {
1398 log_error("Failed to add filter.");
1403 while (!set_isempty(s) &&
1404 dbus_connection_read_write_dispatch(bus, -1))
1407 if (!arg_quiet && d.result) {
1408 if (streq(d.result, "timeout"))
1409 log_error("Job timed out.");
1410 else if (streq(d.result, "canceled"))
1411 log_error("Job canceled.");
1412 else if (streq(d.result, "dependency"))
1413 log_error("A dependency job failed. See system logs for details.");
1414 else if (!streq(d.result, "done") && !streq(d.result, "skipped"))
1415 log_error("Job failed. See system logs and 'systemctl status' for details.");
1418 if (streq_ptr(d.result, "timeout"))
1420 else if (streq_ptr(d.result, "canceled"))
1422 else if (!streq_ptr(d.result, "done") && !streq_ptr(d.result, "skipped"))
1430 /* This is slightly dirty, since we don't undo the filter registration. */
1435 static int start_unit_one(
1436 DBusConnection *bus,
1443 DBusMessage *m = NULL, *reply = NULL;
1452 assert(arg_no_block || s);
1454 if (!(m = dbus_message_new_method_call(
1455 "org.freedesktop.systemd1",
1456 "/org/freedesktop/systemd1",
1457 "org.freedesktop.systemd1.Manager",
1459 log_error("Could not allocate message.");
1464 if (!dbus_message_append_args(m,
1465 DBUS_TYPE_STRING, &name,
1466 DBUS_TYPE_STRING, &mode,
1467 DBUS_TYPE_INVALID)) {
1468 log_error("Could not append arguments to message.");
1473 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, error))) {
1475 if (arg_action != ACTION_SYSTEMCTL && error_is_no_service(error)) {
1476 /* There's always a fallback possible for
1477 * legacy actions. */
1482 log_error("Failed to issue method call: %s", bus_error_message(error));
1487 if (!dbus_message_get_args(reply, error,
1488 DBUS_TYPE_OBJECT_PATH, &path,
1489 DBUS_TYPE_INVALID)) {
1490 log_error("Failed to parse reply: %s", bus_error_message(error));
1495 if (need_daemon_reload(bus, name))
1496 log_warning("Warning: Unit file of created job changed on disk, 'systemctl %s daemon-reload' recommended.",
1497 arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
1499 if (!arg_no_block) {
1502 if (!(p = strdup(path))) {
1503 log_error("Failed to duplicate path.");
1508 if ((r = set_put(s, p)) < 0) {
1510 log_error("Failed to add path to set.");
1519 dbus_message_unref(m);
1522 dbus_message_unref(reply);
1527 static enum action verb_to_action(const char *verb) {
1528 if (streq(verb, "halt"))
1530 else if (streq(verb, "poweroff"))
1531 return ACTION_POWEROFF;
1532 else if (streq(verb, "reboot"))
1533 return ACTION_REBOOT;
1534 else if (streq(verb, "kexec"))
1535 return ACTION_KEXEC;
1536 else if (streq(verb, "rescue"))
1537 return ACTION_RESCUE;
1538 else if (streq(verb, "emergency"))
1539 return ACTION_EMERGENCY;
1540 else if (streq(verb, "default"))
1541 return ACTION_DEFAULT;
1542 else if (streq(verb, "exit"))
1545 return ACTION_INVALID;
1548 static int start_unit(DBusConnection *bus, char **args) {
1550 static const char * const table[_ACTION_MAX] = {
1551 [ACTION_HALT] = SPECIAL_HALT_TARGET,
1552 [ACTION_POWEROFF] = SPECIAL_POWEROFF_TARGET,
1553 [ACTION_REBOOT] = SPECIAL_REBOOT_TARGET,
1554 [ACTION_KEXEC] = SPECIAL_KEXEC_TARGET,
1555 [ACTION_RUNLEVEL2] = SPECIAL_RUNLEVEL2_TARGET,
1556 [ACTION_RUNLEVEL3] = SPECIAL_RUNLEVEL3_TARGET,
1557 [ACTION_RUNLEVEL4] = SPECIAL_RUNLEVEL4_TARGET,
1558 [ACTION_RUNLEVEL5] = SPECIAL_RUNLEVEL5_TARGET,
1559 [ACTION_RESCUE] = SPECIAL_RESCUE_TARGET,
1560 [ACTION_EMERGENCY] = SPECIAL_EMERGENCY_TARGET,
1561 [ACTION_DEFAULT] = SPECIAL_DEFAULT_TARGET,
1562 [ACTION_EXIT] = SPECIAL_EXIT_TARGET
1566 const char *method, *mode, *one_name;
1571 dbus_error_init(&error);
1575 agent_open_if_enabled();
1577 if (arg_action == ACTION_SYSTEMCTL) {
1579 streq(args[0], "stop") ||
1580 streq(args[0], "condstop") ? "StopUnit" :
1581 streq(args[0], "reload") ? "ReloadUnit" :
1582 streq(args[0], "restart") ? "RestartUnit" :
1584 streq(args[0], "try-restart") ||
1585 streq(args[0], "condrestart") ? "TryRestartUnit" :
1587 streq(args[0], "reload-or-restart") ? "ReloadOrRestartUnit" :
1589 streq(args[0], "reload-or-try-restart") ||
1590 streq(args[0], "condreload") ||
1592 streq(args[0], "force-reload") ? "ReloadOrTryRestartUnit" :
1596 (streq(args[0], "isolate") ||
1597 streq(args[0], "rescue") ||
1598 streq(args[0], "emergency")) ? "isolate" : arg_job_mode;
1600 one_name = table[verb_to_action(args[0])];
1603 assert(arg_action < ELEMENTSOF(table));
1604 assert(table[arg_action]);
1606 method = "StartUnit";
1608 mode = (arg_action == ACTION_EMERGENCY ||
1609 arg_action == ACTION_RESCUE ||
1610 arg_action == ACTION_RUNLEVEL2 ||
1611 arg_action == ACTION_RUNLEVEL3 ||
1612 arg_action == ACTION_RUNLEVEL4 ||
1613 arg_action == ACTION_RUNLEVEL5) ? "isolate" : "replace";
1615 one_name = table[arg_action];
1618 if (!arg_no_block) {
1619 if ((ret = enable_wait_for_jobs(bus)) < 0) {
1620 log_error("Could not watch jobs: %s", strerror(-ret));
1624 if (!(s = set_new(string_hash_func, string_compare_func))) {
1625 log_error("Failed to allocate set.");
1632 if ((ret = start_unit_one(bus, method, one_name, mode, &error, s)) <= 0)
1635 STRV_FOREACH(name, args+1)
1636 if ((r = start_unit_one(bus, method, *name, mode, &error, s)) != 0) {
1637 ret = translate_bus_error_to_exit_status(r, &error);
1638 dbus_error_free(&error);
1643 if ((r = wait_for_jobs(bus, s)) < 0) {
1652 dbus_error_free(&error);
1657 static int start_special(DBusConnection *bus, char **args) {
1664 (streq(args[0], "halt") ||
1665 streq(args[0], "poweroff") ||
1666 streq(args[0], "reboot") ||
1667 streq(args[0], "kexec") ||
1668 streq(args[0], "exit")))
1669 return daemon_reload(bus, args);
1671 r = start_unit(bus, args);
1674 warn_wall(verb_to_action(args[0]));
1679 static int check_unit(DBusConnection *bus, char **args) {
1680 DBusMessage *m = NULL, *reply = NULL;
1682 *interface = "org.freedesktop.systemd1.Unit",
1683 *property = "ActiveState";
1684 int r = 3; /* According to LSB: "program is not running" */
1691 dbus_error_init(&error);
1693 STRV_FOREACH(name, args+1) {
1694 const char *path = NULL;
1696 DBusMessageIter iter, sub;
1698 if (!(m = dbus_message_new_method_call(
1699 "org.freedesktop.systemd1",
1700 "/org/freedesktop/systemd1",
1701 "org.freedesktop.systemd1.Manager",
1703 log_error("Could not allocate message.");
1708 if (!dbus_message_append_args(m,
1709 DBUS_TYPE_STRING, name,
1710 DBUS_TYPE_INVALID)) {
1711 log_error("Could not append arguments to message.");
1716 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
1718 /* Hmm, cannot figure out anything about this unit... */
1722 dbus_error_free(&error);
1723 dbus_message_unref(m);
1728 if (!dbus_message_get_args(reply, &error,
1729 DBUS_TYPE_OBJECT_PATH, &path,
1730 DBUS_TYPE_INVALID)) {
1731 log_error("Failed to parse reply: %s", bus_error_message(&error));
1736 dbus_message_unref(m);
1737 if (!(m = dbus_message_new_method_call(
1738 "org.freedesktop.systemd1",
1740 "org.freedesktop.DBus.Properties",
1742 log_error("Could not allocate message.");
1747 if (!dbus_message_append_args(m,
1748 DBUS_TYPE_STRING, &interface,
1749 DBUS_TYPE_STRING, &property,
1750 DBUS_TYPE_INVALID)) {
1751 log_error("Could not append arguments to message.");
1756 dbus_message_unref(reply);
1757 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
1758 log_error("Failed to issue method call: %s", bus_error_message(&error));
1763 if (!dbus_message_iter_init(reply, &iter) ||
1764 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1765 log_error("Failed to parse reply.");
1770 dbus_message_iter_recurse(&iter, &sub);
1772 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1773 log_error("Failed to parse reply.");
1778 dbus_message_iter_get_basic(&sub, &state);
1783 if (streq(state, "active") || streq(state, "reloading"))
1786 dbus_message_unref(m);
1787 dbus_message_unref(reply);
1793 dbus_message_unref(m);
1796 dbus_message_unref(reply);
1798 dbus_error_free(&error);
1803 static int kill_unit(DBusConnection *bus, char **args) {
1804 DBusMessage *m = NULL;
1812 dbus_error_init(&error);
1815 arg_kill_who = "all";
1818 arg_kill_mode = streq(arg_kill_who, "all") ? "control-group" : "process";
1820 STRV_FOREACH(name, args+1) {
1823 if (!(m = dbus_message_new_method_call(
1824 "org.freedesktop.systemd1",
1825 "/org/freedesktop/systemd1",
1826 "org.freedesktop.systemd1.Manager",
1828 log_error("Could not allocate message.");
1833 if (!dbus_message_append_args(m,
1834 DBUS_TYPE_STRING, name,
1835 DBUS_TYPE_STRING, &arg_kill_who,
1836 DBUS_TYPE_STRING, &arg_kill_mode,
1837 DBUS_TYPE_INT32, &arg_signal,
1838 DBUS_TYPE_INVALID)) {
1839 log_error("Could not append arguments to message.");
1844 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
1845 log_error("Failed to issue method call: %s", bus_error_message(&error));
1846 dbus_error_free(&error);
1850 dbus_message_unref(m);
1853 dbus_message_unref(reply);
1859 dbus_message_unref(m);
1861 dbus_error_free(&error);
1866 typedef struct ExecStatusInfo {
1874 usec_t start_timestamp;
1875 usec_t exit_timestamp;
1880 LIST_FIELDS(struct ExecStatusInfo, exec);
1883 static void exec_status_info_free(ExecStatusInfo *i) {
1892 static int exec_status_info_deserialize(DBusMessageIter *sub, ExecStatusInfo *i) {
1893 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
1894 DBusMessageIter sub2, sub3;
1898 int32_t code, status;
1904 if (dbus_message_iter_get_arg_type(sub) != DBUS_TYPE_STRUCT)
1907 dbus_message_iter_recurse(sub, &sub2);
1909 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0)
1912 if (!(i->path = strdup(path)))
1915 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_ARRAY ||
1916 dbus_message_iter_get_element_type(&sub2) != DBUS_TYPE_STRING)
1920 dbus_message_iter_recurse(&sub2, &sub3);
1921 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
1922 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
1923 dbus_message_iter_next(&sub3);
1928 if (!(i->argv = new0(char*, n+1)))
1932 dbus_message_iter_recurse(&sub2, &sub3);
1933 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
1936 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
1937 dbus_message_iter_get_basic(&sub3, &s);
1938 dbus_message_iter_next(&sub3);
1940 if (!(i->argv[n++] = strdup(s)))
1944 if (!dbus_message_iter_next(&sub2) ||
1945 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, true) < 0 ||
1946 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp, true) < 0 ||
1947 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp_monotonic, true) < 0 ||
1948 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp, true) < 0 ||
1949 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp_monotonic, true) < 0 ||
1950 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, true) < 0 ||
1951 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &code, true) < 0 ||
1952 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &status, false) < 0)
1956 i->start_timestamp = (usec_t) start_timestamp;
1957 i->exit_timestamp = (usec_t) exit_timestamp;
1958 i->pid = (pid_t) pid;
1965 typedef struct UnitStatusInfo {
1967 const char *load_state;
1968 const char *active_state;
1969 const char *sub_state;
1970 const char *unit_file_state;
1972 const char *description;
1973 const char *following;
1976 const char *default_control_group;
1978 const char *load_error;
1980 usec_t inactive_exit_timestamp;
1981 usec_t active_enter_timestamp;
1982 usec_t active_exit_timestamp;
1983 usec_t inactive_enter_timestamp;
1985 bool need_daemon_reload;
1990 const char *status_text;
1992 #ifdef HAVE_SYSV_COMPAT
1996 usec_t start_timestamp;
1997 usec_t exit_timestamp;
1999 int exit_code, exit_status;
2001 usec_t condition_timestamp;
2002 bool condition_result;
2005 unsigned n_accepted;
2006 unsigned n_connections;
2010 const char *sysfs_path;
2012 /* Mount, Automount */
2018 LIST_HEAD(ExecStatusInfo, exec);
2021 static void print_status_info(UnitStatusInfo *i) {
2023 const char *on, *off, *ss;
2025 char since1[FORMAT_TIMESTAMP_PRETTY_MAX], *s1;
2026 char since2[FORMAT_TIMESTAMP_MAX], *s2;
2030 /* This shows pretty information about a unit. See
2031 * print_property() for a low-level property printer */
2033 printf("%s", strna(i->id));
2035 if (i->description && !streq_ptr(i->id, i->description))
2036 printf(" - %s", i->description);
2041 printf("\t Follow: unit currently follows state of %s\n", i->following);
2043 if (streq_ptr(i->load_state, "failed") ||
2044 streq_ptr(i->load_state, "banned")) {
2045 on = ansi_highlight(true);
2046 off = ansi_highlight(false);
2051 printf("\t Loaded: %s%s%s (Reason: %s)\n", on, strna(i->load_state), off, i->load_error);
2052 else if (i->path && i->unit_file_state)
2053 printf("\t Loaded: %s%s%s (%s; %s)\n", on, strna(i->load_state), off, i->path, i->unit_file_state);
2055 printf("\t Loaded: %s%s%s (%s)\n", on, strna(i->load_state), off, i->path);
2057 printf("\t Loaded: %s%s%s\n", on, strna(i->load_state), off);
2059 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
2061 if (streq_ptr(i->active_state, "failed")) {
2062 on = ansi_highlight(true);
2063 off = ansi_highlight(false);
2064 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
2065 on = ansi_highlight_green(true);
2066 off = ansi_highlight_green(false);
2071 printf("\t Active: %s%s (%s)%s",
2073 strna(i->active_state),
2077 printf("\t Active: %s%s%s",
2079 strna(i->active_state),
2082 timestamp = (streq_ptr(i->active_state, "active") ||
2083 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
2084 (streq_ptr(i->active_state, "inactive") ||
2085 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
2086 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
2087 i->active_exit_timestamp;
2089 s1 = format_timestamp_pretty(since1, sizeof(since1), timestamp);
2090 s2 = format_timestamp(since2, sizeof(since2), timestamp);
2093 printf(" since %s; %s\n", s2, s1);
2095 printf(" since %s\n", s2);
2099 if (!i->condition_result && i->condition_timestamp > 0) {
2100 s1 = format_timestamp_pretty(since1, sizeof(since1), i->condition_timestamp);
2101 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
2104 printf("\t start condition failed at %s; %s\n", s2, s1);
2106 printf("\t start condition failed at %s\n", s2);
2110 printf("\t Device: %s\n", i->sysfs_path);
2112 printf("\t Where: %s\n", i->where);
2114 printf("\t What: %s\n", i->what);
2117 printf("\tAccepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
2119 LIST_FOREACH(exec, p, i->exec) {
2123 /* Only show exited processes here */
2127 t = strv_join(p->argv, " ");
2128 printf("\t Process: %u %s=%s ", p->pid, p->name, strna(t));
2131 #ifdef HAVE_SYSV_COMPAT
2133 good = is_clean_exit_lsb(p->code, p->status);
2136 good = is_clean_exit(p->code, p->status);
2139 on = ansi_highlight(true);
2140 off = ansi_highlight(false);
2144 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
2146 if (p->code == CLD_EXITED) {
2149 printf("status=%i", p->status);
2151 #ifdef HAVE_SYSV_COMPAT
2152 if ((c = exit_status_to_string(p->status, i->is_sysv ? EXIT_STATUS_LSB : EXIT_STATUS_SYSTEMD)))
2154 if ((c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD)))
2159 printf("signal=%s", signal_to_string(p->status));
2161 printf(")%s\n", off);
2163 if (i->main_pid == p->pid &&
2164 i->start_timestamp == p->start_timestamp &&
2165 i->exit_timestamp == p->start_timestamp)
2166 /* Let's not show this twice */
2169 if (p->pid == i->control_pid)
2173 if (i->main_pid > 0 || i->control_pid > 0) {
2176 if (i->main_pid > 0) {
2177 printf("Main PID: %u", (unsigned) i->main_pid);
2181 get_process_name(i->main_pid, &t);
2186 } else if (i->exit_code > 0) {
2187 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
2189 if (i->exit_code == CLD_EXITED) {
2192 printf("status=%i", i->exit_status);
2194 #ifdef HAVE_SYSV_COMPAT
2195 if ((c = exit_status_to_string(i->exit_status, i->is_sysv ? EXIT_STATUS_LSB : EXIT_STATUS_SYSTEMD)))
2197 if ((c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD)))
2202 printf("signal=%s", signal_to_string(i->exit_status));
2207 if (i->main_pid > 0 && i->control_pid > 0)
2210 if (i->control_pid > 0) {
2213 printf(" Control: %u", (unsigned) i->control_pid);
2215 get_process_name(i->control_pid, &t);
2226 printf("\t Status: \"%s\"\n", i->status_text);
2228 if (i->default_control_group) {
2231 printf("\t CGroup: %s\n", i->default_control_group);
2233 if (arg_transport != TRANSPORT_SSH) {
2234 if ((c = columns()) > 18)
2239 show_cgroup_by_path(i->default_control_group, "\t\t ", c);
2243 if (i->need_daemon_reload)
2244 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %s daemon-reload' recommended.\n",
2245 ansi_highlight(true),
2246 ansi_highlight(false),
2247 arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
2250 static int status_property(const char *name, DBusMessageIter *iter, UnitStatusInfo *i) {
2256 switch (dbus_message_iter_get_arg_type(iter)) {
2258 case DBUS_TYPE_STRING: {
2261 dbus_message_iter_get_basic(iter, &s);
2264 if (streq(name, "Id"))
2266 else if (streq(name, "LoadState"))
2268 else if (streq(name, "ActiveState"))
2269 i->active_state = s;
2270 else if (streq(name, "SubState"))
2272 else if (streq(name, "Description"))
2274 else if (streq(name, "FragmentPath"))
2276 #ifdef HAVE_SYSV_COMPAT
2277 else if (streq(name, "SysVPath")) {
2282 else if (streq(name, "DefaultControlGroup"))
2283 i->default_control_group = s;
2284 else if (streq(name, "StatusText"))
2286 else if (streq(name, "SysFSPath"))
2288 else if (streq(name, "Where"))
2290 else if (streq(name, "What"))
2292 else if (streq(name, "Following"))
2294 else if (streq(name, "UnitFileState"))
2295 i->unit_file_state = s;
2301 case DBUS_TYPE_BOOLEAN: {
2304 dbus_message_iter_get_basic(iter, &b);
2306 if (streq(name, "Accept"))
2308 else if (streq(name, "NeedDaemonReload"))
2309 i->need_daemon_reload = b;
2310 else if (streq(name, "ConditionResult"))
2311 i->condition_result = b;
2316 case DBUS_TYPE_UINT32: {
2319 dbus_message_iter_get_basic(iter, &u);
2321 if (streq(name, "MainPID")) {
2323 i->main_pid = (pid_t) u;
2326 } else if (streq(name, "ControlPID"))
2327 i->control_pid = (pid_t) u;
2328 else if (streq(name, "ExecMainPID")) {
2330 i->main_pid = (pid_t) u;
2331 } else if (streq(name, "NAccepted"))
2333 else if (streq(name, "NConnections"))
2334 i->n_connections = u;
2339 case DBUS_TYPE_INT32: {
2342 dbus_message_iter_get_basic(iter, &j);
2344 if (streq(name, "ExecMainCode"))
2345 i->exit_code = (int) j;
2346 else if (streq(name, "ExecMainStatus"))
2347 i->exit_status = (int) j;
2352 case DBUS_TYPE_UINT64: {
2355 dbus_message_iter_get_basic(iter, &u);
2357 if (streq(name, "ExecMainStartTimestamp"))
2358 i->start_timestamp = (usec_t) u;
2359 else if (streq(name, "ExecMainExitTimestamp"))
2360 i->exit_timestamp = (usec_t) u;
2361 else if (streq(name, "ActiveEnterTimestamp"))
2362 i->active_enter_timestamp = (usec_t) u;
2363 else if (streq(name, "InactiveEnterTimestamp"))
2364 i->inactive_enter_timestamp = (usec_t) u;
2365 else if (streq(name, "InactiveExitTimestamp"))
2366 i->inactive_exit_timestamp = (usec_t) u;
2367 else if (streq(name, "ActiveExitTimestamp"))
2368 i->active_exit_timestamp = (usec_t) u;
2369 else if (streq(name, "ConditionTimestamp"))
2370 i->condition_timestamp = (usec_t) u;
2375 case DBUS_TYPE_ARRAY: {
2377 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
2378 startswith(name, "Exec")) {
2379 DBusMessageIter sub;
2381 dbus_message_iter_recurse(iter, &sub);
2382 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2383 ExecStatusInfo *info;
2386 if (!(info = new0(ExecStatusInfo, 1)))
2389 if (!(info->name = strdup(name))) {
2394 if ((r = exec_status_info_deserialize(&sub, info)) < 0) {
2399 LIST_PREPEND(ExecStatusInfo, exec, i->exec, info);
2401 dbus_message_iter_next(&sub);
2408 case DBUS_TYPE_STRUCT: {
2410 if (streq(name, "LoadError")) {
2411 DBusMessageIter sub;
2412 const char *n, *message;
2415 dbus_message_iter_recurse(iter, &sub);
2417 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &n, true);
2421 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &message, false);
2425 if (!isempty(message))
2426 i->load_error = message;
2436 static int print_property(const char *name, DBusMessageIter *iter) {
2440 /* This is a low-level property printer, see
2441 * print_status_info() for the nicer output */
2443 if (arg_property && !strv_find(arg_property, name))
2446 switch (dbus_message_iter_get_arg_type(iter)) {
2448 case DBUS_TYPE_STRUCT: {
2449 DBusMessageIter sub;
2450 dbus_message_iter_recurse(iter, &sub);
2452 if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32 && streq(name, "Job")) {
2455 dbus_message_iter_get_basic(&sub, &u);
2458 printf("%s=%u\n", name, (unsigned) u);
2460 printf("%s=\n", name);
2463 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "Unit")) {
2466 dbus_message_iter_get_basic(&sub, &s);
2468 if (arg_all || s[0])
2469 printf("%s=%s\n", name, s);
2472 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "LoadError")) {
2473 const char *a = NULL, *b = NULL;
2475 if (bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &a, true) >= 0)
2476 bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &b, false);
2478 if (arg_all || !isempty(a) || !isempty(b))
2479 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
2487 case DBUS_TYPE_ARRAY:
2489 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "EnvironmentFiles")) {
2490 DBusMessageIter sub, sub2;
2492 dbus_message_iter_recurse(iter, &sub);
2493 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2497 dbus_message_iter_recurse(&sub, &sub2);
2499 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
2500 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) >= 0)
2501 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
2503 dbus_message_iter_next(&sub);
2508 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Paths")) {
2509 DBusMessageIter sub, sub2;
2511 dbus_message_iter_recurse(iter, &sub);
2512 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2513 const char *type, *path;
2515 dbus_message_iter_recurse(&sub, &sub2);
2517 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
2518 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
2519 printf("%s=%s\n", type, path);
2521 dbus_message_iter_next(&sub);
2526 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Timers")) {
2527 DBusMessageIter sub, sub2;
2529 dbus_message_iter_recurse(iter, &sub);
2530 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2532 uint64_t value, next_elapse;
2534 dbus_message_iter_recurse(&sub, &sub2);
2536 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &base, true) >= 0 &&
2537 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &value, true) >= 0 &&
2538 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &next_elapse, false) >= 0) {
2539 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
2541 printf("%s={ value=%s ; next_elapse=%s }\n",
2543 format_timespan(timespan1, sizeof(timespan1), value),
2544 format_timespan(timespan2, sizeof(timespan2), next_elapse));
2547 dbus_message_iter_next(&sub);
2552 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "ControlGroupAttributes")) {
2553 DBusMessageIter sub, sub2;
2555 dbus_message_iter_recurse(iter, &sub);
2556 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2557 const char *controller, *attr, *value;
2559 dbus_message_iter_recurse(&sub, &sub2);
2561 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &controller, true) >= 0 &&
2562 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &attr, true) >= 0 &&
2563 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &value, false) >= 0) {
2565 printf("ControlGroupAttribute={ controller=%s ; attribute=%s ; value=\"%s\" }\n",
2571 dbus_message_iter_next(&sub);
2576 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && startswith(name, "Exec")) {
2577 DBusMessageIter sub;
2579 dbus_message_iter_recurse(iter, &sub);
2580 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2581 ExecStatusInfo info;
2584 if (exec_status_info_deserialize(&sub, &info) >= 0) {
2585 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
2588 t = strv_join(info.argv, " ");
2590 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
2594 yes_no(info.ignore),
2595 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
2596 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
2597 (unsigned) info. pid,
2598 sigchld_code_to_string(info.code),
2600 info.code == CLD_EXITED ? "" : "/",
2601 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
2607 strv_free(info.argv);
2609 dbus_message_iter_next(&sub);
2618 if (generic_print_property(name, iter, arg_all) > 0)
2622 printf("%s=[unprintable]\n", name);
2627 static int show_one(const char *verb, DBusConnection *bus, const char *path, bool show_properties, bool *new_line) {
2628 DBusMessage *m = NULL, *reply = NULL;
2629 const char *interface = "";
2632 DBusMessageIter iter, sub, sub2, sub3;
2633 UnitStatusInfo info;
2641 dbus_error_init(&error);
2643 if (!(m = dbus_message_new_method_call(
2644 "org.freedesktop.systemd1",
2646 "org.freedesktop.DBus.Properties",
2648 log_error("Could not allocate message.");
2653 if (!dbus_message_append_args(m,
2654 DBUS_TYPE_STRING, &interface,
2655 DBUS_TYPE_INVALID)) {
2656 log_error("Could not append arguments to message.");
2661 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
2662 log_error("Failed to issue method call: %s", bus_error_message(&error));
2667 if (!dbus_message_iter_init(reply, &iter) ||
2668 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
2669 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
2670 log_error("Failed to parse reply.");
2675 dbus_message_iter_recurse(&iter, &sub);
2682 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
2685 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_DICT_ENTRY) {
2686 log_error("Failed to parse reply.");
2691 dbus_message_iter_recurse(&sub, &sub2);
2693 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0) {
2694 log_error("Failed to parse reply.");
2699 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
2700 log_error("Failed to parse reply.");
2705 dbus_message_iter_recurse(&sub2, &sub3);
2707 if (show_properties)
2708 r = print_property(name, &sub3);
2710 r = status_property(name, &sub3, &info);
2713 log_error("Failed to parse reply.");
2718 dbus_message_iter_next(&sub);
2723 if (!show_properties)
2724 print_status_info(&info);
2726 if (!streq_ptr(info.active_state, "active") &&
2727 !streq_ptr(info.active_state, "reloading") &&
2728 streq(verb, "status"))
2729 /* According to LSB: "program not running" */
2732 while ((p = info.exec)) {
2733 LIST_REMOVE(ExecStatusInfo, exec, info.exec, p);
2734 exec_status_info_free(p);
2739 dbus_message_unref(m);
2742 dbus_message_unref(reply);
2744 dbus_error_free(&error);
2749 static int show(DBusConnection *bus, char **args) {
2750 DBusMessage *m = NULL, *reply = NULL;
2753 bool show_properties, new_line = false;
2759 dbus_error_init(&error);
2761 show_properties = !streq(args[0], "status");
2763 if (show_properties)
2764 pager_open_if_enabled();
2766 if (show_properties && strv_length(args) <= 1) {
2767 /* If not argument is specified inspect the manager
2770 ret = show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line);
2774 STRV_FOREACH(name, args+1) {
2775 const char *path = NULL;
2778 if (safe_atou32(*name, &id) < 0) {
2780 /* Interpret as unit name */
2782 if (!(m = dbus_message_new_method_call(
2783 "org.freedesktop.systemd1",
2784 "/org/freedesktop/systemd1",
2785 "org.freedesktop.systemd1.Manager",
2787 log_error("Could not allocate message.");
2792 if (!dbus_message_append_args(m,
2793 DBUS_TYPE_STRING, name,
2794 DBUS_TYPE_INVALID)) {
2795 log_error("Could not append arguments to message.");
2800 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
2802 if (!dbus_error_has_name(&error, DBUS_ERROR_ACCESS_DENIED)) {
2803 log_error("Failed to issue method call: %s", bus_error_message(&error));
2808 dbus_error_free(&error);
2810 dbus_message_unref(m);
2811 if (!(m = dbus_message_new_method_call(
2812 "org.freedesktop.systemd1",
2813 "/org/freedesktop/systemd1",
2814 "org.freedesktop.systemd1.Manager",
2816 log_error("Could not allocate message.");
2821 if (!dbus_message_append_args(m,
2822 DBUS_TYPE_STRING, name,
2823 DBUS_TYPE_INVALID)) {
2824 log_error("Could not append arguments to message.");
2829 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
2830 log_error("Failed to issue method call: %s", bus_error_message(&error));
2832 if (dbus_error_has_name(&error, BUS_ERROR_NO_SUCH_UNIT))
2833 ret = 4; /* According to LSB: "program or service status is unknown" */
2840 } else if (show_properties) {
2842 /* Interpret as job id */
2844 if (!(m = dbus_message_new_method_call(
2845 "org.freedesktop.systemd1",
2846 "/org/freedesktop/systemd1",
2847 "org.freedesktop.systemd1.Manager",
2849 log_error("Could not allocate message.");
2854 if (!dbus_message_append_args(m,
2855 DBUS_TYPE_UINT32, &id,
2856 DBUS_TYPE_INVALID)) {
2857 log_error("Could not append arguments to message.");
2862 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
2863 log_error("Failed to issue method call: %s", bus_error_message(&error));
2869 /* Interpret as PID */
2871 if (!(m = dbus_message_new_method_call(
2872 "org.freedesktop.systemd1",
2873 "/org/freedesktop/systemd1",
2874 "org.freedesktop.systemd1.Manager",
2876 log_error("Could not allocate message.");
2881 if (!dbus_message_append_args(m,
2882 DBUS_TYPE_UINT32, &id,
2883 DBUS_TYPE_INVALID)) {
2884 log_error("Could not append arguments to message.");
2889 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
2890 log_error("Failed to issue method call: %s", bus_error_message(&error));
2896 if (!dbus_message_get_args(reply, &error,
2897 DBUS_TYPE_OBJECT_PATH, &path,
2898 DBUS_TYPE_INVALID)) {
2899 log_error("Failed to parse reply: %s", bus_error_message(&error));
2904 if ((r = show_one(args[0], bus, path, show_properties, &new_line)) != 0)
2907 dbus_message_unref(m);
2908 dbus_message_unref(reply);
2914 dbus_message_unref(m);
2917 dbus_message_unref(reply);
2919 dbus_error_free(&error);
2924 static int dump(DBusConnection *bus, char **args) {
2925 DBusMessage *m = NULL, *reply = NULL;
2930 dbus_error_init(&error);
2932 pager_open_if_enabled();
2934 if (!(m = dbus_message_new_method_call(
2935 "org.freedesktop.systemd1",
2936 "/org/freedesktop/systemd1",
2937 "org.freedesktop.systemd1.Manager",
2939 log_error("Could not allocate message.");
2943 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
2944 log_error("Failed to issue method call: %s", bus_error_message(&error));
2949 if (!dbus_message_get_args(reply, &error,
2950 DBUS_TYPE_STRING, &text,
2951 DBUS_TYPE_INVALID)) {
2952 log_error("Failed to parse reply: %s", bus_error_message(&error));
2957 fputs(text, stdout);
2963 dbus_message_unref(m);
2966 dbus_message_unref(reply);
2968 dbus_error_free(&error);
2973 static int snapshot(DBusConnection *bus, char **args) {
2974 DBusMessage *m = NULL, *reply = NULL;
2977 const char *name = "", *path, *id;
2978 dbus_bool_t cleanup = FALSE;
2979 DBusMessageIter iter, sub;
2981 *interface = "org.freedesktop.systemd1.Unit",
2984 dbus_error_init(&error);
2986 if (!(m = dbus_message_new_method_call(
2987 "org.freedesktop.systemd1",
2988 "/org/freedesktop/systemd1",
2989 "org.freedesktop.systemd1.Manager",
2990 "CreateSnapshot"))) {
2991 log_error("Could not allocate message.");
2995 if (strv_length(args) > 1)
2998 if (!dbus_message_append_args(m,
2999 DBUS_TYPE_STRING, &name,
3000 DBUS_TYPE_BOOLEAN, &cleanup,
3001 DBUS_TYPE_INVALID)) {
3002 log_error("Could not append arguments to message.");
3007 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3008 log_error("Failed to issue method call: %s", bus_error_message(&error));
3013 if (!dbus_message_get_args(reply, &error,
3014 DBUS_TYPE_OBJECT_PATH, &path,
3015 DBUS_TYPE_INVALID)) {
3016 log_error("Failed to parse reply: %s", bus_error_message(&error));
3021 dbus_message_unref(m);
3022 if (!(m = dbus_message_new_method_call(
3023 "org.freedesktop.systemd1",
3025 "org.freedesktop.DBus.Properties",
3027 log_error("Could not allocate message.");
3031 if (!dbus_message_append_args(m,
3032 DBUS_TYPE_STRING, &interface,
3033 DBUS_TYPE_STRING, &property,
3034 DBUS_TYPE_INVALID)) {
3035 log_error("Could not append arguments to message.");
3040 dbus_message_unref(reply);
3041 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3042 log_error("Failed to issue method call: %s", bus_error_message(&error));
3047 if (!dbus_message_iter_init(reply, &iter) ||
3048 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3049 log_error("Failed to parse reply.");
3054 dbus_message_iter_recurse(&iter, &sub);
3056 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
3057 log_error("Failed to parse reply.");
3062 dbus_message_iter_get_basic(&sub, &id);
3070 dbus_message_unref(m);
3073 dbus_message_unref(reply);
3075 dbus_error_free(&error);
3080 static int delete_snapshot(DBusConnection *bus, char **args) {
3081 DBusMessage *m = NULL, *reply = NULL;
3089 dbus_error_init(&error);
3091 STRV_FOREACH(name, args+1) {
3092 const char *path = NULL;
3094 if (!(m = dbus_message_new_method_call(
3095 "org.freedesktop.systemd1",
3096 "/org/freedesktop/systemd1",
3097 "org.freedesktop.systemd1.Manager",
3099 log_error("Could not allocate message.");
3104 if (!dbus_message_append_args(m,
3105 DBUS_TYPE_STRING, name,
3106 DBUS_TYPE_INVALID)) {
3107 log_error("Could not append arguments to message.");
3112 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3113 log_error("Failed to issue method call: %s", bus_error_message(&error));
3118 if (!dbus_message_get_args(reply, &error,
3119 DBUS_TYPE_OBJECT_PATH, &path,
3120 DBUS_TYPE_INVALID)) {
3121 log_error("Failed to parse reply: %s", bus_error_message(&error));
3126 dbus_message_unref(m);
3127 if (!(m = dbus_message_new_method_call(
3128 "org.freedesktop.systemd1",
3130 "org.freedesktop.systemd1.Snapshot",
3132 log_error("Could not allocate message.");
3137 dbus_message_unref(reply);
3138 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3139 log_error("Failed to issue method call: %s", bus_error_message(&error));
3144 dbus_message_unref(m);
3145 dbus_message_unref(reply);
3153 dbus_message_unref(m);
3156 dbus_message_unref(reply);
3158 dbus_error_free(&error);
3163 static int daemon_reload(DBusConnection *bus, char **args) {
3164 DBusMessage *m = NULL, *reply = NULL;
3169 dbus_error_init(&error);
3171 if (arg_action == ACTION_RELOAD)
3173 else if (arg_action == ACTION_REEXEC)
3174 method = "Reexecute";
3176 assert(arg_action == ACTION_SYSTEMCTL);
3179 streq(args[0], "clear-jobs") ||
3180 streq(args[0], "cancel") ? "ClearJobs" :
3181 streq(args[0], "daemon-reexec") ? "Reexecute" :
3182 streq(args[0], "reset-failed") ? "ResetFailed" :
3183 streq(args[0], "halt") ? "Halt" :
3184 streq(args[0], "poweroff") ? "PowerOff" :
3185 streq(args[0], "reboot") ? "Reboot" :
3186 streq(args[0], "kexec") ? "KExec" :
3187 streq(args[0], "exit") ? "Exit" :
3188 /* "daemon-reload" */ "Reload";
3191 if (!(m = dbus_message_new_method_call(
3192 "org.freedesktop.systemd1",
3193 "/org/freedesktop/systemd1",
3194 "org.freedesktop.systemd1.Manager",
3196 log_error("Could not allocate message.");
3200 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3202 if (arg_action != ACTION_SYSTEMCTL && error_is_no_service(&error)) {
3203 /* There's always a fallback possible for
3204 * legacy actions. */
3209 if (streq(method, "Reexecute") && dbus_error_has_name(&error, DBUS_ERROR_NO_REPLY)) {
3210 /* On reexecution, we expect a disconnect, not
3216 log_error("Failed to issue method call: %s", bus_error_message(&error));
3225 dbus_message_unref(m);
3228 dbus_message_unref(reply);
3230 dbus_error_free(&error);
3235 static int reset_failed(DBusConnection *bus, char **args) {
3236 DBusMessage *m = NULL;
3242 dbus_error_init(&error);
3244 if (strv_length(args) <= 1)
3245 return daemon_reload(bus, args);
3247 STRV_FOREACH(name, args+1) {
3250 if (!(m = dbus_message_new_method_call(
3251 "org.freedesktop.systemd1",
3252 "/org/freedesktop/systemd1",
3253 "org.freedesktop.systemd1.Manager",
3254 "ResetFailedUnit"))) {
3255 log_error("Could not allocate message.");
3260 if (!dbus_message_append_args(m,
3261 DBUS_TYPE_STRING, name,
3262 DBUS_TYPE_INVALID)) {
3263 log_error("Could not append arguments to message.");
3268 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3269 log_error("Failed to issue method call: %s", bus_error_message(&error));
3274 dbus_message_unref(m);
3275 dbus_message_unref(reply);
3283 dbus_message_unref(m);
3285 dbus_error_free(&error);
3290 static int show_enviroment(DBusConnection *bus, char **args) {
3291 DBusMessage *m = NULL, *reply = NULL;
3293 DBusMessageIter iter, sub, sub2;
3296 *interface = "org.freedesktop.systemd1.Manager",
3297 *property = "Environment";
3299 dbus_error_init(&error);
3301 pager_open_if_enabled();
3303 if (!(m = dbus_message_new_method_call(
3304 "org.freedesktop.systemd1",
3305 "/org/freedesktop/systemd1",
3306 "org.freedesktop.DBus.Properties",
3308 log_error("Could not allocate message.");
3312 if (!dbus_message_append_args(m,
3313 DBUS_TYPE_STRING, &interface,
3314 DBUS_TYPE_STRING, &property,
3315 DBUS_TYPE_INVALID)) {
3316 log_error("Could not append arguments to message.");
3321 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3322 log_error("Failed to issue method call: %s", bus_error_message(&error));
3327 if (!dbus_message_iter_init(reply, &iter) ||
3328 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3329 log_error("Failed to parse reply.");
3334 dbus_message_iter_recurse(&iter, &sub);
3336 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_ARRAY ||
3337 dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_STRING) {
3338 log_error("Failed to parse reply.");
3343 dbus_message_iter_recurse(&sub, &sub2);
3345 while (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_INVALID) {
3348 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
3349 log_error("Failed to parse reply.");
3354 dbus_message_iter_get_basic(&sub2, &text);
3355 printf("%s\n", text);
3357 dbus_message_iter_next(&sub2);
3364 dbus_message_unref(m);
3367 dbus_message_unref(reply);
3369 dbus_error_free(&error);
3374 static int set_environment(DBusConnection *bus, char **args) {
3375 DBusMessage *m = NULL, *reply = NULL;
3379 DBusMessageIter iter, sub;
3382 dbus_error_init(&error);
3384 method = streq(args[0], "set-environment")
3386 : "UnsetEnvironment";
3388 if (!(m = dbus_message_new_method_call(
3389 "org.freedesktop.systemd1",
3390 "/org/freedesktop/systemd1",
3391 "org.freedesktop.systemd1.Manager",
3394 log_error("Could not allocate message.");
3398 dbus_message_iter_init_append(m, &iter);
3400 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub)) {
3401 log_error("Could not append arguments to message.");
3406 STRV_FOREACH(name, args+1)
3407 if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, name)) {
3408 log_error("Could not append arguments to message.");
3413 if (!dbus_message_iter_close_container(&iter, &sub)) {
3414 log_error("Could not append arguments to message.");
3419 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3420 log_error("Failed to issue method call: %s", bus_error_message(&error));
3429 dbus_message_unref(m);
3432 dbus_message_unref(reply);
3434 dbus_error_free(&error);
3439 static int enable_sysv_units(char **args) {
3442 #if defined (HAVE_SYSV_COMPAT) && (defined(TARGET_FEDORA) || defined(TARGET_MANDRIVA) || defined(TARGET_SUSE) || defined(TARGET_MEEGO) || defined(TARGET_ALTLINUX))
3443 const char *verb = args[0];
3444 unsigned f = 1, t = 1;
3447 if (arg_scope != UNIT_FILE_SYSTEM)
3450 if (!streq(verb, "enable") &&
3451 !streq(verb, "disable") &&
3452 !streq(verb, "is-enabled"))
3455 /* Processes all SysV units, and reshuffles the array so that
3456 * afterwards only the native units remain */
3459 r = lookup_paths_init(&paths, MANAGER_SYSTEM, false);
3465 for (f = 1; args[f]; f++) {
3468 bool found_native = false, found_sysv;
3470 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
3471 char **k, *l, *q = NULL;
3478 if (!endswith(name, ".service"))
3481 if (path_is_absolute(name))
3484 STRV_FOREACH(k, paths.unit_path) {
3487 if (!isempty(arg_root))
3488 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
3490 asprintf(&p, "%s/%s", *k, name);
3493 log_error("No memory");
3498 found_native = access(p, F_OK) >= 0;
3509 if (!isempty(arg_root))
3510 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
3512 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
3514 log_error("No memory");
3519 p[strlen(p) - sizeof(".service") + 1] = 0;
3520 found_sysv = access(p, F_OK) >= 0;
3527 /* Mark this entry, so that we don't try enabling it as native unit */
3528 args[f] = (char*) "";
3530 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
3532 if (!isempty(arg_root))
3533 argv[c++] = q = strappend("--root=", arg_root);
3535 argv[c++] = file_name_from_path(p);
3537 streq(verb, "enable") ? "on" :
3538 streq(verb, "disable") ? "off" : "--level=5";
3541 l = strv_join((char**)argv, " ");
3543 log_error("No memory.");
3550 log_info("Executing %s", l);
3555 log_error("Failed to fork: %m");
3560 } else if (pid == 0) {
3563 execv(argv[0], (char**) argv);
3564 _exit(EXIT_FAILURE);
3570 j = wait_for_terminate(pid, &status);
3572 log_error("Failed to wait for child: %s", strerror(-r));
3577 if (status.si_code == CLD_EXITED) {
3578 if (streq(verb, "is-enabled")) {
3579 if (status.si_status == 0) {
3588 } else if (status.si_status != 0) {
3599 lookup_paths_free(&paths);
3601 /* Drop all SysV units */
3602 for (f = 1, t = 1; args[f]; f++) {
3604 if (isempty(args[f]))
3607 args[t++] = args[f];
3616 static int enable_unit(DBusConnection *bus, char **args) {
3617 const char *verb = args[0];
3618 UnitFileChange *changes = NULL;
3619 unsigned n_changes = 0, i;
3620 int carries_install_info = -1;
3621 DBusMessage *m = NULL, *reply = NULL;
3625 dbus_error_init(&error);
3627 r = enable_sysv_units(args);
3631 if (!bus || avoid_bus()) {
3632 if (streq(verb, "enable")) {
3633 r = unit_file_enable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3634 carries_install_info = r;
3635 } else if (streq(verb, "disable"))
3636 r = unit_file_disable(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3637 else if (streq(verb, "reenable")) {
3638 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3639 carries_install_info = r;
3640 } else if (streq(verb, "link"))
3641 r = unit_file_link(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3642 else if (streq(verb, "preset")) {
3643 r = unit_file_preset(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3644 carries_install_info = r;
3645 } else if (streq(verb, "mask"))
3646 r = unit_file_mask(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3647 else if (streq(verb, "unmask"))
3648 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3650 assert_not_reached("Unknown verb");
3653 log_error("Operation failed: %s", strerror(-r));
3657 for (i = 0; i < n_changes; i++) {
3658 if (changes[i].type == UNIT_FILE_SYMLINK)
3659 log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
3661 log_info("rm '%s'", changes[i].path);
3666 bool send_force = true, expect_carries_install_info = false;
3668 DBusMessageIter iter, sub, sub2;
3670 if (streq(verb, "enable")) {
3671 method = "EnableUnitFiles";
3672 expect_carries_install_info = true;
3673 } else if (streq(verb, "disable")) {
3674 method = "DisableUnitFiles";
3676 } else if (streq(verb, "reenable")) {
3677 method = "ReenableUnitFiles";
3678 expect_carries_install_info = true;
3679 } else if (streq(verb, "link"))
3680 method = "LinkUnitFiles";
3681 else if (streq(verb, "preset")) {
3682 method = "PresetUnitFiles";
3683 expect_carries_install_info = true;
3684 } else if (streq(verb, "mask"))
3685 method = "MaskUnitFiles";
3686 else if (streq(verb, "unmask")) {
3687 method = "UnmaskUnitFiles";
3690 assert_not_reached("Unknown verb");
3692 m = dbus_message_new_method_call(
3693 "org.freedesktop.systemd1",
3694 "/org/freedesktop/systemd1",
3695 "org.freedesktop.systemd1.Manager",
3698 log_error("Out of memory");
3703 dbus_message_iter_init_append(m, &iter);
3705 r = bus_append_strv_iter(&iter, args+1);
3707 log_error("Failed to append unit files.");
3712 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &a)) {
3713 log_error("Failed to append runtime boolean.");
3721 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b)) {
3722 log_error("Failed to append force boolean.");
3728 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3730 log_error("Failed to issue method call: %s", bus_error_message(&error));
3735 if (!dbus_message_iter_init(reply, &iter)) {
3736 log_error("Failed to initialize iterator.");
3740 if (expect_carries_install_info) {
3741 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &b, true);
3743 log_error("Failed to parse reply.");
3747 carries_install_info = b;
3750 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3751 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
3752 log_error("Failed to parse reply.");
3757 dbus_message_iter_recurse(&iter, &sub);
3758 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
3759 const char *type, *path, *source;
3761 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
3762 log_error("Failed to parse reply.");
3767 dbus_message_iter_recurse(&sub, &sub2);
3769 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
3770 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
3771 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &source, false) < 0) {
3772 log_error("Failed to parse reply.");
3777 if (streq(type, "symlink"))
3778 log_info("ln -s '%s' '%s'", source, path);
3780 log_info("rm '%s'", path);
3782 dbus_message_iter_next(&sub);
3785 /* Try to reload if enabeld */
3787 r = daemon_reload(bus, args);
3790 if (carries_install_info == 0)
3791 log_warning("Warning: unit files do not carry install information. No operation executed.");
3795 dbus_message_unref(m);
3798 dbus_message_unref(reply);
3800 unit_file_changes_free(changes, n_changes);
3802 dbus_error_free(&error);
3806 static int unit_is_enabled(DBusConnection *bus, char **args) {
3809 DBusMessage *m = NULL, *reply = NULL;
3813 dbus_error_init(&error);
3815 r = enable_sysv_units(args);
3821 if (!bus || avoid_bus()) {
3823 STRV_FOREACH(name, args+1) {
3824 UnitFileState state;
3826 state = unit_file_get_state(arg_scope, arg_root, *name);
3832 if (state == UNIT_FILE_ENABLED ||
3833 state == UNIT_FILE_ENABLED_RUNTIME ||
3834 state == UNIT_FILE_STATIC)
3838 puts(unit_file_state_to_string(state));
3842 STRV_FOREACH(name, args+1) {
3845 m = dbus_message_new_method_call(
3846 "org.freedesktop.systemd1",
3847 "/org/freedesktop/systemd1",
3848 "org.freedesktop.systemd1.Manager",
3849 "GetUnitFileState");
3851 log_error("Out of memory");
3856 if (!dbus_message_append_args(m,
3857 DBUS_TYPE_STRING, name,
3858 DBUS_TYPE_INVALID)) {
3859 log_error("Could not append arguments to message.");
3864 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3866 log_error("Failed to issue method call: %s", bus_error_message(&error));
3871 if (!dbus_message_get_args(reply, &error,
3872 DBUS_TYPE_STRING, &s,
3873 DBUS_TYPE_INVALID)) {
3874 log_error("Failed to parse reply: %s", bus_error_message(&error));
3879 dbus_message_unref(m);
3880 dbus_message_unref(reply);
3883 if (streq(s, "enabled") ||
3884 streq(s, "enabled-runtime") ||
3893 r = enabled ? 0 : 1;
3897 dbus_message_unref(m);
3900 dbus_message_unref(reply);
3902 dbus_error_free(&error);
3906 static int systemctl_help(void) {
3908 pager_open_if_enabled();
3910 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
3911 "Query or send control commands to the systemd manager.\n\n"
3912 " -h --help Show this help\n"
3913 " --version Show package version\n"
3914 " -t --type=TYPE List only units of a particular type\n"
3915 " -p --property=NAME Show only properties by this name\n"
3916 " -a --all Show all units/properties, including dead/empty ones\n"
3917 " --failed Show only failed units\n"
3918 " --full Don't ellipsize unit names on output\n"
3919 " --fail When queueing a new job, fail if conflicting jobs are\n"
3921 " --ignore-dependencies\n"
3922 " When queueing a new job, ignore all its dependencies\n"
3923 " --kill-who=WHO Who to send signal to\n"
3924 " -s --signal=SIGNAL Which signal to send\n"
3925 " -H --host=[USER@]HOST\n"
3926 " Show information for remote host\n"
3927 " -P --privileged Acquire privileges before execution\n"
3928 " -q --quiet Suppress output\n"
3929 " --no-block Do not wait until operation finished\n"
3930 " --no-wall Don't send wall message before halt/power-off/reboot\n"
3931 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
3933 " --no-legend Do not print a legend (column headers and hints)\n"
3934 " --no-pager Do not pipe output into a pager\n"
3935 " --no-ask-password\n"
3936 " Do not ask for system passwords\n"
3937 " --order When generating graph for dot, show only order\n"
3938 " --require When generating graph for dot, show only requirement\n"
3939 " --system Connect to system manager\n"
3940 " --user Connect to user service manager\n"
3941 " --global Enable/disable unit files globally\n"
3942 " -f --force When enabling unit files, override existing symlinks\n"
3943 " When shutting down, execute action immediately\n"
3944 " --root=PATH Enable unit files in the specified root directory\n"
3945 " --runtime Enable unit files only temporarily until next reboot\n\n"
3947 " list-units List loaded units\n"
3948 " start [NAME...] Start (activate) one or more units\n"
3949 " stop [NAME...] Stop (deactivate) one or more units\n"
3950 " reload [NAME...] Reload one or more units\n"
3951 " restart [NAME...] Start or restart one or more units\n"
3952 " try-restart [NAME...] Restart one or more units if active\n"
3953 " reload-or-restart [NAME...] Reload one or more units is possible,\n"
3954 " otherwise start or restart\n"
3955 " reload-or-try-restart [NAME...] Reload one or more units is possible,\n"
3956 " otherwise restart if active\n"
3957 " isolate [NAME] Start one unit and stop all others\n"
3958 " kill [NAME...] Send signal to processes of a unit\n"
3959 " is-active [NAME...] Check whether units are active\n"
3960 " status [NAME...|PID...] Show runtime status of one or more units\n"
3961 " show [NAME...|JOB...] Show properties of one or more\n"
3962 " units/jobs or the manager\n"
3963 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
3965 " load [NAME...] Load one or more units\n\n"
3966 "Unit File Commands:\n"
3967 " list-unit-files List installed unit files\n"
3968 " enable [NAME...] Enable one or more unit files\n"
3969 " disable [NAME...] Disable one or more unit files\n"
3970 " reenable [NAME...] Reenable one or more unit files\n"
3971 " preset [NAME...] Enable/disable one or more unit files\n"
3972 " based on preset configuration\n"
3973 " mask [NAME...] Mask one or more units\n"
3974 " unmask [NAME...] Unmask one or more units\n"
3975 " link [PATH...] Link one or more units files into\n"
3976 " the search path\n"
3977 " is-enabled [NAME...] Check whether unit files are enabled\n\n"
3979 " list-jobs List jobs\n"
3980 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
3981 "Status Commands:\n"
3982 " dump Dump server status\n"
3983 " dot Dump dependency graph for dot(1)\n\n"
3984 "Snapshot Commands:\n"
3985 " snapshot [NAME] Create a snapshot\n"
3986 " delete [NAME...] Remove one or more snapshots\n\n"
3987 "Environment Commands:\n"
3988 " show-environment Dump environment\n"
3989 " set-environment [NAME=VALUE...] Set one or more environment variables\n"
3990 " unset-environment [NAME...] Unset one or more environment variables\n\n"
3991 "Manager Lifecycle Commands:\n"
3992 " daemon-reload Reload systemd manager configuration\n"
3993 " daemon-reexec Reexecute systemd manager\n\n"
3994 "System Commands:\n"
3995 " default Enter system default mode\n"
3996 " rescue Enter system rescue mode\n"
3997 " emergency Enter system emergency mode\n"
3998 " halt Shut down and halt the system\n"
3999 " poweroff Shut down and power-off the system\n"
4000 " reboot Shut down and reboot the system\n"
4001 " kexec Shut down and reboot the system with kexec\n"
4002 " exit Ask for user instance termination\n",
4003 program_invocation_short_name);
4008 static int halt_help(void) {
4010 printf("%s [OPTIONS...]\n\n"
4011 "%s the system.\n\n"
4012 " --help Show this help\n"
4013 " --halt Halt the machine\n"
4014 " -p --poweroff Switch off the machine\n"
4015 " --reboot Reboot the machine\n"
4016 " -f --force Force immediate halt/power-off/reboot\n"
4017 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
4018 " -d --no-wtmp Don't write wtmp record\n"
4019 " -n --no-sync Don't sync before halt/power-off/reboot\n"
4020 " --no-wall Don't send wall message before halt/power-off/reboot\n",
4021 program_invocation_short_name,
4022 arg_action == ACTION_REBOOT ? "Reboot" :
4023 arg_action == ACTION_POWEROFF ? "Power off" :
4029 static int shutdown_help(void) {
4031 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
4032 "Shut down the system.\n\n"
4033 " --help Show this help\n"
4034 " -H --halt Halt the machine\n"
4035 " -P --poweroff Power-off the machine\n"
4036 " -r --reboot Reboot the machine\n"
4037 " -h Equivalent to --poweroff, overriden by --halt\n"
4038 " -k Don't halt/power-off/reboot, just send warnings\n"
4039 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4040 " -c Cancel a pending shutdown\n",
4041 program_invocation_short_name);
4046 static int telinit_help(void) {
4048 printf("%s [OPTIONS...] {COMMAND}\n\n"
4049 "Send control commands to the init daemon.\n\n"
4050 " --help Show this help\n"
4051 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
4053 " 0 Power-off the machine\n"
4054 " 6 Reboot the machine\n"
4055 " 2, 3, 4, 5 Start runlevelX.target unit\n"
4056 " 1, s, S Enter rescue mode\n"
4057 " q, Q Reload init daemon configuration\n"
4058 " u, U Reexecute init daemon\n",
4059 program_invocation_short_name);
4064 static int runlevel_help(void) {
4066 printf("%s [OPTIONS...]\n\n"
4067 "Prints the previous and current runlevel of the init system.\n\n"
4068 " --help Show this help\n",
4069 program_invocation_short_name);
4074 static int systemctl_parse_argv(int argc, char *argv[]) {
4078 ARG_IGNORE_DEPENDENCIES,
4094 ARG_NO_ASK_PASSWORD,
4099 static const struct option options[] = {
4100 { "help", no_argument, NULL, 'h' },
4101 { "version", no_argument, NULL, ARG_VERSION },
4102 { "type", required_argument, NULL, 't' },
4103 { "property", required_argument, NULL, 'p' },
4104 { "all", no_argument, NULL, 'a' },
4105 { "failed", no_argument, NULL, ARG_FAILED },
4106 { "full", no_argument, NULL, ARG_FULL },
4107 { "fail", no_argument, NULL, ARG_FAIL },
4108 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
4109 { "user", no_argument, NULL, ARG_USER },
4110 { "system", no_argument, NULL, ARG_SYSTEM },
4111 { "global", no_argument, NULL, ARG_GLOBAL },
4112 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
4113 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
4114 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
4115 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4116 { "quiet", no_argument, NULL, 'q' },
4117 { "order", no_argument, NULL, ARG_ORDER },
4118 { "require", no_argument, NULL, ARG_REQUIRE },
4119 { "root", required_argument, NULL, ARG_ROOT },
4120 { "force", no_argument, NULL, 'f' },
4121 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
4122 { "kill-mode", required_argument, NULL, ARG_KILL_MODE }, /* undocumented on purpose */
4123 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
4124 { "signal", required_argument, NULL, 's' },
4125 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
4126 { "host", required_argument, NULL, 'H' },
4127 { "privileged",no_argument, NULL, 'P' },
4128 { "runtime", no_argument, NULL, ARG_RUNTIME },
4129 { NULL, 0, NULL, 0 }
4137 /* Only when running as systemctl we ask for passwords */
4138 arg_ask_password = true;
4140 while ((c = getopt_long(argc, argv, "ht:p:aqfs:H:P", options, NULL)) >= 0) {
4149 puts(PACKAGE_STRING);
4151 puts(SYSTEMD_FEATURES);
4161 if (!(l = strv_append(arg_property, optarg)))
4164 strv_free(arg_property);
4167 /* If the user asked for a particular
4168 * property, show it to him, even if it is
4179 arg_job_mode = "fail";
4182 case ARG_IGNORE_DEPENDENCIES:
4183 arg_job_mode = "ignore-dependencies";
4187 arg_scope = UNIT_FILE_USER;
4191 arg_scope = UNIT_FILE_SYSTEM;
4195 arg_scope = UNIT_FILE_GLOBAL;
4199 arg_no_block = true;
4203 arg_no_legend = true;
4207 arg_no_pager = true;
4215 arg_dot = DOT_ORDER;
4219 arg_dot = DOT_REQUIRE;
4243 arg_no_reload = true;
4247 arg_kill_who = optarg;
4251 arg_kill_mode = optarg;
4255 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
4256 log_error("Failed to parse signal string %s.", optarg);
4261 case ARG_NO_ASK_PASSWORD:
4262 arg_ask_password = false;
4266 arg_transport = TRANSPORT_POLKIT;
4270 arg_transport = TRANSPORT_SSH;
4282 log_error("Unknown option code %c", c);
4287 if (arg_transport != TRANSPORT_NORMAL && arg_scope != UNIT_FILE_SYSTEM) {
4288 log_error("Cannot access user instance remotely.");
4295 static int halt_parse_argv(int argc, char *argv[]) {
4304 static const struct option options[] = {
4305 { "help", no_argument, NULL, ARG_HELP },
4306 { "halt", no_argument, NULL, ARG_HALT },
4307 { "poweroff", no_argument, NULL, 'p' },
4308 { "reboot", no_argument, NULL, ARG_REBOOT },
4309 { "force", no_argument, NULL, 'f' },
4310 { "wtmp-only", no_argument, NULL, 'w' },
4311 { "no-wtmp", no_argument, NULL, 'd' },
4312 { "no-sync", no_argument, NULL, 'n' },
4313 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4314 { NULL, 0, NULL, 0 }
4322 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
4323 if (runlevel == '0' || runlevel == '6')
4324 arg_immediate = true;
4326 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
4334 arg_action = ACTION_HALT;
4338 if (arg_action != ACTION_REBOOT)
4339 arg_action = ACTION_POWEROFF;
4343 arg_action = ACTION_REBOOT;
4347 arg_immediate = true;
4368 /* Compatibility nops */
4375 log_error("Unknown option code %c", c);
4380 if (optind < argc) {
4381 log_error("Too many arguments.");
4388 static int parse_time_spec(const char *t, usec_t *_u) {
4392 if (streq(t, "now"))
4394 else if (!strchr(t, ':')) {
4397 if (safe_atou64(t, &u) < 0)
4400 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
4409 hour = strtol(t, &e, 10);
4410 if (errno != 0 || *e != ':' || hour < 0 || hour > 23)
4413 minute = strtol(e+1, &e, 10);
4414 if (errno != 0 || *e != 0 || minute < 0 || minute > 59)
4417 n = now(CLOCK_REALTIME);
4418 s = (time_t) (n / USEC_PER_SEC);
4421 assert_se(localtime_r(&s, &tm));
4423 tm.tm_hour = (int) hour;
4424 tm.tm_min = (int) minute;
4427 assert_se(s = mktime(&tm));
4429 *_u = (usec_t) s * USEC_PER_SEC;
4432 *_u += USEC_PER_DAY;
4438 static int shutdown_parse_argv(int argc, char *argv[]) {
4445 static const struct option options[] = {
4446 { "help", no_argument, NULL, ARG_HELP },
4447 { "halt", no_argument, NULL, 'H' },
4448 { "poweroff", no_argument, NULL, 'P' },
4449 { "reboot", no_argument, NULL, 'r' },
4450 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4451 { NULL, 0, NULL, 0 }
4459 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
4467 arg_action = ACTION_HALT;
4471 arg_action = ACTION_POWEROFF;
4476 arg_action = ACTION_KEXEC;
4478 arg_action = ACTION_REBOOT;
4482 if (arg_action != ACTION_HALT)
4483 arg_action = ACTION_POWEROFF;
4496 /* Compatibility nops */
4500 arg_action = ACTION_CANCEL_SHUTDOWN;
4507 log_error("Unknown option code %c", c);
4512 if (argc > optind) {
4513 if ((r = parse_time_spec(argv[optind], &arg_when)) < 0) {
4514 log_error("Failed to parse time specification: %s", argv[optind]);
4518 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
4520 /* We skip the time argument */
4521 if (argc > optind + 1)
4522 arg_wall = argv + optind + 1;
4529 static int telinit_parse_argv(int argc, char *argv[]) {
4536 static const struct option options[] = {
4537 { "help", no_argument, NULL, ARG_HELP },
4538 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4539 { NULL, 0, NULL, 0 }
4542 static const struct {
4546 { '0', ACTION_POWEROFF },
4547 { '6', ACTION_REBOOT },
4548 { '1', ACTION_RESCUE },
4549 { '2', ACTION_RUNLEVEL2 },
4550 { '3', ACTION_RUNLEVEL3 },
4551 { '4', ACTION_RUNLEVEL4 },
4552 { '5', ACTION_RUNLEVEL5 },
4553 { 's', ACTION_RESCUE },
4554 { 'S', ACTION_RESCUE },
4555 { 'q', ACTION_RELOAD },
4556 { 'Q', ACTION_RELOAD },
4557 { 'u', ACTION_REEXEC },
4558 { 'U', ACTION_REEXEC }
4567 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4582 log_error("Unknown option code %c", c);
4587 if (optind >= argc) {
4592 if (optind + 1 < argc) {
4593 log_error("Too many arguments.");
4597 if (strlen(argv[optind]) != 1) {
4598 log_error("Expected single character argument.");
4602 for (i = 0; i < ELEMENTSOF(table); i++)
4603 if (table[i].from == argv[optind][0])
4606 if (i >= ELEMENTSOF(table)) {
4607 log_error("Unknown command %s.", argv[optind]);
4611 arg_action = table[i].to;
4618 static int runlevel_parse_argv(int argc, char *argv[]) {
4624 static const struct option options[] = {
4625 { "help", no_argument, NULL, ARG_HELP },
4626 { NULL, 0, NULL, 0 }
4634 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4645 log_error("Unknown option code %c", c);
4650 if (optind < argc) {
4651 log_error("Too many arguments.");
4658 static int parse_argv(int argc, char *argv[]) {
4662 if (program_invocation_short_name) {
4664 if (strstr(program_invocation_short_name, "halt")) {
4665 arg_action = ACTION_HALT;
4666 return halt_parse_argv(argc, argv);
4667 } else if (strstr(program_invocation_short_name, "poweroff")) {
4668 arg_action = ACTION_POWEROFF;
4669 return halt_parse_argv(argc, argv);
4670 } else if (strstr(program_invocation_short_name, "reboot")) {
4672 arg_action = ACTION_KEXEC;
4674 arg_action = ACTION_REBOOT;
4675 return halt_parse_argv(argc, argv);
4676 } else if (strstr(program_invocation_short_name, "shutdown")) {
4677 arg_action = ACTION_POWEROFF;
4678 return shutdown_parse_argv(argc, argv);
4679 } else if (strstr(program_invocation_short_name, "init")) {
4681 if (sd_booted() > 0) {
4682 arg_action = ACTION_INVALID;
4683 return telinit_parse_argv(argc, argv);
4685 /* Hmm, so some other init system is
4686 * running, we need to forward this
4687 * request to it. For now we simply
4688 * guess that it is Upstart. */
4690 execv("/lib/upstart/telinit", argv);
4692 log_error("Couldn't find an alternative telinit implementation to spawn.");
4696 } else if (strstr(program_invocation_short_name, "runlevel")) {
4697 arg_action = ACTION_RUNLEVEL;
4698 return runlevel_parse_argv(argc, argv);
4702 arg_action = ACTION_SYSTEMCTL;
4703 return systemctl_parse_argv(argc, argv);
4706 static int action_to_runlevel(void) {
4708 static const char table[_ACTION_MAX] = {
4709 [ACTION_HALT] = '0',
4710 [ACTION_POWEROFF] = '0',
4711 [ACTION_REBOOT] = '6',
4712 [ACTION_RUNLEVEL2] = '2',
4713 [ACTION_RUNLEVEL3] = '3',
4714 [ACTION_RUNLEVEL4] = '4',
4715 [ACTION_RUNLEVEL5] = '5',
4716 [ACTION_RESCUE] = '1'
4719 assert(arg_action < _ACTION_MAX);
4721 return table[arg_action];
4724 static int talk_upstart(void) {
4725 DBusMessage *m = NULL, *reply = NULL;
4727 int previous, rl, r;
4729 env1_buf[] = "RUNLEVEL=X",
4730 env2_buf[] = "PREVLEVEL=X";
4731 char *env1 = env1_buf, *env2 = env2_buf;
4732 const char *emit = "runlevel";
4733 dbus_bool_t b_false = FALSE;
4734 DBusMessageIter iter, sub;
4735 DBusConnection *bus;
4737 dbus_error_init(&error);
4739 if (!(rl = action_to_runlevel()))
4742 if (utmp_get_runlevel(&previous, NULL) < 0)
4745 if (!(bus = dbus_connection_open_private("unix:abstract=/com/ubuntu/upstart", &error))) {
4746 if (dbus_error_has_name(&error, DBUS_ERROR_NO_SERVER)) {
4751 log_error("Failed to connect to Upstart bus: %s", bus_error_message(&error));
4756 if ((r = bus_check_peercred(bus)) < 0) {
4757 log_error("Failed to verify owner of bus.");
4761 if (!(m = dbus_message_new_method_call(
4762 "com.ubuntu.Upstart",
4763 "/com/ubuntu/Upstart",
4764 "com.ubuntu.Upstart0_6",
4767 log_error("Could not allocate message.");
4772 dbus_message_iter_init_append(m, &iter);
4774 env1_buf[sizeof(env1_buf)-2] = rl;
4775 env2_buf[sizeof(env2_buf)-2] = previous;
4777 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &emit) ||
4778 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub) ||
4779 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env1) ||
4780 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env2) ||
4781 !dbus_message_iter_close_container(&iter, &sub) ||
4782 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b_false)) {
4783 log_error("Could not append arguments to message.");
4788 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
4790 if (error_is_no_service(&error)) {
4795 log_error("Failed to issue method call: %s", bus_error_message(&error));
4804 dbus_message_unref(m);
4807 dbus_message_unref(reply);
4810 dbus_connection_flush(bus);
4811 dbus_connection_close(bus);
4812 dbus_connection_unref(bus);
4815 dbus_error_free(&error);
4820 static int talk_initctl(void) {
4821 struct init_request request;
4825 if (!(rl = action_to_runlevel()))
4829 request.magic = INIT_MAGIC;
4830 request.sleeptime = 0;
4831 request.cmd = INIT_CMD_RUNLVL;
4832 request.runlevel = rl;
4834 if ((fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY)) < 0) {
4836 if (errno == ENOENT)
4839 log_error("Failed to open "INIT_FIFO": %m");
4844 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
4845 close_nointr_nofail(fd);
4848 log_error("Failed to write to "INIT_FIFO": %m");
4849 return errno ? -errno : -EIO;
4855 static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
4857 static const struct {
4865 int (* const dispatch)(DBusConnection *bus, char **args);
4867 { "list-units", LESS, 1, list_units },
4868 { "list-unit-files", EQUAL, 1, list_unit_files },
4869 { "list-jobs", EQUAL, 1, list_jobs },
4870 { "clear-jobs", EQUAL, 1, daemon_reload },
4871 { "load", MORE, 2, load_unit },
4872 { "cancel", MORE, 2, cancel_job },
4873 { "start", MORE, 2, start_unit },
4874 { "stop", MORE, 2, start_unit },
4875 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
4876 { "reload", MORE, 2, start_unit },
4877 { "restart", MORE, 2, start_unit },
4878 { "try-restart", MORE, 2, start_unit },
4879 { "reload-or-restart", MORE, 2, start_unit },
4880 { "reload-or-try-restart", MORE, 2, start_unit },
4881 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
4882 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
4883 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
4884 { "isolate", EQUAL, 2, start_unit },
4885 { "kill", MORE, 2, kill_unit },
4886 { "is-active", MORE, 2, check_unit },
4887 { "check", MORE, 2, check_unit },
4888 { "show", MORE, 1, show },
4889 { "status", MORE, 2, show },
4890 { "dump", EQUAL, 1, dump },
4891 { "dot", EQUAL, 1, dot },
4892 { "snapshot", LESS, 2, snapshot },
4893 { "delete", MORE, 2, delete_snapshot },
4894 { "daemon-reload", EQUAL, 1, daemon_reload },
4895 { "daemon-reexec", EQUAL, 1, daemon_reload },
4896 { "show-environment", EQUAL, 1, show_enviroment },
4897 { "set-environment", MORE, 2, set_environment },
4898 { "unset-environment", MORE, 2, set_environment },
4899 { "halt", EQUAL, 1, start_special },
4900 { "poweroff", EQUAL, 1, start_special },
4901 { "reboot", EQUAL, 1, start_special },
4902 { "kexec", EQUAL, 1, start_special },
4903 { "default", EQUAL, 1, start_special },
4904 { "rescue", EQUAL, 1, start_special },
4905 { "emergency", EQUAL, 1, start_special },
4906 { "exit", EQUAL, 1, start_special },
4907 { "reset-failed", MORE, 1, reset_failed },
4908 { "enable", MORE, 2, enable_unit },
4909 { "disable", MORE, 2, enable_unit },
4910 { "is-enabled", MORE, 2, unit_is_enabled },
4911 { "reenable", MORE, 2, enable_unit },
4912 { "preset", MORE, 2, enable_unit },
4913 { "mask", MORE, 2, enable_unit },
4914 { "unmask", MORE, 2, enable_unit },
4915 { "link", MORE, 2, enable_unit }
4925 left = argc - optind;
4928 /* Special rule: no arguments means "list-units" */
4931 if (streq(argv[optind], "help")) {
4936 for (i = 0; i < ELEMENTSOF(verbs); i++)
4937 if (streq(argv[optind], verbs[i].verb))
4940 if (i >= ELEMENTSOF(verbs)) {
4941 log_error("Unknown operation %s", argv[optind]);
4946 switch (verbs[i].argc_cmp) {
4949 if (left != verbs[i].argc) {
4950 log_error("Invalid number of arguments.");
4957 if (left < verbs[i].argc) {
4958 log_error("Too few arguments.");
4965 if (left > verbs[i].argc) {
4966 log_error("Too many arguments.");
4973 assert_not_reached("Unknown comparison operator.");
4976 /* Require a bus connection for all operations but
4978 if (!streq(verbs[i].verb, "enable") &&
4979 !streq(verbs[i].verb, "disable") &&
4980 !streq(verbs[i].verb, "is-enable") &&
4981 !streq(verbs[i].verb, "reenable") &&
4982 !streq(verbs[i].verb, "preset") &&
4983 !streq(verbs[i].verb, "mask") &&
4984 !streq(verbs[i].verb, "unmask") &&
4985 !streq(verbs[i].verb, "link")) {
4987 if (running_in_chroot() > 0) {
4988 log_info("Running in chroot, ignoring request.");
4993 log_error("Failed to get D-Bus connection: %s",
4994 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5000 if (!bus && !avoid_bus()) {
5001 log_error("Failed to get D-Bus connection: %s",
5002 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5007 return verbs[i].dispatch(bus, argv + optind);
5010 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
5012 struct msghdr msghdr;
5014 union sockaddr_union sockaddr;
5015 struct shutdownd_command c;
5020 c.dry_run = dry_run;
5024 strncpy(c.wall_message, message, sizeof(c.wall_message));
5026 if ((fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0)) < 0)
5030 sockaddr.sa.sa_family = AF_UNIX;
5031 sockaddr.un.sun_path[0] = 0;
5032 strncpy(sockaddr.un.sun_path, "/run/systemd/shutdownd", sizeof(sockaddr.un.sun_path));
5035 iovec.iov_base = (char*) &c;
5036 iovec.iov_len = sizeof(c);
5039 msghdr.msg_name = &sockaddr;
5040 msghdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + sizeof("/run/systemd/shutdownd") - 1;
5042 msghdr.msg_iov = &iovec;
5043 msghdr.msg_iovlen = 1;
5045 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0) {
5046 close_nointr_nofail(fd);
5050 close_nointr_nofail(fd);
5054 static int reload_with_fallback(DBusConnection *bus) {
5057 /* First, try systemd via D-Bus. */
5058 if (daemon_reload(bus, NULL) >= 0)
5062 /* Nothing else worked, so let's try signals */
5063 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
5065 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
5066 log_error("kill() failed: %m");
5073 static int start_with_fallback(DBusConnection *bus) {
5076 /* First, try systemd via D-Bus. */
5077 if (start_unit(bus, NULL) >= 0)
5081 /* Hmm, talking to systemd via D-Bus didn't work. Then
5082 * let's try to talk to Upstart via D-Bus. */
5083 if (talk_upstart() > 0)
5086 /* Nothing else worked, so let's try
5088 if (talk_initctl() > 0)
5091 log_error("Failed to talk to init daemon.");
5095 warn_wall(arg_action);
5099 static int halt_main(DBusConnection *bus) {
5102 if (geteuid() != 0) {
5103 log_error("Must be root.");
5109 char date[FORMAT_TIMESTAMP_MAX];
5111 m = strv_join(arg_wall, " ");
5112 r = send_shutdownd(arg_when,
5113 arg_action == ACTION_HALT ? 'H' :
5114 arg_action == ACTION_POWEROFF ? 'P' :
5122 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
5124 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
5125 format_timestamp(date, sizeof(date), arg_when));
5130 if (!arg_dry && !arg_immediate)
5131 return start_with_fallback(bus);
5134 if (sd_booted() > 0)
5135 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
5136 else if ((r = utmp_put_shutdown(0)) < 0)
5137 log_warning("Failed to write utmp record: %s", strerror(-r));
5146 /* Make sure C-A-D is handled by the kernel from this
5148 reboot(RB_ENABLE_CAD);
5150 switch (arg_action) {
5153 log_info("Halting.");
5154 reboot(RB_HALT_SYSTEM);
5157 case ACTION_POWEROFF:
5158 log_info("Powering off.");
5159 reboot(RB_POWER_OFF);
5163 log_info("Rebooting.");
5164 reboot(RB_AUTOBOOT);
5168 assert_not_reached("Unknown halt action.");
5171 /* We should never reach this. */
5175 static int runlevel_main(void) {
5176 int r, runlevel, previous;
5178 r = utmp_get_runlevel(&runlevel, &previous);
5185 previous <= 0 ? 'N' : previous,
5186 runlevel <= 0 ? 'N' : runlevel);
5191 int main(int argc, char*argv[]) {
5192 int r, retval = EXIT_FAILURE;
5193 DBusConnection *bus = NULL;
5196 dbus_error_init(&error);
5198 log_parse_environment();
5201 if ((r = parse_argv(argc, argv)) < 0)
5204 retval = EXIT_SUCCESS;
5208 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
5209 * let's shortcut this */
5210 if (arg_action == ACTION_RUNLEVEL) {
5211 r = runlevel_main();
5212 retval = r < 0 ? EXIT_FAILURE : r;
5216 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
5217 log_info("Running in chroot, ignoring request.");
5223 if (arg_transport == TRANSPORT_NORMAL)
5224 bus_connect(arg_scope == UNIT_FILE_SYSTEM ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &bus, &private_bus, &error);
5225 else if (arg_transport == TRANSPORT_POLKIT) {
5226 bus_connect_system_polkit(&bus, &error);
5227 private_bus = false;
5228 } else if (arg_transport == TRANSPORT_SSH) {
5229 bus_connect_system_ssh(NULL, arg_host, &bus, &error);
5230 private_bus = false;
5232 assert_not_reached("Uh, invalid transport...");
5235 switch (arg_action) {
5237 case ACTION_SYSTEMCTL:
5238 r = systemctl_main(bus, argc, argv, &error);
5242 case ACTION_POWEROFF:
5248 case ACTION_RUNLEVEL2:
5249 case ACTION_RUNLEVEL3:
5250 case ACTION_RUNLEVEL4:
5251 case ACTION_RUNLEVEL5:
5253 case ACTION_EMERGENCY:
5254 case ACTION_DEFAULT:
5255 r = start_with_fallback(bus);
5260 r = reload_with_fallback(bus);
5263 case ACTION_CANCEL_SHUTDOWN:
5264 r = send_shutdownd(0, 0, false, false, NULL);
5267 case ACTION_INVALID:
5268 case ACTION_RUNLEVEL:
5270 assert_not_reached("Unknown action");
5273 retval = r < 0 ? EXIT_FAILURE : r;
5277 dbus_connection_flush(bus);
5278 dbus_connection_close(bus);
5279 dbus_connection_unref(bus);
5282 dbus_error_free(&error);
5286 strv_free(arg_property);