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";
1757 m = dbus_message_new_method_call(
1758 "org.freedesktop.login1",
1759 "/org/freedesktop/login1",
1760 "org.freedesktop.login1.Manager",
1763 log_error("Could not allocate message.");
1768 if (!dbus_message_append_args(m,
1769 DBUS_TYPE_BOOLEAN, &interactive,
1770 DBUS_TYPE_INVALID)) {
1771 log_error("Could not append arguments to message.");
1776 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
1778 if (error_is_no_service(&error)) {
1779 log_debug("Failed to issue method call: %s", bus_error_message(&error));
1784 if (dbus_error_has_name(&error, DBUS_ERROR_ACCESS_DENIED)) {
1785 log_debug("Failed to issue method call: %s", bus_error_message(&error));
1790 log_info("Failed to issue method call: %s", bus_error_message(&error));
1799 dbus_message_unref(m);
1802 dbus_message_unref(reply);
1804 dbus_error_free(&error);
1812 static int start_special(DBusConnection *bus, char **args) {
1818 a = verb_to_action(args[0]);
1820 if (arg_force >= 2 && geteuid() != 0) {
1821 log_error("Must be root.");
1825 if (arg_force >= 2 &&
1826 (a == ACTION_HALT ||
1827 a == ACTION_POWEROFF ||
1828 a == ACTION_REBOOT))
1831 if (arg_force >= 1 &&
1832 (a == ACTION_HALT ||
1833 a == ACTION_POWEROFF ||
1834 a == ACTION_REBOOT ||
1835 a == ACTION_KEXEC ||
1837 return daemon_reload(bus, args);
1839 /* first try logind, to allow authentication with polkit */
1840 if (geteuid() != 0 &&
1841 (a == ACTION_POWEROFF ||
1842 a == ACTION_REBOOT)) {
1843 r = reboot_with_logind(bus, a);
1848 r = start_unit(bus, args);
1855 static int check_unit(DBusConnection *bus, char **args) {
1856 DBusMessage *m = NULL, *reply = NULL;
1858 *interface = "org.freedesktop.systemd1.Unit",
1859 *property = "ActiveState";
1860 int r = 3; /* According to LSB: "program is not running" */
1867 dbus_error_init(&error);
1869 STRV_FOREACH(name, args+1) {
1870 const char *path = NULL;
1872 DBusMessageIter iter, sub;
1874 if (!(m = dbus_message_new_method_call(
1875 "org.freedesktop.systemd1",
1876 "/org/freedesktop/systemd1",
1877 "org.freedesktop.systemd1.Manager",
1879 log_error("Could not allocate message.");
1884 if (!dbus_message_append_args(m,
1885 DBUS_TYPE_STRING, name,
1886 DBUS_TYPE_INVALID)) {
1887 log_error("Could not append arguments to message.");
1892 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
1894 /* Hmm, cannot figure out anything about this unit... */
1898 dbus_error_free(&error);
1899 dbus_message_unref(m);
1904 if (!dbus_message_get_args(reply, &error,
1905 DBUS_TYPE_OBJECT_PATH, &path,
1906 DBUS_TYPE_INVALID)) {
1907 log_error("Failed to parse reply: %s", bus_error_message(&error));
1912 dbus_message_unref(m);
1913 if (!(m = dbus_message_new_method_call(
1914 "org.freedesktop.systemd1",
1916 "org.freedesktop.DBus.Properties",
1918 log_error("Could not allocate message.");
1923 if (!dbus_message_append_args(m,
1924 DBUS_TYPE_STRING, &interface,
1925 DBUS_TYPE_STRING, &property,
1926 DBUS_TYPE_INVALID)) {
1927 log_error("Could not append arguments to message.");
1932 dbus_message_unref(reply);
1933 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
1934 log_error("Failed to issue method call: %s", bus_error_message(&error));
1939 if (!dbus_message_iter_init(reply, &iter) ||
1940 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1941 log_error("Failed to parse reply.");
1946 dbus_message_iter_recurse(&iter, &sub);
1948 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1949 log_error("Failed to parse reply.");
1954 dbus_message_iter_get_basic(&sub, &state);
1959 if (streq(state, "active") || streq(state, "reloading"))
1962 dbus_message_unref(m);
1963 dbus_message_unref(reply);
1969 dbus_message_unref(m);
1972 dbus_message_unref(reply);
1974 dbus_error_free(&error);
1979 static int kill_unit(DBusConnection *bus, char **args) {
1980 DBusMessage *m = NULL;
1988 dbus_error_init(&error);
1991 arg_kill_who = "all";
1994 arg_kill_mode = streq(arg_kill_who, "all") ? "control-group" : "process";
1996 STRV_FOREACH(name, args+1) {
1999 if (!(m = dbus_message_new_method_call(
2000 "org.freedesktop.systemd1",
2001 "/org/freedesktop/systemd1",
2002 "org.freedesktop.systemd1.Manager",
2004 log_error("Could not allocate message.");
2009 if (!dbus_message_append_args(m,
2010 DBUS_TYPE_STRING, name,
2011 DBUS_TYPE_STRING, &arg_kill_who,
2012 DBUS_TYPE_STRING, &arg_kill_mode,
2013 DBUS_TYPE_INT32, &arg_signal,
2014 DBUS_TYPE_INVALID)) {
2015 log_error("Could not append arguments to message.");
2020 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
2021 log_error("Failed to issue method call: %s", bus_error_message(&error));
2022 dbus_error_free(&error);
2026 dbus_message_unref(m);
2029 dbus_message_unref(reply);
2035 dbus_message_unref(m);
2037 dbus_error_free(&error);
2042 typedef struct ExecStatusInfo {
2050 usec_t start_timestamp;
2051 usec_t exit_timestamp;
2056 LIST_FIELDS(struct ExecStatusInfo, exec);
2059 static void exec_status_info_free(ExecStatusInfo *i) {
2068 static int exec_status_info_deserialize(DBusMessageIter *sub, ExecStatusInfo *i) {
2069 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
2070 DBusMessageIter sub2, sub3;
2074 int32_t code, status;
2080 if (dbus_message_iter_get_arg_type(sub) != DBUS_TYPE_STRUCT)
2083 dbus_message_iter_recurse(sub, &sub2);
2085 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0)
2088 if (!(i->path = strdup(path)))
2091 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_ARRAY ||
2092 dbus_message_iter_get_element_type(&sub2) != DBUS_TYPE_STRING)
2096 dbus_message_iter_recurse(&sub2, &sub3);
2097 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2098 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2099 dbus_message_iter_next(&sub3);
2104 if (!(i->argv = new0(char*, n+1)))
2108 dbus_message_iter_recurse(&sub2, &sub3);
2109 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2112 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2113 dbus_message_iter_get_basic(&sub3, &s);
2114 dbus_message_iter_next(&sub3);
2116 if (!(i->argv[n++] = strdup(s)))
2120 if (!dbus_message_iter_next(&sub2) ||
2121 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, true) < 0 ||
2122 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp, true) < 0 ||
2123 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp_monotonic, true) < 0 ||
2124 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp, true) < 0 ||
2125 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp_monotonic, true) < 0 ||
2126 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, true) < 0 ||
2127 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &code, true) < 0 ||
2128 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &status, false) < 0)
2132 i->start_timestamp = (usec_t) start_timestamp;
2133 i->exit_timestamp = (usec_t) exit_timestamp;
2134 i->pid = (pid_t) pid;
2141 typedef struct UnitStatusInfo {
2143 const char *load_state;
2144 const char *active_state;
2145 const char *sub_state;
2146 const char *unit_file_state;
2148 const char *description;
2149 const char *following;
2152 const char *default_control_group;
2154 const char *load_error;
2157 usec_t inactive_exit_timestamp;
2158 usec_t inactive_exit_timestamp_monotonic;
2159 usec_t active_enter_timestamp;
2160 usec_t active_exit_timestamp;
2161 usec_t inactive_enter_timestamp;
2163 bool need_daemon_reload;
2168 const char *status_text;
2170 #ifdef HAVE_SYSV_COMPAT
2174 usec_t start_timestamp;
2175 usec_t exit_timestamp;
2177 int exit_code, exit_status;
2179 usec_t condition_timestamp;
2180 bool condition_result;
2183 unsigned n_accepted;
2184 unsigned n_connections;
2188 const char *sysfs_path;
2190 /* Mount, Automount */
2196 LIST_HEAD(ExecStatusInfo, exec);
2199 static void print_status_info(UnitStatusInfo *i) {
2201 const char *on, *off, *ss;
2203 char since1[FORMAT_TIMESTAMP_PRETTY_MAX], *s1;
2204 char since2[FORMAT_TIMESTAMP_MAX], *s2;
2208 /* This shows pretty information about a unit. See
2209 * print_property() for a low-level property printer */
2211 printf("%s", strna(i->id));
2213 if (i->description && !streq_ptr(i->id, i->description))
2214 printf(" - %s", i->description);
2219 printf("\t Follow: unit currently follows state of %s\n", i->following);
2221 if (streq_ptr(i->load_state, "error")) {
2222 on = ansi_highlight_red(true);
2223 off = ansi_highlight_red(false);
2228 printf("\t Loaded: %s%s%s (Reason: %s)\n", on, strna(i->load_state), off, i->load_error);
2229 else if (i->path && i->unit_file_state)
2230 printf("\t Loaded: %s%s%s (%s; %s)\n", on, strna(i->load_state), off, i->path, i->unit_file_state);
2232 printf("\t Loaded: %s%s%s (%s)\n", on, strna(i->load_state), off, i->path);
2234 printf("\t Loaded: %s%s%s\n", on, strna(i->load_state), off);
2236 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
2238 if (streq_ptr(i->active_state, "failed")) {
2239 on = ansi_highlight_red(true);
2240 off = ansi_highlight_red(false);
2241 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
2242 on = ansi_highlight_green(true);
2243 off = ansi_highlight_green(false);
2248 printf("\t Active: %s%s (%s)%s",
2250 strna(i->active_state),
2254 printf("\t Active: %s%s%s",
2256 strna(i->active_state),
2259 if (!isempty(i->result) && !streq(i->result, "success"))
2260 printf(" (Result: %s)", i->result);
2262 timestamp = (streq_ptr(i->active_state, "active") ||
2263 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
2264 (streq_ptr(i->active_state, "inactive") ||
2265 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
2266 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
2267 i->active_exit_timestamp;
2269 s1 = format_timestamp_pretty(since1, sizeof(since1), timestamp);
2270 s2 = format_timestamp(since2, sizeof(since2), timestamp);
2273 printf(" since %s; %s\n", s2, s1);
2275 printf(" since %s\n", s2);
2279 if (!i->condition_result && i->condition_timestamp > 0) {
2280 s1 = format_timestamp_pretty(since1, sizeof(since1), i->condition_timestamp);
2281 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
2284 printf("\t start condition failed at %s; %s\n", s2, s1);
2286 printf("\t start condition failed at %s\n", s2);
2290 printf("\t Device: %s\n", i->sysfs_path);
2292 printf("\t Where: %s\n", i->where);
2294 printf("\t What: %s\n", i->what);
2297 printf("\tAccepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
2299 LIST_FOREACH(exec, p, i->exec) {
2303 /* Only show exited processes here */
2307 t = strv_join(p->argv, " ");
2308 printf("\t Process: %u %s=%s ", p->pid, p->name, strna(t));
2311 #ifdef HAVE_SYSV_COMPAT
2313 good = is_clean_exit_lsb(p->code, p->status);
2316 good = is_clean_exit(p->code, p->status);
2319 on = ansi_highlight_red(true);
2320 off = ansi_highlight_red(false);
2324 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
2326 if (p->code == CLD_EXITED) {
2329 printf("status=%i", p->status);
2331 #ifdef HAVE_SYSV_COMPAT
2332 if ((c = exit_status_to_string(p->status, i->is_sysv ? EXIT_STATUS_LSB : EXIT_STATUS_SYSTEMD)))
2334 if ((c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD)))
2339 printf("signal=%s", signal_to_string(p->status));
2341 printf(")%s\n", off);
2343 if (i->main_pid == p->pid &&
2344 i->start_timestamp == p->start_timestamp &&
2345 i->exit_timestamp == p->start_timestamp)
2346 /* Let's not show this twice */
2349 if (p->pid == i->control_pid)
2353 if (i->main_pid > 0 || i->control_pid > 0) {
2356 if (i->main_pid > 0) {
2357 printf("Main PID: %u", (unsigned) i->main_pid);
2361 get_process_comm(i->main_pid, &t);
2366 } else if (i->exit_code > 0) {
2367 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
2369 if (i->exit_code == CLD_EXITED) {
2372 printf("status=%i", i->exit_status);
2374 #ifdef HAVE_SYSV_COMPAT
2375 if ((c = exit_status_to_string(i->exit_status, i->is_sysv ? EXIT_STATUS_LSB : EXIT_STATUS_SYSTEMD)))
2377 if ((c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD)))
2382 printf("signal=%s", signal_to_string(i->exit_status));
2387 if (i->main_pid > 0 && i->control_pid > 0)
2390 if (i->control_pid > 0) {
2393 printf(" Control: %u", (unsigned) i->control_pid);
2395 get_process_comm(i->control_pid, &t);
2406 printf("\t Status: \"%s\"\n", i->status_text);
2408 if (i->default_control_group) {
2411 printf("\t CGroup: %s\n", i->default_control_group);
2413 if (arg_transport != TRANSPORT_SSH) {
2423 if (i->main_pid > 0)
2424 extra[k++] = i->main_pid;
2426 if (i->control_pid > 0)
2427 extra[k++] = i->control_pid;
2429 show_cgroup_and_extra_by_spec(i->default_control_group, "\t\t ", c, false, arg_all, extra, k);
2433 if (i->id && arg_transport != TRANSPORT_SSH) {
2435 show_journal_by_unit(i->id, arg_output, 0, i->inactive_exit_timestamp_monotonic, arg_lines, arg_all, arg_follow);
2438 if (i->need_daemon_reload)
2439 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %s daemon-reload' recommended.\n",
2440 ansi_highlight_red(true),
2441 ansi_highlight_red(false),
2442 arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
2445 static int status_property(const char *name, DBusMessageIter *iter, UnitStatusInfo *i) {
2451 switch (dbus_message_iter_get_arg_type(iter)) {
2453 case DBUS_TYPE_STRING: {
2456 dbus_message_iter_get_basic(iter, &s);
2459 if (streq(name, "Id"))
2461 else if (streq(name, "LoadState"))
2463 else if (streq(name, "ActiveState"))
2464 i->active_state = s;
2465 else if (streq(name, "SubState"))
2467 else if (streq(name, "Description"))
2469 else if (streq(name, "FragmentPath"))
2471 #ifdef HAVE_SYSV_COMPAT
2472 else if (streq(name, "SysVPath")) {
2477 else if (streq(name, "DefaultControlGroup"))
2478 i->default_control_group = s;
2479 else if (streq(name, "StatusText"))
2481 else if (streq(name, "SysFSPath"))
2483 else if (streq(name, "Where"))
2485 else if (streq(name, "What"))
2487 else if (streq(name, "Following"))
2489 else if (streq(name, "UnitFileState"))
2490 i->unit_file_state = s;
2491 else if (streq(name, "Result"))
2498 case DBUS_TYPE_BOOLEAN: {
2501 dbus_message_iter_get_basic(iter, &b);
2503 if (streq(name, "Accept"))
2505 else if (streq(name, "NeedDaemonReload"))
2506 i->need_daemon_reload = b;
2507 else if (streq(name, "ConditionResult"))
2508 i->condition_result = b;
2513 case DBUS_TYPE_UINT32: {
2516 dbus_message_iter_get_basic(iter, &u);
2518 if (streq(name, "MainPID")) {
2520 i->main_pid = (pid_t) u;
2523 } else if (streq(name, "ControlPID"))
2524 i->control_pid = (pid_t) u;
2525 else if (streq(name, "ExecMainPID")) {
2527 i->main_pid = (pid_t) u;
2528 } else if (streq(name, "NAccepted"))
2530 else if (streq(name, "NConnections"))
2531 i->n_connections = u;
2536 case DBUS_TYPE_INT32: {
2539 dbus_message_iter_get_basic(iter, &j);
2541 if (streq(name, "ExecMainCode"))
2542 i->exit_code = (int) j;
2543 else if (streq(name, "ExecMainStatus"))
2544 i->exit_status = (int) j;
2549 case DBUS_TYPE_UINT64: {
2552 dbus_message_iter_get_basic(iter, &u);
2554 if (streq(name, "ExecMainStartTimestamp"))
2555 i->start_timestamp = (usec_t) u;
2556 else if (streq(name, "ExecMainExitTimestamp"))
2557 i->exit_timestamp = (usec_t) u;
2558 else if (streq(name, "ActiveEnterTimestamp"))
2559 i->active_enter_timestamp = (usec_t) u;
2560 else if (streq(name, "InactiveEnterTimestamp"))
2561 i->inactive_enter_timestamp = (usec_t) u;
2562 else if (streq(name, "InactiveExitTimestamp"))
2563 i->inactive_exit_timestamp = (usec_t) u;
2564 else if (streq(name, "InactiveExitTimestampMonotonic"))
2565 i->inactive_exit_timestamp_monotonic = (usec_t) u;
2566 else if (streq(name, "ActiveExitTimestamp"))
2567 i->active_exit_timestamp = (usec_t) u;
2568 else if (streq(name, "ConditionTimestamp"))
2569 i->condition_timestamp = (usec_t) u;
2574 case DBUS_TYPE_ARRAY: {
2576 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
2577 startswith(name, "Exec")) {
2578 DBusMessageIter sub;
2580 dbus_message_iter_recurse(iter, &sub);
2581 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2582 ExecStatusInfo *info;
2585 if (!(info = new0(ExecStatusInfo, 1)))
2588 if (!(info->name = strdup(name))) {
2593 if ((r = exec_status_info_deserialize(&sub, info)) < 0) {
2598 LIST_PREPEND(ExecStatusInfo, exec, i->exec, info);
2600 dbus_message_iter_next(&sub);
2607 case DBUS_TYPE_STRUCT: {
2609 if (streq(name, "LoadError")) {
2610 DBusMessageIter sub;
2611 const char *n, *message;
2614 dbus_message_iter_recurse(iter, &sub);
2616 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &n, true);
2620 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &message, false);
2624 if (!isempty(message))
2625 i->load_error = message;
2635 static int print_property(const char *name, DBusMessageIter *iter) {
2639 /* This is a low-level property printer, see
2640 * print_status_info() for the nicer output */
2642 if (arg_property && !strv_find(arg_property, name))
2645 switch (dbus_message_iter_get_arg_type(iter)) {
2647 case DBUS_TYPE_STRUCT: {
2648 DBusMessageIter sub;
2649 dbus_message_iter_recurse(iter, &sub);
2651 if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32 && streq(name, "Job")) {
2654 dbus_message_iter_get_basic(&sub, &u);
2657 printf("%s=%u\n", name, (unsigned) u);
2659 printf("%s=\n", name);
2662 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "Unit")) {
2665 dbus_message_iter_get_basic(&sub, &s);
2667 if (arg_all || s[0])
2668 printf("%s=%s\n", name, s);
2671 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "LoadError")) {
2672 const char *a = NULL, *b = NULL;
2674 if (bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &a, true) >= 0)
2675 bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &b, false);
2677 if (arg_all || !isempty(a) || !isempty(b))
2678 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
2686 case DBUS_TYPE_ARRAY:
2688 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "EnvironmentFiles")) {
2689 DBusMessageIter sub, sub2;
2691 dbus_message_iter_recurse(iter, &sub);
2692 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2696 dbus_message_iter_recurse(&sub, &sub2);
2698 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
2699 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) >= 0)
2700 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
2702 dbus_message_iter_next(&sub);
2707 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Paths")) {
2708 DBusMessageIter sub, sub2;
2710 dbus_message_iter_recurse(iter, &sub);
2711 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2712 const char *type, *path;
2714 dbus_message_iter_recurse(&sub, &sub2);
2716 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
2717 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
2718 printf("%s=%s\n", type, path);
2720 dbus_message_iter_next(&sub);
2725 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Timers")) {
2726 DBusMessageIter sub, sub2;
2728 dbus_message_iter_recurse(iter, &sub);
2729 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2731 uint64_t value, next_elapse;
2733 dbus_message_iter_recurse(&sub, &sub2);
2735 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &base, true) >= 0 &&
2736 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &value, true) >= 0 &&
2737 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &next_elapse, false) >= 0) {
2738 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
2740 printf("%s={ value=%s ; next_elapse=%s }\n",
2742 format_timespan(timespan1, sizeof(timespan1), value),
2743 format_timespan(timespan2, sizeof(timespan2), next_elapse));
2746 dbus_message_iter_next(&sub);
2751 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "ControlGroupAttributes")) {
2752 DBusMessageIter sub, sub2;
2754 dbus_message_iter_recurse(iter, &sub);
2755 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2756 const char *controller, *attr, *value;
2758 dbus_message_iter_recurse(&sub, &sub2);
2760 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &controller, true) >= 0 &&
2761 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &attr, true) >= 0 &&
2762 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &value, false) >= 0) {
2764 printf("ControlGroupAttribute={ controller=%s ; attribute=%s ; value=\"%s\" }\n",
2770 dbus_message_iter_next(&sub);
2775 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && startswith(name, "Exec")) {
2776 DBusMessageIter sub;
2778 dbus_message_iter_recurse(iter, &sub);
2779 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2780 ExecStatusInfo info;
2783 if (exec_status_info_deserialize(&sub, &info) >= 0) {
2784 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
2787 t = strv_join(info.argv, " ");
2789 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
2793 yes_no(info.ignore),
2794 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
2795 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
2796 (unsigned) info. pid,
2797 sigchld_code_to_string(info.code),
2799 info.code == CLD_EXITED ? "" : "/",
2800 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
2806 strv_free(info.argv);
2808 dbus_message_iter_next(&sub);
2817 if (generic_print_property(name, iter, arg_all) > 0)
2821 printf("%s=[unprintable]\n", name);
2826 static int show_one(const char *verb, DBusConnection *bus, const char *path, bool show_properties, bool *new_line) {
2827 DBusMessage *m = NULL, *reply = NULL;
2828 const char *interface = "";
2831 DBusMessageIter iter, sub, sub2, sub3;
2832 UnitStatusInfo info;
2840 dbus_error_init(&error);
2842 if (!(m = dbus_message_new_method_call(
2843 "org.freedesktop.systemd1",
2845 "org.freedesktop.DBus.Properties",
2847 log_error("Could not allocate message.");
2852 if (!dbus_message_append_args(m,
2853 DBUS_TYPE_STRING, &interface,
2854 DBUS_TYPE_INVALID)) {
2855 log_error("Could not append arguments to message.");
2860 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
2861 log_error("Failed to issue method call: %s", bus_error_message(&error));
2866 if (!dbus_message_iter_init(reply, &iter) ||
2867 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
2868 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
2869 log_error("Failed to parse reply.");
2874 dbus_message_iter_recurse(&iter, &sub);
2881 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
2884 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_DICT_ENTRY) {
2885 log_error("Failed to parse reply.");
2890 dbus_message_iter_recurse(&sub, &sub2);
2892 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0) {
2893 log_error("Failed to parse reply.");
2898 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
2899 log_error("Failed to parse reply.");
2904 dbus_message_iter_recurse(&sub2, &sub3);
2906 if (show_properties)
2907 r = print_property(name, &sub3);
2909 r = status_property(name, &sub3, &info);
2912 log_error("Failed to parse reply.");
2917 dbus_message_iter_next(&sub);
2922 if (!show_properties)
2923 print_status_info(&info);
2925 if (!streq_ptr(info.active_state, "active") &&
2926 !streq_ptr(info.active_state, "reloading") &&
2927 streq(verb, "status"))
2928 /* According to LSB: "program not running" */
2931 while ((p = info.exec)) {
2932 LIST_REMOVE(ExecStatusInfo, exec, info.exec, p);
2933 exec_status_info_free(p);
2938 dbus_message_unref(m);
2941 dbus_message_unref(reply);
2943 dbus_error_free(&error);
2948 static int show(DBusConnection *bus, char **args) {
2949 DBusMessage *m = NULL, *reply = NULL;
2952 bool show_properties, new_line = false;
2958 dbus_error_init(&error);
2960 show_properties = !streq(args[0], "status");
2962 if (show_properties)
2963 pager_open_if_enabled();
2965 if (show_properties && strv_length(args) <= 1) {
2966 /* If not argument is specified inspect the manager
2969 ret = show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line);
2973 STRV_FOREACH(name, args+1) {
2974 const char *path = NULL;
2977 if (safe_atou32(*name, &id) < 0) {
2979 /* Interpret as unit name */
2981 if (!(m = dbus_message_new_method_call(
2982 "org.freedesktop.systemd1",
2983 "/org/freedesktop/systemd1",
2984 "org.freedesktop.systemd1.Manager",
2986 log_error("Could not allocate message.");
2991 if (!dbus_message_append_args(m,
2992 DBUS_TYPE_STRING, name,
2993 DBUS_TYPE_INVALID)) {
2994 log_error("Could not append arguments to message.");
2999 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3001 if (!dbus_error_has_name(&error, DBUS_ERROR_ACCESS_DENIED)) {
3002 log_error("Failed to issue method call: %s", bus_error_message(&error));
3007 dbus_error_free(&error);
3009 dbus_message_unref(m);
3010 if (!(m = dbus_message_new_method_call(
3011 "org.freedesktop.systemd1",
3012 "/org/freedesktop/systemd1",
3013 "org.freedesktop.systemd1.Manager",
3015 log_error("Could not allocate message.");
3020 if (!dbus_message_append_args(m,
3021 DBUS_TYPE_STRING, name,
3022 DBUS_TYPE_INVALID)) {
3023 log_error("Could not append arguments to message.");
3028 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3029 log_error("Failed to issue method call: %s", bus_error_message(&error));
3031 if (dbus_error_has_name(&error, BUS_ERROR_NO_SUCH_UNIT))
3032 ret = 4; /* According to LSB: "program or service status is unknown" */
3039 } else if (show_properties) {
3041 /* Interpret as job id */
3043 if (!(m = dbus_message_new_method_call(
3044 "org.freedesktop.systemd1",
3045 "/org/freedesktop/systemd1",
3046 "org.freedesktop.systemd1.Manager",
3048 log_error("Could not allocate message.");
3053 if (!dbus_message_append_args(m,
3054 DBUS_TYPE_UINT32, &id,
3055 DBUS_TYPE_INVALID)) {
3056 log_error("Could not append arguments to message.");
3061 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3062 log_error("Failed to issue method call: %s", bus_error_message(&error));
3068 /* Interpret as PID */
3070 if (!(m = dbus_message_new_method_call(
3071 "org.freedesktop.systemd1",
3072 "/org/freedesktop/systemd1",
3073 "org.freedesktop.systemd1.Manager",
3075 log_error("Could not allocate message.");
3080 if (!dbus_message_append_args(m,
3081 DBUS_TYPE_UINT32, &id,
3082 DBUS_TYPE_INVALID)) {
3083 log_error("Could not append arguments to message.");
3088 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3089 log_error("Failed to issue method call: %s", bus_error_message(&error));
3095 if (!dbus_message_get_args(reply, &error,
3096 DBUS_TYPE_OBJECT_PATH, &path,
3097 DBUS_TYPE_INVALID)) {
3098 log_error("Failed to parse reply: %s", bus_error_message(&error));
3103 if ((r = show_one(args[0], bus, path, show_properties, &new_line)) != 0)
3106 dbus_message_unref(m);
3107 dbus_message_unref(reply);
3113 dbus_message_unref(m);
3116 dbus_message_unref(reply);
3118 dbus_error_free(&error);
3123 static int dump(DBusConnection *bus, char **args) {
3124 DBusMessage *m = NULL, *reply = NULL;
3129 dbus_error_init(&error);
3131 pager_open_if_enabled();
3133 if (!(m = dbus_message_new_method_call(
3134 "org.freedesktop.systemd1",
3135 "/org/freedesktop/systemd1",
3136 "org.freedesktop.systemd1.Manager",
3138 log_error("Could not allocate message.");
3142 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3143 log_error("Failed to issue method call: %s", bus_error_message(&error));
3148 if (!dbus_message_get_args(reply, &error,
3149 DBUS_TYPE_STRING, &text,
3150 DBUS_TYPE_INVALID)) {
3151 log_error("Failed to parse reply: %s", bus_error_message(&error));
3156 fputs(text, stdout);
3162 dbus_message_unref(m);
3165 dbus_message_unref(reply);
3167 dbus_error_free(&error);
3172 static int snapshot(DBusConnection *bus, char **args) {
3173 DBusMessage *m = NULL, *reply = NULL;
3176 const char *name = "", *path, *id;
3177 dbus_bool_t cleanup = FALSE;
3178 DBusMessageIter iter, sub;
3180 *interface = "org.freedesktop.systemd1.Unit",
3183 dbus_error_init(&error);
3185 if (!(m = dbus_message_new_method_call(
3186 "org.freedesktop.systemd1",
3187 "/org/freedesktop/systemd1",
3188 "org.freedesktop.systemd1.Manager",
3189 "CreateSnapshot"))) {
3190 log_error("Could not allocate message.");
3194 if (strv_length(args) > 1)
3197 if (!dbus_message_append_args(m,
3198 DBUS_TYPE_STRING, &name,
3199 DBUS_TYPE_BOOLEAN, &cleanup,
3200 DBUS_TYPE_INVALID)) {
3201 log_error("Could not append arguments to message.");
3206 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3207 log_error("Failed to issue method call: %s", bus_error_message(&error));
3212 if (!dbus_message_get_args(reply, &error,
3213 DBUS_TYPE_OBJECT_PATH, &path,
3214 DBUS_TYPE_INVALID)) {
3215 log_error("Failed to parse reply: %s", bus_error_message(&error));
3220 dbus_message_unref(m);
3221 if (!(m = dbus_message_new_method_call(
3222 "org.freedesktop.systemd1",
3224 "org.freedesktop.DBus.Properties",
3226 log_error("Could not allocate message.");
3230 if (!dbus_message_append_args(m,
3231 DBUS_TYPE_STRING, &interface,
3232 DBUS_TYPE_STRING, &property,
3233 DBUS_TYPE_INVALID)) {
3234 log_error("Could not append arguments to message.");
3239 dbus_message_unref(reply);
3240 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3241 log_error("Failed to issue method call: %s", bus_error_message(&error));
3246 if (!dbus_message_iter_init(reply, &iter) ||
3247 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3248 log_error("Failed to parse reply.");
3253 dbus_message_iter_recurse(&iter, &sub);
3255 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
3256 log_error("Failed to parse reply.");
3261 dbus_message_iter_get_basic(&sub, &id);
3269 dbus_message_unref(m);
3272 dbus_message_unref(reply);
3274 dbus_error_free(&error);
3279 static int delete_snapshot(DBusConnection *bus, char **args) {
3280 DBusMessage *m = NULL, *reply = NULL;
3288 dbus_error_init(&error);
3290 STRV_FOREACH(name, args+1) {
3291 const char *path = NULL;
3293 if (!(m = dbus_message_new_method_call(
3294 "org.freedesktop.systemd1",
3295 "/org/freedesktop/systemd1",
3296 "org.freedesktop.systemd1.Manager",
3298 log_error("Could not allocate message.");
3303 if (!dbus_message_append_args(m,
3304 DBUS_TYPE_STRING, name,
3305 DBUS_TYPE_INVALID)) {
3306 log_error("Could not append arguments to message.");
3311 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3312 log_error("Failed to issue method call: %s", bus_error_message(&error));
3317 if (!dbus_message_get_args(reply, &error,
3318 DBUS_TYPE_OBJECT_PATH, &path,
3319 DBUS_TYPE_INVALID)) {
3320 log_error("Failed to parse reply: %s", bus_error_message(&error));
3325 dbus_message_unref(m);
3326 if (!(m = dbus_message_new_method_call(
3327 "org.freedesktop.systemd1",
3329 "org.freedesktop.systemd1.Snapshot",
3331 log_error("Could not allocate message.");
3336 dbus_message_unref(reply);
3337 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3338 log_error("Failed to issue method call: %s", bus_error_message(&error));
3343 dbus_message_unref(m);
3344 dbus_message_unref(reply);
3352 dbus_message_unref(m);
3355 dbus_message_unref(reply);
3357 dbus_error_free(&error);
3362 static int daemon_reload(DBusConnection *bus, char **args) {
3363 DBusMessage *m = NULL, *reply = NULL;
3368 dbus_error_init(&error);
3370 if (arg_action == ACTION_RELOAD)
3372 else if (arg_action == ACTION_REEXEC)
3373 method = "Reexecute";
3375 assert(arg_action == ACTION_SYSTEMCTL);
3378 streq(args[0], "clear-jobs") ||
3379 streq(args[0], "cancel") ? "ClearJobs" :
3380 streq(args[0], "daemon-reexec") ? "Reexecute" :
3381 streq(args[0], "reset-failed") ? "ResetFailed" :
3382 streq(args[0], "halt") ? "Halt" :
3383 streq(args[0], "poweroff") ? "PowerOff" :
3384 streq(args[0], "reboot") ? "Reboot" :
3385 streq(args[0], "kexec") ? "KExec" :
3386 streq(args[0], "exit") ? "Exit" :
3387 /* "daemon-reload" */ "Reload";
3390 if (!(m = dbus_message_new_method_call(
3391 "org.freedesktop.systemd1",
3392 "/org/freedesktop/systemd1",
3393 "org.freedesktop.systemd1.Manager",
3395 log_error("Could not allocate message.");
3399 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3401 if (arg_action != ACTION_SYSTEMCTL && error_is_no_service(&error)) {
3402 /* There's always a fallback possible for
3403 * legacy actions. */
3408 if (streq(method, "Reexecute") && dbus_error_has_name(&error, DBUS_ERROR_NO_REPLY)) {
3409 /* On reexecution, we expect a disconnect, not
3415 log_error("Failed to issue method call: %s", bus_error_message(&error));
3424 dbus_message_unref(m);
3427 dbus_message_unref(reply);
3429 dbus_error_free(&error);
3434 static int reset_failed(DBusConnection *bus, char **args) {
3435 DBusMessage *m = NULL;
3441 dbus_error_init(&error);
3443 if (strv_length(args) <= 1)
3444 return daemon_reload(bus, args);
3446 STRV_FOREACH(name, args+1) {
3449 if (!(m = dbus_message_new_method_call(
3450 "org.freedesktop.systemd1",
3451 "/org/freedesktop/systemd1",
3452 "org.freedesktop.systemd1.Manager",
3453 "ResetFailedUnit"))) {
3454 log_error("Could not allocate message.");
3459 if (!dbus_message_append_args(m,
3460 DBUS_TYPE_STRING, name,
3461 DBUS_TYPE_INVALID)) {
3462 log_error("Could not append arguments to message.");
3467 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3468 log_error("Failed to issue method call: %s", bus_error_message(&error));
3473 dbus_message_unref(m);
3474 dbus_message_unref(reply);
3482 dbus_message_unref(m);
3484 dbus_error_free(&error);
3489 static int show_enviroment(DBusConnection *bus, char **args) {
3490 DBusMessage *m = NULL, *reply = NULL;
3492 DBusMessageIter iter, sub, sub2;
3495 *interface = "org.freedesktop.systemd1.Manager",
3496 *property = "Environment";
3498 dbus_error_init(&error);
3500 pager_open_if_enabled();
3502 if (!(m = dbus_message_new_method_call(
3503 "org.freedesktop.systemd1",
3504 "/org/freedesktop/systemd1",
3505 "org.freedesktop.DBus.Properties",
3507 log_error("Could not allocate message.");
3511 if (!dbus_message_append_args(m,
3512 DBUS_TYPE_STRING, &interface,
3513 DBUS_TYPE_STRING, &property,
3514 DBUS_TYPE_INVALID)) {
3515 log_error("Could not append arguments to message.");
3520 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3521 log_error("Failed to issue method call: %s", bus_error_message(&error));
3526 if (!dbus_message_iter_init(reply, &iter) ||
3527 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3528 log_error("Failed to parse reply.");
3533 dbus_message_iter_recurse(&iter, &sub);
3535 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_ARRAY ||
3536 dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_STRING) {
3537 log_error("Failed to parse reply.");
3542 dbus_message_iter_recurse(&sub, &sub2);
3544 while (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_INVALID) {
3547 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
3548 log_error("Failed to parse reply.");
3553 dbus_message_iter_get_basic(&sub2, &text);
3554 printf("%s\n", text);
3556 dbus_message_iter_next(&sub2);
3563 dbus_message_unref(m);
3566 dbus_message_unref(reply);
3568 dbus_error_free(&error);
3573 static int set_environment(DBusConnection *bus, char **args) {
3574 DBusMessage *m = NULL, *reply = NULL;
3578 DBusMessageIter iter, sub;
3581 dbus_error_init(&error);
3583 method = streq(args[0], "set-environment")
3585 : "UnsetEnvironment";
3587 if (!(m = dbus_message_new_method_call(
3588 "org.freedesktop.systemd1",
3589 "/org/freedesktop/systemd1",
3590 "org.freedesktop.systemd1.Manager",
3593 log_error("Could not allocate message.");
3597 dbus_message_iter_init_append(m, &iter);
3599 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub)) {
3600 log_error("Could not append arguments to message.");
3605 STRV_FOREACH(name, args+1)
3606 if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, name)) {
3607 log_error("Could not append arguments to message.");
3612 if (!dbus_message_iter_close_container(&iter, &sub)) {
3613 log_error("Could not append arguments to message.");
3618 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3619 log_error("Failed to issue method call: %s", bus_error_message(&error));
3628 dbus_message_unref(m);
3631 dbus_message_unref(reply);
3633 dbus_error_free(&error);
3638 static int enable_sysv_units(char **args) {
3641 #if defined (HAVE_SYSV_COMPAT) && (defined(TARGET_FEDORA) || defined(TARGET_MANDRIVA) || defined(TARGET_SUSE) || defined(TARGET_MEEGO) || defined(TARGET_ALTLINUX) || defined(TARGET_MAGEIA))
3642 const char *verb = args[0];
3643 unsigned f = 1, t = 1;
3646 if (arg_scope != UNIT_FILE_SYSTEM)
3649 if (!streq(verb, "enable") &&
3650 !streq(verb, "disable") &&
3651 !streq(verb, "is-enabled"))
3654 /* Processes all SysV units, and reshuffles the array so that
3655 * afterwards only the native units remain */
3658 r = lookup_paths_init(&paths, MANAGER_SYSTEM, false);
3664 for (f = 1; args[f]; f++) {
3667 bool found_native = false, found_sysv;
3669 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
3670 char **k, *l, *q = NULL;
3677 if (!endswith(name, ".service"))
3680 if (path_is_absolute(name))
3683 STRV_FOREACH(k, paths.unit_path) {
3686 if (!isempty(arg_root))
3687 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
3689 asprintf(&p, "%s/%s", *k, name);
3692 log_error("No memory");
3697 found_native = access(p, F_OK) >= 0;
3708 if (!isempty(arg_root))
3709 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
3711 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
3713 log_error("No memory");
3718 p[strlen(p) - sizeof(".service") + 1] = 0;
3719 found_sysv = access(p, F_OK) >= 0;
3726 /* Mark this entry, so that we don't try enabling it as native unit */
3727 args[f] = (char*) "";
3729 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
3731 if (!isempty(arg_root))
3732 argv[c++] = q = strappend("--root=", arg_root);
3734 argv[c++] = path_get_file_name(p);
3736 streq(verb, "enable") ? "on" :
3737 streq(verb, "disable") ? "off" : "--level=5";
3740 l = strv_join((char**)argv, " ");
3742 log_error("No memory.");
3749 log_info("Executing %s", l);
3754 log_error("Failed to fork: %m");
3759 } else if (pid == 0) {
3762 execv(argv[0], (char**) argv);
3763 _exit(EXIT_FAILURE);
3769 j = wait_for_terminate(pid, &status);
3771 log_error("Failed to wait for child: %s", strerror(-r));
3776 if (status.si_code == CLD_EXITED) {
3777 if (streq(verb, "is-enabled")) {
3778 if (status.si_status == 0) {
3787 } else if (status.si_status != 0) {
3798 lookup_paths_free(&paths);
3800 /* Drop all SysV units */
3801 for (f = 1, t = 1; args[f]; f++) {
3803 if (isempty(args[f]))
3806 args[t++] = args[f];
3815 static int enable_unit(DBusConnection *bus, char **args) {
3816 const char *verb = args[0];
3817 UnitFileChange *changes = NULL;
3818 unsigned n_changes = 0, i;
3819 int carries_install_info = -1;
3820 DBusMessage *m = NULL, *reply = NULL;
3824 r = enable_sysv_units(args);
3831 dbus_error_init(&error);
3833 if (!bus || avoid_bus()) {
3834 if (streq(verb, "enable")) {
3835 r = unit_file_enable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3836 carries_install_info = r;
3837 } else if (streq(verb, "disable"))
3838 r = unit_file_disable(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3839 else if (streq(verb, "reenable")) {
3840 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3841 carries_install_info = r;
3842 } else if (streq(verb, "link"))
3843 r = unit_file_link(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3844 else if (streq(verb, "preset")) {
3845 r = unit_file_preset(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3846 carries_install_info = r;
3847 } else if (streq(verb, "mask"))
3848 r = unit_file_mask(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3849 else if (streq(verb, "unmask"))
3850 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3852 assert_not_reached("Unknown verb");
3855 log_error("Operation failed: %s", strerror(-r));
3860 for (i = 0; i < n_changes; i++) {
3861 if (changes[i].type == UNIT_FILE_SYMLINK)
3862 log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
3864 log_info("rm '%s'", changes[i].path);
3870 bool send_force = true, expect_carries_install_info = false;
3872 DBusMessageIter iter, sub, sub2;
3874 if (streq(verb, "enable")) {
3875 method = "EnableUnitFiles";
3876 expect_carries_install_info = true;
3877 } else if (streq(verb, "disable")) {
3878 method = "DisableUnitFiles";
3880 } else if (streq(verb, "reenable")) {
3881 method = "ReenableUnitFiles";
3882 expect_carries_install_info = true;
3883 } else if (streq(verb, "link"))
3884 method = "LinkUnitFiles";
3885 else if (streq(verb, "preset")) {
3886 method = "PresetUnitFiles";
3887 expect_carries_install_info = true;
3888 } else if (streq(verb, "mask"))
3889 method = "MaskUnitFiles";
3890 else if (streq(verb, "unmask")) {
3891 method = "UnmaskUnitFiles";
3894 assert_not_reached("Unknown verb");
3896 m = dbus_message_new_method_call(
3897 "org.freedesktop.systemd1",
3898 "/org/freedesktop/systemd1",
3899 "org.freedesktop.systemd1.Manager",
3902 log_error("Out of memory");
3907 dbus_message_iter_init_append(m, &iter);
3909 r = bus_append_strv_iter(&iter, args+1);
3911 log_error("Failed to append unit files.");
3916 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &a)) {
3917 log_error("Failed to append runtime boolean.");
3925 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b)) {
3926 log_error("Failed to append force boolean.");
3932 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3934 log_error("Failed to issue method call: %s", bus_error_message(&error));
3939 if (!dbus_message_iter_init(reply, &iter)) {
3940 log_error("Failed to initialize iterator.");
3944 if (expect_carries_install_info) {
3945 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &b, true);
3947 log_error("Failed to parse reply.");
3951 carries_install_info = b;
3954 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3955 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
3956 log_error("Failed to parse reply.");
3961 dbus_message_iter_recurse(&iter, &sub);
3962 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
3963 const char *type, *path, *source;
3965 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
3966 log_error("Failed to parse reply.");
3971 dbus_message_iter_recurse(&sub, &sub2);
3973 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
3974 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
3975 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &source, false) < 0) {
3976 log_error("Failed to parse reply.");
3982 if (streq(type, "symlink"))
3983 log_info("ln -s '%s' '%s'", source, path);
3985 log_info("rm '%s'", path);
3988 dbus_message_iter_next(&sub);
3991 /* Try to reload if enabeld */
3993 r = daemon_reload(bus, args);
3996 if (carries_install_info == 0)
3997 log_warning("Warning: unit files do not carry install information. No operation executed.");
4001 dbus_message_unref(m);
4004 dbus_message_unref(reply);
4006 unit_file_changes_free(changes, n_changes);
4008 dbus_error_free(&error);
4012 static int unit_is_enabled(DBusConnection *bus, char **args) {
4015 DBusMessage *m = NULL, *reply = NULL;
4019 dbus_error_init(&error);
4021 r = enable_sysv_units(args);
4027 if (!bus || avoid_bus()) {
4029 STRV_FOREACH(name, args+1) {
4030 UnitFileState state;
4032 state = unit_file_get_state(arg_scope, arg_root, *name);
4038 if (state == UNIT_FILE_ENABLED ||
4039 state == UNIT_FILE_ENABLED_RUNTIME ||
4040 state == UNIT_FILE_STATIC)
4044 puts(unit_file_state_to_string(state));
4048 STRV_FOREACH(name, args+1) {
4051 m = dbus_message_new_method_call(
4052 "org.freedesktop.systemd1",
4053 "/org/freedesktop/systemd1",
4054 "org.freedesktop.systemd1.Manager",
4055 "GetUnitFileState");
4057 log_error("Out of memory");
4062 if (!dbus_message_append_args(m,
4063 DBUS_TYPE_STRING, name,
4064 DBUS_TYPE_INVALID)) {
4065 log_error("Could not append arguments to message.");
4070 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
4072 log_error("Failed to issue method call: %s", bus_error_message(&error));
4077 if (!dbus_message_get_args(reply, &error,
4078 DBUS_TYPE_STRING, &s,
4079 DBUS_TYPE_INVALID)) {
4080 log_error("Failed to parse reply: %s", bus_error_message(&error));
4085 dbus_message_unref(m);
4086 dbus_message_unref(reply);
4089 if (streq(s, "enabled") ||
4090 streq(s, "enabled-runtime") ||
4099 r = enabled ? 0 : 1;
4103 dbus_message_unref(m);
4106 dbus_message_unref(reply);
4108 dbus_error_free(&error);
4112 static int systemctl_help(void) {
4114 pager_open_if_enabled();
4116 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
4117 "Query or send control commands to the systemd manager.\n\n"
4118 " -h --help Show this help\n"
4119 " --version Show package version\n"
4120 " -t --type=TYPE List only units of a particular type\n"
4121 " -p --property=NAME Show only properties by this name\n"
4122 " -a --all Show all units/properties, including dead/empty ones\n"
4123 " --failed Show only failed units\n"
4124 " --full Don't ellipsize unit names on output\n"
4125 " --fail When queueing a new job, fail if conflicting jobs are\n"
4127 " --ignore-dependencies\n"
4128 " When queueing a new job, ignore all its dependencies\n"
4129 " --kill-who=WHO Who to send signal to\n"
4130 " -s --signal=SIGNAL Which signal to send\n"
4131 " -H --host=[USER@]HOST\n"
4132 " Show information for remote host\n"
4133 " -P --privileged Acquire privileges before execution\n"
4134 " -q --quiet Suppress output\n"
4135 " --no-block Do not wait until operation finished\n"
4136 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4137 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
4139 " --no-legend Do not print a legend (column headers and hints)\n"
4140 " --no-pager Do not pipe output into a pager\n"
4141 " --no-ask-password\n"
4142 " Do not ask for system passwords\n"
4143 " --order When generating graph for dot, show only order\n"
4144 " --require When generating graph for dot, show only requirement\n"
4145 " --system Connect to system manager\n"
4146 " --user Connect to user service manager\n"
4147 " --global Enable/disable unit files globally\n"
4148 " -f --force When enabling unit files, override existing symlinks\n"
4149 " When shutting down, execute action immediately\n"
4150 " --root=PATH Enable unit files in the specified root directory\n"
4151 " --runtime Enable unit files only temporarily until next reboot\n"
4152 " -n --lines=INTEGER Journal entries to show\n"
4153 " --follow Follow journal\n"
4154 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
4155 " verbose, export, json, cat)\n\n"
4157 " list-units List loaded units\n"
4158 " start [NAME...] Start (activate) one or more units\n"
4159 " stop [NAME...] Stop (deactivate) one or more units\n"
4160 " reload [NAME...] Reload one or more units\n"
4161 " restart [NAME...] Start or restart one or more units\n"
4162 " try-restart [NAME...] Restart one or more units if active\n"
4163 " reload-or-restart [NAME...] Reload one or more units is possible,\n"
4164 " otherwise start or restart\n"
4165 " reload-or-try-restart [NAME...] Reload one or more units is possible,\n"
4166 " otherwise restart if active\n"
4167 " isolate [NAME] Start one unit and stop all others\n"
4168 " kill [NAME...] Send signal to processes of a unit\n"
4169 " is-active [NAME...] Check whether units are active\n"
4170 " status [NAME...|PID...] Show runtime status of one or more units\n"
4171 " show [NAME...|JOB...] Show properties of one or more\n"
4172 " units/jobs or the manager\n"
4173 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
4175 " load [NAME...] Load one or more units\n\n"
4176 "Unit File Commands:\n"
4177 " list-unit-files List installed unit files\n"
4178 " enable [NAME...] Enable one or more unit files\n"
4179 " disable [NAME...] Disable one or more unit files\n"
4180 " reenable [NAME...] Reenable one or more unit files\n"
4181 " preset [NAME...] Enable/disable one or more unit files\n"
4182 " based on preset configuration\n"
4183 " mask [NAME...] Mask one or more units\n"
4184 " unmask [NAME...] Unmask one or more units\n"
4185 " link [PATH...] Link one or more units files into\n"
4186 " the search path\n"
4187 " is-enabled [NAME...] Check whether unit files are enabled\n\n"
4189 " list-jobs List jobs\n"
4190 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
4191 "Status Commands:\n"
4192 " dump Dump server status\n"
4193 " dot Dump dependency graph for dot(1)\n\n"
4194 "Snapshot Commands:\n"
4195 " snapshot [NAME] Create a snapshot\n"
4196 " delete [NAME...] Remove one or more snapshots\n\n"
4197 "Environment Commands:\n"
4198 " show-environment Dump environment\n"
4199 " set-environment [NAME=VALUE...] Set one or more environment variables\n"
4200 " unset-environment [NAME...] Unset one or more environment variables\n\n"
4201 "Manager Lifecycle Commands:\n"
4202 " daemon-reload Reload systemd manager configuration\n"
4203 " daemon-reexec Reexecute systemd manager\n\n"
4204 "System Commands:\n"
4205 " default Enter system default mode\n"
4206 " rescue Enter system rescue mode\n"
4207 " emergency Enter system emergency mode\n"
4208 " halt Shut down and halt the system\n"
4209 " poweroff Shut down and power-off the system\n"
4210 " reboot Shut down and reboot the system\n"
4211 " kexec Shut down and reboot the system with kexec\n"
4212 " exit Request user instance exit\n"
4213 " suspend Suspend the system\n"
4214 " hibernate Hibernate the system\n",
4215 program_invocation_short_name);
4220 static int halt_help(void) {
4222 printf("%s [OPTIONS...]\n\n"
4223 "%s the system.\n\n"
4224 " --help Show this help\n"
4225 " --halt Halt the machine\n"
4226 " -p --poweroff Switch off the machine\n"
4227 " --reboot Reboot the machine\n"
4228 " -f --force Force immediate halt/power-off/reboot\n"
4229 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
4230 " -d --no-wtmp Don't write wtmp record\n"
4231 " -n --no-sync Don't sync before halt/power-off/reboot\n"
4232 " --no-wall Don't send wall message before halt/power-off/reboot\n",
4233 program_invocation_short_name,
4234 arg_action == ACTION_REBOOT ? "Reboot" :
4235 arg_action == ACTION_POWEROFF ? "Power off" :
4241 static int shutdown_help(void) {
4243 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
4244 "Shut down the system.\n\n"
4245 " --help Show this help\n"
4246 " -H --halt Halt the machine\n"
4247 " -P --poweroff Power-off the machine\n"
4248 " -r --reboot Reboot the machine\n"
4249 " -h Equivalent to --poweroff, overriden by --halt\n"
4250 " -k Don't halt/power-off/reboot, just send warnings\n"
4251 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4252 " -c Cancel a pending shutdown\n",
4253 program_invocation_short_name);
4258 static int telinit_help(void) {
4260 printf("%s [OPTIONS...] {COMMAND}\n\n"
4261 "Send control commands to the init daemon.\n\n"
4262 " --help Show this help\n"
4263 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
4265 " 0 Power-off the machine\n"
4266 " 6 Reboot the machine\n"
4267 " 2, 3, 4, 5 Start runlevelX.target unit\n"
4268 " 1, s, S Enter rescue mode\n"
4269 " q, Q Reload init daemon configuration\n"
4270 " u, U Reexecute init daemon\n",
4271 program_invocation_short_name);
4276 static int runlevel_help(void) {
4278 printf("%s [OPTIONS...]\n\n"
4279 "Prints the previous and current runlevel of the init system.\n\n"
4280 " --help Show this help\n",
4281 program_invocation_short_name);
4286 static int systemctl_parse_argv(int argc, char *argv[]) {
4290 ARG_IGNORE_DEPENDENCIES,
4306 ARG_NO_ASK_PASSWORD,
4313 static const struct option options[] = {
4314 { "help", no_argument, NULL, 'h' },
4315 { "version", no_argument, NULL, ARG_VERSION },
4316 { "type", required_argument, NULL, 't' },
4317 { "property", required_argument, NULL, 'p' },
4318 { "all", no_argument, NULL, 'a' },
4319 { "failed", no_argument, NULL, ARG_FAILED },
4320 { "full", no_argument, NULL, ARG_FULL },
4321 { "fail", no_argument, NULL, ARG_FAIL },
4322 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
4323 { "user", no_argument, NULL, ARG_USER },
4324 { "system", no_argument, NULL, ARG_SYSTEM },
4325 { "global", no_argument, NULL, ARG_GLOBAL },
4326 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
4327 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
4328 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
4329 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4330 { "quiet", no_argument, NULL, 'q' },
4331 { "order", no_argument, NULL, ARG_ORDER },
4332 { "require", no_argument, NULL, ARG_REQUIRE },
4333 { "root", required_argument, NULL, ARG_ROOT },
4334 { "force", no_argument, NULL, ARG_FORCE },
4335 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
4336 { "kill-mode", required_argument, NULL, ARG_KILL_MODE }, /* undocumented on purpose */
4337 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
4338 { "signal", required_argument, NULL, 's' },
4339 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
4340 { "host", required_argument, NULL, 'H' },
4341 { "privileged",no_argument, NULL, 'P' },
4342 { "runtime", no_argument, NULL, ARG_RUNTIME },
4343 { "lines", required_argument, NULL, 'n' },
4344 { "follow", no_argument, NULL, ARG_FOLLOW },
4345 { "output", required_argument, NULL, 'o' },
4346 { NULL, 0, NULL, 0 }
4354 while ((c = getopt_long(argc, argv, "ht:p:aqfs:H:Pn:o:", options, NULL)) >= 0) {
4363 puts(PACKAGE_STRING);
4365 puts(SYSTEMD_FEATURES);
4375 if (!(l = strv_append(arg_property, optarg)))
4378 strv_free(arg_property);
4381 /* If the user asked for a particular
4382 * property, show it to him, even if it is
4393 arg_job_mode = "fail";
4396 case ARG_IGNORE_DEPENDENCIES:
4397 arg_job_mode = "ignore-dependencies";
4401 arg_scope = UNIT_FILE_USER;
4405 arg_scope = UNIT_FILE_SYSTEM;
4409 arg_scope = UNIT_FILE_GLOBAL;
4413 arg_no_block = true;
4417 arg_no_legend = true;
4421 arg_no_pager = true;
4429 arg_dot = DOT_ORDER;
4433 arg_dot = DOT_REQUIRE;
4461 /* -f is short for both --follow and --force! */
4467 arg_no_reload = true;
4471 arg_kill_who = optarg;
4475 arg_kill_mode = optarg;
4479 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
4480 log_error("Failed to parse signal string %s.", optarg);
4485 case ARG_NO_ASK_PASSWORD:
4486 arg_ask_password = false;
4490 arg_transport = TRANSPORT_POLKIT;
4494 arg_transport = TRANSPORT_SSH;
4503 if (safe_atou(optarg, &arg_lines) < 0) {
4504 log_error("Failed to parse lines '%s'", optarg);
4510 arg_output = output_mode_from_string(optarg);
4511 if (arg_output < 0) {
4512 log_error("Unknown output '%s'.", optarg);
4521 log_error("Unknown option code %c", c);
4526 if (arg_transport != TRANSPORT_NORMAL && arg_scope != UNIT_FILE_SYSTEM) {
4527 log_error("Cannot access user instance remotely.");
4534 static int halt_parse_argv(int argc, char *argv[]) {
4543 static const struct option options[] = {
4544 { "help", no_argument, NULL, ARG_HELP },
4545 { "halt", no_argument, NULL, ARG_HALT },
4546 { "poweroff", no_argument, NULL, 'p' },
4547 { "reboot", no_argument, NULL, ARG_REBOOT },
4548 { "force", no_argument, NULL, 'f' },
4549 { "wtmp-only", no_argument, NULL, 'w' },
4550 { "no-wtmp", no_argument, NULL, 'd' },
4551 { "no-sync", no_argument, NULL, 'n' },
4552 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4553 { NULL, 0, NULL, 0 }
4561 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
4562 if (runlevel == '0' || runlevel == '6')
4565 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
4573 arg_action = ACTION_HALT;
4577 if (arg_action != ACTION_REBOOT)
4578 arg_action = ACTION_POWEROFF;
4582 arg_action = ACTION_REBOOT;
4607 /* Compatibility nops */
4614 log_error("Unknown option code %c", c);
4619 if (optind < argc) {
4620 log_error("Too many arguments.");
4627 static int parse_time_spec(const char *t, usec_t *_u) {
4631 if (streq(t, "now"))
4633 else if (!strchr(t, ':')) {
4636 if (safe_atou64(t, &u) < 0)
4639 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
4648 hour = strtol(t, &e, 10);
4649 if (errno != 0 || *e != ':' || hour < 0 || hour > 23)
4652 minute = strtol(e+1, &e, 10);
4653 if (errno != 0 || *e != 0 || minute < 0 || minute > 59)
4656 n = now(CLOCK_REALTIME);
4657 s = (time_t) (n / USEC_PER_SEC);
4660 assert_se(localtime_r(&s, &tm));
4662 tm.tm_hour = (int) hour;
4663 tm.tm_min = (int) minute;
4666 assert_se(s = mktime(&tm));
4668 *_u = (usec_t) s * USEC_PER_SEC;
4671 *_u += USEC_PER_DAY;
4677 static int shutdown_parse_argv(int argc, char *argv[]) {
4684 static const struct option options[] = {
4685 { "help", no_argument, NULL, ARG_HELP },
4686 { "halt", no_argument, NULL, 'H' },
4687 { "poweroff", no_argument, NULL, 'P' },
4688 { "reboot", no_argument, NULL, 'r' },
4689 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
4690 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4691 { NULL, 0, NULL, 0 }
4699 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
4707 arg_action = ACTION_HALT;
4711 arg_action = ACTION_POWEROFF;
4716 arg_action = ACTION_KEXEC;
4718 arg_action = ACTION_REBOOT;
4722 arg_action = ACTION_KEXEC;
4726 if (arg_action != ACTION_HALT)
4727 arg_action = ACTION_POWEROFF;
4740 /* Compatibility nops */
4744 arg_action = ACTION_CANCEL_SHUTDOWN;
4751 log_error("Unknown option code %c", c);
4756 if (argc > optind) {
4757 r = parse_time_spec(argv[optind], &arg_when);
4759 log_error("Failed to parse time specification: %s", argv[optind]);
4763 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
4765 /* We skip the time argument */
4766 if (argc > optind + 1)
4767 arg_wall = argv + optind + 1;
4774 static int telinit_parse_argv(int argc, char *argv[]) {
4781 static const struct option options[] = {
4782 { "help", no_argument, NULL, ARG_HELP },
4783 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4784 { NULL, 0, NULL, 0 }
4787 static const struct {
4791 { '0', ACTION_POWEROFF },
4792 { '6', ACTION_REBOOT },
4793 { '1', ACTION_RESCUE },
4794 { '2', ACTION_RUNLEVEL2 },
4795 { '3', ACTION_RUNLEVEL3 },
4796 { '4', ACTION_RUNLEVEL4 },
4797 { '5', ACTION_RUNLEVEL5 },
4798 { 's', ACTION_RESCUE },
4799 { 'S', ACTION_RESCUE },
4800 { 'q', ACTION_RELOAD },
4801 { 'Q', ACTION_RELOAD },
4802 { 'u', ACTION_REEXEC },
4803 { 'U', ACTION_REEXEC }
4812 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4827 log_error("Unknown option code %c", c);
4832 if (optind >= argc) {
4837 if (optind + 1 < argc) {
4838 log_error("Too many arguments.");
4842 if (strlen(argv[optind]) != 1) {
4843 log_error("Expected single character argument.");
4847 for (i = 0; i < ELEMENTSOF(table); i++)
4848 if (table[i].from == argv[optind][0])
4851 if (i >= ELEMENTSOF(table)) {
4852 log_error("Unknown command %s.", argv[optind]);
4856 arg_action = table[i].to;
4863 static int runlevel_parse_argv(int argc, char *argv[]) {
4869 static const struct option options[] = {
4870 { "help", no_argument, NULL, ARG_HELP },
4871 { NULL, 0, NULL, 0 }
4879 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4890 log_error("Unknown option code %c", c);
4895 if (optind < argc) {
4896 log_error("Too many arguments.");
4903 static int parse_argv(int argc, char *argv[]) {
4907 if (program_invocation_short_name) {
4909 if (strstr(program_invocation_short_name, "halt")) {
4910 arg_action = ACTION_HALT;
4911 return halt_parse_argv(argc, argv);
4912 } else if (strstr(program_invocation_short_name, "poweroff")) {
4913 arg_action = ACTION_POWEROFF;
4914 return halt_parse_argv(argc, argv);
4915 } else if (strstr(program_invocation_short_name, "reboot")) {
4917 arg_action = ACTION_KEXEC;
4919 arg_action = ACTION_REBOOT;
4920 return halt_parse_argv(argc, argv);
4921 } else if (strstr(program_invocation_short_name, "shutdown")) {
4922 arg_action = ACTION_POWEROFF;
4923 return shutdown_parse_argv(argc, argv);
4924 } else if (strstr(program_invocation_short_name, "init")) {
4926 if (sd_booted() > 0) {
4927 arg_action = ACTION_INVALID;
4928 return telinit_parse_argv(argc, argv);
4930 /* Hmm, so some other init system is
4931 * running, we need to forward this
4932 * request to it. For now we simply
4933 * guess that it is Upstart. */
4935 execv("/lib/upstart/telinit", argv);
4937 log_error("Couldn't find an alternative telinit implementation to spawn.");
4941 } else if (strstr(program_invocation_short_name, "runlevel")) {
4942 arg_action = ACTION_RUNLEVEL;
4943 return runlevel_parse_argv(argc, argv);
4947 arg_action = ACTION_SYSTEMCTL;
4948 return systemctl_parse_argv(argc, argv);
4951 static int action_to_runlevel(void) {
4953 static const char table[_ACTION_MAX] = {
4954 [ACTION_HALT] = '0',
4955 [ACTION_POWEROFF] = '0',
4956 [ACTION_REBOOT] = '6',
4957 [ACTION_RUNLEVEL2] = '2',
4958 [ACTION_RUNLEVEL3] = '3',
4959 [ACTION_RUNLEVEL4] = '4',
4960 [ACTION_RUNLEVEL5] = '5',
4961 [ACTION_RESCUE] = '1'
4964 assert(arg_action < _ACTION_MAX);
4966 return table[arg_action];
4969 static int talk_upstart(void) {
4970 DBusMessage *m = NULL, *reply = NULL;
4972 int previous, rl, r;
4974 env1_buf[] = "RUNLEVEL=X",
4975 env2_buf[] = "PREVLEVEL=X";
4976 char *env1 = env1_buf, *env2 = env2_buf;
4977 const char *emit = "runlevel";
4978 dbus_bool_t b_false = FALSE;
4979 DBusMessageIter iter, sub;
4980 DBusConnection *bus;
4982 dbus_error_init(&error);
4984 if (!(rl = action_to_runlevel()))
4987 if (utmp_get_runlevel(&previous, NULL) < 0)
4990 if (!(bus = dbus_connection_open_private("unix:abstract=/com/ubuntu/upstart", &error))) {
4991 if (dbus_error_has_name(&error, DBUS_ERROR_NO_SERVER)) {
4996 log_error("Failed to connect to Upstart bus: %s", bus_error_message(&error));
5001 if ((r = bus_check_peercred(bus)) < 0) {
5002 log_error("Failed to verify owner of bus.");
5006 if (!(m = dbus_message_new_method_call(
5007 "com.ubuntu.Upstart",
5008 "/com/ubuntu/Upstart",
5009 "com.ubuntu.Upstart0_6",
5012 log_error("Could not allocate message.");
5017 dbus_message_iter_init_append(m, &iter);
5019 env1_buf[sizeof(env1_buf)-2] = rl;
5020 env2_buf[sizeof(env2_buf)-2] = previous;
5022 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &emit) ||
5023 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub) ||
5024 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env1) ||
5025 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env2) ||
5026 !dbus_message_iter_close_container(&iter, &sub) ||
5027 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b_false)) {
5028 log_error("Could not append arguments to message.");
5033 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
5035 if (error_is_no_service(&error)) {
5040 log_error("Failed to issue method call: %s", bus_error_message(&error));
5049 dbus_message_unref(m);
5052 dbus_message_unref(reply);
5055 dbus_connection_flush(bus);
5056 dbus_connection_close(bus);
5057 dbus_connection_unref(bus);
5060 dbus_error_free(&error);
5065 static int talk_initctl(void) {
5066 struct init_request request;
5070 if (!(rl = action_to_runlevel()))
5074 request.magic = INIT_MAGIC;
5075 request.sleeptime = 0;
5076 request.cmd = INIT_CMD_RUNLVL;
5077 request.runlevel = rl;
5079 if ((fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY)) < 0) {
5081 if (errno == ENOENT)
5084 log_error("Failed to open "INIT_FIFO": %m");
5089 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
5090 close_nointr_nofail(fd);
5093 log_error("Failed to write to "INIT_FIFO": %m");
5094 return errno ? -errno : -EIO;
5100 static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
5102 static const struct {
5110 int (* const dispatch)(DBusConnection *bus, char **args);
5112 { "list-units", LESS, 1, list_units },
5113 { "list-unit-files", EQUAL, 1, list_unit_files },
5114 { "list-jobs", EQUAL, 1, list_jobs },
5115 { "clear-jobs", EQUAL, 1, daemon_reload },
5116 { "load", MORE, 2, load_unit },
5117 { "cancel", MORE, 2, cancel_job },
5118 { "start", MORE, 2, start_unit },
5119 { "stop", MORE, 2, start_unit },
5120 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5121 { "reload", MORE, 2, start_unit },
5122 { "restart", MORE, 2, start_unit },
5123 { "try-restart", MORE, 2, start_unit },
5124 { "reload-or-restart", MORE, 2, start_unit },
5125 { "reload-or-try-restart", MORE, 2, start_unit },
5126 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
5127 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5128 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
5129 { "isolate", EQUAL, 2, start_unit },
5130 { "kill", MORE, 2, kill_unit },
5131 { "is-active", MORE, 2, check_unit },
5132 { "check", MORE, 2, check_unit },
5133 { "show", MORE, 1, show },
5134 { "status", MORE, 2, show },
5135 { "dump", EQUAL, 1, dump },
5136 { "dot", EQUAL, 1, dot },
5137 { "snapshot", LESS, 2, snapshot },
5138 { "delete", MORE, 2, delete_snapshot },
5139 { "daemon-reload", EQUAL, 1, daemon_reload },
5140 { "daemon-reexec", EQUAL, 1, daemon_reload },
5141 { "show-environment", EQUAL, 1, show_enviroment },
5142 { "set-environment", MORE, 2, set_environment },
5143 { "unset-environment", MORE, 2, set_environment },
5144 { "halt", EQUAL, 1, start_special },
5145 { "poweroff", EQUAL, 1, start_special },
5146 { "reboot", EQUAL, 1, start_special },
5147 { "kexec", EQUAL, 1, start_special },
5148 { "suspend", EQUAL, 1, start_special },
5149 { "hibernate", EQUAL, 1, start_special },
5150 { "default", EQUAL, 1, start_special },
5151 { "rescue", EQUAL, 1, start_special },
5152 { "emergency", EQUAL, 1, start_special },
5153 { "exit", EQUAL, 1, start_special },
5154 { "reset-failed", MORE, 1, reset_failed },
5155 { "enable", MORE, 2, enable_unit },
5156 { "disable", MORE, 2, enable_unit },
5157 { "is-enabled", MORE, 2, unit_is_enabled },
5158 { "reenable", MORE, 2, enable_unit },
5159 { "preset", MORE, 2, enable_unit },
5160 { "mask", MORE, 2, enable_unit },
5161 { "unmask", MORE, 2, enable_unit },
5162 { "link", MORE, 2, enable_unit }
5172 left = argc - optind;
5175 /* Special rule: no arguments means "list-units" */
5178 if (streq(argv[optind], "help")) {
5183 for (i = 0; i < ELEMENTSOF(verbs); i++)
5184 if (streq(argv[optind], verbs[i].verb))
5187 if (i >= ELEMENTSOF(verbs)) {
5188 log_error("Unknown operation %s", argv[optind]);
5193 switch (verbs[i].argc_cmp) {
5196 if (left != verbs[i].argc) {
5197 log_error("Invalid number of arguments.");
5204 if (left < verbs[i].argc) {
5205 log_error("Too few arguments.");
5212 if (left > verbs[i].argc) {
5213 log_error("Too many arguments.");
5220 assert_not_reached("Unknown comparison operator.");
5223 /* Require a bus connection for all operations but
5225 if (!streq(verbs[i].verb, "enable") &&
5226 !streq(verbs[i].verb, "disable") &&
5227 !streq(verbs[i].verb, "is-enabled") &&
5228 !streq(verbs[i].verb, "list-unit-files") &&
5229 !streq(verbs[i].verb, "reenable") &&
5230 !streq(verbs[i].verb, "preset") &&
5231 !streq(verbs[i].verb, "mask") &&
5232 !streq(verbs[i].verb, "unmask") &&
5233 !streq(verbs[i].verb, "link")) {
5235 if (running_in_chroot() > 0) {
5236 log_info("Running in chroot, ignoring request.");
5240 if (((!streq(verbs[i].verb, "reboot") &&
5241 !streq(verbs[i].verb, "halt") &&
5242 !streq(verbs[i].verb, "poweroff")) || arg_force <= 0) && !bus) {
5243 log_error("Failed to get D-Bus connection: %s",
5244 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5250 if (!bus && !avoid_bus()) {
5251 log_error("Failed to get D-Bus connection: %s",
5252 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5257 return verbs[i].dispatch(bus, argv + optind);
5260 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
5262 struct msghdr msghdr;
5263 struct iovec iovec[2];
5264 union sockaddr_union sockaddr;
5265 struct sd_shutdown_command c;
5267 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
5274 c.dry_run = dry_run;
5278 sockaddr.sa.sa_family = AF_UNIX;
5279 strncpy(sockaddr.un.sun_path, "/run/systemd/shutdownd", sizeof(sockaddr.un.sun_path));
5282 msghdr.msg_name = &sockaddr;
5283 msghdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + sizeof("/run/systemd/shutdownd") - 1;
5286 iovec[0].iov_base = (char*) &c;
5287 iovec[0].iov_len = offsetof(struct sd_shutdown_command, wall_message);
5289 if (isempty(message))
5290 msghdr.msg_iovlen = 1;
5292 iovec[1].iov_base = (char*) message;
5293 iovec[1].iov_len = strlen(message);
5294 msghdr.msg_iovlen = 2;
5296 msghdr.msg_iov = iovec;
5298 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0) {
5299 close_nointr_nofail(fd);
5303 close_nointr_nofail(fd);
5307 static int reload_with_fallback(DBusConnection *bus) {
5310 /* First, try systemd via D-Bus. */
5311 if (daemon_reload(bus, NULL) >= 0)
5315 /* Nothing else worked, so let's try signals */
5316 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
5318 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
5319 log_error("kill() failed: %m");
5326 static int start_with_fallback(DBusConnection *bus) {
5329 /* First, try systemd via D-Bus. */
5330 if (start_unit(bus, NULL) >= 0)
5334 /* Hmm, talking to systemd via D-Bus didn't work. Then
5335 * let's try to talk to Upstart via D-Bus. */
5336 if (talk_upstart() > 0)
5339 /* Nothing else worked, so let's try
5341 if (talk_initctl() > 0)
5344 log_error("Failed to talk to init daemon.");
5348 warn_wall(arg_action);
5352 static void halt_now(enum action a) {
5354 /* Make sure C-A-D is handled by the kernel from this
5356 reboot(RB_ENABLE_CAD);
5361 log_info("Halting.");
5362 reboot(RB_HALT_SYSTEM);
5365 case ACTION_POWEROFF:
5366 log_info("Powering off.");
5367 reboot(RB_POWER_OFF);
5371 log_info("Rebooting.");
5372 reboot(RB_AUTOBOOT);
5376 assert_not_reached("Unknown halt action.");
5379 assert_not_reached("Uh? This shouldn't happen.");
5382 static int halt_main(DBusConnection *bus) {
5385 if (geteuid() != 0) {
5386 /* Try logind if we are a normal user and no special
5387 * mode applies. Maybe PolicyKit allows us to shutdown
5390 if (arg_when <= 0 &&
5393 (arg_action == ACTION_POWEROFF ||
5394 arg_action == ACTION_REBOOT)) {
5395 r = reboot_with_logind(bus, arg_action);
5400 log_error("Must be root.");
5407 m = strv_join(arg_wall, " ");
5408 r = send_shutdownd(arg_when,
5409 arg_action == ACTION_HALT ? 'H' :
5410 arg_action == ACTION_POWEROFF ? 'P' :
5411 arg_action == ACTION_KEXEC ? 'K' :
5419 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
5421 char date[FORMAT_TIMESTAMP_MAX];
5423 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
5424 format_timestamp(date, sizeof(date), arg_when));
5429 if (!arg_dry && !arg_force)
5430 return start_with_fallback(bus);
5433 if (sd_booted() > 0)
5434 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
5436 r = utmp_put_shutdown();
5438 log_warning("Failed to write utmp record: %s", strerror(-r));
5448 halt_now(arg_action);
5449 /* We should never reach this. */
5453 static int runlevel_main(void) {
5454 int r, runlevel, previous;
5456 r = utmp_get_runlevel(&runlevel, &previous);
5463 previous <= 0 ? 'N' : previous,
5464 runlevel <= 0 ? 'N' : runlevel);
5469 int main(int argc, char*argv[]) {
5470 int r, retval = EXIT_FAILURE;
5471 DBusConnection *bus = NULL;
5474 dbus_error_init(&error);
5476 log_parse_environment();
5479 r = parse_argv(argc, argv);
5483 retval = EXIT_SUCCESS;
5487 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
5488 * let's shortcut this */
5489 if (arg_action == ACTION_RUNLEVEL) {
5490 r = runlevel_main();
5491 retval = r < 0 ? EXIT_FAILURE : r;
5495 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
5496 log_info("Running in chroot, ignoring request.");
5502 if (arg_transport == TRANSPORT_NORMAL)
5503 bus_connect(arg_scope == UNIT_FILE_SYSTEM ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &bus, &private_bus, &error);
5504 else if (arg_transport == TRANSPORT_POLKIT) {
5505 bus_connect_system_polkit(&bus, &error);
5506 private_bus = false;
5507 } else if (arg_transport == TRANSPORT_SSH) {
5508 bus_connect_system_ssh(NULL, arg_host, &bus, &error);
5509 private_bus = false;
5511 assert_not_reached("Uh, invalid transport...");
5514 switch (arg_action) {
5516 case ACTION_SYSTEMCTL:
5517 r = systemctl_main(bus, argc, argv, &error);
5521 case ACTION_POWEROFF:
5527 case ACTION_RUNLEVEL2:
5528 case ACTION_RUNLEVEL3:
5529 case ACTION_RUNLEVEL4:
5530 case ACTION_RUNLEVEL5:
5532 case ACTION_EMERGENCY:
5533 case ACTION_DEFAULT:
5534 r = start_with_fallback(bus);
5539 r = reload_with_fallback(bus);
5542 case ACTION_CANCEL_SHUTDOWN:
5543 r = send_shutdownd(0, 0, false, false, NULL);
5546 case ACTION_INVALID:
5547 case ACTION_RUNLEVEL:
5549 assert_not_reached("Unknown action");
5552 retval = r < 0 ? EXIT_FAILURE : r;
5556 dbus_connection_flush(bus);
5557 dbus_connection_close(bus);
5558 dbus_connection_unref(bus);
5561 dbus_error_free(&error);
5565 strv_free(arg_property);
5568 ask_password_agent_close();
5569 polkit_agent_close();