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 const char *arg_load_state = NULL;
69 static char **arg_property = NULL;
70 static bool arg_all = false;
71 static const char *arg_job_mode = "replace";
72 static UnitFileScope arg_scope = UNIT_FILE_SYSTEM;
73 static bool arg_no_block = false;
74 static bool arg_no_legend = false;
75 static bool arg_no_pager = false;
76 static bool arg_no_wtmp = false;
77 static bool arg_no_sync = false;
78 static bool arg_no_wall = false;
79 static bool arg_no_reload = false;
80 static bool arg_dry = false;
81 static bool arg_quiet = false;
82 static bool arg_full = false;
83 static int arg_force = 0;
84 static bool arg_ask_password = true;
85 static bool arg_failed = false;
86 static bool arg_runtime = false;
87 static char **arg_wall = NULL;
88 static const char *arg_kill_who = 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();
175 static void polkit_agent_open_if_enabled(void) {
177 /* Open the polkit agent as a child process if necessary */
179 if (!arg_ask_password)
182 if (arg_scope != UNIT_FILE_SYSTEM)
189 static const char *ansi_highlight_red(bool b) {
194 return b ? ANSI_HIGHLIGHT_RED_ON : ANSI_HIGHLIGHT_OFF;
197 static const char *ansi_highlight_green(bool b) {
202 return b ? ANSI_HIGHLIGHT_GREEN_ON : ANSI_HIGHLIGHT_OFF;
205 static bool error_is_no_service(const DBusError *error) {
208 if (!dbus_error_is_set(error))
211 if (dbus_error_has_name(error, DBUS_ERROR_NAME_HAS_NO_OWNER))
214 if (dbus_error_has_name(error, DBUS_ERROR_SERVICE_UNKNOWN))
217 return startswith(error->name, "org.freedesktop.DBus.Error.Spawn.");
220 static int translate_bus_error_to_exit_status(int r, const DBusError *error) {
223 if (!dbus_error_is_set(error))
226 if (dbus_error_has_name(error, DBUS_ERROR_ACCESS_DENIED) ||
227 dbus_error_has_name(error, BUS_ERROR_ONLY_BY_DEPENDENCY) ||
228 dbus_error_has_name(error, BUS_ERROR_NO_ISOLATION) ||
229 dbus_error_has_name(error, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE))
230 return EXIT_NOPERMISSION;
232 if (dbus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT))
233 return EXIT_NOTINSTALLED;
235 if (dbus_error_has_name(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE) ||
236 dbus_error_has_name(error, BUS_ERROR_NOT_SUPPORTED))
237 return EXIT_NOTIMPLEMENTED;
239 if (dbus_error_has_name(error, BUS_ERROR_LOAD_FAILED))
240 return EXIT_NOTCONFIGURED;
248 static int bus_method_call_with_reply(DBusConnection *bus,
249 const char *destination,
251 const char *interface,
253 DBusMessage **return_reply,
254 DBusError *return_error,
255 int first_arg_type, ...) {
257 DBusMessage *m, *reply;
261 dbus_error_init(&error);
264 m = dbus_message_new_method_call(destination, path, interface, method);
270 va_start(ap, first_arg_type);
271 if (!dbus_message_append_args_valist(m, first_arg_type, ap)) {
273 dbus_message_unref(m);
279 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
280 dbus_message_unref(m);
282 log_error("Failed to issue method call: %s", bus_error_message(&error));
283 if (error_is_no_service(&error))
285 else if (dbus_error_has_name(&error, DBUS_ERROR_ACCESS_DENIED))
287 else if (dbus_error_has_name(&error, DBUS_ERROR_NO_REPLY))
294 *return_reply = reply;
296 dbus_message_unref(reply);
301 dbus_error_free(&error);
306 static void warn_wall(enum action a) {
307 static const char *table[_ACTION_MAX] = {
308 [ACTION_HALT] = "The system is going down for system halt NOW!",
309 [ACTION_REBOOT] = "The system is going down for reboot NOW!",
310 [ACTION_POWEROFF] = "The system is going down for power-off NOW!",
311 [ACTION_KEXEC] = "The system is going down for kexec reboot NOW!",
312 [ACTION_RESCUE] = "The system is going down to rescue mode NOW!",
313 [ACTION_EMERGENCY] = "The system is going down to emergency mode NOW!",
314 [ACTION_CANCEL_SHUTDOWN] = "The system shutdown has been cancelled NOW!"
323 p = strv_join(arg_wall, " ");
325 log_error("Failed to join strings.");
341 utmp_wall(table[a], NULL);
344 static bool avoid_bus(void) {
346 if (running_in_chroot() > 0)
349 if (sd_booted() <= 0)
352 if (!isempty(arg_root))
355 if (arg_scope == UNIT_FILE_GLOBAL)
363 const char *description;
364 const char *load_state;
365 const char *active_state;
366 const char *sub_state;
367 const char *following;
368 const char *unit_path;
370 const char *job_type;
371 const char *job_path;
374 static int compare_unit_info(const void *a, const void *b) {
376 const struct unit_info *u = a, *v = b;
378 d1 = strrchr(u->id, '.');
379 d2 = strrchr(v->id, '.');
384 if ((r = strcasecmp(d1, d2)) != 0)
388 return strcasecmp(u->id, v->id);
391 static bool output_show_unit(const struct unit_info *u) {
395 return streq(u->active_state, "failed");
397 return (!arg_type || ((dot = strrchr(u->id, '.')) &&
398 streq(dot+1, arg_type))) &&
399 (!arg_load_state || streq(u->load_state, arg_load_state)) &&
400 (arg_all || !(streq(u->active_state, "inactive")
401 || u->following[0]) || u->job_id > 0);
404 static void output_units_list(const struct unit_info *unit_infos, unsigned c) {
405 unsigned id_len, max_id_len, active_len, sub_len, job_len, desc_len, n_shown = 0;
406 const struct unit_info *u;
408 max_id_len = sizeof("UNIT")-1;
409 active_len = sizeof("ACTIVE")-1;
410 sub_len = sizeof("SUB")-1;
411 job_len = sizeof("JOB")-1;
414 for (u = unit_infos; u < unit_infos + c; u++) {
415 if (!output_show_unit(u))
418 max_id_len = MAX(max_id_len, strlen(u->id));
419 active_len = MAX(active_len, strlen(u->active_state));
420 sub_len = MAX(sub_len, strlen(u->sub_state));
422 job_len = MAX(job_len, strlen(u->job_type));
427 id_len = MIN(max_id_len, 25);
428 basic_len = 5 + id_len + 6 + active_len + sub_len + job_len;
429 if (basic_len < (unsigned) columns()) {
430 unsigned extra_len, incr;
431 extra_len = columns() - basic_len;
432 /* Either UNIT already got 25, or is fully satisfied.
433 * Grant up to 25 to DESC now. */
434 incr = MIN(extra_len, 25);
437 /* split the remaining space between UNIT and DESC,
438 * but do not give UNIT more than it needs. */
440 incr = MIN(extra_len / 2, max_id_len - id_len);
442 desc_len += extra_len - incr;
448 if (!arg_no_legend) {
449 printf("%-*s %-6s %-*s %-*s %-*s ", id_len, "UNIT", "LOAD",
450 active_len, "ACTIVE", sub_len, "SUB", job_len, "JOB");
451 if (!arg_full && arg_no_pager)
452 printf("%.*s\n", desc_len, "DESCRIPTION");
454 printf("%s\n", "DESCRIPTION");
457 for (u = unit_infos; u < unit_infos + c; u++) {
459 const char *on_loaded, *off_loaded;
460 const char *on_active, *off_active;
462 if (!output_show_unit(u))
467 if (streq(u->load_state, "error")) {
468 on_loaded = ansi_highlight_red(true);
469 off_loaded = ansi_highlight_red(false);
471 on_loaded = off_loaded = "";
473 if (streq(u->active_state, "failed")) {
474 on_active = ansi_highlight_red(true);
475 off_active = ansi_highlight_red(false);
477 on_active = off_active = "";
479 e = arg_full ? NULL : ellipsize(u->id, id_len, 33);
481 printf("%-*s %s%-6s%s %s%-*s %-*s%s %-*s ",
482 id_len, e ? e : u->id,
483 on_loaded, u->load_state, off_loaded,
484 on_active, active_len, u->active_state,
485 sub_len, u->sub_state, off_active,
486 job_len, u->job_id ? u->job_type : "");
487 if (!arg_full && arg_no_pager)
488 printf("%.*s\n", desc_len, u->description);
490 printf("%s\n", u->description);
495 if (!arg_no_legend) {
496 printf("\nLOAD = Reflects whether the unit definition was properly loaded.\n"
497 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
498 "SUB = The low-level unit activation state, values depend on unit type.\n"
499 "JOB = Pending job for the unit.\n");
502 printf("\n%u units listed.\n", n_shown);
504 printf("\n%u units listed. Pass --all to see inactive units, too.\n", n_shown);
508 static int list_units(DBusConnection *bus, char **args) {
509 DBusMessage *m = NULL, *reply = NULL;
512 DBusMessageIter iter, sub, sub2;
513 unsigned c = 0, n_units = 0;
514 struct unit_info *unit_infos = NULL;
516 dbus_error_init(&error);
520 pager_open_if_enabled();
522 if (!(m = dbus_message_new_method_call(
523 "org.freedesktop.systemd1",
524 "/org/freedesktop/systemd1",
525 "org.freedesktop.systemd1.Manager",
527 log_error("Could not allocate message.");
531 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
532 log_error("Failed to issue method call: %s", bus_error_message(&error));
537 if (!dbus_message_iter_init(reply, &iter) ||
538 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
539 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
540 log_error("Failed to parse reply.");
545 dbus_message_iter_recurse(&iter, &sub);
547 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
550 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
551 log_error("Failed to parse reply.");
559 n_units = MAX(2*c, 16);
560 w = realloc(unit_infos, sizeof(struct unit_info) * n_units);
563 log_error("Failed to allocate unit array.");
573 dbus_message_iter_recurse(&sub, &sub2);
575 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->id, true) < 0 ||
576 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->description, true) < 0 ||
577 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->load_state, true) < 0 ||
578 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->active_state, true) < 0 ||
579 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->sub_state, true) < 0 ||
580 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->following, true) < 0 ||
581 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &u->unit_path, true) < 0 ||
582 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &u->job_id, true) < 0 ||
583 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->job_type, true) < 0 ||
584 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &u->job_path, false) < 0) {
585 log_error("Failed to parse reply.");
590 dbus_message_iter_next(&sub);
595 qsort(unit_infos, c, sizeof(struct unit_info), compare_unit_info);
596 output_units_list(unit_infos, c);
603 dbus_message_unref(m);
606 dbus_message_unref(reply);
610 dbus_error_free(&error);
615 static int compare_unit_file_list(const void *a, const void *b) {
617 const UnitFileList *u = a, *v = b;
619 d1 = strrchr(u->path, '.');
620 d2 = strrchr(v->path, '.');
625 r = strcasecmp(d1, d2);
630 return strcasecmp(path_get_file_name(u->path), path_get_file_name(v->path));
633 static bool output_show_unit_file(const UnitFileList *u) {
636 return !arg_type || ((dot = strrchr(u->path, '.')) && streq(dot+1, arg_type));
639 static void output_unit_file_list(const UnitFileList *units, unsigned c) {
640 unsigned max_id_len, id_cols, state_cols, n_shown = 0;
641 const UnitFileList *u;
643 max_id_len = sizeof("UNIT FILE")-1;
644 state_cols = sizeof("STATE")-1;
645 for (u = units; u < units + c; u++) {
646 if (!output_show_unit_file(u))
649 max_id_len = MAX(max_id_len, strlen(path_get_file_name(u->path)));
650 state_cols = MAX(state_cols, strlen(unit_file_state_to_string(u->state)));
655 id_cols = MIN(max_id_len, 25);
656 basic_cols = 1 + id_cols + state_cols;
657 if (basic_cols < (unsigned) columns())
658 id_cols += MIN(columns() - basic_cols, max_id_len - id_cols);
660 id_cols = max_id_len;
663 printf("%-*s %-*s\n", id_cols, "UNIT FILE", state_cols, "STATE");
665 for (u = units; u < units + c; u++) {
667 const char *on, *off;
670 if (!output_show_unit_file(u))
675 if (u->state == UNIT_FILE_MASKED ||
676 u->state == UNIT_FILE_MASKED_RUNTIME ||
677 u->state == UNIT_FILE_DISABLED) {
678 on = ansi_highlight_red(true);
679 off = ansi_highlight_red(false);
680 } else if (u->state == UNIT_FILE_ENABLED) {
681 on = ansi_highlight_green(true);
682 off = ansi_highlight_green(false);
686 id = path_get_file_name(u->path);
688 e = arg_full ? NULL : ellipsize(id, id_cols, 33);
690 printf("%-*s %s%-*s%s\n",
692 on, state_cols, unit_file_state_to_string(u->state), off);
698 printf("\n%u unit files listed.\n", n_shown);
701 static int list_unit_files(DBusConnection *bus, char **args) {
702 DBusMessage *m = NULL, *reply = NULL;
705 DBusMessageIter iter, sub, sub2;
706 unsigned c = 0, n_units = 0;
707 UnitFileList *units = NULL;
709 dbus_error_init(&error);
711 pager_open_if_enabled();
718 h = hashmap_new(string_hash_func, string_compare_func);
722 r = unit_file_get_list(arg_scope, arg_root, h);
724 unit_file_list_free(h);
725 log_error("Failed to get unit file list: %s", strerror(-r));
729 n_units = hashmap_size(h);
730 units = new(UnitFileList, n_units);
732 unit_file_list_free(h);
736 HASHMAP_FOREACH(u, h, i) {
737 memcpy(units + c++, u, sizeof(UnitFileList));
745 m = dbus_message_new_method_call(
746 "org.freedesktop.systemd1",
747 "/org/freedesktop/systemd1",
748 "org.freedesktop.systemd1.Manager",
751 log_error("Could not allocate message.");
755 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
757 log_error("Failed to issue method call: %s", bus_error_message(&error));
762 if (!dbus_message_iter_init(reply, &iter) ||
763 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
764 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
765 log_error("Failed to parse reply.");
770 dbus_message_iter_recurse(&iter, &sub);
772 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
776 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
777 log_error("Failed to parse reply.");
785 n_units = MAX(2*c, 16);
786 w = realloc(units, sizeof(struct UnitFileList) * n_units);
789 log_error("Failed to allocate unit array.");
799 dbus_message_iter_recurse(&sub, &sub2);
801 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->path, true) < 0 ||
802 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, false) < 0) {
803 log_error("Failed to parse reply.");
808 u->state = unit_file_state_from_string(state);
810 dbus_message_iter_next(&sub);
816 qsort(units, c, sizeof(UnitFileList), compare_unit_file_list);
817 output_unit_file_list(units, c);
824 dbus_message_unref(m);
827 dbus_message_unref(reply);
831 dbus_error_free(&error);
836 static int dot_one_property(const char *name, const char *prop, DBusMessageIter *iter) {
837 static const char * const colors[] = {
838 "Requires", "[color=\"black\"]",
839 "RequiresOverridable", "[color=\"black\"]",
840 "Requisite", "[color=\"darkblue\"]",
841 "RequisiteOverridable", "[color=\"darkblue\"]",
842 "Wants", "[color=\"grey66\"]",
843 "Conflicts", "[color=\"red\"]",
844 "ConflictedBy", "[color=\"red\"]",
845 "After", "[color=\"green\"]"
848 const char *c = NULL;
855 for (i = 0; i < ELEMENTSOF(colors); i += 2)
856 if (streq(colors[i], prop)) {
864 if (arg_dot != DOT_ALL)
865 if ((arg_dot == DOT_ORDER) != streq(prop, "After"))
868 switch (dbus_message_iter_get_arg_type(iter)) {
870 case DBUS_TYPE_ARRAY:
872 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING) {
875 dbus_message_iter_recurse(iter, &sub);
877 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
880 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING);
881 dbus_message_iter_get_basic(&sub, &s);
882 printf("\t\"%s\"->\"%s\" %s;\n", name, s, c);
884 dbus_message_iter_next(&sub);
894 static int dot_one(DBusConnection *bus, const char *name, const char *path) {
895 DBusMessage *m = NULL, *reply = NULL;
896 const char *interface = "org.freedesktop.systemd1.Unit";
899 DBusMessageIter iter, sub, sub2, sub3;
904 dbus_error_init(&error);
906 if (!(m = dbus_message_new_method_call(
907 "org.freedesktop.systemd1",
909 "org.freedesktop.DBus.Properties",
911 log_error("Could not allocate message.");
916 if (!dbus_message_append_args(m,
917 DBUS_TYPE_STRING, &interface,
918 DBUS_TYPE_INVALID)) {
919 log_error("Could not append arguments to message.");
924 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
925 log_error("Failed to issue method call: %s", bus_error_message(&error));
930 if (!dbus_message_iter_init(reply, &iter) ||
931 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
932 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
933 log_error("Failed to parse reply.");
938 dbus_message_iter_recurse(&iter, &sub);
940 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
943 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_DICT_ENTRY) {
944 log_error("Failed to parse reply.");
949 dbus_message_iter_recurse(&sub, &sub2);
951 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &prop, true) < 0) {
952 log_error("Failed to parse reply.");
957 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
958 log_error("Failed to parse reply.");
963 dbus_message_iter_recurse(&sub2, &sub3);
965 if (dot_one_property(name, prop, &sub3)) {
966 log_error("Failed to parse reply.");
971 dbus_message_iter_next(&sub);
978 dbus_message_unref(m);
981 dbus_message_unref(reply);
983 dbus_error_free(&error);
988 static int dot(DBusConnection *bus, char **args) {
989 DBusMessage *m = NULL, *reply = NULL;
992 DBusMessageIter iter, sub, sub2;
994 dbus_error_init(&error);
998 if (!(m = dbus_message_new_method_call(
999 "org.freedesktop.systemd1",
1000 "/org/freedesktop/systemd1",
1001 "org.freedesktop.systemd1.Manager",
1003 log_error("Could not allocate message.");
1007 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
1008 log_error("Failed to issue method call: %s", bus_error_message(&error));
1013 if (!dbus_message_iter_init(reply, &iter) ||
1014 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
1015 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
1016 log_error("Failed to parse reply.");
1021 printf("digraph systemd {\n");
1023 dbus_message_iter_recurse(&iter, &sub);
1024 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1025 const char *id, *description, *load_state, *active_state, *sub_state, *following, *unit_path;
1027 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
1028 log_error("Failed to parse reply.");
1033 dbus_message_iter_recurse(&sub, &sub2);
1035 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &id, true) < 0 ||
1036 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &description, true) < 0 ||
1037 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &load_state, true) < 0 ||
1038 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &active_state, true) < 0 ||
1039 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &sub_state, true) < 0 ||
1040 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &following, true) < 0 ||
1041 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, true) < 0) {
1042 log_error("Failed to parse reply.");
1047 if ((r = dot_one(bus, id, unit_path)) < 0)
1050 /* printf("\t\"%s\";\n", id); */
1051 dbus_message_iter_next(&sub);
1056 log_info(" Color legend: black = Requires\n"
1057 " dark blue = Requisite\n"
1058 " dark grey = Wants\n"
1059 " red = Conflicts\n"
1060 " green = After\n");
1063 log_notice("-- You probably want to process this output with graphviz' dot tool.\n"
1064 "-- Try a shell pipeline like 'systemctl dot | dot -Tsvg > systemd.svg'!\n");
1070 dbus_message_unref(m);
1073 dbus_message_unref(reply);
1075 dbus_error_free(&error);
1080 static int list_jobs(DBusConnection *bus, char **args) {
1081 DBusMessage *m = NULL, *reply = NULL;
1084 DBusMessageIter iter, sub, sub2;
1087 dbus_error_init(&error);
1091 pager_open_if_enabled();
1093 if (!(m = dbus_message_new_method_call(
1094 "org.freedesktop.systemd1",
1095 "/org/freedesktop/systemd1",
1096 "org.freedesktop.systemd1.Manager",
1098 log_error("Could not allocate message.");
1102 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
1103 log_error("Failed to issue method call: %s", bus_error_message(&error));
1108 if (!dbus_message_iter_init(reply, &iter) ||
1109 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
1110 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
1111 log_error("Failed to parse reply.");
1116 dbus_message_iter_recurse(&iter, &sub);
1119 printf("%4s %-25s %-15s %-7s\n", "JOB", "UNIT", "TYPE", "STATE");
1121 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1122 const char *name, *type, *state, *job_path, *unit_path;
1126 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
1127 log_error("Failed to parse reply.");
1132 dbus_message_iter_recurse(&sub, &sub2);
1134 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &id, true) < 0 ||
1135 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
1136 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
1137 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, true) < 0 ||
1138 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &job_path, true) < 0 ||
1139 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, false) < 0) {
1140 log_error("Failed to parse reply.");
1145 e = arg_full ? NULL : ellipsize(name, 25, 33);
1146 printf("%4u %-25s %-15s %-7s\n", id, e ? e : name, type, state);
1151 dbus_message_iter_next(&sub);
1155 printf("\n%u jobs listed.\n", k);
1161 dbus_message_unref(m);
1164 dbus_message_unref(reply);
1166 dbus_error_free(&error);
1171 static int load_unit(DBusConnection *bus, char **args) {
1172 DBusMessage *m = NULL;
1177 dbus_error_init(&error);
1182 STRV_FOREACH(name, args+1) {
1187 if (!(m = dbus_message_new_method_call(
1188 "org.freedesktop.systemd1",
1189 "/org/freedesktop/systemd1",
1190 "org.freedesktop.systemd1.Manager",
1192 log_error("Could not allocate message.");
1197 n = unit_name_mangle(*name);
1198 b = dbus_message_append_args(m,
1199 DBUS_TYPE_STRING, n ? &n : name,
1203 log_error("Could not append arguments to message.");
1208 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
1210 log_error("Failed to issue method call: %s", bus_error_message(&error));
1215 dbus_message_unref(m);
1216 dbus_message_unref(reply);
1225 dbus_message_unref(m);
1227 dbus_error_free(&error);
1232 static int cancel_job(DBusConnection *bus, char **args) {
1233 DBusMessage *m = NULL, *reply = NULL;
1238 dbus_error_init(&error);
1243 if (strv_length(args) <= 1)
1244 return daemon_reload(bus, args);
1246 STRV_FOREACH(name, args+1) {
1250 if (!(m = dbus_message_new_method_call(
1251 "org.freedesktop.systemd1",
1252 "/org/freedesktop/systemd1",
1253 "org.freedesktop.systemd1.Manager",
1255 log_error("Could not allocate message.");
1260 if ((r = safe_atou(*name, &id)) < 0) {
1261 log_error("Failed to parse job id: %s", strerror(-r));
1265 assert_cc(sizeof(uint32_t) == sizeof(id));
1266 if (!dbus_message_append_args(m,
1267 DBUS_TYPE_UINT32, &id,
1268 DBUS_TYPE_INVALID)) {
1269 log_error("Could not append arguments to message.");
1274 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
1275 log_error("Failed to issue method call: %s", bus_error_message(&error));
1280 if (!dbus_message_get_args(reply, &error,
1281 DBUS_TYPE_OBJECT_PATH, &path,
1282 DBUS_TYPE_INVALID)) {
1283 log_error("Failed to parse reply: %s", bus_error_message(&error));
1288 dbus_message_unref(m);
1289 if (!(m = dbus_message_new_method_call(
1290 "org.freedesktop.systemd1",
1292 "org.freedesktop.systemd1.Job",
1294 log_error("Could not allocate message.");
1299 dbus_message_unref(reply);
1300 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
1301 log_error("Failed to issue method call: %s", bus_error_message(&error));
1306 dbus_message_unref(m);
1307 dbus_message_unref(reply);
1315 dbus_message_unref(m);
1318 dbus_message_unref(reply);
1320 dbus_error_free(&error);
1325 static bool need_daemon_reload(DBusConnection *bus, const char *unit) {
1326 DBusMessage *m = NULL, *reply = NULL;
1327 dbus_bool_t b = FALSE;
1328 DBusMessageIter iter, sub;
1330 *interface = "org.freedesktop.systemd1.Unit",
1331 *property = "NeedDaemonReload",
1336 /* We ignore all errors here, since this is used to show a warning only */
1338 m = dbus_message_new_method_call(
1339 "org.freedesktop.systemd1",
1340 "/org/freedesktop/systemd1",
1341 "org.freedesktop.systemd1.Manager",
1346 n = unit_name_mangle(unit);
1347 k = dbus_message_append_args(m,
1348 DBUS_TYPE_STRING, n ? (const char**) &n : &unit,
1354 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, NULL);
1358 if (!dbus_message_get_args(reply, NULL,
1359 DBUS_TYPE_OBJECT_PATH, &path,
1363 dbus_message_unref(m);
1364 m = dbus_message_new_method_call(
1365 "org.freedesktop.systemd1",
1367 "org.freedesktop.DBus.Properties",
1372 if (!dbus_message_append_args(m,
1373 DBUS_TYPE_STRING, &interface,
1374 DBUS_TYPE_STRING, &property,
1375 DBUS_TYPE_INVALID)) {
1379 dbus_message_unref(reply);
1380 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, NULL);
1384 if (!dbus_message_iter_init(reply, &iter) ||
1385 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
1388 dbus_message_iter_recurse(&iter, &sub);
1390 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_BOOLEAN)
1393 dbus_message_iter_get_basic(&sub, &b);
1397 dbus_message_unref(m);
1400 dbus_message_unref(reply);
1405 typedef struct WaitData {
1410 static DBusHandlerResult wait_filter(DBusConnection *connection, DBusMessage *message, void *data) {
1418 dbus_error_init(&error);
1420 log_debug("Got D-Bus request: %s.%s() on %s",
1421 dbus_message_get_interface(message),
1422 dbus_message_get_member(message),
1423 dbus_message_get_path(message));
1425 if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
1426 log_error("Warning! D-Bus connection terminated.");
1427 dbus_connection_close(connection);
1429 } else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
1431 const char *path, *result, *unit;
1432 dbus_bool_t success = true;
1434 if (dbus_message_get_args(message, &error,
1435 DBUS_TYPE_UINT32, &id,
1436 DBUS_TYPE_OBJECT_PATH, &path,
1437 DBUS_TYPE_STRING, &unit,
1438 DBUS_TYPE_STRING, &result,
1439 DBUS_TYPE_INVALID)) {
1442 p = set_remove(d->set, (char*) path);
1446 d->result = strdup(result);
1451 dbus_error_free(&error);
1452 if (dbus_message_get_args(message, &error,
1453 DBUS_TYPE_UINT32, &id,
1454 DBUS_TYPE_OBJECT_PATH, &path,
1455 DBUS_TYPE_STRING, &result,
1456 DBUS_TYPE_INVALID)) {
1459 /* Compatibility with older systemd versions <
1460 * 183 during upgrades. This should be dropped
1462 p = set_remove(d->set, (char*) path);
1466 d->result = strdup(result);
1471 dbus_error_free(&error);
1472 if (dbus_message_get_args(message, &error,
1473 DBUS_TYPE_UINT32, &id,
1474 DBUS_TYPE_OBJECT_PATH, &path,
1475 DBUS_TYPE_BOOLEAN, &success,
1476 DBUS_TYPE_INVALID)) {
1479 /* Compatibility with older systemd versions <
1480 * 19 during upgrades. This should be dropped
1483 p = set_remove(d->set, (char*) path);
1487 d->result = strdup("failed");
1493 log_error("Failed to parse message: %s", bus_error_message(&error));
1497 dbus_error_free(&error);
1498 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1501 static int enable_wait_for_jobs(DBusConnection *bus) {
1509 dbus_error_init(&error);
1510 dbus_bus_add_match(bus,
1512 "sender='org.freedesktop.systemd1',"
1513 "interface='org.freedesktop.systemd1.Manager',"
1514 "member='JobRemoved',"
1515 "path='/org/freedesktop/systemd1'",
1518 if (dbus_error_is_set(&error)) {
1519 log_error("Failed to add match: %s", bus_error_message(&error));
1520 dbus_error_free(&error);
1524 /* This is slightly dirty, since we don't undo the match registrations. */
1528 static int wait_for_jobs(DBusConnection *bus, Set *s) {
1538 if (!dbus_connection_add_filter(bus, wait_filter, &d, NULL)) {
1539 log_error("Failed to add filter.");
1544 while (!set_isempty(s) &&
1545 dbus_connection_read_write_dispatch(bus, -1))
1548 if (!arg_quiet && d.result) {
1549 if (streq(d.result, "timeout"))
1550 log_error("Job timed out.");
1551 else if (streq(d.result, "canceled"))
1552 log_error("Job canceled.");
1553 else if (streq(d.result, "dependency"))
1554 log_error("A dependency job failed. See system journal for details.");
1555 else if (!streq(d.result, "done") && !streq(d.result, "skipped"))
1556 log_error("Job failed. See system journal and 'systemctl status' for details.");
1559 if (streq_ptr(d.result, "timeout"))
1561 else if (streq_ptr(d.result, "canceled"))
1563 else if (!streq_ptr(d.result, "done") && !streq_ptr(d.result, "skipped"))
1571 /* This is slightly dirty, since we don't undo the filter registration. */
1576 static int check_one_unit(DBusConnection *bus, char *name, bool quiet) {
1577 DBusMessage *m = NULL, *reply = NULL;
1579 DBusMessageIter iter, sub;
1581 *interface = "org.freedesktop.systemd1.Unit",
1582 *property = "ActiveState";
1583 const char *path = NULL;
1585 int r = 3; /* According to LSB: "program is not running" */
1592 dbus_error_init(&error);
1594 m = dbus_message_new_method_call(
1595 "org.freedesktop.systemd1",
1596 "/org/freedesktop/systemd1",
1597 "org.freedesktop.systemd1.Manager",
1600 log_error("Could not allocate message.");
1605 n = unit_name_mangle(name);
1606 b = dbus_message_append_args(m,
1607 DBUS_TYPE_STRING, n ? &n : &name,
1611 log_error("Could not append arguments to message.");
1616 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
1618 /* Hmm, cannot figure out anything about this unit... */
1625 if (!dbus_message_get_args(reply, &error,
1626 DBUS_TYPE_OBJECT_PATH, &path,
1627 DBUS_TYPE_INVALID)) {
1628 log_error("Failed to parse reply: %s", bus_error_message(&error));
1633 dbus_message_unref(m);
1634 m = dbus_message_new_method_call(
1635 "org.freedesktop.systemd1",
1637 "org.freedesktop.DBus.Properties",
1640 log_error("Could not allocate message.");
1645 if (!dbus_message_append_args(m,
1646 DBUS_TYPE_STRING, &interface,
1647 DBUS_TYPE_STRING, &property,
1648 DBUS_TYPE_INVALID)) {
1649 log_error("Could not append arguments to message.");
1654 dbus_message_unref(reply);
1655 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
1657 log_error("Failed to issue method call: %s", bus_error_message(&error));
1662 if (!dbus_message_iter_init(reply, &iter) ||
1663 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1664 log_error("Failed to parse reply.");
1669 dbus_message_iter_recurse(&iter, &sub);
1671 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1672 log_error("Failed to parse reply.");
1677 dbus_message_iter_get_basic(&sub, &state);
1682 if (streq(state, "active") || streq(state, "reloading"))
1687 dbus_message_unref(m);
1690 dbus_message_unref(reply);
1692 dbus_error_free(&error);
1697 static void check_triggering_units(
1698 DBusConnection *bus,
1699 const char *unit_name) {
1702 DBusMessage *m = NULL, *reply = NULL;
1703 DBusMessageIter iter, sub;
1704 char *service_trigger = NULL;
1705 const char *interface = "org.freedesktop.systemd1.Unit",
1706 *triggered_by_property = "TriggeredBy";
1708 char *unit_path = NULL, *n = NULL;
1709 bool print_warning_label = true;
1711 dbus_error_init(&error);
1713 n = unit_name_mangle(unit_name);
1714 unit_path = unit_dbus_path_from_name(n ? n : unit_name);
1717 log_error("Could not allocate dbus path.");
1721 m = dbus_message_new_method_call("org.freedesktop.systemd1",
1723 "org.freedesktop.DBus.Properties",
1726 log_error("Could not allocate message.");
1730 if (!dbus_message_append_args(m,
1731 DBUS_TYPE_STRING, &interface,
1732 DBUS_TYPE_STRING, &triggered_by_property,
1733 DBUS_TYPE_INVALID)) {
1734 log_error("Could not append arguments to message.");
1738 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
1740 log_error("Failed to issue method call: %s", bus_error_message(&error));
1744 if (!dbus_message_iter_init(reply, &iter) ||
1745 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1746 log_error("Failed to parse reply: %s", bus_error_message(&error));
1751 dbus_message_iter_recurse(&iter, &sub);
1752 dbus_message_iter_recurse(&sub, &iter);
1755 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1758 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1759 log_error("Failed to parse reply: %s", bus_error_message(&error));
1763 dbus_message_iter_get_basic(&sub, &service_trigger);
1765 r = check_one_unit(bus, service_trigger, true);
1769 if (print_warning_label) {
1770 log_warning("Warning: Stopping %s, but it can still be activated by:", unit_name);
1771 print_warning_label = false;
1773 log_warning(" %s", service_trigger);
1776 dbus_message_iter_next(&sub);
1780 dbus_message_unref(m);
1783 dbus_message_unref(reply);
1785 dbus_error_free(&error);
1790 static int start_unit_one(
1791 DBusConnection *bus,
1798 DBusMessage *m = NULL, *reply = NULL;
1809 assert(arg_no_block || s);
1811 m = dbus_message_new_method_call(
1812 "org.freedesktop.systemd1",
1813 "/org/freedesktop/systemd1",
1814 "org.freedesktop.systemd1.Manager",
1817 log_error("Could not allocate message.");
1822 n = unit_name_mangle(name);
1823 b = dbus_message_append_args(m,
1824 DBUS_TYPE_STRING, n ? (const char **) &n : &name,
1825 DBUS_TYPE_STRING, &mode,
1829 log_error("Could not append arguments to message.");
1834 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, error);
1837 if (arg_action != ACTION_SYSTEMCTL && error_is_no_service(error)) {
1838 /* There's always a fallback possible for
1839 * legacy actions. */
1844 log_error("Failed to issue method call: %s", bus_error_message(error));
1849 if (!dbus_message_get_args(reply, error,
1850 DBUS_TYPE_OBJECT_PATH, &path,
1851 DBUS_TYPE_INVALID)) {
1852 log_error("Failed to parse reply: %s", bus_error_message(error));
1857 if (need_daemon_reload(bus, name))
1858 log_warning("Warning: Unit file of created job changed on disk, 'systemctl %s daemon-reload' recommended.",
1859 arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
1861 if (!arg_no_block) {
1864 if (!(p = strdup(path))) {
1865 log_error("Failed to duplicate path.");
1870 if ((r = set_put(s, p)) < 0) {
1872 log_error("Failed to add path to set.");
1877 /* When stopping a unit warn if it can still be triggered by
1878 * another active unit (socket, path, timer) */
1879 if (!arg_quiet && streq(method, "StopUnit"))
1880 check_triggering_units(bus, name);
1886 dbus_message_unref(m);
1889 dbus_message_unref(reply);
1894 static enum action verb_to_action(const char *verb) {
1895 if (streq(verb, "halt"))
1897 else if (streq(verb, "poweroff"))
1898 return ACTION_POWEROFF;
1899 else if (streq(verb, "reboot"))
1900 return ACTION_REBOOT;
1901 else if (streq(verb, "kexec"))
1902 return ACTION_KEXEC;
1903 else if (streq(verb, "rescue"))
1904 return ACTION_RESCUE;
1905 else if (streq(verb, "emergency"))
1906 return ACTION_EMERGENCY;
1907 else if (streq(verb, "default"))
1908 return ACTION_DEFAULT;
1909 else if (streq(verb, "exit"))
1911 else if (streq(verb, "suspend"))
1912 return ACTION_SUSPEND;
1913 else if (streq(verb, "hibernate"))
1914 return ACTION_HIBERNATE;
1916 return ACTION_INVALID;
1919 static int start_unit(DBusConnection *bus, char **args) {
1921 static const char * const table[_ACTION_MAX] = {
1922 [ACTION_HALT] = SPECIAL_HALT_TARGET,
1923 [ACTION_POWEROFF] = SPECIAL_POWEROFF_TARGET,
1924 [ACTION_REBOOT] = SPECIAL_REBOOT_TARGET,
1925 [ACTION_KEXEC] = SPECIAL_KEXEC_TARGET,
1926 [ACTION_RUNLEVEL2] = SPECIAL_RUNLEVEL2_TARGET,
1927 [ACTION_RUNLEVEL3] = SPECIAL_RUNLEVEL3_TARGET,
1928 [ACTION_RUNLEVEL4] = SPECIAL_RUNLEVEL4_TARGET,
1929 [ACTION_RUNLEVEL5] = SPECIAL_RUNLEVEL5_TARGET,
1930 [ACTION_RESCUE] = SPECIAL_RESCUE_TARGET,
1931 [ACTION_EMERGENCY] = SPECIAL_EMERGENCY_TARGET,
1932 [ACTION_DEFAULT] = SPECIAL_DEFAULT_TARGET,
1933 [ACTION_EXIT] = SPECIAL_EXIT_TARGET,
1934 [ACTION_SUSPEND] = SPECIAL_SUSPEND_TARGET,
1935 [ACTION_HIBERNATE] = SPECIAL_HIBERNATE_TARGET
1939 const char *method, *mode, *one_name;
1944 dbus_error_init(&error);
1948 ask_password_agent_open_if_enabled();
1950 if (arg_action == ACTION_SYSTEMCTL) {
1952 streq(args[0], "stop") ||
1953 streq(args[0], "condstop") ? "StopUnit" :
1954 streq(args[0], "reload") ? "ReloadUnit" :
1955 streq(args[0], "restart") ? "RestartUnit" :
1957 streq(args[0], "try-restart") ||
1958 streq(args[0], "condrestart") ? "TryRestartUnit" :
1960 streq(args[0], "reload-or-restart") ? "ReloadOrRestartUnit" :
1962 streq(args[0], "reload-or-try-restart") ||
1963 streq(args[0], "condreload") ||
1965 streq(args[0], "force-reload") ? "ReloadOrTryRestartUnit" :
1969 (streq(args[0], "isolate") ||
1970 streq(args[0], "rescue") ||
1971 streq(args[0], "emergency")) ? "isolate" : arg_job_mode;
1973 one_name = table[verb_to_action(args[0])];
1976 assert(arg_action < ELEMENTSOF(table));
1977 assert(table[arg_action]);
1979 method = "StartUnit";
1981 mode = (arg_action == ACTION_EMERGENCY ||
1982 arg_action == ACTION_RESCUE ||
1983 arg_action == ACTION_RUNLEVEL2 ||
1984 arg_action == ACTION_RUNLEVEL3 ||
1985 arg_action == ACTION_RUNLEVEL4 ||
1986 arg_action == ACTION_RUNLEVEL5) ? "isolate" : "replace";
1988 one_name = table[arg_action];
1991 if (!arg_no_block) {
1992 if ((ret = enable_wait_for_jobs(bus)) < 0) {
1993 log_error("Could not watch jobs: %s", strerror(-ret));
1997 if (!(s = set_new(string_hash_func, string_compare_func))) {
1998 log_error("Failed to allocate set.");
2005 if ((ret = start_unit_one(bus, method, one_name, mode, &error, s)) <= 0)
2008 STRV_FOREACH(name, args+1)
2009 if ((r = start_unit_one(bus, method, *name, mode, &error, s)) != 0) {
2010 ret = translate_bus_error_to_exit_status(r, &error);
2011 dbus_error_free(&error);
2016 if ((r = wait_for_jobs(bus, s)) < 0) {
2025 dbus_error_free(&error);
2030 /* Ask systemd-logind, which might grant access to unprivileged users
2031 * through PolicyKit */
2032 static int reboot_with_logind(DBusConnection *bus, enum action a) {
2035 DBusMessage *m = NULL, *reply = NULL;
2037 dbus_bool_t interactive = true;
2040 dbus_error_init(&error);
2042 polkit_agent_open_if_enabled();
2050 case ACTION_POWEROFF:
2051 method = "PowerOff";
2054 case ACTION_SUSPEND:
2058 case ACTION_HIBERNATE:
2059 method = "Hibernate";
2066 m = dbus_message_new_method_call(
2067 "org.freedesktop.login1",
2068 "/org/freedesktop/login1",
2069 "org.freedesktop.login1.Manager",
2072 log_error("Could not allocate message.");
2077 if (!dbus_message_append_args(m,
2078 DBUS_TYPE_BOOLEAN, &interactive,
2079 DBUS_TYPE_INVALID)) {
2080 log_error("Could not append arguments to message.");
2085 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
2087 if (error_is_no_service(&error)) {
2088 log_debug("Failed to issue method call: %s", bus_error_message(&error));
2093 if (dbus_error_has_name(&error, DBUS_ERROR_ACCESS_DENIED)) {
2094 log_debug("Failed to issue method call: %s", bus_error_message(&error));
2099 log_info("Failed to issue method call: %s", bus_error_message(&error));
2108 dbus_message_unref(m);
2111 dbus_message_unref(reply);
2113 dbus_error_free(&error);
2121 static int start_special(DBusConnection *bus, char **args) {
2127 a = verb_to_action(args[0]);
2129 if (arg_force >= 2 && geteuid() != 0) {
2130 log_error("Must be root.");
2134 if (arg_force >= 2 &&
2135 (a == ACTION_HALT ||
2136 a == ACTION_POWEROFF ||
2137 a == ACTION_REBOOT))
2140 if (arg_force >= 1 &&
2141 (a == ACTION_HALT ||
2142 a == ACTION_POWEROFF ||
2143 a == ACTION_REBOOT ||
2144 a == ACTION_KEXEC ||
2146 return daemon_reload(bus, args);
2148 /* first try logind, to allow authentication with polkit */
2149 if (geteuid() != 0 &&
2150 (a == ACTION_POWEROFF ||
2151 a == ACTION_REBOOT ||
2152 a == ACTION_SUSPEND ||
2153 a == ACTION_HIBERNATE)) {
2154 r = reboot_with_logind(bus, a);
2159 r = start_unit(bus, args);
2166 static int check_unit(DBusConnection *bus, char **args) {
2168 int r = 3; /* According to LSB: "program is not running" */
2173 STRV_FOREACH(name, args+1) {
2174 int state = check_one_unit(bus, *name, arg_quiet);
2184 static int kill_unit(DBusConnection *bus, char **args) {
2185 DBusMessage *m = NULL;
2193 dbus_error_init(&error);
2196 arg_kill_who = "all";
2198 STRV_FOREACH(name, args+1) {
2203 m = dbus_message_new_method_call(
2204 "org.freedesktop.systemd1",
2205 "/org/freedesktop/systemd1",
2206 "org.freedesktop.systemd1.Manager",
2209 log_error("Could not allocate message.");
2214 n = unit_name_mangle(*name);
2215 b = dbus_message_append_args(m,
2216 DBUS_TYPE_STRING, n ? &n : name,
2217 DBUS_TYPE_STRING, &arg_kill_who,
2218 DBUS_TYPE_INT32, &arg_signal,
2222 log_error("Could not append arguments to message.");
2227 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
2229 log_error("Failed to issue method call: %s", bus_error_message(&error));
2230 dbus_error_free(&error);
2234 dbus_message_unref(m);
2237 dbus_message_unref(reply);
2243 dbus_message_unref(m);
2245 dbus_error_free(&error);
2250 typedef struct ExecStatusInfo {
2258 usec_t start_timestamp;
2259 usec_t exit_timestamp;
2264 LIST_FIELDS(struct ExecStatusInfo, exec);
2267 static void exec_status_info_free(ExecStatusInfo *i) {
2276 static int exec_status_info_deserialize(DBusMessageIter *sub, ExecStatusInfo *i) {
2277 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
2278 DBusMessageIter sub2, sub3;
2282 int32_t code, status;
2288 if (dbus_message_iter_get_arg_type(sub) != DBUS_TYPE_STRUCT)
2291 dbus_message_iter_recurse(sub, &sub2);
2293 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0)
2296 if (!(i->path = strdup(path)))
2299 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_ARRAY ||
2300 dbus_message_iter_get_element_type(&sub2) != DBUS_TYPE_STRING)
2304 dbus_message_iter_recurse(&sub2, &sub3);
2305 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2306 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2307 dbus_message_iter_next(&sub3);
2312 if (!(i->argv = new0(char*, n+1)))
2316 dbus_message_iter_recurse(&sub2, &sub3);
2317 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2320 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2321 dbus_message_iter_get_basic(&sub3, &s);
2322 dbus_message_iter_next(&sub3);
2324 if (!(i->argv[n++] = strdup(s)))
2328 if (!dbus_message_iter_next(&sub2) ||
2329 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, true) < 0 ||
2330 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp, true) < 0 ||
2331 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp_monotonic, true) < 0 ||
2332 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp, true) < 0 ||
2333 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp_monotonic, true) < 0 ||
2334 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, true) < 0 ||
2335 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &code, true) < 0 ||
2336 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &status, false) < 0)
2340 i->start_timestamp = (usec_t) start_timestamp;
2341 i->exit_timestamp = (usec_t) exit_timestamp;
2342 i->pid = (pid_t) pid;
2349 typedef struct UnitStatusInfo {
2351 const char *load_state;
2352 const char *active_state;
2353 const char *sub_state;
2354 const char *unit_file_state;
2356 const char *description;
2357 const char *following;
2359 char **documentation;
2361 const char *fragment_path;
2362 const char *source_path;
2363 const char *default_control_group;
2365 const char *load_error;
2368 usec_t inactive_exit_timestamp;
2369 usec_t inactive_exit_timestamp_monotonic;
2370 usec_t active_enter_timestamp;
2371 usec_t active_exit_timestamp;
2372 usec_t inactive_enter_timestamp;
2374 bool need_daemon_reload;
2379 const char *status_text;
2382 usec_t start_timestamp;
2383 usec_t exit_timestamp;
2385 int exit_code, exit_status;
2387 usec_t condition_timestamp;
2388 bool condition_result;
2391 unsigned n_accepted;
2392 unsigned n_connections;
2396 const char *sysfs_path;
2398 /* Mount, Automount */
2404 LIST_HEAD(ExecStatusInfo, exec);
2407 static void print_status_info(UnitStatusInfo *i) {
2409 const char *on, *off, *ss;
2411 char since1[FORMAT_TIMESTAMP_PRETTY_MAX], *s1;
2412 char since2[FORMAT_TIMESTAMP_MAX], *s2;
2417 /* This shows pretty information about a unit. See
2418 * print_property() for a low-level property printer */
2420 printf("%s", strna(i->id));
2422 if (i->description && !streq_ptr(i->id, i->description))
2423 printf(" - %s", i->description);
2428 printf("\t Follow: unit currently follows state of %s\n", i->following);
2430 if (streq_ptr(i->load_state, "error")) {
2431 on = ansi_highlight_red(true);
2432 off = ansi_highlight_red(false);
2436 path = i->source_path ? i->source_path : i->fragment_path;
2439 printf("\t Loaded: %s%s%s (Reason: %s)\n", on, strna(i->load_state), off, i->load_error);
2440 else if (path && i->unit_file_state)
2441 printf("\t Loaded: %s%s%s (%s; %s)\n", on, strna(i->load_state), off, path, i->unit_file_state);
2443 printf("\t Loaded: %s%s%s (%s)\n", on, strna(i->load_state), off, path);
2445 printf("\t Loaded: %s%s%s\n", on, strna(i->load_state), off);
2447 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
2449 if (streq_ptr(i->active_state, "failed")) {
2450 on = ansi_highlight_red(true);
2451 off = ansi_highlight_red(false);
2452 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
2453 on = ansi_highlight_green(true);
2454 off = ansi_highlight_green(false);
2459 printf("\t Active: %s%s (%s)%s",
2461 strna(i->active_state),
2465 printf("\t Active: %s%s%s",
2467 strna(i->active_state),
2470 if (!isempty(i->result) && !streq(i->result, "success"))
2471 printf(" (Result: %s)", i->result);
2473 timestamp = (streq_ptr(i->active_state, "active") ||
2474 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
2475 (streq_ptr(i->active_state, "inactive") ||
2476 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
2477 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
2478 i->active_exit_timestamp;
2480 s1 = format_timestamp_pretty(since1, sizeof(since1), timestamp);
2481 s2 = format_timestamp(since2, sizeof(since2), timestamp);
2484 printf(" since %s; %s\n", s2, s1);
2486 printf(" since %s\n", s2);
2490 if (!i->condition_result && i->condition_timestamp > 0) {
2491 s1 = format_timestamp_pretty(since1, sizeof(since1), i->condition_timestamp);
2492 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
2495 printf("\t start condition failed at %s; %s\n", s2, s1);
2497 printf("\t start condition failed at %s\n", s2);
2501 printf("\t Device: %s\n", i->sysfs_path);
2503 printf("\t Where: %s\n", i->where);
2505 printf("\t What: %s\n", i->what);
2507 if (!strv_isempty(i->documentation)) {
2511 STRV_FOREACH(t, i->documentation) {
2513 printf("\t Docs: %s\n", *t);
2516 printf("\t %s\n", *t);
2521 printf("\tAccepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
2523 LIST_FOREACH(exec, p, i->exec) {
2527 /* Only show exited processes here */
2531 t = strv_join(p->argv, " ");
2532 printf("\t Process: %u %s=%s ", p->pid, p->name, strna(t));
2535 good = is_clean_exit_lsb(p->code, p->status);
2537 on = ansi_highlight_red(true);
2538 off = ansi_highlight_red(false);
2542 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
2544 if (p->code == CLD_EXITED) {
2547 printf("status=%i", p->status);
2549 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
2554 printf("signal=%s", signal_to_string(p->status));
2556 printf(")%s\n", off);
2558 if (i->main_pid == p->pid &&
2559 i->start_timestamp == p->start_timestamp &&
2560 i->exit_timestamp == p->start_timestamp)
2561 /* Let's not show this twice */
2564 if (p->pid == i->control_pid)
2568 if (i->main_pid > 0 || i->control_pid > 0) {
2571 if (i->main_pid > 0) {
2572 printf("Main PID: %u", (unsigned) i->main_pid);
2576 get_process_comm(i->main_pid, &t);
2581 } else if (i->exit_code > 0) {
2582 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
2584 if (i->exit_code == CLD_EXITED) {
2587 printf("status=%i", i->exit_status);
2589 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
2594 printf("signal=%s", signal_to_string(i->exit_status));
2599 if (i->main_pid > 0 && i->control_pid > 0)
2602 if (i->control_pid > 0) {
2605 printf(" Control: %u", (unsigned) i->control_pid);
2607 get_process_comm(i->control_pid, &t);
2618 printf("\t Status: \"%s\"\n", i->status_text);
2620 if (i->default_control_group) {
2623 printf("\t CGroup: %s\n", i->default_control_group);
2625 if (arg_transport != TRANSPORT_SSH) {
2635 if (i->main_pid > 0)
2636 extra[k++] = i->main_pid;
2638 if (i->control_pid > 0)
2639 extra[k++] = i->control_pid;
2641 show_cgroup_and_extra_by_spec(i->default_control_group, "\t\t ", c, false, arg_all, extra, k);
2645 if (i->id && arg_transport != TRANSPORT_SSH) {
2647 arg_lines * OUTPUT_SHOW_ALL |
2648 arg_follow * OUTPUT_FOLLOW |
2649 !arg_quiet * OUTPUT_WARN_CUTOFF |
2650 on_tty() * OUTPUT_COLOR;
2653 show_journal_by_unit(i->id, arg_output, 0,
2654 i->inactive_exit_timestamp_monotonic,
2658 if (i->need_daemon_reload)
2659 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %s daemon-reload' recommended.\n",
2660 ansi_highlight_red(true),
2661 ansi_highlight_red(false),
2662 arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
2665 static void show_unit_help(UnitStatusInfo *i) {
2670 if (!i->documentation) {
2671 log_info("Documentation for %s not known.", i->id);
2675 STRV_FOREACH(p, i->documentation) {
2677 if (startswith(*p, "man:")) {
2680 char *page = NULL, *section = NULL;
2681 const char *args[4] = { "man", NULL, NULL, NULL };
2686 if ((*p)[k-1] == ')')
2687 e = strrchr(*p, '(');
2690 page = strndup((*p) + 4, e - *p - 4);
2696 section = strndup(e + 1, *p + k - e - 2);
2710 log_error("Failed to fork: %m");
2718 execvp(args[0], (char**) args);
2719 log_error("Failed to execute man: %m");
2720 _exit(EXIT_FAILURE);
2726 wait_for_terminate(pid, NULL);
2728 log_info("Can't show: %s", *p);
2732 static int status_property(const char *name, DBusMessageIter *iter, UnitStatusInfo *i) {
2738 switch (dbus_message_iter_get_arg_type(iter)) {
2740 case DBUS_TYPE_STRING: {
2743 dbus_message_iter_get_basic(iter, &s);
2746 if (streq(name, "Id"))
2748 else if (streq(name, "LoadState"))
2750 else if (streq(name, "ActiveState"))
2751 i->active_state = s;
2752 else if (streq(name, "SubState"))
2754 else if (streq(name, "Description"))
2756 else if (streq(name, "FragmentPath"))
2757 i->fragment_path = s;
2758 else if (streq(name, "SourcePath"))
2760 else if (streq(name, "DefaultControlGroup"))
2761 i->default_control_group = s;
2762 else if (streq(name, "StatusText"))
2764 else if (streq(name, "SysFSPath"))
2766 else if (streq(name, "Where"))
2768 else if (streq(name, "What"))
2770 else if (streq(name, "Following"))
2772 else if (streq(name, "UnitFileState"))
2773 i->unit_file_state = s;
2774 else if (streq(name, "Result"))
2781 case DBUS_TYPE_BOOLEAN: {
2784 dbus_message_iter_get_basic(iter, &b);
2786 if (streq(name, "Accept"))
2788 else if (streq(name, "NeedDaemonReload"))
2789 i->need_daemon_reload = b;
2790 else if (streq(name, "ConditionResult"))
2791 i->condition_result = b;
2796 case DBUS_TYPE_UINT32: {
2799 dbus_message_iter_get_basic(iter, &u);
2801 if (streq(name, "MainPID")) {
2803 i->main_pid = (pid_t) u;
2806 } else if (streq(name, "ControlPID"))
2807 i->control_pid = (pid_t) u;
2808 else if (streq(name, "ExecMainPID")) {
2810 i->main_pid = (pid_t) u;
2811 } else if (streq(name, "NAccepted"))
2813 else if (streq(name, "NConnections"))
2814 i->n_connections = u;
2819 case DBUS_TYPE_INT32: {
2822 dbus_message_iter_get_basic(iter, &j);
2824 if (streq(name, "ExecMainCode"))
2825 i->exit_code = (int) j;
2826 else if (streq(name, "ExecMainStatus"))
2827 i->exit_status = (int) j;
2832 case DBUS_TYPE_UINT64: {
2835 dbus_message_iter_get_basic(iter, &u);
2837 if (streq(name, "ExecMainStartTimestamp"))
2838 i->start_timestamp = (usec_t) u;
2839 else if (streq(name, "ExecMainExitTimestamp"))
2840 i->exit_timestamp = (usec_t) u;
2841 else if (streq(name, "ActiveEnterTimestamp"))
2842 i->active_enter_timestamp = (usec_t) u;
2843 else if (streq(name, "InactiveEnterTimestamp"))
2844 i->inactive_enter_timestamp = (usec_t) u;
2845 else if (streq(name, "InactiveExitTimestamp"))
2846 i->inactive_exit_timestamp = (usec_t) u;
2847 else if (streq(name, "InactiveExitTimestampMonotonic"))
2848 i->inactive_exit_timestamp_monotonic = (usec_t) u;
2849 else if (streq(name, "ActiveExitTimestamp"))
2850 i->active_exit_timestamp = (usec_t) u;
2851 else if (streq(name, "ConditionTimestamp"))
2852 i->condition_timestamp = (usec_t) u;
2857 case DBUS_TYPE_ARRAY: {
2859 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
2860 startswith(name, "Exec")) {
2861 DBusMessageIter sub;
2863 dbus_message_iter_recurse(iter, &sub);
2864 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2865 ExecStatusInfo *info;
2868 if (!(info = new0(ExecStatusInfo, 1)))
2871 if (!(info->name = strdup(name))) {
2876 if ((r = exec_status_info_deserialize(&sub, info)) < 0) {
2881 LIST_PREPEND(ExecStatusInfo, exec, i->exec, info);
2883 dbus_message_iter_next(&sub);
2885 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
2886 streq(name, "Documentation")) {
2888 DBusMessageIter sub;
2890 dbus_message_iter_recurse(iter, &sub);
2891 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING) {
2895 dbus_message_iter_get_basic(&sub, &s);
2897 l = strv_append(i->documentation, s);
2901 strv_free(i->documentation);
2902 i->documentation = l;
2904 dbus_message_iter_next(&sub);
2911 case DBUS_TYPE_STRUCT: {
2913 if (streq(name, "LoadError")) {
2914 DBusMessageIter sub;
2915 const char *n, *message;
2918 dbus_message_iter_recurse(iter, &sub);
2920 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &n, true);
2924 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &message, false);
2928 if (!isempty(message))
2929 i->load_error = message;
2939 static int print_property(const char *name, DBusMessageIter *iter) {
2943 /* This is a low-level property printer, see
2944 * print_status_info() for the nicer output */
2946 if (arg_property && !strv_find(arg_property, name))
2949 switch (dbus_message_iter_get_arg_type(iter)) {
2951 case DBUS_TYPE_STRUCT: {
2952 DBusMessageIter sub;
2953 dbus_message_iter_recurse(iter, &sub);
2955 if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32 && streq(name, "Job")) {
2958 dbus_message_iter_get_basic(&sub, &u);
2961 printf("%s=%u\n", name, (unsigned) u);
2963 printf("%s=\n", name);
2966 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "Unit")) {
2969 dbus_message_iter_get_basic(&sub, &s);
2971 if (arg_all || s[0])
2972 printf("%s=%s\n", name, s);
2975 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "LoadError")) {
2976 const char *a = NULL, *b = NULL;
2978 if (bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &a, true) >= 0)
2979 bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &b, false);
2981 if (arg_all || !isempty(a) || !isempty(b))
2982 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
2990 case DBUS_TYPE_ARRAY:
2992 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "EnvironmentFiles")) {
2993 DBusMessageIter sub, sub2;
2995 dbus_message_iter_recurse(iter, &sub);
2996 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3000 dbus_message_iter_recurse(&sub, &sub2);
3002 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
3003 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) >= 0)
3004 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
3006 dbus_message_iter_next(&sub);
3011 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Paths")) {
3012 DBusMessageIter sub, sub2;
3014 dbus_message_iter_recurse(iter, &sub);
3015 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3016 const char *type, *path;
3018 dbus_message_iter_recurse(&sub, &sub2);
3020 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
3021 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
3022 printf("%s=%s\n", type, path);
3024 dbus_message_iter_next(&sub);
3029 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Timers")) {
3030 DBusMessageIter sub, sub2;
3032 dbus_message_iter_recurse(iter, &sub);
3033 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3035 uint64_t value, next_elapse;
3037 dbus_message_iter_recurse(&sub, &sub2);
3039 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &base, true) >= 0 &&
3040 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &value, true) >= 0 &&
3041 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &next_elapse, false) >= 0) {
3042 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
3044 printf("%s={ value=%s ; next_elapse=%s }\n",
3046 format_timespan(timespan1, sizeof(timespan1), value),
3047 format_timespan(timespan2, sizeof(timespan2), next_elapse));
3050 dbus_message_iter_next(&sub);
3055 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "ControlGroupAttributes")) {
3056 DBusMessageIter sub, sub2;
3058 dbus_message_iter_recurse(iter, &sub);
3059 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3060 const char *controller, *attr, *value;
3062 dbus_message_iter_recurse(&sub, &sub2);
3064 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &controller, true) >= 0 &&
3065 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &attr, true) >= 0 &&
3066 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &value, false) >= 0) {
3068 printf("ControlGroupAttribute={ controller=%s ; attribute=%s ; value=\"%s\" }\n",
3074 dbus_message_iter_next(&sub);
3079 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && startswith(name, "Exec")) {
3080 DBusMessageIter sub;
3082 dbus_message_iter_recurse(iter, &sub);
3083 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3084 ExecStatusInfo info;
3087 if (exec_status_info_deserialize(&sub, &info) >= 0) {
3088 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
3091 t = strv_join(info.argv, " ");
3093 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
3097 yes_no(info.ignore),
3098 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
3099 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
3100 (unsigned) info. pid,
3101 sigchld_code_to_string(info.code),
3103 info.code == CLD_EXITED ? "" : "/",
3104 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
3110 strv_free(info.argv);
3112 dbus_message_iter_next(&sub);
3121 if (generic_print_property(name, iter, arg_all) > 0)
3125 printf("%s=[unprintable]\n", name);
3130 static int show_one(const char *verb, DBusConnection *bus, const char *path, bool show_properties, bool *new_line) {
3131 DBusMessage *m = NULL, *reply = NULL;
3132 const char *interface = "";
3135 DBusMessageIter iter, sub, sub2, sub3;
3136 UnitStatusInfo info;
3144 dbus_error_init(&error);
3146 if (!(m = dbus_message_new_method_call(
3147 "org.freedesktop.systemd1",
3149 "org.freedesktop.DBus.Properties",
3151 log_error("Could not allocate message.");
3156 if (!dbus_message_append_args(m,
3157 DBUS_TYPE_STRING, &interface,
3158 DBUS_TYPE_INVALID)) {
3159 log_error("Could not append arguments to message.");
3164 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3165 log_error("Failed to issue method call: %s", bus_error_message(&error));
3170 if (!dbus_message_iter_init(reply, &iter) ||
3171 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3172 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
3173 log_error("Failed to parse reply.");
3178 dbus_message_iter_recurse(&iter, &sub);
3185 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
3188 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_DICT_ENTRY) {
3189 log_error("Failed to parse reply.");
3194 dbus_message_iter_recurse(&sub, &sub2);
3196 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0) {
3197 log_error("Failed to parse reply.");
3202 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
3203 log_error("Failed to parse reply.");
3208 dbus_message_iter_recurse(&sub2, &sub3);
3210 if (show_properties)
3211 r = print_property(name, &sub3);
3213 r = status_property(name, &sub3, &info);
3216 log_error("Failed to parse reply.");
3221 dbus_message_iter_next(&sub);
3226 if (!show_properties) {
3227 if (streq(verb, "help"))
3228 show_unit_help(&info);
3230 print_status_info(&info);
3233 strv_free(info.documentation);
3235 if (!streq_ptr(info.active_state, "active") &&
3236 !streq_ptr(info.active_state, "reloading") &&
3237 streq(verb, "status"))
3238 /* According to LSB: "program not running" */
3241 while ((p = info.exec)) {
3242 LIST_REMOVE(ExecStatusInfo, exec, info.exec, p);
3243 exec_status_info_free(p);
3248 dbus_message_unref(m);
3251 dbus_message_unref(reply);
3253 dbus_error_free(&error);
3258 static int show_one_by_pid(const char *verb, DBusConnection *bus, uint32_t pid, bool *new_line) {
3259 DBusMessage *m = NULL, *reply = NULL;
3260 const char *path = NULL;
3264 dbus_error_init(&error);
3266 m = dbus_message_new_method_call(
3267 "org.freedesktop.systemd1",
3268 "/org/freedesktop/systemd1",
3269 "org.freedesktop.systemd1.Manager",
3272 log_error("Could not allocate message.");
3277 if (!dbus_message_append_args(m,
3278 DBUS_TYPE_UINT32, &pid,
3279 DBUS_TYPE_INVALID)) {
3280 log_error("Could not append arguments to message.");
3285 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3287 log_error("Failed to issue method call: %s", bus_error_message(&error));
3292 if (!dbus_message_get_args(reply, &error,
3293 DBUS_TYPE_OBJECT_PATH, &path,
3294 DBUS_TYPE_INVALID)) {
3295 log_error("Failed to parse reply: %s", bus_error_message(&error));
3300 r = show_one(verb, bus, path, false, new_line);
3304 dbus_message_unref(m);
3307 dbus_message_unref(reply);
3309 dbus_error_free(&error);
3314 static int show(DBusConnection *bus, char **args) {
3316 bool show_properties, new_line = false;
3322 show_properties = streq(args[0], "show");
3324 if (show_properties)
3325 pager_open_if_enabled();
3327 if (show_properties && strv_length(args) <= 1) {
3328 /* If not argument is specified inspect the manager
3331 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line);
3334 STRV_FOREACH(name, args+1) {
3337 if (safe_atou32(*name, &id) < 0) {
3339 /* Interpret as unit name */
3341 n = unit_name_mangle(*name);
3342 p = unit_dbus_path_from_name(n ? n : *name);
3347 r = show_one(args[0], bus, p, show_properties, &new_line);
3353 } else if (show_properties) {
3355 /* Interpret as job id */
3358 if (asprintf(&p, "/org/freedesktop/systemd1/job/%u", id) < 0)
3361 r = show_one(args[0], bus, p, show_properties, &new_line);
3369 /* Interpret as PID */
3371 r = show_one_by_pid(args[0], bus, id, &new_line);
3380 static int dump(DBusConnection *bus, char **args) {
3381 DBusMessage *m = NULL, *reply = NULL;
3386 dbus_error_init(&error);
3388 pager_open_if_enabled();
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))) {
3400 log_error("Failed to issue method call: %s", bus_error_message(&error));
3405 if (!dbus_message_get_args(reply, &error,
3406 DBUS_TYPE_STRING, &text,
3407 DBUS_TYPE_INVALID)) {
3408 log_error("Failed to parse reply: %s", bus_error_message(&error));
3413 fputs(text, stdout);
3419 dbus_message_unref(m);
3422 dbus_message_unref(reply);
3424 dbus_error_free(&error);
3429 static int snapshot(DBusConnection *bus, char **args) {
3430 DBusMessage *m = NULL, *reply = NULL;
3433 const char *name = "", *path, *id;
3434 dbus_bool_t cleanup = FALSE;
3435 DBusMessageIter iter, sub;
3437 *interface = "org.freedesktop.systemd1.Unit",
3442 dbus_error_init(&error);
3444 m = dbus_message_new_method_call(
3445 "org.freedesktop.systemd1",
3446 "/org/freedesktop/systemd1",
3447 "org.freedesktop.systemd1.Manager",
3450 log_error("Could not allocate message.");
3454 if (strv_length(args) > 1)
3457 n = unit_name_mangle(name);
3458 b = dbus_message_append_args(m,
3459 DBUS_TYPE_STRING, n ? (const char**) &n : &name,
3460 DBUS_TYPE_BOOLEAN, &cleanup,
3464 log_error("Could not append arguments to message.");
3469 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3471 log_error("Failed to issue method call: %s", bus_error_message(&error));
3476 if (!dbus_message_get_args(reply, &error,
3477 DBUS_TYPE_OBJECT_PATH, &path,
3478 DBUS_TYPE_INVALID)) {
3479 log_error("Failed to parse reply: %s", bus_error_message(&error));
3484 dbus_message_unref(m);
3485 m = dbus_message_new_method_call(
3486 "org.freedesktop.systemd1",
3488 "org.freedesktop.DBus.Properties",
3491 log_error("Could not allocate message.");
3495 if (!dbus_message_append_args(m,
3496 DBUS_TYPE_STRING, &interface,
3497 DBUS_TYPE_STRING, &property,
3498 DBUS_TYPE_INVALID)) {
3499 log_error("Could not append arguments to message.");
3504 dbus_message_unref(reply);
3505 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3507 log_error("Failed to issue method call: %s", bus_error_message(&error));
3512 if (!dbus_message_iter_init(reply, &iter) ||
3513 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3514 log_error("Failed to parse reply.");
3519 dbus_message_iter_recurse(&iter, &sub);
3521 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
3522 log_error("Failed to parse reply.");
3527 dbus_message_iter_get_basic(&sub, &id);
3535 dbus_message_unref(m);
3538 dbus_message_unref(reply);
3540 dbus_error_free(&error);
3545 static int delete_snapshot(DBusConnection *bus, char **args) {
3546 DBusMessage *m = NULL, *reply = NULL;
3554 dbus_error_init(&error);
3556 STRV_FOREACH(name, args+1) {
3557 const char *path = NULL;
3561 m = dbus_message_new_method_call(
3562 "org.freedesktop.systemd1",
3563 "/org/freedesktop/systemd1",
3564 "org.freedesktop.systemd1.Manager",
3567 log_error("Could not allocate message.");
3572 n = unit_name_mangle(*name);
3573 b = dbus_message_append_args(m,
3574 DBUS_TYPE_STRING, n ? &n : name,
3578 log_error("Could not append arguments to message.");
3583 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3585 log_error("Failed to issue method call: %s", bus_error_message(&error));
3590 if (!dbus_message_get_args(reply, &error,
3591 DBUS_TYPE_OBJECT_PATH, &path,
3592 DBUS_TYPE_INVALID)) {
3593 log_error("Failed to parse reply: %s", bus_error_message(&error));
3598 dbus_message_unref(m);
3599 m = dbus_message_new_method_call(
3600 "org.freedesktop.systemd1",
3602 "org.freedesktop.systemd1.Snapshot",
3605 log_error("Could not allocate message.");
3610 dbus_message_unref(reply);
3611 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3613 log_error("Failed to issue method call: %s", bus_error_message(&error));
3618 dbus_message_unref(m);
3619 dbus_message_unref(reply);
3627 dbus_message_unref(m);
3630 dbus_message_unref(reply);
3632 dbus_error_free(&error);
3637 static int daemon_reload(DBusConnection *bus, char **args) {
3638 DBusMessage *m = NULL, *reply = NULL;
3643 dbus_error_init(&error);
3645 if (arg_action == ACTION_RELOAD)
3647 else if (arg_action == ACTION_REEXEC)
3648 method = "Reexecute";
3650 assert(arg_action == ACTION_SYSTEMCTL);
3653 streq(args[0], "clear-jobs") ||
3654 streq(args[0], "cancel") ? "ClearJobs" :
3655 streq(args[0], "daemon-reexec") ? "Reexecute" :
3656 streq(args[0], "reset-failed") ? "ResetFailed" :
3657 streq(args[0], "halt") ? "Halt" :
3658 streq(args[0], "poweroff") ? "PowerOff" :
3659 streq(args[0], "reboot") ? "Reboot" :
3660 streq(args[0], "kexec") ? "KExec" :
3661 streq(args[0], "exit") ? "Exit" :
3662 /* "daemon-reload" */ "Reload";
3665 if (!(m = dbus_message_new_method_call(
3666 "org.freedesktop.systemd1",
3667 "/org/freedesktop/systemd1",
3668 "org.freedesktop.systemd1.Manager",
3670 log_error("Could not allocate message.");
3674 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3676 if (arg_action != ACTION_SYSTEMCTL && error_is_no_service(&error)) {
3677 /* There's always a fallback possible for
3678 * legacy actions. */
3683 if (streq(method, "Reexecute") && dbus_error_has_name(&error, DBUS_ERROR_NO_REPLY)) {
3684 /* On reexecution, we expect a disconnect, not
3690 log_error("Failed to issue method call: %s", bus_error_message(&error));
3699 dbus_message_unref(m);
3702 dbus_message_unref(reply);
3704 dbus_error_free(&error);
3709 static int reset_failed(DBusConnection *bus, char **args) {
3710 DBusMessage *m = NULL;
3716 dbus_error_init(&error);
3718 if (strv_length(args) <= 1)
3719 return daemon_reload(bus, args);
3721 STRV_FOREACH(name, args+1) {
3726 m = dbus_message_new_method_call(
3727 "org.freedesktop.systemd1",
3728 "/org/freedesktop/systemd1",
3729 "org.freedesktop.systemd1.Manager",
3732 log_error("Could not allocate message.");
3737 n = unit_name_mangle(*name);
3738 b = dbus_message_append_args(m,
3739 DBUS_TYPE_STRING, n ? &n : name,
3743 log_error("Could not append arguments to message.");
3748 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3750 log_error("Failed to issue method call: %s", bus_error_message(&error));
3755 dbus_message_unref(m);
3756 dbus_message_unref(reply);
3764 dbus_message_unref(m);
3766 dbus_error_free(&error);
3771 static int show_enviroment(DBusConnection *bus, char **args) {
3772 DBusMessage *m = NULL, *reply = NULL;
3774 DBusMessageIter iter, sub, sub2;
3777 *interface = "org.freedesktop.systemd1.Manager",
3778 *property = "Environment";
3780 dbus_error_init(&error);
3782 pager_open_if_enabled();
3784 if (!(m = dbus_message_new_method_call(
3785 "org.freedesktop.systemd1",
3786 "/org/freedesktop/systemd1",
3787 "org.freedesktop.DBus.Properties",
3789 log_error("Could not allocate message.");
3793 if (!dbus_message_append_args(m,
3794 DBUS_TYPE_STRING, &interface,
3795 DBUS_TYPE_STRING, &property,
3796 DBUS_TYPE_INVALID)) {
3797 log_error("Could not append arguments to message.");
3802 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3803 log_error("Failed to issue method call: %s", bus_error_message(&error));
3808 if (!dbus_message_iter_init(reply, &iter) ||
3809 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3810 log_error("Failed to parse reply.");
3815 dbus_message_iter_recurse(&iter, &sub);
3817 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_ARRAY ||
3818 dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_STRING) {
3819 log_error("Failed to parse reply.");
3824 dbus_message_iter_recurse(&sub, &sub2);
3826 while (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_INVALID) {
3829 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
3830 log_error("Failed to parse reply.");
3835 dbus_message_iter_get_basic(&sub2, &text);
3836 printf("%s\n", text);
3838 dbus_message_iter_next(&sub2);
3845 dbus_message_unref(m);
3848 dbus_message_unref(reply);
3850 dbus_error_free(&error);
3855 static int switch_root(DBusConnection *bus, char **args) {
3856 DBusMessage *m = NULL, *reply = NULL;
3858 const char *root, *init;
3862 dbus_error_init(&error);
3864 l = strv_length(args);
3865 if (l < 2 || l > 3) {
3866 log_error("Wrong number of arguments.");
3871 init = l >= 3 ? args[2] : "";
3873 m = dbus_message_new_method_call(
3874 "org.freedesktop.systemd1",
3875 "/org/freedesktop/systemd1",
3876 "org.freedesktop.systemd1.Manager",
3879 log_error("Could not allocate message.");
3883 if (!dbus_message_append_args(
3885 DBUS_TYPE_STRING, &root,
3886 DBUS_TYPE_STRING, &init,
3887 DBUS_TYPE_INVALID)) {
3888 log_error("Could not append arguments to message.");
3893 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3895 log_error("Failed to issue method call: %s", bus_error_message(&error));
3904 dbus_message_unref(m);
3907 dbus_message_unref(reply);
3909 dbus_error_free(&error);
3914 static int set_environment(DBusConnection *bus, char **args) {
3915 DBusMessage *m = NULL, *reply = NULL;
3919 DBusMessageIter iter, sub;
3922 dbus_error_init(&error);
3924 method = streq(args[0], "set-environment")
3926 : "UnsetEnvironment";
3928 if (!(m = dbus_message_new_method_call(
3929 "org.freedesktop.systemd1",
3930 "/org/freedesktop/systemd1",
3931 "org.freedesktop.systemd1.Manager",
3934 log_error("Could not allocate message.");
3938 dbus_message_iter_init_append(m, &iter);
3940 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub)) {
3941 log_error("Could not append arguments to message.");
3946 STRV_FOREACH(name, args+1)
3947 if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, name)) {
3948 log_error("Could not append arguments to message.");
3953 if (!dbus_message_iter_close_container(&iter, &sub)) {
3954 log_error("Could not append arguments to message.");
3959 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3960 log_error("Failed to issue method call: %s", bus_error_message(&error));
3969 dbus_message_unref(m);
3972 dbus_message_unref(reply);
3974 dbus_error_free(&error);
3979 static int enable_sysv_units(char **args) {
3982 #if defined (HAVE_SYSV_COMPAT) && (defined(TARGET_FEDORA) || defined(TARGET_MANDRIVA) || defined(TARGET_SUSE) || defined(TARGET_ALTLINUX) || defined(TARGET_MAGEIA))
3983 const char *verb = args[0];
3984 unsigned f = 1, t = 1;
3987 if (arg_scope != UNIT_FILE_SYSTEM)
3990 if (!streq(verb, "enable") &&
3991 !streq(verb, "disable") &&
3992 !streq(verb, "is-enabled"))
3995 /* Processes all SysV units, and reshuffles the array so that
3996 * afterwards only the native units remain */
3999 r = lookup_paths_init(&paths, MANAGER_SYSTEM, false, NULL, NULL, NULL);
4004 for (f = 1; args[f]; f++) {
4007 bool found_native = false, found_sysv;
4009 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
4010 char **k, *l, *q = NULL;
4017 if (!endswith(name, ".service"))
4020 if (path_is_absolute(name))
4023 STRV_FOREACH(k, paths.unit_path) {
4026 if (!isempty(arg_root))
4027 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
4029 asprintf(&p, "%s/%s", *k, name);
4036 found_native = access(p, F_OK) >= 0;
4047 if (!isempty(arg_root))
4048 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
4050 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
4056 p[strlen(p) - sizeof(".service") + 1] = 0;
4057 found_sysv = access(p, F_OK) >= 0;
4064 /* Mark this entry, so that we don't try enabling it as native unit */
4065 args[f] = (char*) "";
4067 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
4069 if (!isempty(arg_root))
4070 argv[c++] = q = strappend("--root=", arg_root);
4072 argv[c++] = path_get_file_name(p);
4074 streq(verb, "enable") ? "on" :
4075 streq(verb, "disable") ? "off" : "--level=5";
4078 l = strv_join((char**)argv, " ");
4086 log_info("Executing %s", l);
4091 log_error("Failed to fork: %m");
4096 } else if (pid == 0) {
4099 execv(argv[0], (char**) argv);
4100 _exit(EXIT_FAILURE);
4106 j = wait_for_terminate(pid, &status);
4108 log_error("Failed to wait for child: %s", strerror(-r));
4113 if (status.si_code == CLD_EXITED) {
4114 if (streq(verb, "is-enabled")) {
4115 if (status.si_status == 0) {
4124 } else if (status.si_status != 0) {
4135 lookup_paths_free(&paths);
4137 /* Drop all SysV units */
4138 for (f = 1, t = 1; args[f]; f++) {
4140 if (isempty(args[f]))
4143 args[t++] = args[f];
4152 static int enable_unit(DBusConnection *bus, char **args) {
4153 const char *verb = args[0];
4154 UnitFileChange *changes = NULL;
4155 unsigned n_changes = 0, i;
4156 int carries_install_info = -1;
4157 DBusMessage *m = NULL, *reply = NULL;
4161 r = enable_sysv_units(args);
4168 dbus_error_init(&error);
4170 if (!bus || avoid_bus()) {
4171 if (streq(verb, "enable")) {
4172 r = unit_file_enable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
4173 carries_install_info = r;
4174 } else if (streq(verb, "disable"))
4175 r = unit_file_disable(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
4176 else if (streq(verb, "reenable")) {
4177 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
4178 carries_install_info = r;
4179 } else if (streq(verb, "link"))
4180 r = unit_file_link(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
4181 else if (streq(verb, "preset")) {
4182 r = unit_file_preset(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
4183 carries_install_info = r;
4184 } else if (streq(verb, "mask"))
4185 r = unit_file_mask(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
4186 else if (streq(verb, "unmask"))
4187 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
4189 assert_not_reached("Unknown verb");
4192 log_error("Operation failed: %s", strerror(-r));
4197 for (i = 0; i < n_changes; i++) {
4198 if (changes[i].type == UNIT_FILE_SYMLINK)
4199 log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
4201 log_info("rm '%s'", changes[i].path);
4207 bool send_force = true, expect_carries_install_info = false;
4209 DBusMessageIter iter, sub, sub2;
4211 if (streq(verb, "enable")) {
4212 method = "EnableUnitFiles";
4213 expect_carries_install_info = true;
4214 } else if (streq(verb, "disable")) {
4215 method = "DisableUnitFiles";
4217 } else if (streq(verb, "reenable")) {
4218 method = "ReenableUnitFiles";
4219 expect_carries_install_info = true;
4220 } else if (streq(verb, "link"))
4221 method = "LinkUnitFiles";
4222 else if (streq(verb, "preset")) {
4223 method = "PresetUnitFiles";
4224 expect_carries_install_info = true;
4225 } else if (streq(verb, "mask"))
4226 method = "MaskUnitFiles";
4227 else if (streq(verb, "unmask")) {
4228 method = "UnmaskUnitFiles";
4231 assert_not_reached("Unknown verb");
4233 m = dbus_message_new_method_call(
4234 "org.freedesktop.systemd1",
4235 "/org/freedesktop/systemd1",
4236 "org.freedesktop.systemd1.Manager",
4243 dbus_message_iter_init_append(m, &iter);
4245 r = bus_append_strv_iter(&iter, args+1);
4247 log_error("Failed to append unit files.");
4252 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &a)) {
4253 log_error("Failed to append runtime boolean.");
4261 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b)) {
4262 log_error("Failed to append force boolean.");
4268 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
4270 log_error("Failed to issue method call: %s", bus_error_message(&error));
4275 if (!dbus_message_iter_init(reply, &iter)) {
4276 log_error("Failed to initialize iterator.");
4280 if (expect_carries_install_info) {
4281 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &b, true);
4283 log_error("Failed to parse reply.");
4287 carries_install_info = b;
4290 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
4291 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
4292 log_error("Failed to parse reply.");
4297 dbus_message_iter_recurse(&iter, &sub);
4298 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
4299 const char *type, *path, *source;
4301 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
4302 log_error("Failed to parse reply.");
4307 dbus_message_iter_recurse(&sub, &sub2);
4309 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
4310 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
4311 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &source, false) < 0) {
4312 log_error("Failed to parse reply.");
4318 if (streq(type, "symlink"))
4319 log_info("ln -s '%s' '%s'", source, path);
4321 log_info("rm '%s'", path);
4324 dbus_message_iter_next(&sub);
4327 /* Try to reload if enabeld */
4329 r = daemon_reload(bus, args);
4332 if (carries_install_info == 0)
4333 log_warning("The unit files have no [Install] section. They are not meant to be enabled using systemctl.");
4337 dbus_message_unref(m);
4340 dbus_message_unref(reply);
4342 unit_file_changes_free(changes, n_changes);
4344 dbus_error_free(&error);
4348 static int unit_is_enabled(DBusConnection *bus, char **args) {
4351 DBusMessage *m = NULL, *reply = NULL;
4355 dbus_error_init(&error);
4357 r = enable_sysv_units(args);
4363 if (!bus || avoid_bus()) {
4365 STRV_FOREACH(name, args+1) {
4366 UnitFileState state;
4368 state = unit_file_get_state(arg_scope, arg_root, *name);
4374 if (state == UNIT_FILE_ENABLED ||
4375 state == UNIT_FILE_ENABLED_RUNTIME ||
4376 state == UNIT_FILE_STATIC)
4380 puts(unit_file_state_to_string(state));
4384 STRV_FOREACH(name, args+1) {
4387 m = dbus_message_new_method_call(
4388 "org.freedesktop.systemd1",
4389 "/org/freedesktop/systemd1",
4390 "org.freedesktop.systemd1.Manager",
4391 "GetUnitFileState");
4397 if (!dbus_message_append_args(m,
4398 DBUS_TYPE_STRING, name,
4399 DBUS_TYPE_INVALID)) {
4400 log_error("Could not append arguments to message.");
4405 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
4407 log_error("Failed to issue method call: %s", bus_error_message(&error));
4412 if (!dbus_message_get_args(reply, &error,
4413 DBUS_TYPE_STRING, &s,
4414 DBUS_TYPE_INVALID)) {
4415 log_error("Failed to parse reply: %s", bus_error_message(&error));
4420 dbus_message_unref(m);
4421 dbus_message_unref(reply);
4424 if (streq(s, "enabled") ||
4425 streq(s, "enabled-runtime") ||
4434 r = enabled ? 0 : 1;
4438 dbus_message_unref(m);
4441 dbus_message_unref(reply);
4443 dbus_error_free(&error);
4447 static int systemctl_help(void) {
4449 pager_open_if_enabled();
4451 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
4452 "Query or send control commands to the systemd manager.\n\n"
4453 " -h --help Show this help\n"
4454 " --version Show package version\n"
4455 " -t --type=TYPE List only units of a particular type\n"
4456 " -p --property=NAME Show only properties by this name\n"
4457 " -a --all Show all units/properties, including dead/empty ones\n"
4458 " --failed Show only failed units\n"
4459 " --full Don't ellipsize unit names on output\n"
4460 " --fail When queueing a new job, fail if conflicting jobs are\n"
4462 " --ignore-dependencies\n"
4463 " When queueing a new job, ignore all its dependencies\n"
4464 " --kill-who=WHO Who to send signal to\n"
4465 " -s --signal=SIGNAL Which signal to send\n"
4466 " -H --host=[USER@]HOST\n"
4467 " Show information for remote host\n"
4468 " -P --privileged Acquire privileges before execution\n"
4469 " -q --quiet Suppress output\n"
4470 " --no-block Do not wait until operation finished\n"
4471 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4472 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
4474 " --no-legend Do not print a legend (column headers and hints)\n"
4475 " --no-pager Do not pipe output into a pager\n"
4476 " --no-ask-password\n"
4477 " Do not ask for system passwords\n"
4478 " --order When generating graph for dot, show only order\n"
4479 " --require When generating graph for dot, show only requirement\n"
4480 " --system Connect to system manager\n"
4481 " --user Connect to user service manager\n"
4482 " --global Enable/disable unit files globally\n"
4483 " -f --force When enabling unit files, override existing symlinks\n"
4484 " When shutting down, execute action immediately\n"
4485 " --root=PATH Enable unit files in the specified root directory\n"
4486 " --runtime Enable unit files only temporarily until next reboot\n"
4487 " -n --lines=INTEGER Journal entries to show\n"
4488 " --follow Follow journal\n"
4489 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
4490 " verbose, export, json, cat)\n\n"
4492 " list-units List loaded units\n"
4493 " start [NAME...] Start (activate) one or more units\n"
4494 " stop [NAME...] Stop (deactivate) one or more units\n"
4495 " reload [NAME...] Reload one or more units\n"
4496 " restart [NAME...] Start or restart one or more units\n"
4497 " try-restart [NAME...] Restart one or more units if active\n"
4498 " reload-or-restart [NAME...] Reload one or more units is possible,\n"
4499 " otherwise start or restart\n"
4500 " reload-or-try-restart [NAME...] Reload one or more units is possible,\n"
4501 " otherwise restart if active\n"
4502 " isolate [NAME] Start one unit and stop all others\n"
4503 " kill [NAME...] Send signal to processes of a unit\n"
4504 " is-active [NAME...] Check whether units are active\n"
4505 " status [NAME...|PID...] Show runtime status of one or more units\n"
4506 " show [NAME...|JOB...] Show properties of one or more\n"
4507 " units/jobs or the manager\n"
4508 " help [NAME...|PID...] Show manual for one or more units\n"
4509 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
4511 " load [NAME...] Load one or more units\n\n"
4512 "Unit File Commands:\n"
4513 " list-unit-files List installed unit files\n"
4514 " enable [NAME...] Enable one or more unit files\n"
4515 " disable [NAME...] Disable one or more unit files\n"
4516 " reenable [NAME...] Reenable one or more unit files\n"
4517 " preset [NAME...] Enable/disable one or more unit files\n"
4518 " based on preset configuration\n"
4519 " mask [NAME...] Mask one or more units\n"
4520 " unmask [NAME...] Unmask one or more units\n"
4521 " link [PATH...] Link one or more units files into\n"
4522 " the search path\n"
4523 " is-enabled [NAME...] Check whether unit files are enabled\n\n"
4525 " list-jobs List jobs\n"
4526 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
4527 "Status Commands:\n"
4528 " dump Dump server status\n"
4529 " dot Dump dependency graph for dot(1)\n\n"
4530 "Snapshot Commands:\n"
4531 " snapshot [NAME] Create a snapshot\n"
4532 " delete [NAME...] Remove one or more snapshots\n\n"
4533 "Environment Commands:\n"
4534 " show-environment Dump environment\n"
4535 " set-environment [NAME=VALUE...] Set one or more environment variables\n"
4536 " unset-environment [NAME...] Unset one or more environment variables\n\n"
4537 "Manager Lifecycle Commands:\n"
4538 " daemon-reload Reload systemd manager configuration\n"
4539 " daemon-reexec Reexecute systemd manager\n\n"
4540 "System Commands:\n"
4541 " default Enter system default mode\n"
4542 " rescue Enter system rescue mode\n"
4543 " emergency Enter system emergency mode\n"
4544 " halt Shut down and halt the system\n"
4545 " poweroff Shut down and power-off the system\n"
4546 " reboot Shut down and reboot the system\n"
4547 " kexec Shut down and reboot the system with kexec\n"
4548 " exit Request user instance exit\n"
4549 " switch-root [ROOT] [INIT] Change to a different root file system\n"
4550 " suspend Suspend the system\n"
4551 " hibernate Hibernate the system\n",
4552 program_invocation_short_name);
4557 static int halt_help(void) {
4559 printf("%s [OPTIONS...]\n\n"
4560 "%s the system.\n\n"
4561 " --help Show this help\n"
4562 " --halt Halt the machine\n"
4563 " -p --poweroff Switch off the machine\n"
4564 " --reboot Reboot the machine\n"
4565 " -f --force Force immediate halt/power-off/reboot\n"
4566 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
4567 " -d --no-wtmp Don't write wtmp record\n"
4568 " -n --no-sync Don't sync before halt/power-off/reboot\n"
4569 " --no-wall Don't send wall message before halt/power-off/reboot\n",
4570 program_invocation_short_name,
4571 arg_action == ACTION_REBOOT ? "Reboot" :
4572 arg_action == ACTION_POWEROFF ? "Power off" :
4578 static int shutdown_help(void) {
4580 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
4581 "Shut down the system.\n\n"
4582 " --help Show this help\n"
4583 " -H --halt Halt the machine\n"
4584 " -P --poweroff Power-off the machine\n"
4585 " -r --reboot Reboot the machine\n"
4586 " -h Equivalent to --poweroff, overridden by --halt\n"
4587 " -k Don't halt/power-off/reboot, just send warnings\n"
4588 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4589 " -c Cancel a pending shutdown\n",
4590 program_invocation_short_name);
4595 static int telinit_help(void) {
4597 printf("%s [OPTIONS...] {COMMAND}\n\n"
4598 "Send control commands to the init daemon.\n\n"
4599 " --help Show this help\n"
4600 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
4602 " 0 Power-off the machine\n"
4603 " 6 Reboot the machine\n"
4604 " 2, 3, 4, 5 Start runlevelX.target unit\n"
4605 " 1, s, S Enter rescue mode\n"
4606 " q, Q Reload init daemon configuration\n"
4607 " u, U Reexecute init daemon\n",
4608 program_invocation_short_name);
4613 static int runlevel_help(void) {
4615 printf("%s [OPTIONS...]\n\n"
4616 "Prints the previous and current runlevel of the init system.\n\n"
4617 " --help Show this help\n",
4618 program_invocation_short_name);
4623 static int systemctl_parse_argv(int argc, char *argv[]) {
4627 ARG_IGNORE_DEPENDENCIES,
4642 ARG_NO_ASK_PASSWORD,
4649 static const struct option options[] = {
4650 { "help", no_argument, NULL, 'h' },
4651 { "version", no_argument, NULL, ARG_VERSION },
4652 { "type", required_argument, NULL, 't' },
4653 { "property", required_argument, NULL, 'p' },
4654 { "all", no_argument, NULL, 'a' },
4655 { "failed", no_argument, NULL, ARG_FAILED },
4656 { "full", no_argument, NULL, ARG_FULL },
4657 { "fail", no_argument, NULL, ARG_FAIL },
4658 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
4659 { "user", no_argument, NULL, ARG_USER },
4660 { "system", no_argument, NULL, ARG_SYSTEM },
4661 { "global", no_argument, NULL, ARG_GLOBAL },
4662 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
4663 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
4664 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
4665 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4666 { "quiet", no_argument, NULL, 'q' },
4667 { "order", no_argument, NULL, ARG_ORDER },
4668 { "require", no_argument, NULL, ARG_REQUIRE },
4669 { "root", required_argument, NULL, ARG_ROOT },
4670 { "force", no_argument, NULL, ARG_FORCE },
4671 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
4672 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
4673 { "signal", required_argument, NULL, 's' },
4674 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
4675 { "host", required_argument, NULL, 'H' },
4676 { "privileged",no_argument, NULL, 'P' },
4677 { "runtime", no_argument, NULL, ARG_RUNTIME },
4678 { "lines", required_argument, NULL, 'n' },
4679 { "follow", no_argument, NULL, ARG_FOLLOW },
4680 { "output", required_argument, NULL, 'o' },
4681 { NULL, 0, NULL, 0 }
4689 while ((c = getopt_long(argc, argv, "ht:p:aqfs:H:Pn:o:", options, NULL)) >= 0) {
4698 puts(PACKAGE_STRING);
4700 puts(SYSTEMD_FEATURES);
4704 if (unit_type_from_string(optarg) >= 0) {
4708 if (unit_load_state_from_string(optarg) >= 0) {
4709 arg_load_state = optarg;
4712 log_error("Unkown unit type or load state '%s'.",
4718 if (!(l = strv_append(arg_property, optarg)))
4721 strv_free(arg_property);
4724 /* If the user asked for a particular
4725 * property, show it to him, even if it is
4736 arg_job_mode = "fail";
4739 case ARG_IGNORE_DEPENDENCIES:
4740 arg_job_mode = "ignore-dependencies";
4744 arg_scope = UNIT_FILE_USER;
4748 arg_scope = UNIT_FILE_SYSTEM;
4752 arg_scope = UNIT_FILE_GLOBAL;
4756 arg_no_block = true;
4760 arg_no_legend = true;
4764 arg_no_pager = true;
4772 arg_dot = DOT_ORDER;
4776 arg_dot = DOT_REQUIRE;
4804 /* -f is short for both --follow and --force! */
4810 arg_no_reload = true;
4814 arg_kill_who = optarg;
4818 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
4819 log_error("Failed to parse signal string %s.", optarg);
4824 case ARG_NO_ASK_PASSWORD:
4825 arg_ask_password = false;
4829 arg_transport = TRANSPORT_POLKIT;
4833 arg_transport = TRANSPORT_SSH;
4842 if (safe_atou(optarg, &arg_lines) < 0) {
4843 log_error("Failed to parse lines '%s'", optarg);
4849 arg_output = output_mode_from_string(optarg);
4850 if (arg_output < 0) {
4851 log_error("Unknown output '%s'.", optarg);
4860 log_error("Unknown option code '%c'.", c);
4865 if (arg_transport != TRANSPORT_NORMAL && arg_scope != UNIT_FILE_SYSTEM) {
4866 log_error("Cannot access user instance remotely.");
4873 static int halt_parse_argv(int argc, char *argv[]) {
4882 static const struct option options[] = {
4883 { "help", no_argument, NULL, ARG_HELP },
4884 { "halt", no_argument, NULL, ARG_HALT },
4885 { "poweroff", no_argument, NULL, 'p' },
4886 { "reboot", no_argument, NULL, ARG_REBOOT },
4887 { "force", no_argument, NULL, 'f' },
4888 { "wtmp-only", no_argument, NULL, 'w' },
4889 { "no-wtmp", no_argument, NULL, 'd' },
4890 { "no-sync", no_argument, NULL, 'n' },
4891 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4892 { NULL, 0, NULL, 0 }
4900 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
4901 if (runlevel == '0' || runlevel == '6')
4904 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
4912 arg_action = ACTION_HALT;
4916 if (arg_action != ACTION_REBOOT)
4917 arg_action = ACTION_POWEROFF;
4921 arg_action = ACTION_REBOOT;
4946 /* Compatibility nops */
4953 log_error("Unknown option code '%c'.", c);
4958 if (optind < argc) {
4959 log_error("Too many arguments.");
4966 static int parse_time_spec(const char *t, usec_t *_u) {
4970 if (streq(t, "now"))
4972 else if (!strchr(t, ':')) {
4975 if (safe_atou64(t, &u) < 0)
4978 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
4987 hour = strtol(t, &e, 10);
4988 if (errno != 0 || *e != ':' || hour < 0 || hour > 23)
4991 minute = strtol(e+1, &e, 10);
4992 if (errno != 0 || *e != 0 || minute < 0 || minute > 59)
4995 n = now(CLOCK_REALTIME);
4996 s = (time_t) (n / USEC_PER_SEC);
4999 assert_se(localtime_r(&s, &tm));
5001 tm.tm_hour = (int) hour;
5002 tm.tm_min = (int) minute;
5005 assert_se(s = mktime(&tm));
5007 *_u = (usec_t) s * USEC_PER_SEC;
5010 *_u += USEC_PER_DAY;
5016 static int shutdown_parse_argv(int argc, char *argv[]) {
5023 static const struct option options[] = {
5024 { "help", no_argument, NULL, ARG_HELP },
5025 { "halt", no_argument, NULL, 'H' },
5026 { "poweroff", no_argument, NULL, 'P' },
5027 { "reboot", no_argument, NULL, 'r' },
5028 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
5029 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5030 { NULL, 0, NULL, 0 }
5038 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
5046 arg_action = ACTION_HALT;
5050 arg_action = ACTION_POWEROFF;
5055 arg_action = ACTION_KEXEC;
5057 arg_action = ACTION_REBOOT;
5061 arg_action = ACTION_KEXEC;
5065 if (arg_action != ACTION_HALT)
5066 arg_action = ACTION_POWEROFF;
5079 /* Compatibility nops */
5083 arg_action = ACTION_CANCEL_SHUTDOWN;
5090 log_error("Unknown option code '%c'.", c);
5095 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
5096 r = parse_time_spec(argv[optind], &arg_when);
5098 log_error("Failed to parse time specification: %s", argv[optind]);
5102 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
5104 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
5105 /* No time argument for shutdown cancel */
5106 arg_wall = argv + optind;
5107 else if (argc > optind + 1)
5108 /* We skip the time argument */
5109 arg_wall = argv + optind + 1;
5116 static int telinit_parse_argv(int argc, char *argv[]) {
5123 static const struct option options[] = {
5124 { "help", no_argument, NULL, ARG_HELP },
5125 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5126 { NULL, 0, NULL, 0 }
5129 static const struct {
5133 { '0', ACTION_POWEROFF },
5134 { '6', ACTION_REBOOT },
5135 { '1', ACTION_RESCUE },
5136 { '2', ACTION_RUNLEVEL2 },
5137 { '3', ACTION_RUNLEVEL3 },
5138 { '4', ACTION_RUNLEVEL4 },
5139 { '5', ACTION_RUNLEVEL5 },
5140 { 's', ACTION_RESCUE },
5141 { 'S', ACTION_RESCUE },
5142 { 'q', ACTION_RELOAD },
5143 { 'Q', ACTION_RELOAD },
5144 { 'u', ACTION_REEXEC },
5145 { 'U', ACTION_REEXEC }
5154 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
5169 log_error("Unknown option code '%c'.", c);
5174 if (optind >= argc) {
5179 if (optind + 1 < argc) {
5180 log_error("Too many arguments.");
5184 if (strlen(argv[optind]) != 1) {
5185 log_error("Expected single character argument.");
5189 for (i = 0; i < ELEMENTSOF(table); i++)
5190 if (table[i].from == argv[optind][0])
5193 if (i >= ELEMENTSOF(table)) {
5194 log_error("Unknown command '%s'.", argv[optind]);
5198 arg_action = table[i].to;
5205 static int runlevel_parse_argv(int argc, char *argv[]) {
5211 static const struct option options[] = {
5212 { "help", no_argument, NULL, ARG_HELP },
5213 { NULL, 0, NULL, 0 }
5221 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
5232 log_error("Unknown option code '%c'.", c);
5237 if (optind < argc) {
5238 log_error("Too many arguments.");
5245 static int parse_argv(int argc, char *argv[]) {
5249 if (program_invocation_short_name) {
5251 if (strstr(program_invocation_short_name, "halt")) {
5252 arg_action = ACTION_HALT;
5253 return halt_parse_argv(argc, argv);
5254 } else if (strstr(program_invocation_short_name, "poweroff")) {
5255 arg_action = ACTION_POWEROFF;
5256 return halt_parse_argv(argc, argv);
5257 } else if (strstr(program_invocation_short_name, "reboot")) {
5259 arg_action = ACTION_KEXEC;
5261 arg_action = ACTION_REBOOT;
5262 return halt_parse_argv(argc, argv);
5263 } else if (strstr(program_invocation_short_name, "shutdown")) {
5264 arg_action = ACTION_POWEROFF;
5265 return shutdown_parse_argv(argc, argv);
5266 } else if (strstr(program_invocation_short_name, "init")) {
5268 if (sd_booted() > 0) {
5269 arg_action = ACTION_INVALID;
5270 return telinit_parse_argv(argc, argv);
5272 /* Hmm, so some other init system is
5273 * running, we need to forward this
5274 * request to it. For now we simply
5275 * guess that it is Upstart. */
5277 execv("/lib/upstart/telinit", argv);
5279 log_error("Couldn't find an alternative telinit implementation to spawn.");
5283 } else if (strstr(program_invocation_short_name, "runlevel")) {
5284 arg_action = ACTION_RUNLEVEL;
5285 return runlevel_parse_argv(argc, argv);
5289 arg_action = ACTION_SYSTEMCTL;
5290 return systemctl_parse_argv(argc, argv);
5293 static int action_to_runlevel(void) {
5295 static const char table[_ACTION_MAX] = {
5296 [ACTION_HALT] = '0',
5297 [ACTION_POWEROFF] = '0',
5298 [ACTION_REBOOT] = '6',
5299 [ACTION_RUNLEVEL2] = '2',
5300 [ACTION_RUNLEVEL3] = '3',
5301 [ACTION_RUNLEVEL4] = '4',
5302 [ACTION_RUNLEVEL5] = '5',
5303 [ACTION_RESCUE] = '1'
5306 assert(arg_action < _ACTION_MAX);
5308 return table[arg_action];
5311 static int talk_upstart(void) {
5312 DBusMessage *m = NULL, *reply = NULL;
5314 int previous, rl, r;
5316 env1_buf[] = "RUNLEVEL=X",
5317 env2_buf[] = "PREVLEVEL=X";
5318 char *env1 = env1_buf, *env2 = env2_buf;
5319 const char *emit = "runlevel";
5320 dbus_bool_t b_false = FALSE;
5321 DBusMessageIter iter, sub;
5322 DBusConnection *bus;
5324 dbus_error_init(&error);
5326 if (!(rl = action_to_runlevel()))
5329 if (utmp_get_runlevel(&previous, NULL) < 0)
5332 if (!(bus = dbus_connection_open_private("unix:abstract=/com/ubuntu/upstart", &error))) {
5333 if (dbus_error_has_name(&error, DBUS_ERROR_NO_SERVER)) {
5338 log_error("Failed to connect to Upstart bus: %s", bus_error_message(&error));
5343 if ((r = bus_check_peercred(bus)) < 0) {
5344 log_error("Failed to verify owner of bus.");
5348 if (!(m = dbus_message_new_method_call(
5349 "com.ubuntu.Upstart",
5350 "/com/ubuntu/Upstart",
5351 "com.ubuntu.Upstart0_6",
5354 log_error("Could not allocate message.");
5359 dbus_message_iter_init_append(m, &iter);
5361 env1_buf[sizeof(env1_buf)-2] = rl;
5362 env2_buf[sizeof(env2_buf)-2] = previous;
5364 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &emit) ||
5365 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub) ||
5366 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env1) ||
5367 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env2) ||
5368 !dbus_message_iter_close_container(&iter, &sub) ||
5369 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b_false)) {
5370 log_error("Could not append arguments to message.");
5375 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
5377 if (error_is_no_service(&error)) {
5382 log_error("Failed to issue method call: %s", bus_error_message(&error));
5391 dbus_message_unref(m);
5394 dbus_message_unref(reply);
5397 dbus_connection_flush(bus);
5398 dbus_connection_close(bus);
5399 dbus_connection_unref(bus);
5402 dbus_error_free(&error);
5407 static int talk_initctl(void) {
5408 struct init_request request;
5412 if (!(rl = action_to_runlevel()))
5416 request.magic = INIT_MAGIC;
5417 request.sleeptime = 0;
5418 request.cmd = INIT_CMD_RUNLVL;
5419 request.runlevel = rl;
5421 if ((fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY)) < 0) {
5423 if (errno == ENOENT)
5426 log_error("Failed to open "INIT_FIFO": %m");
5431 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
5432 close_nointr_nofail(fd);
5435 log_error("Failed to write to "INIT_FIFO": %m");
5436 return errno ? -errno : -EIO;
5442 static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
5444 static const struct {
5452 int (* const dispatch)(DBusConnection *bus, char **args);
5454 { "list-units", LESS, 1, list_units },
5455 { "list-unit-files", EQUAL, 1, list_unit_files },
5456 { "list-jobs", EQUAL, 1, list_jobs },
5457 { "clear-jobs", EQUAL, 1, daemon_reload },
5458 { "load", MORE, 2, load_unit },
5459 { "cancel", MORE, 2, cancel_job },
5460 { "start", MORE, 2, start_unit },
5461 { "stop", MORE, 2, start_unit },
5462 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5463 { "reload", MORE, 2, start_unit },
5464 { "restart", MORE, 2, start_unit },
5465 { "try-restart", MORE, 2, start_unit },
5466 { "reload-or-restart", MORE, 2, start_unit },
5467 { "reload-or-try-restart", MORE, 2, start_unit },
5468 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
5469 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5470 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
5471 { "isolate", EQUAL, 2, start_unit },
5472 { "kill", MORE, 2, kill_unit },
5473 { "is-active", MORE, 2, check_unit },
5474 { "check", MORE, 2, check_unit },
5475 { "show", MORE, 1, show },
5476 { "status", MORE, 2, show },
5477 { "help", MORE, 2, show },
5478 { "dump", EQUAL, 1, dump },
5479 { "dot", EQUAL, 1, dot },
5480 { "snapshot", LESS, 2, snapshot },
5481 { "delete", MORE, 2, delete_snapshot },
5482 { "daemon-reload", EQUAL, 1, daemon_reload },
5483 { "daemon-reexec", EQUAL, 1, daemon_reload },
5484 { "show-environment", EQUAL, 1, show_enviroment },
5485 { "set-environment", MORE, 2, set_environment },
5486 { "unset-environment", MORE, 2, set_environment },
5487 { "halt", EQUAL, 1, start_special },
5488 { "poweroff", EQUAL, 1, start_special },
5489 { "reboot", EQUAL, 1, start_special },
5490 { "kexec", EQUAL, 1, start_special },
5491 { "suspend", EQUAL, 1, start_special },
5492 { "hibernate", EQUAL, 1, start_special },
5493 { "default", EQUAL, 1, start_special },
5494 { "rescue", EQUAL, 1, start_special },
5495 { "emergency", EQUAL, 1, start_special },
5496 { "exit", EQUAL, 1, start_special },
5497 { "reset-failed", MORE, 1, reset_failed },
5498 { "enable", MORE, 2, enable_unit },
5499 { "disable", MORE, 2, enable_unit },
5500 { "is-enabled", MORE, 2, unit_is_enabled },
5501 { "reenable", MORE, 2, enable_unit },
5502 { "preset", MORE, 2, enable_unit },
5503 { "mask", MORE, 2, enable_unit },
5504 { "unmask", MORE, 2, enable_unit },
5505 { "link", MORE, 2, enable_unit },
5506 { "switch-root", MORE, 2, switch_root },
5516 left = argc - optind;
5519 /* Special rule: no arguments means "list-units" */
5522 if (streq(argv[optind], "help") && !argv[optind+1]) {
5523 log_error("This command expects one or more "
5524 "unit names. Did you mean --help?");
5528 for (i = 0; i < ELEMENTSOF(verbs); i++)
5529 if (streq(argv[optind], verbs[i].verb))
5532 if (i >= ELEMENTSOF(verbs)) {
5533 log_error("Unknown operation '%s'.", argv[optind]);
5538 switch (verbs[i].argc_cmp) {
5541 if (left != verbs[i].argc) {
5542 log_error("Invalid number of arguments.");
5549 if (left < verbs[i].argc) {
5550 log_error("Too few arguments.");
5557 if (left > verbs[i].argc) {
5558 log_error("Too many arguments.");
5565 assert_not_reached("Unknown comparison operator.");
5568 /* Require a bus connection for all operations but
5570 if (!streq(verbs[i].verb, "enable") &&
5571 !streq(verbs[i].verb, "disable") &&
5572 !streq(verbs[i].verb, "is-enabled") &&
5573 !streq(verbs[i].verb, "list-unit-files") &&
5574 !streq(verbs[i].verb, "reenable") &&
5575 !streq(verbs[i].verb, "preset") &&
5576 !streq(verbs[i].verb, "mask") &&
5577 !streq(verbs[i].verb, "unmask") &&
5578 !streq(verbs[i].verb, "link")) {
5580 if (running_in_chroot() > 0) {
5581 log_info("Running in chroot, ignoring request.");
5585 if (((!streq(verbs[i].verb, "reboot") &&
5586 !streq(verbs[i].verb, "halt") &&
5587 !streq(verbs[i].verb, "poweroff")) || arg_force <= 0) && !bus) {
5588 log_error("Failed to get D-Bus connection: %s",
5589 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5595 if (!bus && !avoid_bus()) {
5596 log_error("Failed to get D-Bus connection: %s",
5597 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5602 return verbs[i].dispatch(bus, argv + optind);
5605 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
5607 struct msghdr msghdr;
5608 struct iovec iovec[2];
5609 union sockaddr_union sockaddr;
5610 struct sd_shutdown_command c;
5612 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
5619 c.dry_run = dry_run;
5623 sockaddr.sa.sa_family = AF_UNIX;
5624 strncpy(sockaddr.un.sun_path, "/run/systemd/shutdownd", sizeof(sockaddr.un.sun_path));
5627 msghdr.msg_name = &sockaddr;
5628 msghdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + sizeof("/run/systemd/shutdownd") - 1;
5631 iovec[0].iov_base = (char*) &c;
5632 iovec[0].iov_len = offsetof(struct sd_shutdown_command, wall_message);
5634 if (isempty(message))
5635 msghdr.msg_iovlen = 1;
5637 iovec[1].iov_base = (char*) message;
5638 iovec[1].iov_len = strlen(message);
5639 msghdr.msg_iovlen = 2;
5641 msghdr.msg_iov = iovec;
5643 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0) {
5644 close_nointr_nofail(fd);
5648 close_nointr_nofail(fd);
5652 static int reload_with_fallback(DBusConnection *bus) {
5655 /* First, try systemd via D-Bus. */
5656 if (daemon_reload(bus, NULL) >= 0)
5660 /* Nothing else worked, so let's try signals */
5661 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
5663 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
5664 log_error("kill() failed: %m");
5671 static int start_with_fallback(DBusConnection *bus) {
5674 /* First, try systemd via D-Bus. */
5675 if (start_unit(bus, NULL) >= 0)
5679 /* Hmm, talking to systemd via D-Bus didn't work. Then
5680 * let's try to talk to Upstart via D-Bus. */
5681 if (talk_upstart() > 0)
5684 /* Nothing else worked, so let's try
5686 if (talk_initctl() > 0)
5689 log_error("Failed to talk to init daemon.");
5693 warn_wall(arg_action);
5697 static _noreturn_ void halt_now(enum action a) {
5699 /* Make sure C-A-D is handled by the kernel from this
5701 reboot(RB_ENABLE_CAD);
5706 log_info("Halting.");
5707 reboot(RB_HALT_SYSTEM);
5710 case ACTION_POWEROFF:
5711 log_info("Powering off.");
5712 reboot(RB_POWER_OFF);
5716 log_info("Rebooting.");
5717 reboot(RB_AUTOBOOT);
5721 assert_not_reached("Unknown halt action.");
5724 assert_not_reached("Uh? This shouldn't happen.");
5727 static int halt_main(DBusConnection *bus) {
5730 if (geteuid() != 0) {
5731 /* Try logind if we are a normal user and no special
5732 * mode applies. Maybe PolicyKit allows us to shutdown
5735 if (arg_when <= 0 &&
5738 (arg_action == ACTION_POWEROFF ||
5739 arg_action == ACTION_REBOOT)) {
5740 r = reboot_with_logind(bus, arg_action);
5745 log_error("Must be root.");
5752 m = strv_join(arg_wall, " ");
5753 r = send_shutdownd(arg_when,
5754 arg_action == ACTION_HALT ? 'H' :
5755 arg_action == ACTION_POWEROFF ? 'P' :
5756 arg_action == ACTION_KEXEC ? 'K' :
5764 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
5766 char date[FORMAT_TIMESTAMP_MAX];
5768 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
5769 format_timestamp(date, sizeof(date), arg_when));
5774 if (!arg_dry && !arg_force)
5775 return start_with_fallback(bus);
5778 if (sd_booted() > 0)
5779 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
5781 r = utmp_put_shutdown();
5783 log_warning("Failed to write utmp record: %s", strerror(-r));
5793 halt_now(arg_action);
5794 /* We should never reach this. */
5798 static int runlevel_main(void) {
5799 int r, runlevel, previous;
5801 r = utmp_get_runlevel(&runlevel, &previous);
5808 previous <= 0 ? 'N' : previous,
5809 runlevel <= 0 ? 'N' : runlevel);
5814 int main(int argc, char*argv[]) {
5815 int r, retval = EXIT_FAILURE;
5816 DBusConnection *bus = NULL;
5819 dbus_error_init(&error);
5821 log_parse_environment();
5824 r = parse_argv(argc, argv);
5828 retval = EXIT_SUCCESS;
5832 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
5833 * let's shortcut this */
5834 if (arg_action == ACTION_RUNLEVEL) {
5835 r = runlevel_main();
5836 retval = r < 0 ? EXIT_FAILURE : r;
5840 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
5841 log_info("Running in chroot, ignoring request.");
5847 if (arg_transport == TRANSPORT_NORMAL)
5848 bus_connect(arg_scope == UNIT_FILE_SYSTEM ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &bus, &private_bus, &error);
5849 else if (arg_transport == TRANSPORT_POLKIT) {
5850 bus_connect_system_polkit(&bus, &error);
5851 private_bus = false;
5852 } else if (arg_transport == TRANSPORT_SSH) {
5853 bus_connect_system_ssh(NULL, arg_host, &bus, &error);
5854 private_bus = false;
5856 assert_not_reached("Uh, invalid transport...");
5859 switch (arg_action) {
5861 case ACTION_SYSTEMCTL:
5862 r = systemctl_main(bus, argc, argv, &error);
5866 case ACTION_POWEROFF:
5872 case ACTION_RUNLEVEL2:
5873 case ACTION_RUNLEVEL3:
5874 case ACTION_RUNLEVEL4:
5875 case ACTION_RUNLEVEL5:
5877 case ACTION_EMERGENCY:
5878 case ACTION_DEFAULT:
5879 r = start_with_fallback(bus);
5884 r = reload_with_fallback(bus);
5887 case ACTION_CANCEL_SHUTDOWN: {
5891 m = strv_join(arg_wall, " ");
5893 retval = EXIT_FAILURE;
5897 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
5899 log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r));
5904 case ACTION_INVALID:
5905 case ACTION_RUNLEVEL:
5907 assert_not_reached("Unknown action");
5910 retval = r < 0 ? EXIT_FAILURE : r;
5914 dbus_connection_flush(bus);
5915 dbus_connection_close(bus);
5916 dbus_connection_unref(bus);
5919 dbus_error_free(&error);
5923 strv_free(arg_property);
5926 ask_password_agent_close();
5927 polkit_agent_close();