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>
29 #include <sys/ioctl.h>
33 #include <sys/socket.h>
36 #include <sys/prctl.h>
37 #include <dbus/dbus.h>
39 #include <systemd/sd-daemon.h>
40 #include <systemd/sd-shutdown.h>
46 #include "utmp-wtmp.h"
49 #include "path-util.h"
51 #include "dbus-common.h"
52 #include "cgroup-show.h"
53 #include "cgroup-util.h"
55 #include "path-lookup.h"
56 #include "conf-parser.h"
57 #include "exit-status.h"
58 #include "bus-errors.h"
60 #include "unit-name.h"
62 #include "spawn-ask-password-agent.h"
63 #include "spawn-polkit-agent.h"
65 #include "logs-show.h"
66 #include "path-util.h"
67 #include "socket-util.h"
69 static const char *arg_type = NULL;
70 static const char *arg_load_state = NULL;
71 static char **arg_property = NULL;
72 static bool arg_all = false;
73 static const char *arg_job_mode = "replace";
74 static UnitFileScope arg_scope = UNIT_FILE_SYSTEM;
75 static bool arg_no_block = false;
76 static bool arg_no_legend = false;
77 static bool arg_no_pager = false;
78 static bool arg_no_wtmp = false;
79 static bool arg_no_wall = false;
80 static bool arg_no_reload = false;
81 static bool arg_ignore_inhibitors = false;
82 static bool arg_dry = false;
83 static bool arg_quiet = false;
84 static bool arg_full = false;
85 static int arg_force = 0;
86 static bool arg_ask_password = true;
87 static bool arg_failed = false;
88 static bool arg_runtime = false;
89 static char **arg_wall = NULL;
90 static const char *arg_kill_who = NULL;
91 static int arg_signal = SIGTERM;
92 static const char *arg_root = NULL;
93 static usec_t arg_when = 0;
115 ACTION_CANCEL_SHUTDOWN,
117 } arg_action = ACTION_SYSTEMCTL;
123 static enum transport {
127 } arg_transport = TRANSPORT_NORMAL;
128 static const char *arg_host = NULL;
129 static unsigned arg_lines = 10;
130 static OutputMode arg_output = OUTPUT_SHORT;
132 static bool private_bus = false;
134 static int daemon_reload(DBusConnection *bus, char **args);
135 static void halt_now(enum action a);
137 static void pager_open_if_enabled(void) {
145 static void ask_password_agent_open_if_enabled(void) {
147 /* Open the password agent as a child process if necessary */
149 if (!arg_ask_password)
152 if (arg_scope != UNIT_FILE_SYSTEM)
155 ask_password_agent_open();
159 static void polkit_agent_open_if_enabled(void) {
161 /* Open the polkit agent as a child process if necessary */
163 if (!arg_ask_password)
166 if (arg_scope != UNIT_FILE_SYSTEM)
173 static const char *ansi_highlight(bool b) {
178 return b ? ANSI_HIGHLIGHT_ON : ANSI_HIGHLIGHT_OFF;
181 static const char *ansi_highlight_red(bool b) {
186 return b ? ANSI_HIGHLIGHT_RED_ON : ANSI_HIGHLIGHT_OFF;
189 static const char *ansi_highlight_green(bool b) {
194 return b ? ANSI_HIGHLIGHT_GREEN_ON : ANSI_HIGHLIGHT_OFF;
197 static int translate_bus_error_to_exit_status(int r, const DBusError *error) {
200 if (!dbus_error_is_set(error))
203 if (dbus_error_has_name(error, DBUS_ERROR_ACCESS_DENIED) ||
204 dbus_error_has_name(error, BUS_ERROR_ONLY_BY_DEPENDENCY) ||
205 dbus_error_has_name(error, BUS_ERROR_NO_ISOLATION) ||
206 dbus_error_has_name(error, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE))
207 return EXIT_NOPERMISSION;
209 if (dbus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT))
210 return EXIT_NOTINSTALLED;
212 if (dbus_error_has_name(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE) ||
213 dbus_error_has_name(error, BUS_ERROR_NOT_SUPPORTED))
214 return EXIT_NOTIMPLEMENTED;
216 if (dbus_error_has_name(error, BUS_ERROR_LOAD_FAILED))
217 return EXIT_NOTCONFIGURED;
225 static void warn_wall(enum action a) {
226 static const char *table[_ACTION_MAX] = {
227 [ACTION_HALT] = "The system is going down for system halt NOW!",
228 [ACTION_REBOOT] = "The system is going down for reboot NOW!",
229 [ACTION_POWEROFF] = "The system is going down for power-off NOW!",
230 [ACTION_KEXEC] = "The system is going down for kexec reboot NOW!",
231 [ACTION_RESCUE] = "The system is going down to rescue mode NOW!",
232 [ACTION_EMERGENCY] = "The system is going down to emergency mode NOW!",
233 [ACTION_CANCEL_SHUTDOWN] = "The system shutdown has been cancelled NOW!"
242 p = strv_join(arg_wall, " ");
244 log_error("Failed to join strings.");
260 utmp_wall(table[a], NULL);
263 static bool avoid_bus(void) {
265 if (running_in_chroot() > 0)
268 if (sd_booted() <= 0)
271 if (!isempty(arg_root))
274 if (arg_scope == UNIT_FILE_GLOBAL)
282 const char *description;
283 const char *load_state;
284 const char *active_state;
285 const char *sub_state;
286 const char *following;
287 const char *unit_path;
289 const char *job_type;
290 const char *job_path;
293 static int compare_unit_info(const void *a, const void *b) {
295 const struct unit_info *u = a, *v = b;
297 d1 = strrchr(u->id, '.');
298 d2 = strrchr(v->id, '.');
303 if ((r = strcasecmp(d1, d2)) != 0)
307 return strcasecmp(u->id, v->id);
310 static bool output_show_unit(const struct unit_info *u) {
314 return streq(u->active_state, "failed");
316 return (!arg_type || ((dot = strrchr(u->id, '.')) &&
317 streq(dot+1, arg_type))) &&
318 (!arg_load_state || streq(u->load_state, arg_load_state)) &&
319 (arg_all || !(streq(u->active_state, "inactive")
320 || u->following[0]) || u->job_id > 0);
323 static void output_units_list(const struct unit_info *unit_infos, unsigned c) {
324 unsigned id_len, max_id_len, active_len, sub_len, job_len, desc_len, n_shown = 0;
325 const struct unit_info *u;
328 max_id_len = sizeof("UNIT")-1;
329 active_len = sizeof("ACTIVE")-1;
330 sub_len = sizeof("SUB")-1;
331 job_len = sizeof("JOB")-1;
334 for (u = unit_infos; u < unit_infos + c; u++) {
335 if (!output_show_unit(u))
338 max_id_len = MAX(max_id_len, strlen(u->id));
339 active_len = MAX(active_len, strlen(u->active_state));
340 sub_len = MAX(sub_len, strlen(u->sub_state));
341 if (u->job_id != 0) {
342 job_len = MAX(job_len, strlen(u->job_type));
349 id_len = MIN(max_id_len, 25);
350 basic_len = 5 + id_len + 5 + active_len + sub_len;
352 basic_len += job_len + 1;
353 if (basic_len < (unsigned) columns()) {
354 unsigned extra_len, incr;
355 extra_len = columns() - basic_len;
356 /* Either UNIT already got 25, or is fully satisfied.
357 * Grant up to 25 to DESC now. */
358 incr = MIN(extra_len, 25);
361 /* split the remaining space between UNIT and DESC,
362 * but do not give UNIT more than it needs. */
364 incr = MIN(extra_len / 2, max_id_len - id_len);
366 desc_len += extra_len - incr;
372 for (u = unit_infos; u < unit_infos + c; u++) {
374 const char *on_loaded, *off_loaded;
375 const char *on_active, *off_active;
377 if (!output_show_unit(u))
380 if (!n_shown && !arg_no_legend) {
381 printf("%-*s %-6s %-*s %-*s ", id_len, "UNIT", "LOAD",
382 active_len, "ACTIVE", sub_len, "SUB");
384 printf("%-*s ", job_len, "JOB");
385 if (!arg_full && arg_no_pager)
386 printf("%.*s\n", desc_len, "DESCRIPTION");
388 printf("%s\n", "DESCRIPTION");
393 if (streq(u->load_state, "error")) {
394 on_loaded = ansi_highlight_red(true);
395 off_loaded = ansi_highlight_red(false);
397 on_loaded = off_loaded = "";
399 if (streq(u->active_state, "failed")) {
400 on_active = ansi_highlight_red(true);
401 off_active = ansi_highlight_red(false);
403 on_active = off_active = "";
405 e = arg_full ? NULL : ellipsize(u->id, id_len, 33);
407 printf("%-*s %s%-6s%s %s%-*s %-*s%s %-*s",
408 id_len, e ? e : u->id,
409 on_loaded, u->load_state, off_loaded,
410 on_active, active_len, u->active_state,
411 sub_len, u->sub_state, off_active,
412 job_count ? job_len + 1 : 0, u->job_id ? u->job_type : "");
413 if (!arg_full && arg_no_pager)
414 printf("%.*s\n", desc_len, u->description);
416 printf("%s\n", u->description);
421 if (!arg_no_legend) {
422 const char *on, *off;
425 printf("\nLOAD = Reflects whether the unit definition was properly loaded.\n"
426 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
427 "SUB = The low-level unit activation state, values depend on unit type.\n");
429 printf("JOB = Pending job for the unit.\n");
431 on = ansi_highlight(true);
432 off = ansi_highlight(false);
434 on = ansi_highlight_red(true);
435 off = ansi_highlight_red(false);
439 printf("%s%u loaded units listed.%s\n"
440 "To show all installed unit files use 'systemctl list-unit-files'.\n",
443 printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
444 "To show all installed unit files use 'systemctl list-unit-files'.\n",
449 static int list_units(DBusConnection *bus, char **args) {
450 DBusMessage *reply = NULL;
452 DBusMessageIter iter, sub, sub2;
453 unsigned c = 0, n_units = 0;
454 struct unit_info *unit_infos = NULL;
456 pager_open_if_enabled();
458 r = bus_method_call_with_reply (
460 "org.freedesktop.systemd1",
461 "/org/freedesktop/systemd1",
462 "org.freedesktop.systemd1.Manager",
470 if (!dbus_message_iter_init(reply, &iter) ||
471 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
472 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
473 log_error("Failed to parse reply.");
478 dbus_message_iter_recurse(&iter, &sub);
480 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
483 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
484 log_error("Failed to parse reply.");
492 n_units = MAX(2*c, 16);
493 w = realloc(unit_infos, sizeof(struct unit_info) * n_units);
496 log_error("Failed to allocate unit array.");
506 dbus_message_iter_recurse(&sub, &sub2);
508 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->id, true) < 0 ||
509 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->description, true) < 0 ||
510 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->load_state, true) < 0 ||
511 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->active_state, true) < 0 ||
512 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->sub_state, true) < 0 ||
513 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->following, true) < 0 ||
514 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &u->unit_path, true) < 0 ||
515 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &u->job_id, true) < 0 ||
516 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->job_type, true) < 0 ||
517 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &u->job_path, false) < 0) {
518 log_error("Failed to parse reply.");
523 dbus_message_iter_next(&sub);
528 qsort(unit_infos, c, sizeof(struct unit_info), compare_unit_info);
529 output_units_list(unit_infos, c);
534 dbus_message_unref(reply);
541 static int compare_unit_file_list(const void *a, const void *b) {
543 const UnitFileList *u = a, *v = b;
545 d1 = strrchr(u->path, '.');
546 d2 = strrchr(v->path, '.');
551 r = strcasecmp(d1, d2);
556 return strcasecmp(path_get_file_name(u->path), path_get_file_name(v->path));
559 static bool output_show_unit_file(const UnitFileList *u) {
562 return !arg_type || ((dot = strrchr(u->path, '.')) && streq(dot+1, arg_type));
565 static void output_unit_file_list(const UnitFileList *units, unsigned c) {
566 unsigned max_id_len, id_cols, state_cols, n_shown = 0;
567 const UnitFileList *u;
569 max_id_len = sizeof("UNIT FILE")-1;
570 state_cols = sizeof("STATE")-1;
571 for (u = units; u < units + c; u++) {
572 if (!output_show_unit_file(u))
575 max_id_len = MAX(max_id_len, strlen(path_get_file_name(u->path)));
576 state_cols = MAX(state_cols, strlen(unit_file_state_to_string(u->state)));
581 id_cols = MIN(max_id_len, 25);
582 basic_cols = 1 + id_cols + state_cols;
583 if (basic_cols < (unsigned) columns())
584 id_cols += MIN(columns() - basic_cols, max_id_len - id_cols);
586 id_cols = max_id_len;
589 printf("%-*s %-*s\n", id_cols, "UNIT FILE", state_cols, "STATE");
591 for (u = units; u < units + c; u++) {
593 const char *on, *off;
596 if (!output_show_unit_file(u))
601 if (u->state == UNIT_FILE_MASKED ||
602 u->state == UNIT_FILE_MASKED_RUNTIME ||
603 u->state == UNIT_FILE_DISABLED ||
604 u->state == UNIT_FILE_INVALID) {
605 on = ansi_highlight_red(true);
606 off = ansi_highlight_red(false);
607 } else if (u->state == UNIT_FILE_ENABLED) {
608 on = ansi_highlight_green(true);
609 off = ansi_highlight_green(false);
613 id = path_get_file_name(u->path);
615 e = arg_full ? NULL : ellipsize(id, id_cols, 33);
617 printf("%-*s %s%-*s%s\n",
619 on, state_cols, unit_file_state_to_string(u->state), off);
625 printf("\n%u unit files listed.\n", n_shown);
628 static int list_unit_files(DBusConnection *bus, char **args) {
629 DBusMessage *reply = NULL;
631 DBusMessageIter iter, sub, sub2;
632 unsigned c = 0, n_units = 0;
633 UnitFileList *units = NULL;
635 pager_open_if_enabled();
642 h = hashmap_new(string_hash_func, string_compare_func);
646 r = unit_file_get_list(arg_scope, arg_root, h);
648 unit_file_list_free(h);
649 log_error("Failed to get unit file list: %s", strerror(-r));
653 n_units = hashmap_size(h);
654 units = new(UnitFileList, n_units);
656 unit_file_list_free(h);
660 HASHMAP_FOREACH(u, h, i) {
661 memcpy(units + c++, u, sizeof(UnitFileList));
667 r = bus_method_call_with_reply (
669 "org.freedesktop.systemd1",
670 "/org/freedesktop/systemd1",
671 "org.freedesktop.systemd1.Manager",
679 if (!dbus_message_iter_init(reply, &iter) ||
680 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
681 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
682 log_error("Failed to parse reply.");
687 dbus_message_iter_recurse(&iter, &sub);
689 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
693 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
694 log_error("Failed to parse reply.");
702 n_units = MAX(2*c, 16);
703 w = realloc(units, sizeof(struct UnitFileList) * n_units);
706 log_error("Failed to allocate unit array.");
716 dbus_message_iter_recurse(&sub, &sub2);
718 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->path, true) < 0 ||
719 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, false) < 0) {
720 log_error("Failed to parse reply.");
725 u->state = unit_file_state_from_string(state);
727 dbus_message_iter_next(&sub);
733 qsort(units, c, sizeof(UnitFileList), compare_unit_file_list);
734 output_unit_file_list(units, c);
741 dbus_message_unref(reply);
748 static int dot_one_property(const char *name, const char *prop, DBusMessageIter *iter) {
749 static const char * const colors[] = {
750 "Requires", "[color=\"black\"]",
751 "RequiresOverridable", "[color=\"black\"]",
752 "Requisite", "[color=\"darkblue\"]",
753 "RequisiteOverridable", "[color=\"darkblue\"]",
754 "Wants", "[color=\"grey66\"]",
755 "Conflicts", "[color=\"red\"]",
756 "ConflictedBy", "[color=\"red\"]",
757 "After", "[color=\"green\"]"
760 const char *c = NULL;
767 for (i = 0; i < ELEMENTSOF(colors); i += 2)
768 if (streq(colors[i], prop)) {
776 if (arg_dot != DOT_ALL)
777 if ((arg_dot == DOT_ORDER) != streq(prop, "After"))
780 switch (dbus_message_iter_get_arg_type(iter)) {
782 case DBUS_TYPE_ARRAY:
784 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING) {
787 dbus_message_iter_recurse(iter, &sub);
789 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
792 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING);
793 dbus_message_iter_get_basic(&sub, &s);
794 printf("\t\"%s\"->\"%s\" %s;\n", name, s, c);
796 dbus_message_iter_next(&sub);
806 static int dot_one(DBusConnection *bus, const char *name, const char *path) {
807 DBusMessage *reply = NULL;
808 const char *interface = "org.freedesktop.systemd1.Unit";
810 DBusMessageIter iter, sub, sub2, sub3;
814 r = bus_method_call_with_reply (
816 "org.freedesktop.systemd1",
818 "org.freedesktop.DBus.Properties",
822 DBUS_TYPE_STRING, &interface,
827 if (!dbus_message_iter_init(reply, &iter) ||
828 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
829 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
830 log_error("Failed to parse reply.");
835 dbus_message_iter_recurse(&iter, &sub);
837 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
840 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_DICT_ENTRY) {
841 log_error("Failed to parse reply.");
846 dbus_message_iter_recurse(&sub, &sub2);
848 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &prop, true) < 0) {
849 log_error("Failed to parse reply.");
854 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
855 log_error("Failed to parse reply.");
860 dbus_message_iter_recurse(&sub2, &sub3);
862 if (dot_one_property(name, prop, &sub3)) {
863 log_error("Failed to parse reply.");
868 dbus_message_iter_next(&sub);
873 dbus_message_unref(reply);
878 static int dot(DBusConnection *bus, char **args) {
879 DBusMessage *reply = NULL;
881 DBusMessageIter iter, sub, sub2;
883 r = bus_method_call_with_reply (
885 "org.freedesktop.systemd1",
886 "/org/freedesktop/systemd1",
887 "org.freedesktop.systemd1.Manager",
895 if (!dbus_message_iter_init(reply, &iter) ||
896 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
897 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
898 log_error("Failed to parse reply.");
903 printf("digraph systemd {\n");
905 dbus_message_iter_recurse(&iter, &sub);
906 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
907 const char *id, *description, *load_state, *active_state, *sub_state, *following, *unit_path;
909 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
910 log_error("Failed to parse reply.");
915 dbus_message_iter_recurse(&sub, &sub2);
917 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &id, true) < 0 ||
918 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &description, true) < 0 ||
919 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &load_state, true) < 0 ||
920 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &active_state, true) < 0 ||
921 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &sub_state, true) < 0 ||
922 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &following, true) < 0 ||
923 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, true) < 0) {
924 log_error("Failed to parse reply.");
929 if ((r = dot_one(bus, id, unit_path)) < 0)
932 /* printf("\t\"%s\";\n", id); */
933 dbus_message_iter_next(&sub);
938 log_info(" Color legend: black = Requires\n"
939 " dark blue = Requisite\n"
940 " dark grey = Wants\n"
945 log_notice("-- You probably want to process this output with graphviz' dot tool.\n"
946 "-- Try a shell pipeline like 'systemctl dot | dot -Tsvg > systemd.svg'!\n");
952 dbus_message_unref(reply);
957 static int list_jobs(DBusConnection *bus, char **args) {
958 DBusMessage *reply = NULL;
960 DBusMessageIter iter, sub, sub2;
963 pager_open_if_enabled();
965 r = bus_method_call_with_reply (
967 "org.freedesktop.systemd1",
968 "/org/freedesktop/systemd1",
969 "org.freedesktop.systemd1.Manager",
977 if (!dbus_message_iter_init(reply, &iter) ||
978 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
979 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
980 log_error("Failed to parse reply.");
985 dbus_message_iter_recurse(&iter, &sub);
988 printf("%4s %-25s %-15s %-7s\n", "JOB", "UNIT", "TYPE", "STATE");
990 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
991 const char *name, *type, *state, *job_path, *unit_path;
995 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
996 log_error("Failed to parse reply.");
1001 dbus_message_iter_recurse(&sub, &sub2);
1003 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &id, true) < 0 ||
1004 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
1005 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
1006 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, true) < 0 ||
1007 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &job_path, true) < 0 ||
1008 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, false) < 0) {
1009 log_error("Failed to parse reply.");
1014 e = arg_full ? NULL : ellipsize(name, 25, 33);
1015 printf("%4u %-25s %-15s %-7s\n", id, e ? e : name, type, state);
1020 dbus_message_iter_next(&sub);
1024 printf("\n%u jobs listed.\n", k);
1030 dbus_message_unref(reply);
1035 static int load_unit(DBusConnection *bus, char **args) {
1040 STRV_FOREACH(name, args+1) {
1041 _cleanup_free_ char *n = NULL;
1044 n = unit_name_mangle(*name);
1045 r = bus_method_call_with_reply (
1047 "org.freedesktop.systemd1",
1048 "/org/freedesktop/systemd1",
1049 "org.freedesktop.systemd1.Manager",
1053 DBUS_TYPE_STRING, n ? &n : name,
1062 static int cancel_job(DBusConnection *bus, char **args) {
1067 if (strv_length(args) <= 1)
1068 return daemon_reload(bus, args);
1070 STRV_FOREACH(name, args+1) {
1074 r = safe_atou32(*name, &id);
1076 log_error("Failed to parse job id: %s", strerror(-r));
1080 r = bus_method_call_with_reply(
1082 "org.freedesktop.systemd1",
1083 "/org/freedesktop/systemd1",
1084 "org.freedesktop.systemd1.Manager",
1088 DBUS_TYPE_UINT32, &id,
1097 static bool need_daemon_reload(DBusConnection *bus, const char *unit) {
1098 DBusMessage *reply = NULL;
1099 dbus_bool_t b = FALSE;
1100 DBusMessageIter iter, sub;
1102 *interface = "org.freedesktop.systemd1.Unit",
1103 *property = "NeedDaemonReload",
1108 /* We ignore all errors here, since this is used to show a warning only */
1110 n = unit_name_mangle(unit);
1111 r = bus_method_call_with_reply (
1113 "org.freedesktop.systemd1",
1114 "/org/freedesktop/systemd1",
1115 "org.freedesktop.systemd1.Manager",
1119 DBUS_TYPE_STRING, n ? (const char**) &n : &unit,
1125 if (!dbus_message_get_args(reply, NULL,
1126 DBUS_TYPE_OBJECT_PATH, &path,
1130 dbus_message_unref(reply);
1131 r = bus_method_call_with_reply (
1133 "org.freedesktop.systemd1",
1135 "org.freedesktop.DBus.Properties",
1139 DBUS_TYPE_STRING, &interface,
1140 DBUS_TYPE_STRING, &property,
1145 if (!dbus_message_iter_init(reply, &iter) ||
1146 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
1149 dbus_message_iter_recurse(&iter, &sub);
1151 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_BOOLEAN)
1154 dbus_message_iter_get_basic(&sub, &b);
1158 dbus_message_unref(reply);
1163 typedef struct WaitData {
1170 static DBusHandlerResult wait_filter(DBusConnection *connection, DBusMessage *message, void *data) {
1178 dbus_error_init(&error);
1180 log_debug("Got D-Bus request: %s.%s() on %s",
1181 dbus_message_get_interface(message),
1182 dbus_message_get_member(message),
1183 dbus_message_get_path(message));
1185 if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
1186 log_error("Warning! D-Bus connection terminated.");
1187 dbus_connection_close(connection);
1189 } else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
1191 const char *path, *result, *unit;
1192 dbus_bool_t success = true;
1194 if (dbus_message_get_args(message, &error,
1195 DBUS_TYPE_UINT32, &id,
1196 DBUS_TYPE_OBJECT_PATH, &path,
1197 DBUS_TYPE_STRING, &unit,
1198 DBUS_TYPE_STRING, &result,
1199 DBUS_TYPE_INVALID)) {
1202 p = set_remove(d->set, (char*) path);
1205 if (!isempty(result))
1206 d->result = strdup(result);
1209 d->name = strdup(unit);
1214 dbus_error_free(&error);
1215 if (dbus_message_get_args(message, &error,
1216 DBUS_TYPE_UINT32, &id,
1217 DBUS_TYPE_OBJECT_PATH, &path,
1218 DBUS_TYPE_STRING, &result,
1219 DBUS_TYPE_INVALID)) {
1222 /* Compatibility with older systemd versions <
1223 * 183 during upgrades. This should be dropped
1225 p = set_remove(d->set, (char*) path);
1229 d->result = strdup(result);
1234 dbus_error_free(&error);
1235 if (dbus_message_get_args(message, &error,
1236 DBUS_TYPE_UINT32, &id,
1237 DBUS_TYPE_OBJECT_PATH, &path,
1238 DBUS_TYPE_BOOLEAN, &success,
1239 DBUS_TYPE_INVALID)) {
1242 /* Compatibility with older systemd versions <
1243 * 19 during upgrades. This should be dropped
1246 p = set_remove(d->set, (char*) path);
1250 d->result = strdup("failed");
1256 log_error("Failed to parse message: %s", bus_error_message(&error));
1260 dbus_error_free(&error);
1261 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1264 static int enable_wait_for_jobs(DBusConnection *bus) {
1272 dbus_error_init(&error);
1273 dbus_bus_add_match(bus,
1275 "sender='org.freedesktop.systemd1',"
1276 "interface='org.freedesktop.systemd1.Manager',"
1277 "member='JobRemoved',"
1278 "path='/org/freedesktop/systemd1'",
1281 if (dbus_error_is_set(&error)) {
1282 log_error("Failed to add match: %s", bus_error_message(&error));
1283 dbus_error_free(&error);
1287 /* This is slightly dirty, since we don't undo the match registrations. */
1291 static int wait_for_jobs(DBusConnection *bus, Set *s) {
1301 if (!dbus_connection_add_filter(bus, wait_filter, &d, NULL))
1304 while (!set_isempty(s)) {
1306 if (!dbus_connection_read_write_dispatch(bus, -1)) {
1307 log_error("Disconnected from bus.");
1308 return -ECONNREFUSED;
1315 if (streq(d.result, "timeout"))
1316 log_error("Job for %s timed out.", strna(d.name));
1317 else if (streq(d.result, "canceled"))
1318 log_error("Job for %s canceled.", strna(d.name));
1319 else if (streq(d.result, "dependency"))
1320 log_error("A dependency job for %s failed. See 'journalctl -xn' for details.", strna(d.name));
1321 else if (!streq(d.result, "done") && !streq(d.result, "skipped"))
1322 log_error("Job for %s failed. See 'systemctl status %s' and 'journalctl -xn' for details.", strna(d.name), strna(d.name));
1325 if (streq_ptr(d.result, "timeout"))
1327 else if (streq_ptr(d.result, "canceled"))
1329 else if (!streq_ptr(d.result, "done") && !streq_ptr(d.result, "skipped"))
1340 dbus_connection_remove_filter(bus, wait_filter, &d);
1344 static int check_one_unit(DBusConnection *bus, const char *name, char **check_states, bool quiet) {
1345 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1346 DBusMessageIter iter, sub;
1348 *interface = "org.freedesktop.systemd1.Unit",
1349 *property = "ActiveState";
1350 const char *state, *path;
1351 _cleanup_free_ char *n = NULL;
1357 dbus_error_init(&error);
1359 n = unit_name_mangle(name);
1363 r = bus_method_call_with_reply (
1365 "org.freedesktop.systemd1",
1366 "/org/freedesktop/systemd1",
1367 "org.freedesktop.systemd1.Manager",
1371 DBUS_TYPE_STRING, &n,
1374 dbus_error_free(&error);
1381 if (!dbus_message_get_args(reply, NULL,
1382 DBUS_TYPE_OBJECT_PATH, &path,
1383 DBUS_TYPE_INVALID)) {
1384 log_error("Failed to parse reply.");
1388 dbus_message_unref(reply);
1391 r = bus_method_call_with_reply(
1393 "org.freedesktop.systemd1",
1395 "org.freedesktop.DBus.Properties",
1399 DBUS_TYPE_STRING, &interface,
1400 DBUS_TYPE_STRING, &property,
1408 if (!dbus_message_iter_init(reply, &iter) ||
1409 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1410 log_error("Failed to parse reply.");
1414 dbus_message_iter_recurse(&iter, &sub);
1416 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1417 log_error("Failed to parse reply.");
1421 dbus_message_iter_get_basic(&sub, &state);
1426 return strv_find(check_states, state) ? 1 : 0;
1429 static void check_triggering_units(
1430 DBusConnection *bus,
1431 const char *unit_name) {
1433 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1434 DBusMessageIter iter, sub;
1435 const char *interface = "org.freedesktop.systemd1.Unit",
1436 *triggered_by_property = "TriggeredBy";
1438 char _cleanup_free_ *unit_path = NULL, *n = NULL;
1439 bool print_warning_label = true;
1442 n = unit_name_mangle(unit_name);
1448 unit_path = unit_dbus_path_from_name(n);
1454 r = bus_method_call_with_reply(
1456 "org.freedesktop.systemd1",
1458 "org.freedesktop.DBus.Properties",
1462 DBUS_TYPE_STRING, &interface,
1463 DBUS_TYPE_STRING, &triggered_by_property,
1468 if (!dbus_message_iter_init(reply, &iter) ||
1469 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1470 log_error("Failed to parse reply.");
1474 dbus_message_iter_recurse(&iter, &sub);
1475 dbus_message_iter_recurse(&sub, &iter);
1478 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1479 const char * const check_states[] = {
1484 const char *service_trigger;
1486 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1487 log_error("Failed to parse reply.");
1491 dbus_message_iter_get_basic(&sub, &service_trigger);
1493 r = check_one_unit(bus, service_trigger, (char**) check_states, true);
1497 if (print_warning_label) {
1498 log_warning("Warning: Stopping %s, but it can still be activated by:", unit_name);
1499 print_warning_label = false;
1502 log_warning(" %s", service_trigger);
1505 dbus_message_iter_next(&sub);
1509 static int start_unit_one(
1510 DBusConnection *bus,
1517 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1520 _cleanup_free_ char *n, *p = NULL;
1527 n = unit_name_mangle(name);
1531 r = bus_method_call_with_reply(
1533 "org.freedesktop.systemd1",
1534 "/org/freedesktop/systemd1",
1535 "org.freedesktop.systemd1.Manager",
1539 DBUS_TYPE_STRING, &n,
1540 DBUS_TYPE_STRING, &mode,
1543 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
1544 /* There's always a fallback possible for
1545 * legacy actions. */
1548 log_error("Failed to issue method call: %s", bus_error_message(error));
1553 if (!dbus_message_get_args(reply, error,
1554 DBUS_TYPE_OBJECT_PATH, &path,
1555 DBUS_TYPE_INVALID)) {
1556 log_error("Failed to parse reply: %s", bus_error_message(error));
1560 if (need_daemon_reload(bus, n))
1561 log_warning("Warning: Unit file of %s changed on disk, 'systemctl %s daemon-reload' recommended.",
1562 n, arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
1571 log_error("Failed to add path to set.");
1581 static enum action verb_to_action(const char *verb) {
1582 if (streq(verb, "halt"))
1584 else if (streq(verb, "poweroff"))
1585 return ACTION_POWEROFF;
1586 else if (streq(verb, "reboot"))
1587 return ACTION_REBOOT;
1588 else if (streq(verb, "kexec"))
1589 return ACTION_KEXEC;
1590 else if (streq(verb, "rescue"))
1591 return ACTION_RESCUE;
1592 else if (streq(verb, "emergency"))
1593 return ACTION_EMERGENCY;
1594 else if (streq(verb, "default"))
1595 return ACTION_DEFAULT;
1596 else if (streq(verb, "exit"))
1598 else if (streq(verb, "suspend"))
1599 return ACTION_SUSPEND;
1600 else if (streq(verb, "hibernate"))
1601 return ACTION_HIBERNATE;
1602 else if (streq(verb, "hybrid-sleep"))
1603 return ACTION_HYBRID_SLEEP;
1605 return ACTION_INVALID;
1608 static int start_unit(DBusConnection *bus, char **args) {
1610 static const char * const table[_ACTION_MAX] = {
1611 [ACTION_HALT] = SPECIAL_HALT_TARGET,
1612 [ACTION_POWEROFF] = SPECIAL_POWEROFF_TARGET,
1613 [ACTION_REBOOT] = SPECIAL_REBOOT_TARGET,
1614 [ACTION_KEXEC] = SPECIAL_KEXEC_TARGET,
1615 [ACTION_RUNLEVEL2] = SPECIAL_RUNLEVEL2_TARGET,
1616 [ACTION_RUNLEVEL3] = SPECIAL_RUNLEVEL3_TARGET,
1617 [ACTION_RUNLEVEL4] = SPECIAL_RUNLEVEL4_TARGET,
1618 [ACTION_RUNLEVEL5] = SPECIAL_RUNLEVEL5_TARGET,
1619 [ACTION_RESCUE] = SPECIAL_RESCUE_TARGET,
1620 [ACTION_EMERGENCY] = SPECIAL_EMERGENCY_TARGET,
1621 [ACTION_DEFAULT] = SPECIAL_DEFAULT_TARGET,
1622 [ACTION_EXIT] = SPECIAL_EXIT_TARGET,
1623 [ACTION_SUSPEND] = SPECIAL_SUSPEND_TARGET,
1624 [ACTION_HIBERNATE] = SPECIAL_HIBERNATE_TARGET,
1625 [ACTION_HYBRID_SLEEP] = SPECIAL_HYBRID_SLEEP_TARGET
1629 const char *method, *mode, *one_name;
1634 dbus_error_init(&error);
1638 ask_password_agent_open_if_enabled();
1640 if (arg_action == ACTION_SYSTEMCTL) {
1642 streq(args[0], "stop") ||
1643 streq(args[0], "condstop") ? "StopUnit" :
1644 streq(args[0], "reload") ? "ReloadUnit" :
1645 streq(args[0], "restart") ? "RestartUnit" :
1647 streq(args[0], "try-restart") ||
1648 streq(args[0], "condrestart") ? "TryRestartUnit" :
1650 streq(args[0], "reload-or-restart") ? "ReloadOrRestartUnit" :
1652 streq(args[0], "reload-or-try-restart") ||
1653 streq(args[0], "condreload") ||
1655 streq(args[0], "force-reload") ? "ReloadOrTryRestartUnit" :
1659 (streq(args[0], "isolate") ||
1660 streq(args[0], "rescue") ||
1661 streq(args[0], "emergency")) ? "isolate" : arg_job_mode;
1663 one_name = table[verb_to_action(args[0])];
1666 assert(arg_action < ELEMENTSOF(table));
1667 assert(table[arg_action]);
1669 method = "StartUnit";
1671 mode = (arg_action == ACTION_EMERGENCY ||
1672 arg_action == ACTION_RESCUE ||
1673 arg_action == ACTION_RUNLEVEL2 ||
1674 arg_action == ACTION_RUNLEVEL3 ||
1675 arg_action == ACTION_RUNLEVEL4 ||
1676 arg_action == ACTION_RUNLEVEL5) ? "isolate" : "replace";
1678 one_name = table[arg_action];
1681 if (!arg_no_block) {
1682 ret = enable_wait_for_jobs(bus);
1684 log_error("Could not watch jobs: %s", strerror(-ret));
1688 s = set_new(string_hash_func, string_compare_func);
1696 ret = start_unit_one(bus, method, one_name, mode, &error, s);
1698 ret = translate_bus_error_to_exit_status(ret, &error);
1700 STRV_FOREACH(name, args+1) {
1701 r = start_unit_one(bus, method, *name, mode, &error, s);
1703 ret = translate_bus_error_to_exit_status(r, &error);
1704 dbus_error_free(&error);
1709 if (!arg_no_block) {
1710 r = wait_for_jobs(bus, s);
1716 /* When stopping units, warn if they can still be triggered by
1717 * another active unit (socket, path, timer) */
1718 if (!arg_quiet && streq(method, "StopUnit")) {
1720 check_triggering_units(bus, one_name);
1722 STRV_FOREACH(name, args+1)
1723 check_triggering_units(bus, *name);
1729 dbus_error_free(&error);
1734 /* Ask systemd-logind, which might grant access to unprivileged users
1735 * through PolicyKit */
1736 static int reboot_with_logind(DBusConnection *bus, enum action a) {
1739 dbus_bool_t interactive = true;
1744 polkit_agent_open_if_enabled();
1752 case ACTION_POWEROFF:
1753 method = "PowerOff";
1756 case ACTION_SUSPEND:
1760 case ACTION_HIBERNATE:
1761 method = "Hibernate";
1764 case ACTION_HYBRID_SLEEP:
1765 method = "HybridSleep";
1772 return bus_method_call_with_reply (
1774 "org.freedesktop.login1",
1775 "/org/freedesktop/login1",
1776 "org.freedesktop.login1.Manager",
1780 DBUS_TYPE_BOOLEAN, &interactive,
1787 static int check_inhibitors(DBusConnection *bus, enum action a) {
1789 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1790 DBusMessageIter iter, sub, sub2;
1797 if (arg_ignore_inhibitors || arg_force > 0)
1809 r = bus_method_call_with_reply(
1811 "org.freedesktop.login1",
1812 "/org/freedesktop/login1",
1813 "org.freedesktop.login1.Manager",
1819 /* If logind is not around, then there are no inhibitors... */
1822 if (!dbus_message_iter_init(reply, &iter) ||
1823 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
1824 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
1825 log_error("Failed to parse reply.");
1829 dbus_message_iter_recurse(&iter, &sub);
1830 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1831 const char *what, *who, *why, *mode;
1833 _cleanup_strv_free_ char **sv = NULL;
1834 _cleanup_free_ char *comm = NULL;
1836 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
1837 log_error("Failed to parse reply.");
1841 dbus_message_iter_recurse(&sub, &sub2);
1843 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &what, true) < 0 ||
1844 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &who, true) < 0 ||
1845 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &why, true) < 0 ||
1846 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &mode, true) < 0 ||
1847 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &uid, true) < 0 ||
1848 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, false) < 0) {
1849 log_error("Failed to parse reply.");
1853 if (!streq(mode, "block"))
1856 sv = strv_split(what, ":");
1860 if (!strv_contains(sv,
1862 a == ACTION_POWEROFF ||
1863 a == ACTION_REBOOT ||
1864 a == ACTION_KEXEC ? "shutdown" : "sleep"))
1867 get_process_comm(pid, &comm);
1868 log_warning("Operation inhibited by \"%s\" (PID %lu \"%s\", UID %lu), reason is \"%s\".", who, (unsigned long) pid, strna(comm), (unsigned long) uid, why);
1872 dbus_message_iter_next(&sub);
1875 dbus_message_iter_recurse(&iter, &sub);
1880 log_error("Please try again after closing inhibitors or ignore them with 'systemctl %s -i'.",
1881 a == ACTION_HALT ? "halt" :
1882 a == ACTION_POWEROFF ? "poweroff" :
1883 a == ACTION_REBOOT ? "reboot" :
1884 a == ACTION_KEXEC ? "kexec" :
1885 a == ACTION_SUSPEND ? "suspend" :
1886 a == ACTION_HIBERNATE ? "hibernate" : "hybrid-sleep");
1894 static int start_special(DBusConnection *bus, char **args) {
1900 a = verb_to_action(args[0]);
1902 r = check_inhibitors(bus, a);
1906 if (arg_force >= 2 && geteuid() != 0) {
1907 log_error("Must be root.");
1911 if (arg_force >= 2 &&
1912 (a == ACTION_HALT ||
1913 a == ACTION_POWEROFF ||
1914 a == ACTION_REBOOT))
1917 if (arg_force >= 1 &&
1918 (a == ACTION_HALT ||
1919 a == ACTION_POWEROFF ||
1920 a == ACTION_REBOOT ||
1921 a == ACTION_KEXEC ||
1923 return daemon_reload(bus, args);
1925 /* first try logind, to allow authentication with polkit */
1926 if (geteuid() != 0 &&
1927 (a == ACTION_POWEROFF ||
1928 a == ACTION_REBOOT ||
1929 a == ACTION_SUSPEND ||
1930 a == ACTION_HIBERNATE ||
1931 a == ACTION_HYBRID_SLEEP)) {
1932 r = reboot_with_logind(bus, a);
1937 r = start_unit(bus, args);
1944 static int check_unit_active(DBusConnection *bus, char **args) {
1945 const char * const check_states[] = {
1952 int r = 3; /* According to LSB: "program is not running" */
1957 STRV_FOREACH(name, args+1) {
1960 state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
1970 static int check_unit_failed(DBusConnection *bus, char **args) {
1971 const char * const check_states[] = {
1982 STRV_FOREACH(name, args+1) {
1985 state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
1995 static int kill_unit(DBusConnection *bus, char **args) {
2003 arg_kill_who = "all";
2005 STRV_FOREACH(name, args+1) {
2006 _cleanup_free_ char *n = NULL;
2008 n = unit_name_mangle(*name);
2010 r = bus_method_call_with_reply(
2012 "org.freedesktop.systemd1",
2013 "/org/freedesktop/systemd1",
2014 "org.freedesktop.systemd1.Manager",
2018 DBUS_TYPE_STRING, n ? &n : name,
2019 DBUS_TYPE_STRING, &arg_kill_who,
2020 DBUS_TYPE_INT32, &arg_signal,
2028 static int set_cgroup(DBusConnection *bus, char **args) {
2029 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
2032 DBusMessageIter iter;
2034 _cleanup_free_ char *n = NULL;
2039 dbus_error_init(&error);
2042 streq(args[0], "set-cgroup") ? "SetUnitControlGroups" :
2043 streq(args[0], "unset-group") ? "UnsetUnitControlGroups"
2044 : "UnsetUnitControlGroupAttributes";
2046 n = unit_name_mangle(args[1]);
2050 m = dbus_message_new_method_call(
2051 "org.freedesktop.systemd1",
2052 "/org/freedesktop/systemd1",
2053 "org.freedesktop.systemd1.Manager",
2058 dbus_message_iter_init_append(m, &iter);
2059 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &n))
2062 r = bus_append_strv_iter(&iter, args + 2);
2066 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
2068 log_error("Failed to issue method call: %s", bus_error_message(&error));
2069 dbus_error_free(&error);
2076 static int set_cgroup_attr(DBusConnection *bus, char **args) {
2077 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
2079 DBusMessageIter iter, sub, sub2;
2082 _cleanup_free_ char *n = NULL;
2087 dbus_error_init(&error);
2089 if (strv_length(args) % 2 != 0) {
2090 log_error("Expecting an uneven number of arguments!");
2094 n = unit_name_mangle(args[1]);
2098 m = dbus_message_new_method_call(
2099 "org.freedesktop.systemd1",
2100 "/org/freedesktop/systemd1",
2101 "org.freedesktop.systemd1.Manager",
2102 "SetUnitControlGroupAttributes");
2106 dbus_message_iter_init_append(m, &iter);
2107 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &n) ||
2108 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ss)", &sub))
2111 STRV_FOREACH_PAIR(x, y, args + 2) {
2112 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
2113 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, x) ||
2114 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, y) ||
2115 !dbus_message_iter_close_container(&sub, &sub2))
2119 if (!dbus_message_iter_close_container(&iter, &sub))
2122 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
2124 log_error("Failed to issue method call: %s", bus_error_message(&error));
2125 dbus_error_free(&error);
2132 typedef struct ExecStatusInfo {
2140 usec_t start_timestamp;
2141 usec_t exit_timestamp;
2146 LIST_FIELDS(struct ExecStatusInfo, exec);
2149 static void exec_status_info_free(ExecStatusInfo *i) {
2158 static int exec_status_info_deserialize(DBusMessageIter *sub, ExecStatusInfo *i) {
2159 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
2160 DBusMessageIter sub2, sub3;
2164 int32_t code, status;
2170 if (dbus_message_iter_get_arg_type(sub) != DBUS_TYPE_STRUCT)
2173 dbus_message_iter_recurse(sub, &sub2);
2175 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0)
2178 if (!(i->path = strdup(path)))
2181 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_ARRAY ||
2182 dbus_message_iter_get_element_type(&sub2) != DBUS_TYPE_STRING)
2186 dbus_message_iter_recurse(&sub2, &sub3);
2187 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2188 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2189 dbus_message_iter_next(&sub3);
2194 if (!(i->argv = new0(char*, n+1)))
2198 dbus_message_iter_recurse(&sub2, &sub3);
2199 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2202 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2203 dbus_message_iter_get_basic(&sub3, &s);
2204 dbus_message_iter_next(&sub3);
2206 if (!(i->argv[n++] = strdup(s)))
2210 if (!dbus_message_iter_next(&sub2) ||
2211 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, true) < 0 ||
2212 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp, true) < 0 ||
2213 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp_monotonic, true) < 0 ||
2214 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp, true) < 0 ||
2215 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp_monotonic, true) < 0 ||
2216 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, true) < 0 ||
2217 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &code, true) < 0 ||
2218 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &status, false) < 0)
2222 i->start_timestamp = (usec_t) start_timestamp;
2223 i->exit_timestamp = (usec_t) exit_timestamp;
2224 i->pid = (pid_t) pid;
2231 typedef struct UnitStatusInfo {
2233 const char *load_state;
2234 const char *active_state;
2235 const char *sub_state;
2236 const char *unit_file_state;
2238 const char *description;
2239 const char *following;
2241 char **documentation;
2243 const char *fragment_path;
2244 const char *source_path;
2245 const char *default_control_group;
2247 const char *load_error;
2250 usec_t inactive_exit_timestamp;
2251 usec_t inactive_exit_timestamp_monotonic;
2252 usec_t active_enter_timestamp;
2253 usec_t active_exit_timestamp;
2254 usec_t inactive_enter_timestamp;
2256 bool need_daemon_reload;
2261 const char *status_text;
2264 usec_t start_timestamp;
2265 usec_t exit_timestamp;
2267 int exit_code, exit_status;
2269 usec_t condition_timestamp;
2270 bool condition_result;
2273 unsigned n_accepted;
2274 unsigned n_connections;
2278 const char *sysfs_path;
2280 /* Mount, Automount */
2286 LIST_HEAD(ExecStatusInfo, exec);
2289 static void print_status_info(UnitStatusInfo *i) {
2291 const char *on, *off, *ss;
2293 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
2294 char since2[FORMAT_TIMESTAMP_MAX], *s2;
2299 /* This shows pretty information about a unit. See
2300 * print_property() for a low-level property printer */
2302 printf("%s", strna(i->id));
2304 if (i->description && !streq_ptr(i->id, i->description))
2305 printf(" - %s", i->description);
2310 printf("\t Follow: unit currently follows state of %s\n", i->following);
2312 if (streq_ptr(i->load_state, "error")) {
2313 on = ansi_highlight_red(true);
2314 off = ansi_highlight_red(false);
2318 path = i->source_path ? i->source_path : i->fragment_path;
2321 printf("\t Loaded: %s%s%s (Reason: %s)\n", on, strna(i->load_state), off, i->load_error);
2322 else if (path && i->unit_file_state)
2323 printf("\t Loaded: %s%s%s (%s; %s)\n", on, strna(i->load_state), off, path, i->unit_file_state);
2325 printf("\t Loaded: %s%s%s (%s)\n", on, strna(i->load_state), off, path);
2327 printf("\t Loaded: %s%s%s\n", on, strna(i->load_state), off);
2329 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
2331 if (streq_ptr(i->active_state, "failed")) {
2332 on = ansi_highlight_red(true);
2333 off = ansi_highlight_red(false);
2334 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
2335 on = ansi_highlight_green(true);
2336 off = ansi_highlight_green(false);
2341 printf("\t Active: %s%s (%s)%s",
2343 strna(i->active_state),
2347 printf("\t Active: %s%s%s",
2349 strna(i->active_state),
2352 if (!isempty(i->result) && !streq(i->result, "success"))
2353 printf(" (Result: %s)", i->result);
2355 timestamp = (streq_ptr(i->active_state, "active") ||
2356 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
2357 (streq_ptr(i->active_state, "inactive") ||
2358 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
2359 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
2360 i->active_exit_timestamp;
2362 s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
2363 s2 = format_timestamp(since2, sizeof(since2), timestamp);
2366 printf(" since %s; %s\n", s2, s1);
2368 printf(" since %s\n", s2);
2372 if (!i->condition_result && i->condition_timestamp > 0) {
2373 s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
2374 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
2377 printf("\t start condition failed at %s; %s\n", s2, s1);
2379 printf("\t start condition failed at %s\n", s2);
2383 printf("\t Device: %s\n", i->sysfs_path);
2385 printf("\t Where: %s\n", i->where);
2387 printf("\t What: %s\n", i->what);
2389 if (!strv_isempty(i->documentation)) {
2393 STRV_FOREACH(t, i->documentation) {
2395 printf("\t Docs: %s\n", *t);
2398 printf("\t %s\n", *t);
2403 printf("\tAccepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
2405 LIST_FOREACH(exec, p, i->exec) {
2409 /* Only show exited processes here */
2413 t = strv_join(p->argv, " ");
2414 printf("\t Process: %u %s=%s ", p->pid, p->name, strna(t));
2417 good = is_clean_exit_lsb(p->code, p->status, NULL);
2419 on = ansi_highlight_red(true);
2420 off = ansi_highlight_red(false);
2424 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
2426 if (p->code == CLD_EXITED) {
2429 printf("status=%i", p->status);
2431 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
2436 printf("signal=%s", signal_to_string(p->status));
2438 printf(")%s\n", off);
2440 if (i->main_pid == p->pid &&
2441 i->start_timestamp == p->start_timestamp &&
2442 i->exit_timestamp == p->start_timestamp)
2443 /* Let's not show this twice */
2446 if (p->pid == i->control_pid)
2450 if (i->main_pid > 0 || i->control_pid > 0) {
2453 if (i->main_pid > 0) {
2454 printf("Main PID: %u", (unsigned) i->main_pid);
2458 get_process_comm(i->main_pid, &t);
2463 } else if (i->exit_code > 0) {
2464 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
2466 if (i->exit_code == CLD_EXITED) {
2469 printf("status=%i", i->exit_status);
2471 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
2476 printf("signal=%s", signal_to_string(i->exit_status));
2481 if (i->main_pid > 0 && i->control_pid > 0)
2484 if (i->control_pid > 0) {
2487 printf(" Control: %u", (unsigned) i->control_pid);
2489 get_process_comm(i->control_pid, &t);
2500 printf("\t Status: \"%s\"\n", i->status_text);
2502 if (i->default_control_group &&
2503 (i->main_pid > 0 || i->control_pid > 0 || cg_is_empty_by_spec(i->default_control_group, false) == 0)) {
2506 printf("\t CGroup: %s\n", i->default_control_group);
2508 if (arg_transport != TRANSPORT_SSH) {
2518 if (i->main_pid > 0)
2519 extra[k++] = i->main_pid;
2521 if (i->control_pid > 0)
2522 extra[k++] = i->control_pid;
2524 show_cgroup_and_extra_by_spec(i->default_control_group, "\t\t ", c, false, arg_all, extra, k);
2528 if (i->id && arg_transport != TRANSPORT_SSH) {
2530 arg_all * OUTPUT_SHOW_ALL |
2531 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
2532 on_tty() * OUTPUT_COLOR |
2533 !arg_quiet * OUTPUT_WARN_CUTOFF;
2536 show_journal_by_unit(stdout,
2540 i->inactive_exit_timestamp_monotonic,
2545 if (i->need_daemon_reload)
2546 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %s daemon-reload' recommended.\n",
2547 ansi_highlight_red(true),
2548 ansi_highlight_red(false),
2549 arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
2552 static void show_unit_help(UnitStatusInfo *i) {
2557 if (!i->documentation) {
2558 log_info("Documentation for %s not known.", i->id);
2562 STRV_FOREACH(p, i->documentation) {
2564 if (startswith(*p, "man:")) {
2567 char *page = NULL, *section = NULL;
2568 const char *args[4] = { "man", NULL, NULL, NULL };
2573 if ((*p)[k-1] == ')')
2574 e = strrchr(*p, '(');
2577 page = strndup((*p) + 4, e - *p - 4);
2583 section = strndup(e + 1, *p + k - e - 2);
2597 log_error("Failed to fork: %m");
2605 execvp(args[0], (char**) args);
2606 log_error("Failed to execute man: %m");
2607 _exit(EXIT_FAILURE);
2613 wait_for_terminate(pid, NULL);
2615 log_info("Can't show: %s", *p);
2619 static int status_property(const char *name, DBusMessageIter *iter, UnitStatusInfo *i) {
2625 switch (dbus_message_iter_get_arg_type(iter)) {
2627 case DBUS_TYPE_STRING: {
2630 dbus_message_iter_get_basic(iter, &s);
2633 if (streq(name, "Id"))
2635 else if (streq(name, "LoadState"))
2637 else if (streq(name, "ActiveState"))
2638 i->active_state = s;
2639 else if (streq(name, "SubState"))
2641 else if (streq(name, "Description"))
2643 else if (streq(name, "FragmentPath"))
2644 i->fragment_path = s;
2645 else if (streq(name, "SourcePath"))
2647 else if (streq(name, "DefaultControlGroup"))
2648 i->default_control_group = s;
2649 else if (streq(name, "StatusText"))
2651 else if (streq(name, "SysFSPath"))
2653 else if (streq(name, "Where"))
2655 else if (streq(name, "What"))
2657 else if (streq(name, "Following"))
2659 else if (streq(name, "UnitFileState"))
2660 i->unit_file_state = s;
2661 else if (streq(name, "Result"))
2668 case DBUS_TYPE_BOOLEAN: {
2671 dbus_message_iter_get_basic(iter, &b);
2673 if (streq(name, "Accept"))
2675 else if (streq(name, "NeedDaemonReload"))
2676 i->need_daemon_reload = b;
2677 else if (streq(name, "ConditionResult"))
2678 i->condition_result = b;
2683 case DBUS_TYPE_UINT32: {
2686 dbus_message_iter_get_basic(iter, &u);
2688 if (streq(name, "MainPID")) {
2690 i->main_pid = (pid_t) u;
2693 } else if (streq(name, "ControlPID"))
2694 i->control_pid = (pid_t) u;
2695 else if (streq(name, "ExecMainPID")) {
2697 i->main_pid = (pid_t) u;
2698 } else if (streq(name, "NAccepted"))
2700 else if (streq(name, "NConnections"))
2701 i->n_connections = u;
2706 case DBUS_TYPE_INT32: {
2709 dbus_message_iter_get_basic(iter, &j);
2711 if (streq(name, "ExecMainCode"))
2712 i->exit_code = (int) j;
2713 else if (streq(name, "ExecMainStatus"))
2714 i->exit_status = (int) j;
2719 case DBUS_TYPE_UINT64: {
2722 dbus_message_iter_get_basic(iter, &u);
2724 if (streq(name, "ExecMainStartTimestamp"))
2725 i->start_timestamp = (usec_t) u;
2726 else if (streq(name, "ExecMainExitTimestamp"))
2727 i->exit_timestamp = (usec_t) u;
2728 else if (streq(name, "ActiveEnterTimestamp"))
2729 i->active_enter_timestamp = (usec_t) u;
2730 else if (streq(name, "InactiveEnterTimestamp"))
2731 i->inactive_enter_timestamp = (usec_t) u;
2732 else if (streq(name, "InactiveExitTimestamp"))
2733 i->inactive_exit_timestamp = (usec_t) u;
2734 else if (streq(name, "InactiveExitTimestampMonotonic"))
2735 i->inactive_exit_timestamp_monotonic = (usec_t) u;
2736 else if (streq(name, "ActiveExitTimestamp"))
2737 i->active_exit_timestamp = (usec_t) u;
2738 else if (streq(name, "ConditionTimestamp"))
2739 i->condition_timestamp = (usec_t) u;
2744 case DBUS_TYPE_ARRAY: {
2746 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
2747 startswith(name, "Exec")) {
2748 DBusMessageIter sub;
2750 dbus_message_iter_recurse(iter, &sub);
2751 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2752 ExecStatusInfo *info;
2755 if (!(info = new0(ExecStatusInfo, 1)))
2758 if (!(info->name = strdup(name))) {
2763 if ((r = exec_status_info_deserialize(&sub, info)) < 0) {
2768 LIST_PREPEND(ExecStatusInfo, exec, i->exec, info);
2770 dbus_message_iter_next(&sub);
2772 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
2773 streq(name, "Documentation")) {
2775 DBusMessageIter sub;
2777 dbus_message_iter_recurse(iter, &sub);
2778 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING) {
2782 dbus_message_iter_get_basic(&sub, &s);
2784 l = strv_append(i->documentation, s);
2788 strv_free(i->documentation);
2789 i->documentation = l;
2791 dbus_message_iter_next(&sub);
2798 case DBUS_TYPE_STRUCT: {
2800 if (streq(name, "LoadError")) {
2801 DBusMessageIter sub;
2802 const char *n, *message;
2805 dbus_message_iter_recurse(iter, &sub);
2807 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &n, true);
2811 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &message, false);
2815 if (!isempty(message))
2816 i->load_error = message;
2826 static int print_property(const char *name, DBusMessageIter *iter) {
2830 /* This is a low-level property printer, see
2831 * print_status_info() for the nicer output */
2833 if (arg_property && !strv_find(arg_property, name))
2836 switch (dbus_message_iter_get_arg_type(iter)) {
2838 case DBUS_TYPE_STRUCT: {
2839 DBusMessageIter sub;
2840 dbus_message_iter_recurse(iter, &sub);
2842 if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32 && streq(name, "Job")) {
2845 dbus_message_iter_get_basic(&sub, &u);
2848 printf("%s=%u\n", name, (unsigned) u);
2850 printf("%s=\n", name);
2853 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "Unit")) {
2856 dbus_message_iter_get_basic(&sub, &s);
2858 if (arg_all || s[0])
2859 printf("%s=%s\n", name, s);
2862 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "LoadError")) {
2863 const char *a = NULL, *b = NULL;
2865 if (bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &a, true) >= 0)
2866 bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &b, false);
2868 if (arg_all || !isempty(a) || !isempty(b))
2869 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
2877 case DBUS_TYPE_ARRAY:
2879 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "EnvironmentFiles")) {
2880 DBusMessageIter sub, sub2;
2882 dbus_message_iter_recurse(iter, &sub);
2883 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2887 dbus_message_iter_recurse(&sub, &sub2);
2889 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
2890 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) >= 0)
2891 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
2893 dbus_message_iter_next(&sub);
2898 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Paths")) {
2899 DBusMessageIter sub, sub2;
2901 dbus_message_iter_recurse(iter, &sub);
2902 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2903 const char *type, *path;
2905 dbus_message_iter_recurse(&sub, &sub2);
2907 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
2908 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
2909 printf("%s=%s\n", type, path);
2911 dbus_message_iter_next(&sub);
2916 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Timers")) {
2917 DBusMessageIter sub, sub2;
2919 dbus_message_iter_recurse(iter, &sub);
2920 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2922 uint64_t value, next_elapse;
2924 dbus_message_iter_recurse(&sub, &sub2);
2926 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &base, true) >= 0 &&
2927 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &value, true) >= 0 &&
2928 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &next_elapse, false) >= 0) {
2929 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
2931 printf("%s={ value=%s ; next_elapse=%s }\n",
2933 format_timespan(timespan1, sizeof(timespan1), value),
2934 format_timespan(timespan2, sizeof(timespan2), next_elapse));
2937 dbus_message_iter_next(&sub);
2942 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "ControlGroupAttributes")) {
2943 DBusMessageIter sub, sub2;
2945 dbus_message_iter_recurse(iter, &sub);
2946 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2947 const char *controller, *attr, *value;
2949 dbus_message_iter_recurse(&sub, &sub2);
2951 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &controller, true) >= 0 &&
2952 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &attr, true) >= 0 &&
2953 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &value, false) >= 0) {
2955 printf("ControlGroupAttribute={ controller=%s ; attribute=%s ; value=\"%s\" }\n",
2961 dbus_message_iter_next(&sub);
2966 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && startswith(name, "Exec")) {
2967 DBusMessageIter sub;
2969 dbus_message_iter_recurse(iter, &sub);
2970 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2971 ExecStatusInfo info;
2974 if (exec_status_info_deserialize(&sub, &info) >= 0) {
2975 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
2978 t = strv_join(info.argv, " ");
2980 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
2984 yes_no(info.ignore),
2985 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
2986 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
2987 (unsigned) info. pid,
2988 sigchld_code_to_string(info.code),
2990 info.code == CLD_EXITED ? "" : "/",
2991 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
2997 strv_free(info.argv);
2999 dbus_message_iter_next(&sub);
3008 if (generic_print_property(name, iter, arg_all) > 0)
3012 printf("%s=[unprintable]\n", name);
3017 static int show_one(const char *verb, DBusConnection *bus, const char *path, bool show_properties, bool *new_line) {
3018 DBusMessage *reply = NULL;
3019 const char *interface = "";
3021 DBusMessageIter iter, sub, sub2, sub3;
3022 UnitStatusInfo info;
3030 r = bus_method_call_with_reply (
3032 "org.freedesktop.systemd1",
3034 "org.freedesktop.DBus.Properties",
3038 DBUS_TYPE_STRING, &interface,
3043 if (!dbus_message_iter_init(reply, &iter) ||
3044 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3045 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
3046 log_error("Failed to parse reply.");
3051 dbus_message_iter_recurse(&iter, &sub);
3058 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
3061 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_DICT_ENTRY) {
3062 log_error("Failed to parse reply.");
3067 dbus_message_iter_recurse(&sub, &sub2);
3069 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0) {
3070 log_error("Failed to parse reply.");
3075 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
3076 log_error("Failed to parse reply.");
3081 dbus_message_iter_recurse(&sub2, &sub3);
3083 if (show_properties)
3084 r = print_property(name, &sub3);
3086 r = status_property(name, &sub3, &info);
3089 log_error("Failed to parse reply.");
3094 dbus_message_iter_next(&sub);
3099 if (!show_properties) {
3100 if (streq(verb, "help"))
3101 show_unit_help(&info);
3103 print_status_info(&info);
3106 strv_free(info.documentation);
3108 if (!streq_ptr(info.active_state, "active") &&
3109 !streq_ptr(info.active_state, "reloading") &&
3110 streq(verb, "status"))
3111 /* According to LSB: "program not running" */
3114 while ((p = info.exec)) {
3115 LIST_REMOVE(ExecStatusInfo, exec, info.exec, p);
3116 exec_status_info_free(p);
3121 dbus_message_unref(reply);
3126 static int show_one_by_pid(const char *verb, DBusConnection *bus, uint32_t pid, bool *new_line) {
3127 DBusMessage *reply = NULL;
3128 const char *path = NULL;
3132 dbus_error_init(&error);
3134 r = bus_method_call_with_reply (
3136 "org.freedesktop.systemd1",
3137 "/org/freedesktop/systemd1",
3138 "org.freedesktop.systemd1.Manager",
3142 DBUS_TYPE_UINT32, &pid,
3147 if (!dbus_message_get_args(reply, &error,
3148 DBUS_TYPE_OBJECT_PATH, &path,
3149 DBUS_TYPE_INVALID)) {
3150 log_error("Failed to parse reply: %s", bus_error_message(&error));
3155 r = show_one(verb, bus, path, false, new_line);
3159 dbus_message_unref(reply);
3161 dbus_error_free(&error);
3166 static int show(DBusConnection *bus, char **args) {
3168 bool show_properties, new_line = false;
3174 show_properties = streq(args[0], "show");
3176 if (show_properties)
3177 pager_open_if_enabled();
3179 if (show_properties && strv_length(args) <= 1) {
3180 /* If not argument is specified inspect the manager
3183 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line);
3186 STRV_FOREACH(name, args+1) {
3189 if (safe_atou32(*name, &id) < 0) {
3191 /* Interpret as unit name */
3193 n = unit_name_mangle(*name);
3194 p = unit_dbus_path_from_name(n ? n : *name);
3199 r = show_one(args[0], bus, p, show_properties, &new_line);
3205 } else if (show_properties) {
3207 /* Interpret as job id */
3210 if (asprintf(&p, "/org/freedesktop/systemd1/job/%u", id) < 0)
3213 r = show_one(args[0], bus, p, show_properties, &new_line);
3221 /* Interpret as PID */
3223 r = show_one_by_pid(args[0], bus, id, &new_line);
3232 static int dump(DBusConnection *bus, char **args) {
3233 DBusMessage *reply = NULL;
3238 dbus_error_init(&error);
3240 pager_open_if_enabled();
3242 r = bus_method_call_with_reply (
3244 "org.freedesktop.systemd1",
3245 "/org/freedesktop/systemd1",
3246 "org.freedesktop.systemd1.Manager",
3254 if (!dbus_message_get_args(reply, &error,
3255 DBUS_TYPE_STRING, &text,
3256 DBUS_TYPE_INVALID)) {
3257 log_error("Failed to parse reply: %s", bus_error_message(&error));
3262 fputs(text, stdout);
3266 dbus_message_unref(reply);
3268 dbus_error_free(&error);
3273 static int snapshot(DBusConnection *bus, char **args) {
3274 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3277 dbus_bool_t cleanup = FALSE;
3278 DBusMessageIter iter, sub;
3280 *name = "", *path, *id,
3281 *interface = "org.freedesktop.systemd1.Unit",
3283 _cleanup_free_ char *n = NULL;
3285 dbus_error_init(&error);
3287 if (strv_length(args) > 1) {
3289 n = unit_name_mangle(name);
3292 r = bus_method_call_with_reply (
3294 "org.freedesktop.systemd1",
3295 "/org/freedesktop/systemd1",
3296 "org.freedesktop.systemd1.Manager",
3300 DBUS_TYPE_STRING, n ? (const char**) &n : &name,
3301 DBUS_TYPE_BOOLEAN, &cleanup,
3306 if (!dbus_message_get_args(reply, &error,
3307 DBUS_TYPE_OBJECT_PATH, &path,
3308 DBUS_TYPE_INVALID)) {
3309 log_error("Failed to parse reply: %s", bus_error_message(&error));
3314 dbus_message_unref(reply);
3317 r = bus_method_call_with_reply (
3319 "org.freedesktop.systemd1",
3321 "org.freedesktop.DBus.Properties",
3325 DBUS_TYPE_STRING, &interface,
3326 DBUS_TYPE_STRING, &property,
3331 if (!dbus_message_iter_init(reply, &iter) ||
3332 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3333 log_error("Failed to parse reply.");
3338 dbus_message_iter_recurse(&iter, &sub);
3340 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
3341 log_error("Failed to parse reply.");
3346 dbus_message_iter_get_basic(&sub, &id);
3352 dbus_error_free(&error);
3357 static int delete_snapshot(DBusConnection *bus, char **args) {
3362 STRV_FOREACH(name, args+1) {
3363 _cleanup_free_ char *n = NULL;
3366 n = unit_name_mangle(*name);
3367 r = bus_method_call_with_reply(
3369 "org.freedesktop.systemd1",
3370 "/org/freedesktop/systemd1",
3371 "org.freedesktop.systemd1.Manager",
3375 DBUS_TYPE_STRING, n ? &n : name,
3384 static int daemon_reload(DBusConnection *bus, char **args) {
3389 if (arg_action == ACTION_RELOAD)
3391 else if (arg_action == ACTION_REEXEC)
3392 method = "Reexecute";
3394 assert(arg_action == ACTION_SYSTEMCTL);
3397 streq(args[0], "clear-jobs") ||
3398 streq(args[0], "cancel") ? "ClearJobs" :
3399 streq(args[0], "daemon-reexec") ? "Reexecute" :
3400 streq(args[0], "reset-failed") ? "ResetFailed" :
3401 streq(args[0], "halt") ? "Halt" :
3402 streq(args[0], "poweroff") ? "PowerOff" :
3403 streq(args[0], "reboot") ? "Reboot" :
3404 streq(args[0], "kexec") ? "KExec" :
3405 streq(args[0], "exit") ? "Exit" :
3406 /* "daemon-reload" */ "Reload";
3409 r = bus_method_call_with_reply (
3411 "org.freedesktop.systemd1",
3412 "/org/freedesktop/systemd1",
3413 "org.freedesktop.systemd1.Manager",
3419 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
3420 /* There's always a fallback possible for
3421 * legacy actions. */
3423 else if (r == -ETIMEDOUT && streq(method, "Reexecute"))
3424 /* On reexecution, we expect a disconnect, not
3428 log_error("Failed to issue method call: %s", bus_error_message(&error));
3429 dbus_error_free(&error);
3434 static int reset_failed(DBusConnection *bus, char **args) {
3438 if (strv_length(args) <= 1)
3439 return daemon_reload(bus, args);
3441 STRV_FOREACH(name, args+1) {
3442 n = unit_name_mangle(*name);
3443 r = bus_method_call_with_reply (
3445 "org.freedesktop.systemd1",
3446 "/org/freedesktop/systemd1",
3447 "org.freedesktop.systemd1.Manager",
3451 DBUS_TYPE_STRING, n ? &n : name,
3462 static int show_enviroment(DBusConnection *bus, char **args) {
3463 DBusMessage *reply = NULL;
3464 DBusMessageIter iter, sub, sub2;
3467 *interface = "org.freedesktop.systemd1.Manager",
3468 *property = "Environment";
3470 pager_open_if_enabled();
3472 r = bus_method_call_with_reply (
3474 "org.freedesktop.systemd1",
3475 "/org/freedesktop/systemd1",
3476 "org.freedesktop.DBus.Properties",
3480 DBUS_TYPE_STRING, &interface,
3481 DBUS_TYPE_STRING, &property,
3486 if (!dbus_message_iter_init(reply, &iter) ||
3487 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3488 log_error("Failed to parse reply.");
3493 dbus_message_iter_recurse(&iter, &sub);
3495 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_ARRAY ||
3496 dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_STRING) {
3497 log_error("Failed to parse reply.");
3502 dbus_message_iter_recurse(&sub, &sub2);
3504 while (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_INVALID) {
3507 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
3508 log_error("Failed to parse reply.");
3513 dbus_message_iter_get_basic(&sub2, &text);
3514 printf("%s\n", text);
3516 dbus_message_iter_next(&sub2);
3523 dbus_message_unref(reply);
3528 static int switch_root(DBusConnection *bus, char **args) {
3531 _cleanup_free_ char *init = NULL;
3533 l = strv_length(args);
3534 if (l < 2 || l > 3) {
3535 log_error("Wrong number of arguments.");
3542 init = strdup(args[2]);
3544 parse_env_file("/proc/cmdline", WHITESPACE,
3556 log_debug("switching root - root: %s; init: %s", root, init);
3558 return bus_method_call_with_reply (
3560 "org.freedesktop.systemd1",
3561 "/org/freedesktop/systemd1",
3562 "org.freedesktop.systemd1.Manager",
3566 DBUS_TYPE_STRING, &root,
3567 DBUS_TYPE_STRING, &init,
3571 static int set_environment(DBusConnection *bus, char **args) {
3572 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
3575 DBusMessageIter iter;
3581 dbus_error_init(&error);
3583 method = streq(args[0], "set-environment")
3585 : "UnsetEnvironment";
3587 m = dbus_message_new_method_call(
3588 "org.freedesktop.systemd1",
3589 "/org/freedesktop/systemd1",
3590 "org.freedesktop.systemd1.Manager",
3595 dbus_message_iter_init_append(m, &iter);
3597 r = bus_append_strv_iter(&iter, args + 1);
3601 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3603 log_error("Failed to issue method call: %s", bus_error_message(&error));
3611 dbus_error_free(&error);
3615 static int enable_sysv_units(char **args) {
3618 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
3619 const char *verb = args[0];
3620 unsigned f = 1, t = 1;
3623 if (arg_scope != UNIT_FILE_SYSTEM)
3626 if (!streq(verb, "enable") &&
3627 !streq(verb, "disable") &&
3628 !streq(verb, "is-enabled"))
3631 /* Processes all SysV units, and reshuffles the array so that
3632 * afterwards only the native units remain */
3635 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, NULL, NULL, NULL);
3640 for (f = 1; args[f]; f++) {
3643 bool found_native = false, found_sysv;
3645 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
3646 char **k, *l, *q = NULL;
3653 if (!endswith(name, ".service"))
3656 if (path_is_absolute(name))
3659 STRV_FOREACH(k, paths.unit_path) {
3662 if (!isempty(arg_root))
3663 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
3665 asprintf(&p, "%s/%s", *k, name);
3672 found_native = access(p, F_OK) >= 0;
3683 if (!isempty(arg_root))
3684 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
3686 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
3692 p[strlen(p) - sizeof(".service") + 1] = 0;
3693 found_sysv = access(p, F_OK) >= 0;
3700 /* Mark this entry, so that we don't try enabling it as native unit */
3701 args[f] = (char*) "";
3703 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
3705 if (!isempty(arg_root))
3706 argv[c++] = q = strappend("--root=", arg_root);
3708 argv[c++] = path_get_file_name(p);
3710 streq(verb, "enable") ? "on" :
3711 streq(verb, "disable") ? "off" : "--level=5";
3714 l = strv_join((char**)argv, " ");
3722 log_info("Executing %s", l);
3727 log_error("Failed to fork: %m");
3732 } else if (pid == 0) {
3735 execv(argv[0], (char**) argv);
3736 _exit(EXIT_FAILURE);
3742 j = wait_for_terminate(pid, &status);
3744 log_error("Failed to wait for child: %s", strerror(-r));
3749 if (status.si_code == CLD_EXITED) {
3750 if (streq(verb, "is-enabled")) {
3751 if (status.si_status == 0) {
3760 } else if (status.si_status != 0) {
3771 lookup_paths_free(&paths);
3773 /* Drop all SysV units */
3774 for (f = 1, t = 1; args[f]; f++) {
3776 if (isempty(args[f]))
3779 args[t++] = args[f];
3788 static int mangle_names(char **original_names, char ***mangled_names) {
3789 char **i, **l, **name;
3791 l = new(char*, strv_length(original_names) + 1);
3796 STRV_FOREACH(name, original_names) {
3798 /* When enabling units qualified path names are OK,
3799 * too, hence allow them explicitly. */
3804 *i = unit_name_mangle(*name);
3820 static int enable_unit(DBusConnection *bus, char **args) {
3821 const char *verb = args[0];
3822 UnitFileChange *changes = NULL;
3823 unsigned n_changes = 0, i;
3824 int carries_install_info = -1;
3825 DBusMessage *m = NULL, *reply = NULL;
3828 char **mangled_names = NULL;
3830 r = enable_sysv_units(args);
3837 dbus_error_init(&error);
3839 if (!bus || avoid_bus()) {
3840 if (streq(verb, "enable")) {
3841 r = unit_file_enable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3842 carries_install_info = r;
3843 } else if (streq(verb, "disable"))
3844 r = unit_file_disable(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3845 else if (streq(verb, "reenable")) {
3846 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3847 carries_install_info = r;
3848 } else if (streq(verb, "link"))
3849 r = unit_file_link(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3850 else if (streq(verb, "preset")) {
3851 r = unit_file_preset(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3852 carries_install_info = r;
3853 } else if (streq(verb, "mask"))
3854 r = unit_file_mask(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3855 else if (streq(verb, "unmask"))
3856 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3858 assert_not_reached("Unknown verb");
3861 log_error("Operation failed: %s", strerror(-r));
3866 for (i = 0; i < n_changes; i++) {
3867 if (changes[i].type == UNIT_FILE_SYMLINK)
3868 log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
3870 log_info("rm '%s'", changes[i].path);
3877 bool send_force = true, expect_carries_install_info = false;
3879 DBusMessageIter iter, sub, sub2;
3881 if (streq(verb, "enable")) {
3882 method = "EnableUnitFiles";
3883 expect_carries_install_info = true;
3884 } else if (streq(verb, "disable")) {
3885 method = "DisableUnitFiles";
3887 } else if (streq(verb, "reenable")) {
3888 method = "ReenableUnitFiles";
3889 expect_carries_install_info = true;
3890 } else if (streq(verb, "link"))
3891 method = "LinkUnitFiles";
3892 else if (streq(verb, "preset")) {
3893 method = "PresetUnitFiles";
3894 expect_carries_install_info = true;
3895 } else if (streq(verb, "mask"))
3896 method = "MaskUnitFiles";
3897 else if (streq(verb, "unmask")) {
3898 method = "UnmaskUnitFiles";
3901 assert_not_reached("Unknown verb");
3903 m = dbus_message_new_method_call(
3904 "org.freedesktop.systemd1",
3905 "/org/freedesktop/systemd1",
3906 "org.freedesktop.systemd1.Manager",
3913 dbus_message_iter_init_append(m, &iter);
3915 r = mangle_names(args+1, &mangled_names);
3919 r = bus_append_strv_iter(&iter, mangled_names);
3921 log_error("Failed to append unit files.");
3926 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &a)) {
3927 log_error("Failed to append runtime boolean.");
3935 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b)) {
3936 log_error("Failed to append force boolean.");
3942 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3944 log_error("Failed to issue method call: %s", bus_error_message(&error));
3949 if (!dbus_message_iter_init(reply, &iter)) {
3950 log_error("Failed to initialize iterator.");
3954 if (expect_carries_install_info) {
3955 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &b, true);
3957 log_error("Failed to parse reply.");
3961 carries_install_info = b;
3964 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3965 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
3966 log_error("Failed to parse reply.");
3971 dbus_message_iter_recurse(&iter, &sub);
3972 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
3973 const char *type, *path, *source;
3975 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
3976 log_error("Failed to parse reply.");
3981 dbus_message_iter_recurse(&sub, &sub2);
3983 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
3984 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
3985 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &source, false) < 0) {
3986 log_error("Failed to parse reply.");
3992 if (streq(type, "symlink"))
3993 log_info("ln -s '%s' '%s'", source, path);
3995 log_info("rm '%s'", path);
3998 dbus_message_iter_next(&sub);
4001 /* Try to reload if enabeld */
4003 r = daemon_reload(bus, args);
4006 if (carries_install_info == 0)
4008 "The unit files have no [Install] section. They are not meant to be enabled\n"
4009 "using systemctl.\n"
4010 "Possible reasons for having this kind of units are:\n"
4011 "1) A unit may be statically enabled by being symlinked from another unit's\n"
4012 " .wants/ or .requires/ directory.\n"
4013 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
4014 " a requirement dependency on it.\n"
4015 "3) A unit may be started when needed via activation (socket, path, timer,\n"
4016 " D-Bus, udev, scripted systemctl call, ...).\n");
4020 dbus_message_unref(m);
4023 dbus_message_unref(reply);
4025 unit_file_changes_free(changes, n_changes);
4027 dbus_error_free(&error);
4029 strv_free(mangled_names);
4034 static int unit_is_enabled(DBusConnection *bus, char **args) {
4037 DBusMessage *reply = NULL;
4041 dbus_error_init(&error);
4043 r = enable_sysv_units(args);
4049 if (!bus || avoid_bus()) {
4051 STRV_FOREACH(name, args+1) {
4052 UnitFileState state;
4054 state = unit_file_get_state(arg_scope, arg_root, *name);
4060 if (state == UNIT_FILE_ENABLED ||
4061 state == UNIT_FILE_ENABLED_RUNTIME ||
4062 state == UNIT_FILE_STATIC)
4066 puts(unit_file_state_to_string(state));
4070 STRV_FOREACH(name, args+1) {
4073 r = bus_method_call_with_reply (
4075 "org.freedesktop.systemd1",
4076 "/org/freedesktop/systemd1",
4077 "org.freedesktop.systemd1.Manager",
4081 DBUS_TYPE_STRING, name,
4086 if (!dbus_message_get_args(reply, &error,
4087 DBUS_TYPE_STRING, &s,
4088 DBUS_TYPE_INVALID)) {
4089 log_error("Failed to parse reply: %s", bus_error_message(&error));
4094 dbus_message_unref(reply);
4097 if (streq(s, "enabled") ||
4098 streq(s, "enabled-runtime") ||
4107 r = enabled ? 0 : 1;
4111 dbus_message_unref(reply);
4113 dbus_error_free(&error);
4117 static int systemctl_help(void) {
4119 pager_open_if_enabled();
4121 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
4122 "Query or send control commands to the systemd manager.\n\n"
4123 " -h --help Show this help\n"
4124 " --version Show package version\n"
4125 " -t --type=TYPE List only units of a particular type\n"
4126 " -p --property=NAME Show only properties by this name\n"
4127 " -a --all Show all units/properties, including dead/empty ones\n"
4128 " --failed Show only failed units\n"
4129 " --full Don't ellipsize unit names on output\n"
4130 " --fail When queueing a new job, fail if conflicting jobs are\n"
4132 " --ignore-dependencies\n"
4133 " When queueing a new job, ignore all its dependencies\n"
4134 " -i --ignore-inhibitors\n"
4135 " When shutting down or sleeping, ignore inhibitors\n"
4136 " --kill-who=WHO Who to send signal to\n"
4137 " -s --signal=SIGNAL Which signal to send\n"
4138 " -H --host=[USER@]HOST\n"
4139 " Show information for remote host\n"
4140 " -P --privileged Acquire privileges before execution\n"
4141 " -q --quiet Suppress output\n"
4142 " --no-block Do not wait until operation finished\n"
4143 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4144 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
4146 " --no-legend Do not print a legend (column headers and hints)\n"
4147 " --no-pager Do not pipe output into a pager\n"
4148 " --no-ask-password\n"
4149 " Do not ask for system passwords\n"
4150 " --order When generating graph for dot, show only order\n"
4151 " --require When generating graph for dot, show only requirement\n"
4152 " --system Connect to system manager\n"
4153 " --user Connect to user service manager\n"
4154 " --global Enable/disable unit files globally\n"
4155 " -f --force When enabling unit files, override existing symlinks\n"
4156 " When shutting down, execute action immediately\n"
4157 " --root=PATH Enable unit files in the specified root directory\n"
4158 " --runtime Enable unit files only temporarily until next reboot\n"
4159 " -n --lines=INTEGER Journal entries to show\n"
4160 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
4161 " verbose, export, json, json-pretty, json-sse, cat)\n\n"
4163 " list-units List loaded units\n"
4164 " start [NAME...] Start (activate) one or more units\n"
4165 " stop [NAME...] Stop (deactivate) one or more units\n"
4166 " reload [NAME...] Reload one or more units\n"
4167 " restart [NAME...] Start or restart one or more units\n"
4168 " try-restart [NAME...] Restart one or more units if active\n"
4169 " reload-or-restart [NAME...] Reload one or more units if possible,\n"
4170 " otherwise start or restart\n"
4171 " reload-or-try-restart [NAME...] Reload one or more units if possible,\n"
4172 " otherwise restart if active\n"
4173 " isolate [NAME] Start one unit and stop all others\n"
4174 " kill [NAME...] Send signal to processes of a unit\n"
4175 " is-active [NAME...] Check whether units are active\n"
4176 " is-failed [NAME...] Check whether units are failed\n"
4177 " status [NAME...|PID...] Show runtime status of one or more units\n"
4178 " show [NAME...|JOB...] Show properties of one or more\n"
4179 " units/jobs or the manager\n"
4180 " help [NAME...|PID...] Show manual for one or more units\n"
4181 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
4183 " set-cgroup [NAME] [CGROUP...] Add unit to a control group\n"
4184 " unset-cgroup [NAME] [CGROUP...] Remove unit from a control group\n"
4185 " set-cgroup-attr [NAME] [ATTR] [VALUE] ...\n"
4186 " Set control group attribute\n"
4187 " unset-cgroup-attr [NAME] [ATTR...]\n"
4188 " Unset control group attribute\n"
4189 " load [NAME...] Load one or more units\n\n"
4190 "Unit File Commands:\n"
4191 " list-unit-files List installed unit files\n"
4192 " enable [NAME...] Enable one or more unit files\n"
4193 " disable [NAME...] Disable one or more unit files\n"
4194 " reenable [NAME...] Reenable one or more unit files\n"
4195 " preset [NAME...] Enable/disable one or more unit files\n"
4196 " based on preset configuration\n"
4197 " mask [NAME...] Mask one or more units\n"
4198 " unmask [NAME...] Unmask one or more units\n"
4199 " link [PATH...] Link one or more units files into\n"
4200 " the search path\n"
4201 " is-enabled [NAME...] Check whether unit files are enabled\n\n"
4203 " list-jobs List jobs\n"
4204 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
4205 "Status Commands:\n"
4206 " dump Dump server status\n"
4207 " dot Dump dependency graph for dot(1)\n\n"
4208 "Snapshot Commands:\n"
4209 " snapshot [NAME] Create a snapshot\n"
4210 " delete [NAME...] Remove one or more snapshots\n\n"
4211 "Environment Commands:\n"
4212 " show-environment Dump environment\n"
4213 " set-environment [NAME=VALUE...] Set one or more environment variables\n"
4214 " unset-environment [NAME...] Unset one or more environment variables\n\n"
4215 "Manager Lifecycle Commands:\n"
4216 " daemon-reload Reload systemd manager configuration\n"
4217 " daemon-reexec Reexecute systemd manager\n\n"
4218 "System Commands:\n"
4219 " default Enter system default mode\n"
4220 " rescue Enter system rescue mode\n"
4221 " emergency Enter system emergency mode\n"
4222 " halt Shut down and halt the system\n"
4223 " poweroff Shut down and power-off the system\n"
4224 " reboot Shut down and reboot the system\n"
4225 " kexec Shut down and reboot the system with kexec\n"
4226 " exit Request user instance exit\n"
4227 " switch-root [ROOT] [INIT] Change to a different root file system\n"
4228 " suspend Suspend the system\n"
4229 " hibernate Hibernate the system\n"
4230 " hybrid-sleep Hibernate and suspend the system\n",
4231 program_invocation_short_name);
4236 static int halt_help(void) {
4238 printf("%s [OPTIONS...]\n\n"
4239 "%s the system.\n\n"
4240 " --help Show this help\n"
4241 " --halt Halt the machine\n"
4242 " -p --poweroff Switch off the machine\n"
4243 " --reboot Reboot the machine\n"
4244 " -f --force Force immediate halt/power-off/reboot\n"
4245 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
4246 " -d --no-wtmp Don't write wtmp record\n"
4247 " --no-wall Don't send wall message before halt/power-off/reboot\n",
4248 program_invocation_short_name,
4249 arg_action == ACTION_REBOOT ? "Reboot" :
4250 arg_action == ACTION_POWEROFF ? "Power off" :
4256 static int shutdown_help(void) {
4258 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
4259 "Shut down the system.\n\n"
4260 " --help Show this help\n"
4261 " -H --halt Halt the machine\n"
4262 " -P --poweroff Power-off the machine\n"
4263 " -r --reboot Reboot the machine\n"
4264 " -h Equivalent to --poweroff, overridden by --halt\n"
4265 " -k Don't halt/power-off/reboot, just send warnings\n"
4266 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4267 " -c Cancel a pending shutdown\n",
4268 program_invocation_short_name);
4273 static int telinit_help(void) {
4275 printf("%s [OPTIONS...] {COMMAND}\n\n"
4276 "Send control commands to the init daemon.\n\n"
4277 " --help Show this help\n"
4278 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
4280 " 0 Power-off the machine\n"
4281 " 6 Reboot the machine\n"
4282 " 2, 3, 4, 5 Start runlevelX.target unit\n"
4283 " 1, s, S Enter rescue mode\n"
4284 " q, Q Reload init daemon configuration\n"
4285 " u, U Reexecute init daemon\n",
4286 program_invocation_short_name);
4291 static int runlevel_help(void) {
4293 printf("%s [OPTIONS...]\n\n"
4294 "Prints the previous and current runlevel of the init system.\n\n"
4295 " --help Show this help\n",
4296 program_invocation_short_name);
4301 static int help_types(void) {
4304 puts("Available unit types:");
4305 for(i = UNIT_SERVICE; i < _UNIT_TYPE_MAX; i++)
4306 if (unit_type_table[i])
4307 puts(unit_type_table[i]);
4309 puts("\nAvailable unit load states: ");
4310 for(i = UNIT_STUB; i < _UNIT_LOAD_STATE_MAX; i++)
4311 if (unit_type_table[i])
4312 puts(unit_load_state_table[i]);
4317 static int systemctl_parse_argv(int argc, char *argv[]) {
4321 ARG_IGNORE_DEPENDENCIES,
4336 ARG_NO_ASK_PASSWORD,
4342 static const struct option options[] = {
4343 { "help", no_argument, NULL, 'h' },
4344 { "version", no_argument, NULL, ARG_VERSION },
4345 { "type", required_argument, NULL, 't' },
4346 { "property", required_argument, NULL, 'p' },
4347 { "all", no_argument, NULL, 'a' },
4348 { "failed", no_argument, NULL, ARG_FAILED },
4349 { "full", no_argument, NULL, ARG_FULL },
4350 { "fail", no_argument, NULL, ARG_FAIL },
4351 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
4352 { "ignore-inhibitors", no_argument, NULL, 'i' },
4353 { "user", no_argument, NULL, ARG_USER },
4354 { "system", no_argument, NULL, ARG_SYSTEM },
4355 { "global", no_argument, NULL, ARG_GLOBAL },
4356 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
4357 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
4358 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
4359 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4360 { "quiet", no_argument, NULL, 'q' },
4361 { "order", no_argument, NULL, ARG_ORDER },
4362 { "require", no_argument, NULL, ARG_REQUIRE },
4363 { "root", required_argument, NULL, ARG_ROOT },
4364 { "force", no_argument, NULL, ARG_FORCE },
4365 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
4366 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
4367 { "signal", required_argument, NULL, 's' },
4368 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
4369 { "host", required_argument, NULL, 'H' },
4370 { "privileged",no_argument, NULL, 'P' },
4371 { "runtime", no_argument, NULL, ARG_RUNTIME },
4372 { "lines", required_argument, NULL, 'n' },
4373 { "output", required_argument, NULL, 'o' },
4374 { NULL, 0, NULL, 0 }
4382 while ((c = getopt_long(argc, argv, "ht:p:aqfs:H:Pn:o:i", options, NULL)) >= 0) {
4391 puts(PACKAGE_STRING);
4392 puts(SYSTEMD_FEATURES);
4396 if (streq(optarg, "help")) {
4401 if (unit_type_from_string(optarg) >= 0) {
4405 if (unit_load_state_from_string(optarg) >= 0) {
4406 arg_load_state = optarg;
4409 log_error("Unkown unit type or load state '%s'.",
4411 log_info("Use -t help to see a list of allowed values.");
4416 if (!(l = strv_append(arg_property, optarg)))
4419 strv_free(arg_property);
4422 /* If the user asked for a particular
4423 * property, show it to him, even if it is
4434 arg_job_mode = "fail";
4437 case ARG_IGNORE_DEPENDENCIES:
4438 arg_job_mode = "ignore-dependencies";
4442 arg_scope = UNIT_FILE_USER;
4446 arg_scope = UNIT_FILE_SYSTEM;
4450 arg_scope = UNIT_FILE_GLOBAL;
4454 arg_no_block = true;
4458 arg_no_legend = true;
4462 arg_no_pager = true;
4470 arg_dot = DOT_ORDER;
4474 arg_dot = DOT_REQUIRE;
4502 arg_no_reload = true;
4506 arg_kill_who = optarg;
4510 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
4511 log_error("Failed to parse signal string %s.", optarg);
4516 case ARG_NO_ASK_PASSWORD:
4517 arg_ask_password = false;
4521 arg_transport = TRANSPORT_POLKIT;
4525 arg_transport = TRANSPORT_SSH;
4534 if (safe_atou(optarg, &arg_lines) < 0) {
4535 log_error("Failed to parse lines '%s'", optarg);
4541 arg_output = output_mode_from_string(optarg);
4542 if (arg_output < 0) {
4543 log_error("Unknown output '%s'.", optarg);
4549 arg_ignore_inhibitors = true;
4556 log_error("Unknown option code '%c'.", c);
4561 if (arg_transport != TRANSPORT_NORMAL && arg_scope != UNIT_FILE_SYSTEM) {
4562 log_error("Cannot access user instance remotely.");
4569 static int halt_parse_argv(int argc, char *argv[]) {
4578 static const struct option options[] = {
4579 { "help", no_argument, NULL, ARG_HELP },
4580 { "halt", no_argument, NULL, ARG_HALT },
4581 { "poweroff", no_argument, NULL, 'p' },
4582 { "reboot", no_argument, NULL, ARG_REBOOT },
4583 { "force", no_argument, NULL, 'f' },
4584 { "wtmp-only", no_argument, NULL, 'w' },
4585 { "no-wtmp", no_argument, NULL, 'd' },
4586 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4587 { NULL, 0, NULL, 0 }
4595 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
4596 if (runlevel == '0' || runlevel == '6')
4599 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
4607 arg_action = ACTION_HALT;
4611 if (arg_action != ACTION_REBOOT)
4612 arg_action = ACTION_POWEROFF;
4616 arg_action = ACTION_REBOOT;
4638 /* Compatibility nops */
4645 log_error("Unknown option code '%c'.", c);
4650 if (optind < argc) {
4651 log_error("Too many arguments.");
4658 static int parse_time_spec(const char *t, usec_t *_u) {
4662 if (streq(t, "now"))
4664 else if (!strchr(t, ':')) {
4667 if (safe_atou64(t, &u) < 0)
4670 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
4679 hour = strtol(t, &e, 10);
4680 if (errno != 0 || *e != ':' || hour < 0 || hour > 23)
4683 minute = strtol(e+1, &e, 10);
4684 if (errno != 0 || *e != 0 || minute < 0 || minute > 59)
4687 n = now(CLOCK_REALTIME);
4688 s = (time_t) (n / USEC_PER_SEC);
4691 assert_se(localtime_r(&s, &tm));
4693 tm.tm_hour = (int) hour;
4694 tm.tm_min = (int) minute;
4697 assert_se(s = mktime(&tm));
4699 *_u = (usec_t) s * USEC_PER_SEC;
4702 *_u += USEC_PER_DAY;
4708 static int shutdown_parse_argv(int argc, char *argv[]) {
4715 static const struct option options[] = {
4716 { "help", no_argument, NULL, ARG_HELP },
4717 { "halt", no_argument, NULL, 'H' },
4718 { "poweroff", no_argument, NULL, 'P' },
4719 { "reboot", no_argument, NULL, 'r' },
4720 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
4721 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4722 { NULL, 0, NULL, 0 }
4730 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
4738 arg_action = ACTION_HALT;
4742 arg_action = ACTION_POWEROFF;
4747 arg_action = ACTION_KEXEC;
4749 arg_action = ACTION_REBOOT;
4753 arg_action = ACTION_KEXEC;
4757 if (arg_action != ACTION_HALT)
4758 arg_action = ACTION_POWEROFF;
4771 /* Compatibility nops */
4775 arg_action = ACTION_CANCEL_SHUTDOWN;
4782 log_error("Unknown option code '%c'.", c);
4787 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
4788 r = parse_time_spec(argv[optind], &arg_when);
4790 log_error("Failed to parse time specification: %s", argv[optind]);
4794 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
4796 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
4797 /* No time argument for shutdown cancel */
4798 arg_wall = argv + optind;
4799 else if (argc > optind + 1)
4800 /* We skip the time argument */
4801 arg_wall = argv + optind + 1;
4808 static int telinit_parse_argv(int argc, char *argv[]) {
4815 static const struct option options[] = {
4816 { "help", no_argument, NULL, ARG_HELP },
4817 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4818 { NULL, 0, NULL, 0 }
4821 static const struct {
4825 { '0', ACTION_POWEROFF },
4826 { '6', ACTION_REBOOT },
4827 { '1', ACTION_RESCUE },
4828 { '2', ACTION_RUNLEVEL2 },
4829 { '3', ACTION_RUNLEVEL3 },
4830 { '4', ACTION_RUNLEVEL4 },
4831 { '5', ACTION_RUNLEVEL5 },
4832 { 's', ACTION_RESCUE },
4833 { 'S', ACTION_RESCUE },
4834 { 'q', ACTION_RELOAD },
4835 { 'Q', ACTION_RELOAD },
4836 { 'u', ACTION_REEXEC },
4837 { 'U', ACTION_REEXEC }
4846 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4861 log_error("Unknown option code '%c'.", c);
4866 if (optind >= argc) {
4871 if (optind + 1 < argc) {
4872 log_error("Too many arguments.");
4876 if (strlen(argv[optind]) != 1) {
4877 log_error("Expected single character argument.");
4881 for (i = 0; i < ELEMENTSOF(table); i++)
4882 if (table[i].from == argv[optind][0])
4885 if (i >= ELEMENTSOF(table)) {
4886 log_error("Unknown command '%s'.", argv[optind]);
4890 arg_action = table[i].to;
4897 static int runlevel_parse_argv(int argc, char *argv[]) {
4903 static const struct option options[] = {
4904 { "help", no_argument, NULL, ARG_HELP },
4905 { NULL, 0, NULL, 0 }
4913 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4924 log_error("Unknown option code '%c'.", c);
4929 if (optind < argc) {
4930 log_error("Too many arguments.");
4937 static int parse_argv(int argc, char *argv[]) {
4941 if (program_invocation_short_name) {
4943 if (strstr(program_invocation_short_name, "halt")) {
4944 arg_action = ACTION_HALT;
4945 return halt_parse_argv(argc, argv);
4946 } else if (strstr(program_invocation_short_name, "poweroff")) {
4947 arg_action = ACTION_POWEROFF;
4948 return halt_parse_argv(argc, argv);
4949 } else if (strstr(program_invocation_short_name, "reboot")) {
4951 arg_action = ACTION_KEXEC;
4953 arg_action = ACTION_REBOOT;
4954 return halt_parse_argv(argc, argv);
4955 } else if (strstr(program_invocation_short_name, "shutdown")) {
4956 arg_action = ACTION_POWEROFF;
4957 return shutdown_parse_argv(argc, argv);
4958 } else if (strstr(program_invocation_short_name, "init")) {
4960 if (sd_booted() > 0) {
4961 arg_action = ACTION_INVALID;
4962 return telinit_parse_argv(argc, argv);
4964 /* Hmm, so some other init system is
4965 * running, we need to forward this
4966 * request to it. For now we simply
4967 * guess that it is Upstart. */
4969 execv("/lib/upstart/telinit", argv);
4971 log_error("Couldn't find an alternative telinit implementation to spawn.");
4975 } else if (strstr(program_invocation_short_name, "runlevel")) {
4976 arg_action = ACTION_RUNLEVEL;
4977 return runlevel_parse_argv(argc, argv);
4981 arg_action = ACTION_SYSTEMCTL;
4982 return systemctl_parse_argv(argc, argv);
4985 static int action_to_runlevel(void) {
4987 static const char table[_ACTION_MAX] = {
4988 [ACTION_HALT] = '0',
4989 [ACTION_POWEROFF] = '0',
4990 [ACTION_REBOOT] = '6',
4991 [ACTION_RUNLEVEL2] = '2',
4992 [ACTION_RUNLEVEL3] = '3',
4993 [ACTION_RUNLEVEL4] = '4',
4994 [ACTION_RUNLEVEL5] = '5',
4995 [ACTION_RESCUE] = '1'
4998 assert(arg_action < _ACTION_MAX);
5000 return table[arg_action];
5003 static int talk_upstart(void) {
5004 DBusMessage *m = NULL, *reply = NULL;
5006 int previous, rl, r;
5008 env1_buf[] = "RUNLEVEL=X",
5009 env2_buf[] = "PREVLEVEL=X";
5010 char *env1 = env1_buf, *env2 = env2_buf;
5011 const char *emit = "runlevel";
5012 dbus_bool_t b_false = FALSE;
5013 DBusMessageIter iter, sub;
5014 DBusConnection *bus;
5016 dbus_error_init(&error);
5018 if (!(rl = action_to_runlevel()))
5021 if (utmp_get_runlevel(&previous, NULL) < 0)
5024 if (!(bus = dbus_connection_open_private("unix:abstract=/com/ubuntu/upstart", &error))) {
5025 if (dbus_error_has_name(&error, DBUS_ERROR_NO_SERVER)) {
5030 log_error("Failed to connect to Upstart bus: %s", bus_error_message(&error));
5035 if ((r = bus_check_peercred(bus)) < 0) {
5036 log_error("Failed to verify owner of bus.");
5040 if (!(m = dbus_message_new_method_call(
5041 "com.ubuntu.Upstart",
5042 "/com/ubuntu/Upstart",
5043 "com.ubuntu.Upstart0_6",
5046 log_error("Could not allocate message.");
5051 dbus_message_iter_init_append(m, &iter);
5053 env1_buf[sizeof(env1_buf)-2] = rl;
5054 env2_buf[sizeof(env2_buf)-2] = previous;
5056 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &emit) ||
5057 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub) ||
5058 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env1) ||
5059 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env2) ||
5060 !dbus_message_iter_close_container(&iter, &sub) ||
5061 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b_false)) {
5062 log_error("Could not append arguments to message.");
5067 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
5069 if (bus_error_is_no_service(&error)) {
5074 log_error("Failed to issue method call: %s", bus_error_message(&error));
5083 dbus_message_unref(m);
5086 dbus_message_unref(reply);
5089 dbus_connection_flush(bus);
5090 dbus_connection_close(bus);
5091 dbus_connection_unref(bus);
5094 dbus_error_free(&error);
5099 static int talk_initctl(void) {
5100 struct init_request request;
5104 if (!(rl = action_to_runlevel()))
5108 request.magic = INIT_MAGIC;
5109 request.sleeptime = 0;
5110 request.cmd = INIT_CMD_RUNLVL;
5111 request.runlevel = rl;
5113 if ((fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY)) < 0) {
5115 if (errno == ENOENT)
5118 log_error("Failed to open "INIT_FIFO": %m");
5123 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
5124 close_nointr_nofail(fd);
5127 log_error("Failed to write to "INIT_FIFO": %m");
5128 return errno ? -errno : -EIO;
5134 static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
5136 static const struct {
5144 int (* const dispatch)(DBusConnection *bus, char **args);
5146 { "list-units", LESS, 1, list_units },
5147 { "list-unit-files", EQUAL, 1, list_unit_files },
5148 { "list-jobs", EQUAL, 1, list_jobs },
5149 { "clear-jobs", EQUAL, 1, daemon_reload },
5150 { "load", MORE, 2, load_unit },
5151 { "cancel", MORE, 2, cancel_job },
5152 { "start", MORE, 2, start_unit },
5153 { "stop", MORE, 2, start_unit },
5154 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5155 { "reload", MORE, 2, start_unit },
5156 { "restart", MORE, 2, start_unit },
5157 { "try-restart", MORE, 2, start_unit },
5158 { "reload-or-restart", MORE, 2, start_unit },
5159 { "reload-or-try-restart", MORE, 2, start_unit },
5160 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
5161 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5162 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
5163 { "isolate", EQUAL, 2, start_unit },
5164 { "set-cgroup", MORE, 2, set_cgroup },
5165 { "unset-cgroup", MORE, 2, set_cgroup },
5166 { "set-cgroup-attr", MORE, 2, set_cgroup_attr },
5167 { "unset-cgroup-attr", MORE, 2, set_cgroup },
5168 { "kill", MORE, 2, kill_unit },
5169 { "is-active", MORE, 2, check_unit_active },
5170 { "check", MORE, 2, check_unit_active },
5171 { "is-failed", MORE, 2, check_unit_failed },
5172 { "show", MORE, 1, show },
5173 { "status", MORE, 2, show },
5174 { "help", MORE, 2, show },
5175 { "dump", EQUAL, 1, dump },
5176 { "dot", EQUAL, 1, dot },
5177 { "snapshot", LESS, 2, snapshot },
5178 { "delete", MORE, 2, delete_snapshot },
5179 { "daemon-reload", EQUAL, 1, daemon_reload },
5180 { "daemon-reexec", EQUAL, 1, daemon_reload },
5181 { "show-environment", EQUAL, 1, show_enviroment },
5182 { "set-environment", MORE, 2, set_environment },
5183 { "unset-environment", MORE, 2, set_environment },
5184 { "halt", EQUAL, 1, start_special },
5185 { "poweroff", EQUAL, 1, start_special },
5186 { "reboot", EQUAL, 1, start_special },
5187 { "kexec", EQUAL, 1, start_special },
5188 { "suspend", EQUAL, 1, start_special },
5189 { "hibernate", EQUAL, 1, start_special },
5190 { "hybrid-sleep", EQUAL, 1, start_special },
5191 { "default", EQUAL, 1, start_special },
5192 { "rescue", EQUAL, 1, start_special },
5193 { "emergency", EQUAL, 1, start_special },
5194 { "exit", EQUAL, 1, start_special },
5195 { "reset-failed", MORE, 1, reset_failed },
5196 { "enable", MORE, 2, enable_unit },
5197 { "disable", MORE, 2, enable_unit },
5198 { "is-enabled", MORE, 2, unit_is_enabled },
5199 { "reenable", MORE, 2, enable_unit },
5200 { "preset", MORE, 2, enable_unit },
5201 { "mask", MORE, 2, enable_unit },
5202 { "unmask", MORE, 2, enable_unit },
5203 { "link", MORE, 2, enable_unit },
5204 { "switch-root", MORE, 2, switch_root },
5214 left = argc - optind;
5217 /* Special rule: no arguments means "list-units" */
5220 if (streq(argv[optind], "help") && !argv[optind+1]) {
5221 log_error("This command expects one or more "
5222 "unit names. Did you mean --help?");
5226 for (i = 0; i < ELEMENTSOF(verbs); i++)
5227 if (streq(argv[optind], verbs[i].verb))
5230 if (i >= ELEMENTSOF(verbs)) {
5231 log_error("Unknown operation '%s'.", argv[optind]);
5236 switch (verbs[i].argc_cmp) {
5239 if (left != verbs[i].argc) {
5240 log_error("Invalid number of arguments.");
5247 if (left < verbs[i].argc) {
5248 log_error("Too few arguments.");
5255 if (left > verbs[i].argc) {
5256 log_error("Too many arguments.");
5263 assert_not_reached("Unknown comparison operator.");
5266 /* Require a bus connection for all operations but
5268 if (!streq(verbs[i].verb, "enable") &&
5269 !streq(verbs[i].verb, "disable") &&
5270 !streq(verbs[i].verb, "is-enabled") &&
5271 !streq(verbs[i].verb, "list-unit-files") &&
5272 !streq(verbs[i].verb, "reenable") &&
5273 !streq(verbs[i].verb, "preset") &&
5274 !streq(verbs[i].verb, "mask") &&
5275 !streq(verbs[i].verb, "unmask") &&
5276 !streq(verbs[i].verb, "link")) {
5278 if (running_in_chroot() > 0) {
5279 log_info("Running in chroot, ignoring request.");
5283 if (((!streq(verbs[i].verb, "reboot") &&
5284 !streq(verbs[i].verb, "halt") &&
5285 !streq(verbs[i].verb, "poweroff")) || arg_force <= 0) && !bus) {
5286 log_error("Failed to get D-Bus connection: %s",
5287 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5293 if (!bus && !avoid_bus()) {
5294 log_error("Failed to get D-Bus connection: %s",
5295 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5300 return verbs[i].dispatch(bus, argv + optind);
5303 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
5305 struct msghdr msghdr;
5306 struct iovec iovec[2];
5307 union sockaddr_union sockaddr;
5308 struct sd_shutdown_command c;
5310 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
5317 c.dry_run = dry_run;
5321 sockaddr.sa.sa_family = AF_UNIX;
5322 strncpy(sockaddr.un.sun_path, "/run/systemd/shutdownd", sizeof(sockaddr.un.sun_path));
5325 msghdr.msg_name = &sockaddr;
5326 msghdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + sizeof("/run/systemd/shutdownd") - 1;
5329 iovec[0].iov_base = (char*) &c;
5330 iovec[0].iov_len = offsetof(struct sd_shutdown_command, wall_message);
5332 if (isempty(message))
5333 msghdr.msg_iovlen = 1;
5335 iovec[1].iov_base = (char*) message;
5336 iovec[1].iov_len = strlen(message);
5337 msghdr.msg_iovlen = 2;
5339 msghdr.msg_iov = iovec;
5341 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0) {
5342 close_nointr_nofail(fd);
5346 close_nointr_nofail(fd);
5350 static int reload_with_fallback(DBusConnection *bus) {
5353 /* First, try systemd via D-Bus. */
5354 if (daemon_reload(bus, NULL) >= 0)
5358 /* Nothing else worked, so let's try signals */
5359 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
5361 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
5362 log_error("kill() failed: %m");
5369 static int start_with_fallback(DBusConnection *bus) {
5372 /* First, try systemd via D-Bus. */
5373 if (start_unit(bus, NULL) >= 0)
5377 /* Hmm, talking to systemd via D-Bus didn't work. Then
5378 * let's try to talk to Upstart via D-Bus. */
5379 if (talk_upstart() > 0)
5382 /* Nothing else worked, so let's try
5384 if (talk_initctl() > 0)
5387 log_error("Failed to talk to init daemon.");
5391 warn_wall(arg_action);
5395 static _noreturn_ void halt_now(enum action a) {
5397 /* Make sure C-A-D is handled by the kernel from this
5399 reboot(RB_ENABLE_CAD);
5404 log_info("Halting.");
5405 reboot(RB_HALT_SYSTEM);
5408 case ACTION_POWEROFF:
5409 log_info("Powering off.");
5410 reboot(RB_POWER_OFF);
5414 log_info("Rebooting.");
5415 reboot(RB_AUTOBOOT);
5419 assert_not_reached("Unknown halt action.");
5422 assert_not_reached("Uh? This shouldn't happen.");
5425 static int halt_main(DBusConnection *bus) {
5428 r = check_inhibitors(bus, arg_action);
5432 if (geteuid() != 0) {
5433 /* Try logind if we are a normal user and no special
5434 * mode applies. Maybe PolicyKit allows us to shutdown
5437 if (arg_when <= 0 &&
5440 (arg_action == ACTION_POWEROFF ||
5441 arg_action == ACTION_REBOOT)) {
5442 r = reboot_with_logind(bus, arg_action);
5447 log_error("Must be root.");
5454 m = strv_join(arg_wall, " ");
5455 r = send_shutdownd(arg_when,
5456 arg_action == ACTION_HALT ? 'H' :
5457 arg_action == ACTION_POWEROFF ? 'P' :
5458 arg_action == ACTION_KEXEC ? 'K' :
5466 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
5468 char date[FORMAT_TIMESTAMP_MAX];
5470 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
5471 format_timestamp(date, sizeof(date), arg_when));
5476 if (!arg_dry && !arg_force)
5477 return start_with_fallback(bus);
5480 if (sd_booted() > 0)
5481 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
5483 r = utmp_put_shutdown();
5485 log_warning("Failed to write utmp record: %s", strerror(-r));
5492 halt_now(arg_action);
5493 /* We should never reach this. */
5497 static int runlevel_main(void) {
5498 int r, runlevel, previous;
5500 r = utmp_get_runlevel(&runlevel, &previous);
5507 previous <= 0 ? 'N' : previous,
5508 runlevel <= 0 ? 'N' : runlevel);
5513 int main(int argc, char*argv[]) {
5514 int r, retval = EXIT_FAILURE;
5515 DBusConnection *bus = NULL;
5518 dbus_error_init(&error);
5520 setlocale(LC_ALL, "");
5521 log_parse_environment();
5524 r = parse_argv(argc, argv);
5528 retval = EXIT_SUCCESS;
5532 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
5533 * let's shortcut this */
5534 if (arg_action == ACTION_RUNLEVEL) {
5535 r = runlevel_main();
5536 retval = r < 0 ? EXIT_FAILURE : r;
5540 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
5541 log_info("Running in chroot, ignoring request.");
5547 if (arg_transport == TRANSPORT_NORMAL)
5548 bus_connect(arg_scope == UNIT_FILE_SYSTEM ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &bus, &private_bus, &error);
5549 else if (arg_transport == TRANSPORT_POLKIT) {
5550 bus_connect_system_polkit(&bus, &error);
5551 private_bus = false;
5552 } else if (arg_transport == TRANSPORT_SSH) {
5553 bus_connect_system_ssh(NULL, arg_host, &bus, &error);
5554 private_bus = false;
5556 assert_not_reached("Uh, invalid transport...");
5559 switch (arg_action) {
5561 case ACTION_SYSTEMCTL:
5562 r = systemctl_main(bus, argc, argv, &error);
5566 case ACTION_POWEROFF:
5572 case ACTION_RUNLEVEL2:
5573 case ACTION_RUNLEVEL3:
5574 case ACTION_RUNLEVEL4:
5575 case ACTION_RUNLEVEL5:
5577 case ACTION_EMERGENCY:
5578 case ACTION_DEFAULT:
5579 r = start_with_fallback(bus);
5584 r = reload_with_fallback(bus);
5587 case ACTION_CANCEL_SHUTDOWN: {
5591 m = strv_join(arg_wall, " ");
5593 retval = EXIT_FAILURE;
5597 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
5599 log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r));
5604 case ACTION_INVALID:
5605 case ACTION_RUNLEVEL:
5607 assert_not_reached("Unknown action");
5610 retval = r < 0 ? EXIT_FAILURE : r;
5614 dbus_connection_flush(bus);
5615 dbus_connection_close(bus);
5616 dbus_connection_unref(bus);
5619 dbus_error_free(&error);
5623 strv_free(arg_property);
5626 ask_password_agent_close();
5627 polkit_agent_close();