1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
22 #include <sys/reboot.h>
28 #include <sys/ioctl.h>
32 #include <sys/socket.h>
35 #include <sys/prctl.h>
36 #include <dbus/dbus.h>
38 #include <systemd/sd-daemon.h>
39 #include <systemd/sd-shutdown.h>
45 #include "utmp-wtmp.h"
48 #include "path-util.h"
50 #include "dbus-common.h"
51 #include "cgroup-show.h"
52 #include "cgroup-util.h"
54 #include "path-lookup.h"
55 #include "conf-parser.h"
56 #include "exit-status.h"
57 #include "bus-errors.h"
59 #include "unit-name.h"
61 #include "spawn-ask-password-agent.h"
62 #include "spawn-polkit-agent.h"
64 #include "logs-show.h"
65 #include "path-util.h"
67 static const char *arg_type = NULL;
68 static char **arg_property = NULL;
69 static bool arg_all = false;
70 static const char *arg_job_mode = "replace";
71 static UnitFileScope arg_scope = UNIT_FILE_SYSTEM;
72 static bool arg_no_block = false;
73 static bool arg_no_legend = false;
74 static bool arg_no_pager = false;
75 static bool arg_no_wtmp = false;
76 static bool arg_no_sync = false;
77 static bool arg_no_wall = false;
78 static bool arg_no_reload = false;
79 static bool arg_dry = false;
80 static bool arg_quiet = false;
81 static bool arg_full = false;
82 static int arg_force = 0;
83 static bool arg_ask_password = true;
84 static bool arg_failed = false;
85 static bool arg_runtime = false;
86 static char **arg_wall = NULL;
87 static const char *arg_kill_who = NULL;
88 static const char *arg_kill_mode = NULL;
89 static int arg_signal = SIGTERM;
90 static const char *arg_root = NULL;
91 static usec_t arg_when = 0;
112 ACTION_CANCEL_SHUTDOWN,
114 } arg_action = ACTION_SYSTEMCTL;
120 static enum transport {
124 } arg_transport = TRANSPORT_NORMAL;
125 static const char *arg_host = NULL;
126 static bool arg_follow = false;
127 static unsigned arg_lines = 10;
128 static OutputMode arg_output = OUTPUT_SHORT;
130 static bool private_bus = false;
132 static int daemon_reload(DBusConnection *bus, char **args);
133 static void halt_now(enum action a);
135 static bool on_tty(void) {
138 /* Note that this is invoked relatively early, before we start
139 * the pager. That means the value we return reflects whether
140 * we originally were started on a tty, not if we currently
141 * are. But this is intended, since we want colour and so on
142 * when run in our own pager. */
144 if (_unlikely_(t < 0))
145 t = isatty(STDOUT_FILENO) > 0;
150 static void pager_open_if_enabled(void) {
152 /* Cache result before we open the pager */
161 static void ask_password_agent_open_if_enabled(void) {
163 /* Open the password agent as a child process if necessary */
165 if (!arg_ask_password)
168 if (arg_scope != UNIT_FILE_SYSTEM)
171 ask_password_agent_open();
174 static void polkit_agent_open_if_enabled(void) {
176 /* Open the polkit agent as a child process if necessary */
178 if (!arg_ask_password)
181 if (arg_scope != UNIT_FILE_SYSTEM)
187 static const char *ansi_highlight_red(bool b) {
192 return b ? ANSI_HIGHLIGHT_RED_ON : ANSI_HIGHLIGHT_OFF;
195 static const char *ansi_highlight_green(bool b) {
200 return b ? ANSI_HIGHLIGHT_GREEN_ON : ANSI_HIGHLIGHT_OFF;
203 static bool error_is_no_service(const DBusError *error) {
206 if (!dbus_error_is_set(error))
209 if (dbus_error_has_name(error, DBUS_ERROR_NAME_HAS_NO_OWNER))
212 if (dbus_error_has_name(error, DBUS_ERROR_SERVICE_UNKNOWN))
215 return startswith(error->name, "org.freedesktop.DBus.Error.Spawn.");
218 static int translate_bus_error_to_exit_status(int r, const DBusError *error) {
221 if (!dbus_error_is_set(error))
224 if (dbus_error_has_name(error, DBUS_ERROR_ACCESS_DENIED) ||
225 dbus_error_has_name(error, BUS_ERROR_ONLY_BY_DEPENDENCY) ||
226 dbus_error_has_name(error, BUS_ERROR_NO_ISOLATION) ||
227 dbus_error_has_name(error, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE))
228 return EXIT_NOPERMISSION;
230 if (dbus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT))
231 return EXIT_NOTINSTALLED;
233 if (dbus_error_has_name(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE) ||
234 dbus_error_has_name(error, BUS_ERROR_NOT_SUPPORTED))
235 return EXIT_NOTIMPLEMENTED;
237 if (dbus_error_has_name(error, BUS_ERROR_LOAD_FAILED))
238 return EXIT_NOTCONFIGURED;
246 static void warn_wall(enum action a) {
247 static const char *table[_ACTION_MAX] = {
248 [ACTION_HALT] = "The system is going down for system halt NOW!",
249 [ACTION_REBOOT] = "The system is going down for reboot NOW!",
250 [ACTION_POWEROFF] = "The system is going down for power-off NOW!",
251 [ACTION_KEXEC] = "The system is going down for kexec reboot NOW!",
252 [ACTION_RESCUE] = "The system is going down to rescue mode NOW!",
253 [ACTION_EMERGENCY] = "The system is going down to emergency mode NOW!"
262 p = strv_join(arg_wall, " ");
264 log_error("Failed to join strings.");
280 utmp_wall(table[a], NULL);
283 static bool avoid_bus(void) {
285 if (running_in_chroot() > 0)
288 if (sd_booted() <= 0)
291 if (!isempty(arg_root))
294 if (arg_scope == UNIT_FILE_GLOBAL)
302 const char *description;
303 const char *load_state;
304 const char *active_state;
305 const char *sub_state;
306 const char *following;
307 const char *unit_path;
309 const char *job_type;
310 const char *job_path;
313 static int compare_unit_info(const void *a, const void *b) {
315 const struct unit_info *u = a, *v = b;
317 d1 = strrchr(u->id, '.');
318 d2 = strrchr(v->id, '.');
323 if ((r = strcasecmp(d1, d2)) != 0)
327 return strcasecmp(u->id, v->id);
330 static bool output_show_unit(const struct unit_info *u) {
334 return streq(u->active_state, "failed");
336 return (!arg_type || ((dot = strrchr(u->id, '.')) &&
337 streq(dot+1, arg_type))) &&
338 (arg_all || !(streq(u->active_state, "inactive") || u->following[0]) || u->job_id > 0);
341 static void output_units_list(const struct unit_info *unit_infos, unsigned c) {
342 unsigned id_len, max_id_len, active_len, sub_len, job_len, desc_len, n_shown = 0;
343 const struct unit_info *u;
345 max_id_len = sizeof("UNIT")-1;
346 active_len = sizeof("ACTIVE")-1;
347 sub_len = sizeof("SUB")-1;
348 job_len = sizeof("JOB")-1;
351 for (u = unit_infos; u < unit_infos + c; u++) {
352 if (!output_show_unit(u))
355 max_id_len = MAX(max_id_len, strlen(u->id));
356 active_len = MAX(active_len, strlen(u->active_state));
357 sub_len = MAX(sub_len, strlen(u->sub_state));
359 job_len = MAX(job_len, strlen(u->job_type));
364 id_len = MIN(max_id_len, 25);
365 basic_len = 5 + id_len + 6 + active_len + sub_len + job_len;
366 if (basic_len < (unsigned) columns()) {
367 unsigned extra_len, incr;
368 extra_len = columns() - basic_len;
369 /* Either UNIT already got 25, or is fully satisfied.
370 * Grant up to 25 to DESC now. */
371 incr = MIN(extra_len, 25);
374 /* split the remaining space between UNIT and DESC,
375 * but do not give UNIT more than it needs. */
377 incr = MIN(extra_len / 2, max_id_len - id_len);
379 desc_len += extra_len - incr;
385 if (!arg_no_legend) {
386 printf("%-*s %-6s %-*s %-*s %-*s ", id_len, "UNIT", "LOAD",
387 active_len, "ACTIVE", sub_len, "SUB", job_len, "JOB");
388 if (!arg_full && arg_no_pager)
389 printf("%.*s\n", desc_len, "DESCRIPTION");
391 printf("%s\n", "DESCRIPTION");
394 for (u = unit_infos; u < unit_infos + c; u++) {
396 const char *on_loaded, *off_loaded;
397 const char *on_active, *off_active;
399 if (!output_show_unit(u))
404 if (streq(u->load_state, "error")) {
405 on_loaded = ansi_highlight_red(true);
406 off_loaded = ansi_highlight_red(false);
408 on_loaded = off_loaded = "";
410 if (streq(u->active_state, "failed")) {
411 on_active = ansi_highlight_red(true);
412 off_active = ansi_highlight_red(false);
414 on_active = off_active = "";
416 e = arg_full ? NULL : ellipsize(u->id, id_len, 33);
418 printf("%-*s %s%-6s%s %s%-*s %-*s%s %-*s ",
419 id_len, e ? e : u->id,
420 on_loaded, u->load_state, off_loaded,
421 on_active, active_len, u->active_state,
422 sub_len, u->sub_state, off_active,
423 job_len, u->job_id ? u->job_type : "");
424 if (!arg_full && arg_no_pager)
425 printf("%.*s\n", desc_len, u->description);
427 printf("%s\n", u->description);
432 if (!arg_no_legend) {
433 printf("\nLOAD = Reflects whether the unit definition was properly loaded.\n"
434 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
435 "SUB = The low-level unit activation state, values depend on unit type.\n"
436 "JOB = Pending job for the unit.\n");
439 printf("\n%u units listed.\n", n_shown);
441 printf("\n%u units listed. Pass --all to see inactive units, too.\n", n_shown);
445 static int list_units(DBusConnection *bus, char **args) {
446 DBusMessage *m = NULL, *reply = NULL;
449 DBusMessageIter iter, sub, sub2;
450 unsigned c = 0, n_units = 0;
451 struct unit_info *unit_infos = NULL;
453 dbus_error_init(&error);
457 pager_open_if_enabled();
459 if (!(m = dbus_message_new_method_call(
460 "org.freedesktop.systemd1",
461 "/org/freedesktop/systemd1",
462 "org.freedesktop.systemd1.Manager",
464 log_error("Could not allocate message.");
468 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
469 log_error("Failed to issue method call: %s", bus_error_message(&error));
474 if (!dbus_message_iter_init(reply, &iter) ||
475 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
476 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
477 log_error("Failed to parse reply.");
482 dbus_message_iter_recurse(&iter, &sub);
484 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
487 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
488 log_error("Failed to parse reply.");
496 n_units = MAX(2*c, 16);
497 w = realloc(unit_infos, sizeof(struct unit_info) * n_units);
500 log_error("Failed to allocate unit array.");
510 dbus_message_iter_recurse(&sub, &sub2);
512 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->id, true) < 0 ||
513 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->description, true) < 0 ||
514 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->load_state, true) < 0 ||
515 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->active_state, true) < 0 ||
516 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->sub_state, true) < 0 ||
517 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->following, true) < 0 ||
518 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &u->unit_path, true) < 0 ||
519 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &u->job_id, true) < 0 ||
520 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->job_type, true) < 0 ||
521 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &u->job_path, false) < 0) {
522 log_error("Failed to parse reply.");
527 dbus_message_iter_next(&sub);
532 qsort(unit_infos, c, sizeof(struct unit_info), compare_unit_info);
533 output_units_list(unit_infos, c);
540 dbus_message_unref(m);
543 dbus_message_unref(reply);
547 dbus_error_free(&error);
552 static int compare_unit_file_list(const void *a, const void *b) {
554 const UnitFileList *u = a, *v = b;
556 d1 = strrchr(u->path, '.');
557 d2 = strrchr(v->path, '.');
562 r = strcasecmp(d1, d2);
567 return strcasecmp(path_get_file_name(u->path), path_get_file_name(v->path));
570 static bool output_show_unit_file(const UnitFileList *u) {
573 return !arg_type || ((dot = strrchr(u->path, '.')) && streq(dot+1, arg_type));
576 static void output_unit_file_list(const UnitFileList *units, unsigned c) {
577 unsigned max_id_len, id_cols, state_cols, n_shown = 0;
578 const UnitFileList *u;
580 max_id_len = sizeof("UNIT FILE")-1;
581 state_cols = sizeof("STATE")-1;
582 for (u = units; u < units + c; u++) {
583 if (!output_show_unit_file(u))
586 max_id_len = MAX(max_id_len, strlen(path_get_file_name(u->path)));
587 state_cols = MAX(state_cols, strlen(unit_file_state_to_string(u->state)));
592 id_cols = MIN(max_id_len, 25);
593 basic_cols = 1 + id_cols + state_cols;
594 if (basic_cols < (unsigned) columns())
595 id_cols += MIN(columns() - basic_cols, max_id_len - id_cols);
597 id_cols = max_id_len;
600 printf("%-*s %-*s\n", id_cols, "UNIT FILE", state_cols, "STATE");
602 for (u = units; u < units + c; u++) {
604 const char *on, *off;
607 if (!output_show_unit_file(u))
612 if (u->state == UNIT_FILE_MASKED ||
613 u->state == UNIT_FILE_MASKED_RUNTIME ||
614 u->state == UNIT_FILE_DISABLED) {
615 on = ansi_highlight_red(true);
616 off = ansi_highlight_red(false);
617 } else if (u->state == UNIT_FILE_ENABLED) {
618 on = ansi_highlight_green(true);
619 off = ansi_highlight_green(false);
623 id = path_get_file_name(u->path);
625 e = arg_full ? NULL : ellipsize(id, id_cols, 33);
627 printf("%-*s %s%-*s%s\n",
629 on, state_cols, unit_file_state_to_string(u->state), off);
635 printf("\n%u unit files listed.\n", n_shown);
638 static int list_unit_files(DBusConnection *bus, char **args) {
639 DBusMessage *m = NULL, *reply = NULL;
642 DBusMessageIter iter, sub, sub2;
643 unsigned c = 0, n_units = 0;
644 UnitFileList *units = NULL;
646 dbus_error_init(&error);
648 pager_open_if_enabled();
655 h = hashmap_new(string_hash_func, string_compare_func);
657 log_error("Out of memory");
661 r = unit_file_get_list(arg_scope, arg_root, h);
663 unit_file_list_free(h);
664 log_error("Failed to get unit file list: %s", strerror(-r));
668 n_units = hashmap_size(h);
669 units = new(UnitFileList, n_units);
671 unit_file_list_free(h);
672 log_error("Out of memory");
676 HASHMAP_FOREACH(u, h, i) {
677 memcpy(units + c++, u, sizeof(UnitFileList));
685 m = dbus_message_new_method_call(
686 "org.freedesktop.systemd1",
687 "/org/freedesktop/systemd1",
688 "org.freedesktop.systemd1.Manager",
691 log_error("Could not allocate message.");
695 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
697 log_error("Failed to issue method call: %s", bus_error_message(&error));
702 if (!dbus_message_iter_init(reply, &iter) ||
703 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
704 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
705 log_error("Failed to parse reply.");
710 dbus_message_iter_recurse(&iter, &sub);
712 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
716 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
717 log_error("Failed to parse reply.");
725 n_units = MAX(2*c, 16);
726 w = realloc(units, sizeof(struct UnitFileList) * n_units);
729 log_error("Failed to allocate unit array.");
739 dbus_message_iter_recurse(&sub, &sub2);
741 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->path, true) < 0 ||
742 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, false) < 0) {
743 log_error("Failed to parse reply.");
748 u->state = unit_file_state_from_string(state);
750 dbus_message_iter_next(&sub);
756 qsort(units, c, sizeof(UnitFileList), compare_unit_file_list);
757 output_unit_file_list(units, c);
764 dbus_message_unref(m);
767 dbus_message_unref(reply);
771 dbus_error_free(&error);
776 static int dot_one_property(const char *name, const char *prop, DBusMessageIter *iter) {
777 static const char * const colors[] = {
778 "Requires", "[color=\"black\"]",
779 "RequiresOverridable", "[color=\"black\"]",
780 "Requisite", "[color=\"darkblue\"]",
781 "RequisiteOverridable", "[color=\"darkblue\"]",
782 "Wants", "[color=\"darkgrey\"]",
783 "Conflicts", "[color=\"red\"]",
784 "ConflictedBy", "[color=\"red\"]",
785 "After", "[color=\"green\"]"
788 const char *c = NULL;
795 for (i = 0; i < ELEMENTSOF(colors); i += 2)
796 if (streq(colors[i], prop)) {
804 if (arg_dot != DOT_ALL)
805 if ((arg_dot == DOT_ORDER) != streq(prop, "After"))
808 switch (dbus_message_iter_get_arg_type(iter)) {
810 case DBUS_TYPE_ARRAY:
812 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING) {
815 dbus_message_iter_recurse(iter, &sub);
817 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
820 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING);
821 dbus_message_iter_get_basic(&sub, &s);
822 printf("\t\"%s\"->\"%s\" %s;\n", name, s, c);
824 dbus_message_iter_next(&sub);
834 static int dot_one(DBusConnection *bus, const char *name, const char *path) {
835 DBusMessage *m = NULL, *reply = NULL;
836 const char *interface = "org.freedesktop.systemd1.Unit";
839 DBusMessageIter iter, sub, sub2, sub3;
844 dbus_error_init(&error);
846 if (!(m = dbus_message_new_method_call(
847 "org.freedesktop.systemd1",
849 "org.freedesktop.DBus.Properties",
851 log_error("Could not allocate message.");
856 if (!dbus_message_append_args(m,
857 DBUS_TYPE_STRING, &interface,
858 DBUS_TYPE_INVALID)) {
859 log_error("Could not append arguments to message.");
864 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
865 log_error("Failed to issue method call: %s", bus_error_message(&error));
870 if (!dbus_message_iter_init(reply, &iter) ||
871 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
872 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
873 log_error("Failed to parse reply.");
878 dbus_message_iter_recurse(&iter, &sub);
880 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
883 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_DICT_ENTRY) {
884 log_error("Failed to parse reply.");
889 dbus_message_iter_recurse(&sub, &sub2);
891 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &prop, true) < 0) {
892 log_error("Failed to parse reply.");
897 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
898 log_error("Failed to parse reply.");
903 dbus_message_iter_recurse(&sub2, &sub3);
905 if (dot_one_property(name, prop, &sub3)) {
906 log_error("Failed to parse reply.");
911 dbus_message_iter_next(&sub);
918 dbus_message_unref(m);
921 dbus_message_unref(reply);
923 dbus_error_free(&error);
928 static int dot(DBusConnection *bus, char **args) {
929 DBusMessage *m = NULL, *reply = NULL;
932 DBusMessageIter iter, sub, sub2;
934 dbus_error_init(&error);
938 if (!(m = dbus_message_new_method_call(
939 "org.freedesktop.systemd1",
940 "/org/freedesktop/systemd1",
941 "org.freedesktop.systemd1.Manager",
943 log_error("Could not allocate message.");
947 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
948 log_error("Failed to issue method call: %s", bus_error_message(&error));
953 if (!dbus_message_iter_init(reply, &iter) ||
954 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
955 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
956 log_error("Failed to parse reply.");
961 printf("digraph systemd {\n");
963 dbus_message_iter_recurse(&iter, &sub);
964 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
965 const char *id, *description, *load_state, *active_state, *sub_state, *following, *unit_path;
967 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
968 log_error("Failed to parse reply.");
973 dbus_message_iter_recurse(&sub, &sub2);
975 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &id, true) < 0 ||
976 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &description, true) < 0 ||
977 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &load_state, true) < 0 ||
978 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &active_state, true) < 0 ||
979 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &sub_state, true) < 0 ||
980 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &following, true) < 0 ||
981 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, true) < 0) {
982 log_error("Failed to parse reply.");
987 if ((r = dot_one(bus, id, unit_path)) < 0)
990 /* printf("\t\"%s\";\n", id); */
991 dbus_message_iter_next(&sub);
996 log_info(" Color legend: black = Requires\n"
997 " dark blue = Requisite\n"
998 " dark grey = Wants\n"
1000 " green = After\n");
1003 log_notice("-- You probably want to process this output with graphviz' dot tool.\n"
1004 "-- Try a shell pipeline like 'systemctl dot | dot -Tsvg > systemd.svg'!\n");
1010 dbus_message_unref(m);
1013 dbus_message_unref(reply);
1015 dbus_error_free(&error);
1020 static int list_jobs(DBusConnection *bus, char **args) {
1021 DBusMessage *m = NULL, *reply = NULL;
1024 DBusMessageIter iter, sub, sub2;
1027 dbus_error_init(&error);
1031 pager_open_if_enabled();
1033 if (!(m = dbus_message_new_method_call(
1034 "org.freedesktop.systemd1",
1035 "/org/freedesktop/systemd1",
1036 "org.freedesktop.systemd1.Manager",
1038 log_error("Could not allocate message.");
1042 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
1043 log_error("Failed to issue method call: %s", bus_error_message(&error));
1048 if (!dbus_message_iter_init(reply, &iter) ||
1049 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
1050 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
1051 log_error("Failed to parse reply.");
1056 dbus_message_iter_recurse(&iter, &sub);
1059 printf("%4s %-25s %-15s %-7s\n", "JOB", "UNIT", "TYPE", "STATE");
1061 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1062 const char *name, *type, *state, *job_path, *unit_path;
1066 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
1067 log_error("Failed to parse reply.");
1072 dbus_message_iter_recurse(&sub, &sub2);
1074 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &id, true) < 0 ||
1075 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
1076 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
1077 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, true) < 0 ||
1078 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &job_path, true) < 0 ||
1079 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, false) < 0) {
1080 log_error("Failed to parse reply.");
1085 e = arg_full ? NULL : ellipsize(name, 25, 33);
1086 printf("%4u %-25s %-15s %-7s\n", id, e ? e : name, type, state);
1091 dbus_message_iter_next(&sub);
1095 printf("\n%u jobs listed.\n", k);
1101 dbus_message_unref(m);
1104 dbus_message_unref(reply);
1106 dbus_error_free(&error);
1111 static int load_unit(DBusConnection *bus, char **args) {
1112 DBusMessage *m = NULL;
1117 dbus_error_init(&error);
1122 STRV_FOREACH(name, args+1) {
1125 if (!(m = dbus_message_new_method_call(
1126 "org.freedesktop.systemd1",
1127 "/org/freedesktop/systemd1",
1128 "org.freedesktop.systemd1.Manager",
1130 log_error("Could not allocate message.");
1135 if (!dbus_message_append_args(m,
1136 DBUS_TYPE_STRING, name,
1137 DBUS_TYPE_INVALID)) {
1138 log_error("Could not append arguments to message.");
1143 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
1144 log_error("Failed to issue method call: %s", bus_error_message(&error));
1149 dbus_message_unref(m);
1150 dbus_message_unref(reply);
1159 dbus_message_unref(m);
1161 dbus_error_free(&error);
1166 static int cancel_job(DBusConnection *bus, char **args) {
1167 DBusMessage *m = NULL, *reply = NULL;
1172 dbus_error_init(&error);
1177 if (strv_length(args) <= 1)
1178 return daemon_reload(bus, args);
1180 STRV_FOREACH(name, args+1) {
1184 if (!(m = dbus_message_new_method_call(
1185 "org.freedesktop.systemd1",
1186 "/org/freedesktop/systemd1",
1187 "org.freedesktop.systemd1.Manager",
1189 log_error("Could not allocate message.");
1194 if ((r = safe_atou(*name, &id)) < 0) {
1195 log_error("Failed to parse job id: %s", strerror(-r));
1199 assert_cc(sizeof(uint32_t) == sizeof(id));
1200 if (!dbus_message_append_args(m,
1201 DBUS_TYPE_UINT32, &id,
1202 DBUS_TYPE_INVALID)) {
1203 log_error("Could not append arguments to message.");
1208 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
1209 log_error("Failed to issue method call: %s", bus_error_message(&error));
1214 if (!dbus_message_get_args(reply, &error,
1215 DBUS_TYPE_OBJECT_PATH, &path,
1216 DBUS_TYPE_INVALID)) {
1217 log_error("Failed to parse reply: %s", bus_error_message(&error));
1222 dbus_message_unref(m);
1223 if (!(m = dbus_message_new_method_call(
1224 "org.freedesktop.systemd1",
1226 "org.freedesktop.systemd1.Job",
1228 log_error("Could not allocate message.");
1233 dbus_message_unref(reply);
1234 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
1235 log_error("Failed to issue method call: %s", bus_error_message(&error));
1240 dbus_message_unref(m);
1241 dbus_message_unref(reply);
1249 dbus_message_unref(m);
1252 dbus_message_unref(reply);
1254 dbus_error_free(&error);
1259 static bool need_daemon_reload(DBusConnection *bus, const char *unit) {
1260 DBusMessage *m = NULL, *reply = NULL;
1261 dbus_bool_t b = FALSE;
1262 DBusMessageIter iter, sub;
1264 *interface = "org.freedesktop.systemd1.Unit",
1265 *property = "NeedDaemonReload",
1268 /* We ignore all errors here, since this is used to show a warning only */
1270 if (!(m = dbus_message_new_method_call(
1271 "org.freedesktop.systemd1",
1272 "/org/freedesktop/systemd1",
1273 "org.freedesktop.systemd1.Manager",
1277 if (!dbus_message_append_args(m,
1278 DBUS_TYPE_STRING, &unit,
1282 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, NULL)))
1285 if (!dbus_message_get_args(reply, NULL,
1286 DBUS_TYPE_OBJECT_PATH, &path,
1290 dbus_message_unref(m);
1291 if (!(m = dbus_message_new_method_call(
1292 "org.freedesktop.systemd1",
1294 "org.freedesktop.DBus.Properties",
1298 if (!dbus_message_append_args(m,
1299 DBUS_TYPE_STRING, &interface,
1300 DBUS_TYPE_STRING, &property,
1301 DBUS_TYPE_INVALID)) {
1305 dbus_message_unref(reply);
1306 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, NULL)))
1309 if (!dbus_message_iter_init(reply, &iter) ||
1310 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
1313 dbus_message_iter_recurse(&iter, &sub);
1315 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_BOOLEAN)
1318 dbus_message_iter_get_basic(&sub, &b);
1322 dbus_message_unref(m);
1325 dbus_message_unref(reply);
1330 typedef struct WaitData {
1335 static DBusHandlerResult wait_filter(DBusConnection *connection, DBusMessage *message, void *data) {
1343 dbus_error_init(&error);
1345 log_debug("Got D-Bus request: %s.%s() on %s",
1346 dbus_message_get_interface(message),
1347 dbus_message_get_member(message),
1348 dbus_message_get_path(message));
1350 if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
1351 log_error("Warning! D-Bus connection terminated.");
1352 dbus_connection_close(connection);
1354 } else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
1356 const char *path, *result, *unit;
1357 dbus_bool_t success = true;
1359 if (dbus_message_get_args(message, &error,
1360 DBUS_TYPE_UINT32, &id,
1361 DBUS_TYPE_OBJECT_PATH, &path,
1362 DBUS_TYPE_STRING, &unit,
1363 DBUS_TYPE_STRING, &result,
1364 DBUS_TYPE_INVALID)) {
1367 p = set_remove(d->set, (char*) path);
1371 d->result = strdup(result);
1376 dbus_error_free(&error);
1377 if (dbus_message_get_args(message, &error,
1378 DBUS_TYPE_UINT32, &id,
1379 DBUS_TYPE_OBJECT_PATH, &path,
1380 DBUS_TYPE_STRING, &result,
1381 DBUS_TYPE_INVALID)) {
1384 /* Compatibility with older systemd versions <
1385 * 183 during upgrades. This should be dropped
1387 p = set_remove(d->set, (char*) path);
1391 d->result = strdup(result);
1396 dbus_error_free(&error);
1397 if (dbus_message_get_args(message, &error,
1398 DBUS_TYPE_UINT32, &id,
1399 DBUS_TYPE_OBJECT_PATH, &path,
1400 DBUS_TYPE_BOOLEAN, &success,
1401 DBUS_TYPE_INVALID)) {
1404 /* Compatibility with older systemd versions <
1405 * 19 during upgrades. This should be dropped
1408 p = set_remove(d->set, (char*) path);
1412 d->result = strdup("failed");
1418 log_error("Failed to parse message: %s", bus_error_message(&error));
1422 dbus_error_free(&error);
1423 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1426 static int enable_wait_for_jobs(DBusConnection *bus) {
1434 dbus_error_init(&error);
1435 dbus_bus_add_match(bus,
1437 "sender='org.freedesktop.systemd1',"
1438 "interface='org.freedesktop.systemd1.Manager',"
1439 "member='JobRemoved',"
1440 "path='/org/freedesktop/systemd1'",
1443 if (dbus_error_is_set(&error)) {
1444 log_error("Failed to add match: %s", bus_error_message(&error));
1445 dbus_error_free(&error);
1449 /* This is slightly dirty, since we don't undo the match registrations. */
1453 static int wait_for_jobs(DBusConnection *bus, Set *s) {
1463 if (!dbus_connection_add_filter(bus, wait_filter, &d, NULL)) {
1464 log_error("Failed to add filter.");
1469 while (!set_isempty(s) &&
1470 dbus_connection_read_write_dispatch(bus, -1))
1473 if (!arg_quiet && d.result) {
1474 if (streq(d.result, "timeout"))
1475 log_error("Job timed out.");
1476 else if (streq(d.result, "canceled"))
1477 log_error("Job canceled.");
1478 else if (streq(d.result, "dependency"))
1479 log_error("A dependency job failed. See system journal for details.");
1480 else if (!streq(d.result, "done") && !streq(d.result, "skipped"))
1481 log_error("Job failed. See system journal and 'systemctl status' for details.");
1484 if (streq_ptr(d.result, "timeout"))
1486 else if (streq_ptr(d.result, "canceled"))
1488 else if (!streq_ptr(d.result, "done") && !streq_ptr(d.result, "skipped"))
1496 /* This is slightly dirty, since we don't undo the filter registration. */
1501 static int start_unit_one(
1502 DBusConnection *bus,
1509 DBusMessage *m = NULL, *reply = NULL;
1518 assert(arg_no_block || s);
1520 if (!(m = dbus_message_new_method_call(
1521 "org.freedesktop.systemd1",
1522 "/org/freedesktop/systemd1",
1523 "org.freedesktop.systemd1.Manager",
1525 log_error("Could not allocate message.");
1530 if (!dbus_message_append_args(m,
1531 DBUS_TYPE_STRING, &name,
1532 DBUS_TYPE_STRING, &mode,
1533 DBUS_TYPE_INVALID)) {
1534 log_error("Could not append arguments to message.");
1539 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, error))) {
1541 if (arg_action != ACTION_SYSTEMCTL && error_is_no_service(error)) {
1542 /* There's always a fallback possible for
1543 * 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));
1561 if (need_daemon_reload(bus, name))
1562 log_warning("Warning: Unit file of created job changed on disk, 'systemctl %s daemon-reload' recommended.",
1563 arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
1565 if (!arg_no_block) {
1568 if (!(p = strdup(path))) {
1569 log_error("Failed to duplicate path.");
1574 if ((r = set_put(s, p)) < 0) {
1576 log_error("Failed to add path to set.");
1585 dbus_message_unref(m);
1588 dbus_message_unref(reply);
1593 static enum action verb_to_action(const char *verb) {
1594 if (streq(verb, "halt"))
1596 else if (streq(verb, "poweroff"))
1597 return ACTION_POWEROFF;
1598 else if (streq(verb, "reboot"))
1599 return ACTION_REBOOT;
1600 else if (streq(verb, "kexec"))
1601 return ACTION_KEXEC;
1602 else if (streq(verb, "rescue"))
1603 return ACTION_RESCUE;
1604 else if (streq(verb, "emergency"))
1605 return ACTION_EMERGENCY;
1606 else if (streq(verb, "default"))
1607 return ACTION_DEFAULT;
1608 else if (streq(verb, "exit"))
1610 else if (streq(verb, "suspend"))
1611 return ACTION_SUSPEND;
1612 else if (streq(verb, "hibernate"))
1613 return ACTION_HIBERNATE;
1615 return ACTION_INVALID;
1618 static int start_unit(DBusConnection *bus, char **args) {
1620 static const char * const table[_ACTION_MAX] = {
1621 [ACTION_HALT] = SPECIAL_HALT_TARGET,
1622 [ACTION_POWEROFF] = SPECIAL_POWEROFF_TARGET,
1623 [ACTION_REBOOT] = SPECIAL_REBOOT_TARGET,
1624 [ACTION_KEXEC] = SPECIAL_KEXEC_TARGET,
1625 [ACTION_RUNLEVEL2] = SPECIAL_RUNLEVEL2_TARGET,
1626 [ACTION_RUNLEVEL3] = SPECIAL_RUNLEVEL3_TARGET,
1627 [ACTION_RUNLEVEL4] = SPECIAL_RUNLEVEL4_TARGET,
1628 [ACTION_RUNLEVEL5] = SPECIAL_RUNLEVEL5_TARGET,
1629 [ACTION_RESCUE] = SPECIAL_RESCUE_TARGET,
1630 [ACTION_EMERGENCY] = SPECIAL_EMERGENCY_TARGET,
1631 [ACTION_DEFAULT] = SPECIAL_DEFAULT_TARGET,
1632 [ACTION_EXIT] = SPECIAL_EXIT_TARGET,
1633 [ACTION_SUSPEND] = SPECIAL_SUSPEND_TARGET,
1634 [ACTION_HIBERNATE] = SPECIAL_HIBERNATE_TARGET
1638 const char *method, *mode, *one_name;
1643 dbus_error_init(&error);
1647 ask_password_agent_open_if_enabled();
1649 if (arg_action == ACTION_SYSTEMCTL) {
1651 streq(args[0], "stop") ||
1652 streq(args[0], "condstop") ? "StopUnit" :
1653 streq(args[0], "reload") ? "ReloadUnit" :
1654 streq(args[0], "restart") ? "RestartUnit" :
1656 streq(args[0], "try-restart") ||
1657 streq(args[0], "condrestart") ? "TryRestartUnit" :
1659 streq(args[0], "reload-or-restart") ? "ReloadOrRestartUnit" :
1661 streq(args[0], "reload-or-try-restart") ||
1662 streq(args[0], "condreload") ||
1664 streq(args[0], "force-reload") ? "ReloadOrTryRestartUnit" :
1668 (streq(args[0], "isolate") ||
1669 streq(args[0], "rescue") ||
1670 streq(args[0], "emergency")) ? "isolate" : arg_job_mode;
1672 one_name = table[verb_to_action(args[0])];
1675 assert(arg_action < ELEMENTSOF(table));
1676 assert(table[arg_action]);
1678 method = "StartUnit";
1680 mode = (arg_action == ACTION_EMERGENCY ||
1681 arg_action == ACTION_RESCUE ||
1682 arg_action == ACTION_RUNLEVEL2 ||
1683 arg_action == ACTION_RUNLEVEL3 ||
1684 arg_action == ACTION_RUNLEVEL4 ||
1685 arg_action == ACTION_RUNLEVEL5) ? "isolate" : "replace";
1687 one_name = table[arg_action];
1690 if (!arg_no_block) {
1691 if ((ret = enable_wait_for_jobs(bus)) < 0) {
1692 log_error("Could not watch jobs: %s", strerror(-ret));
1696 if (!(s = set_new(string_hash_func, string_compare_func))) {
1697 log_error("Failed to allocate set.");
1704 if ((ret = start_unit_one(bus, method, one_name, mode, &error, s)) <= 0)
1707 STRV_FOREACH(name, args+1)
1708 if ((r = start_unit_one(bus, method, *name, mode, &error, s)) != 0) {
1709 ret = translate_bus_error_to_exit_status(r, &error);
1710 dbus_error_free(&error);
1715 if ((r = wait_for_jobs(bus, s)) < 0) {
1724 dbus_error_free(&error);
1729 /* Ask systemd-logind, which might grant access to unprivileged users
1730 * through PolicyKit */
1731 static int reboot_with_logind(DBusConnection *bus, enum action a) {
1734 DBusMessage *m = NULL, *reply = NULL;
1736 dbus_bool_t interactive = true;
1739 dbus_error_init(&error);
1741 polkit_agent_open_if_enabled();
1749 case ACTION_POWEROFF:
1750 method = "PowerOff";
1753 case ACTION_SUSPEND:
1757 case ACTION_HIBERNATE:
1758 method = "Hibernate";
1765 m = dbus_message_new_method_call(
1766 "org.freedesktop.login1",
1767 "/org/freedesktop/login1",
1768 "org.freedesktop.login1.Manager",
1771 log_error("Could not allocate message.");
1776 if (!dbus_message_append_args(m,
1777 DBUS_TYPE_BOOLEAN, &interactive,
1778 DBUS_TYPE_INVALID)) {
1779 log_error("Could not append arguments to message.");
1784 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
1786 if (error_is_no_service(&error)) {
1787 log_debug("Failed to issue method call: %s", bus_error_message(&error));
1792 if (dbus_error_has_name(&error, DBUS_ERROR_ACCESS_DENIED)) {
1793 log_debug("Failed to issue method call: %s", bus_error_message(&error));
1798 log_info("Failed to issue method call: %s", bus_error_message(&error));
1807 dbus_message_unref(m);
1810 dbus_message_unref(reply);
1812 dbus_error_free(&error);
1820 static int start_special(DBusConnection *bus, char **args) {
1826 a = verb_to_action(args[0]);
1828 if (arg_force >= 2 && geteuid() != 0) {
1829 log_error("Must be root.");
1833 if (arg_force >= 2 &&
1834 (a == ACTION_HALT ||
1835 a == ACTION_POWEROFF ||
1836 a == ACTION_REBOOT))
1839 if (arg_force >= 1 &&
1840 (a == ACTION_HALT ||
1841 a == ACTION_POWEROFF ||
1842 a == ACTION_REBOOT ||
1843 a == ACTION_KEXEC ||
1845 return daemon_reload(bus, args);
1847 /* first try logind, to allow authentication with polkit */
1848 if (geteuid() != 0 &&
1849 (a == ACTION_POWEROFF ||
1850 a == ACTION_REBOOT ||
1851 a == ACTION_SUSPEND ||
1852 a == ACTION_HIBERNATE)) {
1853 r = reboot_with_logind(bus, a);
1858 r = start_unit(bus, args);
1865 static int check_unit(DBusConnection *bus, char **args) {
1866 DBusMessage *m = NULL, *reply = NULL;
1868 *interface = "org.freedesktop.systemd1.Unit",
1869 *property = "ActiveState";
1870 int r = 3; /* According to LSB: "program is not running" */
1877 dbus_error_init(&error);
1879 STRV_FOREACH(name, args+1) {
1880 const char *path = NULL;
1882 DBusMessageIter iter, sub;
1884 if (!(m = dbus_message_new_method_call(
1885 "org.freedesktop.systemd1",
1886 "/org/freedesktop/systemd1",
1887 "org.freedesktop.systemd1.Manager",
1889 log_error("Could not allocate message.");
1894 if (!dbus_message_append_args(m,
1895 DBUS_TYPE_STRING, name,
1896 DBUS_TYPE_INVALID)) {
1897 log_error("Could not append arguments to message.");
1902 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
1904 /* Hmm, cannot figure out anything about this unit... */
1908 dbus_error_free(&error);
1909 dbus_message_unref(m);
1914 if (!dbus_message_get_args(reply, &error,
1915 DBUS_TYPE_OBJECT_PATH, &path,
1916 DBUS_TYPE_INVALID)) {
1917 log_error("Failed to parse reply: %s", bus_error_message(&error));
1922 dbus_message_unref(m);
1923 if (!(m = dbus_message_new_method_call(
1924 "org.freedesktop.systemd1",
1926 "org.freedesktop.DBus.Properties",
1928 log_error("Could not allocate message.");
1933 if (!dbus_message_append_args(m,
1934 DBUS_TYPE_STRING, &interface,
1935 DBUS_TYPE_STRING, &property,
1936 DBUS_TYPE_INVALID)) {
1937 log_error("Could not append arguments to message.");
1942 dbus_message_unref(reply);
1943 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
1944 log_error("Failed to issue method call: %s", bus_error_message(&error));
1949 if (!dbus_message_iter_init(reply, &iter) ||
1950 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1951 log_error("Failed to parse reply.");
1956 dbus_message_iter_recurse(&iter, &sub);
1958 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1959 log_error("Failed to parse reply.");
1964 dbus_message_iter_get_basic(&sub, &state);
1969 if (streq(state, "active") || streq(state, "reloading"))
1972 dbus_message_unref(m);
1973 dbus_message_unref(reply);
1979 dbus_message_unref(m);
1982 dbus_message_unref(reply);
1984 dbus_error_free(&error);
1989 static int kill_unit(DBusConnection *bus, char **args) {
1990 DBusMessage *m = NULL;
1998 dbus_error_init(&error);
2001 arg_kill_who = "all";
2004 arg_kill_mode = streq(arg_kill_who, "all") ? "control-group" : "process";
2006 STRV_FOREACH(name, args+1) {
2009 if (!(m = dbus_message_new_method_call(
2010 "org.freedesktop.systemd1",
2011 "/org/freedesktop/systemd1",
2012 "org.freedesktop.systemd1.Manager",
2014 log_error("Could not allocate message.");
2019 if (!dbus_message_append_args(m,
2020 DBUS_TYPE_STRING, name,
2021 DBUS_TYPE_STRING, &arg_kill_who,
2022 DBUS_TYPE_STRING, &arg_kill_mode,
2023 DBUS_TYPE_INT32, &arg_signal,
2024 DBUS_TYPE_INVALID)) {
2025 log_error("Could not append arguments to message.");
2030 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
2031 log_error("Failed to issue method call: %s", bus_error_message(&error));
2032 dbus_error_free(&error);
2036 dbus_message_unref(m);
2039 dbus_message_unref(reply);
2045 dbus_message_unref(m);
2047 dbus_error_free(&error);
2052 typedef struct ExecStatusInfo {
2060 usec_t start_timestamp;
2061 usec_t exit_timestamp;
2066 LIST_FIELDS(struct ExecStatusInfo, exec);
2069 static void exec_status_info_free(ExecStatusInfo *i) {
2078 static int exec_status_info_deserialize(DBusMessageIter *sub, ExecStatusInfo *i) {
2079 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
2080 DBusMessageIter sub2, sub3;
2084 int32_t code, status;
2090 if (dbus_message_iter_get_arg_type(sub) != DBUS_TYPE_STRUCT)
2093 dbus_message_iter_recurse(sub, &sub2);
2095 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0)
2098 if (!(i->path = strdup(path)))
2101 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_ARRAY ||
2102 dbus_message_iter_get_element_type(&sub2) != DBUS_TYPE_STRING)
2106 dbus_message_iter_recurse(&sub2, &sub3);
2107 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2108 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2109 dbus_message_iter_next(&sub3);
2114 if (!(i->argv = new0(char*, n+1)))
2118 dbus_message_iter_recurse(&sub2, &sub3);
2119 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2122 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2123 dbus_message_iter_get_basic(&sub3, &s);
2124 dbus_message_iter_next(&sub3);
2126 if (!(i->argv[n++] = strdup(s)))
2130 if (!dbus_message_iter_next(&sub2) ||
2131 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, true) < 0 ||
2132 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp, true) < 0 ||
2133 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp_monotonic, true) < 0 ||
2134 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp, true) < 0 ||
2135 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp_monotonic, true) < 0 ||
2136 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, true) < 0 ||
2137 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &code, true) < 0 ||
2138 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &status, false) < 0)
2142 i->start_timestamp = (usec_t) start_timestamp;
2143 i->exit_timestamp = (usec_t) exit_timestamp;
2144 i->pid = (pid_t) pid;
2151 typedef struct UnitStatusInfo {
2153 const char *load_state;
2154 const char *active_state;
2155 const char *sub_state;
2156 const char *unit_file_state;
2158 const char *description;
2159 const char *following;
2161 char **documentation;
2163 const char *fragment_path;
2164 const char *source_path;
2165 const char *default_control_group;
2167 const char *load_error;
2170 usec_t inactive_exit_timestamp;
2171 usec_t inactive_exit_timestamp_monotonic;
2172 usec_t active_enter_timestamp;
2173 usec_t active_exit_timestamp;
2174 usec_t inactive_enter_timestamp;
2176 bool need_daemon_reload;
2181 const char *status_text;
2184 usec_t start_timestamp;
2185 usec_t exit_timestamp;
2187 int exit_code, exit_status;
2189 usec_t condition_timestamp;
2190 bool condition_result;
2193 unsigned n_accepted;
2194 unsigned n_connections;
2198 const char *sysfs_path;
2200 /* Mount, Automount */
2206 LIST_HEAD(ExecStatusInfo, exec);
2209 static void print_status_info(UnitStatusInfo *i) {
2211 const char *on, *off, *ss;
2213 char since1[FORMAT_TIMESTAMP_PRETTY_MAX], *s1;
2214 char since2[FORMAT_TIMESTAMP_MAX], *s2;
2219 /* This shows pretty information about a unit. See
2220 * print_property() for a low-level property printer */
2222 printf("%s", strna(i->id));
2224 if (i->description && !streq_ptr(i->id, i->description))
2225 printf(" - %s", i->description);
2230 printf("\t Follow: unit currently follows state of %s\n", i->following);
2232 if (streq_ptr(i->load_state, "error")) {
2233 on = ansi_highlight_red(true);
2234 off = ansi_highlight_red(false);
2238 path = i->source_path ? i->source_path : i->fragment_path;
2241 printf("\t Loaded: %s%s%s (Reason: %s)\n", on, strna(i->load_state), off, i->load_error);
2242 else if (path && i->unit_file_state)
2243 printf("\t Loaded: %s%s%s (%s; %s)\n", on, strna(i->load_state), off, path, i->unit_file_state);
2245 printf("\t Loaded: %s%s%s (%s)\n", on, strna(i->load_state), off, path);
2247 printf("\t Loaded: %s%s%s\n", on, strna(i->load_state), off);
2249 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
2251 if (streq_ptr(i->active_state, "failed")) {
2252 on = ansi_highlight_red(true);
2253 off = ansi_highlight_red(false);
2254 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
2255 on = ansi_highlight_green(true);
2256 off = ansi_highlight_green(false);
2261 printf("\t Active: %s%s (%s)%s",
2263 strna(i->active_state),
2267 printf("\t Active: %s%s%s",
2269 strna(i->active_state),
2272 if (!isempty(i->result) && !streq(i->result, "success"))
2273 printf(" (Result: %s)", i->result);
2275 timestamp = (streq_ptr(i->active_state, "active") ||
2276 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
2277 (streq_ptr(i->active_state, "inactive") ||
2278 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
2279 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
2280 i->active_exit_timestamp;
2282 s1 = format_timestamp_pretty(since1, sizeof(since1), timestamp);
2283 s2 = format_timestamp(since2, sizeof(since2), timestamp);
2286 printf(" since %s; %s\n", s2, s1);
2288 printf(" since %s\n", s2);
2292 if (!i->condition_result && i->condition_timestamp > 0) {
2293 s1 = format_timestamp_pretty(since1, sizeof(since1), i->condition_timestamp);
2294 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
2297 printf("\t start condition failed at %s; %s\n", s2, s1);
2299 printf("\t start condition failed at %s\n", s2);
2303 printf("\t Device: %s\n", i->sysfs_path);
2305 printf("\t Where: %s\n", i->where);
2307 printf("\t What: %s\n", i->what);
2309 if (!strv_isempty(i->documentation)) {
2313 STRV_FOREACH(t, i->documentation) {
2315 printf("\t Docs: %s\n", *t);
2318 printf("\t %s\n", *t);
2323 printf("\tAccepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
2325 LIST_FOREACH(exec, p, i->exec) {
2329 /* Only show exited processes here */
2333 t = strv_join(p->argv, " ");
2334 printf("\t Process: %u %s=%s ", p->pid, p->name, strna(t));
2337 good = is_clean_exit_lsb(p->code, p->status);
2339 on = ansi_highlight_red(true);
2340 off = ansi_highlight_red(false);
2344 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
2346 if (p->code == CLD_EXITED) {
2349 printf("status=%i", p->status);
2351 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
2356 printf("signal=%s", signal_to_string(p->status));
2358 printf(")%s\n", off);
2360 if (i->main_pid == p->pid &&
2361 i->start_timestamp == p->start_timestamp &&
2362 i->exit_timestamp == p->start_timestamp)
2363 /* Let's not show this twice */
2366 if (p->pid == i->control_pid)
2370 if (i->main_pid > 0 || i->control_pid > 0) {
2373 if (i->main_pid > 0) {
2374 printf("Main PID: %u", (unsigned) i->main_pid);
2378 get_process_comm(i->main_pid, &t);
2383 } else if (i->exit_code > 0) {
2384 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
2386 if (i->exit_code == CLD_EXITED) {
2389 printf("status=%i", i->exit_status);
2391 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
2396 printf("signal=%s", signal_to_string(i->exit_status));
2401 if (i->main_pid > 0 && i->control_pid > 0)
2404 if (i->control_pid > 0) {
2407 printf(" Control: %u", (unsigned) i->control_pid);
2409 get_process_comm(i->control_pid, &t);
2420 printf("\t Status: \"%s\"\n", i->status_text);
2422 if (i->default_control_group) {
2425 printf("\t CGroup: %s\n", i->default_control_group);
2427 if (arg_transport != TRANSPORT_SSH) {
2437 if (i->main_pid > 0)
2438 extra[k++] = i->main_pid;
2440 if (i->control_pid > 0)
2441 extra[k++] = i->control_pid;
2443 show_cgroup_and_extra_by_spec(i->default_control_group, "\t\t ", c, false, arg_all, extra, k);
2447 if (i->id && arg_transport != TRANSPORT_SSH) {
2449 show_journal_by_unit(i->id, arg_output, 0, i->inactive_exit_timestamp_monotonic, arg_lines, arg_all, arg_follow);
2452 if (i->need_daemon_reload)
2453 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %s daemon-reload' recommended.\n",
2454 ansi_highlight_red(true),
2455 ansi_highlight_red(false),
2456 arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
2459 static int status_property(const char *name, DBusMessageIter *iter, UnitStatusInfo *i) {
2465 switch (dbus_message_iter_get_arg_type(iter)) {
2467 case DBUS_TYPE_STRING: {
2470 dbus_message_iter_get_basic(iter, &s);
2473 if (streq(name, "Id"))
2475 else if (streq(name, "LoadState"))
2477 else if (streq(name, "ActiveState"))
2478 i->active_state = s;
2479 else if (streq(name, "SubState"))
2481 else if (streq(name, "Description"))
2483 else if (streq(name, "FragmentPath"))
2484 i->fragment_path = s;
2485 else if (streq(name, "SourcePath"))
2487 else if (streq(name, "DefaultControlGroup"))
2488 i->default_control_group = s;
2489 else if (streq(name, "StatusText"))
2491 else if (streq(name, "SysFSPath"))
2493 else if (streq(name, "Where"))
2495 else if (streq(name, "What"))
2497 else if (streq(name, "Following"))
2499 else if (streq(name, "UnitFileState"))
2500 i->unit_file_state = s;
2501 else if (streq(name, "Result"))
2508 case DBUS_TYPE_BOOLEAN: {
2511 dbus_message_iter_get_basic(iter, &b);
2513 if (streq(name, "Accept"))
2515 else if (streq(name, "NeedDaemonReload"))
2516 i->need_daemon_reload = b;
2517 else if (streq(name, "ConditionResult"))
2518 i->condition_result = b;
2523 case DBUS_TYPE_UINT32: {
2526 dbus_message_iter_get_basic(iter, &u);
2528 if (streq(name, "MainPID")) {
2530 i->main_pid = (pid_t) u;
2533 } else if (streq(name, "ControlPID"))
2534 i->control_pid = (pid_t) u;
2535 else if (streq(name, "ExecMainPID")) {
2537 i->main_pid = (pid_t) u;
2538 } else if (streq(name, "NAccepted"))
2540 else if (streq(name, "NConnections"))
2541 i->n_connections = u;
2546 case DBUS_TYPE_INT32: {
2549 dbus_message_iter_get_basic(iter, &j);
2551 if (streq(name, "ExecMainCode"))
2552 i->exit_code = (int) j;
2553 else if (streq(name, "ExecMainStatus"))
2554 i->exit_status = (int) j;
2559 case DBUS_TYPE_UINT64: {
2562 dbus_message_iter_get_basic(iter, &u);
2564 if (streq(name, "ExecMainStartTimestamp"))
2565 i->start_timestamp = (usec_t) u;
2566 else if (streq(name, "ExecMainExitTimestamp"))
2567 i->exit_timestamp = (usec_t) u;
2568 else if (streq(name, "ActiveEnterTimestamp"))
2569 i->active_enter_timestamp = (usec_t) u;
2570 else if (streq(name, "InactiveEnterTimestamp"))
2571 i->inactive_enter_timestamp = (usec_t) u;
2572 else if (streq(name, "InactiveExitTimestamp"))
2573 i->inactive_exit_timestamp = (usec_t) u;
2574 else if (streq(name, "InactiveExitTimestampMonotonic"))
2575 i->inactive_exit_timestamp_monotonic = (usec_t) u;
2576 else if (streq(name, "ActiveExitTimestamp"))
2577 i->active_exit_timestamp = (usec_t) u;
2578 else if (streq(name, "ConditionTimestamp"))
2579 i->condition_timestamp = (usec_t) u;
2584 case DBUS_TYPE_ARRAY: {
2586 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
2587 startswith(name, "Exec")) {
2588 DBusMessageIter sub;
2590 dbus_message_iter_recurse(iter, &sub);
2591 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2592 ExecStatusInfo *info;
2595 if (!(info = new0(ExecStatusInfo, 1)))
2598 if (!(info->name = strdup(name))) {
2603 if ((r = exec_status_info_deserialize(&sub, info)) < 0) {
2608 LIST_PREPEND(ExecStatusInfo, exec, i->exec, info);
2610 dbus_message_iter_next(&sub);
2612 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
2613 streq(name, "Documentation")) {
2615 DBusMessageIter sub;
2617 dbus_message_iter_recurse(iter, &sub);
2618 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING) {
2622 dbus_message_iter_get_basic(&sub, &s);
2624 l = strv_append(i->documentation, s);
2628 strv_free(i->documentation);
2629 i->documentation = l;
2631 dbus_message_iter_next(&sub);
2638 case DBUS_TYPE_STRUCT: {
2640 if (streq(name, "LoadError")) {
2641 DBusMessageIter sub;
2642 const char *n, *message;
2645 dbus_message_iter_recurse(iter, &sub);
2647 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &n, true);
2651 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &message, false);
2655 if (!isempty(message))
2656 i->load_error = message;
2666 static int print_property(const char *name, DBusMessageIter *iter) {
2670 /* This is a low-level property printer, see
2671 * print_status_info() for the nicer output */
2673 if (arg_property && !strv_find(arg_property, name))
2676 switch (dbus_message_iter_get_arg_type(iter)) {
2678 case DBUS_TYPE_STRUCT: {
2679 DBusMessageIter sub;
2680 dbus_message_iter_recurse(iter, &sub);
2682 if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32 && streq(name, "Job")) {
2685 dbus_message_iter_get_basic(&sub, &u);
2688 printf("%s=%u\n", name, (unsigned) u);
2690 printf("%s=\n", name);
2693 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "Unit")) {
2696 dbus_message_iter_get_basic(&sub, &s);
2698 if (arg_all || s[0])
2699 printf("%s=%s\n", name, s);
2702 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "LoadError")) {
2703 const char *a = NULL, *b = NULL;
2705 if (bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &a, true) >= 0)
2706 bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &b, false);
2708 if (arg_all || !isempty(a) || !isempty(b))
2709 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
2717 case DBUS_TYPE_ARRAY:
2719 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "EnvironmentFiles")) {
2720 DBusMessageIter sub, sub2;
2722 dbus_message_iter_recurse(iter, &sub);
2723 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2727 dbus_message_iter_recurse(&sub, &sub2);
2729 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
2730 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) >= 0)
2731 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
2733 dbus_message_iter_next(&sub);
2738 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Paths")) {
2739 DBusMessageIter sub, sub2;
2741 dbus_message_iter_recurse(iter, &sub);
2742 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2743 const char *type, *path;
2745 dbus_message_iter_recurse(&sub, &sub2);
2747 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
2748 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
2749 printf("%s=%s\n", type, path);
2751 dbus_message_iter_next(&sub);
2756 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Timers")) {
2757 DBusMessageIter sub, sub2;
2759 dbus_message_iter_recurse(iter, &sub);
2760 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2762 uint64_t value, next_elapse;
2764 dbus_message_iter_recurse(&sub, &sub2);
2766 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &base, true) >= 0 &&
2767 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &value, true) >= 0 &&
2768 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &next_elapse, false) >= 0) {
2769 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
2771 printf("%s={ value=%s ; next_elapse=%s }\n",
2773 format_timespan(timespan1, sizeof(timespan1), value),
2774 format_timespan(timespan2, sizeof(timespan2), next_elapse));
2777 dbus_message_iter_next(&sub);
2782 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "ControlGroupAttributes")) {
2783 DBusMessageIter sub, sub2;
2785 dbus_message_iter_recurse(iter, &sub);
2786 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2787 const char *controller, *attr, *value;
2789 dbus_message_iter_recurse(&sub, &sub2);
2791 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &controller, true) >= 0 &&
2792 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &attr, true) >= 0 &&
2793 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &value, false) >= 0) {
2795 printf("ControlGroupAttribute={ controller=%s ; attribute=%s ; value=\"%s\" }\n",
2801 dbus_message_iter_next(&sub);
2806 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && startswith(name, "Exec")) {
2807 DBusMessageIter sub;
2809 dbus_message_iter_recurse(iter, &sub);
2810 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2811 ExecStatusInfo info;
2814 if (exec_status_info_deserialize(&sub, &info) >= 0) {
2815 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
2818 t = strv_join(info.argv, " ");
2820 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
2824 yes_no(info.ignore),
2825 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
2826 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
2827 (unsigned) info. pid,
2828 sigchld_code_to_string(info.code),
2830 info.code == CLD_EXITED ? "" : "/",
2831 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
2837 strv_free(info.argv);
2839 dbus_message_iter_next(&sub);
2848 if (generic_print_property(name, iter, arg_all) > 0)
2852 printf("%s=[unprintable]\n", name);
2857 static int show_one(const char *verb, DBusConnection *bus, const char *path, bool show_properties, bool *new_line) {
2858 DBusMessage *m = NULL, *reply = NULL;
2859 const char *interface = "";
2862 DBusMessageIter iter, sub, sub2, sub3;
2863 UnitStatusInfo info;
2871 dbus_error_init(&error);
2873 if (!(m = dbus_message_new_method_call(
2874 "org.freedesktop.systemd1",
2876 "org.freedesktop.DBus.Properties",
2878 log_error("Could not allocate message.");
2883 if (!dbus_message_append_args(m,
2884 DBUS_TYPE_STRING, &interface,
2885 DBUS_TYPE_INVALID)) {
2886 log_error("Could not append arguments to message.");
2891 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
2892 log_error("Failed to issue method call: %s", bus_error_message(&error));
2897 if (!dbus_message_iter_init(reply, &iter) ||
2898 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
2899 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
2900 log_error("Failed to parse reply.");
2905 dbus_message_iter_recurse(&iter, &sub);
2912 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
2915 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_DICT_ENTRY) {
2916 log_error("Failed to parse reply.");
2921 dbus_message_iter_recurse(&sub, &sub2);
2923 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0) {
2924 log_error("Failed to parse reply.");
2929 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
2930 log_error("Failed to parse reply.");
2935 dbus_message_iter_recurse(&sub2, &sub3);
2937 if (show_properties)
2938 r = print_property(name, &sub3);
2940 r = status_property(name, &sub3, &info);
2943 log_error("Failed to parse reply.");
2948 dbus_message_iter_next(&sub);
2953 if (!show_properties)
2954 print_status_info(&info);
2956 strv_free(info.documentation);
2958 if (!streq_ptr(info.active_state, "active") &&
2959 !streq_ptr(info.active_state, "reloading") &&
2960 streq(verb, "status"))
2961 /* According to LSB: "program not running" */
2964 while ((p = info.exec)) {
2965 LIST_REMOVE(ExecStatusInfo, exec, info.exec, p);
2966 exec_status_info_free(p);
2971 dbus_message_unref(m);
2974 dbus_message_unref(reply);
2976 dbus_error_free(&error);
2981 static int show_one_by_pid(const char *verb, DBusConnection *bus, uint32_t pid, bool *new_line) {
2982 DBusMessage *m = NULL, *reply = NULL;
2983 const char *path = NULL;
2987 dbus_error_init(&error);
2989 m = dbus_message_new_method_call(
2990 "org.freedesktop.systemd1",
2991 "/org/freedesktop/systemd1",
2992 "org.freedesktop.systemd1.Manager",
2995 log_error("Could not allocate message.");
3000 if (!dbus_message_append_args(m,
3001 DBUS_TYPE_UINT32, &pid,
3002 DBUS_TYPE_INVALID)) {
3003 log_error("Could not append arguments to message.");
3008 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3010 log_error("Failed to issue method call: %s", bus_error_message(&error));
3015 if (!dbus_message_get_args(reply, &error,
3016 DBUS_TYPE_OBJECT_PATH, &path,
3017 DBUS_TYPE_INVALID)) {
3018 log_error("Failed to parse reply: %s", bus_error_message(&error));
3023 r = show_one(verb, bus, path, false, new_line);
3027 dbus_message_unref(m);
3030 dbus_message_unref(reply);
3032 dbus_error_free(&error);
3037 static int show(DBusConnection *bus, char **args) {
3039 bool show_properties, new_line = false;
3045 show_properties = !streq(args[0], "status");
3047 if (show_properties)
3048 pager_open_if_enabled();
3050 if (show_properties && strv_length(args) <= 1) {
3051 /* If not argument is specified inspect the manager
3054 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line);
3057 STRV_FOREACH(name, args+1) {
3060 if (safe_atou32(*name, &id) < 0) {
3062 /* Interpret as unit name */
3065 e = bus_path_escape(*name);
3068 p = strappend("/org/freedesktop/systemd1/unit/", e);
3073 r = show_one(args[0], bus, p, show_properties, &new_line);
3079 } else if (show_properties) {
3081 /* Interpret as job id */
3084 if (asprintf(&p, "/org/freedesktop/systemd1/job/%u", id) < 0)
3087 r = show_one(args[0], bus, p, show_properties, &new_line);
3095 /* Interpret as PID */
3097 r = show_one_by_pid(args[0], bus, id, &new_line);
3106 static int dump(DBusConnection *bus, char **args) {
3107 DBusMessage *m = NULL, *reply = NULL;
3112 dbus_error_init(&error);
3114 pager_open_if_enabled();
3116 if (!(m = dbus_message_new_method_call(
3117 "org.freedesktop.systemd1",
3118 "/org/freedesktop/systemd1",
3119 "org.freedesktop.systemd1.Manager",
3121 log_error("Could not allocate message.");
3125 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3126 log_error("Failed to issue method call: %s", bus_error_message(&error));
3131 if (!dbus_message_get_args(reply, &error,
3132 DBUS_TYPE_STRING, &text,
3133 DBUS_TYPE_INVALID)) {
3134 log_error("Failed to parse reply: %s", bus_error_message(&error));
3139 fputs(text, stdout);
3145 dbus_message_unref(m);
3148 dbus_message_unref(reply);
3150 dbus_error_free(&error);
3155 static int snapshot(DBusConnection *bus, char **args) {
3156 DBusMessage *m = NULL, *reply = NULL;
3159 const char *name = "", *path, *id;
3160 dbus_bool_t cleanup = FALSE;
3161 DBusMessageIter iter, sub;
3163 *interface = "org.freedesktop.systemd1.Unit",
3166 dbus_error_init(&error);
3168 if (!(m = dbus_message_new_method_call(
3169 "org.freedesktop.systemd1",
3170 "/org/freedesktop/systemd1",
3171 "org.freedesktop.systemd1.Manager",
3172 "CreateSnapshot"))) {
3173 log_error("Could not allocate message.");
3177 if (strv_length(args) > 1)
3180 if (!dbus_message_append_args(m,
3181 DBUS_TYPE_STRING, &name,
3182 DBUS_TYPE_BOOLEAN, &cleanup,
3183 DBUS_TYPE_INVALID)) {
3184 log_error("Could not append arguments to message.");
3189 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3190 log_error("Failed to issue method call: %s", bus_error_message(&error));
3195 if (!dbus_message_get_args(reply, &error,
3196 DBUS_TYPE_OBJECT_PATH, &path,
3197 DBUS_TYPE_INVALID)) {
3198 log_error("Failed to parse reply: %s", bus_error_message(&error));
3203 dbus_message_unref(m);
3204 if (!(m = dbus_message_new_method_call(
3205 "org.freedesktop.systemd1",
3207 "org.freedesktop.DBus.Properties",
3209 log_error("Could not allocate message.");
3213 if (!dbus_message_append_args(m,
3214 DBUS_TYPE_STRING, &interface,
3215 DBUS_TYPE_STRING, &property,
3216 DBUS_TYPE_INVALID)) {
3217 log_error("Could not append arguments to message.");
3222 dbus_message_unref(reply);
3223 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3224 log_error("Failed to issue method call: %s", bus_error_message(&error));
3229 if (!dbus_message_iter_init(reply, &iter) ||
3230 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3231 log_error("Failed to parse reply.");
3236 dbus_message_iter_recurse(&iter, &sub);
3238 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
3239 log_error("Failed to parse reply.");
3244 dbus_message_iter_get_basic(&sub, &id);
3252 dbus_message_unref(m);
3255 dbus_message_unref(reply);
3257 dbus_error_free(&error);
3262 static int delete_snapshot(DBusConnection *bus, char **args) {
3263 DBusMessage *m = NULL, *reply = NULL;
3271 dbus_error_init(&error);
3273 STRV_FOREACH(name, args+1) {
3274 const char *path = NULL;
3276 if (!(m = dbus_message_new_method_call(
3277 "org.freedesktop.systemd1",
3278 "/org/freedesktop/systemd1",
3279 "org.freedesktop.systemd1.Manager",
3281 log_error("Could not allocate message.");
3286 if (!dbus_message_append_args(m,
3287 DBUS_TYPE_STRING, name,
3288 DBUS_TYPE_INVALID)) {
3289 log_error("Could not append arguments to message.");
3294 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3295 log_error("Failed to issue method call: %s", bus_error_message(&error));
3300 if (!dbus_message_get_args(reply, &error,
3301 DBUS_TYPE_OBJECT_PATH, &path,
3302 DBUS_TYPE_INVALID)) {
3303 log_error("Failed to parse reply: %s", bus_error_message(&error));
3308 dbus_message_unref(m);
3309 if (!(m = dbus_message_new_method_call(
3310 "org.freedesktop.systemd1",
3312 "org.freedesktop.systemd1.Snapshot",
3314 log_error("Could not allocate message.");
3319 dbus_message_unref(reply);
3320 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3321 log_error("Failed to issue method call: %s", bus_error_message(&error));
3326 dbus_message_unref(m);
3327 dbus_message_unref(reply);
3335 dbus_message_unref(m);
3338 dbus_message_unref(reply);
3340 dbus_error_free(&error);
3345 static int daemon_reload(DBusConnection *bus, char **args) {
3346 DBusMessage *m = NULL, *reply = NULL;
3351 dbus_error_init(&error);
3353 if (arg_action == ACTION_RELOAD)
3355 else if (arg_action == ACTION_REEXEC)
3356 method = "Reexecute";
3358 assert(arg_action == ACTION_SYSTEMCTL);
3361 streq(args[0], "clear-jobs") ||
3362 streq(args[0], "cancel") ? "ClearJobs" :
3363 streq(args[0], "daemon-reexec") ? "Reexecute" :
3364 streq(args[0], "reset-failed") ? "ResetFailed" :
3365 streq(args[0], "halt") ? "Halt" :
3366 streq(args[0], "poweroff") ? "PowerOff" :
3367 streq(args[0], "reboot") ? "Reboot" :
3368 streq(args[0], "kexec") ? "KExec" :
3369 streq(args[0], "exit") ? "Exit" :
3370 /* "daemon-reload" */ "Reload";
3373 if (!(m = dbus_message_new_method_call(
3374 "org.freedesktop.systemd1",
3375 "/org/freedesktop/systemd1",
3376 "org.freedesktop.systemd1.Manager",
3378 log_error("Could not allocate message.");
3382 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3384 if (arg_action != ACTION_SYSTEMCTL && error_is_no_service(&error)) {
3385 /* There's always a fallback possible for
3386 * legacy actions. */
3391 if (streq(method, "Reexecute") && dbus_error_has_name(&error, DBUS_ERROR_NO_REPLY)) {
3392 /* On reexecution, we expect a disconnect, not
3398 log_error("Failed to issue method call: %s", bus_error_message(&error));
3407 dbus_message_unref(m);
3410 dbus_message_unref(reply);
3412 dbus_error_free(&error);
3417 static int reset_failed(DBusConnection *bus, char **args) {
3418 DBusMessage *m = NULL;
3424 dbus_error_init(&error);
3426 if (strv_length(args) <= 1)
3427 return daemon_reload(bus, args);
3429 STRV_FOREACH(name, args+1) {
3432 if (!(m = dbus_message_new_method_call(
3433 "org.freedesktop.systemd1",
3434 "/org/freedesktop/systemd1",
3435 "org.freedesktop.systemd1.Manager",
3436 "ResetFailedUnit"))) {
3437 log_error("Could not allocate message.");
3442 if (!dbus_message_append_args(m,
3443 DBUS_TYPE_STRING, name,
3444 DBUS_TYPE_INVALID)) {
3445 log_error("Could not append arguments to message.");
3450 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3451 log_error("Failed to issue method call: %s", bus_error_message(&error));
3456 dbus_message_unref(m);
3457 dbus_message_unref(reply);
3465 dbus_message_unref(m);
3467 dbus_error_free(&error);
3472 static int show_enviroment(DBusConnection *bus, char **args) {
3473 DBusMessage *m = NULL, *reply = NULL;
3475 DBusMessageIter iter, sub, sub2;
3478 *interface = "org.freedesktop.systemd1.Manager",
3479 *property = "Environment";
3481 dbus_error_init(&error);
3483 pager_open_if_enabled();
3485 if (!(m = dbus_message_new_method_call(
3486 "org.freedesktop.systemd1",
3487 "/org/freedesktop/systemd1",
3488 "org.freedesktop.DBus.Properties",
3490 log_error("Could not allocate message.");
3494 if (!dbus_message_append_args(m,
3495 DBUS_TYPE_STRING, &interface,
3496 DBUS_TYPE_STRING, &property,
3497 DBUS_TYPE_INVALID)) {
3498 log_error("Could not append arguments to message.");
3503 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3504 log_error("Failed to issue method call: %s", bus_error_message(&error));
3509 if (!dbus_message_iter_init(reply, &iter) ||
3510 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3511 log_error("Failed to parse reply.");
3516 dbus_message_iter_recurse(&iter, &sub);
3518 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_ARRAY ||
3519 dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_STRING) {
3520 log_error("Failed to parse reply.");
3525 dbus_message_iter_recurse(&sub, &sub2);
3527 while (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_INVALID) {
3530 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
3531 log_error("Failed to parse reply.");
3536 dbus_message_iter_get_basic(&sub2, &text);
3537 printf("%s\n", text);
3539 dbus_message_iter_next(&sub2);
3546 dbus_message_unref(m);
3549 dbus_message_unref(reply);
3551 dbus_error_free(&error);
3556 static int switch_root(DBusConnection *bus, char **args) {
3557 DBusMessage *m = NULL, *reply = NULL;
3559 const char *root, *init;
3563 dbus_error_init(&error);
3565 l = strv_length(args);
3566 if (l < 2 || l > 3) {
3567 log_error("Wrong number of arguments.");
3572 init = l >= 3 ? args[2] : "";
3574 m = dbus_message_new_method_call(
3575 "org.freedesktop.systemd1",
3576 "/org/freedesktop/systemd1",
3577 "org.freedesktop.systemd1.Manager",
3580 log_error("Could not allocate message.");
3584 if (!dbus_message_append_args(
3586 DBUS_TYPE_STRING, &root,
3587 DBUS_TYPE_STRING, &init,
3588 DBUS_TYPE_INVALID)) {
3589 log_error("Could not append arguments to message.");
3594 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3596 log_error("Failed to issue method call: %s", bus_error_message(&error));
3605 dbus_message_unref(m);
3608 dbus_message_unref(reply);
3610 dbus_error_free(&error);
3615 static int set_environment(DBusConnection *bus, char **args) {
3616 DBusMessage *m = NULL, *reply = NULL;
3620 DBusMessageIter iter, sub;
3623 dbus_error_init(&error);
3625 method = streq(args[0], "set-environment")
3627 : "UnsetEnvironment";
3629 if (!(m = dbus_message_new_method_call(
3630 "org.freedesktop.systemd1",
3631 "/org/freedesktop/systemd1",
3632 "org.freedesktop.systemd1.Manager",
3635 log_error("Could not allocate message.");
3639 dbus_message_iter_init_append(m, &iter);
3641 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub)) {
3642 log_error("Could not append arguments to message.");
3647 STRV_FOREACH(name, args+1)
3648 if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, name)) {
3649 log_error("Could not append arguments to message.");
3654 if (!dbus_message_iter_close_container(&iter, &sub)) {
3655 log_error("Could not append arguments to message.");
3660 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3661 log_error("Failed to issue method call: %s", bus_error_message(&error));
3670 dbus_message_unref(m);
3673 dbus_message_unref(reply);
3675 dbus_error_free(&error);
3680 static int enable_sysv_units(char **args) {
3683 #if defined (HAVE_SYSV_COMPAT) && (defined(TARGET_FEDORA) || defined(TARGET_MANDRIVA) || defined(TARGET_SUSE) || defined(TARGET_MEEGO) || defined(TARGET_ALTLINUX) || defined(TARGET_MAGEIA))
3684 const char *verb = args[0];
3685 unsigned f = 1, t = 1;
3688 if (arg_scope != UNIT_FILE_SYSTEM)
3691 if (!streq(verb, "enable") &&
3692 !streq(verb, "disable") &&
3693 !streq(verb, "is-enabled"))
3696 /* Processes all SysV units, and reshuffles the array so that
3697 * afterwards only the native units remain */
3700 r = lookup_paths_init(&paths, MANAGER_SYSTEM, false);
3706 for (f = 1; args[f]; f++) {
3709 bool found_native = false, found_sysv;
3711 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
3712 char **k, *l, *q = NULL;
3719 if (!endswith(name, ".service"))
3722 if (path_is_absolute(name))
3725 STRV_FOREACH(k, paths.unit_path) {
3728 if (!isempty(arg_root))
3729 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
3731 asprintf(&p, "%s/%s", *k, name);
3734 log_error("No memory");
3739 found_native = access(p, F_OK) >= 0;
3750 if (!isempty(arg_root))
3751 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
3753 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
3755 log_error("No memory");
3760 p[strlen(p) - sizeof(".service") + 1] = 0;
3761 found_sysv = access(p, F_OK) >= 0;
3768 /* Mark this entry, so that we don't try enabling it as native unit */
3769 args[f] = (char*) "";
3771 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
3773 if (!isempty(arg_root))
3774 argv[c++] = q = strappend("--root=", arg_root);
3776 argv[c++] = path_get_file_name(p);
3778 streq(verb, "enable") ? "on" :
3779 streq(verb, "disable") ? "off" : "--level=5";
3782 l = strv_join((char**)argv, " ");
3784 log_error("No memory.");
3791 log_info("Executing %s", l);
3796 log_error("Failed to fork: %m");
3801 } else if (pid == 0) {
3804 execv(argv[0], (char**) argv);
3805 _exit(EXIT_FAILURE);
3811 j = wait_for_terminate(pid, &status);
3813 log_error("Failed to wait for child: %s", strerror(-r));
3818 if (status.si_code == CLD_EXITED) {
3819 if (streq(verb, "is-enabled")) {
3820 if (status.si_status == 0) {
3829 } else if (status.si_status != 0) {
3840 lookup_paths_free(&paths);
3842 /* Drop all SysV units */
3843 for (f = 1, t = 1; args[f]; f++) {
3845 if (isempty(args[f]))
3848 args[t++] = args[f];
3857 static int enable_unit(DBusConnection *bus, char **args) {
3858 const char *verb = args[0];
3859 UnitFileChange *changes = NULL;
3860 unsigned n_changes = 0, i;
3861 int carries_install_info = -1;
3862 DBusMessage *m = NULL, *reply = NULL;
3866 r = enable_sysv_units(args);
3873 dbus_error_init(&error);
3875 if (!bus || avoid_bus()) {
3876 if (streq(verb, "enable")) {
3877 r = unit_file_enable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3878 carries_install_info = r;
3879 } else if (streq(verb, "disable"))
3880 r = unit_file_disable(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3881 else if (streq(verb, "reenable")) {
3882 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3883 carries_install_info = r;
3884 } else if (streq(verb, "link"))
3885 r = unit_file_link(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3886 else if (streq(verb, "preset")) {
3887 r = unit_file_preset(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3888 carries_install_info = r;
3889 } else if (streq(verb, "mask"))
3890 r = unit_file_mask(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3891 else if (streq(verb, "unmask"))
3892 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3894 assert_not_reached("Unknown verb");
3897 log_error("Operation failed: %s", strerror(-r));
3902 for (i = 0; i < n_changes; i++) {
3903 if (changes[i].type == UNIT_FILE_SYMLINK)
3904 log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
3906 log_info("rm '%s'", changes[i].path);
3912 bool send_force = true, expect_carries_install_info = false;
3914 DBusMessageIter iter, sub, sub2;
3916 if (streq(verb, "enable")) {
3917 method = "EnableUnitFiles";
3918 expect_carries_install_info = true;
3919 } else if (streq(verb, "disable")) {
3920 method = "DisableUnitFiles";
3922 } else if (streq(verb, "reenable")) {
3923 method = "ReenableUnitFiles";
3924 expect_carries_install_info = true;
3925 } else if (streq(verb, "link"))
3926 method = "LinkUnitFiles";
3927 else if (streq(verb, "preset")) {
3928 method = "PresetUnitFiles";
3929 expect_carries_install_info = true;
3930 } else if (streq(verb, "mask"))
3931 method = "MaskUnitFiles";
3932 else if (streq(verb, "unmask")) {
3933 method = "UnmaskUnitFiles";
3936 assert_not_reached("Unknown verb");
3938 m = dbus_message_new_method_call(
3939 "org.freedesktop.systemd1",
3940 "/org/freedesktop/systemd1",
3941 "org.freedesktop.systemd1.Manager",
3944 log_error("Out of memory");
3949 dbus_message_iter_init_append(m, &iter);
3951 r = bus_append_strv_iter(&iter, args+1);
3953 log_error("Failed to append unit files.");
3958 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &a)) {
3959 log_error("Failed to append runtime boolean.");
3967 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b)) {
3968 log_error("Failed to append force boolean.");
3974 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3976 log_error("Failed to issue method call: %s", bus_error_message(&error));
3981 if (!dbus_message_iter_init(reply, &iter)) {
3982 log_error("Failed to initialize iterator.");
3986 if (expect_carries_install_info) {
3987 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &b, true);
3989 log_error("Failed to parse reply.");
3993 carries_install_info = b;
3996 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3997 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
3998 log_error("Failed to parse reply.");
4003 dbus_message_iter_recurse(&iter, &sub);
4004 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
4005 const char *type, *path, *source;
4007 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
4008 log_error("Failed to parse reply.");
4013 dbus_message_iter_recurse(&sub, &sub2);
4015 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
4016 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
4017 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &source, false) < 0) {
4018 log_error("Failed to parse reply.");
4024 if (streq(type, "symlink"))
4025 log_info("ln -s '%s' '%s'", source, path);
4027 log_info("rm '%s'", path);
4030 dbus_message_iter_next(&sub);
4033 /* Try to reload if enabeld */
4035 r = daemon_reload(bus, args);
4038 if (carries_install_info == 0)
4039 log_warning("Warning: unit files do not carry install information. No operation executed.");
4043 dbus_message_unref(m);
4046 dbus_message_unref(reply);
4048 unit_file_changes_free(changes, n_changes);
4050 dbus_error_free(&error);
4054 static int unit_is_enabled(DBusConnection *bus, char **args) {
4057 DBusMessage *m = NULL, *reply = NULL;
4061 dbus_error_init(&error);
4063 r = enable_sysv_units(args);
4069 if (!bus || avoid_bus()) {
4071 STRV_FOREACH(name, args+1) {
4072 UnitFileState state;
4074 state = unit_file_get_state(arg_scope, arg_root, *name);
4080 if (state == UNIT_FILE_ENABLED ||
4081 state == UNIT_FILE_ENABLED_RUNTIME ||
4082 state == UNIT_FILE_STATIC)
4086 puts(unit_file_state_to_string(state));
4090 STRV_FOREACH(name, args+1) {
4093 m = dbus_message_new_method_call(
4094 "org.freedesktop.systemd1",
4095 "/org/freedesktop/systemd1",
4096 "org.freedesktop.systemd1.Manager",
4097 "GetUnitFileState");
4099 log_error("Out of memory");
4104 if (!dbus_message_append_args(m,
4105 DBUS_TYPE_STRING, name,
4106 DBUS_TYPE_INVALID)) {
4107 log_error("Could not append arguments to message.");
4112 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
4114 log_error("Failed to issue method call: %s", bus_error_message(&error));
4119 if (!dbus_message_get_args(reply, &error,
4120 DBUS_TYPE_STRING, &s,
4121 DBUS_TYPE_INVALID)) {
4122 log_error("Failed to parse reply: %s", bus_error_message(&error));
4127 dbus_message_unref(m);
4128 dbus_message_unref(reply);
4131 if (streq(s, "enabled") ||
4132 streq(s, "enabled-runtime") ||
4141 r = enabled ? 0 : 1;
4145 dbus_message_unref(m);
4148 dbus_message_unref(reply);
4150 dbus_error_free(&error);
4154 static int systemctl_help(void) {
4156 pager_open_if_enabled();
4158 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
4159 "Query or send control commands to the systemd manager.\n\n"
4160 " -h --help Show this help\n"
4161 " --version Show package version\n"
4162 " -t --type=TYPE List only units of a particular type\n"
4163 " -p --property=NAME Show only properties by this name\n"
4164 " -a --all Show all units/properties, including dead/empty ones\n"
4165 " --failed Show only failed units\n"
4166 " --full Don't ellipsize unit names on output\n"
4167 " --fail When queueing a new job, fail if conflicting jobs are\n"
4169 " --ignore-dependencies\n"
4170 " When queueing a new job, ignore all its dependencies\n"
4171 " --kill-who=WHO Who to send signal to\n"
4172 " -s --signal=SIGNAL Which signal to send\n"
4173 " -H --host=[USER@]HOST\n"
4174 " Show information for remote host\n"
4175 " -P --privileged Acquire privileges before execution\n"
4176 " -q --quiet Suppress output\n"
4177 " --no-block Do not wait until operation finished\n"
4178 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4179 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
4181 " --no-legend Do not print a legend (column headers and hints)\n"
4182 " --no-pager Do not pipe output into a pager\n"
4183 " --no-ask-password\n"
4184 " Do not ask for system passwords\n"
4185 " --order When generating graph for dot, show only order\n"
4186 " --require When generating graph for dot, show only requirement\n"
4187 " --system Connect to system manager\n"
4188 " --user Connect to user service manager\n"
4189 " --global Enable/disable unit files globally\n"
4190 " -f --force When enabling unit files, override existing symlinks\n"
4191 " When shutting down, execute action immediately\n"
4192 " --root=PATH Enable unit files in the specified root directory\n"
4193 " --runtime Enable unit files only temporarily until next reboot\n"
4194 " -n --lines=INTEGER Journal entries to show\n"
4195 " --follow Follow journal\n"
4196 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
4197 " verbose, export, json, cat)\n\n"
4199 " list-units List loaded units\n"
4200 " start [NAME...] Start (activate) one or more units\n"
4201 " stop [NAME...] Stop (deactivate) one or more units\n"
4202 " reload [NAME...] Reload one or more units\n"
4203 " restart [NAME...] Start or restart one or more units\n"
4204 " try-restart [NAME...] Restart one or more units if active\n"
4205 " reload-or-restart [NAME...] Reload one or more units is possible,\n"
4206 " otherwise start or restart\n"
4207 " reload-or-try-restart [NAME...] Reload one or more units is possible,\n"
4208 " otherwise restart if active\n"
4209 " isolate [NAME] Start one unit and stop all others\n"
4210 " kill [NAME...] Send signal to processes of a unit\n"
4211 " is-active [NAME...] Check whether units are active\n"
4212 " status [NAME...|PID...] Show runtime status of one or more units\n"
4213 " show [NAME...|JOB...] Show properties of one or more\n"
4214 " units/jobs or the manager\n"
4215 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
4217 " load [NAME...] Load one or more units\n\n"
4218 "Unit File Commands:\n"
4219 " list-unit-files List installed unit files\n"
4220 " enable [NAME...] Enable one or more unit files\n"
4221 " disable [NAME...] Disable one or more unit files\n"
4222 " reenable [NAME...] Reenable one or more unit files\n"
4223 " preset [NAME...] Enable/disable one or more unit files\n"
4224 " based on preset configuration\n"
4225 " mask [NAME...] Mask one or more units\n"
4226 " unmask [NAME...] Unmask one or more units\n"
4227 " link [PATH...] Link one or more units files into\n"
4228 " the search path\n"
4229 " is-enabled [NAME...] Check whether unit files are enabled\n\n"
4231 " list-jobs List jobs\n"
4232 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
4233 "Status Commands:\n"
4234 " dump Dump server status\n"
4235 " dot Dump dependency graph for dot(1)\n\n"
4236 "Snapshot Commands:\n"
4237 " snapshot [NAME] Create a snapshot\n"
4238 " delete [NAME...] Remove one or more snapshots\n\n"
4239 "Environment Commands:\n"
4240 " show-environment Dump environment\n"
4241 " set-environment [NAME=VALUE...] Set one or more environment variables\n"
4242 " unset-environment [NAME...] Unset one or more environment variables\n\n"
4243 "Manager Lifecycle Commands:\n"
4244 " daemon-reload Reload systemd manager configuration\n"
4245 " daemon-reexec Reexecute systemd manager\n\n"
4246 "System Commands:\n"
4247 " default Enter system default mode\n"
4248 " rescue Enter system rescue mode\n"
4249 " emergency Enter system emergency mode\n"
4250 " halt Shut down and halt the system\n"
4251 " poweroff Shut down and power-off the system\n"
4252 " reboot Shut down and reboot the system\n"
4253 " kexec Shut down and reboot the system with kexec\n"
4254 " exit Request user instance exit\n"
4255 " switch-root [ROOT] [INIT] Change to a different root file system\n"
4256 " suspend Suspend the system\n"
4257 " hibernate Hibernate the system\n",
4258 program_invocation_short_name);
4263 static int halt_help(void) {
4265 printf("%s [OPTIONS...]\n\n"
4266 "%s the system.\n\n"
4267 " --help Show this help\n"
4268 " --halt Halt the machine\n"
4269 " -p --poweroff Switch off the machine\n"
4270 " --reboot Reboot the machine\n"
4271 " -f --force Force immediate halt/power-off/reboot\n"
4272 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
4273 " -d --no-wtmp Don't write wtmp record\n"
4274 " -n --no-sync Don't sync before halt/power-off/reboot\n"
4275 " --no-wall Don't send wall message before halt/power-off/reboot\n",
4276 program_invocation_short_name,
4277 arg_action == ACTION_REBOOT ? "Reboot" :
4278 arg_action == ACTION_POWEROFF ? "Power off" :
4284 static int shutdown_help(void) {
4286 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
4287 "Shut down the system.\n\n"
4288 " --help Show this help\n"
4289 " -H --halt Halt the machine\n"
4290 " -P --poweroff Power-off the machine\n"
4291 " -r --reboot Reboot the machine\n"
4292 " -h Equivalent to --poweroff, overridden by --halt\n"
4293 " -k Don't halt/power-off/reboot, just send warnings\n"
4294 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4295 " -c Cancel a pending shutdown\n",
4296 program_invocation_short_name);
4301 static int telinit_help(void) {
4303 printf("%s [OPTIONS...] {COMMAND}\n\n"
4304 "Send control commands to the init daemon.\n\n"
4305 " --help Show this help\n"
4306 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
4308 " 0 Power-off the machine\n"
4309 " 6 Reboot the machine\n"
4310 " 2, 3, 4, 5 Start runlevelX.target unit\n"
4311 " 1, s, S Enter rescue mode\n"
4312 " q, Q Reload init daemon configuration\n"
4313 " u, U Reexecute init daemon\n",
4314 program_invocation_short_name);
4319 static int runlevel_help(void) {
4321 printf("%s [OPTIONS...]\n\n"
4322 "Prints the previous and current runlevel of the init system.\n\n"
4323 " --help Show this help\n",
4324 program_invocation_short_name);
4329 static int systemctl_parse_argv(int argc, char *argv[]) {
4333 ARG_IGNORE_DEPENDENCIES,
4349 ARG_NO_ASK_PASSWORD,
4356 static const struct option options[] = {
4357 { "help", no_argument, NULL, 'h' },
4358 { "version", no_argument, NULL, ARG_VERSION },
4359 { "type", required_argument, NULL, 't' },
4360 { "property", required_argument, NULL, 'p' },
4361 { "all", no_argument, NULL, 'a' },
4362 { "failed", no_argument, NULL, ARG_FAILED },
4363 { "full", no_argument, NULL, ARG_FULL },
4364 { "fail", no_argument, NULL, ARG_FAIL },
4365 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
4366 { "user", no_argument, NULL, ARG_USER },
4367 { "system", no_argument, NULL, ARG_SYSTEM },
4368 { "global", no_argument, NULL, ARG_GLOBAL },
4369 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
4370 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
4371 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
4372 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4373 { "quiet", no_argument, NULL, 'q' },
4374 { "order", no_argument, NULL, ARG_ORDER },
4375 { "require", no_argument, NULL, ARG_REQUIRE },
4376 { "root", required_argument, NULL, ARG_ROOT },
4377 { "force", no_argument, NULL, ARG_FORCE },
4378 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
4379 { "kill-mode", required_argument, NULL, ARG_KILL_MODE }, /* undocumented on purpose */
4380 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
4381 { "signal", required_argument, NULL, 's' },
4382 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
4383 { "host", required_argument, NULL, 'H' },
4384 { "privileged",no_argument, NULL, 'P' },
4385 { "runtime", no_argument, NULL, ARG_RUNTIME },
4386 { "lines", required_argument, NULL, 'n' },
4387 { "follow", no_argument, NULL, ARG_FOLLOW },
4388 { "output", required_argument, NULL, 'o' },
4389 { NULL, 0, NULL, 0 }
4397 while ((c = getopt_long(argc, argv, "ht:p:aqfs:H:Pn:o:", options, NULL)) >= 0) {
4406 puts(PACKAGE_STRING);
4408 puts(SYSTEMD_FEATURES);
4418 if (!(l = strv_append(arg_property, optarg)))
4421 strv_free(arg_property);
4424 /* If the user asked for a particular
4425 * property, show it to him, even if it is
4436 arg_job_mode = "fail";
4439 case ARG_IGNORE_DEPENDENCIES:
4440 arg_job_mode = "ignore-dependencies";
4444 arg_scope = UNIT_FILE_USER;
4448 arg_scope = UNIT_FILE_SYSTEM;
4452 arg_scope = UNIT_FILE_GLOBAL;
4456 arg_no_block = true;
4460 arg_no_legend = true;
4464 arg_no_pager = true;
4472 arg_dot = DOT_ORDER;
4476 arg_dot = DOT_REQUIRE;
4504 /* -f is short for both --follow and --force! */
4510 arg_no_reload = true;
4514 arg_kill_who = optarg;
4518 arg_kill_mode = optarg;
4522 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
4523 log_error("Failed to parse signal string %s.", optarg);
4528 case ARG_NO_ASK_PASSWORD:
4529 arg_ask_password = false;
4533 arg_transport = TRANSPORT_POLKIT;
4537 arg_transport = TRANSPORT_SSH;
4546 if (safe_atou(optarg, &arg_lines) < 0) {
4547 log_error("Failed to parse lines '%s'", optarg);
4553 arg_output = output_mode_from_string(optarg);
4554 if (arg_output < 0) {
4555 log_error("Unknown output '%s'.", optarg);
4564 log_error("Unknown option code %c", c);
4569 if (arg_transport != TRANSPORT_NORMAL && arg_scope != UNIT_FILE_SYSTEM) {
4570 log_error("Cannot access user instance remotely.");
4577 static int halt_parse_argv(int argc, char *argv[]) {
4586 static const struct option options[] = {
4587 { "help", no_argument, NULL, ARG_HELP },
4588 { "halt", no_argument, NULL, ARG_HALT },
4589 { "poweroff", no_argument, NULL, 'p' },
4590 { "reboot", no_argument, NULL, ARG_REBOOT },
4591 { "force", no_argument, NULL, 'f' },
4592 { "wtmp-only", no_argument, NULL, 'w' },
4593 { "no-wtmp", no_argument, NULL, 'd' },
4594 { "no-sync", no_argument, NULL, 'n' },
4595 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4596 { NULL, 0, NULL, 0 }
4604 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
4605 if (runlevel == '0' || runlevel == '6')
4608 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
4616 arg_action = ACTION_HALT;
4620 if (arg_action != ACTION_REBOOT)
4621 arg_action = ACTION_POWEROFF;
4625 arg_action = ACTION_REBOOT;
4650 /* Compatibility nops */
4657 log_error("Unknown option code %c", c);
4662 if (optind < argc) {
4663 log_error("Too many arguments.");
4670 static int parse_time_spec(const char *t, usec_t *_u) {
4674 if (streq(t, "now"))
4676 else if (!strchr(t, ':')) {
4679 if (safe_atou64(t, &u) < 0)
4682 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
4691 hour = strtol(t, &e, 10);
4692 if (errno != 0 || *e != ':' || hour < 0 || hour > 23)
4695 minute = strtol(e+1, &e, 10);
4696 if (errno != 0 || *e != 0 || minute < 0 || minute > 59)
4699 n = now(CLOCK_REALTIME);
4700 s = (time_t) (n / USEC_PER_SEC);
4703 assert_se(localtime_r(&s, &tm));
4705 tm.tm_hour = (int) hour;
4706 tm.tm_min = (int) minute;
4709 assert_se(s = mktime(&tm));
4711 *_u = (usec_t) s * USEC_PER_SEC;
4714 *_u += USEC_PER_DAY;
4720 static int shutdown_parse_argv(int argc, char *argv[]) {
4727 static const struct option options[] = {
4728 { "help", no_argument, NULL, ARG_HELP },
4729 { "halt", no_argument, NULL, 'H' },
4730 { "poweroff", no_argument, NULL, 'P' },
4731 { "reboot", no_argument, NULL, 'r' },
4732 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
4733 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4734 { NULL, 0, NULL, 0 }
4742 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
4750 arg_action = ACTION_HALT;
4754 arg_action = ACTION_POWEROFF;
4759 arg_action = ACTION_KEXEC;
4761 arg_action = ACTION_REBOOT;
4765 arg_action = ACTION_KEXEC;
4769 if (arg_action != ACTION_HALT)
4770 arg_action = ACTION_POWEROFF;
4783 /* Compatibility nops */
4787 arg_action = ACTION_CANCEL_SHUTDOWN;
4794 log_error("Unknown option code %c", c);
4799 if (argc > optind) {
4800 r = parse_time_spec(argv[optind], &arg_when);
4802 log_error("Failed to parse time specification: %s", argv[optind]);
4806 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
4808 /* We skip the time argument */
4809 if (argc > optind + 1)
4810 arg_wall = argv + optind + 1;
4817 static int telinit_parse_argv(int argc, char *argv[]) {
4824 static const struct option options[] = {
4825 { "help", no_argument, NULL, ARG_HELP },
4826 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4827 { NULL, 0, NULL, 0 }
4830 static const struct {
4834 { '0', ACTION_POWEROFF },
4835 { '6', ACTION_REBOOT },
4836 { '1', ACTION_RESCUE },
4837 { '2', ACTION_RUNLEVEL2 },
4838 { '3', ACTION_RUNLEVEL3 },
4839 { '4', ACTION_RUNLEVEL4 },
4840 { '5', ACTION_RUNLEVEL5 },
4841 { 's', ACTION_RESCUE },
4842 { 'S', ACTION_RESCUE },
4843 { 'q', ACTION_RELOAD },
4844 { 'Q', ACTION_RELOAD },
4845 { 'u', ACTION_REEXEC },
4846 { 'U', ACTION_REEXEC }
4855 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4870 log_error("Unknown option code %c", c);
4875 if (optind >= argc) {
4880 if (optind + 1 < argc) {
4881 log_error("Too many arguments.");
4885 if (strlen(argv[optind]) != 1) {
4886 log_error("Expected single character argument.");
4890 for (i = 0; i < ELEMENTSOF(table); i++)
4891 if (table[i].from == argv[optind][0])
4894 if (i >= ELEMENTSOF(table)) {
4895 log_error("Unknown command %s.", argv[optind]);
4899 arg_action = table[i].to;
4906 static int runlevel_parse_argv(int argc, char *argv[]) {
4912 static const struct option options[] = {
4913 { "help", no_argument, NULL, ARG_HELP },
4914 { NULL, 0, NULL, 0 }
4922 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4933 log_error("Unknown option code %c", c);
4938 if (optind < argc) {
4939 log_error("Too many arguments.");
4946 static int parse_argv(int argc, char *argv[]) {
4950 if (program_invocation_short_name) {
4952 if (strstr(program_invocation_short_name, "halt")) {
4953 arg_action = ACTION_HALT;
4954 return halt_parse_argv(argc, argv);
4955 } else if (strstr(program_invocation_short_name, "poweroff")) {
4956 arg_action = ACTION_POWEROFF;
4957 return halt_parse_argv(argc, argv);
4958 } else if (strstr(program_invocation_short_name, "reboot")) {
4960 arg_action = ACTION_KEXEC;
4962 arg_action = ACTION_REBOOT;
4963 return halt_parse_argv(argc, argv);
4964 } else if (strstr(program_invocation_short_name, "shutdown")) {
4965 arg_action = ACTION_POWEROFF;
4966 return shutdown_parse_argv(argc, argv);
4967 } else if (strstr(program_invocation_short_name, "init")) {
4969 if (sd_booted() > 0) {
4970 arg_action = ACTION_INVALID;
4971 return telinit_parse_argv(argc, argv);
4973 /* Hmm, so some other init system is
4974 * running, we need to forward this
4975 * request to it. For now we simply
4976 * guess that it is Upstart. */
4978 execv("/lib/upstart/telinit", argv);
4980 log_error("Couldn't find an alternative telinit implementation to spawn.");
4984 } else if (strstr(program_invocation_short_name, "runlevel")) {
4985 arg_action = ACTION_RUNLEVEL;
4986 return runlevel_parse_argv(argc, argv);
4990 arg_action = ACTION_SYSTEMCTL;
4991 return systemctl_parse_argv(argc, argv);
4994 static int action_to_runlevel(void) {
4996 static const char table[_ACTION_MAX] = {
4997 [ACTION_HALT] = '0',
4998 [ACTION_POWEROFF] = '0',
4999 [ACTION_REBOOT] = '6',
5000 [ACTION_RUNLEVEL2] = '2',
5001 [ACTION_RUNLEVEL3] = '3',
5002 [ACTION_RUNLEVEL4] = '4',
5003 [ACTION_RUNLEVEL5] = '5',
5004 [ACTION_RESCUE] = '1'
5007 assert(arg_action < _ACTION_MAX);
5009 return table[arg_action];
5012 static int talk_upstart(void) {
5013 DBusMessage *m = NULL, *reply = NULL;
5015 int previous, rl, r;
5017 env1_buf[] = "RUNLEVEL=X",
5018 env2_buf[] = "PREVLEVEL=X";
5019 char *env1 = env1_buf, *env2 = env2_buf;
5020 const char *emit = "runlevel";
5021 dbus_bool_t b_false = FALSE;
5022 DBusMessageIter iter, sub;
5023 DBusConnection *bus;
5025 dbus_error_init(&error);
5027 if (!(rl = action_to_runlevel()))
5030 if (utmp_get_runlevel(&previous, NULL) < 0)
5033 if (!(bus = dbus_connection_open_private("unix:abstract=/com/ubuntu/upstart", &error))) {
5034 if (dbus_error_has_name(&error, DBUS_ERROR_NO_SERVER)) {
5039 log_error("Failed to connect to Upstart bus: %s", bus_error_message(&error));
5044 if ((r = bus_check_peercred(bus)) < 0) {
5045 log_error("Failed to verify owner of bus.");
5049 if (!(m = dbus_message_new_method_call(
5050 "com.ubuntu.Upstart",
5051 "/com/ubuntu/Upstart",
5052 "com.ubuntu.Upstart0_6",
5055 log_error("Could not allocate message.");
5060 dbus_message_iter_init_append(m, &iter);
5062 env1_buf[sizeof(env1_buf)-2] = rl;
5063 env2_buf[sizeof(env2_buf)-2] = previous;
5065 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &emit) ||
5066 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub) ||
5067 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env1) ||
5068 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env2) ||
5069 !dbus_message_iter_close_container(&iter, &sub) ||
5070 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b_false)) {
5071 log_error("Could not append arguments to message.");
5076 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
5078 if (error_is_no_service(&error)) {
5083 log_error("Failed to issue method call: %s", bus_error_message(&error));
5092 dbus_message_unref(m);
5095 dbus_message_unref(reply);
5098 dbus_connection_flush(bus);
5099 dbus_connection_close(bus);
5100 dbus_connection_unref(bus);
5103 dbus_error_free(&error);
5108 static int talk_initctl(void) {
5109 struct init_request request;
5113 if (!(rl = action_to_runlevel()))
5117 request.magic = INIT_MAGIC;
5118 request.sleeptime = 0;
5119 request.cmd = INIT_CMD_RUNLVL;
5120 request.runlevel = rl;
5122 if ((fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY)) < 0) {
5124 if (errno == ENOENT)
5127 log_error("Failed to open "INIT_FIFO": %m");
5132 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
5133 close_nointr_nofail(fd);
5136 log_error("Failed to write to "INIT_FIFO": %m");
5137 return errno ? -errno : -EIO;
5143 static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
5145 static const struct {
5153 int (* const dispatch)(DBusConnection *bus, char **args);
5155 { "list-units", LESS, 1, list_units },
5156 { "list-unit-files", EQUAL, 1, list_unit_files },
5157 { "list-jobs", EQUAL, 1, list_jobs },
5158 { "clear-jobs", EQUAL, 1, daemon_reload },
5159 { "load", MORE, 2, load_unit },
5160 { "cancel", MORE, 2, cancel_job },
5161 { "start", MORE, 2, start_unit },
5162 { "stop", MORE, 2, start_unit },
5163 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5164 { "reload", MORE, 2, start_unit },
5165 { "restart", MORE, 2, start_unit },
5166 { "try-restart", MORE, 2, start_unit },
5167 { "reload-or-restart", MORE, 2, start_unit },
5168 { "reload-or-try-restart", MORE, 2, start_unit },
5169 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
5170 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5171 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
5172 { "isolate", EQUAL, 2, start_unit },
5173 { "kill", MORE, 2, kill_unit },
5174 { "is-active", MORE, 2, check_unit },
5175 { "check", MORE, 2, check_unit },
5176 { "show", MORE, 1, show },
5177 { "status", MORE, 2, show },
5178 { "dump", EQUAL, 1, dump },
5179 { "dot", EQUAL, 1, dot },
5180 { "snapshot", LESS, 2, snapshot },
5181 { "delete", MORE, 2, delete_snapshot },
5182 { "daemon-reload", EQUAL, 1, daemon_reload },
5183 { "daemon-reexec", EQUAL, 1, daemon_reload },
5184 { "show-environment", EQUAL, 1, show_enviroment },
5185 { "set-environment", MORE, 2, set_environment },
5186 { "unset-environment", MORE, 2, set_environment },
5187 { "halt", EQUAL, 1, start_special },
5188 { "poweroff", EQUAL, 1, start_special },
5189 { "reboot", EQUAL, 1, start_special },
5190 { "kexec", EQUAL, 1, start_special },
5191 { "suspend", EQUAL, 1, start_special },
5192 { "hibernate", EQUAL, 1, start_special },
5193 { "default", EQUAL, 1, start_special },
5194 { "rescue", EQUAL, 1, start_special },
5195 { "emergency", EQUAL, 1, start_special },
5196 { "exit", EQUAL, 1, start_special },
5197 { "reset-failed", MORE, 1, reset_failed },
5198 { "enable", MORE, 2, enable_unit },
5199 { "disable", MORE, 2, enable_unit },
5200 { "is-enabled", MORE, 2, unit_is_enabled },
5201 { "reenable", MORE, 2, enable_unit },
5202 { "preset", MORE, 2, enable_unit },
5203 { "mask", MORE, 2, enable_unit },
5204 { "unmask", MORE, 2, enable_unit },
5205 { "link", MORE, 2, enable_unit },
5206 { "switch-root", MORE, 2, switch_root },
5216 left = argc - optind;
5219 /* Special rule: no arguments means "list-units" */
5222 if (streq(argv[optind], "help")) {
5227 for (i = 0; i < ELEMENTSOF(verbs); i++)
5228 if (streq(argv[optind], verbs[i].verb))
5231 if (i >= ELEMENTSOF(verbs)) {
5232 log_error("Unknown operation %s", argv[optind]);
5237 switch (verbs[i].argc_cmp) {
5240 if (left != verbs[i].argc) {
5241 log_error("Invalid number of arguments.");
5248 if (left < verbs[i].argc) {
5249 log_error("Too few arguments.");
5256 if (left > verbs[i].argc) {
5257 log_error("Too many arguments.");
5264 assert_not_reached("Unknown comparison operator.");
5267 /* Require a bus connection for all operations but
5269 if (!streq(verbs[i].verb, "enable") &&
5270 !streq(verbs[i].verb, "disable") &&
5271 !streq(verbs[i].verb, "is-enabled") &&
5272 !streq(verbs[i].verb, "list-unit-files") &&
5273 !streq(verbs[i].verb, "reenable") &&
5274 !streq(verbs[i].verb, "preset") &&
5275 !streq(verbs[i].verb, "mask") &&
5276 !streq(verbs[i].verb, "unmask") &&
5277 !streq(verbs[i].verb, "link")) {
5279 if (running_in_chroot() > 0) {
5280 log_info("Running in chroot, ignoring request.");
5284 if (((!streq(verbs[i].verb, "reboot") &&
5285 !streq(verbs[i].verb, "halt") &&
5286 !streq(verbs[i].verb, "poweroff")) || arg_force <= 0) && !bus) {
5287 log_error("Failed to get D-Bus connection: %s",
5288 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5294 if (!bus && !avoid_bus()) {
5295 log_error("Failed to get D-Bus connection: %s",
5296 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5301 return verbs[i].dispatch(bus, argv + optind);
5304 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
5306 struct msghdr msghdr;
5307 struct iovec iovec[2];
5308 union sockaddr_union sockaddr;
5309 struct sd_shutdown_command c;
5311 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
5318 c.dry_run = dry_run;
5322 sockaddr.sa.sa_family = AF_UNIX;
5323 strncpy(sockaddr.un.sun_path, "/run/systemd/shutdownd", sizeof(sockaddr.un.sun_path));
5326 msghdr.msg_name = &sockaddr;
5327 msghdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + sizeof("/run/systemd/shutdownd") - 1;
5330 iovec[0].iov_base = (char*) &c;
5331 iovec[0].iov_len = offsetof(struct sd_shutdown_command, wall_message);
5333 if (isempty(message))
5334 msghdr.msg_iovlen = 1;
5336 iovec[1].iov_base = (char*) message;
5337 iovec[1].iov_len = strlen(message);
5338 msghdr.msg_iovlen = 2;
5340 msghdr.msg_iov = iovec;
5342 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0) {
5343 close_nointr_nofail(fd);
5347 close_nointr_nofail(fd);
5351 static int reload_with_fallback(DBusConnection *bus) {
5354 /* First, try systemd via D-Bus. */
5355 if (daemon_reload(bus, NULL) >= 0)
5359 /* Nothing else worked, so let's try signals */
5360 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
5362 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
5363 log_error("kill() failed: %m");
5370 static int start_with_fallback(DBusConnection *bus) {
5373 /* First, try systemd via D-Bus. */
5374 if (start_unit(bus, NULL) >= 0)
5378 /* Hmm, talking to systemd via D-Bus didn't work. Then
5379 * let's try to talk to Upstart via D-Bus. */
5380 if (talk_upstart() > 0)
5383 /* Nothing else worked, so let's try
5385 if (talk_initctl() > 0)
5388 log_error("Failed to talk to init daemon.");
5392 warn_wall(arg_action);
5396 static void halt_now(enum action a) {
5398 /* Make sure C-A-D is handled by the kernel from this
5400 reboot(RB_ENABLE_CAD);
5405 log_info("Halting.");
5406 reboot(RB_HALT_SYSTEM);
5409 case ACTION_POWEROFF:
5410 log_info("Powering off.");
5411 reboot(RB_POWER_OFF);
5415 log_info("Rebooting.");
5416 reboot(RB_AUTOBOOT);
5420 assert_not_reached("Unknown halt action.");
5423 assert_not_reached("Uh? This shouldn't happen.");
5426 static int halt_main(DBusConnection *bus) {
5429 if (geteuid() != 0) {
5430 /* Try logind if we are a normal user and no special
5431 * mode applies. Maybe PolicyKit allows us to shutdown
5434 if (arg_when <= 0 &&
5437 (arg_action == ACTION_POWEROFF ||
5438 arg_action == ACTION_REBOOT)) {
5439 r = reboot_with_logind(bus, arg_action);
5444 log_error("Must be root.");
5451 m = strv_join(arg_wall, " ");
5452 r = send_shutdownd(arg_when,
5453 arg_action == ACTION_HALT ? 'H' :
5454 arg_action == ACTION_POWEROFF ? 'P' :
5455 arg_action == ACTION_KEXEC ? 'K' :
5463 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
5465 char date[FORMAT_TIMESTAMP_MAX];
5467 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
5468 format_timestamp(date, sizeof(date), arg_when));
5473 if (!arg_dry && !arg_force)
5474 return start_with_fallback(bus);
5477 if (sd_booted() > 0)
5478 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
5480 r = utmp_put_shutdown();
5482 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 log_parse_environment();
5523 r = parse_argv(argc, argv);
5527 retval = EXIT_SUCCESS;
5531 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
5532 * let's shortcut this */
5533 if (arg_action == ACTION_RUNLEVEL) {
5534 r = runlevel_main();
5535 retval = r < 0 ? EXIT_FAILURE : r;
5539 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
5540 log_info("Running in chroot, ignoring request.");
5546 if (arg_transport == TRANSPORT_NORMAL)
5547 bus_connect(arg_scope == UNIT_FILE_SYSTEM ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &bus, &private_bus, &error);
5548 else if (arg_transport == TRANSPORT_POLKIT) {
5549 bus_connect_system_polkit(&bus, &error);
5550 private_bus = false;
5551 } else if (arg_transport == TRANSPORT_SSH) {
5552 bus_connect_system_ssh(NULL, arg_host, &bus, &error);
5553 private_bus = false;
5555 assert_not_reached("Uh, invalid transport...");
5558 switch (arg_action) {
5560 case ACTION_SYSTEMCTL:
5561 r = systemctl_main(bus, argc, argv, &error);
5565 case ACTION_POWEROFF:
5571 case ACTION_RUNLEVEL2:
5572 case ACTION_RUNLEVEL3:
5573 case ACTION_RUNLEVEL4:
5574 case ACTION_RUNLEVEL5:
5576 case ACTION_EMERGENCY:
5577 case ACTION_DEFAULT:
5578 r = start_with_fallback(bus);
5583 r = reload_with_fallback(bus);
5586 case ACTION_CANCEL_SHUTDOWN:
5587 r = send_shutdownd(0, 0, false, false, NULL);
5590 case ACTION_INVALID:
5591 case ACTION_RUNLEVEL:
5593 assert_not_reached("Unknown action");
5596 retval = r < 0 ? EXIT_FAILURE : r;
5600 dbus_connection_flush(bus);
5601 dbus_connection_close(bus);
5602 dbus_connection_unref(bus);
5605 dbus_error_free(&error);
5609 strv_free(arg_property);
5612 ask_password_agent_close();
5613 polkit_agent_close();