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 Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
22 #include <sys/reboot.h>
28 #include <sys/ioctl.h>
32 #include <sys/socket.h>
35 #include <sys/prctl.h>
36 #include <dbus/dbus.h>
38 #include <systemd/sd-daemon.h>
39 #include <systemd/sd-shutdown.h>
45 #include "utmp-wtmp.h"
48 #include "path-util.h"
50 #include "dbus-common.h"
51 #include "cgroup-show.h"
52 #include "cgroup-util.h"
54 #include "path-lookup.h"
55 #include "conf-parser.h"
56 #include "exit-status.h"
57 #include "bus-errors.h"
59 #include "unit-name.h"
61 #include "spawn-ask-password-agent.h"
62 #include "spawn-polkit-agent.h"
64 #include "logs-show.h"
65 #include "path-util.h"
67 static const char *arg_type = NULL;
68 static char **arg_property = NULL;
69 static bool arg_all = false;
70 static const char *arg_job_mode = "replace";
71 static UnitFileScope arg_scope = UNIT_FILE_SYSTEM;
72 static bool arg_no_block = false;
73 static bool arg_no_legend = false;
74 static bool arg_no_pager = false;
75 static bool arg_no_wtmp = false;
76 static bool arg_no_sync = false;
77 static bool arg_no_wall = false;
78 static bool arg_no_reload = false;
79 static bool arg_dry = false;
80 static bool arg_quiet = false;
81 static bool arg_full = false;
82 static int arg_force = 0;
83 static bool arg_ask_password = true;
84 static bool arg_failed = false;
85 static bool arg_runtime = false;
86 static char **arg_wall = NULL;
87 static const char *arg_kill_who = NULL;
88 static const char *arg_kill_mode = NULL;
89 static int arg_signal = SIGTERM;
90 static const char *arg_root = NULL;
91 static usec_t arg_when = 0;
112 ACTION_CANCEL_SHUTDOWN,
114 } arg_action = ACTION_SYSTEMCTL;
120 static enum transport {
124 } arg_transport = TRANSPORT_NORMAL;
125 static const char *arg_host = NULL;
126 static bool arg_follow = false;
127 static unsigned arg_lines = 10;
128 static OutputMode arg_output = OUTPUT_SHORT;
130 static bool private_bus = false;
132 static int daemon_reload(DBusConnection *bus, char **args);
133 static void halt_now(enum action a);
135 static bool on_tty(void) {
138 /* Note that this is invoked relatively early, before we start
139 * the pager. That means the value we return reflects whether
140 * we originally were started on a tty, not if we currently
141 * are. But this is intended, since we want colour and so on
142 * when run in our own pager. */
144 if (_unlikely_(t < 0))
145 t = isatty(STDOUT_FILENO) > 0;
150 static void pager_open_if_enabled(void) {
152 /* Cache result before we open the pager */
161 static void ask_password_agent_open_if_enabled(void) {
163 /* Open the password agent as a child process if necessary */
165 if (!arg_ask_password)
168 if (arg_scope != UNIT_FILE_SYSTEM)
171 ask_password_agent_open();
175 static void polkit_agent_open_if_enabled(void) {
177 /* Open the polkit agent as a child process if necessary */
179 if (!arg_ask_password)
182 if (arg_scope != UNIT_FILE_SYSTEM)
189 static const char *ansi_highlight_red(bool b) {
194 return b ? ANSI_HIGHLIGHT_RED_ON : ANSI_HIGHLIGHT_OFF;
197 static const char *ansi_highlight_green(bool b) {
202 return b ? ANSI_HIGHLIGHT_GREEN_ON : ANSI_HIGHLIGHT_OFF;
205 static bool error_is_no_service(const DBusError *error) {
208 if (!dbus_error_is_set(error))
211 if (dbus_error_has_name(error, DBUS_ERROR_NAME_HAS_NO_OWNER))
214 if (dbus_error_has_name(error, DBUS_ERROR_SERVICE_UNKNOWN))
217 return startswith(error->name, "org.freedesktop.DBus.Error.Spawn.");
220 static int translate_bus_error_to_exit_status(int r, const DBusError *error) {
223 if (!dbus_error_is_set(error))
226 if (dbus_error_has_name(error, DBUS_ERROR_ACCESS_DENIED) ||
227 dbus_error_has_name(error, BUS_ERROR_ONLY_BY_DEPENDENCY) ||
228 dbus_error_has_name(error, BUS_ERROR_NO_ISOLATION) ||
229 dbus_error_has_name(error, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE))
230 return EXIT_NOPERMISSION;
232 if (dbus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT))
233 return EXIT_NOTINSTALLED;
235 if (dbus_error_has_name(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE) ||
236 dbus_error_has_name(error, BUS_ERROR_NOT_SUPPORTED))
237 return EXIT_NOTIMPLEMENTED;
239 if (dbus_error_has_name(error, BUS_ERROR_LOAD_FAILED))
240 return EXIT_NOTCONFIGURED;
248 static void warn_wall(enum action a) {
249 static const char *table[_ACTION_MAX] = {
250 [ACTION_HALT] = "The system is going down for system halt NOW!",
251 [ACTION_REBOOT] = "The system is going down for reboot NOW!",
252 [ACTION_POWEROFF] = "The system is going down for power-off NOW!",
253 [ACTION_KEXEC] = "The system is going down for kexec reboot NOW!",
254 [ACTION_RESCUE] = "The system is going down to rescue mode NOW!",
255 [ACTION_EMERGENCY] = "The system is going down to emergency mode NOW!"
264 p = strv_join(arg_wall, " ");
266 log_error("Failed to join strings.");
282 utmp_wall(table[a], NULL);
285 static bool avoid_bus(void) {
287 if (running_in_chroot() > 0)
290 if (sd_booted() <= 0)
293 if (!isempty(arg_root))
296 if (arg_scope == UNIT_FILE_GLOBAL)
304 const char *description;
305 const char *load_state;
306 const char *active_state;
307 const char *sub_state;
308 const char *following;
309 const char *unit_path;
311 const char *job_type;
312 const char *job_path;
315 static int compare_unit_info(const void *a, const void *b) {
317 const struct unit_info *u = a, *v = b;
319 d1 = strrchr(u->id, '.');
320 d2 = strrchr(v->id, '.');
325 if ((r = strcasecmp(d1, d2)) != 0)
329 return strcasecmp(u->id, v->id);
332 static bool output_show_unit(const struct unit_info *u) {
336 return streq(u->active_state, "failed");
338 return (!arg_type || ((dot = strrchr(u->id, '.')) &&
339 streq(dot+1, arg_type))) &&
340 (arg_all || !(streq(u->active_state, "inactive") || u->following[0]) || u->job_id > 0);
343 static void output_units_list(const struct unit_info *unit_infos, unsigned c) {
344 unsigned id_len, max_id_len, active_len, sub_len, job_len, desc_len, n_shown = 0;
345 const struct unit_info *u;
347 max_id_len = sizeof("UNIT")-1;
348 active_len = sizeof("ACTIVE")-1;
349 sub_len = sizeof("SUB")-1;
350 job_len = sizeof("JOB")-1;
353 for (u = unit_infos; u < unit_infos + c; u++) {
354 if (!output_show_unit(u))
357 max_id_len = MAX(max_id_len, strlen(u->id));
358 active_len = MAX(active_len, strlen(u->active_state));
359 sub_len = MAX(sub_len, strlen(u->sub_state));
361 job_len = MAX(job_len, strlen(u->job_type));
366 id_len = MIN(max_id_len, 25);
367 basic_len = 5 + id_len + 6 + active_len + sub_len + job_len;
368 if (basic_len < (unsigned) columns()) {
369 unsigned extra_len, incr;
370 extra_len = columns() - basic_len;
371 /* Either UNIT already got 25, or is fully satisfied.
372 * Grant up to 25 to DESC now. */
373 incr = MIN(extra_len, 25);
376 /* split the remaining space between UNIT and DESC,
377 * but do not give UNIT more than it needs. */
379 incr = MIN(extra_len / 2, max_id_len - id_len);
381 desc_len += extra_len - incr;
387 if (!arg_no_legend) {
388 printf("%-*s %-6s %-*s %-*s %-*s ", id_len, "UNIT", "LOAD",
389 active_len, "ACTIVE", sub_len, "SUB", job_len, "JOB");
390 if (!arg_full && arg_no_pager)
391 printf("%.*s\n", desc_len, "DESCRIPTION");
393 printf("%s\n", "DESCRIPTION");
396 for (u = unit_infos; u < unit_infos + c; u++) {
398 const char *on_loaded, *off_loaded;
399 const char *on_active, *off_active;
401 if (!output_show_unit(u))
406 if (streq(u->load_state, "error")) {
407 on_loaded = ansi_highlight_red(true);
408 off_loaded = ansi_highlight_red(false);
410 on_loaded = off_loaded = "";
412 if (streq(u->active_state, "failed")) {
413 on_active = ansi_highlight_red(true);
414 off_active = ansi_highlight_red(false);
416 on_active = off_active = "";
418 e = arg_full ? NULL : ellipsize(u->id, id_len, 33);
420 printf("%-*s %s%-6s%s %s%-*s %-*s%s %-*s ",
421 id_len, e ? e : u->id,
422 on_loaded, u->load_state, off_loaded,
423 on_active, active_len, u->active_state,
424 sub_len, u->sub_state, off_active,
425 job_len, u->job_id ? u->job_type : "");
426 if (!arg_full && arg_no_pager)
427 printf("%.*s\n", desc_len, u->description);
429 printf("%s\n", u->description);
434 if (!arg_no_legend) {
435 printf("\nLOAD = Reflects whether the unit definition was properly loaded.\n"
436 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
437 "SUB = The low-level unit activation state, values depend on unit type.\n"
438 "JOB = Pending job for the unit.\n");
441 printf("\n%u units listed.\n", n_shown);
443 printf("\n%u units listed. Pass --all to see inactive units, too.\n", n_shown);
447 static int list_units(DBusConnection *bus, char **args) {
448 DBusMessage *m = NULL, *reply = NULL;
451 DBusMessageIter iter, sub, sub2;
452 unsigned c = 0, n_units = 0;
453 struct unit_info *unit_infos = NULL;
455 dbus_error_init(&error);
459 pager_open_if_enabled();
461 if (!(m = dbus_message_new_method_call(
462 "org.freedesktop.systemd1",
463 "/org/freedesktop/systemd1",
464 "org.freedesktop.systemd1.Manager",
466 log_error("Could not allocate message.");
470 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
471 log_error("Failed to issue method call: %s", bus_error_message(&error));
476 if (!dbus_message_iter_init(reply, &iter) ||
477 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
478 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
479 log_error("Failed to parse reply.");
484 dbus_message_iter_recurse(&iter, &sub);
486 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
489 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
490 log_error("Failed to parse reply.");
498 n_units = MAX(2*c, 16);
499 w = realloc(unit_infos, sizeof(struct unit_info) * n_units);
502 log_error("Failed to allocate unit array.");
512 dbus_message_iter_recurse(&sub, &sub2);
514 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->id, true) < 0 ||
515 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->description, true) < 0 ||
516 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->load_state, true) < 0 ||
517 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->active_state, true) < 0 ||
518 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->sub_state, true) < 0 ||
519 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->following, true) < 0 ||
520 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &u->unit_path, true) < 0 ||
521 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &u->job_id, true) < 0 ||
522 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->job_type, true) < 0 ||
523 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &u->job_path, false) < 0) {
524 log_error("Failed to parse reply.");
529 dbus_message_iter_next(&sub);
534 qsort(unit_infos, c, sizeof(struct unit_info), compare_unit_info);
535 output_units_list(unit_infos, c);
542 dbus_message_unref(m);
545 dbus_message_unref(reply);
549 dbus_error_free(&error);
554 static int compare_unit_file_list(const void *a, const void *b) {
556 const UnitFileList *u = a, *v = b;
558 d1 = strrchr(u->path, '.');
559 d2 = strrchr(v->path, '.');
564 r = strcasecmp(d1, d2);
569 return strcasecmp(path_get_file_name(u->path), path_get_file_name(v->path));
572 static bool output_show_unit_file(const UnitFileList *u) {
575 return !arg_type || ((dot = strrchr(u->path, '.')) && streq(dot+1, arg_type));
578 static void output_unit_file_list(const UnitFileList *units, unsigned c) {
579 unsigned max_id_len, id_cols, state_cols, n_shown = 0;
580 const UnitFileList *u;
582 max_id_len = sizeof("UNIT FILE")-1;
583 state_cols = sizeof("STATE")-1;
584 for (u = units; u < units + c; u++) {
585 if (!output_show_unit_file(u))
588 max_id_len = MAX(max_id_len, strlen(path_get_file_name(u->path)));
589 state_cols = MAX(state_cols, strlen(unit_file_state_to_string(u->state)));
594 id_cols = MIN(max_id_len, 25);
595 basic_cols = 1 + id_cols + state_cols;
596 if (basic_cols < (unsigned) columns())
597 id_cols += MIN(columns() - basic_cols, max_id_len - id_cols);
599 id_cols = max_id_len;
602 printf("%-*s %-*s\n", id_cols, "UNIT FILE", state_cols, "STATE");
604 for (u = units; u < units + c; u++) {
606 const char *on, *off;
609 if (!output_show_unit_file(u))
614 if (u->state == UNIT_FILE_MASKED ||
615 u->state == UNIT_FILE_MASKED_RUNTIME ||
616 u->state == UNIT_FILE_DISABLED) {
617 on = ansi_highlight_red(true);
618 off = ansi_highlight_red(false);
619 } else if (u->state == UNIT_FILE_ENABLED) {
620 on = ansi_highlight_green(true);
621 off = ansi_highlight_green(false);
625 id = path_get_file_name(u->path);
627 e = arg_full ? NULL : ellipsize(id, id_cols, 33);
629 printf("%-*s %s%-*s%s\n",
631 on, state_cols, unit_file_state_to_string(u->state), off);
637 printf("\n%u unit files listed.\n", n_shown);
640 static int list_unit_files(DBusConnection *bus, char **args) {
641 DBusMessage *m = NULL, *reply = NULL;
644 DBusMessageIter iter, sub, sub2;
645 unsigned c = 0, n_units = 0;
646 UnitFileList *units = NULL;
648 dbus_error_init(&error);
650 pager_open_if_enabled();
657 h = hashmap_new(string_hash_func, string_compare_func);
659 log_error("Out of memory");
663 r = unit_file_get_list(arg_scope, arg_root, h);
665 unit_file_list_free(h);
666 log_error("Failed to get unit file list: %s", strerror(-r));
670 n_units = hashmap_size(h);
671 units = new(UnitFileList, n_units);
673 unit_file_list_free(h);
674 log_error("Out of memory");
678 HASHMAP_FOREACH(u, h, i) {
679 memcpy(units + c++, u, sizeof(UnitFileList));
687 m = dbus_message_new_method_call(
688 "org.freedesktop.systemd1",
689 "/org/freedesktop/systemd1",
690 "org.freedesktop.systemd1.Manager",
693 log_error("Could not allocate message.");
697 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
699 log_error("Failed to issue method call: %s", bus_error_message(&error));
704 if (!dbus_message_iter_init(reply, &iter) ||
705 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
706 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
707 log_error("Failed to parse reply.");
712 dbus_message_iter_recurse(&iter, &sub);
714 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
718 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
719 log_error("Failed to parse reply.");
727 n_units = MAX(2*c, 16);
728 w = realloc(units, sizeof(struct UnitFileList) * n_units);
731 log_error("Failed to allocate unit array.");
741 dbus_message_iter_recurse(&sub, &sub2);
743 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->path, true) < 0 ||
744 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, false) < 0) {
745 log_error("Failed to parse reply.");
750 u->state = unit_file_state_from_string(state);
752 dbus_message_iter_next(&sub);
758 qsort(units, c, sizeof(UnitFileList), compare_unit_file_list);
759 output_unit_file_list(units, c);
766 dbus_message_unref(m);
769 dbus_message_unref(reply);
773 dbus_error_free(&error);
778 static int dot_one_property(const char *name, const char *prop, DBusMessageIter *iter) {
779 static const char * const colors[] = {
780 "Requires", "[color=\"black\"]",
781 "RequiresOverridable", "[color=\"black\"]",
782 "Requisite", "[color=\"darkblue\"]",
783 "RequisiteOverridable", "[color=\"darkblue\"]",
784 "Wants", "[color=\"darkgrey\"]",
785 "Conflicts", "[color=\"red\"]",
786 "ConflictedBy", "[color=\"red\"]",
787 "After", "[color=\"green\"]"
790 const char *c = NULL;
797 for (i = 0; i < ELEMENTSOF(colors); i += 2)
798 if (streq(colors[i], prop)) {
806 if (arg_dot != DOT_ALL)
807 if ((arg_dot == DOT_ORDER) != streq(prop, "After"))
810 switch (dbus_message_iter_get_arg_type(iter)) {
812 case DBUS_TYPE_ARRAY:
814 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING) {
817 dbus_message_iter_recurse(iter, &sub);
819 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
822 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING);
823 dbus_message_iter_get_basic(&sub, &s);
824 printf("\t\"%s\"->\"%s\" %s;\n", name, s, c);
826 dbus_message_iter_next(&sub);
836 static int dot_one(DBusConnection *bus, const char *name, const char *path) {
837 DBusMessage *m = NULL, *reply = NULL;
838 const char *interface = "org.freedesktop.systemd1.Unit";
841 DBusMessageIter iter, sub, sub2, sub3;
846 dbus_error_init(&error);
848 if (!(m = dbus_message_new_method_call(
849 "org.freedesktop.systemd1",
851 "org.freedesktop.DBus.Properties",
853 log_error("Could not allocate message.");
858 if (!dbus_message_append_args(m,
859 DBUS_TYPE_STRING, &interface,
860 DBUS_TYPE_INVALID)) {
861 log_error("Could not append arguments to message.");
866 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
867 log_error("Failed to issue method call: %s", bus_error_message(&error));
872 if (!dbus_message_iter_init(reply, &iter) ||
873 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
874 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
875 log_error("Failed to parse reply.");
880 dbus_message_iter_recurse(&iter, &sub);
882 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
885 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_DICT_ENTRY) {
886 log_error("Failed to parse reply.");
891 dbus_message_iter_recurse(&sub, &sub2);
893 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &prop, true) < 0) {
894 log_error("Failed to parse reply.");
899 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
900 log_error("Failed to parse reply.");
905 dbus_message_iter_recurse(&sub2, &sub3);
907 if (dot_one_property(name, prop, &sub3)) {
908 log_error("Failed to parse reply.");
913 dbus_message_iter_next(&sub);
920 dbus_message_unref(m);
923 dbus_message_unref(reply);
925 dbus_error_free(&error);
930 static int dot(DBusConnection *bus, char **args) {
931 DBusMessage *m = NULL, *reply = NULL;
934 DBusMessageIter iter, sub, sub2;
936 dbus_error_init(&error);
940 if (!(m = dbus_message_new_method_call(
941 "org.freedesktop.systemd1",
942 "/org/freedesktop/systemd1",
943 "org.freedesktop.systemd1.Manager",
945 log_error("Could not allocate message.");
949 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
950 log_error("Failed to issue method call: %s", bus_error_message(&error));
955 if (!dbus_message_iter_init(reply, &iter) ||
956 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
957 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
958 log_error("Failed to parse reply.");
963 printf("digraph systemd {\n");
965 dbus_message_iter_recurse(&iter, &sub);
966 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
967 const char *id, *description, *load_state, *active_state, *sub_state, *following, *unit_path;
969 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
970 log_error("Failed to parse reply.");
975 dbus_message_iter_recurse(&sub, &sub2);
977 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &id, true) < 0 ||
978 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &description, true) < 0 ||
979 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &load_state, true) < 0 ||
980 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &active_state, true) < 0 ||
981 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &sub_state, true) < 0 ||
982 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &following, true) < 0 ||
983 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, true) < 0) {
984 log_error("Failed to parse reply.");
989 if ((r = dot_one(bus, id, unit_path)) < 0)
992 /* printf("\t\"%s\";\n", id); */
993 dbus_message_iter_next(&sub);
998 log_info(" Color legend: black = Requires\n"
999 " dark blue = Requisite\n"
1000 " dark grey = Wants\n"
1001 " red = Conflicts\n"
1002 " green = After\n");
1005 log_notice("-- You probably want to process this output with graphviz' dot tool.\n"
1006 "-- Try a shell pipeline like 'systemctl dot | dot -Tsvg > systemd.svg'!\n");
1012 dbus_message_unref(m);
1015 dbus_message_unref(reply);
1017 dbus_error_free(&error);
1022 static int list_jobs(DBusConnection *bus, char **args) {
1023 DBusMessage *m = NULL, *reply = NULL;
1026 DBusMessageIter iter, sub, sub2;
1029 dbus_error_init(&error);
1033 pager_open_if_enabled();
1035 if (!(m = dbus_message_new_method_call(
1036 "org.freedesktop.systemd1",
1037 "/org/freedesktop/systemd1",
1038 "org.freedesktop.systemd1.Manager",
1040 log_error("Could not allocate message.");
1044 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
1045 log_error("Failed to issue method call: %s", bus_error_message(&error));
1050 if (!dbus_message_iter_init(reply, &iter) ||
1051 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
1052 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
1053 log_error("Failed to parse reply.");
1058 dbus_message_iter_recurse(&iter, &sub);
1061 printf("%4s %-25s %-15s %-7s\n", "JOB", "UNIT", "TYPE", "STATE");
1063 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1064 const char *name, *type, *state, *job_path, *unit_path;
1068 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
1069 log_error("Failed to parse reply.");
1074 dbus_message_iter_recurse(&sub, &sub2);
1076 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &id, true) < 0 ||
1077 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
1078 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
1079 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, true) < 0 ||
1080 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &job_path, true) < 0 ||
1081 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, false) < 0) {
1082 log_error("Failed to parse reply.");
1087 e = arg_full ? NULL : ellipsize(name, 25, 33);
1088 printf("%4u %-25s %-15s %-7s\n", id, e ? e : name, type, state);
1093 dbus_message_iter_next(&sub);
1097 printf("\n%u jobs listed.\n", k);
1103 dbus_message_unref(m);
1106 dbus_message_unref(reply);
1108 dbus_error_free(&error);
1113 static int load_unit(DBusConnection *bus, char **args) {
1114 DBusMessage *m = NULL;
1119 dbus_error_init(&error);
1124 STRV_FOREACH(name, args+1) {
1127 if (!(m = dbus_message_new_method_call(
1128 "org.freedesktop.systemd1",
1129 "/org/freedesktop/systemd1",
1130 "org.freedesktop.systemd1.Manager",
1132 log_error("Could not allocate message.");
1137 if (!dbus_message_append_args(m,
1138 DBUS_TYPE_STRING, name,
1139 DBUS_TYPE_INVALID)) {
1140 log_error("Could not append arguments to message.");
1145 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
1146 log_error("Failed to issue method call: %s", bus_error_message(&error));
1151 dbus_message_unref(m);
1152 dbus_message_unref(reply);
1161 dbus_message_unref(m);
1163 dbus_error_free(&error);
1168 static int cancel_job(DBusConnection *bus, char **args) {
1169 DBusMessage *m = NULL, *reply = NULL;
1174 dbus_error_init(&error);
1179 if (strv_length(args) <= 1)
1180 return daemon_reload(bus, args);
1182 STRV_FOREACH(name, args+1) {
1186 if (!(m = dbus_message_new_method_call(
1187 "org.freedesktop.systemd1",
1188 "/org/freedesktop/systemd1",
1189 "org.freedesktop.systemd1.Manager",
1191 log_error("Could not allocate message.");
1196 if ((r = safe_atou(*name, &id)) < 0) {
1197 log_error("Failed to parse job id: %s", strerror(-r));
1201 assert_cc(sizeof(uint32_t) == sizeof(id));
1202 if (!dbus_message_append_args(m,
1203 DBUS_TYPE_UINT32, &id,
1204 DBUS_TYPE_INVALID)) {
1205 log_error("Could not append arguments to message.");
1210 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
1211 log_error("Failed to issue method call: %s", bus_error_message(&error));
1216 if (!dbus_message_get_args(reply, &error,
1217 DBUS_TYPE_OBJECT_PATH, &path,
1218 DBUS_TYPE_INVALID)) {
1219 log_error("Failed to parse reply: %s", bus_error_message(&error));
1224 dbus_message_unref(m);
1225 if (!(m = dbus_message_new_method_call(
1226 "org.freedesktop.systemd1",
1228 "org.freedesktop.systemd1.Job",
1230 log_error("Could not allocate message.");
1235 dbus_message_unref(reply);
1236 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
1237 log_error("Failed to issue method call: %s", bus_error_message(&error));
1242 dbus_message_unref(m);
1243 dbus_message_unref(reply);
1251 dbus_message_unref(m);
1254 dbus_message_unref(reply);
1256 dbus_error_free(&error);
1261 static bool need_daemon_reload(DBusConnection *bus, const char *unit) {
1262 DBusMessage *m = NULL, *reply = NULL;
1263 dbus_bool_t b = FALSE;
1264 DBusMessageIter iter, sub;
1266 *interface = "org.freedesktop.systemd1.Unit",
1267 *property = "NeedDaemonReload",
1270 /* We ignore all errors here, since this is used to show a warning only */
1272 if (!(m = dbus_message_new_method_call(
1273 "org.freedesktop.systemd1",
1274 "/org/freedesktop/systemd1",
1275 "org.freedesktop.systemd1.Manager",
1279 if (!dbus_message_append_args(m,
1280 DBUS_TYPE_STRING, &unit,
1284 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, NULL)))
1287 if (!dbus_message_get_args(reply, NULL,
1288 DBUS_TYPE_OBJECT_PATH, &path,
1292 dbus_message_unref(m);
1293 if (!(m = dbus_message_new_method_call(
1294 "org.freedesktop.systemd1",
1296 "org.freedesktop.DBus.Properties",
1300 if (!dbus_message_append_args(m,
1301 DBUS_TYPE_STRING, &interface,
1302 DBUS_TYPE_STRING, &property,
1303 DBUS_TYPE_INVALID)) {
1307 dbus_message_unref(reply);
1308 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, NULL)))
1311 if (!dbus_message_iter_init(reply, &iter) ||
1312 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
1315 dbus_message_iter_recurse(&iter, &sub);
1317 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_BOOLEAN)
1320 dbus_message_iter_get_basic(&sub, &b);
1324 dbus_message_unref(m);
1327 dbus_message_unref(reply);
1332 typedef struct WaitData {
1337 static DBusHandlerResult wait_filter(DBusConnection *connection, DBusMessage *message, void *data) {
1345 dbus_error_init(&error);
1347 log_debug("Got D-Bus request: %s.%s() on %s",
1348 dbus_message_get_interface(message),
1349 dbus_message_get_member(message),
1350 dbus_message_get_path(message));
1352 if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
1353 log_error("Warning! D-Bus connection terminated.");
1354 dbus_connection_close(connection);
1356 } else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
1358 const char *path, *result, *unit;
1359 dbus_bool_t success = true;
1361 if (dbus_message_get_args(message, &error,
1362 DBUS_TYPE_UINT32, &id,
1363 DBUS_TYPE_OBJECT_PATH, &path,
1364 DBUS_TYPE_STRING, &unit,
1365 DBUS_TYPE_STRING, &result,
1366 DBUS_TYPE_INVALID)) {
1369 p = set_remove(d->set, (char*) path);
1373 d->result = strdup(result);
1378 dbus_error_free(&error);
1379 if (dbus_message_get_args(message, &error,
1380 DBUS_TYPE_UINT32, &id,
1381 DBUS_TYPE_OBJECT_PATH, &path,
1382 DBUS_TYPE_STRING, &result,
1383 DBUS_TYPE_INVALID)) {
1386 /* Compatibility with older systemd versions <
1387 * 183 during upgrades. This should be dropped
1389 p = set_remove(d->set, (char*) path);
1393 d->result = strdup(result);
1398 dbus_error_free(&error);
1399 if (dbus_message_get_args(message, &error,
1400 DBUS_TYPE_UINT32, &id,
1401 DBUS_TYPE_OBJECT_PATH, &path,
1402 DBUS_TYPE_BOOLEAN, &success,
1403 DBUS_TYPE_INVALID)) {
1406 /* Compatibility with older systemd versions <
1407 * 19 during upgrades. This should be dropped
1410 p = set_remove(d->set, (char*) path);
1414 d->result = strdup("failed");
1420 log_error("Failed to parse message: %s", bus_error_message(&error));
1424 dbus_error_free(&error);
1425 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1428 static int enable_wait_for_jobs(DBusConnection *bus) {
1436 dbus_error_init(&error);
1437 dbus_bus_add_match(bus,
1439 "sender='org.freedesktop.systemd1',"
1440 "interface='org.freedesktop.systemd1.Manager',"
1441 "member='JobRemoved',"
1442 "path='/org/freedesktop/systemd1'",
1445 if (dbus_error_is_set(&error)) {
1446 log_error("Failed to add match: %s", bus_error_message(&error));
1447 dbus_error_free(&error);
1451 /* This is slightly dirty, since we don't undo the match registrations. */
1455 static int wait_for_jobs(DBusConnection *bus, Set *s) {
1465 if (!dbus_connection_add_filter(bus, wait_filter, &d, NULL)) {
1466 log_error("Failed to add filter.");
1471 while (!set_isempty(s) &&
1472 dbus_connection_read_write_dispatch(bus, -1))
1475 if (!arg_quiet && d.result) {
1476 if (streq(d.result, "timeout"))
1477 log_error("Job timed out.");
1478 else if (streq(d.result, "canceled"))
1479 log_error("Job canceled.");
1480 else if (streq(d.result, "dependency"))
1481 log_error("A dependency job failed. See system journal for details.");
1482 else if (!streq(d.result, "done") && !streq(d.result, "skipped"))
1483 log_error("Job failed. See system journal and 'systemctl status' for details.");
1486 if (streq_ptr(d.result, "timeout"))
1488 else if (streq_ptr(d.result, "canceled"))
1490 else if (!streq_ptr(d.result, "done") && !streq_ptr(d.result, "skipped"))
1498 /* This is slightly dirty, since we don't undo the filter registration. */
1503 static int check_one_unit(DBusConnection *bus, char *name, bool quiet) {
1504 DBusMessage *m = NULL, *reply = NULL;
1506 DBusMessageIter iter, sub;
1508 *interface = "org.freedesktop.systemd1.Unit",
1509 *property = "ActiveState";
1510 const char *path = NULL;
1512 int r = 3; /* According to LSB: "program is not running" */
1517 dbus_error_init(&error);
1519 m = dbus_message_new_method_call(
1520 "org.freedesktop.systemd1",
1521 "/org/freedesktop/systemd1",
1522 "org.freedesktop.systemd1.Manager",
1525 log_error("Could not allocate message.");
1530 if (!dbus_message_append_args(m,
1531 DBUS_TYPE_STRING, &name,
1532 DBUS_TYPE_INVALID)) {
1533 log_error("Could not append arguments to message.");
1538 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
1540 /* Hmm, cannot figure out anything about this unit... */
1547 if (!dbus_message_get_args(reply, &error,
1548 DBUS_TYPE_OBJECT_PATH, &path,
1549 DBUS_TYPE_INVALID)) {
1550 log_error("Failed to parse reply: %s", bus_error_message(&error));
1555 dbus_message_unref(m);
1556 m = dbus_message_new_method_call(
1557 "org.freedesktop.systemd1",
1559 "org.freedesktop.DBus.Properties",
1562 log_error("Could not allocate message.");
1567 if (!dbus_message_append_args(m,
1568 DBUS_TYPE_STRING, &interface,
1569 DBUS_TYPE_STRING, &property,
1570 DBUS_TYPE_INVALID)) {
1571 log_error("Could not append arguments to message.");
1576 dbus_message_unref(reply);
1577 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
1579 log_error("Failed to issue method call: %s", bus_error_message(&error));
1584 if (!dbus_message_iter_init(reply, &iter) ||
1585 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1586 log_error("Failed to parse reply.");
1591 dbus_message_iter_recurse(&iter, &sub);
1593 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1594 log_error("Failed to parse reply.");
1599 dbus_message_iter_get_basic(&sub, &state);
1604 if (streq(state, "active") || streq(state, "reloading"))
1609 dbus_message_unref(m);
1612 dbus_message_unref(reply);
1614 dbus_error_free(&error);
1619 static void check_triggering_units(
1620 DBusConnection *bus,
1621 const char *unit_name) {
1624 DBusMessage *m = NULL, *reply = NULL;
1625 DBusMessageIter iter, sub;
1626 char *service_trigger = NULL;
1627 const char *interface = "org.freedesktop.systemd1.Unit",
1628 *triggered_by_property = "TriggeredBy";
1630 char *unit_path = NULL;
1631 bool print_warning_label = true;
1633 dbus_error_init(&error);
1635 unit_path = unit_dbus_path_from_name(unit_name);
1637 log_error("Could not allocate dbus path.");
1641 m = dbus_message_new_method_call("org.freedesktop.systemd1",
1643 "org.freedesktop.DBus.Properties",
1646 log_error("Could not allocate message.");
1650 if (!dbus_message_append_args(m,
1651 DBUS_TYPE_STRING, &interface,
1652 DBUS_TYPE_STRING, &triggered_by_property,
1653 DBUS_TYPE_INVALID)) {
1654 log_error("Could not append arguments to message.");
1658 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
1660 log_error("Failed to issue method call: %s", bus_error_message(&error));
1664 if (!dbus_message_iter_init(reply, &iter) ||
1665 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1666 log_error("Failed to parse reply: %s", bus_error_message(&error));
1671 dbus_message_iter_recurse(&iter, &sub);
1672 dbus_message_iter_recurse(&sub, &iter);
1675 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1678 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1679 log_error("Failed to parse reply: %s", bus_error_message(&error));
1683 dbus_message_iter_get_basic(&sub, &service_trigger);
1685 r = check_one_unit(bus, service_trigger, true);
1689 if (print_warning_label) {
1690 log_warning("Warning: Stopping %s, but it can still be activated by:", unit_name);
1691 print_warning_label = false;
1693 log_warning(" %s", service_trigger);
1696 dbus_message_iter_next(&sub);
1700 dbus_message_unref(m);
1703 dbus_message_unref(reply);
1705 dbus_error_free(&error);
1710 static int start_unit_one(
1711 DBusConnection *bus,
1718 DBusMessage *m = NULL, *reply = NULL;
1727 assert(arg_no_block || s);
1729 if (!(m = dbus_message_new_method_call(
1730 "org.freedesktop.systemd1",
1731 "/org/freedesktop/systemd1",
1732 "org.freedesktop.systemd1.Manager",
1734 log_error("Could not allocate message.");
1739 if (!dbus_message_append_args(m,
1740 DBUS_TYPE_STRING, &name,
1741 DBUS_TYPE_STRING, &mode,
1742 DBUS_TYPE_INVALID)) {
1743 log_error("Could not append arguments to message.");
1748 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, error))) {
1750 if (arg_action != ACTION_SYSTEMCTL && error_is_no_service(error)) {
1751 /* There's always a fallback possible for
1752 * legacy actions. */
1757 log_error("Failed to issue method call: %s", bus_error_message(error));
1762 if (!dbus_message_get_args(reply, error,
1763 DBUS_TYPE_OBJECT_PATH, &path,
1764 DBUS_TYPE_INVALID)) {
1765 log_error("Failed to parse reply: %s", bus_error_message(error));
1770 if (need_daemon_reload(bus, name))
1771 log_warning("Warning: Unit file of created job changed on disk, 'systemctl %s daemon-reload' recommended.",
1772 arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
1774 if (!arg_no_block) {
1777 if (!(p = strdup(path))) {
1778 log_error("Failed to duplicate path.");
1783 if ((r = set_put(s, p)) < 0) {
1785 log_error("Failed to add path to set.");
1790 /* When stopping a unit warn if it can still be triggered by
1791 * another active unit (socket, path, timer) */
1792 if (!arg_quiet && streq(method, "StopUnit"))
1793 check_triggering_units(bus, name);
1799 dbus_message_unref(m);
1802 dbus_message_unref(reply);
1807 static enum action verb_to_action(const char *verb) {
1808 if (streq(verb, "halt"))
1810 else if (streq(verb, "poweroff"))
1811 return ACTION_POWEROFF;
1812 else if (streq(verb, "reboot"))
1813 return ACTION_REBOOT;
1814 else if (streq(verb, "kexec"))
1815 return ACTION_KEXEC;
1816 else if (streq(verb, "rescue"))
1817 return ACTION_RESCUE;
1818 else if (streq(verb, "emergency"))
1819 return ACTION_EMERGENCY;
1820 else if (streq(verb, "default"))
1821 return ACTION_DEFAULT;
1822 else if (streq(verb, "exit"))
1824 else if (streq(verb, "suspend"))
1825 return ACTION_SUSPEND;
1826 else if (streq(verb, "hibernate"))
1827 return ACTION_HIBERNATE;
1829 return ACTION_INVALID;
1832 static int start_unit(DBusConnection *bus, char **args) {
1834 static const char * const table[_ACTION_MAX] = {
1835 [ACTION_HALT] = SPECIAL_HALT_TARGET,
1836 [ACTION_POWEROFF] = SPECIAL_POWEROFF_TARGET,
1837 [ACTION_REBOOT] = SPECIAL_REBOOT_TARGET,
1838 [ACTION_KEXEC] = SPECIAL_KEXEC_TARGET,
1839 [ACTION_RUNLEVEL2] = SPECIAL_RUNLEVEL2_TARGET,
1840 [ACTION_RUNLEVEL3] = SPECIAL_RUNLEVEL3_TARGET,
1841 [ACTION_RUNLEVEL4] = SPECIAL_RUNLEVEL4_TARGET,
1842 [ACTION_RUNLEVEL5] = SPECIAL_RUNLEVEL5_TARGET,
1843 [ACTION_RESCUE] = SPECIAL_RESCUE_TARGET,
1844 [ACTION_EMERGENCY] = SPECIAL_EMERGENCY_TARGET,
1845 [ACTION_DEFAULT] = SPECIAL_DEFAULT_TARGET,
1846 [ACTION_EXIT] = SPECIAL_EXIT_TARGET,
1847 [ACTION_SUSPEND] = SPECIAL_SUSPEND_TARGET,
1848 [ACTION_HIBERNATE] = SPECIAL_HIBERNATE_TARGET
1852 const char *method, *mode, *one_name;
1857 dbus_error_init(&error);
1861 ask_password_agent_open_if_enabled();
1863 if (arg_action == ACTION_SYSTEMCTL) {
1865 streq(args[0], "stop") ||
1866 streq(args[0], "condstop") ? "StopUnit" :
1867 streq(args[0], "reload") ? "ReloadUnit" :
1868 streq(args[0], "restart") ? "RestartUnit" :
1870 streq(args[0], "try-restart") ||
1871 streq(args[0], "condrestart") ? "TryRestartUnit" :
1873 streq(args[0], "reload-or-restart") ? "ReloadOrRestartUnit" :
1875 streq(args[0], "reload-or-try-restart") ||
1876 streq(args[0], "condreload") ||
1878 streq(args[0], "force-reload") ? "ReloadOrTryRestartUnit" :
1882 (streq(args[0], "isolate") ||
1883 streq(args[0], "rescue") ||
1884 streq(args[0], "emergency")) ? "isolate" : arg_job_mode;
1886 one_name = table[verb_to_action(args[0])];
1889 assert(arg_action < ELEMENTSOF(table));
1890 assert(table[arg_action]);
1892 method = "StartUnit";
1894 mode = (arg_action == ACTION_EMERGENCY ||
1895 arg_action == ACTION_RESCUE ||
1896 arg_action == ACTION_RUNLEVEL2 ||
1897 arg_action == ACTION_RUNLEVEL3 ||
1898 arg_action == ACTION_RUNLEVEL4 ||
1899 arg_action == ACTION_RUNLEVEL5) ? "isolate" : "replace";
1901 one_name = table[arg_action];
1904 if (!arg_no_block) {
1905 if ((ret = enable_wait_for_jobs(bus)) < 0) {
1906 log_error("Could not watch jobs: %s", strerror(-ret));
1910 if (!(s = set_new(string_hash_func, string_compare_func))) {
1911 log_error("Failed to allocate set.");
1918 if ((ret = start_unit_one(bus, method, one_name, mode, &error, s)) <= 0)
1921 STRV_FOREACH(name, args+1)
1922 if ((r = start_unit_one(bus, method, *name, mode, &error, s)) != 0) {
1923 ret = translate_bus_error_to_exit_status(r, &error);
1924 dbus_error_free(&error);
1929 if ((r = wait_for_jobs(bus, s)) < 0) {
1938 dbus_error_free(&error);
1943 /* Ask systemd-logind, which might grant access to unprivileged users
1944 * through PolicyKit */
1945 static int reboot_with_logind(DBusConnection *bus, enum action a) {
1948 DBusMessage *m = NULL, *reply = NULL;
1950 dbus_bool_t interactive = true;
1953 dbus_error_init(&error);
1955 polkit_agent_open_if_enabled();
1963 case ACTION_POWEROFF:
1964 method = "PowerOff";
1967 case ACTION_SUSPEND:
1971 case ACTION_HIBERNATE:
1972 method = "Hibernate";
1979 m = dbus_message_new_method_call(
1980 "org.freedesktop.login1",
1981 "/org/freedesktop/login1",
1982 "org.freedesktop.login1.Manager",
1985 log_error("Could not allocate message.");
1990 if (!dbus_message_append_args(m,
1991 DBUS_TYPE_BOOLEAN, &interactive,
1992 DBUS_TYPE_INVALID)) {
1993 log_error("Could not append arguments to message.");
1998 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
2000 if (error_is_no_service(&error)) {
2001 log_debug("Failed to issue method call: %s", bus_error_message(&error));
2006 if (dbus_error_has_name(&error, DBUS_ERROR_ACCESS_DENIED)) {
2007 log_debug("Failed to issue method call: %s", bus_error_message(&error));
2012 log_info("Failed to issue method call: %s", bus_error_message(&error));
2021 dbus_message_unref(m);
2024 dbus_message_unref(reply);
2026 dbus_error_free(&error);
2034 static int start_special(DBusConnection *bus, char **args) {
2040 a = verb_to_action(args[0]);
2042 if (arg_force >= 2 && geteuid() != 0) {
2043 log_error("Must be root.");
2047 if (arg_force >= 2 &&
2048 (a == ACTION_HALT ||
2049 a == ACTION_POWEROFF ||
2050 a == ACTION_REBOOT))
2053 if (arg_force >= 1 &&
2054 (a == ACTION_HALT ||
2055 a == ACTION_POWEROFF ||
2056 a == ACTION_REBOOT ||
2057 a == ACTION_KEXEC ||
2059 return daemon_reload(bus, args);
2061 /* first try logind, to allow authentication with polkit */
2062 if (geteuid() != 0 &&
2063 (a == ACTION_POWEROFF ||
2064 a == ACTION_REBOOT ||
2065 a == ACTION_SUSPEND ||
2066 a == ACTION_HIBERNATE)) {
2067 r = reboot_with_logind(bus, a);
2072 r = start_unit(bus, args);
2079 static int check_unit(DBusConnection *bus, char **args) {
2081 int r = 3; /* According to LSB: "program is not running" */
2086 STRV_FOREACH(name, args+1) {
2087 int state = check_one_unit(bus, *name, arg_quiet);
2097 static int kill_unit(DBusConnection *bus, char **args) {
2098 DBusMessage *m = NULL;
2106 dbus_error_init(&error);
2109 arg_kill_who = "all";
2112 arg_kill_mode = streq(arg_kill_who, "all") ? "control-group" : "process";
2114 STRV_FOREACH(name, args+1) {
2117 if (!(m = dbus_message_new_method_call(
2118 "org.freedesktop.systemd1",
2119 "/org/freedesktop/systemd1",
2120 "org.freedesktop.systemd1.Manager",
2122 log_error("Could not allocate message.");
2127 if (!dbus_message_append_args(m,
2128 DBUS_TYPE_STRING, name,
2129 DBUS_TYPE_STRING, &arg_kill_who,
2130 DBUS_TYPE_STRING, &arg_kill_mode,
2131 DBUS_TYPE_INT32, &arg_signal,
2132 DBUS_TYPE_INVALID)) {
2133 log_error("Could not append arguments to message.");
2138 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
2139 log_error("Failed to issue method call: %s", bus_error_message(&error));
2140 dbus_error_free(&error);
2144 dbus_message_unref(m);
2147 dbus_message_unref(reply);
2153 dbus_message_unref(m);
2155 dbus_error_free(&error);
2160 typedef struct ExecStatusInfo {
2168 usec_t start_timestamp;
2169 usec_t exit_timestamp;
2174 LIST_FIELDS(struct ExecStatusInfo, exec);
2177 static void exec_status_info_free(ExecStatusInfo *i) {
2186 static int exec_status_info_deserialize(DBusMessageIter *sub, ExecStatusInfo *i) {
2187 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
2188 DBusMessageIter sub2, sub3;
2192 int32_t code, status;
2198 if (dbus_message_iter_get_arg_type(sub) != DBUS_TYPE_STRUCT)
2201 dbus_message_iter_recurse(sub, &sub2);
2203 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0)
2206 if (!(i->path = strdup(path)))
2209 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_ARRAY ||
2210 dbus_message_iter_get_element_type(&sub2) != DBUS_TYPE_STRING)
2214 dbus_message_iter_recurse(&sub2, &sub3);
2215 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2216 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2217 dbus_message_iter_next(&sub3);
2222 if (!(i->argv = new0(char*, n+1)))
2226 dbus_message_iter_recurse(&sub2, &sub3);
2227 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2230 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2231 dbus_message_iter_get_basic(&sub3, &s);
2232 dbus_message_iter_next(&sub3);
2234 if (!(i->argv[n++] = strdup(s)))
2238 if (!dbus_message_iter_next(&sub2) ||
2239 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, true) < 0 ||
2240 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp, true) < 0 ||
2241 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp_monotonic, true) < 0 ||
2242 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp, true) < 0 ||
2243 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp_monotonic, true) < 0 ||
2244 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, true) < 0 ||
2245 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &code, true) < 0 ||
2246 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &status, false) < 0)
2250 i->start_timestamp = (usec_t) start_timestamp;
2251 i->exit_timestamp = (usec_t) exit_timestamp;
2252 i->pid = (pid_t) pid;
2259 typedef struct UnitStatusInfo {
2261 const char *load_state;
2262 const char *active_state;
2263 const char *sub_state;
2264 const char *unit_file_state;
2266 const char *description;
2267 const char *following;
2269 char **documentation;
2271 const char *fragment_path;
2272 const char *source_path;
2273 const char *default_control_group;
2275 const char *load_error;
2278 usec_t inactive_exit_timestamp;
2279 usec_t inactive_exit_timestamp_monotonic;
2280 usec_t active_enter_timestamp;
2281 usec_t active_exit_timestamp;
2282 usec_t inactive_enter_timestamp;
2284 bool need_daemon_reload;
2289 const char *status_text;
2292 usec_t start_timestamp;
2293 usec_t exit_timestamp;
2295 int exit_code, exit_status;
2297 usec_t condition_timestamp;
2298 bool condition_result;
2301 unsigned n_accepted;
2302 unsigned n_connections;
2306 const char *sysfs_path;
2308 /* Mount, Automount */
2314 LIST_HEAD(ExecStatusInfo, exec);
2317 static void print_status_info(UnitStatusInfo *i) {
2319 const char *on, *off, *ss;
2321 char since1[FORMAT_TIMESTAMP_PRETTY_MAX], *s1;
2322 char since2[FORMAT_TIMESTAMP_MAX], *s2;
2327 /* This shows pretty information about a unit. See
2328 * print_property() for a low-level property printer */
2330 printf("%s", strna(i->id));
2332 if (i->description && !streq_ptr(i->id, i->description))
2333 printf(" - %s", i->description);
2338 printf("\t Follow: unit currently follows state of %s\n", i->following);
2340 if (streq_ptr(i->load_state, "error")) {
2341 on = ansi_highlight_red(true);
2342 off = ansi_highlight_red(false);
2346 path = i->source_path ? i->source_path : i->fragment_path;
2349 printf("\t Loaded: %s%s%s (Reason: %s)\n", on, strna(i->load_state), off, i->load_error);
2350 else if (path && i->unit_file_state)
2351 printf("\t Loaded: %s%s%s (%s; %s)\n", on, strna(i->load_state), off, path, i->unit_file_state);
2353 printf("\t Loaded: %s%s%s (%s)\n", on, strna(i->load_state), off, path);
2355 printf("\t Loaded: %s%s%s\n", on, strna(i->load_state), off);
2357 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
2359 if (streq_ptr(i->active_state, "failed")) {
2360 on = ansi_highlight_red(true);
2361 off = ansi_highlight_red(false);
2362 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
2363 on = ansi_highlight_green(true);
2364 off = ansi_highlight_green(false);
2369 printf("\t Active: %s%s (%s)%s",
2371 strna(i->active_state),
2375 printf("\t Active: %s%s%s",
2377 strna(i->active_state),
2380 if (!isempty(i->result) && !streq(i->result, "success"))
2381 printf(" (Result: %s)", i->result);
2383 timestamp = (streq_ptr(i->active_state, "active") ||
2384 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
2385 (streq_ptr(i->active_state, "inactive") ||
2386 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
2387 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
2388 i->active_exit_timestamp;
2390 s1 = format_timestamp_pretty(since1, sizeof(since1), timestamp);
2391 s2 = format_timestamp(since2, sizeof(since2), timestamp);
2394 printf(" since %s; %s\n", s2, s1);
2396 printf(" since %s\n", s2);
2400 if (!i->condition_result && i->condition_timestamp > 0) {
2401 s1 = format_timestamp_pretty(since1, sizeof(since1), i->condition_timestamp);
2402 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
2405 printf("\t start condition failed at %s; %s\n", s2, s1);
2407 printf("\t start condition failed at %s\n", s2);
2411 printf("\t Device: %s\n", i->sysfs_path);
2413 printf("\t Where: %s\n", i->where);
2415 printf("\t What: %s\n", i->what);
2417 if (!strv_isempty(i->documentation)) {
2421 STRV_FOREACH(t, i->documentation) {
2423 printf("\t Docs: %s\n", *t);
2426 printf("\t %s\n", *t);
2431 printf("\tAccepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
2433 LIST_FOREACH(exec, p, i->exec) {
2437 /* Only show exited processes here */
2441 t = strv_join(p->argv, " ");
2442 printf("\t Process: %u %s=%s ", p->pid, p->name, strna(t));
2445 good = is_clean_exit_lsb(p->code, p->status);
2447 on = ansi_highlight_red(true);
2448 off = ansi_highlight_red(false);
2452 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
2454 if (p->code == CLD_EXITED) {
2457 printf("status=%i", p->status);
2459 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
2464 printf("signal=%s", signal_to_string(p->status));
2466 printf(")%s\n", off);
2468 if (i->main_pid == p->pid &&
2469 i->start_timestamp == p->start_timestamp &&
2470 i->exit_timestamp == p->start_timestamp)
2471 /* Let's not show this twice */
2474 if (p->pid == i->control_pid)
2478 if (i->main_pid > 0 || i->control_pid > 0) {
2481 if (i->main_pid > 0) {
2482 printf("Main PID: %u", (unsigned) i->main_pid);
2486 get_process_comm(i->main_pid, &t);
2491 } else if (i->exit_code > 0) {
2492 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
2494 if (i->exit_code == CLD_EXITED) {
2497 printf("status=%i", i->exit_status);
2499 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
2504 printf("signal=%s", signal_to_string(i->exit_status));
2509 if (i->main_pid > 0 && i->control_pid > 0)
2512 if (i->control_pid > 0) {
2515 printf(" Control: %u", (unsigned) i->control_pid);
2517 get_process_comm(i->control_pid, &t);
2528 printf("\t Status: \"%s\"\n", i->status_text);
2530 if (i->default_control_group) {
2533 printf("\t CGroup: %s\n", i->default_control_group);
2535 if (arg_transport != TRANSPORT_SSH) {
2545 if (i->main_pid > 0)
2546 extra[k++] = i->main_pid;
2548 if (i->control_pid > 0)
2549 extra[k++] = i->control_pid;
2551 show_cgroup_and_extra_by_spec(i->default_control_group, "\t\t ", c, false, arg_all, extra, k);
2555 if (i->id && arg_transport != TRANSPORT_SSH) {
2557 show_journal_by_unit(i->id, arg_output, 0, i->inactive_exit_timestamp_monotonic, arg_lines, arg_all, arg_follow, !arg_quiet);
2560 if (i->need_daemon_reload)
2561 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %s daemon-reload' recommended.\n",
2562 ansi_highlight_red(true),
2563 ansi_highlight_red(false),
2564 arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
2567 static void show_unit_help(UnitStatusInfo *i) {
2572 if (!i->documentation) {
2573 log_info("Documentation for %s not known.", i->id);
2577 STRV_FOREACH(p, i->documentation) {
2579 if (startswith(*p, "man:")) {
2582 char *page = NULL, *section = NULL;
2583 const char *args[4] = { "man", NULL, NULL, NULL };
2588 if ((*p)[k-1] == ')')
2589 e = strrchr(*p, '(');
2592 page = strndup((*p) + 4, e - *p - 4);
2594 log_error("Out of memory.");
2598 section = strndup(e + 1, *p + k - e - 2);
2601 log_error("Out of memory");
2612 log_error("Failed to fork: %m");
2620 execvp(args[0], (char**) args);
2621 log_error("Failed to execute man: %m");
2622 _exit(EXIT_FAILURE);
2628 wait_for_terminate(pid, NULL);
2630 log_info("Can't show %s.", *p);
2634 static int status_property(const char *name, DBusMessageIter *iter, UnitStatusInfo *i) {
2640 switch (dbus_message_iter_get_arg_type(iter)) {
2642 case DBUS_TYPE_STRING: {
2645 dbus_message_iter_get_basic(iter, &s);
2648 if (streq(name, "Id"))
2650 else if (streq(name, "LoadState"))
2652 else if (streq(name, "ActiveState"))
2653 i->active_state = s;
2654 else if (streq(name, "SubState"))
2656 else if (streq(name, "Description"))
2658 else if (streq(name, "FragmentPath"))
2659 i->fragment_path = s;
2660 else if (streq(name, "SourcePath"))
2662 else if (streq(name, "DefaultControlGroup"))
2663 i->default_control_group = s;
2664 else if (streq(name, "StatusText"))
2666 else if (streq(name, "SysFSPath"))
2668 else if (streq(name, "Where"))
2670 else if (streq(name, "What"))
2672 else if (streq(name, "Following"))
2674 else if (streq(name, "UnitFileState"))
2675 i->unit_file_state = s;
2676 else if (streq(name, "Result"))
2683 case DBUS_TYPE_BOOLEAN: {
2686 dbus_message_iter_get_basic(iter, &b);
2688 if (streq(name, "Accept"))
2690 else if (streq(name, "NeedDaemonReload"))
2691 i->need_daemon_reload = b;
2692 else if (streq(name, "ConditionResult"))
2693 i->condition_result = b;
2698 case DBUS_TYPE_UINT32: {
2701 dbus_message_iter_get_basic(iter, &u);
2703 if (streq(name, "MainPID")) {
2705 i->main_pid = (pid_t) u;
2708 } else if (streq(name, "ControlPID"))
2709 i->control_pid = (pid_t) u;
2710 else if (streq(name, "ExecMainPID")) {
2712 i->main_pid = (pid_t) u;
2713 } else if (streq(name, "NAccepted"))
2715 else if (streq(name, "NConnections"))
2716 i->n_connections = u;
2721 case DBUS_TYPE_INT32: {
2724 dbus_message_iter_get_basic(iter, &j);
2726 if (streq(name, "ExecMainCode"))
2727 i->exit_code = (int) j;
2728 else if (streq(name, "ExecMainStatus"))
2729 i->exit_status = (int) j;
2734 case DBUS_TYPE_UINT64: {
2737 dbus_message_iter_get_basic(iter, &u);
2739 if (streq(name, "ExecMainStartTimestamp"))
2740 i->start_timestamp = (usec_t) u;
2741 else if (streq(name, "ExecMainExitTimestamp"))
2742 i->exit_timestamp = (usec_t) u;
2743 else if (streq(name, "ActiveEnterTimestamp"))
2744 i->active_enter_timestamp = (usec_t) u;
2745 else if (streq(name, "InactiveEnterTimestamp"))
2746 i->inactive_enter_timestamp = (usec_t) u;
2747 else if (streq(name, "InactiveExitTimestamp"))
2748 i->inactive_exit_timestamp = (usec_t) u;
2749 else if (streq(name, "InactiveExitTimestampMonotonic"))
2750 i->inactive_exit_timestamp_monotonic = (usec_t) u;
2751 else if (streq(name, "ActiveExitTimestamp"))
2752 i->active_exit_timestamp = (usec_t) u;
2753 else if (streq(name, "ConditionTimestamp"))
2754 i->condition_timestamp = (usec_t) u;
2759 case DBUS_TYPE_ARRAY: {
2761 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
2762 startswith(name, "Exec")) {
2763 DBusMessageIter sub;
2765 dbus_message_iter_recurse(iter, &sub);
2766 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2767 ExecStatusInfo *info;
2770 if (!(info = new0(ExecStatusInfo, 1)))
2773 if (!(info->name = strdup(name))) {
2778 if ((r = exec_status_info_deserialize(&sub, info)) < 0) {
2783 LIST_PREPEND(ExecStatusInfo, exec, i->exec, info);
2785 dbus_message_iter_next(&sub);
2787 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
2788 streq(name, "Documentation")) {
2790 DBusMessageIter sub;
2792 dbus_message_iter_recurse(iter, &sub);
2793 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING) {
2797 dbus_message_iter_get_basic(&sub, &s);
2799 l = strv_append(i->documentation, s);
2803 strv_free(i->documentation);
2804 i->documentation = l;
2806 dbus_message_iter_next(&sub);
2813 case DBUS_TYPE_STRUCT: {
2815 if (streq(name, "LoadError")) {
2816 DBusMessageIter sub;
2817 const char *n, *message;
2820 dbus_message_iter_recurse(iter, &sub);
2822 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &n, true);
2826 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &message, false);
2830 if (!isempty(message))
2831 i->load_error = message;
2841 static int print_property(const char *name, DBusMessageIter *iter) {
2845 /* This is a low-level property printer, see
2846 * print_status_info() for the nicer output */
2848 if (arg_property && !strv_find(arg_property, name))
2851 switch (dbus_message_iter_get_arg_type(iter)) {
2853 case DBUS_TYPE_STRUCT: {
2854 DBusMessageIter sub;
2855 dbus_message_iter_recurse(iter, &sub);
2857 if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32 && streq(name, "Job")) {
2860 dbus_message_iter_get_basic(&sub, &u);
2863 printf("%s=%u\n", name, (unsigned) u);
2865 printf("%s=\n", name);
2868 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "Unit")) {
2871 dbus_message_iter_get_basic(&sub, &s);
2873 if (arg_all || s[0])
2874 printf("%s=%s\n", name, s);
2877 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "LoadError")) {
2878 const char *a = NULL, *b = NULL;
2880 if (bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &a, true) >= 0)
2881 bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &b, false);
2883 if (arg_all || !isempty(a) || !isempty(b))
2884 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
2892 case DBUS_TYPE_ARRAY:
2894 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "EnvironmentFiles")) {
2895 DBusMessageIter sub, sub2;
2897 dbus_message_iter_recurse(iter, &sub);
2898 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2902 dbus_message_iter_recurse(&sub, &sub2);
2904 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
2905 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) >= 0)
2906 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
2908 dbus_message_iter_next(&sub);
2913 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Paths")) {
2914 DBusMessageIter sub, sub2;
2916 dbus_message_iter_recurse(iter, &sub);
2917 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2918 const char *type, *path;
2920 dbus_message_iter_recurse(&sub, &sub2);
2922 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
2923 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
2924 printf("%s=%s\n", type, path);
2926 dbus_message_iter_next(&sub);
2931 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Timers")) {
2932 DBusMessageIter sub, sub2;
2934 dbus_message_iter_recurse(iter, &sub);
2935 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2937 uint64_t value, next_elapse;
2939 dbus_message_iter_recurse(&sub, &sub2);
2941 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &base, true) >= 0 &&
2942 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &value, true) >= 0 &&
2943 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &next_elapse, false) >= 0) {
2944 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
2946 printf("%s={ value=%s ; next_elapse=%s }\n",
2948 format_timespan(timespan1, sizeof(timespan1), value),
2949 format_timespan(timespan2, sizeof(timespan2), next_elapse));
2952 dbus_message_iter_next(&sub);
2957 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "ControlGroupAttributes")) {
2958 DBusMessageIter sub, sub2;
2960 dbus_message_iter_recurse(iter, &sub);
2961 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2962 const char *controller, *attr, *value;
2964 dbus_message_iter_recurse(&sub, &sub2);
2966 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &controller, true) >= 0 &&
2967 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &attr, true) >= 0 &&
2968 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &value, false) >= 0) {
2970 printf("ControlGroupAttribute={ controller=%s ; attribute=%s ; value=\"%s\" }\n",
2976 dbus_message_iter_next(&sub);
2981 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && startswith(name, "Exec")) {
2982 DBusMessageIter sub;
2984 dbus_message_iter_recurse(iter, &sub);
2985 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2986 ExecStatusInfo info;
2989 if (exec_status_info_deserialize(&sub, &info) >= 0) {
2990 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
2993 t = strv_join(info.argv, " ");
2995 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
2999 yes_no(info.ignore),
3000 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
3001 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
3002 (unsigned) info. pid,
3003 sigchld_code_to_string(info.code),
3005 info.code == CLD_EXITED ? "" : "/",
3006 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
3012 strv_free(info.argv);
3014 dbus_message_iter_next(&sub);
3023 if (generic_print_property(name, iter, arg_all) > 0)
3027 printf("%s=[unprintable]\n", name);
3032 static int show_one(const char *verb, DBusConnection *bus, const char *path, bool show_properties, bool *new_line) {
3033 DBusMessage *m = NULL, *reply = NULL;
3034 const char *interface = "";
3037 DBusMessageIter iter, sub, sub2, sub3;
3038 UnitStatusInfo info;
3046 dbus_error_init(&error);
3048 if (!(m = dbus_message_new_method_call(
3049 "org.freedesktop.systemd1",
3051 "org.freedesktop.DBus.Properties",
3053 log_error("Could not allocate message.");
3058 if (!dbus_message_append_args(m,
3059 DBUS_TYPE_STRING, &interface,
3060 DBUS_TYPE_INVALID)) {
3061 log_error("Could not append arguments to message.");
3066 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3067 log_error("Failed to issue method call: %s", bus_error_message(&error));
3072 if (!dbus_message_iter_init(reply, &iter) ||
3073 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3074 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
3075 log_error("Failed to parse reply.");
3080 dbus_message_iter_recurse(&iter, &sub);
3087 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
3090 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_DICT_ENTRY) {
3091 log_error("Failed to parse reply.");
3096 dbus_message_iter_recurse(&sub, &sub2);
3098 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0) {
3099 log_error("Failed to parse reply.");
3104 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
3105 log_error("Failed to parse reply.");
3110 dbus_message_iter_recurse(&sub2, &sub3);
3112 if (show_properties)
3113 r = print_property(name, &sub3);
3115 r = status_property(name, &sub3, &info);
3118 log_error("Failed to parse reply.");
3123 dbus_message_iter_next(&sub);
3128 if (!show_properties) {
3129 if (streq(verb, "help"))
3130 show_unit_help(&info);
3132 print_status_info(&info);
3135 strv_free(info.documentation);
3137 if (!streq_ptr(info.active_state, "active") &&
3138 !streq_ptr(info.active_state, "reloading") &&
3139 streq(verb, "status"))
3140 /* According to LSB: "program not running" */
3143 while ((p = info.exec)) {
3144 LIST_REMOVE(ExecStatusInfo, exec, info.exec, p);
3145 exec_status_info_free(p);
3150 dbus_message_unref(m);
3153 dbus_message_unref(reply);
3155 dbus_error_free(&error);
3160 static int show_one_by_pid(const char *verb, DBusConnection *bus, uint32_t pid, bool *new_line) {
3161 DBusMessage *m = NULL, *reply = NULL;
3162 const char *path = NULL;
3166 dbus_error_init(&error);
3168 m = dbus_message_new_method_call(
3169 "org.freedesktop.systemd1",
3170 "/org/freedesktop/systemd1",
3171 "org.freedesktop.systemd1.Manager",
3174 log_error("Could not allocate message.");
3179 if (!dbus_message_append_args(m,
3180 DBUS_TYPE_UINT32, &pid,
3181 DBUS_TYPE_INVALID)) {
3182 log_error("Could not append arguments to message.");
3187 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3189 log_error("Failed to issue method call: %s", bus_error_message(&error));
3194 if (!dbus_message_get_args(reply, &error,
3195 DBUS_TYPE_OBJECT_PATH, &path,
3196 DBUS_TYPE_INVALID)) {
3197 log_error("Failed to parse reply: %s", bus_error_message(&error));
3202 r = show_one(verb, bus, path, false, new_line);
3206 dbus_message_unref(m);
3209 dbus_message_unref(reply);
3211 dbus_error_free(&error);
3216 static int show(DBusConnection *bus, char **args) {
3218 bool show_properties, new_line = false;
3224 show_properties = streq(args[0], "show");
3226 if (show_properties)
3227 pager_open_if_enabled();
3229 if (show_properties && strv_length(args) <= 1) {
3230 /* If not argument is specified inspect the manager
3233 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line);
3236 STRV_FOREACH(name, args+1) {
3239 if (safe_atou32(*name, &id) < 0) {
3241 /* Interpret as unit name */
3243 char *p = unit_dbus_path_from_name(*name);
3247 r = show_one(args[0], bus, p, show_properties, &new_line);
3253 } else if (show_properties) {
3255 /* Interpret as job id */
3258 if (asprintf(&p, "/org/freedesktop/systemd1/job/%u", id) < 0)
3261 r = show_one(args[0], bus, p, show_properties, &new_line);
3269 /* Interpret as PID */
3271 r = show_one_by_pid(args[0], bus, id, &new_line);
3280 static int dump(DBusConnection *bus, char **args) {
3281 DBusMessage *m = NULL, *reply = NULL;
3286 dbus_error_init(&error);
3288 pager_open_if_enabled();
3290 if (!(m = dbus_message_new_method_call(
3291 "org.freedesktop.systemd1",
3292 "/org/freedesktop/systemd1",
3293 "org.freedesktop.systemd1.Manager",
3295 log_error("Could not allocate message.");
3299 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3300 log_error("Failed to issue method call: %s", bus_error_message(&error));
3305 if (!dbus_message_get_args(reply, &error,
3306 DBUS_TYPE_STRING, &text,
3307 DBUS_TYPE_INVALID)) {
3308 log_error("Failed to parse reply: %s", bus_error_message(&error));
3313 fputs(text, stdout);
3319 dbus_message_unref(m);
3322 dbus_message_unref(reply);
3324 dbus_error_free(&error);
3329 static int snapshot(DBusConnection *bus, char **args) {
3330 DBusMessage *m = NULL, *reply = NULL;
3333 const char *name = "", *path, *id;
3334 dbus_bool_t cleanup = FALSE;
3335 DBusMessageIter iter, sub;
3337 *interface = "org.freedesktop.systemd1.Unit",
3340 dbus_error_init(&error);
3342 if (!(m = dbus_message_new_method_call(
3343 "org.freedesktop.systemd1",
3344 "/org/freedesktop/systemd1",
3345 "org.freedesktop.systemd1.Manager",
3346 "CreateSnapshot"))) {
3347 log_error("Could not allocate message.");
3351 if (strv_length(args) > 1)
3354 if (!dbus_message_append_args(m,
3355 DBUS_TYPE_STRING, &name,
3356 DBUS_TYPE_BOOLEAN, &cleanup,
3357 DBUS_TYPE_INVALID)) {
3358 log_error("Could not append arguments to message.");
3363 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3364 log_error("Failed to issue method call: %s", bus_error_message(&error));
3369 if (!dbus_message_get_args(reply, &error,
3370 DBUS_TYPE_OBJECT_PATH, &path,
3371 DBUS_TYPE_INVALID)) {
3372 log_error("Failed to parse reply: %s", bus_error_message(&error));
3377 dbus_message_unref(m);
3378 if (!(m = dbus_message_new_method_call(
3379 "org.freedesktop.systemd1",
3381 "org.freedesktop.DBus.Properties",
3383 log_error("Could not allocate message.");
3387 if (!dbus_message_append_args(m,
3388 DBUS_TYPE_STRING, &interface,
3389 DBUS_TYPE_STRING, &property,
3390 DBUS_TYPE_INVALID)) {
3391 log_error("Could not append arguments to message.");
3396 dbus_message_unref(reply);
3397 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3398 log_error("Failed to issue method call: %s", bus_error_message(&error));
3403 if (!dbus_message_iter_init(reply, &iter) ||
3404 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3405 log_error("Failed to parse reply.");
3410 dbus_message_iter_recurse(&iter, &sub);
3412 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
3413 log_error("Failed to parse reply.");
3418 dbus_message_iter_get_basic(&sub, &id);
3426 dbus_message_unref(m);
3429 dbus_message_unref(reply);
3431 dbus_error_free(&error);
3436 static int delete_snapshot(DBusConnection *bus, char **args) {
3437 DBusMessage *m = NULL, *reply = NULL;
3445 dbus_error_init(&error);
3447 STRV_FOREACH(name, args+1) {
3448 const char *path = NULL;
3450 if (!(m = dbus_message_new_method_call(
3451 "org.freedesktop.systemd1",
3452 "/org/freedesktop/systemd1",
3453 "org.freedesktop.systemd1.Manager",
3455 log_error("Could not allocate message.");
3460 if (!dbus_message_append_args(m,
3461 DBUS_TYPE_STRING, name,
3462 DBUS_TYPE_INVALID)) {
3463 log_error("Could not append arguments to message.");
3468 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3469 log_error("Failed to issue method call: %s", bus_error_message(&error));
3474 if (!dbus_message_get_args(reply, &error,
3475 DBUS_TYPE_OBJECT_PATH, &path,
3476 DBUS_TYPE_INVALID)) {
3477 log_error("Failed to parse reply: %s", bus_error_message(&error));
3482 dbus_message_unref(m);
3483 if (!(m = dbus_message_new_method_call(
3484 "org.freedesktop.systemd1",
3486 "org.freedesktop.systemd1.Snapshot",
3488 log_error("Could not allocate message.");
3493 dbus_message_unref(reply);
3494 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3495 log_error("Failed to issue method call: %s", bus_error_message(&error));
3500 dbus_message_unref(m);
3501 dbus_message_unref(reply);
3509 dbus_message_unref(m);
3512 dbus_message_unref(reply);
3514 dbus_error_free(&error);
3519 static int daemon_reload(DBusConnection *bus, char **args) {
3520 DBusMessage *m = NULL, *reply = NULL;
3525 dbus_error_init(&error);
3527 if (arg_action == ACTION_RELOAD)
3529 else if (arg_action == ACTION_REEXEC)
3530 method = "Reexecute";
3532 assert(arg_action == ACTION_SYSTEMCTL);
3535 streq(args[0], "clear-jobs") ||
3536 streq(args[0], "cancel") ? "ClearJobs" :
3537 streq(args[0], "daemon-reexec") ? "Reexecute" :
3538 streq(args[0], "reset-failed") ? "ResetFailed" :
3539 streq(args[0], "halt") ? "Halt" :
3540 streq(args[0], "poweroff") ? "PowerOff" :
3541 streq(args[0], "reboot") ? "Reboot" :
3542 streq(args[0], "kexec") ? "KExec" :
3543 streq(args[0], "exit") ? "Exit" :
3544 /* "daemon-reload" */ "Reload";
3547 if (!(m = dbus_message_new_method_call(
3548 "org.freedesktop.systemd1",
3549 "/org/freedesktop/systemd1",
3550 "org.freedesktop.systemd1.Manager",
3552 log_error("Could not allocate message.");
3556 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3558 if (arg_action != ACTION_SYSTEMCTL && error_is_no_service(&error)) {
3559 /* There's always a fallback possible for
3560 * legacy actions. */
3565 if (streq(method, "Reexecute") && dbus_error_has_name(&error, DBUS_ERROR_NO_REPLY)) {
3566 /* On reexecution, we expect a disconnect, not
3572 log_error("Failed to issue method call: %s", bus_error_message(&error));
3581 dbus_message_unref(m);
3584 dbus_message_unref(reply);
3586 dbus_error_free(&error);
3591 static int reset_failed(DBusConnection *bus, char **args) {
3592 DBusMessage *m = NULL;
3598 dbus_error_init(&error);
3600 if (strv_length(args) <= 1)
3601 return daemon_reload(bus, args);
3603 STRV_FOREACH(name, args+1) {
3606 if (!(m = dbus_message_new_method_call(
3607 "org.freedesktop.systemd1",
3608 "/org/freedesktop/systemd1",
3609 "org.freedesktop.systemd1.Manager",
3610 "ResetFailedUnit"))) {
3611 log_error("Could not allocate message.");
3616 if (!dbus_message_append_args(m,
3617 DBUS_TYPE_STRING, name,
3618 DBUS_TYPE_INVALID)) {
3619 log_error("Could not append arguments to message.");
3624 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3625 log_error("Failed to issue method call: %s", bus_error_message(&error));
3630 dbus_message_unref(m);
3631 dbus_message_unref(reply);
3639 dbus_message_unref(m);
3641 dbus_error_free(&error);
3646 static int show_enviroment(DBusConnection *bus, char **args) {
3647 DBusMessage *m = NULL, *reply = NULL;
3649 DBusMessageIter iter, sub, sub2;
3652 *interface = "org.freedesktop.systemd1.Manager",
3653 *property = "Environment";
3655 dbus_error_init(&error);
3657 pager_open_if_enabled();
3659 if (!(m = dbus_message_new_method_call(
3660 "org.freedesktop.systemd1",
3661 "/org/freedesktop/systemd1",
3662 "org.freedesktop.DBus.Properties",
3664 log_error("Could not allocate message.");
3668 if (!dbus_message_append_args(m,
3669 DBUS_TYPE_STRING, &interface,
3670 DBUS_TYPE_STRING, &property,
3671 DBUS_TYPE_INVALID)) {
3672 log_error("Could not append arguments to message.");
3677 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3678 log_error("Failed to issue method call: %s", bus_error_message(&error));
3683 if (!dbus_message_iter_init(reply, &iter) ||
3684 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3685 log_error("Failed to parse reply.");
3690 dbus_message_iter_recurse(&iter, &sub);
3692 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_ARRAY ||
3693 dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_STRING) {
3694 log_error("Failed to parse reply.");
3699 dbus_message_iter_recurse(&sub, &sub2);
3701 while (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_INVALID) {
3704 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
3705 log_error("Failed to parse reply.");
3710 dbus_message_iter_get_basic(&sub2, &text);
3711 printf("%s\n", text);
3713 dbus_message_iter_next(&sub2);
3720 dbus_message_unref(m);
3723 dbus_message_unref(reply);
3725 dbus_error_free(&error);
3730 static int switch_root(DBusConnection *bus, char **args) {
3731 DBusMessage *m = NULL, *reply = NULL;
3733 const char *root, *init;
3737 dbus_error_init(&error);
3739 l = strv_length(args);
3740 if (l < 2 || l > 3) {
3741 log_error("Wrong number of arguments.");
3746 init = l >= 3 ? args[2] : "";
3748 m = dbus_message_new_method_call(
3749 "org.freedesktop.systemd1",
3750 "/org/freedesktop/systemd1",
3751 "org.freedesktop.systemd1.Manager",
3754 log_error("Could not allocate message.");
3758 if (!dbus_message_append_args(
3760 DBUS_TYPE_STRING, &root,
3761 DBUS_TYPE_STRING, &init,
3762 DBUS_TYPE_INVALID)) {
3763 log_error("Could not append arguments to message.");
3768 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3770 log_error("Failed to issue method call: %s", bus_error_message(&error));
3779 dbus_message_unref(m);
3782 dbus_message_unref(reply);
3784 dbus_error_free(&error);
3789 static int set_environment(DBusConnection *bus, char **args) {
3790 DBusMessage *m = NULL, *reply = NULL;
3794 DBusMessageIter iter, sub;
3797 dbus_error_init(&error);
3799 method = streq(args[0], "set-environment")
3801 : "UnsetEnvironment";
3803 if (!(m = dbus_message_new_method_call(
3804 "org.freedesktop.systemd1",
3805 "/org/freedesktop/systemd1",
3806 "org.freedesktop.systemd1.Manager",
3809 log_error("Could not allocate message.");
3813 dbus_message_iter_init_append(m, &iter);
3815 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub)) {
3816 log_error("Could not append arguments to message.");
3821 STRV_FOREACH(name, args+1)
3822 if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, name)) {
3823 log_error("Could not append arguments to message.");
3828 if (!dbus_message_iter_close_container(&iter, &sub)) {
3829 log_error("Could not append arguments to message.");
3834 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3835 log_error("Failed to issue method call: %s", bus_error_message(&error));
3844 dbus_message_unref(m);
3847 dbus_message_unref(reply);
3849 dbus_error_free(&error);
3854 static int enable_sysv_units(char **args) {
3857 #if defined (HAVE_SYSV_COMPAT) && (defined(TARGET_FEDORA) || defined(TARGET_MANDRIVA) || defined(TARGET_SUSE) || defined(TARGET_MEEGO) || defined(TARGET_ALTLINUX) || defined(TARGET_MAGEIA))
3858 const char *verb = args[0];
3859 unsigned f = 1, t = 1;
3862 if (arg_scope != UNIT_FILE_SYSTEM)
3865 if (!streq(verb, "enable") &&
3866 !streq(verb, "disable") &&
3867 !streq(verb, "is-enabled"))
3870 /* Processes all SysV units, and reshuffles the array so that
3871 * afterwards only the native units remain */
3874 r = lookup_paths_init(&paths, MANAGER_SYSTEM, false, NULL, NULL, NULL);
3879 for (f = 1; args[f]; f++) {
3882 bool found_native = false, found_sysv;
3884 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
3885 char **k, *l, *q = NULL;
3892 if (!endswith(name, ".service"))
3895 if (path_is_absolute(name))
3898 STRV_FOREACH(k, paths.unit_path) {
3901 if (!isempty(arg_root))
3902 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
3904 asprintf(&p, "%s/%s", *k, name);
3907 log_error("No memory");
3912 found_native = access(p, F_OK) >= 0;
3923 if (!isempty(arg_root))
3924 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
3926 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
3928 log_error("No memory");
3933 p[strlen(p) - sizeof(".service") + 1] = 0;
3934 found_sysv = access(p, F_OK) >= 0;
3941 /* Mark this entry, so that we don't try enabling it as native unit */
3942 args[f] = (char*) "";
3944 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
3946 if (!isempty(arg_root))
3947 argv[c++] = q = strappend("--root=", arg_root);
3949 argv[c++] = path_get_file_name(p);
3951 streq(verb, "enable") ? "on" :
3952 streq(verb, "disable") ? "off" : "--level=5";
3955 l = strv_join((char**)argv, " ");
3957 log_error("No memory.");
3964 log_info("Executing %s", l);
3969 log_error("Failed to fork: %m");
3974 } else if (pid == 0) {
3977 execv(argv[0], (char**) argv);
3978 _exit(EXIT_FAILURE);
3984 j = wait_for_terminate(pid, &status);
3986 log_error("Failed to wait for child: %s", strerror(-r));
3991 if (status.si_code == CLD_EXITED) {
3992 if (streq(verb, "is-enabled")) {
3993 if (status.si_status == 0) {
4002 } else if (status.si_status != 0) {
4013 lookup_paths_free(&paths);
4015 /* Drop all SysV units */
4016 for (f = 1, t = 1; args[f]; f++) {
4018 if (isempty(args[f]))
4021 args[t++] = args[f];
4030 static int enable_unit(DBusConnection *bus, char **args) {
4031 const char *verb = args[0];
4032 UnitFileChange *changes = NULL;
4033 unsigned n_changes = 0, i;
4034 int carries_install_info = -1;
4035 DBusMessage *m = NULL, *reply = NULL;
4039 r = enable_sysv_units(args);
4046 dbus_error_init(&error);
4048 if (!bus || avoid_bus()) {
4049 if (streq(verb, "enable")) {
4050 r = unit_file_enable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
4051 carries_install_info = r;
4052 } else if (streq(verb, "disable"))
4053 r = unit_file_disable(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
4054 else if (streq(verb, "reenable")) {
4055 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
4056 carries_install_info = r;
4057 } else if (streq(verb, "link"))
4058 r = unit_file_link(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
4059 else if (streq(verb, "preset")) {
4060 r = unit_file_preset(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
4061 carries_install_info = r;
4062 } else if (streq(verb, "mask"))
4063 r = unit_file_mask(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
4064 else if (streq(verb, "unmask"))
4065 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
4067 assert_not_reached("Unknown verb");
4070 log_error("Operation failed: %s", strerror(-r));
4075 for (i = 0; i < n_changes; i++) {
4076 if (changes[i].type == UNIT_FILE_SYMLINK)
4077 log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
4079 log_info("rm '%s'", changes[i].path);
4085 bool send_force = true, expect_carries_install_info = false;
4087 DBusMessageIter iter, sub, sub2;
4089 if (streq(verb, "enable")) {
4090 method = "EnableUnitFiles";
4091 expect_carries_install_info = true;
4092 } else if (streq(verb, "disable")) {
4093 method = "DisableUnitFiles";
4095 } else if (streq(verb, "reenable")) {
4096 method = "ReenableUnitFiles";
4097 expect_carries_install_info = true;
4098 } else if (streq(verb, "link"))
4099 method = "LinkUnitFiles";
4100 else if (streq(verb, "preset")) {
4101 method = "PresetUnitFiles";
4102 expect_carries_install_info = true;
4103 } else if (streq(verb, "mask"))
4104 method = "MaskUnitFiles";
4105 else if (streq(verb, "unmask")) {
4106 method = "UnmaskUnitFiles";
4109 assert_not_reached("Unknown verb");
4111 m = dbus_message_new_method_call(
4112 "org.freedesktop.systemd1",
4113 "/org/freedesktop/systemd1",
4114 "org.freedesktop.systemd1.Manager",
4117 log_error("Out of memory");
4122 dbus_message_iter_init_append(m, &iter);
4124 r = bus_append_strv_iter(&iter, args+1);
4126 log_error("Failed to append unit files.");
4131 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &a)) {
4132 log_error("Failed to append runtime boolean.");
4140 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b)) {
4141 log_error("Failed to append force boolean.");
4147 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
4149 log_error("Failed to issue method call: %s", bus_error_message(&error));
4154 if (!dbus_message_iter_init(reply, &iter)) {
4155 log_error("Failed to initialize iterator.");
4159 if (expect_carries_install_info) {
4160 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &b, true);
4162 log_error("Failed to parse reply.");
4166 carries_install_info = b;
4169 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
4170 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
4171 log_error("Failed to parse reply.");
4176 dbus_message_iter_recurse(&iter, &sub);
4177 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
4178 const char *type, *path, *source;
4180 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
4181 log_error("Failed to parse reply.");
4186 dbus_message_iter_recurse(&sub, &sub2);
4188 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
4189 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
4190 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &source, false) < 0) {
4191 log_error("Failed to parse reply.");
4197 if (streq(type, "symlink"))
4198 log_info("ln -s '%s' '%s'", source, path);
4200 log_info("rm '%s'", path);
4203 dbus_message_iter_next(&sub);
4206 /* Try to reload if enabeld */
4208 r = daemon_reload(bus, args);
4211 if (carries_install_info == 0)
4212 log_warning("The unit files have no [Install] section. They are not meant to be enabled using systemctl.");
4216 dbus_message_unref(m);
4219 dbus_message_unref(reply);
4221 unit_file_changes_free(changes, n_changes);
4223 dbus_error_free(&error);
4227 static int unit_is_enabled(DBusConnection *bus, char **args) {
4230 DBusMessage *m = NULL, *reply = NULL;
4234 dbus_error_init(&error);
4236 r = enable_sysv_units(args);
4242 if (!bus || avoid_bus()) {
4244 STRV_FOREACH(name, args+1) {
4245 UnitFileState state;
4247 state = unit_file_get_state(arg_scope, arg_root, *name);
4253 if (state == UNIT_FILE_ENABLED ||
4254 state == UNIT_FILE_ENABLED_RUNTIME ||
4255 state == UNIT_FILE_STATIC)
4259 puts(unit_file_state_to_string(state));
4263 STRV_FOREACH(name, args+1) {
4266 m = dbus_message_new_method_call(
4267 "org.freedesktop.systemd1",
4268 "/org/freedesktop/systemd1",
4269 "org.freedesktop.systemd1.Manager",
4270 "GetUnitFileState");
4272 log_error("Out of memory");
4277 if (!dbus_message_append_args(m,
4278 DBUS_TYPE_STRING, name,
4279 DBUS_TYPE_INVALID)) {
4280 log_error("Could not append arguments to message.");
4285 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
4287 log_error("Failed to issue method call: %s", bus_error_message(&error));
4292 if (!dbus_message_get_args(reply, &error,
4293 DBUS_TYPE_STRING, &s,
4294 DBUS_TYPE_INVALID)) {
4295 log_error("Failed to parse reply: %s", bus_error_message(&error));
4300 dbus_message_unref(m);
4301 dbus_message_unref(reply);
4304 if (streq(s, "enabled") ||
4305 streq(s, "enabled-runtime") ||
4314 r = enabled ? 0 : 1;
4318 dbus_message_unref(m);
4321 dbus_message_unref(reply);
4323 dbus_error_free(&error);
4327 static int systemctl_help(void) {
4329 pager_open_if_enabled();
4331 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
4332 "Query or send control commands to the systemd manager.\n\n"
4333 " -h --help Show this help\n"
4334 " --version Show package version\n"
4335 " -t --type=TYPE List only units of a particular type\n"
4336 " -p --property=NAME Show only properties by this name\n"
4337 " -a --all Show all units/properties, including dead/empty ones\n"
4338 " --failed Show only failed units\n"
4339 " --full Don't ellipsize unit names on output\n"
4340 " --fail When queueing a new job, fail if conflicting jobs are\n"
4342 " --ignore-dependencies\n"
4343 " When queueing a new job, ignore all its dependencies\n"
4344 " --kill-who=WHO Who to send signal to\n"
4345 " -s --signal=SIGNAL Which signal to send\n"
4346 " -H --host=[USER@]HOST\n"
4347 " Show information for remote host\n"
4348 " -P --privileged Acquire privileges before execution\n"
4349 " -q --quiet Suppress output\n"
4350 " --no-block Do not wait until operation finished\n"
4351 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4352 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
4354 " --no-legend Do not print a legend (column headers and hints)\n"
4355 " --no-pager Do not pipe output into a pager\n"
4356 " --no-ask-password\n"
4357 " Do not ask for system passwords\n"
4358 " --order When generating graph for dot, show only order\n"
4359 " --require When generating graph for dot, show only requirement\n"
4360 " --system Connect to system manager\n"
4361 " --user Connect to user service manager\n"
4362 " --global Enable/disable unit files globally\n"
4363 " -f --force When enabling unit files, override existing symlinks\n"
4364 " When shutting down, execute action immediately\n"
4365 " --root=PATH Enable unit files in the specified root directory\n"
4366 " --runtime Enable unit files only temporarily until next reboot\n"
4367 " -n --lines=INTEGER Journal entries to show\n"
4368 " --follow Follow journal\n"
4369 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
4370 " verbose, export, json, cat)\n\n"
4372 " list-units List loaded units\n"
4373 " start [NAME...] Start (activate) one or more units\n"
4374 " stop [NAME...] Stop (deactivate) one or more units\n"
4375 " reload [NAME...] Reload one or more units\n"
4376 " restart [NAME...] Start or restart one or more units\n"
4377 " try-restart [NAME...] Restart one or more units if active\n"
4378 " reload-or-restart [NAME...] Reload one or more units is possible,\n"
4379 " otherwise start or restart\n"
4380 " reload-or-try-restart [NAME...] Reload one or more units is possible,\n"
4381 " otherwise restart if active\n"
4382 " isolate [NAME] Start one unit and stop all others\n"
4383 " kill [NAME...] Send signal to processes of a unit\n"
4384 " is-active [NAME...] Check whether units are active\n"
4385 " status [NAME...|PID...] Show runtime status of one or more units\n"
4386 " show [NAME...|JOB...] Show properties of one or more\n"
4387 " units/jobs or the manager\n"
4388 " help [NAME...|PID...] Show manual for one or more units\n"
4389 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
4391 " load [NAME...] Load one or more units\n\n"
4392 "Unit File Commands:\n"
4393 " list-unit-files List installed unit files\n"
4394 " enable [NAME...] Enable one or more unit files\n"
4395 " disable [NAME...] Disable one or more unit files\n"
4396 " reenable [NAME...] Reenable one or more unit files\n"
4397 " preset [NAME...] Enable/disable one or more unit files\n"
4398 " based on preset configuration\n"
4399 " mask [NAME...] Mask one or more units\n"
4400 " unmask [NAME...] Unmask one or more units\n"
4401 " link [PATH...] Link one or more units files into\n"
4402 " the search path\n"
4403 " is-enabled [NAME...] Check whether unit files are enabled\n\n"
4405 " list-jobs List jobs\n"
4406 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
4407 "Status Commands:\n"
4408 " dump Dump server status\n"
4409 " dot Dump dependency graph for dot(1)\n\n"
4410 "Snapshot Commands:\n"
4411 " snapshot [NAME] Create a snapshot\n"
4412 " delete [NAME...] Remove one or more snapshots\n\n"
4413 "Environment Commands:\n"
4414 " show-environment Dump environment\n"
4415 " set-environment [NAME=VALUE...] Set one or more environment variables\n"
4416 " unset-environment [NAME...] Unset one or more environment variables\n\n"
4417 "Manager Lifecycle Commands:\n"
4418 " daemon-reload Reload systemd manager configuration\n"
4419 " daemon-reexec Reexecute systemd manager\n\n"
4420 "System Commands:\n"
4421 " default Enter system default mode\n"
4422 " rescue Enter system rescue mode\n"
4423 " emergency Enter system emergency mode\n"
4424 " halt Shut down and halt the system\n"
4425 " poweroff Shut down and power-off the system\n"
4426 " reboot Shut down and reboot the system\n"
4427 " kexec Shut down and reboot the system with kexec\n"
4428 " exit Request user instance exit\n"
4429 " switch-root [ROOT] [INIT] Change to a different root file system\n"
4430 " suspend Suspend the system\n"
4431 " hibernate Hibernate the system\n",
4432 program_invocation_short_name);
4437 static int halt_help(void) {
4439 printf("%s [OPTIONS...]\n\n"
4440 "%s the system.\n\n"
4441 " --help Show this help\n"
4442 " --halt Halt the machine\n"
4443 " -p --poweroff Switch off the machine\n"
4444 " --reboot Reboot the machine\n"
4445 " -f --force Force immediate halt/power-off/reboot\n"
4446 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
4447 " -d --no-wtmp Don't write wtmp record\n"
4448 " -n --no-sync Don't sync before halt/power-off/reboot\n"
4449 " --no-wall Don't send wall message before halt/power-off/reboot\n",
4450 program_invocation_short_name,
4451 arg_action == ACTION_REBOOT ? "Reboot" :
4452 arg_action == ACTION_POWEROFF ? "Power off" :
4458 static int shutdown_help(void) {
4460 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
4461 "Shut down the system.\n\n"
4462 " --help Show this help\n"
4463 " -H --halt Halt the machine\n"
4464 " -P --poweroff Power-off the machine\n"
4465 " -r --reboot Reboot the machine\n"
4466 " -h Equivalent to --poweroff, overridden by --halt\n"
4467 " -k Don't halt/power-off/reboot, just send warnings\n"
4468 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4469 " -c Cancel a pending shutdown\n",
4470 program_invocation_short_name);
4475 static int telinit_help(void) {
4477 printf("%s [OPTIONS...] {COMMAND}\n\n"
4478 "Send control commands to the init daemon.\n\n"
4479 " --help Show this help\n"
4480 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
4482 " 0 Power-off the machine\n"
4483 " 6 Reboot the machine\n"
4484 " 2, 3, 4, 5 Start runlevelX.target unit\n"
4485 " 1, s, S Enter rescue mode\n"
4486 " q, Q Reload init daemon configuration\n"
4487 " u, U Reexecute init daemon\n",
4488 program_invocation_short_name);
4493 static int runlevel_help(void) {
4495 printf("%s [OPTIONS...]\n\n"
4496 "Prints the previous and current runlevel of the init system.\n\n"
4497 " --help Show this help\n",
4498 program_invocation_short_name);
4503 static int systemctl_parse_argv(int argc, char *argv[]) {
4507 ARG_IGNORE_DEPENDENCIES,
4523 ARG_NO_ASK_PASSWORD,
4530 static const struct option options[] = {
4531 { "help", no_argument, NULL, 'h' },
4532 { "version", no_argument, NULL, ARG_VERSION },
4533 { "type", required_argument, NULL, 't' },
4534 { "property", required_argument, NULL, 'p' },
4535 { "all", no_argument, NULL, 'a' },
4536 { "failed", no_argument, NULL, ARG_FAILED },
4537 { "full", no_argument, NULL, ARG_FULL },
4538 { "fail", no_argument, NULL, ARG_FAIL },
4539 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
4540 { "user", no_argument, NULL, ARG_USER },
4541 { "system", no_argument, NULL, ARG_SYSTEM },
4542 { "global", no_argument, NULL, ARG_GLOBAL },
4543 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
4544 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
4545 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
4546 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4547 { "quiet", no_argument, NULL, 'q' },
4548 { "order", no_argument, NULL, ARG_ORDER },
4549 { "require", no_argument, NULL, ARG_REQUIRE },
4550 { "root", required_argument, NULL, ARG_ROOT },
4551 { "force", no_argument, NULL, ARG_FORCE },
4552 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
4553 { "kill-mode", required_argument, NULL, ARG_KILL_MODE }, /* undocumented on purpose */
4554 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
4555 { "signal", required_argument, NULL, 's' },
4556 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
4557 { "host", required_argument, NULL, 'H' },
4558 { "privileged",no_argument, NULL, 'P' },
4559 { "runtime", no_argument, NULL, ARG_RUNTIME },
4560 { "lines", required_argument, NULL, 'n' },
4561 { "follow", no_argument, NULL, ARG_FOLLOW },
4562 { "output", required_argument, NULL, 'o' },
4563 { NULL, 0, NULL, 0 }
4571 while ((c = getopt_long(argc, argv, "ht:p:aqfs:H:Pn:o:", options, NULL)) >= 0) {
4580 puts(PACKAGE_STRING);
4582 puts(SYSTEMD_FEATURES);
4592 if (!(l = strv_append(arg_property, optarg)))
4595 strv_free(arg_property);
4598 /* If the user asked for a particular
4599 * property, show it to him, even if it is
4610 arg_job_mode = "fail";
4613 case ARG_IGNORE_DEPENDENCIES:
4614 arg_job_mode = "ignore-dependencies";
4618 arg_scope = UNIT_FILE_USER;
4622 arg_scope = UNIT_FILE_SYSTEM;
4626 arg_scope = UNIT_FILE_GLOBAL;
4630 arg_no_block = true;
4634 arg_no_legend = true;
4638 arg_no_pager = true;
4646 arg_dot = DOT_ORDER;
4650 arg_dot = DOT_REQUIRE;
4678 /* -f is short for both --follow and --force! */
4684 arg_no_reload = true;
4688 arg_kill_who = optarg;
4692 arg_kill_mode = optarg;
4696 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
4697 log_error("Failed to parse signal string %s.", optarg);
4702 case ARG_NO_ASK_PASSWORD:
4703 arg_ask_password = false;
4707 arg_transport = TRANSPORT_POLKIT;
4711 arg_transport = TRANSPORT_SSH;
4720 if (safe_atou(optarg, &arg_lines) < 0) {
4721 log_error("Failed to parse lines '%s'", optarg);
4727 arg_output = output_mode_from_string(optarg);
4728 if (arg_output < 0) {
4729 log_error("Unknown output '%s'.", optarg);
4738 log_error("Unknown option code %c", c);
4743 if (arg_transport != TRANSPORT_NORMAL && arg_scope != UNIT_FILE_SYSTEM) {
4744 log_error("Cannot access user instance remotely.");
4751 static int halt_parse_argv(int argc, char *argv[]) {
4760 static const struct option options[] = {
4761 { "help", no_argument, NULL, ARG_HELP },
4762 { "halt", no_argument, NULL, ARG_HALT },
4763 { "poweroff", no_argument, NULL, 'p' },
4764 { "reboot", no_argument, NULL, ARG_REBOOT },
4765 { "force", no_argument, NULL, 'f' },
4766 { "wtmp-only", no_argument, NULL, 'w' },
4767 { "no-wtmp", no_argument, NULL, 'd' },
4768 { "no-sync", no_argument, NULL, 'n' },
4769 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4770 { NULL, 0, NULL, 0 }
4778 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
4779 if (runlevel == '0' || runlevel == '6')
4782 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
4790 arg_action = ACTION_HALT;
4794 if (arg_action != ACTION_REBOOT)
4795 arg_action = ACTION_POWEROFF;
4799 arg_action = ACTION_REBOOT;
4824 /* Compatibility nops */
4831 log_error("Unknown option code %c", c);
4836 if (optind < argc) {
4837 log_error("Too many arguments.");
4844 static int parse_time_spec(const char *t, usec_t *_u) {
4848 if (streq(t, "now"))
4850 else if (!strchr(t, ':')) {
4853 if (safe_atou64(t, &u) < 0)
4856 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
4865 hour = strtol(t, &e, 10);
4866 if (errno != 0 || *e != ':' || hour < 0 || hour > 23)
4869 minute = strtol(e+1, &e, 10);
4870 if (errno != 0 || *e != 0 || minute < 0 || minute > 59)
4873 n = now(CLOCK_REALTIME);
4874 s = (time_t) (n / USEC_PER_SEC);
4877 assert_se(localtime_r(&s, &tm));
4879 tm.tm_hour = (int) hour;
4880 tm.tm_min = (int) minute;
4883 assert_se(s = mktime(&tm));
4885 *_u = (usec_t) s * USEC_PER_SEC;
4888 *_u += USEC_PER_DAY;
4894 static int shutdown_parse_argv(int argc, char *argv[]) {
4901 static const struct option options[] = {
4902 { "help", no_argument, NULL, ARG_HELP },
4903 { "halt", no_argument, NULL, 'H' },
4904 { "poweroff", no_argument, NULL, 'P' },
4905 { "reboot", no_argument, NULL, 'r' },
4906 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
4907 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4908 { NULL, 0, NULL, 0 }
4916 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
4924 arg_action = ACTION_HALT;
4928 arg_action = ACTION_POWEROFF;
4933 arg_action = ACTION_KEXEC;
4935 arg_action = ACTION_REBOOT;
4939 arg_action = ACTION_KEXEC;
4943 if (arg_action != ACTION_HALT)
4944 arg_action = ACTION_POWEROFF;
4957 /* Compatibility nops */
4961 arg_action = ACTION_CANCEL_SHUTDOWN;
4968 log_error("Unknown option code %c", c);
4973 if (argc > optind) {
4974 r = parse_time_spec(argv[optind], &arg_when);
4976 log_error("Failed to parse time specification: %s", argv[optind]);
4980 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
4982 /* We skip the time argument */
4983 if (argc > optind + 1)
4984 arg_wall = argv + optind + 1;
4991 static int telinit_parse_argv(int argc, char *argv[]) {
4998 static const struct option options[] = {
4999 { "help", no_argument, NULL, ARG_HELP },
5000 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5001 { NULL, 0, NULL, 0 }
5004 static const struct {
5008 { '0', ACTION_POWEROFF },
5009 { '6', ACTION_REBOOT },
5010 { '1', ACTION_RESCUE },
5011 { '2', ACTION_RUNLEVEL2 },
5012 { '3', ACTION_RUNLEVEL3 },
5013 { '4', ACTION_RUNLEVEL4 },
5014 { '5', ACTION_RUNLEVEL5 },
5015 { 's', ACTION_RESCUE },
5016 { 'S', ACTION_RESCUE },
5017 { 'q', ACTION_RELOAD },
5018 { 'Q', ACTION_RELOAD },
5019 { 'u', ACTION_REEXEC },
5020 { 'U', ACTION_REEXEC }
5029 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
5044 log_error("Unknown option code %c", c);
5049 if (optind >= argc) {
5054 if (optind + 1 < argc) {
5055 log_error("Too many arguments.");
5059 if (strlen(argv[optind]) != 1) {
5060 log_error("Expected single character argument.");
5064 for (i = 0; i < ELEMENTSOF(table); i++)
5065 if (table[i].from == argv[optind][0])
5068 if (i >= ELEMENTSOF(table)) {
5069 log_error("Unknown command %s.", argv[optind]);
5073 arg_action = table[i].to;
5080 static int runlevel_parse_argv(int argc, char *argv[]) {
5086 static const struct option options[] = {
5087 { "help", no_argument, NULL, ARG_HELP },
5088 { NULL, 0, NULL, 0 }
5096 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
5107 log_error("Unknown option code %c", c);
5112 if (optind < argc) {
5113 log_error("Too many arguments.");
5120 static int parse_argv(int argc, char *argv[]) {
5124 if (program_invocation_short_name) {
5126 if (strstr(program_invocation_short_name, "halt")) {
5127 arg_action = ACTION_HALT;
5128 return halt_parse_argv(argc, argv);
5129 } else if (strstr(program_invocation_short_name, "poweroff")) {
5130 arg_action = ACTION_POWEROFF;
5131 return halt_parse_argv(argc, argv);
5132 } else if (strstr(program_invocation_short_name, "reboot")) {
5134 arg_action = ACTION_KEXEC;
5136 arg_action = ACTION_REBOOT;
5137 return halt_parse_argv(argc, argv);
5138 } else if (strstr(program_invocation_short_name, "shutdown")) {
5139 arg_action = ACTION_POWEROFF;
5140 return shutdown_parse_argv(argc, argv);
5141 } else if (strstr(program_invocation_short_name, "init")) {
5143 if (sd_booted() > 0) {
5144 arg_action = ACTION_INVALID;
5145 return telinit_parse_argv(argc, argv);
5147 /* Hmm, so some other init system is
5148 * running, we need to forward this
5149 * request to it. For now we simply
5150 * guess that it is Upstart. */
5152 execv("/lib/upstart/telinit", argv);
5154 log_error("Couldn't find an alternative telinit implementation to spawn.");
5158 } else if (strstr(program_invocation_short_name, "runlevel")) {
5159 arg_action = ACTION_RUNLEVEL;
5160 return runlevel_parse_argv(argc, argv);
5164 arg_action = ACTION_SYSTEMCTL;
5165 return systemctl_parse_argv(argc, argv);
5168 static int action_to_runlevel(void) {
5170 static const char table[_ACTION_MAX] = {
5171 [ACTION_HALT] = '0',
5172 [ACTION_POWEROFF] = '0',
5173 [ACTION_REBOOT] = '6',
5174 [ACTION_RUNLEVEL2] = '2',
5175 [ACTION_RUNLEVEL3] = '3',
5176 [ACTION_RUNLEVEL4] = '4',
5177 [ACTION_RUNLEVEL5] = '5',
5178 [ACTION_RESCUE] = '1'
5181 assert(arg_action < _ACTION_MAX);
5183 return table[arg_action];
5186 static int talk_upstart(void) {
5187 DBusMessage *m = NULL, *reply = NULL;
5189 int previous, rl, r;
5191 env1_buf[] = "RUNLEVEL=X",
5192 env2_buf[] = "PREVLEVEL=X";
5193 char *env1 = env1_buf, *env2 = env2_buf;
5194 const char *emit = "runlevel";
5195 dbus_bool_t b_false = FALSE;
5196 DBusMessageIter iter, sub;
5197 DBusConnection *bus;
5199 dbus_error_init(&error);
5201 if (!(rl = action_to_runlevel()))
5204 if (utmp_get_runlevel(&previous, NULL) < 0)
5207 if (!(bus = dbus_connection_open_private("unix:abstract=/com/ubuntu/upstart", &error))) {
5208 if (dbus_error_has_name(&error, DBUS_ERROR_NO_SERVER)) {
5213 log_error("Failed to connect to Upstart bus: %s", bus_error_message(&error));
5218 if ((r = bus_check_peercred(bus)) < 0) {
5219 log_error("Failed to verify owner of bus.");
5223 if (!(m = dbus_message_new_method_call(
5224 "com.ubuntu.Upstart",
5225 "/com/ubuntu/Upstart",
5226 "com.ubuntu.Upstart0_6",
5229 log_error("Could not allocate message.");
5234 dbus_message_iter_init_append(m, &iter);
5236 env1_buf[sizeof(env1_buf)-2] = rl;
5237 env2_buf[sizeof(env2_buf)-2] = previous;
5239 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &emit) ||
5240 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub) ||
5241 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env1) ||
5242 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env2) ||
5243 !dbus_message_iter_close_container(&iter, &sub) ||
5244 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b_false)) {
5245 log_error("Could not append arguments to message.");
5250 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
5252 if (error_is_no_service(&error)) {
5257 log_error("Failed to issue method call: %s", bus_error_message(&error));
5266 dbus_message_unref(m);
5269 dbus_message_unref(reply);
5272 dbus_connection_flush(bus);
5273 dbus_connection_close(bus);
5274 dbus_connection_unref(bus);
5277 dbus_error_free(&error);
5282 static int talk_initctl(void) {
5283 struct init_request request;
5287 if (!(rl = action_to_runlevel()))
5291 request.magic = INIT_MAGIC;
5292 request.sleeptime = 0;
5293 request.cmd = INIT_CMD_RUNLVL;
5294 request.runlevel = rl;
5296 if ((fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY)) < 0) {
5298 if (errno == ENOENT)
5301 log_error("Failed to open "INIT_FIFO": %m");
5306 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
5307 close_nointr_nofail(fd);
5310 log_error("Failed to write to "INIT_FIFO": %m");
5311 return errno ? -errno : -EIO;
5317 static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
5319 static const struct {
5327 int (* const dispatch)(DBusConnection *bus, char **args);
5329 { "list-units", LESS, 1, list_units },
5330 { "list-unit-files", EQUAL, 1, list_unit_files },
5331 { "list-jobs", EQUAL, 1, list_jobs },
5332 { "clear-jobs", EQUAL, 1, daemon_reload },
5333 { "load", MORE, 2, load_unit },
5334 { "cancel", MORE, 2, cancel_job },
5335 { "start", MORE, 2, start_unit },
5336 { "stop", MORE, 2, start_unit },
5337 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5338 { "reload", MORE, 2, start_unit },
5339 { "restart", MORE, 2, start_unit },
5340 { "try-restart", MORE, 2, start_unit },
5341 { "reload-or-restart", MORE, 2, start_unit },
5342 { "reload-or-try-restart", MORE, 2, start_unit },
5343 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
5344 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5345 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
5346 { "isolate", EQUAL, 2, start_unit },
5347 { "kill", MORE, 2, kill_unit },
5348 { "is-active", MORE, 2, check_unit },
5349 { "check", MORE, 2, check_unit },
5350 { "show", MORE, 1, show },
5351 { "status", MORE, 2, show },
5352 { "help", MORE, 2, show },
5353 { "dump", EQUAL, 1, dump },
5354 { "dot", EQUAL, 1, dot },
5355 { "snapshot", LESS, 2, snapshot },
5356 { "delete", MORE, 2, delete_snapshot },
5357 { "daemon-reload", EQUAL, 1, daemon_reload },
5358 { "daemon-reexec", EQUAL, 1, daemon_reload },
5359 { "show-environment", EQUAL, 1, show_enviroment },
5360 { "set-environment", MORE, 2, set_environment },
5361 { "unset-environment", MORE, 2, set_environment },
5362 { "halt", EQUAL, 1, start_special },
5363 { "poweroff", EQUAL, 1, start_special },
5364 { "reboot", EQUAL, 1, start_special },
5365 { "kexec", EQUAL, 1, start_special },
5366 { "suspend", EQUAL, 1, start_special },
5367 { "hibernate", EQUAL, 1, start_special },
5368 { "default", EQUAL, 1, start_special },
5369 { "rescue", EQUAL, 1, start_special },
5370 { "emergency", EQUAL, 1, start_special },
5371 { "exit", EQUAL, 1, start_special },
5372 { "reset-failed", MORE, 1, reset_failed },
5373 { "enable", MORE, 2, enable_unit },
5374 { "disable", MORE, 2, enable_unit },
5375 { "is-enabled", MORE, 2, unit_is_enabled },
5376 { "reenable", MORE, 2, enable_unit },
5377 { "preset", MORE, 2, enable_unit },
5378 { "mask", MORE, 2, enable_unit },
5379 { "unmask", MORE, 2, enable_unit },
5380 { "link", MORE, 2, enable_unit },
5381 { "switch-root", MORE, 2, switch_root },
5391 left = argc - optind;
5394 /* Special rule: no arguments means "list-units" */
5397 if (streq(argv[optind], "help") && !argv[optind+1]) {
5398 log_error("This command expects one or more "
5399 "unit names. Did you mean --help?");
5403 for (i = 0; i < ELEMENTSOF(verbs); i++)
5404 if (streq(argv[optind], verbs[i].verb))
5407 if (i >= ELEMENTSOF(verbs)) {
5408 log_error("Unknown operation %s", argv[optind]);
5413 switch (verbs[i].argc_cmp) {
5416 if (left != verbs[i].argc) {
5417 log_error("Invalid number of arguments.");
5424 if (left < verbs[i].argc) {
5425 log_error("Too few arguments.");
5432 if (left > verbs[i].argc) {
5433 log_error("Too many arguments.");
5440 assert_not_reached("Unknown comparison operator.");
5443 /* Require a bus connection for all operations but
5445 if (!streq(verbs[i].verb, "enable") &&
5446 !streq(verbs[i].verb, "disable") &&
5447 !streq(verbs[i].verb, "is-enabled") &&
5448 !streq(verbs[i].verb, "list-unit-files") &&
5449 !streq(verbs[i].verb, "reenable") &&
5450 !streq(verbs[i].verb, "preset") &&
5451 !streq(verbs[i].verb, "mask") &&
5452 !streq(verbs[i].verb, "unmask") &&
5453 !streq(verbs[i].verb, "link")) {
5455 if (running_in_chroot() > 0) {
5456 log_info("Running in chroot, ignoring request.");
5460 if (((!streq(verbs[i].verb, "reboot") &&
5461 !streq(verbs[i].verb, "halt") &&
5462 !streq(verbs[i].verb, "poweroff")) || arg_force <= 0) && !bus) {
5463 log_error("Failed to get D-Bus connection: %s",
5464 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5470 if (!bus && !avoid_bus()) {
5471 log_error("Failed to get D-Bus connection: %s",
5472 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5477 return verbs[i].dispatch(bus, argv + optind);
5480 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
5482 struct msghdr msghdr;
5483 struct iovec iovec[2];
5484 union sockaddr_union sockaddr;
5485 struct sd_shutdown_command c;
5487 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
5494 c.dry_run = dry_run;
5498 sockaddr.sa.sa_family = AF_UNIX;
5499 strncpy(sockaddr.un.sun_path, "/run/systemd/shutdownd", sizeof(sockaddr.un.sun_path));
5502 msghdr.msg_name = &sockaddr;
5503 msghdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + sizeof("/run/systemd/shutdownd") - 1;
5506 iovec[0].iov_base = (char*) &c;
5507 iovec[0].iov_len = offsetof(struct sd_shutdown_command, wall_message);
5509 if (isempty(message))
5510 msghdr.msg_iovlen = 1;
5512 iovec[1].iov_base = (char*) message;
5513 iovec[1].iov_len = strlen(message);
5514 msghdr.msg_iovlen = 2;
5516 msghdr.msg_iov = iovec;
5518 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0) {
5519 close_nointr_nofail(fd);
5523 close_nointr_nofail(fd);
5527 static int reload_with_fallback(DBusConnection *bus) {
5530 /* First, try systemd via D-Bus. */
5531 if (daemon_reload(bus, NULL) >= 0)
5535 /* Nothing else worked, so let's try signals */
5536 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
5538 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
5539 log_error("kill() failed: %m");
5546 static int start_with_fallback(DBusConnection *bus) {
5549 /* First, try systemd via D-Bus. */
5550 if (start_unit(bus, NULL) >= 0)
5554 /* Hmm, talking to systemd via D-Bus didn't work. Then
5555 * let's try to talk to Upstart via D-Bus. */
5556 if (talk_upstart() > 0)
5559 /* Nothing else worked, so let's try
5561 if (talk_initctl() > 0)
5564 log_error("Failed to talk to init daemon.");
5568 warn_wall(arg_action);
5572 static void halt_now(enum action a) {
5574 /* Make sure C-A-D is handled by the kernel from this
5576 reboot(RB_ENABLE_CAD);
5581 log_info("Halting.");
5582 reboot(RB_HALT_SYSTEM);
5585 case ACTION_POWEROFF:
5586 log_info("Powering off.");
5587 reboot(RB_POWER_OFF);
5591 log_info("Rebooting.");
5592 reboot(RB_AUTOBOOT);
5596 assert_not_reached("Unknown halt action.");
5599 assert_not_reached("Uh? This shouldn't happen.");
5602 static int halt_main(DBusConnection *bus) {
5605 if (geteuid() != 0) {
5606 /* Try logind if we are a normal user and no special
5607 * mode applies. Maybe PolicyKit allows us to shutdown
5610 if (arg_when <= 0 &&
5613 (arg_action == ACTION_POWEROFF ||
5614 arg_action == ACTION_REBOOT)) {
5615 r = reboot_with_logind(bus, arg_action);
5620 log_error("Must be root.");
5627 m = strv_join(arg_wall, " ");
5628 r = send_shutdownd(arg_when,
5629 arg_action == ACTION_HALT ? 'H' :
5630 arg_action == ACTION_POWEROFF ? 'P' :
5631 arg_action == ACTION_KEXEC ? 'K' :
5639 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
5641 char date[FORMAT_TIMESTAMP_MAX];
5643 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
5644 format_timestamp(date, sizeof(date), arg_when));
5649 if (!arg_dry && !arg_force)
5650 return start_with_fallback(bus);
5653 if (sd_booted() > 0)
5654 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
5656 r = utmp_put_shutdown();
5658 log_warning("Failed to write utmp record: %s", strerror(-r));
5668 halt_now(arg_action);
5669 /* We should never reach this. */
5673 static int runlevel_main(void) {
5674 int r, runlevel, previous;
5676 r = utmp_get_runlevel(&runlevel, &previous);
5683 previous <= 0 ? 'N' : previous,
5684 runlevel <= 0 ? 'N' : runlevel);
5689 int main(int argc, char*argv[]) {
5690 int r, retval = EXIT_FAILURE;
5691 DBusConnection *bus = NULL;
5694 dbus_error_init(&error);
5696 log_parse_environment();
5699 r = parse_argv(argc, argv);
5703 retval = EXIT_SUCCESS;
5707 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
5708 * let's shortcut this */
5709 if (arg_action == ACTION_RUNLEVEL) {
5710 r = runlevel_main();
5711 retval = r < 0 ? EXIT_FAILURE : r;
5715 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
5716 log_info("Running in chroot, ignoring request.");
5722 if (arg_transport == TRANSPORT_NORMAL)
5723 bus_connect(arg_scope == UNIT_FILE_SYSTEM ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &bus, &private_bus, &error);
5724 else if (arg_transport == TRANSPORT_POLKIT) {
5725 bus_connect_system_polkit(&bus, &error);
5726 private_bus = false;
5727 } else if (arg_transport == TRANSPORT_SSH) {
5728 bus_connect_system_ssh(NULL, arg_host, &bus, &error);
5729 private_bus = false;
5731 assert_not_reached("Uh, invalid transport...");
5734 switch (arg_action) {
5736 case ACTION_SYSTEMCTL:
5737 r = systemctl_main(bus, argc, argv, &error);
5741 case ACTION_POWEROFF:
5747 case ACTION_RUNLEVEL2:
5748 case ACTION_RUNLEVEL3:
5749 case ACTION_RUNLEVEL4:
5750 case ACTION_RUNLEVEL5:
5752 case ACTION_EMERGENCY:
5753 case ACTION_DEFAULT:
5754 r = start_with_fallback(bus);
5759 r = reload_with_fallback(bus);
5762 case ACTION_CANCEL_SHUTDOWN:
5763 r = send_shutdownd(0, 0, false, false, NULL);
5766 case ACTION_INVALID:
5767 case ACTION_RUNLEVEL:
5769 assert_not_reached("Unknown action");
5772 retval = r < 0 ? EXIT_FAILURE : r;
5776 dbus_connection_flush(bus);
5777 dbus_connection_close(bus);
5778 dbus_connection_unref(bus);
5781 dbus_error_free(&error);
5785 strv_free(arg_property);
5788 ask_password_agent_close();
5789 polkit_agent_close();