X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fsystemctl%2Fsystemctl.c;h=0034c553840514c805f400672baa764ffd8e8b97;hb=957eb8cab28dc83aa4b800d033031e53cd0a9e00;hp=acede4e765959ce32a2d136b6cc911de2e74b6ab;hpb=9eb977db5b89b44f254ab40c1876a76b7d7ea2d0;p=elogind.git diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index acede4e76..0034c5538 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -97,6 +97,8 @@ static enum action { ACTION_REBOOT, ACTION_KEXEC, ACTION_EXIT, + ACTION_SUSPEND, + ACTION_HIBERNATE, ACTION_RUNLEVEL2, ACTION_RUNLEVEL3, ACTION_RUNLEVEL4, @@ -1605,6 +1607,10 @@ static enum action verb_to_action(const char *verb) { return ACTION_DEFAULT; else if (streq(verb, "exit")) return ACTION_EXIT; + else if (streq(verb, "suspend")) + return ACTION_SUSPEND; + else if (streq(verb, "hibernate")) + return ACTION_HIBERNATE; else return ACTION_INVALID; } @@ -1623,7 +1629,9 @@ static int start_unit(DBusConnection *bus, char **args) { [ACTION_RESCUE] = SPECIAL_RESCUE_TARGET, [ACTION_EMERGENCY] = SPECIAL_EMERGENCY_TARGET, [ACTION_DEFAULT] = SPECIAL_DEFAULT_TARGET, - [ACTION_EXIT] = SPECIAL_EXIT_TARGET + [ACTION_EXIT] = SPECIAL_EXIT_TARGET, + [ACTION_SUSPEND] = SPECIAL_SUSPEND_TARGET, + [ACTION_HIBERNATE] = SPECIAL_HIBERNATE_TARGET }; int r, ret = 0; @@ -1742,6 +1750,14 @@ static int reboot_with_logind(DBusConnection *bus, enum action a) { method = "PowerOff"; break; + case ACTION_SUSPEND: + method = "Suspend"; + break; + + case ACTION_HIBERNATE: + method = "Hibernate"; + break; + default: return -EINVAL; } @@ -1831,7 +1847,9 @@ static int start_special(DBusConnection *bus, char **args) { /* first try logind, to allow authentication with polkit */ if (geteuid() != 0 && (a == ACTION_POWEROFF || - a == ACTION_REBOOT)) { + a == ACTION_REBOOT || + a == ACTION_SUSPEND || + a == ACTION_HIBERNATE)) { r = reboot_with_logind(bus, a); if (r >= 0) return r; @@ -3562,6 +3580,65 @@ finish: return r; } +static int switch_root(DBusConnection *bus, char **args) { + DBusMessage *m = NULL, *reply = NULL; + unsigned l; + const char *root, *init; + DBusError error; + int r; + + dbus_error_init(&error); + + l = strv_length(args); + if (l < 2 || l > 3) { + log_error("Wrong number of arguments."); + return -EINVAL; + } + + root = args[1]; + init = l >= 3 ? args[2] : ""; + + m = dbus_message_new_method_call( + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "SwitchRoot"); + if (!m) { + log_error("Could not allocate message."); + return -ENOMEM; + } + + if (!dbus_message_append_args( + m, + DBUS_TYPE_STRING, &root, + DBUS_TYPE_STRING, &init, + DBUS_TYPE_INVALID)) { + log_error("Could not append arguments to message."); + r = -ENOMEM; + goto finish; + } + + reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error); + if (!reply) { + log_error("Failed to issue method call: %s", bus_error_message(&error)); + r = -EIO; + goto finish; + } + + r = 0; + +finish: + if (m) + dbus_message_unref(m); + + if (reply) + dbus_message_unref(reply); + + dbus_error_free(&error); + + return r; +} + static int set_environment(DBusConnection *bus, char **args) { DBusMessage *m = NULL, *reply = NULL; DBusError error; @@ -4201,7 +4278,10 @@ static int systemctl_help(void) { " poweroff Shut down and power-off the system\n" " reboot Shut down and reboot the system\n" " kexec Shut down and reboot the system with kexec\n" - " exit Ask for user instance termination\n", + " exit Request user instance exit\n" + " switch-root [ROOT] [INIT] Change to a different root file system\n" + " suspend Suspend the system\n" + " hibernate Hibernate the system\n", program_invocation_short_name); return 0; @@ -5135,6 +5215,8 @@ static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError { "poweroff", EQUAL, 1, start_special }, { "reboot", EQUAL, 1, start_special }, { "kexec", EQUAL, 1, start_special }, + { "suspend", EQUAL, 1, start_special }, + { "hibernate", EQUAL, 1, start_special }, { "default", EQUAL, 1, start_special }, { "rescue", EQUAL, 1, start_special }, { "emergency", EQUAL, 1, start_special }, @@ -5147,7 +5229,8 @@ static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError { "preset", MORE, 2, enable_unit }, { "mask", MORE, 2, enable_unit }, { "unmask", MORE, 2, enable_unit }, - { "link", MORE, 2, enable_unit } + { "link", MORE, 2, enable_unit }, + { "switch-root", MORE, 2, switch_root }, }; int left;