[systemd-commits] 9 commits - .gitignore Makefile.am TODO man/logind.conf.xml man/systemctl.xml man/systemd-inhibit.xml man/systemd.special.xml src/core src/login src/shared src/sleep src/systemctl units/.gitignore units/hibernate.service.in units/hibernate.target units/sleep.target units/suspend.service.in units/suspend.target
Lennart Poettering
lennart at kemper.freedesktop.org
Tue May 8 16:36:16 PDT 2012
.gitignore | 1
Makefile.am | 18 -
TODO | 14
man/logind.conf.xml | 11
man/systemctl.xml | 10
man/systemd-inhibit.xml | 8
man/systemd.special.xml | 34 +
src/core/dbus-manager.c | 52 ++
src/core/main.c | 194 +++++++----
src/core/manager.c | 3
src/core/manager.h | 4
src/core/shutdown.c | 6
src/core/special.h | 2
src/login/inhibit.c | 6
src/login/logind-dbus.c | 505 +++++++++++++++++++----------
src/login/logind-inhibit.c | 16
src/login/logind-inhibit.h | 8
src/login/logind.c | 6
src/login/logind.h | 7
src/login/org.freedesktop.login1.conf | 16
src/login/org.freedesktop.login1.policy.in | 84 ++++
src/login/test-inhibit.c | 14
src/shared/path-util.h | 1
src/shared/util.c | 51 ++
src/shared/util.h | 2
src/sleep/Makefile | 1
src/sleep/sleep.c | 83 ++++
src/systemctl/systemctl.c | 28 +
units/.gitignore | 2
units/hibernate.service.in | 16
units/hibernate.target | 14
units/sleep.target | 13
units/suspend.service.in | 16
units/suspend.target | 14
34 files changed, 951 insertions(+), 309 deletions(-)
New commits:
commit 07f74a7ebde5acf098ab72dc49a3371731ffb476
Author: Lennart Poettering <lennart at poettering.net>
Date: Wed May 9 01:26:30 2012 +0200
update TODO
diff --git a/TODO b/TODO
index 47a890d..d2bb326 100644
--- a/TODO
+++ b/TODO
@@ -22,6 +22,11 @@ Bugfixes:
* properly handle .mount unit state tracking when two mount points are stacked one on top of another on the exact same mount point.
Features:
+
+* expose switch-root in systemctl
+
+* remove old root in switch-root logic
+
* improve !/proc/*/loginuid situation: make /proc/*/loginuid less dependent on CONFIG_AUDIT,
or use the users cgroup information when /proc/*/loginuid is not available.
commit d4d046e3fdf198be0d329ea79b30f56ae6bbb4d7
Author: Lennart Poettering <lennart at poettering.net>
Date: Wed May 9 01:25:52 2012 +0200
util: a few updates for rm_rf()
diff --git a/src/shared/util.c b/src/shared/util.c
index 5f06c4b..c9899fb 100644
--- a/src/shared/util.c
+++ b/src/shared/util.c
@@ -3139,7 +3139,8 @@ static int rm_rf_children(int fd, bool only_dirs, bool honour_sticky) {
/* This returns the first error we run into, but nevertheless
* tries to go on */
- if (!(d = fdopendir(fd))) {
+ d = fdopendir(fd);
+ if (!d) {
close_nointr_nofail(fd);
return errno == ENOENT ? 0 : -errno;
@@ -3150,9 +3151,9 @@ static int rm_rf_children(int fd, bool only_dirs, bool honour_sticky) {
bool is_dir, keep_around = false;
int r;
- if ((r = readdir_r(d, &buf, &de)) != 0) {
- if (ret == 0)
- ret = -r;
+ r = readdir_r(d, &buf, &de);
+ if (r != 0 && ret == 0) {
+ ret = -r;
break;
}
@@ -3199,17 +3200,16 @@ static int rm_rf_children(int fd, bool only_dirs, bool honour_sticky) {
if (is_dir) {
int subdir_fd;
- subdir_fd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
+ subdir_fd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME);
if (subdir_fd < 0) {
if (ret == 0 && errno != ENOENT)
ret = -errno;
continue;
}
- if ((r = rm_rf_children(subdir_fd, only_dirs, honour_sticky)) < 0) {
- if (ret == 0)
- ret = r;
- }
+ r = rm_rf_children(subdir_fd, only_dirs, honour_sticky);
+ if (r < 0 && ret == 0)
+ ret = r;
if (!keep_around)
if (unlinkat(fd, de->d_name, AT_REMOVEDIR) < 0) {
@@ -3237,13 +3237,14 @@ int rm_rf(const char *path, bool only_dirs, bool delete_root, bool honour_sticky
assert(path);
- if ((fd = open(path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC)) < 0) {
+ fd = open(path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME);
+ if (fd < 0) {
if (errno != ENOTDIR)
return -errno;
if (delete_root && !only_dirs)
- if (unlink(path) < 0)
+ if (unlink(path) < 0 && errno != ENOENT)
return -errno;
return 0;
commit 664f88a7e653918942b858e3f387be2ebc9ebf03
Author: Lennart Poettering <lennart at poettering.net>
Date: Wed May 9 01:24:50 2012 +0200
manager: introduce SwitchRoot bus call for initrd/main transition
diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c
index bdc9192..2e6bc3d 100644
--- a/src/core/dbus-manager.c
+++ b/src/core/dbus-manager.c
@@ -32,6 +32,7 @@
#include "install.h"
#include "watchdog.h"
#include "hwclock.h"
+#include "path-util.h"
#define BUS_MANAGER_INTERFACE_BEGIN \
" <interface name=\"org.freedesktop.systemd1.Manager\">\n"
@@ -126,6 +127,10 @@
" <method name=\"PowerOff\"/>\n" \
" <method name=\"Halt\"/>\n" \
" <method name=\"KExec\"/>\n" \
+ " <method name=\"SwitchRoot\">\n" \
+ " <arg name=\"new_root\" type=\"s\" direction=\"in\"/>\n" \
+ " <arg name=\"init\" type=\"s\" direction=\"in\"/>\n" \
+ " </method>\n" \
" <method name=\"SetEnvironment\">\n" \
" <arg name=\"names\" type=\"as\" direction=\"in\"/>\n" \
" </method>\n" \
@@ -1177,6 +1182,53 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
m->exit_code = MANAGER_KEXEC;
+ } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "SwitchRoot")) {
+ const char *switch_root, *switch_root_init;
+ char *u, *v;
+
+ if (!dbus_message_get_args(
+ message,
+ &error,
+ DBUS_TYPE_STRING, &switch_root,
+ DBUS_TYPE_STRING, &switch_root_init,
+ DBUS_TYPE_INVALID))
+ return bus_send_error_reply(connection, message, &error, -EINVAL);
+
+ if (path_equal(switch_root, "/") || !is_path(switch_root))
+ return bus_send_error_reply(connection, message, NULL, -EINVAL);
+
+ if (!isempty(switch_root_init) && !is_path(switch_root_init))
+ return bus_send_error_reply(connection, message, NULL, -EINVAL);
+
+ if (m->running_as != MANAGER_SYSTEM) {
+ dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Switching root is only supported for system managers.");
+ return bus_send_error_reply(connection, message, &error, -ENOTSUP);
+ }
+
+ u = strdup(switch_root);
+ if (!u)
+ goto oom;
+
+ if (!isempty(switch_root_init)) {
+ v = strdup(switch_root_init);
+ if (!v) {
+ free(u);
+ goto oom;
+ }
+ } else
+ v = NULL;
+
+ free(m->switch_root);
+ free(m->switch_root_init);
+ m->switch_root = u;
+ m->switch_root_init = v;
+
+ reply = dbus_message_new_method_return(message);
+ if (!reply)
+ goto oom;
+
+ m->exit_code = MANAGER_SWITCH_ROOT;
+
} else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "SetEnvironment")) {
char **l = NULL, **e = NULL;
diff --git a/src/core/main.c b/src/core/main.c
index 5878099..d7ce8ab 100644
--- a/src/core/main.c
+++ b/src/core/main.c
@@ -32,6 +32,7 @@
#include <sys/wait.h>
#include <fcntl.h>
#include <sys/prctl.h>
+#include <sys/mount.h>
#include "manager.h"
#include "log.h"
@@ -47,6 +48,7 @@
#include "def.h"
#include "virt.h"
#include "watchdog.h"
+#include "path-util.h"
#include "mount-setup.h"
#include "loopback-setup.h"
@@ -1165,6 +1167,36 @@ static void test_cgroups(void) {
sleep(10);
}
+static int do_switch_root(const char *switch_root) {
+ int r;
+
+ if (path_equal(switch_root, "/"))
+ return 0;
+
+ if (chdir(switch_root) < 0) {
+ r = -errno;
+ goto fail;
+ }
+
+ if (mount(switch_root, "/", NULL, MS_MOVE, NULL) < 0) {
+ r = -errno;
+ chdir("/");
+ goto fail;
+ }
+
+ if (chroot(".") < 0)
+ log_warning("Failed to change root, ignoring: %s", strerror(-r));
+
+ /* FIXME: remove old root */
+
+ return 0;
+
+fail:
+ log_error("Failed to switch root, ignoring: %s", strerror(-r));
+
+ return r;
+}
+
int main(int argc, char *argv[]) {
Manager *m = NULL;
int r, retval = EXIT_FAILURE;
@@ -1179,6 +1211,7 @@ int main(int argc, char *argv[]) {
int j;
bool loaded_policy = false;
bool arm_reboot_watchdog = false;
+ char *switch_root = NULL, *switch_root_init = NULL;
#ifdef HAVE_SYSV_COMPAT
if (getpid() != 1 && strstr(program_invocation_short_name, "init")) {
@@ -1549,6 +1582,7 @@ int main(int argc, char *argv[]) {
break;
case MANAGER_REEXECUTE:
+
if (prepare_reexecute(m, &serialization, &fds) < 0)
goto finish;
@@ -1556,6 +1590,20 @@ int main(int argc, char *argv[]) {
log_notice("Reexecuting.");
goto finish;
+ case MANAGER_SWITCH_ROOT:
+ /* Steal the switch root parameters */
+ switch_root = m->switch_root;
+ switch_root_init = m->switch_root_init;
+ m->switch_root = m->switch_root_init = NULL;
+
+ if (!switch_root_init)
+ if (prepare_reexecute(m, &serialization, &fds) < 0)
+ goto finish;
+
+ reexecute = true;
+ log_notice("Switching root.");
+ goto finish;
+
case MANAGER_REBOOT:
case MANAGER_POWEROFF:
case MANAGER_HALT:
@@ -1588,66 +1636,66 @@ finish:
free_join_controllers();
dbus_shutdown();
-
label_finish();
if (reexecute) {
- const char *args[15];
- unsigned i = 0;
- char sfd[16];
+ const char **args;
+ unsigned i;
- assert(serialization);
- assert(fds);
+ /* Close and disarm the watchdog, so that the new
+ * instance can reinitialize it, but doesn't get
+ * rebooted while we do that */
+ watchdog_close(true);
- args[i++] = SYSTEMD_BINARY_PATH;
+ if (switch_root)
+ do_switch_root(switch_root);
- args[i++] = "--log-level";
- args[i++] = log_level_to_string(log_get_max_level());
+ args = newa(const char*, MAX(5, argc+1));
- args[i++] = "--log-target";
- args[i++] = log_target_to_string(log_get_target());
+ if (!switch_root_init) {
+ char sfd[16];
- if (arg_running_as == MANAGER_SYSTEM)
- args[i++] = "--system";
- else
- args[i++] = "--user";
+ /* First try to spawn ourselves with the right
+ * path, and with full serialization. We do
+ * this only if the user didn't specify an
+ * explicit init to spawn. */
- if (arg_dump_core)
- args[i++] = "--dump-core";
+ assert(serialization);
+ assert(fds);
- if (arg_crash_shell)
- args[i++] = "--crash-shell";
+ snprintf(sfd, sizeof(sfd), "%i", fileno(serialization));
+ char_array_0(sfd);
- if (arg_confirm_spawn)
- args[i++] = "--confirm-spawn";
+ i = 0;
+ args[i++] = SYSTEMD_BINARY_PATH;
+ args[i++] = arg_running_as == MANAGER_SYSTEM ? "--system" : "--user";
+ args[i++] = "--deserialize";
+ args[i++] = sfd;
+ args[i++] = NULL;
- if (arg_show_status)
- args[i++] = "--show-status=1";
- else
- args[i++] = "--show-status=0";
+ assert(i <= ELEMENTSOF(args));
+ execv(args[0], (char* const*) args);
+ }
-#ifdef HAVE_SYSV_COMPAT
- if (arg_sysv_console)
- args[i++] = "--sysv-console=1";
- else
- args[i++] = "--sysv-console=0";
-#endif
+ /* Try the fallback, if there is any, without any
+ * serialization. We pass the original argv[] and
+ * envp[]. (Well, modulo the ordering changes due to
+ * getopt() in argv[], and some cleanups in envp[],
+ * but let's hope that doesn't matter.) */
- snprintf(sfd, sizeof(sfd), "%i", fileno(serialization));
- char_array_0(sfd);
+ if (serialization)
+ fclose(serialization);
- args[i++] = "--deserialize";
- args[i++] = sfd;
+ if (fds)
+ fdset_free(fds);
+ i = 0;
+ args[i++] = switch_root_init ? switch_root_init : "/sbin/init";
+ for (j = 1; j < argc; j++)
+ args[i++] = argv[j];
args[i++] = NULL;
assert(i <= ELEMENTSOF(args));
-
- /* Close and disarm the watchdog, so that the new
- * instance can reinitialize it, but doesn't get
- * rebooted while we do that */
- watchdog_close(true);
-
execv(args[0], (char* const*) args);
log_error("Failed to reexecute: %m");
diff --git a/src/core/manager.c b/src/core/manager.c
index c6baf22..bd86f89 100644
--- a/src/core/manager.c
+++ b/src/core/manager.c
@@ -522,6 +522,9 @@ void manager_free(Manager *m) {
close_pipe(m->idle_pipe);
+ free(m->switch_root);
+ free(m->switch_root_init);
+
free(m);
}
diff --git a/src/core/manager.h b/src/core/manager.h
index 6d1f5d8..92dc75d 100644
--- a/src/core/manager.h
+++ b/src/core/manager.h
@@ -45,6 +45,7 @@ typedef enum ManagerExitCode {
MANAGER_POWEROFF,
MANAGER_HALT,
MANAGER_KEXEC,
+ MANAGER_SWITCH_ROOT,
_MANAGER_EXIT_CODE_MAX,
_MANAGER_EXIT_CODE_INVALID = -1
} ManagerExitCode;
@@ -233,6 +234,9 @@ struct Manager {
/* Type=idle pipes */
int idle_pipe[2];
+
+ char *switch_root;
+ char *switch_root_init;
};
int manager_new(ManagerRunningAs running_as, Manager **m);
commit 14753f341937b75b244261f36807330456fa33a8
Author: Lennart Poettering <lennart at poettering.net>
Date: Tue May 8 23:37:25 2012 +0200
path-util: there is no function path_parent()
diff --git a/src/shared/path-util.h b/src/shared/path-util.h
index 181b981..a441783 100644
--- a/src/shared/path-util.h
+++ b/src/shared/path-util.h
@@ -31,7 +31,6 @@ int path_get_parent(const char *path, char **parent);
bool path_is_absolute(const char *p);
char *path_make_absolute(const char *p, const char *prefix);
char *path_make_absolute_cwd(const char *p);
-int path_parent(const char *path, char **parent);
char *path_kill_slashes(char *path);
bool path_startswith(const char *path, const char *prefix);
bool path_equal(const char *a, const char *b);
commit a5d87bf0eaf718afe62fb0b18c2f526c6e4375fc
Author: Lennart Poettering <lennart at poettering.net>
Date: Tue May 8 23:36:55 2012 +0200
main: simplify+unify logic for parsing runtime booleans
diff --git a/src/core/main.c b/src/core/main.c
index fe4522e..5878099 100644
--- a/src/core/main.c
+++ b/src/core/main.c
@@ -760,9 +760,9 @@ static int parse_argv(int argc, char *argv[]) {
{ "test", no_argument, NULL, ARG_TEST },
{ "help", no_argument, NULL, 'h' },
{ "dump-configuration-items", no_argument, NULL, ARG_DUMP_CONFIGURATION_ITEMS },
- { "dump-core", no_argument, NULL, ARG_DUMP_CORE },
- { "crash-shell", no_argument, NULL, ARG_CRASH_SHELL },
- { "confirm-spawn", no_argument, NULL, ARG_CONFIRM_SPAWN },
+ { "dump-core", optional_argument, NULL, ARG_DUMP_CORE },
+ { "crash-shell", optional_argument, NULL, ARG_CRASH_SHELL },
+ { "confirm-spawn", optional_argument, NULL, ARG_CONFIRM_SPAWN },
{ "show-status", optional_argument, NULL, ARG_SHOW_STATUS },
#ifdef HAVE_SYSV_COMPAT
{ "sysv-console", optional_argument, NULL, ARG_SYSV_CONSOLE },
@@ -871,39 +871,49 @@ static int parse_argv(int argc, char *argv[]) {
break;
case ARG_DUMP_CORE:
- arg_dump_core = true;
+ r = optarg ? parse_boolean(optarg) : 1;
+ if (r < 0) {
+ log_error("Failed to parse dump core boolean %s.", optarg);
+ return r;
+ }
+ arg_dump_core = r;
break;
case ARG_CRASH_SHELL:
- arg_crash_shell = true;
+ r = optarg ? parse_boolean(optarg) : 1;
+ if (r < 0) {
+ log_error("Failed to parse crash shell boolean %s.", optarg);
+ return r;
+ }
+ arg_crash_shell = r;
break;
case ARG_CONFIRM_SPAWN:
- arg_confirm_spawn = true;
+ r = optarg ? parse_boolean(optarg) : 1;
+ if (r < 0) {
+ log_error("Failed to parse confirm spawn boolean %s.", optarg);
+ return r;
+ }
+ arg_confirm_spawn = r;
break;
case ARG_SHOW_STATUS:
-
- if (optarg) {
- if ((r = parse_boolean(optarg)) < 0) {
- log_error("Failed to show status boolean %s.", optarg);
- return r;
- }
- arg_show_status = r;
- } else
- arg_show_status = true;
+ r = optarg ? parse_boolean(optarg) : 1;
+ if (r < 0) {
+ log_error("Failed to parse show status boolean %s.", optarg);
+ return r;
+ }
+ arg_show_status = r;
break;
+
#ifdef HAVE_SYSV_COMPAT
case ARG_SYSV_CONSOLE:
-
- if (optarg) {
- if ((r = parse_boolean(optarg)) < 0) {
- log_error("Failed to SysV console boolean %s.", optarg);
- return r;
- }
- arg_sysv_console = r;
- } else
- arg_sysv_console = true;
+ r = optarg ? parse_boolean(optarg) : 1;
+ if (r < 0) {
+ log_error("Failed to parse SysV console boolean %s.", optarg);
+ return r;
+ }
+ arg_sysv_console = r;
break;
#endif
@@ -1014,9 +1024,9 @@ static int help(void) {
" --unit=UNIT Set default unit\n"
" --system Run a system instance, even if PID != 1\n"
" --user Run a user instance\n"
- " --dump-core Dump core on crash\n"
- " --crash-shell Run shell on crash\n"
- " --confirm-spawn Ask for confirmation when spawning processes\n"
+ " --dump-core[=0|1] Dump core on crash\n"
+ " --crash-shell[=0|1] Run shell on crash\n"
+ " --confirm-spawn[=0|1] Ask for confirmation when spawning processes\n"
" --show-status[=0|1] Show status updates on the console during bootup\n"
#ifdef HAVE_SYSV_COMPAT
" --sysv-console[=0|1] Connect output of SysV scripts to console\n"
commit d889a2069a87e4617b32ddbdeace5a53a12c699d
Author: Lennart Poettering <lennart at poettering.net>
Date: Tue May 8 19:02:25 2012 +0200
logind: implement suspend/hibernate calls with inhibition logic
diff --git a/TODO b/TODO
index aeba2b5..47a890d 100644
--- a/TODO
+++ b/TODO
@@ -36,7 +36,7 @@ Features:
* automount: implement expire
* logind: auto-suspend, auto-shutdown:
- IdleAction=(none|suspend|hibernate|poweroff)
+ IdleAction=(none|suspend|opportunistic|hibernate|poweroff)
IdleActionDelay=...
SessionIdleMode=(explicit|ignore|login)
ForceShutdown=(yes|no)
diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c
index 9fc3a14..e089eeb 100644
--- a/src/login/logind-dbus.c
+++ b/src/login/logind-dbus.c
@@ -135,12 +135,24 @@
" <method name=\"Reboot\">\n" \
" <arg name=\"interactive\" type=\"b\" direction=\"in\"/>\n" \
" </method>\n" \
+ " <method name=\"Suspend\">\n" \
+ " <arg name=\"interactive\" type=\"b\" direction=\"in\"/>\n" \
+ " </method>\n" \
+ " <method name=\"Hibernate\">\n" \
+ " <arg name=\"interactive\" type=\"b\" direction=\"in\"/>\n" \
+ " </method>\n" \
" <method name=\"CanPowerOff\">\n" \
" <arg name=\"result\" type=\"s\" direction=\"out\"/>\n" \
" </method>\n" \
" <method name=\"CanReboot\">\n" \
" <arg name=\"result\" type=\"s\" direction=\"out\"/>\n" \
" </method>\n" \
+ " <method name=\"CanSuspend\">\n" \
+ " <arg name=\"result\" type=\"s\" direction=\"out\"/>\n" \
+ " </method>\n" \
+ " <method name=\"CanHibernate\">\n" \
+ " <arg name=\"result\" type=\"s\" direction=\"out\"/>\n" \
+ " </method>\n" \
" <method name=\"Inhibit\">\n" \
" <arg name=\"what\" type=\"s\" direction=\"in\"/>\n" \
" <arg name=\"who\" type=\"s\" direction=\"in\"/>\n" \
@@ -178,6 +190,9 @@
" <signal name=\"PrepareForShutdown\">\n" \
" <arg name=\"active\" type=\"b\"/>\n" \
" </signal>\n" \
+ " <signal name=\"PrepareForSleep\">\n" \
+ " <arg name=\"active\" type=\"b\"/>\n" \
+ " </signal>\n" \
" <property name=\"ControlGroupHierarchy\" type=\"s\" access=\"read\"/>\n" \
" <property name=\"Controllers\" type=\"as\" access=\"read\"/>\n" \
" <property name=\"ResetControllers\" type=\"as\" access=\"read\"/>\n" \
@@ -937,12 +952,12 @@ static int have_multiple_sessions(
return false;
}
-static int send_start_unit(DBusConnection *connection, const char *name, DBusError *error) {
+static int send_start_unit(DBusConnection *connection, const char *unit_name, DBusError *error) {
DBusMessage *message, *reply;
const char *mode = "replace";
assert(connection);
- assert(name);
+ assert(unit_name);
message = dbus_message_new_method_call(
"org.freedesktop.systemd1",
@@ -953,7 +968,7 @@ static int send_start_unit(DBusConnection *connection, const char *name, DBusErr
return -ENOMEM;
if (!dbus_message_append_args(message,
- DBUS_TYPE_STRING, &name,
+ DBUS_TYPE_STRING, &unit_name,
DBUS_TYPE_STRING, &mode,
DBUS_TYPE_INVALID)) {
dbus_message_unref(message);
@@ -970,14 +985,22 @@ static int send_start_unit(DBusConnection *connection, const char *name, DBusErr
return 0;
}
-static int send_prepare_for_shutdown(Manager *m, bool _active) {
+static int send_prepare_for(Manager *m, InhibitWhat w, bool _active) {
+ static const char * const signal_name[_INHIBIT_WHAT_MAX] = {
+ [INHIBIT_SHUTDOWN] = "PrepareForShutdown",
+ [INHIBIT_SLEEP] = "PrepareForSleep"
+ };
+
dbus_bool_t active = _active;
DBusMessage *message;
int r = 0;
assert(m);
+ assert(w >= 0);
+ assert(w < _INHIBIT_WHAT_MAX);
+ assert(signal_name[w]);
- message = dbus_message_new_signal("/org/freedesktop/login1", "org.freedesktop.login1.Manager", "PrepareForShutdown");
+ message = dbus_message_new_signal("/org/freedesktop/login1", "org.freedesktop.login1.Manager", signal_name[w]);
if (!message)
return -ENOMEM;
@@ -989,21 +1012,222 @@ static int send_prepare_for_shutdown(Manager *m, bool _active) {
return r;
}
-static int delay_shutdown(Manager *m, const char *name) {
+static int delay_shutdown_or_sleep(Manager *m, InhibitWhat w, const char *unit_name) {
assert(m);
+ assert(w >= 0);
+ assert(w < _INHIBIT_WHAT_MAX);
- if (!m->delayed_shutdown) {
- /* Tell everybody to prepare for shutdown */
- send_prepare_for_shutdown(m, true);
+ /* Tell everybody to prepare for shutdown/sleep */
+ send_prepare_for(m, w, true);
- /* Update timestamp for timeout */
- m->delayed_shutdown_timestamp = now(CLOCK_MONOTONIC);
- }
+ /* Update timestamp for timeout */
+ if (!m->delayed_unit)
+ m->delayed_timestamp = now(CLOCK_MONOTONIC);
/* Remember what we want to do, possibly overriding what kind
- * of shutdown we previously queued. */
- m->delayed_shutdown = name;
+ * of unit we previously queued. */
+ m->delayed_unit = unit_name;
+ m->delayed_what = w;
+
+ return 0;
+}
+
+static int bus_manager_can_shutdown_or_sleep(
+ Manager *m,
+ DBusConnection *connection,
+ DBusMessage *message,
+ InhibitWhat w,
+ const char *action,
+ const char *action_multiple_sessions,
+ const char *action_ignore_inhibit,
+ const char *sleep_type,
+ DBusError *error,
+ DBusMessage **_reply) {
+
+ bool multiple_sessions, challenge, blocked, b;
+ const char *result;
+ DBusMessage *reply = NULL;
+ int r;
+
+ assert(m);
+ assert(connection);
+ assert(message);
+ assert(w >= 0);
+ assert(w <= _INHIBIT_WHAT_MAX);
+ assert(action);
+ assert(action_multiple_sessions);
+ assert(action_ignore_inhibit);
+ assert(error);
+ assert(_reply);
+
+ if (sleep_type) {
+ r = can_sleep(sleep_type);
+ if (r < 0)
+ return r;
+
+ result = "na";
+ goto finish;
+ }
+
+ r = have_multiple_sessions(connection, m, message, error);
+ if (r < 0)
+ return r;
+
+ multiple_sessions = r > 0;
+ blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL);
+
+ if (multiple_sessions) {
+ r = verify_polkit(connection, message, action_multiple_sessions, false, &challenge, error);
+ if (r < 0)
+ return r;
+
+ if (r > 0)
+ result = "yes";
+ else if (challenge)
+ result = "challenge";
+ else
+ result = "no";
+ }
+
+ if (blocked) {
+ r = verify_polkit(connection, message, action_ignore_inhibit, false, &challenge, error);
+ if (r < 0)
+ return r;
+
+ if (r > 0 && !result)
+ result = "yes";
+ else if (challenge && (!result || streq(result, "yes")))
+ result = "challenge";
+ else
+ result = "no";
+ }
+
+ if (!multiple_sessions && !blocked) {
+ /* If neither inhibit nor multiple sessions
+ * apply then just check the normal policy */
+
+ r = verify_polkit(connection, message, action, false, &challenge, error);
+ if (r < 0)
+ return r;
+
+ if (r > 0)
+ result = "yes";
+ else if (challenge)
+ result = "challenge";
+ else
+ result = "no";
+ }
+
+finish:
+ reply = dbus_message_new_method_return(message);
+ if (!reply)
+ return -ENOMEM;
+
+ b = dbus_message_append_args(
+ reply,
+ DBUS_TYPE_STRING, &result,
+ DBUS_TYPE_INVALID);
+ if (!b) {
+ dbus_message_unref(reply);
+ return -ENOMEM;
+ }
+
+ *_reply = reply;
+ return 0;
+}
+
+static int bus_manager_do_shutdown_or_sleep(
+ Manager *m,
+ DBusConnection *connection,
+ DBusMessage *message,
+ const char *unit_name,
+ InhibitWhat w,
+ const char *action,
+ const char *action_multiple_sessions,
+ const char *action_ignore_inhibit,
+ const char *sleep_type,
+ DBusError *error,
+ DBusMessage **_reply) {
+
+ dbus_bool_t interactive;
+ bool multiple_sessions, blocked, delayed;
+ DBusMessage *reply = NULL;
+ int r;
+
+ assert(m);
+ assert(connection);
+ assert(message);
+ assert(unit_name);
+ assert(w >= 0);
+ assert(w <= _INHIBIT_WHAT_MAX);
+ assert(action);
+ assert(action_multiple_sessions);
+ assert(action_ignore_inhibit);
+ assert(error);
+ assert(_reply);
+
+ if (!dbus_message_get_args(
+ message,
+ error,
+ DBUS_TYPE_BOOLEAN, &interactive,
+ DBUS_TYPE_INVALID))
+ return -EINVAL;
+
+ if (sleep_type) {
+ r = can_sleep(sleep_type);
+ if (r < 0)
+ return r;
+
+ if (r == 0)
+ return -ENOTSUP;
+ }
+
+ r = have_multiple_sessions(connection, m, message, error);
+ if (r < 0)
+ return r;
+
+ multiple_sessions = r > 0;
+ blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL);
+
+ if (multiple_sessions) {
+ r = verify_polkit(connection, message, action_multiple_sessions, interactive, NULL, error);
+ if (r < 0)
+ return r;
+ }
+
+ if (blocked) {
+ r = verify_polkit(connection, message, action_ignore_inhibit, interactive, NULL, error);
+ if (r < 0)
+ return r;
+ }
+
+ if (!multiple_sessions && !blocked) {
+ r = verify_polkit(connection, message, action, interactive, NULL, error);
+ if (r < 0)
+ return r;
+ }
+
+ delayed =
+ m->inhibit_delay_max > 0 &&
+ manager_is_inhibited(m, w, INHIBIT_DELAY, NULL);
+
+ if (delayed) {
+ /* Shutdown is delayed, keep in mind what we
+ * want to do, and start a timeout */
+ r = delay_shutdown_or_sleep(m, w, unit_name);
+ } else
+ /* Shutdown is not delayed, execute it
+ * immediately */
+ r = send_start_unit(connection, unit_name, error);
+
+ if (r < 0)
+ return r;
+
+ reply = dbus_message_new_method_return(message);
+ if (!reply)
+ return -ENOMEM;
+ *_reply = reply;
return 0;
}
@@ -1731,158 +1955,104 @@ static DBusHandlerResult manager_message_handler(
if (!reply)
goto oom;
- } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "PowerOff") ||
- dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "Reboot")) {
- dbus_bool_t interactive;
- bool multiple_sessions, blocked, delayed;
- const char *name, *action;
-
- if (!dbus_message_get_args(
- message,
- &error,
- DBUS_TYPE_BOOLEAN, &interactive,
- DBUS_TYPE_INVALID))
- return bus_send_error_reply(connection, message, &error, -EINVAL);
-
- r = have_multiple_sessions(connection, m, message, &error);
+ } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "PowerOff")) {
+
+ r = bus_manager_do_shutdown_or_sleep(
+ m, connection, message,
+ SPECIAL_POWEROFF_TARGET,
+ INHIBIT_SHUTDOWN,
+ "org.freedesktop.login1.power-off",
+ "org.freedesktop.login1.power-off-multiple-sessions",
+ "org.freedesktop.login1.power-off-ignore-inhibit",
+ NULL,
+ &error, &reply);
if (r < 0)
return bus_send_error_reply(connection, message, &error, r);
-
- multiple_sessions = r > 0;
- blocked = manager_is_inhibited(m, INHIBIT_SHUTDOWN, INHIBIT_BLOCK, NULL);
-
- if (multiple_sessions) {
- action = streq(dbus_message_get_member(message), "PowerOff") ?
- "org.freedesktop.login1.power-off-multiple-sessions" :
- "org.freedesktop.login1.reboot-multiple-sessions";
-
- r = verify_polkit(connection, message, action, interactive, NULL, &error);
- if (r < 0)
- return bus_send_error_reply(connection, message, &error, r);
- }
-
- if (blocked) {
- action = streq(dbus_message_get_member(message), "PowerOff") ?
- "org.freedesktop.login1.power-off-ignore-inhibit" :
- "org.freedesktop.login1.reboot-ignore-inhibit";
-
- r = verify_polkit(connection, message, action, interactive, NULL, &error);
- if (r < 0)
- return bus_send_error_reply(connection, message, &error, r);
- }
-
- if (!multiple_sessions && !blocked) {
- action = streq(dbus_message_get_member(message), "PowerOff") ?
- "org.freedesktop.login1.power-off" :
- "org.freedesktop.login1.reboot";
-
- r = verify_polkit(connection, message, action, interactive, NULL, &error);
- if (r < 0)
- return bus_send_error_reply(connection, message, &error, r);
- }
-
- name = streq(dbus_message_get_member(message), "PowerOff") ?
- SPECIAL_POWEROFF_TARGET : SPECIAL_REBOOT_TARGET;
-
- delayed =
- m->inhibit_delay_max > 0 &&
- manager_is_inhibited(m, INHIBIT_SHUTDOWN, INHIBIT_DELAY, NULL);
-
- if (delayed) {
- /* Shutdown is delayed, keep in mind what we
- * want to do, and start a timeout */
- r = delay_shutdown(m, name);
- if (r < 0)
- return bus_send_error_reply(connection, message, NULL, r);
- } else {
- /* Shutdown is not delayed, execute it
- * immediately */
- r = send_start_unit(connection, name, &error);
- if (r < 0)
- return bus_send_error_reply(connection, message, &error, r);
- }
-
- reply = dbus_message_new_method_return(message);
- if (!reply)
- goto oom;
-
- } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "CanPowerOff") ||
- dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "CanReboot")) {
-
- bool multiple_sessions, challenge, inhibit, b;
- const char *action, *result;
-
- r = have_multiple_sessions(connection, m, message, &error);
+ } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "Reboot")) {
+ r = bus_manager_do_shutdown_or_sleep(
+ m, connection, message,
+ SPECIAL_REBOOT_TARGET,
+ INHIBIT_SHUTDOWN,
+ "org.freedesktop.login1.reboot",
+ "org.freedesktop.login1.reboot-multiple-sessions",
+ "org.freedesktop.login1.reboot-ignore-inhibit",
+ NULL,
+ &error, &reply);
if (r < 0)
return bus_send_error_reply(connection, message, &error, r);
- multiple_sessions = r > 0;
- inhibit = manager_is_inhibited(m, INHIBIT_SHUTDOWN, INHIBIT_BLOCK, NULL);
-
- if (multiple_sessions) {
- action = streq(dbus_message_get_member(message), "CanPowerOff") ?
- "org.freedesktop.login1.power-off-multiple-sessions" :
- "org.freedesktop.login1.reboot-multiple-sessions";
-
- r = verify_polkit(connection, message, action, false, &challenge, &error);
- if (r < 0)
- return bus_send_error_reply(connection, message, &error, r);
-
- if (r > 0)
- result = "yes";
- else if (challenge)
- result = "challenge";
- else
- result = "no";
- }
-
- if (inhibit) {
- action = streq(dbus_message_get_member(message), "CanPowerOff") ?
- "org.freedesktop.login1.power-off-ignore-inhibit" :
- "org.freedesktop.login1.reboot-ignore-inhibit";
-
- r = verify_polkit(connection, message, action, false, &challenge, &error);
- if (r < 0)
- return bus_send_error_reply(connection, message, &error, r);
-
- if (r > 0 && !result)
- result = "yes";
- else if (challenge && (!result || streq(result, "yes")))
- result = "challenge";
- else
- result = "no";
- }
-
- if (!multiple_sessions && !inhibit) {
- /* If neither inhibit nor multiple sessions
- * apply then just check the normal policy */
-
- action = streq(dbus_message_get_member(message), "CanPowerOff") ?
- "org.freedesktop.login1.power-off" :
- "org.freedesktop.login1.reboot";
+ } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "Suspend")) {
+ r = bus_manager_do_shutdown_or_sleep(
+ m, connection, message,
+ SPECIAL_SUSPEND_TARGET,
+ INHIBIT_SLEEP,
+ "org.freedesktop.login1.suspend",
+ "org.freedesktop.login1.suspend-multiple-sessions",
+ "org.freedesktop.login1.suspend-ignore-inhibit",
+ "mem",
+ &error, &reply);
+ if (r < 0)
+ return bus_send_error_reply(connection, message, &error, r);
+ } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "Hibernate")) {
+ r = bus_manager_do_shutdown_or_sleep(
+ m, connection, message,
+ SPECIAL_HIBERNATE_TARGET,
+ INHIBIT_SLEEP,
+ "org.freedesktop.login1.hibernate",
+ "org.freedesktop.login1.hibernate-multiple-sessions",
+ "org.freedesktop.login1.hibernate-ignore-inhibit",
+ "disk",
+ &error, &reply);
+ if (r < 0)
+ return bus_send_error_reply(connection, message, &error, r);
- r = verify_polkit(connection, message, action, false, &challenge, &error);
- if (r < 0)
- return bus_send_error_reply(connection, message, &error, r);
+ } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "CanPowerOff")) {
- if (r > 0)
- result = "yes";
- else if (challenge)
- result = "challenge";
- else
- result = "no";
- }
+ r = bus_manager_can_shutdown_or_sleep(
+ m, connection, message,
+ INHIBIT_SHUTDOWN,
+ "org.freedesktop.login1.power-off",
+ "org.freedesktop.login1.power-off-multiple-sessions",
+ "org.freedesktop.login1.power-off-ignore-inhibit",
+ NULL,
+ &error, &reply);
+ if (r < 0)
+ return bus_send_error_reply(connection, message, &error, r);
+ } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "CanReboot")) {
+ r = bus_manager_can_shutdown_or_sleep(
+ m, connection, message,
+ INHIBIT_SHUTDOWN,
+ "org.freedesktop.login1.reboot",
+ "org.freedesktop.login1.reboot-multiple-sessions",
+ "org.freedesktop.login1.reboot-ignore-inhibit",
+ NULL,
+ &error, &reply);
+ if (r < 0)
+ return bus_send_error_reply(connection, message, &error, r);
- reply = dbus_message_new_method_return(message);
- if (!reply)
- goto oom;
+ } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "CanSuspend")) {
+ r = bus_manager_can_shutdown_or_sleep(
+ m, connection, message,
+ INHIBIT_SLEEP,
+ "org.freedesktop.login1.suspend",
+ "org.freedesktop.login1.suspend-multiple-sessions",
+ "org.freedesktop.login1.suspend-ignore-inhibit",
+ "mem",
+ &error, &reply);
+ if (r < 0)
+ return bus_send_error_reply(connection, message, &error, r);
- b = dbus_message_append_args(
- reply,
- DBUS_TYPE_STRING, &result,
- DBUS_TYPE_INVALID);
- if (!b)
- goto oom;
+ } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "CanHibernate")) {
+ r = bus_manager_can_shutdown_or_sleep(
+ m, connection, message,
+ INHIBIT_SLEEP,
+ "org.freedesktop.login1.hibernate",
+ "org.freedesktop.login1.hibernate-multiple-sessions",
+ "org.freedesktop.login1.hibernate-ignore-inhibit",
+ "disk",
+ &error, &reply);
+ if (r < 0)
+ return bus_send_error_reply(connection, message, &error, r);
} else if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Introspectable", "Introspect")) {
char *introspection = NULL;
@@ -2029,38 +2199,39 @@ finish:
return r;
}
-int manager_dispatch_delayed_shutdown(Manager *manager) {
- const char *name;
+int manager_dispatch_delayed(Manager *manager) {
+ const char *unit_name;
DBusError error;
bool delayed;
int r;
assert(manager);
- if (!manager->delayed_shutdown)
+ if (!manager->delayed_unit)
return 0;
/* Continue delay? */
delayed =
- manager->delayed_shutdown_timestamp + manager->inhibit_delay_max > now(CLOCK_MONOTONIC) &&
- manager_is_inhibited(manager, INHIBIT_SHUTDOWN, INHIBIT_DELAY, NULL);
+ manager->delayed_timestamp + manager->inhibit_delay_max > now(CLOCK_MONOTONIC) &&
+ manager_is_inhibited(manager, manager->delayed_what, INHIBIT_DELAY, NULL);
if (delayed)
return 0;
/* Reset delay data */
- name = manager->delayed_shutdown;
- manager->delayed_shutdown = NULL;
+ unit_name = manager->delayed_unit;
+ manager->delayed_unit = NULL;
/* Actually do the shutdown */
dbus_error_init(&error);
- r = send_start_unit(manager->bus, name, &error);
+ r = send_start_unit(manager->bus, unit_name, &error);
if (r < 0) {
- log_warning("Failed to send delayed shutdown message: %s", bus_error_message_or_strerror(&error, -r));
+ log_warning("Failed to send delayed message: %s", bus_error_message_or_strerror(&error, -r));
+ dbus_error_free(&error);
return r;
}
/* Tell people about it */
- send_prepare_for_shutdown(manager, false);
+ send_prepare_for(manager, manager->delayed_what, false);
return 1;
}
diff --git a/src/login/logind-inhibit.c b/src/login/logind-inhibit.c
index 2007ec7..512fc07 100644
--- a/src/login/logind-inhibit.c
+++ b/src/login/logind-inhibit.c
@@ -163,7 +163,7 @@ int inhibitor_start(Inhibitor *i) {
i->started = true;
- manager_send_changed(i->manager, "Inhibited\0");
+ manager_send_changed(i->manager, i->mode == INHIBIT_BLOCK ? "BlockInhibited\0" : "DelayInhibited\0");
return 0;
}
@@ -182,7 +182,7 @@ int inhibitor_stop(Inhibitor *i) {
i->started = false;
- manager_send_changed(i->manager, "Inhibited\0");
+ manager_send_changed(i->manager, i->mode == INHIBIT_BLOCK ? "BlockInhibited\0" : "DelayInhibited\0");
return 0;
}
diff --git a/src/login/logind-inhibit.h b/src/login/logind-inhibit.h
index 6364b00..4377f00 100644
--- a/src/login/logind-inhibit.h
+++ b/src/login/logind-inhibit.h
@@ -23,11 +23,10 @@
***/
typedef struct Inhibitor Inhibitor;
+typedef enum InhibitWhat InhibitWhat;
#include "list.h"
#include "util.h"
-#include "logind.h"
-#include "logind-seat.h"
typedef enum InhibitWhat {
INHIBIT_SHUTDOWN = 1,
@@ -44,6 +43,9 @@ typedef enum InhibitMode {
_INHIBIT_MODE_INVALID = -1
} InhibitMode;
+#include "logind.h"
+#include "logind-seat.h"
+
struct Inhibitor {
Manager *manager;
diff --git a/src/login/logind.c b/src/login/logind.c
index 5860bfc..8d4f733 100644
--- a/src/login/logind.c
+++ b/src/login/logind.c
@@ -1269,7 +1269,7 @@ int manager_run(Manager *m) {
manager_gc(m, true);
- if (manager_dispatch_delayed_shutdown(m) > 0)
+ if (manager_dispatch_delayed(m) > 0)
continue;
if (dbus_connection_dispatch(m->bus) != DBUS_DISPATCH_COMPLETE)
@@ -1277,11 +1277,11 @@ int manager_run(Manager *m) {
manager_gc(m, true);
- if (m->delayed_shutdown) {
+ if (m->delayed_unit) {
usec_t x, y;
x = now(CLOCK_MONOTONIC);
- y = m->delayed_shutdown_timestamp + m->inhibit_delay_max;
+ y = m->delayed_timestamp + m->inhibit_delay_max;
msec = x >= y ? 0 : (int) ((y - x) / USEC_PER_MSEC);
}
diff --git a/src/login/logind.h b/src/login/logind.h
index 2c05452..2433221 100644
--- a/src/login/logind.h
+++ b/src/login/logind.h
@@ -85,8 +85,9 @@ struct Manager {
/* If a shutdown was delayed due to a inhibitor this contains
the unit name we are supposed to start after the delay is
over */
- const char *delayed_shutdown;
- usec_t delayed_shutdown_timestamp;
+ const char *delayed_unit;
+ InhibitWhat delayed_what;
+ usec_t delayed_timestamp;
usec_t inhibit_delay_max;
};
@@ -140,7 +141,7 @@ DBusHandlerResult bus_message_filter(DBusConnection *c, DBusMessage *message, vo
int manager_send_changed(Manager *manager, const char *properties);
-int manager_dispatch_delayed_shutdown(Manager *manager);
+int manager_dispatch_delayed(Manager *manager);
/* gperf lookup function */
const struct ConfigPerfItem* logind_gperf_lookup(const char *key, unsigned length);
diff --git a/src/login/org.freedesktop.login1.conf b/src/login/org.freedesktop.login1.conf
index 0f70b37..5860fd9 100644
--- a/src/login/org.freedesktop.login1.conf
+++ b/src/login/org.freedesktop.login1.conf
@@ -94,6 +94,14 @@
<allow send_destination="org.freedesktop.login1"
send_interface="org.freedesktop.login1.Manager"
+ send_member="Suspend"/>
+
+ <allow send_destination="org.freedesktop.login1"
+ send_interface="org.freedesktop.login1.Manager"
+ send_member="Hibernate"/>
+
+ <allow send_destination="org.freedesktop.login1"
+ send_interface="org.freedesktop.login1.Manager"
send_member="CanPowerOff"/>
<allow send_destination="org.freedesktop.login1"
@@ -102,6 +110,14 @@
<allow send_destination="org.freedesktop.login1"
send_interface="org.freedesktop.login1.Manager"
+ send_member="CanSuspend"/>
+
+ <allow send_destination="org.freedesktop.login1"
+ send_interface="org.freedesktop.login1.Manager"
+ send_member="CanHibernate"/>
+
+ <allow send_destination="org.freedesktop.login1"
+ send_interface="org.freedesktop.login1.Manager"
send_member="AttachDevice"/>
<allow send_destination="org.freedesktop.login1"
diff --git a/src/login/org.freedesktop.login1.policy.in b/src/login/org.freedesktop.login1.policy.in
index 76ed2be..8422645 100644
--- a/src/login/org.freedesktop.login1.policy.in
+++ b/src/login/org.freedesktop.login1.policy.in
@@ -48,7 +48,7 @@
<action id="org.freedesktop.login1.attach-device">
<_description>Allow attaching devices to seats</_description>
- <_message>Authentication is required to allow attaching a device to a seat.</_message>
+ <_message>Authentication is required for attaching a device to a seat.</_message>
<defaults>
<allow_any>auth_admin_keep</allow_any>
<allow_inactive>auth_admin_keep</allow_inactive>
@@ -58,7 +58,7 @@
<action id="org.freedesktop.login1.flush-devices">
<_description>Flush device to seat attachments</_description>
- <_message>Authentication is required to allow resetting how devices are attached to seats.</_message>
+ <_message>Authentication is required for resetting how devices are attached to seats.</_message>
<defaults>
<allow_any>auth_admin_keep</allow_any>
<allow_inactive>auth_admin_keep</allow_inactive>
@@ -68,7 +68,7 @@
<action id="org.freedesktop.login1.power-off">
<_description>Power off the system</_description>
- <_message>Authentication is required to allow powering off the system.</_message>
+ <_message>Authentication is required for powering off the system.</_message>
<defaults>
<allow_any>auth_admin_keep</allow_any>
<allow_inactive>auth_admin_keep</allow_inactive>
@@ -77,8 +77,8 @@
</action>
<action id="org.freedesktop.login1.power-off-multiple-sessions">
- <_description>Power off the system when other users are logged in</_description>
- <_message>Authentication is required to allow powering off the system while other users are logged in.</_message>
+ <_description>Power off the system while other users are logged in</_description>
+ <_message>Authentication is required for powering off the system while other users are logged in.</_message>
<defaults>
<allow_any>auth_admin_keep</allow_any>
<allow_inactive>auth_admin_keep</allow_inactive>
@@ -87,8 +87,8 @@
</action>
<action id="org.freedesktop.login1.power-off-ignore-inhibit">
- <_description>Power off the system when an application asked to inhibit it</_description>
- <_message>Authentication is required to allow powering off the system while an application asked to inhibit it.</_message>
+ <_description>Power off the system while an application asked to inhibit it</_description>
+ <_message>Authentication is required for powering off the system while an application asked to inhibit it.</_message>
<defaults>
<allow_any>auth_admin_keep</allow_any>
<allow_inactive>auth_admin_keep</allow_inactive>
@@ -98,7 +98,7 @@
<action id="org.freedesktop.login1.reboot">
<_description>Reboot the system</_description>
- <_message>Authentication is required to allow rebooting the system.</_message>
+ <_message>Authentication is required for rebooting the system.</_message>
<defaults>
<allow_any>auth_admin_keep</allow_any>
<allow_inactive>auth_admin_keep</allow_inactive>
@@ -107,8 +107,8 @@
</action>
<action id="org.freedesktop.login1.reboot-multiple-sessions">
- <_description>Reboot the system when other users are logged in</_description>
- <_message>Authentication is required to allow rebooting the system while other users are logged in.</_message>
+ <_description>Reboot the system while other users are logged in</_description>
+ <_message>Authentication is required for rebooting the system while other users are logged in.</_message>
<defaults>
<allow_any>auth_admin_keep</allow_any>
<allow_inactive>auth_admin_keep</allow_inactive>
@@ -117,8 +117,68 @@
</action>
<action id="org.freedesktop.login1.reboot-ignore-inhibit">
- <_description>Reboot the system when an application asked to inhibit it</_description>
- <_message>Authentication is required to allow rebooting the system while an application asked to inhibit it.</_message>
+ <_description>Reboot the system while an application asked to inhibit it</_description>
+ <_message>Authentication is required for rebooting the system while an application asked to inhibit it.</_message>
+ <defaults>
+ <allow_any>auth_admin_keep</allow_any>
+ <allow_inactive>auth_admin_keep</allow_inactive>
+ <allow_active>auth_admin_keep</allow_active>
+ </defaults>
+ </action>
+
+ <action id="org.freedesktop.login1.suspend">
+ <_description>Suspend the system</_description>
+ <_message>Authentication is required for suspending the system.</_message>
+ <defaults>
+ <allow_any>auth_admin_keep</allow_any>
+ <allow_inactive>auth_admin_keep</allow_inactive>
+ <allow_active>yes</allow_active>
+ </defaults>
+ </action>
+
+ <action id="org.freedesktop.login1.suspend-multiple-sessions">
+ <_description>Suspend the system while other users are logged in</_description>
+ <_message>Authentication is required for suspending the system while other users are logged in.</_message>
+ <defaults>
+ <allow_any>auth_admin_keep</allow_any>
+ <allow_inactive>auth_admin_keep</allow_inactive>
+ <allow_active>auth_admin_keep</allow_active>
+ </defaults>
+ </action>
+
+ <action id="org.freedesktop.login1.suspend-ignore-inhibit">
+ <_description>Suspend the system while an application asked to inhibit it</_description>
+ <_message>Authentication is required for suspending the system while an application asked to inhibit it.</_message>
+ <defaults>
+ <allow_any>auth_admin_keep</allow_any>
+ <allow_inactive>auth_admin_keep</allow_inactive>
+ <allow_active>auth_admin_keep</allow_active>
+ </defaults>
+ </action>
+
+ <action id="org.freedesktop.login1.hibernate">
+ <_description>Hibernate the system</_description>
+ <_message>Authentication is required for hibernating the system.</_message>
+ <defaults>
+ <allow_any>auth_admin_keep</allow_any>
+ <allow_inactive>auth_admin_keep</allow_inactive>
+ <allow_active>yes</allow_active>
+ </defaults>
+ </action>
+
+ <action id="org.freedesktop.login1.hibernate-multiple-sessions">
+ <_description>Hibernate the system while other users are logged in</_description>
+ <_message>Authentication is required for hibernating the system while other users are logged in.</_message>
+ <defaults>
+ <allow_any>auth_admin_keep</allow_any>
+ <allow_inactive>auth_admin_keep</allow_inactive>
+ <allow_active>auth_admin_keep</allow_active>
+ </defaults>
+ </action>
+
+ <action id="org.freedesktop.login1.hibernate-ignore-inhibit">
+ <_description>Hibernate the system while an application asked to inhibit it</_description>
+ <_message>Authentication is required for hibernating the system while an application asked to inhibit it.</_message>
<defaults>
<allow_any>auth_admin_keep</allow_any>
<allow_inactive>auth_admin_keep</allow_inactive>
diff --git a/src/shared/util.c b/src/shared/util.c
index d8d3f1a..5f06c4b 100644
--- a/src/shared/util.c
+++ b/src/shared/util.c
@@ -5590,3 +5590,28 @@ int getenv_for_pid(pid_t pid, const char *field, char **_value) {
return r;
}
+
+int can_sleep(const char *type) {
+ char *p, *w, *state;
+ size_t l, k;
+ bool found = false;
+ int r;
+
+ assert(type);
+
+ r = read_one_line_file("/sys/power/state", &p);
+ if (r < 0)
+ return r == -ENOENT ? 0 : r;
+
+ k = strlen(type);
+
+ FOREACH_WORD_SEPARATOR(w, l, p, WHITESPACE, state) {
+ if (l == k && strncmp(w, type, l) == 0) {
+ found = true;
+ break;
+ }
+ }
+
+ free(p);
+ return found;
+}
diff --git a/src/shared/util.h b/src/shared/util.h
index 59a69a8..272ab48 100644
--- a/src/shared/util.h
+++ b/src/shared/util.h
@@ -505,4 +505,6 @@ int setrlimit_closest(int resource, const struct rlimit *rlim);
int getenv_for_pid(pid_t pid, const char *field, char **_value);
+int can_sleep(const char *type);
+
#endif
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index 762b5be..4708a35 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -1750,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;
}
@@ -1839,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;
commit 6edd7d0a09171ea5ae8e01b7b1cbcb0bdfbfeb16
Author: Lennart Poettering <lennart at poettering.net>
Date: Sat May 5 02:06:58 2012 +0200
sleep: implement suspend/hibernate as first class targets
diff --git a/.gitignore b/.gitignore
index 7f22255..e61f1cd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
+/systemd-sleep
/systemd-inhibit
/systemd-remount-fs
/build-aux
diff --git a/Makefile.am b/Makefile.am
index dbcfeb3..002a86a 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -67,6 +67,7 @@ usergeneratordir=$(pkglibexecdir)/user-generators
pkgincludedir=$(includedir)/systemd
systemgeneratordir=$(rootlibexecdir)/system-generators
systemshutdowndir=$(rootlibexecdir)/system-shutdown
+systemsleepdir=$(rootlibexecdir)/system-sleep
systemunitdir=$(rootprefix)/lib/systemd/system
udevlibexecdir=$(rootprefix)/lib/udev
udevhomedir = $(libexecdir)/udev
@@ -117,6 +118,7 @@ AM_CPPFLAGS = \
-DSYSTEMD_CGROUP_AGENT_PATH=\"$(rootlibexecdir)/systemd-cgroups-agent\" \
-DSYSTEMD_BINARY_PATH=\"$(rootlibexecdir)/systemd\" \
-DSYSTEMD_SHUTDOWN_BINARY_PATH=\"$(rootlibexecdir)/systemd-shutdown\" \
+ -DSYSTEMD_SLEEP_BINARY_PATH=\"$(rootlibexecdir)/systemd-sleep\" \
-DSYSTEMCTL_BINARY_PATH=\"$(rootbindir)/systemctl\" \
-DSYSTEMD_TTY_ASK_PASSWORD_AGENT_BINARY_PATH=\"$(rootbindir)/systemd-tty-ask-password-agent\" \
-DSYSTEMD_STDIO_BRIDGE_BINARY_PATH=\"$(bindir)/systemd-stdio-bridge\" \
@@ -230,7 +232,8 @@ rootlibexec_PROGRAMS = \
systemd-fsck \
systemd-timestamp \
systemd-ac-power \
- systemd-sysctl
+ systemd-sysctl \
+ systemd-sleep
systemgenerator_PROGRAMS = \
systemd-getty-generator
@@ -266,6 +269,7 @@ dist_systemunit_DATA = \
units/nss-lookup.target \
units/nss-user-lookup.target \
units/mail-transfer-agent.target \
+ units/hibernate.target \
units/http-daemon.target \
units/poweroff.target \
units/reboot.target \
@@ -276,7 +280,9 @@ dist_systemunit_DATA = \
units/final.target \
units/umount.target \
units/sigpwr.target \
+ units/sleep.target \
units/sockets.target \
+ units/suspend.target \
units/swap.target \
units/systemd-initctl.socket \
units/systemd-shutdownd.socket \
@@ -318,12 +324,14 @@ nodist_systemunit_DATA = \
units/systemd-sysctl.service \
units/halt.service \
units/emergency.service \
+ units/hibernate.service \
units/poweroff.service \
units/reboot.service \
units/kexec.service \
units/fsck at .service \
units/fsck-root.service \
units/rescue.service \
+ units/suspend.service \
units/user at .service \
units/systemd-udev.service \
units/systemd-udev-trigger.service \
@@ -1063,6 +1071,13 @@ systemd_sysctl_LDADD = \
libsystemd-shared.la
# ------------------------------------------------------------------------------
+systemd_sleep_SOURCES = \
+ src/sleep/sleep.c
+
+systemd_sleep_LDADD = \
+ libsystemd-shared.la
+
+# ------------------------------------------------------------------------------
systemd_fsck_SOURCES = \
src/fsck/fsck.c
@@ -3027,6 +3042,7 @@ systemd-install-data-hook:
$(DESTDIR)$(prefix)/lib/sysctl.d \
$(DESTDIR)$(sysconfdir)/sysctl.d \
$(DESTDIR)$(systemshutdowndir) \
+ $(DESTDIR)$(systemsleepdir) \
$(DESTDIR)$(systemgeneratordir) \
$(DESTDIR)$(usergeneratordir)
$(MKDIR_P) -m 0755 \
diff --git a/TODO b/TODO
index cd7aecf..aeba2b5 100644
--- a/TODO
+++ b/TODO
@@ -53,9 +53,6 @@ Features:
* ExecOnFailure=/usr/bin/foo
-* logind: add "mode" flag to poweroff/suspend inhibit logic so that we can
- support both "inhibit" and "delay" mode.
-
* fedora: make sshd and pam_loginuid work in nspawn containers
* fix utmp for console logins in containers
@@ -72,8 +69,6 @@ Features:
* journald: allow forwarding of log data to specific TTY instea dof console
-* suspend/hibernate/hybrid support, auto-suspend logic with idle hint
-
* add RequiredBy to [Install]
* udev: move to LGPL
diff --git a/man/systemctl.xml b/man/systemctl.xml
index dd0ff78..9e113eb 100644
--- a/man/systemctl.xml
+++ b/man/systemctl.xml
@@ -1149,6 +1149,16 @@
<option>--user</option> option) and
will fail otherwise.</para></listitem>
</varlistentry>
+ <varlistentry>
+ <term><command>suspend</command></term>
+
+ <listitem><para>Suspend the system.</para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><command>hibernate</command></term>
+
+ <listitem><para>Hibernate the system.</para></listitem>
+ </varlistentry>
</variablelist>
</refsect1>
diff --git a/man/systemd.special.xml b/man/systemd.special.xml
index 39c3802..984e998 100644
--- a/man/systemd.special.xml
+++ b/man/systemd.special.xml
@@ -58,6 +58,7 @@
<filename>exit.service</filename>,
<filename>final.service</filename>,
<filename>graphical.target</filename>,
+ <filename>hibernate.target</filename>,
<filename>http-daemon.target</filename>,
<filename>halt.target</filename>,
<filename>kbrequest.target</filename>,
@@ -80,7 +81,9 @@
<filename>runlevel5.target</filename>,
<filename>shutdown.target</filename>,
<filename>sigpwr.target</filename>,
+ <filename>sleep.target</filename>,
<filename>sockets.target</filename>,
+ <filename>suspend.target</filename>,
<filename>swap.target</filename>,
<filename>sysinit.target</filename>,
<filename>syslog.service</filename>,
@@ -240,6 +243,15 @@
</listitem>
</varlistentry>
<varlistentry>
+ <term><filename>hibernate.target</filename></term>
+ <listitem>
+ <para>A special target unit
+ for hibernating the
+ system. This pulls in
+ <filename>sleep.target</filename>.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
<term><filename>http-daemon.target</filename></term>
<listitem>
<para>A target for pulling in
@@ -591,6 +603,19 @@
</listitem>
</varlistentry>
<varlistentry>
+ <term><filename>sleep.target</filename></term>
+ <listitem>
+ <para>A special target unit
+ that is pulled in by
+ <filename>suspend.target</filename>
+ and
+ <filename>hibernate.target</filename>
+ and may be used to hook units
+ into the sleep state
+ logic.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
<term><filename>sockets.target</filename></term>
<listitem>
<para>A special target unit
@@ -605,6 +630,15 @@
</listitem>
</varlistentry>
<varlistentry>
+ <term><filename>suspend.target</filename></term>
+ <listitem>
+ <para>A special target unit
+ for suspending the
+ system. This pulls in
+ <filename>sleep.target</filename>.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
<term><filename>swap.target</filename></term>
<listitem>
<para>Similar to
diff --git a/src/core/shutdown.c b/src/core/shutdown.c
index 2494bb8..a8dfe26 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 2db4711..bc9b330 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 8a0b2a1..d8d3f1a 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 0000000..d0b0e8e
--- /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 0000000..7062dc2
--- /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 acede4e..762b5be 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 },
diff --git a/units/.gitignore b/units/.gitignore
index 68c174f..dc5e1d4 100644
--- a/units/.gitignore
+++ b/units/.gitignore
@@ -1,3 +1,5 @@
+/hibernate.service
+/suspend.service
/console-getty.service
/systemd-journald.service
user at .service
diff --git a/units/hibernate.service.in b/units/hibernate.service.in
new file mode 100644
index 0000000..6dba653
--- /dev/null
+++ b/units/hibernate.service.in
@@ -0,0 +1,16 @@
+# This file is part of systemd.
+#
+# 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.
+
+[Unit]
+Description=Hibernate
+DefaultDependencies=no
+Requires=sleep.target
+After=sleep.target
+
+[Service]
+Type=oneshot
+ExecStart=@rootlibexecdir@/systemd-sleep hibernate
diff --git a/units/hibernate.target b/units/hibernate.target
new file mode 100644
index 0000000..05238a7
--- /dev/null
+++ b/units/hibernate.target
@@ -0,0 +1,14 @@
+# This file is part of systemd.
+#
+# 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.
+
+# See systemd.special(7) for details
+
+[Unit]
+Description=Hibernate
+DefaultDependencies=no
+BindTo=hibernate.service
+After=hibernate.service
diff --git a/units/sleep.target b/units/sleep.target
new file mode 100644
index 0000000..9f4b247
--- /dev/null
+++ b/units/sleep.target
@@ -0,0 +1,13 @@
+# This file is part of systemd.
+#
+# 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.
+
+# See systemd.special(7) for details
+
+[Unit]
+Description=Sleep
+DefaultDependencies=no
+RefuseManualStart=yes
diff --git a/units/suspend.service.in b/units/suspend.service.in
new file mode 100644
index 0000000..3cf819e
--- /dev/null
+++ b/units/suspend.service.in
@@ -0,0 +1,16 @@
+# This file is part of systemd.
+#
+# 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.
+
+[Unit]
+Description=Suspend
+DefaultDependencies=no
+Requires=sleep.target
+After=sleep.target
+
+[Service]
+Type=oneshot
+ExecStart=@rootlibexecdir@/systemd-sleep suspend
diff --git a/units/suspend.target b/units/suspend.target
new file mode 100644
index 0000000..3ddb449
--- /dev/null
+++ b/units/suspend.target
@@ -0,0 +1,14 @@
+# This file is part of systemd.
+#
+# 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.
+
+# See systemd.special(7) for details
+
+[Unit]
+Description=Suspend
+DefaultDependencies=no
+BindTo=suspend.service
+After=suspend.service
commit 4943c1c94ba751c98763f4232b4350481b22c90a
Author: Lennart Poettering <lennart at poettering.net>
Date: Sat May 5 00:46:31 2012 +0200
logind: use "sleep" as generic term for "suspend", "hibernate", and later on "hybrid suspend"
diff --git a/TODO b/TODO
index ebdc98d..cd7aecf 100644
--- a/TODO
+++ b/TODO
@@ -41,8 +41,6 @@ Features:
SessionIdleMode=(explicit|ignore|login)
ForceShutdown=(yes|no)
-* logind: use "sleep" as generic term for "suspend", "hibernate", ...
-
* services which create their own subcgroups break cgroup-empty notification (needs to be fixed in the kernel)
* don't delete /tmp/systemd-namespace-* before a process is gone down
diff --git a/man/logind.conf.xml b/man/logind.conf.xml
index deca1cd..166038b 100644
--- a/man/logind.conf.xml
+++ b/man/logind.conf.xml
@@ -151,11 +151,12 @@
<term><varname>InhibitDelayMaxSec=</varname></term>
<listitem><para>Specifies the maximum
- time a suspend or reboot is delayed
- due to an inhibitor lock of type
- <literal>delay</literal> being taken
- before it is ignored and the operation
- executed anyway. Defaults to
+ time a system shutdown or sleep
+ request is delayed due to an inhibitor
+ lock of type <literal>delay</literal>
+ being taken before it is ignored and
+ the operation executed
+ anyway. Defaults to
5s.</para></listitem>
</varlistentry>
diff --git a/man/systemd-inhibit.xml b/man/systemd-inhibit.xml
index 3409590..c71a954 100644
--- a/man/systemd-inhibit.xml
+++ b/man/systemd-inhibit.xml
@@ -60,14 +60,14 @@
<title>Description</title>
<para><command>systemd-inhibit</command> may be used
- to execute a program with a shutdown, suspend or idle
+ to execute a program with a shutdown, sleep or idle
inhibitor lock taken. The lock will be acquired before
the specified command line is executed and released
afterwards.</para>
<para>Inhibitor locks may be used to block or delay
- suspend and shutdown requests from the user, as well
- as automatic idle handling of the OS. This may be used
+ system sleep and shutdown requests from the user, as well
+ as automatic idle handling of the OS. This is useful
to avoid system suspends while an optical disc is
being recorded, or similar operations that should not
be interrupted.</para>
@@ -101,7 +101,7 @@
separated list of one or more
operations to inhibit:
<literal>shutdown</literal>,
- <literal>suspend</literal>,
+ <literal>sleep</literal>,
<literal>idle</literal>, for
inhibiting reboot/power-off/halt/kexec,
suspending/hibernating, resp. the
diff --git a/src/login/inhibit.c b/src/login/inhibit.c
index a817c84..6f24a1b 100644
--- a/src/login/inhibit.c
+++ b/src/login/inhibit.c
@@ -31,7 +31,7 @@
#include "build.h"
#include "strv.h"
-static const char* arg_what = "idle:suspend:shutdown";
+static const char* arg_what = "idle:sleep:shutdown";
static const char* arg_who = NULL;
static const char* arg_why = "Unknown reason";
static const char* arg_mode = "block";
@@ -182,11 +182,11 @@ finish:
static int help(void) {
printf("%s [OPTIONS...] {COMMAND} ...\n\n"
- "Execute a process while inhibiting shutdown/suspend/idle.\n\n"
+ "Execute a process while inhibiting shutdown/sleep/idle.\n\n"
" -h --help Show this help\n"
" --version Show package version\n"
" --what=WHAT Operations to inhibit, colon separated list of idle,\n"
- " suspend, shutdown\n"
+ " sleep, shutdown\n"
" --who=STRING A descriptive string who is inhibiting\n"
" --why=STRING A descriptive string why is being inhibited\n"
" --mode=MODE One of block or delay\n"
diff --git a/src/login/logind-inhibit.c b/src/login/logind-inhibit.c
index b5b801e..2007ec7 100644
--- a/src/login/logind-inhibit.c
+++ b/src/login/logind-inhibit.c
@@ -376,12 +376,12 @@ const char *inhibit_what_to_string(InhibitWhat w) {
static const char* const table[_INHIBIT_WHAT_MAX] = {
[0] = "",
[INHIBIT_SHUTDOWN] = "shutdown",
- [INHIBIT_SUSPEND] = "suspend",
+ [INHIBIT_SLEEP] = "sleep",
[INHIBIT_IDLE] = "idle",
- [INHIBIT_SHUTDOWN|INHIBIT_SUSPEND] = "shutdown:suspend",
+ [INHIBIT_SHUTDOWN|INHIBIT_SLEEP] = "shutdown:sleep",
[INHIBIT_SHUTDOWN|INHIBIT_IDLE] = "shutdown:idle",
- [INHIBIT_SHUTDOWN|INHIBIT_SUSPEND|INHIBIT_IDLE] = "shutdown:suspend:idle",
- [INHIBIT_SUSPEND|INHIBIT_IDLE] = "suspend:idle"
+ [INHIBIT_SHUTDOWN|INHIBIT_SLEEP|INHIBIT_IDLE] = "shutdown:sleep:idle",
+ [INHIBIT_SLEEP|INHIBIT_IDLE] = "sleep:idle"
};
if (w < 0 || w >= _INHIBIT_WHAT_MAX)
@@ -398,8 +398,8 @@ InhibitWhat inhibit_what_from_string(const char *s) {
FOREACH_WORD_SEPARATOR(w, l, s, ":", state) {
if (l == 8 && strncmp(w, "shutdown", l) == 0)
what |= INHIBIT_SHUTDOWN;
- else if (l == 7 && strncmp(w, "suspend", l) == 0)
- what |= INHIBIT_SUSPEND;
+ else if (l == 5 && strncmp(w, "sleep", l) == 0)
+ what |= INHIBIT_SLEEP;
else if (l == 4 && strncmp(w, "idle", l) == 0)
what |= INHIBIT_IDLE;
else
diff --git a/src/login/logind-inhibit.h b/src/login/logind-inhibit.h
index 823af39..6364b00 100644
--- a/src/login/logind-inhibit.h
+++ b/src/login/logind-inhibit.h
@@ -31,7 +31,7 @@ typedef struct Inhibitor Inhibitor;
typedef enum InhibitWhat {
INHIBIT_SHUTDOWN = 1,
- INHIBIT_SUSPEND = 2,
+ INHIBIT_SLEEP = 2,
INHIBIT_IDLE = 4,
_INHIBIT_WHAT_MAX = 8,
_INHIBIT_WHAT_INVALID = -1
diff --git a/src/login/test-inhibit.c b/src/login/test-inhibit.c
index 634f1e1..7b6deff 100644
--- a/src/login/test-inhibit.c
+++ b/src/login/test-inhibit.c
@@ -119,7 +119,7 @@ int main(int argc, char*argv[]) {
print_inhibitors(bus);
- fd1 = inhibit(bus, "suspend");
+ fd1 = inhibit(bus, "sleep");
assert(fd1 >= 0);
print_inhibitors(bus);
commit dd5f0a96f734aafa00f6c3aea4003b7fdd278d81
Author: Lennart Poettering <lennart at poettering.net>
Date: Sat May 5 00:39:24 2012 +0200
logind: fix test-inhibit
diff --git a/src/login/test-inhibit.c b/src/login/test-inhibit.c
index c83e960..634f1e1 100644
--- a/src/login/test-inhibit.c
+++ b/src/login/test-inhibit.c
@@ -30,7 +30,7 @@
static int inhibit(DBusConnection *bus, const char *what) {
DBusMessage *m, *reply;
DBusError error;
- const char *who = "Test Tool", *reason = "Just because!";
+ const char *who = "Test Tool", *reason = "Just because!", *mode = "block";
int fd;
dbus_error_init(&error);
@@ -46,6 +46,7 @@ static int inhibit(DBusConnection *bus, const char *what) {
DBUS_TYPE_STRING, &what,
DBUS_TYPE_STRING, &who,
DBUS_TYPE_STRING, &reason,
+ DBUS_TYPE_STRING, &mode,
DBUS_TYPE_INVALID));
reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
@@ -83,19 +84,20 @@ static void print_inhibitors(DBusConnection *bus) {
dbus_message_iter_recurse(&iter, &sub);
while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
- const char *what, *who, *reason;
+ const char *what, *who, *why, *mode;
dbus_uint32_t uid, pid;
dbus_message_iter_recurse(&sub, &sub2);
assert_se(bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &what, true) >= 0);
assert_se(bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &who, true) >= 0);
- assert_se(bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &reason, true) >= 0);
+ assert_se(bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &why, true) >= 0);
+ assert_se(bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &mode, true) >= 0);
assert_se(bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &uid, true) >= 0);
assert_se(bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, false) >= 0);
- printf("what=<%s> who=<%s> reason=<%s> uid=<%lu> pid=<%lu>\n",
- what, who, reason, (unsigned long) uid, (unsigned long) pid);
+ printf("what=<%s> who=<%s> why=<%s> mode=<%s> uid=<%lu> pid=<%lu>\n",
+ what, who, why, mode, (unsigned long) uid, (unsigned long) pid);
dbus_message_iter_next(&sub);
More information about the systemd-commits
mailing list