diff options
author | Lennart Poettering <lennart@poettering.net> | 2012-05-05 02:06:58 +0200 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2012-05-08 13:54:23 +0200 |
commit | 6edd7d0a09171ea5ae8e01b7b1cbcb0bdfbfeb16 (patch) | |
tree | 85a09e06fd5dfc98cb198fafb9a33b70e79a4c63 /src | |
parent | 4943c1c94ba751c98763f4232b4350481b22c90a (diff) |
sleep: implement suspend/hibernate as first class targets
Diffstat (limited to 'src')
-rw-r--r-- | src/core/shutdown.c | 6 | ||||
-rw-r--r-- | src/core/special.h | 2 | ||||
-rw-r--r-- | src/shared/util.c | 3 | ||||
l--------- | src/sleep/Makefile | 1 | ||||
-rw-r--r-- | src/sleep/sleep.c | 83 | ||||
-rw-r--r-- | src/systemctl/systemctl.c | 16 |
6 files changed, 106 insertions, 5 deletions
diff --git a/src/core/shutdown.c b/src/core/shutdown.c index 2494bb86a1..a8dfe2614f 100644 --- a/src/core/shutdown.c +++ b/src/core/shutdown.c @@ -309,6 +309,7 @@ int main(int argc, char *argv[]) { unsigned retries; bool need_umount = true, need_swapoff = true, need_loop_detach = true, need_dm_detach = true; bool killed_everbody = false, in_container, use_watchdog = false; + char *arguments[3]; log_parse_environment(); log_set_target(LOG_TARGET_CONSOLE); /* syslog will die if not gone yet */ @@ -442,7 +443,10 @@ int main(int argc, char *argv[]) { if (retries >= FINALIZE_ATTEMPTS) log_error("Too many iterations, giving up."); - execute_directory(SYSTEM_SHUTDOWN_PATH, NULL, NULL); + arguments[0] = NULL; + arguments[1] = argv[1]; + arguments[2] = NULL; + execute_directory(SYSTEM_SHUTDOWN_PATH, NULL, arguments); /* If we are in a container, just exit, this will kill our * container for good. */ diff --git a/src/core/special.h b/src/core/special.h index 2db4711c2e..bc9b330ffb 100644 --- a/src/core/special.h +++ b/src/core/special.h @@ -36,6 +36,8 @@ #define SPECIAL_REBOOT_TARGET "reboot.target" #define SPECIAL_KEXEC_TARGET "kexec.target" #define SPECIAL_EXIT_TARGET "exit.target" +#define SPECIAL_SUSPEND_TARGET "suspend.target" +#define SPECIAL_HIBERNATE_TARGET "hibernate.target" /* Special boot targets */ #define SPECIAL_RESCUE_TARGET "rescue.target" diff --git a/src/shared/util.c b/src/shared/util.c index 8a0b2a1b46..d8d3f1a16d 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -4106,8 +4106,7 @@ void execute_directory(const char *directory, DIR *d, char *argv[]) { _argv[1] = NULL; argv = _argv; } else - if (!argv[0]) - argv[0] = path; + argv[0] = path; execv(path, argv); diff --git a/src/sleep/Makefile b/src/sleep/Makefile new file mode 120000 index 0000000000..d0b0e8e008 --- /dev/null +++ b/src/sleep/Makefile @@ -0,0 +1 @@ +../Makefile
\ No newline at end of file diff --git a/src/sleep/sleep.c b/src/sleep/sleep.c new file mode 100644 index 0000000000..7062dc242f --- /dev/null +++ b/src/sleep/sleep.c @@ -0,0 +1,83 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/*** + This file is part of systemd. + + Copyright 2012 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + +#include <stdio.h> +#include <errno.h> +#include <string.h> + +#include "log.h" +#include "util.h" + +int main(int argc, char *argv[]) { + const char *verb; + char* arguments[4]; + int r; + FILE *f; + + log_set_target(LOG_TARGET_AUTO); + log_parse_environment(); + log_open(); + + if (argc != 2) { + log_error("Invalid number of arguments."); + r = -EINVAL; + goto finish; + } + + if (streq(argv[1], "suspend")) + verb = "mem"; + else if (streq(argv[1], "hibernate")) + verb = "disk"; + else { + log_error("Unknown action '%s'.", argv[1]); + r = -EINVAL; + goto finish; + } + + f = fopen("/sys/power/state", "we"); + if (!f) { + log_error("Failed to open /sys/power/state: %m"); + r = -errno; + goto finish; + } + + arguments[0] = NULL; + arguments[1] = (char*) "pre"; + arguments[2] = argv[1]; + arguments[3] = NULL; + execute_directory(SYSTEMD_SLEEP_BINARY_PATH, NULL, arguments); + + fputs(verb, f); + fputc('\n', f); + fflush(f); + + r = ferror(f) ? -errno : 0; + + arguments[1] = (char*) "post"; + execute_directory(SYSTEMD_SLEEP_BINARY_PATH, NULL, arguments); + + fclose(f); + +finish: + + return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; + +} diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index acede4e765..762b5be346 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; @@ -4201,7 +4209,9 @@ 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" + " suspend Suspend the system\n" + " hibernate Hibernate the system\n", program_invocation_short_name); return 0; @@ -5135,6 +5145,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 }, |