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;
2164 const char *default_control_group;
2166 const char *load_error;
2169 usec_t inactive_exit_timestamp;
2170 usec_t inactive_exit_timestamp_monotonic;
2171 usec_t active_enter_timestamp;
2172 usec_t active_exit_timestamp;
2173 usec_t inactive_enter_timestamp;
2175 bool need_daemon_reload;
2180 const char *status_text;
2182 #ifdef HAVE_SYSV_COMPAT
2186 usec_t start_timestamp;
2187 usec_t exit_timestamp;
2189 int exit_code, exit_status;
2191 usec_t condition_timestamp;
2192 bool condition_result;
2195 unsigned n_accepted;
2196 unsigned n_connections;
2200 const char *sysfs_path;
2202 /* Mount, Automount */
2208 LIST_HEAD(ExecStatusInfo, exec);
2211 static void print_status_info(UnitStatusInfo *i) {
2213 const char *on, *off, *ss;
2215 char since1[FORMAT_TIMESTAMP_PRETTY_MAX], *s1;
2216 char since2[FORMAT_TIMESTAMP_MAX], *s2;
2220 /* This shows pretty information about a unit. See
2221 * print_property() for a low-level property printer */
2223 printf("%s", strna(i->id));
2225 if (i->description && !streq_ptr(i->id, i->description))
2226 printf(" - %s", i->description);
2231 printf("\t Follow: unit currently follows state of %s\n", i->following);
2233 if (streq_ptr(i->load_state, "error")) {
2234 on = ansi_highlight_red(true);
2235 off = ansi_highlight_red(false);
2240 printf("\t Loaded: %s%s%s (Reason: %s)\n", on, strna(i->load_state), off, i->load_error);
2241 else if (i->path && i->unit_file_state)
2242 printf("\t Loaded: %s%s%s (%s; %s)\n", on, strna(i->load_state), off, i->path, i->unit_file_state);
2244 printf("\t Loaded: %s%s%s (%s)\n", on, strna(i->load_state), off, i->path);
2246 printf("\t Loaded: %s%s%s\n", on, strna(i->load_state), off);
2248 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
2250 if (streq_ptr(i->active_state, "failed")) {
2251 on = ansi_highlight_red(true);
2252 off = ansi_highlight_red(false);
2253 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
2254 on = ansi_highlight_green(true);
2255 off = ansi_highlight_green(false);
2260 printf("\t Active: %s%s (%s)%s",
2262 strna(i->active_state),
2266 printf("\t Active: %s%s%s",
2268 strna(i->active_state),
2271 if (!isempty(i->result) && !streq(i->result, "success"))
2272 printf(" (Result: %s)", i->result);
2274 timestamp = (streq_ptr(i->active_state, "active") ||
2275 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
2276 (streq_ptr(i->active_state, "inactive") ||
2277 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
2278 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
2279 i->active_exit_timestamp;
2281 s1 = format_timestamp_pretty(since1, sizeof(since1), timestamp);
2282 s2 = format_timestamp(since2, sizeof(since2), timestamp);
2285 printf(" since %s; %s\n", s2, s1);
2287 printf(" since %s\n", s2);
2291 if (!i->condition_result && i->condition_timestamp > 0) {
2292 s1 = format_timestamp_pretty(since1, sizeof(since1), i->condition_timestamp);
2293 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
2296 printf("\t start condition failed at %s; %s\n", s2, s1);
2298 printf("\t start condition failed at %s\n", s2);
2302 printf("\t Device: %s\n", i->sysfs_path);
2304 printf("\t Where: %s\n", i->where);
2306 printf("\t What: %s\n", i->what);
2308 if (!strv_isempty(i->documentation)) {
2312 STRV_FOREACH(t, i->documentation) {
2314 printf("\t Docs: %s\n", *t);
2317 printf("\t %s\n", *t);
2322 printf("\tAccepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
2324 LIST_FOREACH(exec, p, i->exec) {
2328 /* Only show exited processes here */
2332 t = strv_join(p->argv, " ");
2333 printf("\t Process: %u %s=%s ", p->pid, p->name, strna(t));
2336 #ifdef HAVE_SYSV_COMPAT
2338 good = is_clean_exit_lsb(p->code, p->status);
2341 good = is_clean_exit(p->code, p->status);
2344 on = ansi_highlight_red(true);
2345 off = ansi_highlight_red(false);
2349 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
2351 if (p->code == CLD_EXITED) {
2354 printf("status=%i", p->status);
2356 #ifdef HAVE_SYSV_COMPAT
2357 if ((c = exit_status_to_string(p->status, i->is_sysv ? EXIT_STATUS_LSB : EXIT_STATUS_SYSTEMD)))
2359 if ((c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD)))
2364 printf("signal=%s", signal_to_string(p->status));
2366 printf(")%s\n", off);
2368 if (i->main_pid == p->pid &&
2369 i->start_timestamp == p->start_timestamp &&
2370 i->exit_timestamp == p->start_timestamp)
2371 /* Let's not show this twice */
2374 if (p->pid == i->control_pid)
2378 if (i->main_pid > 0 || i->control_pid > 0) {
2381 if (i->main_pid > 0) {
2382 printf("Main PID: %u", (unsigned) i->main_pid);
2386 get_process_comm(i->main_pid, &t);
2391 } else if (i->exit_code > 0) {
2392 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
2394 if (i->exit_code == CLD_EXITED) {
2397 printf("status=%i", i->exit_status);
2399 #ifdef HAVE_SYSV_COMPAT
2400 if ((c = exit_status_to_string(i->exit_status, i->is_sysv ? EXIT_STATUS_LSB : EXIT_STATUS_SYSTEMD)))
2402 if ((c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD)))
2407 printf("signal=%s", signal_to_string(i->exit_status));
2412 if (i->main_pid > 0 && i->control_pid > 0)
2415 if (i->control_pid > 0) {
2418 printf(" Control: %u", (unsigned) i->control_pid);
2420 get_process_comm(i->control_pid, &t);
2431 printf("\t Status: \"%s\"\n", i->status_text);
2433 if (i->default_control_group) {
2436 printf("\t CGroup: %s\n", i->default_control_group);
2438 if (arg_transport != TRANSPORT_SSH) {
2448 if (i->main_pid > 0)
2449 extra[k++] = i->main_pid;
2451 if (i->control_pid > 0)
2452 extra[k++] = i->control_pid;
2454 show_cgroup_and_extra_by_spec(i->default_control_group, "\t\t ", c, false, arg_all, extra, k);
2458 if (i->id && arg_transport != TRANSPORT_SSH) {
2460 show_journal_by_unit(i->id, arg_output, 0, i->inactive_exit_timestamp_monotonic, arg_lines, arg_all, arg_follow);
2463 if (i->need_daemon_reload)
2464 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %s daemon-reload' recommended.\n",
2465 ansi_highlight_red(true),
2466 ansi_highlight_red(false),
2467 arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
2470 static int status_property(const char *name, DBusMessageIter *iter, UnitStatusInfo *i) {
2476 switch (dbus_message_iter_get_arg_type(iter)) {
2478 case DBUS_TYPE_STRING: {
2481 dbus_message_iter_get_basic(iter, &s);
2484 if (streq(name, "Id"))
2486 else if (streq(name, "LoadState"))
2488 else if (streq(name, "ActiveState"))
2489 i->active_state = s;
2490 else if (streq(name, "SubState"))
2492 else if (streq(name, "Description"))
2494 else if (streq(name, "FragmentPath"))
2496 #ifdef HAVE_SYSV_COMPAT
2497 else if (streq(name, "SysVPath")) {
2502 else if (streq(name, "DefaultControlGroup"))
2503 i->default_control_group = s;
2504 else if (streq(name, "StatusText"))
2506 else if (streq(name, "SysFSPath"))
2508 else if (streq(name, "Where"))
2510 else if (streq(name, "What"))
2512 else if (streq(name, "Following"))
2514 else if (streq(name, "UnitFileState"))
2515 i->unit_file_state = s;
2516 else if (streq(name, "Result"))
2523 case DBUS_TYPE_BOOLEAN: {
2526 dbus_message_iter_get_basic(iter, &b);
2528 if (streq(name, "Accept"))
2530 else if (streq(name, "NeedDaemonReload"))
2531 i->need_daemon_reload = b;
2532 else if (streq(name, "ConditionResult"))
2533 i->condition_result = b;
2538 case DBUS_TYPE_UINT32: {
2541 dbus_message_iter_get_basic(iter, &u);
2543 if (streq(name, "MainPID")) {
2545 i->main_pid = (pid_t) u;
2548 } else if (streq(name, "ControlPID"))
2549 i->control_pid = (pid_t) u;
2550 else if (streq(name, "ExecMainPID")) {
2552 i->main_pid = (pid_t) u;
2553 } else if (streq(name, "NAccepted"))
2555 else if (streq(name, "NConnections"))
2556 i->n_connections = u;
2561 case DBUS_TYPE_INT32: {
2564 dbus_message_iter_get_basic(iter, &j);
2566 if (streq(name, "ExecMainCode"))
2567 i->exit_code = (int) j;
2568 else if (streq(name, "ExecMainStatus"))
2569 i->exit_status = (int) j;
2574 case DBUS_TYPE_UINT64: {
2577 dbus_message_iter_get_basic(iter, &u);
2579 if (streq(name, "ExecMainStartTimestamp"))
2580 i->start_timestamp = (usec_t) u;
2581 else if (streq(name, "ExecMainExitTimestamp"))
2582 i->exit_timestamp = (usec_t) u;
2583 else if (streq(name, "ActiveEnterTimestamp"))
2584 i->active_enter_timestamp = (usec_t) u;
2585 else if (streq(name, "InactiveEnterTimestamp"))
2586 i->inactive_enter_timestamp = (usec_t) u;
2587 else if (streq(name, "InactiveExitTimestamp"))
2588 i->inactive_exit_timestamp = (usec_t) u;
2589 else if (streq(name, "InactiveExitTimestampMonotonic"))
2590 i->inactive_exit_timestamp_monotonic = (usec_t) u;
2591 else if (streq(name, "ActiveExitTimestamp"))
2592 i->active_exit_timestamp = (usec_t) u;
2593 else if (streq(name, "ConditionTimestamp"))
2594 i->condition_timestamp = (usec_t) u;
2599 case DBUS_TYPE_ARRAY: {
2601 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
2602 startswith(name, "Exec")) {
2603 DBusMessageIter sub;
2605 dbus_message_iter_recurse(iter, &sub);
2606 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2607 ExecStatusInfo *info;
2610 if (!(info = new0(ExecStatusInfo, 1)))
2613 if (!(info->name = strdup(name))) {
2618 if ((r = exec_status_info_deserialize(&sub, info)) < 0) {
2623 LIST_PREPEND(ExecStatusInfo, exec, i->exec, info);
2625 dbus_message_iter_next(&sub);
2627 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
2628 streq(name, "Documentation")) {
2630 DBusMessageIter sub;
2632 dbus_message_iter_recurse(iter, &sub);
2633 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING) {
2637 dbus_message_iter_get_basic(&sub, &s);
2639 l = strv_append(i->documentation, s);
2643 strv_free(i->documentation);
2644 i->documentation = l;
2646 dbus_message_iter_next(&sub);
2653 case DBUS_TYPE_STRUCT: {
2655 if (streq(name, "LoadError")) {
2656 DBusMessageIter sub;
2657 const char *n, *message;
2660 dbus_message_iter_recurse(iter, &sub);
2662 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &n, true);
2666 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &message, false);
2670 if (!isempty(message))
2671 i->load_error = message;
2681 static int print_property(const char *name, DBusMessageIter *iter) {
2685 /* This is a low-level property printer, see
2686 * print_status_info() for the nicer output */
2688 if (arg_property && !strv_find(arg_property, name))
2691 switch (dbus_message_iter_get_arg_type(iter)) {
2693 case DBUS_TYPE_STRUCT: {
2694 DBusMessageIter sub;
2695 dbus_message_iter_recurse(iter, &sub);
2697 if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32 && streq(name, "Job")) {
2700 dbus_message_iter_get_basic(&sub, &u);
2703 printf("%s=%u\n", name, (unsigned) u);
2705 printf("%s=\n", name);
2708 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "Unit")) {
2711 dbus_message_iter_get_basic(&sub, &s);
2713 if (arg_all || s[0])
2714 printf("%s=%s\n", name, s);
2717 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "LoadError")) {
2718 const char *a = NULL, *b = NULL;
2720 if (bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &a, true) >= 0)
2721 bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &b, false);
2723 if (arg_all || !isempty(a) || !isempty(b))
2724 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
2732 case DBUS_TYPE_ARRAY:
2734 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "EnvironmentFiles")) {
2735 DBusMessageIter sub, sub2;
2737 dbus_message_iter_recurse(iter, &sub);
2738 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2742 dbus_message_iter_recurse(&sub, &sub2);
2744 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
2745 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) >= 0)
2746 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
2748 dbus_message_iter_next(&sub);
2753 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Paths")) {
2754 DBusMessageIter sub, sub2;
2756 dbus_message_iter_recurse(iter, &sub);
2757 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2758 const char *type, *path;
2760 dbus_message_iter_recurse(&sub, &sub2);
2762 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
2763 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
2764 printf("%s=%s\n", type, path);
2766 dbus_message_iter_next(&sub);
2771 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Timers")) {
2772 DBusMessageIter sub, sub2;
2774 dbus_message_iter_recurse(iter, &sub);
2775 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2777 uint64_t value, next_elapse;
2779 dbus_message_iter_recurse(&sub, &sub2);
2781 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &base, true) >= 0 &&
2782 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &value, true) >= 0 &&
2783 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &next_elapse, false) >= 0) {
2784 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
2786 printf("%s={ value=%s ; next_elapse=%s }\n",
2788 format_timespan(timespan1, sizeof(timespan1), value),
2789 format_timespan(timespan2, sizeof(timespan2), next_elapse));
2792 dbus_message_iter_next(&sub);
2797 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "ControlGroupAttributes")) {
2798 DBusMessageIter sub, sub2;
2800 dbus_message_iter_recurse(iter, &sub);
2801 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2802 const char *controller, *attr, *value;
2804 dbus_message_iter_recurse(&sub, &sub2);
2806 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &controller, true) >= 0 &&
2807 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &attr, true) >= 0 &&
2808 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &value, false) >= 0) {
2810 printf("ControlGroupAttribute={ controller=%s ; attribute=%s ; value=\"%s\" }\n",
2816 dbus_message_iter_next(&sub);
2821 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && startswith(name, "Exec")) {
2822 DBusMessageIter sub;
2824 dbus_message_iter_recurse(iter, &sub);
2825 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2826 ExecStatusInfo info;
2829 if (exec_status_info_deserialize(&sub, &info) >= 0) {
2830 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
2833 t = strv_join(info.argv, " ");
2835 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
2839 yes_no(info.ignore),
2840 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
2841 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
2842 (unsigned) info. pid,
2843 sigchld_code_to_string(info.code),
2845 info.code == CLD_EXITED ? "" : "/",
2846 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
2852 strv_free(info.argv);
2854 dbus_message_iter_next(&sub);
2863 if (generic_print_property(name, iter, arg_all) > 0)
2867 printf("%s=[unprintable]\n", name);
2872 static int show_one(const char *verb, DBusConnection *bus, const char *path, bool show_properties, bool *new_line) {
2873 DBusMessage *m = NULL, *reply = NULL;
2874 const char *interface = "";
2877 DBusMessageIter iter, sub, sub2, sub3;
2878 UnitStatusInfo info;
2886 dbus_error_init(&error);
2888 if (!(m = dbus_message_new_method_call(
2889 "org.freedesktop.systemd1",
2891 "org.freedesktop.DBus.Properties",
2893 log_error("Could not allocate message.");
2898 if (!dbus_message_append_args(m,
2899 DBUS_TYPE_STRING, &interface,
2900 DBUS_TYPE_INVALID)) {
2901 log_error("Could not append arguments to message.");
2906 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
2907 log_error("Failed to issue method call: %s", bus_error_message(&error));
2912 if (!dbus_message_iter_init(reply, &iter) ||
2913 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
2914 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
2915 log_error("Failed to parse reply.");
2920 dbus_message_iter_recurse(&iter, &sub);
2927 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
2930 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_DICT_ENTRY) {
2931 log_error("Failed to parse reply.");
2936 dbus_message_iter_recurse(&sub, &sub2);
2938 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0) {
2939 log_error("Failed to parse reply.");
2944 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
2945 log_error("Failed to parse reply.");
2950 dbus_message_iter_recurse(&sub2, &sub3);
2952 if (show_properties)
2953 r = print_property(name, &sub3);
2955 r = status_property(name, &sub3, &info);
2958 log_error("Failed to parse reply.");
2963 dbus_message_iter_next(&sub);
2968 if (!show_properties)
2969 print_status_info(&info);
2971 strv_free(info.documentation);
2973 if (!streq_ptr(info.active_state, "active") &&
2974 !streq_ptr(info.active_state, "reloading") &&
2975 streq(verb, "status"))
2976 /* According to LSB: "program not running" */
2979 while ((p = info.exec)) {
2980 LIST_REMOVE(ExecStatusInfo, exec, info.exec, p);
2981 exec_status_info_free(p);
2986 dbus_message_unref(m);
2989 dbus_message_unref(reply);
2991 dbus_error_free(&error);
2996 static int show_one_by_pid(const char *verb, DBusConnection *bus, uint32_t pid, bool *new_line) {
2997 DBusMessage *m = NULL, *reply = NULL;
2998 const char *path = NULL;
3002 dbus_error_init(&error);
3004 m = dbus_message_new_method_call(
3005 "org.freedesktop.systemd1",
3006 "/org/freedesktop/systemd1",
3007 "org.freedesktop.systemd1.Manager",
3010 log_error("Could not allocate message.");
3015 if (!dbus_message_append_args(m,
3016 DBUS_TYPE_UINT32, &pid,
3017 DBUS_TYPE_INVALID)) {
3018 log_error("Could not append arguments to message.");
3023 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3025 log_error("Failed to issue method call: %s", bus_error_message(&error));
3030 if (!dbus_message_get_args(reply, &error,
3031 DBUS_TYPE_OBJECT_PATH, &path,
3032 DBUS_TYPE_INVALID)) {
3033 log_error("Failed to parse reply: %s", bus_error_message(&error));
3038 r = show_one(verb, bus, path, false, new_line);
3042 dbus_message_unref(m);
3045 dbus_message_unref(reply);
3047 dbus_error_free(&error);
3052 static int show(DBusConnection *bus, char **args) {
3054 bool show_properties, new_line = false;
3060 show_properties = !streq(args[0], "status");
3062 if (show_properties)
3063 pager_open_if_enabled();
3065 if (show_properties && strv_length(args) <= 1) {
3066 /* If not argument is specified inspect the manager
3069 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line);
3072 STRV_FOREACH(name, args+1) {
3075 if (safe_atou32(*name, &id) < 0) {
3077 /* Interpret as unit name */
3080 e = bus_path_escape(*name);
3083 p = strappend("/org/freedesktop/systemd1/unit/", e);
3088 r = show_one(args[0], bus, p, show_properties, &new_line);
3094 } else if (show_properties) {
3096 /* Interpret as job id */
3099 if (asprintf(&p, "/org/freedesktop/systemd1/job/%u", id) < 0)
3102 r = show_one(args[0], bus, p, show_properties, &new_line);
3110 /* Interpret as PID */
3112 r = show_one_by_pid(args[0], bus, id, &new_line);
3121 static int dump(DBusConnection *bus, char **args) {
3122 DBusMessage *m = NULL, *reply = NULL;
3127 dbus_error_init(&error);
3129 pager_open_if_enabled();
3131 if (!(m = dbus_message_new_method_call(
3132 "org.freedesktop.systemd1",
3133 "/org/freedesktop/systemd1",
3134 "org.freedesktop.systemd1.Manager",
3136 log_error("Could not allocate message.");
3140 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3141 log_error("Failed to issue method call: %s", bus_error_message(&error));
3146 if (!dbus_message_get_args(reply, &error,
3147 DBUS_TYPE_STRING, &text,
3148 DBUS_TYPE_INVALID)) {
3149 log_error("Failed to parse reply: %s", bus_error_message(&error));
3154 fputs(text, stdout);
3160 dbus_message_unref(m);
3163 dbus_message_unref(reply);
3165 dbus_error_free(&error);
3170 static int snapshot(DBusConnection *bus, char **args) {
3171 DBusMessage *m = NULL, *reply = NULL;
3174 const char *name = "", *path, *id;
3175 dbus_bool_t cleanup = FALSE;
3176 DBusMessageIter iter, sub;
3178 *interface = "org.freedesktop.systemd1.Unit",
3181 dbus_error_init(&error);
3183 if (!(m = dbus_message_new_method_call(
3184 "org.freedesktop.systemd1",
3185 "/org/freedesktop/systemd1",
3186 "org.freedesktop.systemd1.Manager",
3187 "CreateSnapshot"))) {
3188 log_error("Could not allocate message.");
3192 if (strv_length(args) > 1)
3195 if (!dbus_message_append_args(m,
3196 DBUS_TYPE_STRING, &name,
3197 DBUS_TYPE_BOOLEAN, &cleanup,
3198 DBUS_TYPE_INVALID)) {
3199 log_error("Could not append arguments to message.");
3204 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3205 log_error("Failed to issue method call: %s", bus_error_message(&error));
3210 if (!dbus_message_get_args(reply, &error,
3211 DBUS_TYPE_OBJECT_PATH, &path,
3212 DBUS_TYPE_INVALID)) {
3213 log_error("Failed to parse reply: %s", bus_error_message(&error));
3218 dbus_message_unref(m);
3219 if (!(m = dbus_message_new_method_call(
3220 "org.freedesktop.systemd1",
3222 "org.freedesktop.DBus.Properties",
3224 log_error("Could not allocate message.");
3228 if (!dbus_message_append_args(m,
3229 DBUS_TYPE_STRING, &interface,
3230 DBUS_TYPE_STRING, &property,
3231 DBUS_TYPE_INVALID)) {
3232 log_error("Could not append arguments to message.");
3237 dbus_message_unref(reply);
3238 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3239 log_error("Failed to issue method call: %s", bus_error_message(&error));
3244 if (!dbus_message_iter_init(reply, &iter) ||
3245 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3246 log_error("Failed to parse reply.");
3251 dbus_message_iter_recurse(&iter, &sub);
3253 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
3254 log_error("Failed to parse reply.");
3259 dbus_message_iter_get_basic(&sub, &id);
3267 dbus_message_unref(m);
3270 dbus_message_unref(reply);
3272 dbus_error_free(&error);
3277 static int delete_snapshot(DBusConnection *bus, char **args) {
3278 DBusMessage *m = NULL, *reply = NULL;
3286 dbus_error_init(&error);
3288 STRV_FOREACH(name, args+1) {
3289 const char *path = NULL;
3291 if (!(m = dbus_message_new_method_call(
3292 "org.freedesktop.systemd1",
3293 "/org/freedesktop/systemd1",
3294 "org.freedesktop.systemd1.Manager",
3296 log_error("Could not allocate message.");
3301 if (!dbus_message_append_args(m,
3302 DBUS_TYPE_STRING, name,
3303 DBUS_TYPE_INVALID)) {
3304 log_error("Could not append arguments to message.");
3309 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3310 log_error("Failed to issue method call: %s", bus_error_message(&error));
3315 if (!dbus_message_get_args(reply, &error,
3316 DBUS_TYPE_OBJECT_PATH, &path,
3317 DBUS_TYPE_INVALID)) {
3318 log_error("Failed to parse reply: %s", bus_error_message(&error));
3323 dbus_message_unref(m);
3324 if (!(m = dbus_message_new_method_call(
3325 "org.freedesktop.systemd1",
3327 "org.freedesktop.systemd1.Snapshot",
3329 log_error("Could not allocate message.");
3334 dbus_message_unref(reply);
3335 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3336 log_error("Failed to issue method call: %s", bus_error_message(&error));
3341 dbus_message_unref(m);
3342 dbus_message_unref(reply);
3350 dbus_message_unref(m);
3353 dbus_message_unref(reply);
3355 dbus_error_free(&error);
3360 static int daemon_reload(DBusConnection *bus, char **args) {
3361 DBusMessage *m = NULL, *reply = NULL;
3366 dbus_error_init(&error);
3368 if (arg_action == ACTION_RELOAD)
3370 else if (arg_action == ACTION_REEXEC)
3371 method = "Reexecute";
3373 assert(arg_action == ACTION_SYSTEMCTL);
3376 streq(args[0], "clear-jobs") ||
3377 streq(args[0], "cancel") ? "ClearJobs" :
3378 streq(args[0], "daemon-reexec") ? "Reexecute" :
3379 streq(args[0], "reset-failed") ? "ResetFailed" :
3380 streq(args[0], "halt") ? "Halt" :
3381 streq(args[0], "poweroff") ? "PowerOff" :
3382 streq(args[0], "reboot") ? "Reboot" :
3383 streq(args[0], "kexec") ? "KExec" :
3384 streq(args[0], "exit") ? "Exit" :
3385 /* "daemon-reload" */ "Reload";
3388 if (!(m = dbus_message_new_method_call(
3389 "org.freedesktop.systemd1",
3390 "/org/freedesktop/systemd1",
3391 "org.freedesktop.systemd1.Manager",
3393 log_error("Could not allocate message.");
3397 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3399 if (arg_action != ACTION_SYSTEMCTL && error_is_no_service(&error)) {
3400 /* There's always a fallback possible for
3401 * legacy actions. */
3406 if (streq(method, "Reexecute") && dbus_error_has_name(&error, DBUS_ERROR_NO_REPLY)) {
3407 /* On reexecution, we expect a disconnect, not
3413 log_error("Failed to issue method call: %s", bus_error_message(&error));
3422 dbus_message_unref(m);
3425 dbus_message_unref(reply);
3427 dbus_error_free(&error);
3432 static int reset_failed(DBusConnection *bus, char **args) {
3433 DBusMessage *m = NULL;
3439 dbus_error_init(&error);
3441 if (strv_length(args) <= 1)
3442 return daemon_reload(bus, args);
3444 STRV_FOREACH(name, args+1) {
3447 if (!(m = dbus_message_new_method_call(
3448 "org.freedesktop.systemd1",
3449 "/org/freedesktop/systemd1",
3450 "org.freedesktop.systemd1.Manager",
3451 "ResetFailedUnit"))) {
3452 log_error("Could not allocate message.");
3457 if (!dbus_message_append_args(m,
3458 DBUS_TYPE_STRING, name,
3459 DBUS_TYPE_INVALID)) {
3460 log_error("Could not append arguments to message.");
3465 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3466 log_error("Failed to issue method call: %s", bus_error_message(&error));
3471 dbus_message_unref(m);
3472 dbus_message_unref(reply);
3480 dbus_message_unref(m);
3482 dbus_error_free(&error);
3487 static int show_enviroment(DBusConnection *bus, char **args) {
3488 DBusMessage *m = NULL, *reply = NULL;
3490 DBusMessageIter iter, sub, sub2;
3493 *interface = "org.freedesktop.systemd1.Manager",
3494 *property = "Environment";
3496 dbus_error_init(&error);
3498 pager_open_if_enabled();
3500 if (!(m = dbus_message_new_method_call(
3501 "org.freedesktop.systemd1",
3502 "/org/freedesktop/systemd1",
3503 "org.freedesktop.DBus.Properties",
3505 log_error("Could not allocate message.");
3509 if (!dbus_message_append_args(m,
3510 DBUS_TYPE_STRING, &interface,
3511 DBUS_TYPE_STRING, &property,
3512 DBUS_TYPE_INVALID)) {
3513 log_error("Could not append arguments to message.");
3518 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3519 log_error("Failed to issue method call: %s", bus_error_message(&error));
3524 if (!dbus_message_iter_init(reply, &iter) ||
3525 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3526 log_error("Failed to parse reply.");
3531 dbus_message_iter_recurse(&iter, &sub);
3533 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_ARRAY ||
3534 dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_STRING) {
3535 log_error("Failed to parse reply.");
3540 dbus_message_iter_recurse(&sub, &sub2);
3542 while (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_INVALID) {
3545 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
3546 log_error("Failed to parse reply.");
3551 dbus_message_iter_get_basic(&sub2, &text);
3552 printf("%s\n", text);
3554 dbus_message_iter_next(&sub2);
3561 dbus_message_unref(m);
3564 dbus_message_unref(reply);
3566 dbus_error_free(&error);
3571 static int switch_root(DBusConnection *bus, char **args) {
3572 DBusMessage *m = NULL, *reply = NULL;
3574 const char *root, *init;
3578 dbus_error_init(&error);
3580 l = strv_length(args);
3581 if (l < 2 || l > 3) {
3582 log_error("Wrong number of arguments.");
3587 init = l >= 3 ? args[2] : "";
3589 m = dbus_message_new_method_call(
3590 "org.freedesktop.systemd1",
3591 "/org/freedesktop/systemd1",
3592 "org.freedesktop.systemd1.Manager",
3595 log_error("Could not allocate message.");
3599 if (!dbus_message_append_args(
3601 DBUS_TYPE_STRING, &root,
3602 DBUS_TYPE_STRING, &init,
3603 DBUS_TYPE_INVALID)) {
3604 log_error("Could not append arguments to message.");
3609 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3611 log_error("Failed to issue method call: %s", bus_error_message(&error));
3620 dbus_message_unref(m);
3623 dbus_message_unref(reply);
3625 dbus_error_free(&error);
3630 static int set_environment(DBusConnection *bus, char **args) {
3631 DBusMessage *m = NULL, *reply = NULL;
3635 DBusMessageIter iter, sub;
3638 dbus_error_init(&error);
3640 method = streq(args[0], "set-environment")
3642 : "UnsetEnvironment";
3644 if (!(m = dbus_message_new_method_call(
3645 "org.freedesktop.systemd1",
3646 "/org/freedesktop/systemd1",
3647 "org.freedesktop.systemd1.Manager",
3650 log_error("Could not allocate message.");
3654 dbus_message_iter_init_append(m, &iter);
3656 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub)) {
3657 log_error("Could not append arguments to message.");
3662 STRV_FOREACH(name, args+1)
3663 if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, name)) {
3664 log_error("Could not append arguments to message.");
3669 if (!dbus_message_iter_close_container(&iter, &sub)) {
3670 log_error("Could not append arguments to message.");
3675 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3676 log_error("Failed to issue method call: %s", bus_error_message(&error));
3685 dbus_message_unref(m);
3688 dbus_message_unref(reply);
3690 dbus_error_free(&error);
3695 static int enable_sysv_units(char **args) {
3698 #if defined (HAVE_SYSV_COMPAT) && (defined(TARGET_FEDORA) || defined(TARGET_MANDRIVA) || defined(TARGET_SUSE) || defined(TARGET_MEEGO) || defined(TARGET_ALTLINUX) || defined(TARGET_MAGEIA))
3699 const char *verb = args[0];
3700 unsigned f = 1, t = 1;
3703 if (arg_scope != UNIT_FILE_SYSTEM)
3706 if (!streq(verb, "enable") &&
3707 !streq(verb, "disable") &&
3708 !streq(verb, "is-enabled"))
3711 /* Processes all SysV units, and reshuffles the array so that
3712 * afterwards only the native units remain */
3715 r = lookup_paths_init(&paths, MANAGER_SYSTEM, false);
3721 for (f = 1; args[f]; f++) {
3724 bool found_native = false, found_sysv;
3726 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
3727 char **k, *l, *q = NULL;
3734 if (!endswith(name, ".service"))
3737 if (path_is_absolute(name))
3740 STRV_FOREACH(k, paths.unit_path) {
3743 if (!isempty(arg_root))
3744 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
3746 asprintf(&p, "%s/%s", *k, name);
3749 log_error("No memory");
3754 found_native = access(p, F_OK) >= 0;
3765 if (!isempty(arg_root))
3766 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
3768 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
3770 log_error("No memory");
3775 p[strlen(p) - sizeof(".service") + 1] = 0;
3776 found_sysv = access(p, F_OK) >= 0;
3783 /* Mark this entry, so that we don't try enabling it as native unit */
3784 args[f] = (char*) "";
3786 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
3788 if (!isempty(arg_root))
3789 argv[c++] = q = strappend("--root=", arg_root);
3791 argv[c++] = path_get_file_name(p);
3793 streq(verb, "enable") ? "on" :
3794 streq(verb, "disable") ? "off" : "--level=5";
3797 l = strv_join((char**)argv, " ");
3799 log_error("No memory.");
3806 log_info("Executing %s", l);
3811 log_error("Failed to fork: %m");
3816 } else if (pid == 0) {
3819 execv(argv[0], (char**) argv);
3820 _exit(EXIT_FAILURE);
3826 j = wait_for_terminate(pid, &status);
3828 log_error("Failed to wait for child: %s", strerror(-r));
3833 if (status.si_code == CLD_EXITED) {
3834 if (streq(verb, "is-enabled")) {
3835 if (status.si_status == 0) {
3844 } else if (status.si_status != 0) {
3855 lookup_paths_free(&paths);
3857 /* Drop all SysV units */
3858 for (f = 1, t = 1; args[f]; f++) {
3860 if (isempty(args[f]))
3863 args[t++] = args[f];
3872 static int enable_unit(DBusConnection *bus, char **args) {
3873 const char *verb = args[0];
3874 UnitFileChange *changes = NULL;
3875 unsigned n_changes = 0, i;
3876 int carries_install_info = -1;
3877 DBusMessage *m = NULL, *reply = NULL;
3881 r = enable_sysv_units(args);
3888 dbus_error_init(&error);
3890 if (!bus || avoid_bus()) {
3891 if (streq(verb, "enable")) {
3892 r = unit_file_enable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3893 carries_install_info = r;
3894 } else if (streq(verb, "disable"))
3895 r = unit_file_disable(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3896 else if (streq(verb, "reenable")) {
3897 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3898 carries_install_info = r;
3899 } else if (streq(verb, "link"))
3900 r = unit_file_link(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3901 else if (streq(verb, "preset")) {
3902 r = unit_file_preset(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3903 carries_install_info = r;
3904 } else if (streq(verb, "mask"))
3905 r = unit_file_mask(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3906 else if (streq(verb, "unmask"))
3907 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3909 assert_not_reached("Unknown verb");
3912 log_error("Operation failed: %s", strerror(-r));
3917 for (i = 0; i < n_changes; i++) {
3918 if (changes[i].type == UNIT_FILE_SYMLINK)
3919 log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
3921 log_info("rm '%s'", changes[i].path);
3927 bool send_force = true, expect_carries_install_info = false;
3929 DBusMessageIter iter, sub, sub2;
3931 if (streq(verb, "enable")) {
3932 method = "EnableUnitFiles";
3933 expect_carries_install_info = true;
3934 } else if (streq(verb, "disable")) {
3935 method = "DisableUnitFiles";
3937 } else if (streq(verb, "reenable")) {
3938 method = "ReenableUnitFiles";
3939 expect_carries_install_info = true;
3940 } else if (streq(verb, "link"))
3941 method = "LinkUnitFiles";
3942 else if (streq(verb, "preset")) {
3943 method = "PresetUnitFiles";
3944 expect_carries_install_info = true;
3945 } else if (streq(verb, "mask"))
3946 method = "MaskUnitFiles";
3947 else if (streq(verb, "unmask")) {
3948 method = "UnmaskUnitFiles";
3951 assert_not_reached("Unknown verb");
3953 m = dbus_message_new_method_call(
3954 "org.freedesktop.systemd1",
3955 "/org/freedesktop/systemd1",
3956 "org.freedesktop.systemd1.Manager",
3959 log_error("Out of memory");
3964 dbus_message_iter_init_append(m, &iter);
3966 r = bus_append_strv_iter(&iter, args+1);
3968 log_error("Failed to append unit files.");
3973 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &a)) {
3974 log_error("Failed to append runtime boolean.");
3982 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b)) {
3983 log_error("Failed to append force boolean.");
3989 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3991 log_error("Failed to issue method call: %s", bus_error_message(&error));
3996 if (!dbus_message_iter_init(reply, &iter)) {
3997 log_error("Failed to initialize iterator.");
4001 if (expect_carries_install_info) {
4002 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &b, true);
4004 log_error("Failed to parse reply.");
4008 carries_install_info = b;
4011 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
4012 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
4013 log_error("Failed to parse reply.");
4018 dbus_message_iter_recurse(&iter, &sub);
4019 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
4020 const char *type, *path, *source;
4022 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
4023 log_error("Failed to parse reply.");
4028 dbus_message_iter_recurse(&sub, &sub2);
4030 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
4031 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
4032 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &source, false) < 0) {
4033 log_error("Failed to parse reply.");
4039 if (streq(type, "symlink"))
4040 log_info("ln -s '%s' '%s'", source, path);
4042 log_info("rm '%s'", path);
4045 dbus_message_iter_next(&sub);
4048 /* Try to reload if enabeld */
4050 r = daemon_reload(bus, args);
4053 if (carries_install_info == 0)
4054 log_warning("Warning: unit files do not carry install information. No operation executed.");
4058 dbus_message_unref(m);
4061 dbus_message_unref(reply);
4063 unit_file_changes_free(changes, n_changes);
4065 dbus_error_free(&error);
4069 static int unit_is_enabled(DBusConnection *bus, char **args) {
4072 DBusMessage *m = NULL, *reply = NULL;
4076 dbus_error_init(&error);
4078 r = enable_sysv_units(args);
4084 if (!bus || avoid_bus()) {
4086 STRV_FOREACH(name, args+1) {
4087 UnitFileState state;
4089 state = unit_file_get_state(arg_scope, arg_root, *name);
4095 if (state == UNIT_FILE_ENABLED ||
4096 state == UNIT_FILE_ENABLED_RUNTIME ||
4097 state == UNIT_FILE_STATIC)
4101 puts(unit_file_state_to_string(state));
4105 STRV_FOREACH(name, args+1) {
4108 m = dbus_message_new_method_call(
4109 "org.freedesktop.systemd1",
4110 "/org/freedesktop/systemd1",
4111 "org.freedesktop.systemd1.Manager",
4112 "GetUnitFileState");
4114 log_error("Out of memory");
4119 if (!dbus_message_append_args(m,
4120 DBUS_TYPE_STRING, name,
4121 DBUS_TYPE_INVALID)) {
4122 log_error("Could not append arguments to message.");
4127 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
4129 log_error("Failed to issue method call: %s", bus_error_message(&error));
4134 if (!dbus_message_get_args(reply, &error,
4135 DBUS_TYPE_STRING, &s,
4136 DBUS_TYPE_INVALID)) {
4137 log_error("Failed to parse reply: %s", bus_error_message(&error));
4142 dbus_message_unref(m);
4143 dbus_message_unref(reply);
4146 if (streq(s, "enabled") ||
4147 streq(s, "enabled-runtime") ||
4156 r = enabled ? 0 : 1;
4160 dbus_message_unref(m);
4163 dbus_message_unref(reply);
4165 dbus_error_free(&error);
4169 static int systemctl_help(void) {
4171 pager_open_if_enabled();
4173 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
4174 "Query or send control commands to the systemd manager.\n\n"
4175 " -h --help Show this help\n"
4176 " --version Show package version\n"
4177 " -t --type=TYPE List only units of a particular type\n"
4178 " -p --property=NAME Show only properties by this name\n"
4179 " -a --all Show all units/properties, including dead/empty ones\n"
4180 " --failed Show only failed units\n"
4181 " --full Don't ellipsize unit names on output\n"
4182 " --fail When queueing a new job, fail if conflicting jobs are\n"
4184 " --ignore-dependencies\n"
4185 " When queueing a new job, ignore all its dependencies\n"
4186 " --kill-who=WHO Who to send signal to\n"
4187 " -s --signal=SIGNAL Which signal to send\n"
4188 " -H --host=[USER@]HOST\n"
4189 " Show information for remote host\n"
4190 " -P --privileged Acquire privileges before execution\n"
4191 " -q --quiet Suppress output\n"
4192 " --no-block Do not wait until operation finished\n"
4193 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4194 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
4196 " --no-legend Do not print a legend (column headers and hints)\n"
4197 " --no-pager Do not pipe output into a pager\n"
4198 " --no-ask-password\n"
4199 " Do not ask for system passwords\n"
4200 " --order When generating graph for dot, show only order\n"
4201 " --require When generating graph for dot, show only requirement\n"
4202 " --system Connect to system manager\n"
4203 " --user Connect to user service manager\n"
4204 " --global Enable/disable unit files globally\n"
4205 " -f --force When enabling unit files, override existing symlinks\n"
4206 " When shutting down, execute action immediately\n"
4207 " --root=PATH Enable unit files in the specified root directory\n"
4208 " --runtime Enable unit files only temporarily until next reboot\n"
4209 " -n --lines=INTEGER Journal entries to show\n"
4210 " --follow Follow journal\n"
4211 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
4212 " verbose, export, json, cat)\n\n"
4214 " list-units List loaded units\n"
4215 " start [NAME...] Start (activate) one or more units\n"
4216 " stop [NAME...] Stop (deactivate) one or more units\n"
4217 " reload [NAME...] Reload one or more units\n"
4218 " restart [NAME...] Start or restart one or more units\n"
4219 " try-restart [NAME...] Restart one or more units if active\n"
4220 " reload-or-restart [NAME...] Reload one or more units is possible,\n"
4221 " otherwise start or restart\n"
4222 " reload-or-try-restart [NAME...] Reload one or more units is possible,\n"
4223 " otherwise restart if active\n"
4224 " isolate [NAME] Start one unit and stop all others\n"
4225 " kill [NAME...] Send signal to processes of a unit\n"
4226 " is-active [NAME...] Check whether units are active\n"
4227 " status [NAME...|PID...] Show runtime status of one or more units\n"
4228 " show [NAME...|JOB...] Show properties of one or more\n"
4229 " units/jobs or the manager\n"
4230 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
4232 " load [NAME...] Load one or more units\n\n"
4233 "Unit File Commands:\n"
4234 " list-unit-files List installed unit files\n"
4235 " enable [NAME...] Enable one or more unit files\n"
4236 " disable [NAME...] Disable one or more unit files\n"
4237 " reenable [NAME...] Reenable one or more unit files\n"
4238 " preset [NAME...] Enable/disable one or more unit files\n"
4239 " based on preset configuration\n"
4240 " mask [NAME...] Mask one or more units\n"
4241 " unmask [NAME...] Unmask one or more units\n"
4242 " link [PATH...] Link one or more units files into\n"
4243 " the search path\n"
4244 " is-enabled [NAME...] Check whether unit files are enabled\n\n"
4246 " list-jobs List jobs\n"
4247 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
4248 "Status Commands:\n"
4249 " dump Dump server status\n"
4250 " dot Dump dependency graph for dot(1)\n\n"
4251 "Snapshot Commands:\n"
4252 " snapshot [NAME] Create a snapshot\n"
4253 " delete [NAME...] Remove one or more snapshots\n\n"
4254 "Environment Commands:\n"
4255 " show-environment Dump environment\n"
4256 " set-environment [NAME=VALUE...] Set one or more environment variables\n"
4257 " unset-environment [NAME...] Unset one or more environment variables\n\n"
4258 "Manager Lifecycle Commands:\n"
4259 " daemon-reload Reload systemd manager configuration\n"
4260 " daemon-reexec Reexecute systemd manager\n\n"
4261 "System Commands:\n"
4262 " default Enter system default mode\n"
4263 " rescue Enter system rescue mode\n"
4264 " emergency Enter system emergency mode\n"
4265 " halt Shut down and halt the system\n"
4266 " poweroff Shut down and power-off the system\n"
4267 " reboot Shut down and reboot the system\n"
4268 " kexec Shut down and reboot the system with kexec\n"
4269 " exit Request user instance exit\n"
4270 " switch-root [ROOT] [INIT] Change to a different root file system\n"
4271 " suspend Suspend the system\n"
4272 " hibernate Hibernate the system\n",
4273 program_invocation_short_name);
4278 static int halt_help(void) {
4280 printf("%s [OPTIONS...]\n\n"
4281 "%s the system.\n\n"
4282 " --help Show this help\n"
4283 " --halt Halt the machine\n"
4284 " -p --poweroff Switch off the machine\n"
4285 " --reboot Reboot the machine\n"
4286 " -f --force Force immediate halt/power-off/reboot\n"
4287 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
4288 " -d --no-wtmp Don't write wtmp record\n"
4289 " -n --no-sync Don't sync before halt/power-off/reboot\n"
4290 " --no-wall Don't send wall message before halt/power-off/reboot\n",
4291 program_invocation_short_name,
4292 arg_action == ACTION_REBOOT ? "Reboot" :
4293 arg_action == ACTION_POWEROFF ? "Power off" :
4299 static int shutdown_help(void) {
4301 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
4302 "Shut down the system.\n\n"
4303 " --help Show this help\n"
4304 " -H --halt Halt the machine\n"
4305 " -P --poweroff Power-off the machine\n"
4306 " -r --reboot Reboot the machine\n"
4307 " -h Equivalent to --poweroff, overridden by --halt\n"
4308 " -k Don't halt/power-off/reboot, just send warnings\n"
4309 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4310 " -c Cancel a pending shutdown\n",
4311 program_invocation_short_name);
4316 static int telinit_help(void) {
4318 printf("%s [OPTIONS...] {COMMAND}\n\n"
4319 "Send control commands to the init daemon.\n\n"
4320 " --help Show this help\n"
4321 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
4323 " 0 Power-off the machine\n"
4324 " 6 Reboot the machine\n"
4325 " 2, 3, 4, 5 Start runlevelX.target unit\n"
4326 " 1, s, S Enter rescue mode\n"
4327 " q, Q Reload init daemon configuration\n"
4328 " u, U Reexecute init daemon\n",
4329 program_invocation_short_name);
4334 static int runlevel_help(void) {
4336 printf("%s [OPTIONS...]\n\n"
4337 "Prints the previous and current runlevel of the init system.\n\n"
4338 " --help Show this help\n",
4339 program_invocation_short_name);
4344 static int systemctl_parse_argv(int argc, char *argv[]) {
4348 ARG_IGNORE_DEPENDENCIES,
4364 ARG_NO_ASK_PASSWORD,
4371 static const struct option options[] = {
4372 { "help", no_argument, NULL, 'h' },
4373 { "version", no_argument, NULL, ARG_VERSION },
4374 { "type", required_argument, NULL, 't' },
4375 { "property", required_argument, NULL, 'p' },
4376 { "all", no_argument, NULL, 'a' },
4377 { "failed", no_argument, NULL, ARG_FAILED },
4378 { "full", no_argument, NULL, ARG_FULL },
4379 { "fail", no_argument, NULL, ARG_FAIL },
4380 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
4381 { "user", no_argument, NULL, ARG_USER },
4382 { "system", no_argument, NULL, ARG_SYSTEM },
4383 { "global", no_argument, NULL, ARG_GLOBAL },
4384 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
4385 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
4386 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
4387 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4388 { "quiet", no_argument, NULL, 'q' },
4389 { "order", no_argument, NULL, ARG_ORDER },
4390 { "require", no_argument, NULL, ARG_REQUIRE },
4391 { "root", required_argument, NULL, ARG_ROOT },
4392 { "force", no_argument, NULL, ARG_FORCE },
4393 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
4394 { "kill-mode", required_argument, NULL, ARG_KILL_MODE }, /* undocumented on purpose */
4395 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
4396 { "signal", required_argument, NULL, 's' },
4397 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
4398 { "host", required_argument, NULL, 'H' },
4399 { "privileged",no_argument, NULL, 'P' },
4400 { "runtime", no_argument, NULL, ARG_RUNTIME },
4401 { "lines", required_argument, NULL, 'n' },
4402 { "follow", no_argument, NULL, ARG_FOLLOW },
4403 { "output", required_argument, NULL, 'o' },
4404 { NULL, 0, NULL, 0 }
4412 while ((c = getopt_long(argc, argv, "ht:p:aqfs:H:Pn:o:", options, NULL)) >= 0) {
4421 puts(PACKAGE_STRING);
4423 puts(SYSTEMD_FEATURES);
4433 if (!(l = strv_append(arg_property, optarg)))
4436 strv_free(arg_property);
4439 /* If the user asked for a particular
4440 * property, show it to him, even if it is
4451 arg_job_mode = "fail";
4454 case ARG_IGNORE_DEPENDENCIES:
4455 arg_job_mode = "ignore-dependencies";
4459 arg_scope = UNIT_FILE_USER;
4463 arg_scope = UNIT_FILE_SYSTEM;
4467 arg_scope = UNIT_FILE_GLOBAL;
4471 arg_no_block = true;
4475 arg_no_legend = true;
4479 arg_no_pager = true;
4487 arg_dot = DOT_ORDER;
4491 arg_dot = DOT_REQUIRE;
4519 /* -f is short for both --follow and --force! */
4525 arg_no_reload = true;
4529 arg_kill_who = optarg;
4533 arg_kill_mode = optarg;
4537 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
4538 log_error("Failed to parse signal string %s.", optarg);
4543 case ARG_NO_ASK_PASSWORD:
4544 arg_ask_password = false;
4548 arg_transport = TRANSPORT_POLKIT;
4552 arg_transport = TRANSPORT_SSH;
4561 if (safe_atou(optarg, &arg_lines) < 0) {
4562 log_error("Failed to parse lines '%s'", optarg);
4568 arg_output = output_mode_from_string(optarg);
4569 if (arg_output < 0) {
4570 log_error("Unknown output '%s'.", optarg);
4579 log_error("Unknown option code %c", c);
4584 if (arg_transport != TRANSPORT_NORMAL && arg_scope != UNIT_FILE_SYSTEM) {
4585 log_error("Cannot access user instance remotely.");
4592 static int halt_parse_argv(int argc, char *argv[]) {
4601 static const struct option options[] = {
4602 { "help", no_argument, NULL, ARG_HELP },
4603 { "halt", no_argument, NULL, ARG_HALT },
4604 { "poweroff", no_argument, NULL, 'p' },
4605 { "reboot", no_argument, NULL, ARG_REBOOT },
4606 { "force", no_argument, NULL, 'f' },
4607 { "wtmp-only", no_argument, NULL, 'w' },
4608 { "no-wtmp", no_argument, NULL, 'd' },
4609 { "no-sync", no_argument, NULL, 'n' },
4610 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4611 { NULL, 0, NULL, 0 }
4619 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
4620 if (runlevel == '0' || runlevel == '6')
4623 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
4631 arg_action = ACTION_HALT;
4635 if (arg_action != ACTION_REBOOT)
4636 arg_action = ACTION_POWEROFF;
4640 arg_action = ACTION_REBOOT;
4665 /* Compatibility nops */
4672 log_error("Unknown option code %c", c);
4677 if (optind < argc) {
4678 log_error("Too many arguments.");
4685 static int parse_time_spec(const char *t, usec_t *_u) {
4689 if (streq(t, "now"))
4691 else if (!strchr(t, ':')) {
4694 if (safe_atou64(t, &u) < 0)
4697 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
4706 hour = strtol(t, &e, 10);
4707 if (errno != 0 || *e != ':' || hour < 0 || hour > 23)
4710 minute = strtol(e+1, &e, 10);
4711 if (errno != 0 || *e != 0 || minute < 0 || minute > 59)
4714 n = now(CLOCK_REALTIME);
4715 s = (time_t) (n / USEC_PER_SEC);
4718 assert_se(localtime_r(&s, &tm));
4720 tm.tm_hour = (int) hour;
4721 tm.tm_min = (int) minute;
4724 assert_se(s = mktime(&tm));
4726 *_u = (usec_t) s * USEC_PER_SEC;
4729 *_u += USEC_PER_DAY;
4735 static int shutdown_parse_argv(int argc, char *argv[]) {
4742 static const struct option options[] = {
4743 { "help", no_argument, NULL, ARG_HELP },
4744 { "halt", no_argument, NULL, 'H' },
4745 { "poweroff", no_argument, NULL, 'P' },
4746 { "reboot", no_argument, NULL, 'r' },
4747 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
4748 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4749 { NULL, 0, NULL, 0 }
4757 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
4765 arg_action = ACTION_HALT;
4769 arg_action = ACTION_POWEROFF;
4774 arg_action = ACTION_KEXEC;
4776 arg_action = ACTION_REBOOT;
4780 arg_action = ACTION_KEXEC;
4784 if (arg_action != ACTION_HALT)
4785 arg_action = ACTION_POWEROFF;
4798 /* Compatibility nops */
4802 arg_action = ACTION_CANCEL_SHUTDOWN;
4809 log_error("Unknown option code %c", c);
4814 if (argc > optind) {
4815 r = parse_time_spec(argv[optind], &arg_when);
4817 log_error("Failed to parse time specification: %s", argv[optind]);
4821 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
4823 /* We skip the time argument */
4824 if (argc > optind + 1)
4825 arg_wall = argv + optind + 1;
4832 static int telinit_parse_argv(int argc, char *argv[]) {
4839 static const struct option options[] = {
4840 { "help", no_argument, NULL, ARG_HELP },
4841 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4842 { NULL, 0, NULL, 0 }
4845 static const struct {
4849 { '0', ACTION_POWEROFF },
4850 { '6', ACTION_REBOOT },
4851 { '1', ACTION_RESCUE },
4852 { '2', ACTION_RUNLEVEL2 },
4853 { '3', ACTION_RUNLEVEL3 },
4854 { '4', ACTION_RUNLEVEL4 },
4855 { '5', ACTION_RUNLEVEL5 },
4856 { 's', ACTION_RESCUE },
4857 { 'S', ACTION_RESCUE },
4858 { 'q', ACTION_RELOAD },
4859 { 'Q', ACTION_RELOAD },
4860 { 'u', ACTION_REEXEC },
4861 { 'U', ACTION_REEXEC }
4870 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4885 log_error("Unknown option code %c", c);
4890 if (optind >= argc) {
4895 if (optind + 1 < argc) {
4896 log_error("Too many arguments.");
4900 if (strlen(argv[optind]) != 1) {
4901 log_error("Expected single character argument.");
4905 for (i = 0; i < ELEMENTSOF(table); i++)
4906 if (table[i].from == argv[optind][0])
4909 if (i >= ELEMENTSOF(table)) {
4910 log_error("Unknown command %s.", argv[optind]);
4914 arg_action = table[i].to;
4921 static int runlevel_parse_argv(int argc, char *argv[]) {
4927 static const struct option options[] = {
4928 { "help", no_argument, NULL, ARG_HELP },
4929 { NULL, 0, NULL, 0 }
4937 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4948 log_error("Unknown option code %c", c);
4953 if (optind < argc) {
4954 log_error("Too many arguments.");
4961 static int parse_argv(int argc, char *argv[]) {
4965 if (program_invocation_short_name) {
4967 if (strstr(program_invocation_short_name, "halt")) {
4968 arg_action = ACTION_HALT;
4969 return halt_parse_argv(argc, argv);
4970 } else if (strstr(program_invocation_short_name, "poweroff")) {
4971 arg_action = ACTION_POWEROFF;
4972 return halt_parse_argv(argc, argv);
4973 } else if (strstr(program_invocation_short_name, "reboot")) {
4975 arg_action = ACTION_KEXEC;
4977 arg_action = ACTION_REBOOT;
4978 return halt_parse_argv(argc, argv);
4979 } else if (strstr(program_invocation_short_name, "shutdown")) {
4980 arg_action = ACTION_POWEROFF;
4981 return shutdown_parse_argv(argc, argv);
4982 } else if (strstr(program_invocation_short_name, "init")) {
4984 if (sd_booted() > 0) {
4985 arg_action = ACTION_INVALID;
4986 return telinit_parse_argv(argc, argv);
4988 /* Hmm, so some other init system is
4989 * running, we need to forward this
4990 * request to it. For now we simply
4991 * guess that it is Upstart. */
4993 execv("/lib/upstart/telinit", argv);
4995 log_error("Couldn't find an alternative telinit implementation to spawn.");
4999 } else if (strstr(program_invocation_short_name, "runlevel")) {
5000 arg_action = ACTION_RUNLEVEL;
5001 return runlevel_parse_argv(argc, argv);
5005 arg_action = ACTION_SYSTEMCTL;
5006 return systemctl_parse_argv(argc, argv);
5009 static int action_to_runlevel(void) {
5011 static const char table[_ACTION_MAX] = {
5012 [ACTION_HALT] = '0',
5013 [ACTION_POWEROFF] = '0',
5014 [ACTION_REBOOT] = '6',
5015 [ACTION_RUNLEVEL2] = '2',
5016 [ACTION_RUNLEVEL3] = '3',
5017 [ACTION_RUNLEVEL4] = '4',
5018 [ACTION_RUNLEVEL5] = '5',
5019 [ACTION_RESCUE] = '1'
5022 assert(arg_action < _ACTION_MAX);
5024 return table[arg_action];
5027 static int talk_upstart(void) {
5028 DBusMessage *m = NULL, *reply = NULL;
5030 int previous, rl, r;
5032 env1_buf[] = "RUNLEVEL=X",
5033 env2_buf[] = "PREVLEVEL=X";
5034 char *env1 = env1_buf, *env2 = env2_buf;
5035 const char *emit = "runlevel";
5036 dbus_bool_t b_false = FALSE;
5037 DBusMessageIter iter, sub;
5038 DBusConnection *bus;
5040 dbus_error_init(&error);
5042 if (!(rl = action_to_runlevel()))
5045 if (utmp_get_runlevel(&previous, NULL) < 0)
5048 if (!(bus = dbus_connection_open_private("unix:abstract=/com/ubuntu/upstart", &error))) {
5049 if (dbus_error_has_name(&error, DBUS_ERROR_NO_SERVER)) {
5054 log_error("Failed to connect to Upstart bus: %s", bus_error_message(&error));
5059 if ((r = bus_check_peercred(bus)) < 0) {
5060 log_error("Failed to verify owner of bus.");
5064 if (!(m = dbus_message_new_method_call(
5065 "com.ubuntu.Upstart",
5066 "/com/ubuntu/Upstart",
5067 "com.ubuntu.Upstart0_6",
5070 log_error("Could not allocate message.");
5075 dbus_message_iter_init_append(m, &iter);
5077 env1_buf[sizeof(env1_buf)-2] = rl;
5078 env2_buf[sizeof(env2_buf)-2] = previous;
5080 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &emit) ||
5081 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub) ||
5082 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env1) ||
5083 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env2) ||
5084 !dbus_message_iter_close_container(&iter, &sub) ||
5085 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b_false)) {
5086 log_error("Could not append arguments to message.");
5091 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
5093 if (error_is_no_service(&error)) {
5098 log_error("Failed to issue method call: %s", bus_error_message(&error));
5107 dbus_message_unref(m);
5110 dbus_message_unref(reply);
5113 dbus_connection_flush(bus);
5114 dbus_connection_close(bus);
5115 dbus_connection_unref(bus);
5118 dbus_error_free(&error);
5123 static int talk_initctl(void) {
5124 struct init_request request;
5128 if (!(rl = action_to_runlevel()))
5132 request.magic = INIT_MAGIC;
5133 request.sleeptime = 0;
5134 request.cmd = INIT_CMD_RUNLVL;
5135 request.runlevel = rl;
5137 if ((fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY)) < 0) {
5139 if (errno == ENOENT)
5142 log_error("Failed to open "INIT_FIFO": %m");
5147 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
5148 close_nointr_nofail(fd);
5151 log_error("Failed to write to "INIT_FIFO": %m");
5152 return errno ? -errno : -EIO;
5158 static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
5160 static const struct {
5168 int (* const dispatch)(DBusConnection *bus, char **args);
5170 { "list-units", LESS, 1, list_units },
5171 { "list-unit-files", EQUAL, 1, list_unit_files },
5172 { "list-jobs", EQUAL, 1, list_jobs },
5173 { "clear-jobs", EQUAL, 1, daemon_reload },
5174 { "load", MORE, 2, load_unit },
5175 { "cancel", MORE, 2, cancel_job },
5176 { "start", MORE, 2, start_unit },
5177 { "stop", MORE, 2, start_unit },
5178 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5179 { "reload", MORE, 2, start_unit },
5180 { "restart", MORE, 2, start_unit },
5181 { "try-restart", MORE, 2, start_unit },
5182 { "reload-or-restart", MORE, 2, start_unit },
5183 { "reload-or-try-restart", MORE, 2, start_unit },
5184 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
5185 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5186 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
5187 { "isolate", EQUAL, 2, start_unit },
5188 { "kill", MORE, 2, kill_unit },
5189 { "is-active", MORE, 2, check_unit },
5190 { "check", MORE, 2, check_unit },
5191 { "show", MORE, 1, show },
5192 { "status", MORE, 2, show },
5193 { "dump", EQUAL, 1, dump },
5194 { "dot", EQUAL, 1, dot },
5195 { "snapshot", LESS, 2, snapshot },
5196 { "delete", MORE, 2, delete_snapshot },
5197 { "daemon-reload", EQUAL, 1, daemon_reload },
5198 { "daemon-reexec", EQUAL, 1, daemon_reload },
5199 { "show-environment", EQUAL, 1, show_enviroment },
5200 { "set-environment", MORE, 2, set_environment },
5201 { "unset-environment", MORE, 2, set_environment },
5202 { "halt", EQUAL, 1, start_special },
5203 { "poweroff", EQUAL, 1, start_special },
5204 { "reboot", EQUAL, 1, start_special },
5205 { "kexec", EQUAL, 1, start_special },
5206 { "suspend", EQUAL, 1, start_special },
5207 { "hibernate", EQUAL, 1, start_special },
5208 { "default", EQUAL, 1, start_special },
5209 { "rescue", EQUAL, 1, start_special },
5210 { "emergency", EQUAL, 1, start_special },
5211 { "exit", EQUAL, 1, start_special },
5212 { "reset-failed", MORE, 1, reset_failed },
5213 { "enable", MORE, 2, enable_unit },
5214 { "disable", MORE, 2, enable_unit },
5215 { "is-enabled", MORE, 2, unit_is_enabled },
5216 { "reenable", MORE, 2, enable_unit },
5217 { "preset", MORE, 2, enable_unit },
5218 { "mask", MORE, 2, enable_unit },
5219 { "unmask", MORE, 2, enable_unit },
5220 { "link", MORE, 2, enable_unit },
5221 { "switch-root", MORE, 2, switch_root },
5231 left = argc - optind;
5234 /* Special rule: no arguments means "list-units" */
5237 if (streq(argv[optind], "help")) {
5242 for (i = 0; i < ELEMENTSOF(verbs); i++)
5243 if (streq(argv[optind], verbs[i].verb))
5246 if (i >= ELEMENTSOF(verbs)) {
5247 log_error("Unknown operation %s", argv[optind]);
5252 switch (verbs[i].argc_cmp) {
5255 if (left != verbs[i].argc) {
5256 log_error("Invalid number of arguments.");
5263 if (left < verbs[i].argc) {
5264 log_error("Too few arguments.");
5271 if (left > verbs[i].argc) {
5272 log_error("Too many arguments.");
5279 assert_not_reached("Unknown comparison operator.");
5282 /* Require a bus connection for all operations but
5284 if (!streq(verbs[i].verb, "enable") &&
5285 !streq(verbs[i].verb, "disable") &&
5286 !streq(verbs[i].verb, "is-enabled") &&
5287 !streq(verbs[i].verb, "list-unit-files") &&
5288 !streq(verbs[i].verb, "reenable") &&
5289 !streq(verbs[i].verb, "preset") &&
5290 !streq(verbs[i].verb, "mask") &&
5291 !streq(verbs[i].verb, "unmask") &&
5292 !streq(verbs[i].verb, "link")) {
5294 if (running_in_chroot() > 0) {
5295 log_info("Running in chroot, ignoring request.");
5299 if (((!streq(verbs[i].verb, "reboot") &&
5300 !streq(verbs[i].verb, "halt") &&
5301 !streq(verbs[i].verb, "poweroff")) || arg_force <= 0) && !bus) {
5302 log_error("Failed to get D-Bus connection: %s",
5303 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5309 if (!bus && !avoid_bus()) {
5310 log_error("Failed to get D-Bus connection: %s",
5311 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5316 return verbs[i].dispatch(bus, argv + optind);
5319 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
5321 struct msghdr msghdr;
5322 struct iovec iovec[2];
5323 union sockaddr_union sockaddr;
5324 struct sd_shutdown_command c;
5326 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
5333 c.dry_run = dry_run;
5337 sockaddr.sa.sa_family = AF_UNIX;
5338 strncpy(sockaddr.un.sun_path, "/run/systemd/shutdownd", sizeof(sockaddr.un.sun_path));
5341 msghdr.msg_name = &sockaddr;
5342 msghdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + sizeof("/run/systemd/shutdownd") - 1;
5345 iovec[0].iov_base = (char*) &c;
5346 iovec[0].iov_len = offsetof(struct sd_shutdown_command, wall_message);
5348 if (isempty(message))
5349 msghdr.msg_iovlen = 1;
5351 iovec[1].iov_base = (char*) message;
5352 iovec[1].iov_len = strlen(message);
5353 msghdr.msg_iovlen = 2;
5355 msghdr.msg_iov = iovec;
5357 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0) {
5358 close_nointr_nofail(fd);
5362 close_nointr_nofail(fd);
5366 static int reload_with_fallback(DBusConnection *bus) {
5369 /* First, try systemd via D-Bus. */
5370 if (daemon_reload(bus, NULL) >= 0)
5374 /* Nothing else worked, so let's try signals */
5375 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
5377 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
5378 log_error("kill() failed: %m");
5385 static int start_with_fallback(DBusConnection *bus) {
5388 /* First, try systemd via D-Bus. */
5389 if (start_unit(bus, NULL) >= 0)
5393 /* Hmm, talking to systemd via D-Bus didn't work. Then
5394 * let's try to talk to Upstart via D-Bus. */
5395 if (talk_upstart() > 0)
5398 /* Nothing else worked, so let's try
5400 if (talk_initctl() > 0)
5403 log_error("Failed to talk to init daemon.");
5407 warn_wall(arg_action);
5411 static void halt_now(enum action a) {
5413 /* Make sure C-A-D is handled by the kernel from this
5415 reboot(RB_ENABLE_CAD);
5420 log_info("Halting.");
5421 reboot(RB_HALT_SYSTEM);
5424 case ACTION_POWEROFF:
5425 log_info("Powering off.");
5426 reboot(RB_POWER_OFF);
5430 log_info("Rebooting.");
5431 reboot(RB_AUTOBOOT);
5435 assert_not_reached("Unknown halt action.");
5438 assert_not_reached("Uh? This shouldn't happen.");
5441 static int halt_main(DBusConnection *bus) {
5444 if (geteuid() != 0) {
5445 /* Try logind if we are a normal user and no special
5446 * mode applies. Maybe PolicyKit allows us to shutdown
5449 if (arg_when <= 0 &&
5452 (arg_action == ACTION_POWEROFF ||
5453 arg_action == ACTION_REBOOT)) {
5454 r = reboot_with_logind(bus, arg_action);
5459 log_error("Must be root.");
5466 m = strv_join(arg_wall, " ");
5467 r = send_shutdownd(arg_when,
5468 arg_action == ACTION_HALT ? 'H' :
5469 arg_action == ACTION_POWEROFF ? 'P' :
5470 arg_action == ACTION_KEXEC ? 'K' :
5478 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
5480 char date[FORMAT_TIMESTAMP_MAX];
5482 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
5483 format_timestamp(date, sizeof(date), arg_when));
5488 if (!arg_dry && !arg_force)
5489 return start_with_fallback(bus);
5492 if (sd_booted() > 0)
5493 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
5495 r = utmp_put_shutdown();
5497 log_warning("Failed to write utmp record: %s", strerror(-r));
5507 halt_now(arg_action);
5508 /* We should never reach this. */
5512 static int runlevel_main(void) {
5513 int r, runlevel, previous;
5515 r = utmp_get_runlevel(&runlevel, &previous);
5522 previous <= 0 ? 'N' : previous,
5523 runlevel <= 0 ? 'N' : runlevel);
5528 int main(int argc, char*argv[]) {
5529 int r, retval = EXIT_FAILURE;
5530 DBusConnection *bus = NULL;
5533 dbus_error_init(&error);
5535 log_parse_environment();
5538 r = parse_argv(argc, argv);
5542 retval = EXIT_SUCCESS;
5546 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
5547 * let's shortcut this */
5548 if (arg_action == ACTION_RUNLEVEL) {
5549 r = runlevel_main();
5550 retval = r < 0 ? EXIT_FAILURE : r;
5554 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
5555 log_info("Running in chroot, ignoring request.");
5561 if (arg_transport == TRANSPORT_NORMAL)
5562 bus_connect(arg_scope == UNIT_FILE_SYSTEM ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &bus, &private_bus, &error);
5563 else if (arg_transport == TRANSPORT_POLKIT) {
5564 bus_connect_system_polkit(&bus, &error);
5565 private_bus = false;
5566 } else if (arg_transport == TRANSPORT_SSH) {
5567 bus_connect_system_ssh(NULL, arg_host, &bus, &error);
5568 private_bus = false;
5570 assert_not_reached("Uh, invalid transport...");
5573 switch (arg_action) {
5575 case ACTION_SYSTEMCTL:
5576 r = systemctl_main(bus, argc, argv, &error);
5580 case ACTION_POWEROFF:
5586 case ACTION_RUNLEVEL2:
5587 case ACTION_RUNLEVEL3:
5588 case ACTION_RUNLEVEL4:
5589 case ACTION_RUNLEVEL5:
5591 case ACTION_EMERGENCY:
5592 case ACTION_DEFAULT:
5593 r = start_with_fallback(bus);
5598 r = reload_with_fallback(bus);
5601 case ACTION_CANCEL_SHUTDOWN:
5602 r = send_shutdownd(0, 0, false, false, NULL);
5605 case ACTION_INVALID:
5606 case ACTION_RUNLEVEL:
5608 assert_not_reached("Unknown action");
5611 retval = r < 0 ? EXIT_FAILURE : r;
5615 dbus_connection_flush(bus);
5616 dbus_connection_close(bus);
5617 dbus_connection_unref(bus);
5620 dbus_error_free(&error);
5624 strv_free(arg_property);
5627 ask_password_agent_close();
5628 polkit_agent_close();