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, NULL, NULL, NULL);
3705 for (f = 1; args[f]; f++) {
3708 bool found_native = false, found_sysv;
3710 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
3711 char **k, *l, *q = NULL;
3718 if (!endswith(name, ".service"))
3721 if (path_is_absolute(name))
3724 STRV_FOREACH(k, paths.unit_path) {
3727 if (!isempty(arg_root))
3728 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
3730 asprintf(&p, "%s/%s", *k, name);
3733 log_error("No memory");
3738 found_native = access(p, F_OK) >= 0;
3749 if (!isempty(arg_root))
3750 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
3752 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
3754 log_error("No memory");
3759 p[strlen(p) - sizeof(".service") + 1] = 0;
3760 found_sysv = access(p, F_OK) >= 0;
3767 /* Mark this entry, so that we don't try enabling it as native unit */
3768 args[f] = (char*) "";
3770 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
3772 if (!isempty(arg_root))
3773 argv[c++] = q = strappend("--root=", arg_root);
3775 argv[c++] = path_get_file_name(p);
3777 streq(verb, "enable") ? "on" :
3778 streq(verb, "disable") ? "off" : "--level=5";
3781 l = strv_join((char**)argv, " ");
3783 log_error("No memory.");
3790 log_info("Executing %s", l);
3795 log_error("Failed to fork: %m");
3800 } else if (pid == 0) {
3803 execv(argv[0], (char**) argv);
3804 _exit(EXIT_FAILURE);
3810 j = wait_for_terminate(pid, &status);
3812 log_error("Failed to wait for child: %s", strerror(-r));
3817 if (status.si_code == CLD_EXITED) {
3818 if (streq(verb, "is-enabled")) {
3819 if (status.si_status == 0) {
3828 } else if (status.si_status != 0) {
3839 lookup_paths_free(&paths);
3841 /* Drop all SysV units */
3842 for (f = 1, t = 1; args[f]; f++) {
3844 if (isempty(args[f]))
3847 args[t++] = args[f];
3856 static int enable_unit(DBusConnection *bus, char **args) {
3857 const char *verb = args[0];
3858 UnitFileChange *changes = NULL;
3859 unsigned n_changes = 0, i;
3860 int carries_install_info = -1;
3861 DBusMessage *m = NULL, *reply = NULL;
3865 r = enable_sysv_units(args);
3872 dbus_error_init(&error);
3874 if (!bus || avoid_bus()) {
3875 if (streq(verb, "enable")) {
3876 r = unit_file_enable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3877 carries_install_info = r;
3878 } else if (streq(verb, "disable"))
3879 r = unit_file_disable(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3880 else if (streq(verb, "reenable")) {
3881 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3882 carries_install_info = r;
3883 } else if (streq(verb, "link"))
3884 r = unit_file_link(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3885 else if (streq(verb, "preset")) {
3886 r = unit_file_preset(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3887 carries_install_info = r;
3888 } else if (streq(verb, "mask"))
3889 r = unit_file_mask(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3890 else if (streq(verb, "unmask"))
3891 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3893 assert_not_reached("Unknown verb");
3896 log_error("Operation failed: %s", strerror(-r));
3901 for (i = 0; i < n_changes; i++) {
3902 if (changes[i].type == UNIT_FILE_SYMLINK)
3903 log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
3905 log_info("rm '%s'", changes[i].path);
3911 bool send_force = true, expect_carries_install_info = false;
3913 DBusMessageIter iter, sub, sub2;
3915 if (streq(verb, "enable")) {
3916 method = "EnableUnitFiles";
3917 expect_carries_install_info = true;
3918 } else if (streq(verb, "disable")) {
3919 method = "DisableUnitFiles";
3921 } else if (streq(verb, "reenable")) {
3922 method = "ReenableUnitFiles";
3923 expect_carries_install_info = true;
3924 } else if (streq(verb, "link"))
3925 method = "LinkUnitFiles";
3926 else if (streq(verb, "preset")) {
3927 method = "PresetUnitFiles";
3928 expect_carries_install_info = true;
3929 } else if (streq(verb, "mask"))
3930 method = "MaskUnitFiles";
3931 else if (streq(verb, "unmask")) {
3932 method = "UnmaskUnitFiles";
3935 assert_not_reached("Unknown verb");
3937 m = dbus_message_new_method_call(
3938 "org.freedesktop.systemd1",
3939 "/org/freedesktop/systemd1",
3940 "org.freedesktop.systemd1.Manager",
3943 log_error("Out of memory");
3948 dbus_message_iter_init_append(m, &iter);
3950 r = bus_append_strv_iter(&iter, args+1);
3952 log_error("Failed to append unit files.");
3957 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &a)) {
3958 log_error("Failed to append runtime boolean.");
3966 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b)) {
3967 log_error("Failed to append force boolean.");
3973 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3975 log_error("Failed to issue method call: %s", bus_error_message(&error));
3980 if (!dbus_message_iter_init(reply, &iter)) {
3981 log_error("Failed to initialize iterator.");
3985 if (expect_carries_install_info) {
3986 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &b, true);
3988 log_error("Failed to parse reply.");
3992 carries_install_info = b;
3995 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3996 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
3997 log_error("Failed to parse reply.");
4002 dbus_message_iter_recurse(&iter, &sub);
4003 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
4004 const char *type, *path, *source;
4006 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
4007 log_error("Failed to parse reply.");
4012 dbus_message_iter_recurse(&sub, &sub2);
4014 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
4015 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
4016 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &source, false) < 0) {
4017 log_error("Failed to parse reply.");
4023 if (streq(type, "symlink"))
4024 log_info("ln -s '%s' '%s'", source, path);
4026 log_info("rm '%s'", path);
4029 dbus_message_iter_next(&sub);
4032 /* Try to reload if enabeld */
4034 r = daemon_reload(bus, args);
4037 if (carries_install_info == 0)
4038 log_warning("Warning: unit files do not carry install information. No operation executed.");
4042 dbus_message_unref(m);
4045 dbus_message_unref(reply);
4047 unit_file_changes_free(changes, n_changes);
4049 dbus_error_free(&error);
4053 static int unit_is_enabled(DBusConnection *bus, char **args) {
4056 DBusMessage *m = NULL, *reply = NULL;
4060 dbus_error_init(&error);
4062 r = enable_sysv_units(args);
4068 if (!bus || avoid_bus()) {
4070 STRV_FOREACH(name, args+1) {
4071 UnitFileState state;
4073 state = unit_file_get_state(arg_scope, arg_root, *name);
4079 if (state == UNIT_FILE_ENABLED ||
4080 state == UNIT_FILE_ENABLED_RUNTIME ||
4081 state == UNIT_FILE_STATIC)
4085 puts(unit_file_state_to_string(state));
4089 STRV_FOREACH(name, args+1) {
4092 m = dbus_message_new_method_call(
4093 "org.freedesktop.systemd1",
4094 "/org/freedesktop/systemd1",
4095 "org.freedesktop.systemd1.Manager",
4096 "GetUnitFileState");
4098 log_error("Out of memory");
4103 if (!dbus_message_append_args(m,
4104 DBUS_TYPE_STRING, name,
4105 DBUS_TYPE_INVALID)) {
4106 log_error("Could not append arguments to message.");
4111 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
4113 log_error("Failed to issue method call: %s", bus_error_message(&error));
4118 if (!dbus_message_get_args(reply, &error,
4119 DBUS_TYPE_STRING, &s,
4120 DBUS_TYPE_INVALID)) {
4121 log_error("Failed to parse reply: %s", bus_error_message(&error));
4126 dbus_message_unref(m);
4127 dbus_message_unref(reply);
4130 if (streq(s, "enabled") ||
4131 streq(s, "enabled-runtime") ||
4140 r = enabled ? 0 : 1;
4144 dbus_message_unref(m);
4147 dbus_message_unref(reply);
4149 dbus_error_free(&error);
4153 static int systemctl_help(void) {
4155 pager_open_if_enabled();
4157 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
4158 "Query or send control commands to the systemd manager.\n\n"
4159 " -h --help Show this help\n"
4160 " --version Show package version\n"
4161 " -t --type=TYPE List only units of a particular type\n"
4162 " -p --property=NAME Show only properties by this name\n"
4163 " -a --all Show all units/properties, including dead/empty ones\n"
4164 " --failed Show only failed units\n"
4165 " --full Don't ellipsize unit names on output\n"
4166 " --fail When queueing a new job, fail if conflicting jobs are\n"
4168 " --ignore-dependencies\n"
4169 " When queueing a new job, ignore all its dependencies\n"
4170 " --kill-who=WHO Who to send signal to\n"
4171 " -s --signal=SIGNAL Which signal to send\n"
4172 " -H --host=[USER@]HOST\n"
4173 " Show information for remote host\n"
4174 " -P --privileged Acquire privileges before execution\n"
4175 " -q --quiet Suppress output\n"
4176 " --no-block Do not wait until operation finished\n"
4177 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4178 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
4180 " --no-legend Do not print a legend (column headers and hints)\n"
4181 " --no-pager Do not pipe output into a pager\n"
4182 " --no-ask-password\n"
4183 " Do not ask for system passwords\n"
4184 " --order When generating graph for dot, show only order\n"
4185 " --require When generating graph for dot, show only requirement\n"
4186 " --system Connect to system manager\n"
4187 " --user Connect to user service manager\n"
4188 " --global Enable/disable unit files globally\n"
4189 " -f --force When enabling unit files, override existing symlinks\n"
4190 " When shutting down, execute action immediately\n"
4191 " --root=PATH Enable unit files in the specified root directory\n"
4192 " --runtime Enable unit files only temporarily until next reboot\n"
4193 " -n --lines=INTEGER Journal entries to show\n"
4194 " --follow Follow journal\n"
4195 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
4196 " verbose, export, json, cat)\n\n"
4198 " list-units List loaded units\n"
4199 " start [NAME...] Start (activate) one or more units\n"
4200 " stop [NAME...] Stop (deactivate) one or more units\n"
4201 " reload [NAME...] Reload one or more units\n"
4202 " restart [NAME...] Start or restart one or more units\n"
4203 " try-restart [NAME...] Restart one or more units if active\n"
4204 " reload-or-restart [NAME...] Reload one or more units is possible,\n"
4205 " otherwise start or restart\n"
4206 " reload-or-try-restart [NAME...] Reload one or more units is possible,\n"
4207 " otherwise restart if active\n"
4208 " isolate [NAME] Start one unit and stop all others\n"
4209 " kill [NAME...] Send signal to processes of a unit\n"
4210 " is-active [NAME...] Check whether units are active\n"
4211 " status [NAME...|PID...] Show runtime status of one or more units\n"
4212 " show [NAME...|JOB...] Show properties of one or more\n"
4213 " units/jobs or the manager\n"
4214 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
4216 " load [NAME...] Load one or more units\n\n"
4217 "Unit File Commands:\n"
4218 " list-unit-files List installed unit files\n"
4219 " enable [NAME...] Enable one or more unit files\n"
4220 " disable [NAME...] Disable one or more unit files\n"
4221 " reenable [NAME...] Reenable one or more unit files\n"
4222 " preset [NAME...] Enable/disable one or more unit files\n"
4223 " based on preset configuration\n"
4224 " mask [NAME...] Mask one or more units\n"
4225 " unmask [NAME...] Unmask one or more units\n"
4226 " link [PATH...] Link one or more units files into\n"
4227 " the search path\n"
4228 " is-enabled [NAME...] Check whether unit files are enabled\n\n"
4230 " list-jobs List jobs\n"
4231 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
4232 "Status Commands:\n"
4233 " dump Dump server status\n"
4234 " dot Dump dependency graph for dot(1)\n\n"
4235 "Snapshot Commands:\n"
4236 " snapshot [NAME] Create a snapshot\n"
4237 " delete [NAME...] Remove one or more snapshots\n\n"
4238 "Environment Commands:\n"
4239 " show-environment Dump environment\n"
4240 " set-environment [NAME=VALUE...] Set one or more environment variables\n"
4241 " unset-environment [NAME...] Unset one or more environment variables\n\n"
4242 "Manager Lifecycle Commands:\n"
4243 " daemon-reload Reload systemd manager configuration\n"
4244 " daemon-reexec Reexecute systemd manager\n\n"
4245 "System Commands:\n"
4246 " default Enter system default mode\n"
4247 " rescue Enter system rescue mode\n"
4248 " emergency Enter system emergency mode\n"
4249 " halt Shut down and halt the system\n"
4250 " poweroff Shut down and power-off the system\n"
4251 " reboot Shut down and reboot the system\n"
4252 " kexec Shut down and reboot the system with kexec\n"
4253 " exit Request user instance exit\n"
4254 " switch-root [ROOT] [INIT] Change to a different root file system\n"
4255 " suspend Suspend the system\n"
4256 " hibernate Hibernate the system\n",
4257 program_invocation_short_name);
4262 static int halt_help(void) {
4264 printf("%s [OPTIONS...]\n\n"
4265 "%s the system.\n\n"
4266 " --help Show this help\n"
4267 " --halt Halt the machine\n"
4268 " -p --poweroff Switch off the machine\n"
4269 " --reboot Reboot the machine\n"
4270 " -f --force Force immediate halt/power-off/reboot\n"
4271 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
4272 " -d --no-wtmp Don't write wtmp record\n"
4273 " -n --no-sync Don't sync before halt/power-off/reboot\n"
4274 " --no-wall Don't send wall message before halt/power-off/reboot\n",
4275 program_invocation_short_name,
4276 arg_action == ACTION_REBOOT ? "Reboot" :
4277 arg_action == ACTION_POWEROFF ? "Power off" :
4283 static int shutdown_help(void) {
4285 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
4286 "Shut down the system.\n\n"
4287 " --help Show this help\n"
4288 " -H --halt Halt the machine\n"
4289 " -P --poweroff Power-off the machine\n"
4290 " -r --reboot Reboot the machine\n"
4291 " -h Equivalent to --poweroff, overridden by --halt\n"
4292 " -k Don't halt/power-off/reboot, just send warnings\n"
4293 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4294 " -c Cancel a pending shutdown\n",
4295 program_invocation_short_name);
4300 static int telinit_help(void) {
4302 printf("%s [OPTIONS...] {COMMAND}\n\n"
4303 "Send control commands to the init daemon.\n\n"
4304 " --help Show this help\n"
4305 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
4307 " 0 Power-off the machine\n"
4308 " 6 Reboot the machine\n"
4309 " 2, 3, 4, 5 Start runlevelX.target unit\n"
4310 " 1, s, S Enter rescue mode\n"
4311 " q, Q Reload init daemon configuration\n"
4312 " u, U Reexecute init daemon\n",
4313 program_invocation_short_name);
4318 static int runlevel_help(void) {
4320 printf("%s [OPTIONS...]\n\n"
4321 "Prints the previous and current runlevel of the init system.\n\n"
4322 " --help Show this help\n",
4323 program_invocation_short_name);
4328 static int systemctl_parse_argv(int argc, char *argv[]) {
4332 ARG_IGNORE_DEPENDENCIES,
4348 ARG_NO_ASK_PASSWORD,
4355 static const struct option options[] = {
4356 { "help", no_argument, NULL, 'h' },
4357 { "version", no_argument, NULL, ARG_VERSION },
4358 { "type", required_argument, NULL, 't' },
4359 { "property", required_argument, NULL, 'p' },
4360 { "all", no_argument, NULL, 'a' },
4361 { "failed", no_argument, NULL, ARG_FAILED },
4362 { "full", no_argument, NULL, ARG_FULL },
4363 { "fail", no_argument, NULL, ARG_FAIL },
4364 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
4365 { "user", no_argument, NULL, ARG_USER },
4366 { "system", no_argument, NULL, ARG_SYSTEM },
4367 { "global", no_argument, NULL, ARG_GLOBAL },
4368 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
4369 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
4370 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
4371 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4372 { "quiet", no_argument, NULL, 'q' },
4373 { "order", no_argument, NULL, ARG_ORDER },
4374 { "require", no_argument, NULL, ARG_REQUIRE },
4375 { "root", required_argument, NULL, ARG_ROOT },
4376 { "force", no_argument, NULL, ARG_FORCE },
4377 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
4378 { "kill-mode", required_argument, NULL, ARG_KILL_MODE }, /* undocumented on purpose */
4379 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
4380 { "signal", required_argument, NULL, 's' },
4381 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
4382 { "host", required_argument, NULL, 'H' },
4383 { "privileged",no_argument, NULL, 'P' },
4384 { "runtime", no_argument, NULL, ARG_RUNTIME },
4385 { "lines", required_argument, NULL, 'n' },
4386 { "follow", no_argument, NULL, ARG_FOLLOW },
4387 { "output", required_argument, NULL, 'o' },
4388 { NULL, 0, NULL, 0 }
4396 while ((c = getopt_long(argc, argv, "ht:p:aqfs:H:Pn:o:", options, NULL)) >= 0) {
4405 puts(PACKAGE_STRING);
4407 puts(SYSTEMD_FEATURES);
4417 if (!(l = strv_append(arg_property, optarg)))
4420 strv_free(arg_property);
4423 /* If the user asked for a particular
4424 * property, show it to him, even if it is
4435 arg_job_mode = "fail";
4438 case ARG_IGNORE_DEPENDENCIES:
4439 arg_job_mode = "ignore-dependencies";
4443 arg_scope = UNIT_FILE_USER;
4447 arg_scope = UNIT_FILE_SYSTEM;
4451 arg_scope = UNIT_FILE_GLOBAL;
4455 arg_no_block = true;
4459 arg_no_legend = true;
4463 arg_no_pager = true;
4471 arg_dot = DOT_ORDER;
4475 arg_dot = DOT_REQUIRE;
4503 /* -f is short for both --follow and --force! */
4509 arg_no_reload = true;
4513 arg_kill_who = optarg;
4517 arg_kill_mode = optarg;
4521 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
4522 log_error("Failed to parse signal string %s.", optarg);
4527 case ARG_NO_ASK_PASSWORD:
4528 arg_ask_password = false;
4532 arg_transport = TRANSPORT_POLKIT;
4536 arg_transport = TRANSPORT_SSH;
4545 if (safe_atou(optarg, &arg_lines) < 0) {
4546 log_error("Failed to parse lines '%s'", optarg);
4552 arg_output = output_mode_from_string(optarg);
4553 if (arg_output < 0) {
4554 log_error("Unknown output '%s'.", optarg);
4563 log_error("Unknown option code %c", c);
4568 if (arg_transport != TRANSPORT_NORMAL && arg_scope != UNIT_FILE_SYSTEM) {
4569 log_error("Cannot access user instance remotely.");
4576 static int halt_parse_argv(int argc, char *argv[]) {
4585 static const struct option options[] = {
4586 { "help", no_argument, NULL, ARG_HELP },
4587 { "halt", no_argument, NULL, ARG_HALT },
4588 { "poweroff", no_argument, NULL, 'p' },
4589 { "reboot", no_argument, NULL, ARG_REBOOT },
4590 { "force", no_argument, NULL, 'f' },
4591 { "wtmp-only", no_argument, NULL, 'w' },
4592 { "no-wtmp", no_argument, NULL, 'd' },
4593 { "no-sync", no_argument, NULL, 'n' },
4594 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4595 { NULL, 0, NULL, 0 }
4603 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
4604 if (runlevel == '0' || runlevel == '6')
4607 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
4615 arg_action = ACTION_HALT;
4619 if (arg_action != ACTION_REBOOT)
4620 arg_action = ACTION_POWEROFF;
4624 arg_action = ACTION_REBOOT;
4649 /* Compatibility nops */
4656 log_error("Unknown option code %c", c);
4661 if (optind < argc) {
4662 log_error("Too many arguments.");
4669 static int parse_time_spec(const char *t, usec_t *_u) {
4673 if (streq(t, "now"))
4675 else if (!strchr(t, ':')) {
4678 if (safe_atou64(t, &u) < 0)
4681 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
4690 hour = strtol(t, &e, 10);
4691 if (errno != 0 || *e != ':' || hour < 0 || hour > 23)
4694 minute = strtol(e+1, &e, 10);
4695 if (errno != 0 || *e != 0 || minute < 0 || minute > 59)
4698 n = now(CLOCK_REALTIME);
4699 s = (time_t) (n / USEC_PER_SEC);
4702 assert_se(localtime_r(&s, &tm));
4704 tm.tm_hour = (int) hour;
4705 tm.tm_min = (int) minute;
4708 assert_se(s = mktime(&tm));
4710 *_u = (usec_t) s * USEC_PER_SEC;
4713 *_u += USEC_PER_DAY;
4719 static int shutdown_parse_argv(int argc, char *argv[]) {
4726 static const struct option options[] = {
4727 { "help", no_argument, NULL, ARG_HELP },
4728 { "halt", no_argument, NULL, 'H' },
4729 { "poweroff", no_argument, NULL, 'P' },
4730 { "reboot", no_argument, NULL, 'r' },
4731 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
4732 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4733 { NULL, 0, NULL, 0 }
4741 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
4749 arg_action = ACTION_HALT;
4753 arg_action = ACTION_POWEROFF;
4758 arg_action = ACTION_KEXEC;
4760 arg_action = ACTION_REBOOT;
4764 arg_action = ACTION_KEXEC;
4768 if (arg_action != ACTION_HALT)
4769 arg_action = ACTION_POWEROFF;
4782 /* Compatibility nops */
4786 arg_action = ACTION_CANCEL_SHUTDOWN;
4793 log_error("Unknown option code %c", c);
4798 if (argc > optind) {
4799 r = parse_time_spec(argv[optind], &arg_when);
4801 log_error("Failed to parse time specification: %s", argv[optind]);
4805 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
4807 /* We skip the time argument */
4808 if (argc > optind + 1)
4809 arg_wall = argv + optind + 1;
4816 static int telinit_parse_argv(int argc, char *argv[]) {
4823 static const struct option options[] = {
4824 { "help", no_argument, NULL, ARG_HELP },
4825 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4826 { NULL, 0, NULL, 0 }
4829 static const struct {
4833 { '0', ACTION_POWEROFF },
4834 { '6', ACTION_REBOOT },
4835 { '1', ACTION_RESCUE },
4836 { '2', ACTION_RUNLEVEL2 },
4837 { '3', ACTION_RUNLEVEL3 },
4838 { '4', ACTION_RUNLEVEL4 },
4839 { '5', ACTION_RUNLEVEL5 },
4840 { 's', ACTION_RESCUE },
4841 { 'S', ACTION_RESCUE },
4842 { 'q', ACTION_RELOAD },
4843 { 'Q', ACTION_RELOAD },
4844 { 'u', ACTION_REEXEC },
4845 { 'U', ACTION_REEXEC }
4854 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4869 log_error("Unknown option code %c", c);
4874 if (optind >= argc) {
4879 if (optind + 1 < argc) {
4880 log_error("Too many arguments.");
4884 if (strlen(argv[optind]) != 1) {
4885 log_error("Expected single character argument.");
4889 for (i = 0; i < ELEMENTSOF(table); i++)
4890 if (table[i].from == argv[optind][0])
4893 if (i >= ELEMENTSOF(table)) {
4894 log_error("Unknown command %s.", argv[optind]);
4898 arg_action = table[i].to;
4905 static int runlevel_parse_argv(int argc, char *argv[]) {
4911 static const struct option options[] = {
4912 { "help", no_argument, NULL, ARG_HELP },
4913 { NULL, 0, NULL, 0 }
4921 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4932 log_error("Unknown option code %c", c);
4937 if (optind < argc) {
4938 log_error("Too many arguments.");
4945 static int parse_argv(int argc, char *argv[]) {
4949 if (program_invocation_short_name) {
4951 if (strstr(program_invocation_short_name, "halt")) {
4952 arg_action = ACTION_HALT;
4953 return halt_parse_argv(argc, argv);
4954 } else if (strstr(program_invocation_short_name, "poweroff")) {
4955 arg_action = ACTION_POWEROFF;
4956 return halt_parse_argv(argc, argv);
4957 } else if (strstr(program_invocation_short_name, "reboot")) {
4959 arg_action = ACTION_KEXEC;
4961 arg_action = ACTION_REBOOT;
4962 return halt_parse_argv(argc, argv);
4963 } else if (strstr(program_invocation_short_name, "shutdown")) {
4964 arg_action = ACTION_POWEROFF;
4965 return shutdown_parse_argv(argc, argv);
4966 } else if (strstr(program_invocation_short_name, "init")) {
4968 if (sd_booted() > 0) {
4969 arg_action = ACTION_INVALID;
4970 return telinit_parse_argv(argc, argv);
4972 /* Hmm, so some other init system is
4973 * running, we need to forward this
4974 * request to it. For now we simply
4975 * guess that it is Upstart. */
4977 execv("/lib/upstart/telinit", argv);
4979 log_error("Couldn't find an alternative telinit implementation to spawn.");
4983 } else if (strstr(program_invocation_short_name, "runlevel")) {
4984 arg_action = ACTION_RUNLEVEL;
4985 return runlevel_parse_argv(argc, argv);
4989 arg_action = ACTION_SYSTEMCTL;
4990 return systemctl_parse_argv(argc, argv);
4993 static int action_to_runlevel(void) {
4995 static const char table[_ACTION_MAX] = {
4996 [ACTION_HALT] = '0',
4997 [ACTION_POWEROFF] = '0',
4998 [ACTION_REBOOT] = '6',
4999 [ACTION_RUNLEVEL2] = '2',
5000 [ACTION_RUNLEVEL3] = '3',
5001 [ACTION_RUNLEVEL4] = '4',
5002 [ACTION_RUNLEVEL5] = '5',
5003 [ACTION_RESCUE] = '1'
5006 assert(arg_action < _ACTION_MAX);
5008 return table[arg_action];
5011 static int talk_upstart(void) {
5012 DBusMessage *m = NULL, *reply = NULL;
5014 int previous, rl, r;
5016 env1_buf[] = "RUNLEVEL=X",
5017 env2_buf[] = "PREVLEVEL=X";
5018 char *env1 = env1_buf, *env2 = env2_buf;
5019 const char *emit = "runlevel";
5020 dbus_bool_t b_false = FALSE;
5021 DBusMessageIter iter, sub;
5022 DBusConnection *bus;
5024 dbus_error_init(&error);
5026 if (!(rl = action_to_runlevel()))
5029 if (utmp_get_runlevel(&previous, NULL) < 0)
5032 if (!(bus = dbus_connection_open_private("unix:abstract=/com/ubuntu/upstart", &error))) {
5033 if (dbus_error_has_name(&error, DBUS_ERROR_NO_SERVER)) {
5038 log_error("Failed to connect to Upstart bus: %s", bus_error_message(&error));
5043 if ((r = bus_check_peercred(bus)) < 0) {
5044 log_error("Failed to verify owner of bus.");
5048 if (!(m = dbus_message_new_method_call(
5049 "com.ubuntu.Upstart",
5050 "/com/ubuntu/Upstart",
5051 "com.ubuntu.Upstart0_6",
5054 log_error("Could not allocate message.");
5059 dbus_message_iter_init_append(m, &iter);
5061 env1_buf[sizeof(env1_buf)-2] = rl;
5062 env2_buf[sizeof(env2_buf)-2] = previous;
5064 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &emit) ||
5065 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub) ||
5066 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env1) ||
5067 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env2) ||
5068 !dbus_message_iter_close_container(&iter, &sub) ||
5069 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b_false)) {
5070 log_error("Could not append arguments to message.");
5075 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
5077 if (error_is_no_service(&error)) {
5082 log_error("Failed to issue method call: %s", bus_error_message(&error));
5091 dbus_message_unref(m);
5094 dbus_message_unref(reply);
5097 dbus_connection_flush(bus);
5098 dbus_connection_close(bus);
5099 dbus_connection_unref(bus);
5102 dbus_error_free(&error);
5107 static int talk_initctl(void) {
5108 struct init_request request;
5112 if (!(rl = action_to_runlevel()))
5116 request.magic = INIT_MAGIC;
5117 request.sleeptime = 0;
5118 request.cmd = INIT_CMD_RUNLVL;
5119 request.runlevel = rl;
5121 if ((fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY)) < 0) {
5123 if (errno == ENOENT)
5126 log_error("Failed to open "INIT_FIFO": %m");
5131 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
5132 close_nointr_nofail(fd);
5135 log_error("Failed to write to "INIT_FIFO": %m");
5136 return errno ? -errno : -EIO;
5142 static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
5144 static const struct {
5152 int (* const dispatch)(DBusConnection *bus, char **args);
5154 { "list-units", LESS, 1, list_units },
5155 { "list-unit-files", EQUAL, 1, list_unit_files },
5156 { "list-jobs", EQUAL, 1, list_jobs },
5157 { "clear-jobs", EQUAL, 1, daemon_reload },
5158 { "load", MORE, 2, load_unit },
5159 { "cancel", MORE, 2, cancel_job },
5160 { "start", MORE, 2, start_unit },
5161 { "stop", MORE, 2, start_unit },
5162 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5163 { "reload", MORE, 2, start_unit },
5164 { "restart", MORE, 2, start_unit },
5165 { "try-restart", MORE, 2, start_unit },
5166 { "reload-or-restart", MORE, 2, start_unit },
5167 { "reload-or-try-restart", MORE, 2, start_unit },
5168 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
5169 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5170 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
5171 { "isolate", EQUAL, 2, start_unit },
5172 { "kill", MORE, 2, kill_unit },
5173 { "is-active", MORE, 2, check_unit },
5174 { "check", MORE, 2, check_unit },
5175 { "show", MORE, 1, show },
5176 { "status", MORE, 2, show },
5177 { "dump", EQUAL, 1, dump },
5178 { "dot", EQUAL, 1, dot },
5179 { "snapshot", LESS, 2, snapshot },
5180 { "delete", MORE, 2, delete_snapshot },
5181 { "daemon-reload", EQUAL, 1, daemon_reload },
5182 { "daemon-reexec", EQUAL, 1, daemon_reload },
5183 { "show-environment", EQUAL, 1, show_enviroment },
5184 { "set-environment", MORE, 2, set_environment },
5185 { "unset-environment", MORE, 2, set_environment },
5186 { "halt", EQUAL, 1, start_special },
5187 { "poweroff", EQUAL, 1, start_special },
5188 { "reboot", EQUAL, 1, start_special },
5189 { "kexec", EQUAL, 1, start_special },
5190 { "suspend", EQUAL, 1, start_special },
5191 { "hibernate", EQUAL, 1, start_special },
5192 { "default", EQUAL, 1, start_special },
5193 { "rescue", EQUAL, 1, start_special },
5194 { "emergency", EQUAL, 1, start_special },
5195 { "exit", EQUAL, 1, start_special },
5196 { "reset-failed", MORE, 1, reset_failed },
5197 { "enable", MORE, 2, enable_unit },
5198 { "disable", MORE, 2, enable_unit },
5199 { "is-enabled", MORE, 2, unit_is_enabled },
5200 { "reenable", MORE, 2, enable_unit },
5201 { "preset", MORE, 2, enable_unit },
5202 { "mask", MORE, 2, enable_unit },
5203 { "unmask", MORE, 2, enable_unit },
5204 { "link", MORE, 2, enable_unit },
5205 { "switch-root", MORE, 2, switch_root },
5215 left = argc - optind;
5218 /* Special rule: no arguments means "list-units" */
5221 if (streq(argv[optind], "help")) {
5226 for (i = 0; i < ELEMENTSOF(verbs); i++)
5227 if (streq(argv[optind], verbs[i].verb))
5230 if (i >= ELEMENTSOF(verbs)) {
5231 log_error("Unknown operation %s", argv[optind]);
5236 switch (verbs[i].argc_cmp) {
5239 if (left != verbs[i].argc) {
5240 log_error("Invalid number of arguments.");
5247 if (left < verbs[i].argc) {
5248 log_error("Too few arguments.");
5255 if (left > verbs[i].argc) {
5256 log_error("Too many arguments.");
5263 assert_not_reached("Unknown comparison operator.");
5266 /* Require a bus connection for all operations but
5268 if (!streq(verbs[i].verb, "enable") &&
5269 !streq(verbs[i].verb, "disable") &&
5270 !streq(verbs[i].verb, "is-enabled") &&
5271 !streq(verbs[i].verb, "list-unit-files") &&
5272 !streq(verbs[i].verb, "reenable") &&
5273 !streq(verbs[i].verb, "preset") &&
5274 !streq(verbs[i].verb, "mask") &&
5275 !streq(verbs[i].verb, "unmask") &&
5276 !streq(verbs[i].verb, "link")) {
5278 if (running_in_chroot() > 0) {
5279 log_info("Running in chroot, ignoring request.");
5283 if (((!streq(verbs[i].verb, "reboot") &&
5284 !streq(verbs[i].verb, "halt") &&
5285 !streq(verbs[i].verb, "poweroff")) || arg_force <= 0) && !bus) {
5286 log_error("Failed to get D-Bus connection: %s",
5287 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5293 if (!bus && !avoid_bus()) {
5294 log_error("Failed to get D-Bus connection: %s",
5295 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5300 return verbs[i].dispatch(bus, argv + optind);
5303 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
5305 struct msghdr msghdr;
5306 struct iovec iovec[2];
5307 union sockaddr_union sockaddr;
5308 struct sd_shutdown_command c;
5310 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
5317 c.dry_run = dry_run;
5321 sockaddr.sa.sa_family = AF_UNIX;
5322 strncpy(sockaddr.un.sun_path, "/run/systemd/shutdownd", sizeof(sockaddr.un.sun_path));
5325 msghdr.msg_name = &sockaddr;
5326 msghdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + sizeof("/run/systemd/shutdownd") - 1;
5329 iovec[0].iov_base = (char*) &c;
5330 iovec[0].iov_len = offsetof(struct sd_shutdown_command, wall_message);
5332 if (isempty(message))
5333 msghdr.msg_iovlen = 1;
5335 iovec[1].iov_base = (char*) message;
5336 iovec[1].iov_len = strlen(message);
5337 msghdr.msg_iovlen = 2;
5339 msghdr.msg_iov = iovec;
5341 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0) {
5342 close_nointr_nofail(fd);
5346 close_nointr_nofail(fd);
5350 static int reload_with_fallback(DBusConnection *bus) {
5353 /* First, try systemd via D-Bus. */
5354 if (daemon_reload(bus, NULL) >= 0)
5358 /* Nothing else worked, so let's try signals */
5359 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
5361 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
5362 log_error("kill() failed: %m");
5369 static int start_with_fallback(DBusConnection *bus) {
5372 /* First, try systemd via D-Bus. */
5373 if (start_unit(bus, NULL) >= 0)
5377 /* Hmm, talking to systemd via D-Bus didn't work. Then
5378 * let's try to talk to Upstart via D-Bus. */
5379 if (talk_upstart() > 0)
5382 /* Nothing else worked, so let's try
5384 if (talk_initctl() > 0)
5387 log_error("Failed to talk to init daemon.");
5391 warn_wall(arg_action);
5395 static void halt_now(enum action a) {
5397 /* Make sure C-A-D is handled by the kernel from this
5399 reboot(RB_ENABLE_CAD);
5404 log_info("Halting.");
5405 reboot(RB_HALT_SYSTEM);
5408 case ACTION_POWEROFF:
5409 log_info("Powering off.");
5410 reboot(RB_POWER_OFF);
5414 log_info("Rebooting.");
5415 reboot(RB_AUTOBOOT);
5419 assert_not_reached("Unknown halt action.");
5422 assert_not_reached("Uh? This shouldn't happen.");
5425 static int halt_main(DBusConnection *bus) {
5428 if (geteuid() != 0) {
5429 /* Try logind if we are a normal user and no special
5430 * mode applies. Maybe PolicyKit allows us to shutdown
5433 if (arg_when <= 0 &&
5436 (arg_action == ACTION_POWEROFF ||
5437 arg_action == ACTION_REBOOT)) {
5438 r = reboot_with_logind(bus, arg_action);
5443 log_error("Must be root.");
5450 m = strv_join(arg_wall, " ");
5451 r = send_shutdownd(arg_when,
5452 arg_action == ACTION_HALT ? 'H' :
5453 arg_action == ACTION_POWEROFF ? 'P' :
5454 arg_action == ACTION_KEXEC ? 'K' :
5462 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
5464 char date[FORMAT_TIMESTAMP_MAX];
5466 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
5467 format_timestamp(date, sizeof(date), arg_when));
5472 if (!arg_dry && !arg_force)
5473 return start_with_fallback(bus);
5476 if (sd_booted() > 0)
5477 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
5479 r = utmp_put_shutdown();
5481 log_warning("Failed to write utmp record: %s", strerror(-r));
5491 halt_now(arg_action);
5492 /* We should never reach this. */
5496 static int runlevel_main(void) {
5497 int r, runlevel, previous;
5499 r = utmp_get_runlevel(&runlevel, &previous);
5506 previous <= 0 ? 'N' : previous,
5507 runlevel <= 0 ? 'N' : runlevel);
5512 int main(int argc, char*argv[]) {
5513 int r, retval = EXIT_FAILURE;
5514 DBusConnection *bus = NULL;
5517 dbus_error_init(&error);
5519 log_parse_environment();
5522 r = parse_argv(argc, argv);
5526 retval = EXIT_SUCCESS;
5530 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
5531 * let's shortcut this */
5532 if (arg_action == ACTION_RUNLEVEL) {
5533 r = runlevel_main();
5534 retval = r < 0 ? EXIT_FAILURE : r;
5538 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
5539 log_info("Running in chroot, ignoring request.");
5545 if (arg_transport == TRANSPORT_NORMAL)
5546 bus_connect(arg_scope == UNIT_FILE_SYSTEM ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &bus, &private_bus, &error);
5547 else if (arg_transport == TRANSPORT_POLKIT) {
5548 bus_connect_system_polkit(&bus, &error);
5549 private_bus = false;
5550 } else if (arg_transport == TRANSPORT_SSH) {
5551 bus_connect_system_ssh(NULL, arg_host, &bus, &error);
5552 private_bus = false;
5554 assert_not_reached("Uh, invalid transport...");
5557 switch (arg_action) {
5559 case ACTION_SYSTEMCTL:
5560 r = systemctl_main(bus, argc, argv, &error);
5564 case ACTION_POWEROFF:
5570 case ACTION_RUNLEVEL2:
5571 case ACTION_RUNLEVEL3:
5572 case ACTION_RUNLEVEL4:
5573 case ACTION_RUNLEVEL5:
5575 case ACTION_EMERGENCY:
5576 case ACTION_DEFAULT:
5577 r = start_with_fallback(bus);
5582 r = reload_with_fallback(bus);
5585 case ACTION_CANCEL_SHUTDOWN:
5586 r = send_shutdownd(0, 0, false, false, NULL);
5589 case ACTION_INVALID:
5590 case ACTION_RUNLEVEL:
5592 assert_not_reached("Unknown action");
5595 retval = r < 0 ? EXIT_FAILURE : r;
5599 dbus_connection_flush(bus);
5600 dbus_connection_close(bus);
5601 dbus_connection_unref(bus);
5604 dbus_error_free(&error);
5608 strv_free(arg_property);
5611 ask_password_agent_close();
5612 polkit_agent_close();