From f536abd4560d2f871698bb4d27566c66cfe110ef Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Wed, 28 Mar 2018 11:00:06 -0500 Subject: [PATCH] Rename suspend-to-hibernate to suspend-then-hibernate Per some discussion with Gnome folks, they would prefer this name as it's more descriptive of what's happening. --- man/logind.conf.xml | 13 ++-- man/rules/meson.build | 30 ++++----- src/basic/special.h | 1 + src/login/logind-action.c | 13 +++- src/login/logind-action.h | 1 + src/login/logind-dbus.c | 51 ++++++--------- src/login/org.freedesktop.login1.conf | 8 +++ src/shared/sleep-config.c | 6 +- src/sleep/sleep.c | 94 +++++++++++++++++++++++++-- 9 files changed, 158 insertions(+), 59 deletions(-) diff --git a/man/logind.conf.xml b/man/logind.conf.xml index 9c5dfe1ea..a932cbb9f 100644 --- a/man/logind.conf.xml +++ b/man/logind.conf.xml @@ -1,6 +1,9 @@ + "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" [ + +%entities; +]> user should be killed when the user logs out. If true, the processes listed in their session cgroup will be terminated. If false, the session cgroup is ignored - and processes are not killed. Defaults to yes, but see the options KillOnlyUsers= and KillExcludeUsers= below. @@ -216,7 +219,8 @@ kexec, suspend, hibernate, - hybrid-sleep, and + hybrid-sleep, + suspend-then-hibernate, and lock. Defaults to ignore. @@ -265,7 +269,8 @@ kexec, suspend, hibernate, - hybrid-sleep, and + hybrid-sleep, + suspend-then-hibernate, and lock. If ignore, logind will never handle these keys. If lock, all running sessions will be diff --git a/man/rules/meson.build b/man/rules/meson.build index e33dc4393..fbd163e0e 100644 --- a/man/rules/meson.build +++ b/man/rules/meson.build @@ -1,6 +1,5 @@ # Do not edit. Generated by make-man-rules.py. manpages = [ - ['pam_elogind', '8', [], 'HAVE_PAM'], ['binfmt.d', '5', [], 'ENABLE_BINFMT'], ['bootctl', '1', [], 'ENABLE_EFI'], ['bootup', '7', [], ''], @@ -43,6 +42,7 @@ manpages = [ ['nss-resolve', '8', ['libnss_resolve.so.2'], 'ENABLE_RESOLVE'], ['nss-elogind', '8', ['libnss_elogind.so.2'], 'ENABLE_NSS_SYSTEMD'], ['os-release', '5', [], ''], + ['pam_elogind', '8', [], 'HAVE_PAM'], ['resolved.conf', '5', ['resolved.conf.d'], 'ENABLE_RESOLVE'], ['runlevel', '8', [], 'ENABLE_UTMP'], ['sd-boot', '7', [], 'ENABLE_EFI'], @@ -517,7 +517,6 @@ manpages = [ ['elogind-ask-password-console.path', 'elogind-ask-password-wall.path', 'elogind-ask-password-wall.service'], - ''], ['elogind-ask-password', '1', [], ''], ['elogind-backlight@.service', '8', ['elogind-backlight'], 'ENABLE_BACKLIGHT'], ['elogind-binfmt.service', '8', ['elogind-binfmt'], 'ENABLE_BINFMT'], @@ -525,6 +524,7 @@ manpages = [ ['elogind-cgls', '1', [], ''], ['elogind-cgtop', '1', [], ''], ['elogind-coredump', + ''], '8', ['elogind-coredump.socket', 'elogind-coredump@.service'], 'ENABLE_COREDUMP'], @@ -543,18 +543,18 @@ manpages = [ ['elogind-escape', '1', [], ''], ['elogind-firstboot', '1', ['elogind-firstboot.service'], 'ENABLE_FIRSTBOOT'], ['elogind-fsck@.service', - '8', ['elogind-fsck', 'elogind-fsck-root.service'], - ''], ['elogind-fstab-generator', '8', [], ''], ['elogind-getty-generator', '8', [], ''], ['elogind-gpt-auto-generator', '8', [], ''], ['elogind-halt.service', - '8', ['elogind-kexec.service', 'elogind-poweroff.service', 'elogind-reboot.service', 'elogind-shutdown'], + '8', + ''], + '8', ''], ['elogind-hibernate-resume-generator', '8', [], 'ENABLE_HIBERNATE'], ['elogind-hibernate-resume@.service', @@ -576,27 +576,27 @@ manpages = [ ['elogind-journal-remote', '8', [], 'HAVE_MICROHTTPD'], ['elogind-journal-upload', '8', [], 'HAVE_MICROHTTPD'], ['elogind-journald.service', - '8', ['elogind-journald', 'elogind-journald-audit.socket', 'elogind-journald-dev-log.socket', 'elogind-journald.socket'], - ''], ['elogind-localed.service', '8', ['elogind-localed'], 'ENABLE_LOCALED'], ['elogind.service', '8', ['elogind'], 'ENABLE_LOGIND'], ['elogind-machine-id-commit.service', '8', [], ''], ['elogind-machine-id-setup', '1', [], ''], ['elogind-machined.service', '8', ['elogind-machined'], 'ENABLE_MACHINED'], ['elogind-makefs@.service', - '8', ['elogind-growfs', 'elogind-growfs@.service', 'elogind-makefs', 'elogind-makeswap@.service'], - ''], ['elogind-modules-load.service', '8', ['elogind-modules-load'], 'HAVE_KMOD'], ['elogind-mount', '1', ['elogind-umount'], ''], ['elogind-networkd-wait-online.service', + '8', + ''], + '8', + ''], '8', ['elogind-networkd-wait-online'], 'ENABLE_NETWORKD'], @@ -625,15 +625,15 @@ manpages = [ ['elogind-socket-activate', '1', [], ''], ['elogind-socket-proxyd', '8', [], ''], ['elogind-suspend.service', - '8', ['elogind-hibernate.service', 'elogind-hybrid-sleep.service', - 'elogind-suspend-to-hibernate.service', 'elogind-sleep'], - ''], ['elogind-sysctl.service', '8', ['elogind-sysctl'], ''], ['elogind-system-update-generator', '8', [], ''], ['elogind-system.conf', + '8', + 'elogind-suspend-then-hibernate.service', + ''], '5', ['system.conf.d', 'elogind-user.conf', 'user.conf.d'], ''], @@ -643,18 +643,18 @@ manpages = [ ['elogind-timedated.service', '8', ['elogind-timedated'], 'ENABLE_TIMEDATED'], ['elogind-timesyncd.service', '8', ['elogind-timesyncd'], 'ENABLE_TIMESYNCD'], ['elogind-tmpfiles', - '8', ['elogind-tmpfiles-clean.service', 'elogind-tmpfiles-clean.timer', 'elogind-tmpfiles-setup-dev.service', 'elogind-tmpfiles-setup.service'], - ''], ['elogind-tty-ask-password-agent', '1', [], ''], ['elogind-udevd.service', - '8', ['elogind-udevd', 'elogind-udevd-control.socket', 'elogind-udevd-kernel.socket'], + '8', + ''], + '8', ''], ['elogind-update-done.service', '8', ['elogind-update-done'], ''], ['elogind-update-utmp.service', diff --git a/src/basic/special.h b/src/basic/special.h index c058b1d85..808d8896a 100644 --- a/src/basic/special.h +++ b/src/basic/special.h @@ -37,6 +37,7 @@ #define SPECIAL_SUSPEND_TARGET "suspend.target" #define SPECIAL_HIBERNATE_TARGET "hibernate.target" #define SPECIAL_HYBRID_SLEEP_TARGET "hybrid-sleep.target" +#define SPECIAL_SUSPEND_THEN_HIBERNATE_TARGET "suspend-then-hibernate.target" /* Special boot targets */ #define SPECIAL_RESCUE_TARGET "rescue.target" diff --git a/src/login/logind-action.c b/src/login/logind-action.c index bae42db99..f431a1b80 100644 --- a/src/login/logind-action.c +++ b/src/login/logind-action.c @@ -53,7 +53,8 @@ int manager_handle_action( [HANDLE_KEXEC] = "Rebooting via kexec...", [HANDLE_SUSPEND] = "Suspending...", [HANDLE_HIBERNATE] = "Hibernating...", - [HANDLE_HYBRID_SLEEP] = "Hibernating and suspending..." + [HANDLE_HYBRID_SLEEP] = "Hibernating and suspending...", + [HANDLE_SUSPEND_THEN_HIBERNATE] = "Suspending, then hibernating...", }; #if 0 /// elogind does this itself. No target table required @@ -64,7 +65,8 @@ int manager_handle_action( [HANDLE_KEXEC] = SPECIAL_KEXEC_TARGET, [HANDLE_SUSPEND] = SPECIAL_SUSPEND_TARGET, [HANDLE_HIBERNATE] = SPECIAL_HIBERNATE_TARGET, - [HANDLE_HYBRID_SLEEP] = SPECIAL_HYBRID_SLEEP_TARGET + [HANDLE_HYBRID_SLEEP] = SPECIAL_HYBRID_SLEEP_TARGET, + [HANDLE_SUSPEND_THEN_HIBERNATE] = SPECIAL_SUSPEND_THEN_HIBERNATE_TARGET, }; #endif // 0 @@ -119,6 +121,8 @@ int manager_handle_action( supported = can_sleep("hibernate") > 0; else if (handle == HANDLE_HYBRID_SLEEP) supported = can_sleep("hybrid-sleep") > 0; + else if (handle == HANDLE_SUSPEND_THEN_HIBERNATE) + supported = can_sleep("suspend-then-hibernate") > 0; #else if (handle == HANDLE_SUSPEND) supported = can_sleep(m, "suspend") > 0; @@ -142,7 +146,9 @@ int manager_handle_action( return -EALREADY; } - inhibit_operation = IN_SET(handle, HANDLE_SUSPEND, HANDLE_HIBERNATE, HANDLE_HYBRID_SLEEP) ? INHIBIT_SLEEP : INHIBIT_SHUTDOWN; + inhibit_operation = IN_SET(handle, HANDLE_SUSPEND, HANDLE_HIBERNATE, + HANDLE_HYBRID_SLEEP, + HANDLE_SUSPEND_THEN_HIBERNATE) ? INHIBIT_SLEEP : INHIBIT_SHUTDOWN; /* If the actual operation is inhibited, warn and fail */ if (!ignore_inhibited && @@ -193,6 +199,7 @@ static const char* const handle_action_table[_HANDLE_ACTION_MAX] = { [HANDLE_SUSPEND] = "suspend", [HANDLE_HIBERNATE] = "hibernate", [HANDLE_HYBRID_SLEEP] = "hybrid-sleep", + [HANDLE_SUSPEND_THEN_HIBERNATE] = "suspend-then-hibernate", [HANDLE_LOCK] = "lock" }; diff --git a/src/login/logind-action.h b/src/login/logind-action.h index 8c31ec42b..9f5dee684 100644 --- a/src/login/logind-action.h +++ b/src/login/logind-action.h @@ -29,6 +29,7 @@ typedef enum HandleAction { HANDLE_SUSPEND, HANDLE_HIBERNATE, HANDLE_HYBRID_SLEEP, + HANDLE_SUSPEND_THEN_HIBERNATE, HANDLE_LOCK, _HANDLE_ACTION_MAX, _HANDLE_ACTION_INVALID = -1 diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c index 165274461..7f99a8cce 100644 --- a/src/login/logind-dbus.c +++ b/src/login/logind-dbus.c @@ -661,10 +661,9 @@ static int method_list_inhibitors(sd_bus_message *message, void *userdata, sd_bu static int method_create_session(sd_bus_message *message, void *userdata, sd_bus_error *error) { const char *service, *type, *class, *cseat, *tty, *display, *remote_user, *remote_host, *desktop; - uint32_t audit_id = 0; - _cleanup_free_ char *unit = NULL; - _cleanup_free_ char *id = NULL; + _cleanup_free_ char *unit = NULL, *id = NULL; Session *session = NULL; + uint32_t audit_id = 0; Manager *m = userdata; User *user = NULL; Seat *seat = NULL; @@ -688,7 +687,7 @@ static int method_create_session(sd_bus_message *message, void *userdata, sd_bus if (!uid_is_valid(uid)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid UID"); - if (leader < 0 || leader == 1) + if (leader < 0 || leader == 1 || leader == getpid_cached()) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid leader PID"); if (isempty(type)) @@ -734,7 +733,7 @@ static int method_create_session(sd_bus_message *message, void *userdata, sd_bus if (v <= 0) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Cannot determine VT number from virtual console TTY %s", tty); - if (!vtnr) + if (vtnr == 0) vtnr = (uint32_t) v; else if (vtnr != (uint32_t) v) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Specified TTY and VT number do not match"); @@ -752,7 +751,7 @@ static int method_create_session(sd_bus_message *message, void *userdata, sd_bus if (seat) { if (seat_has_vts(seat)) { - if (!vtnr || vtnr > 63) + if (vtnr <= 0 || vtnr > 63) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "VT number out of range"); } else { if (vtnr != 0) @@ -792,16 +791,13 @@ static int method_create_session(sd_bus_message *message, void *userdata, sd_bus return r; } - /* - * Check if we are already in a logind session. Or if we are in user@.service - * which is a special PAM session that avoids creating a logind session. - */ - r = cg_pid_get_unit(leader, &unit); + /* Check if we are already in a logind session. Or if we are in user@.service which is a special PAM session + * that avoids creating a logind session. */ + r = manager_get_user_by_pid(m, leader, NULL); if (r < 0) return r; - if (hashmap_get(m->session_units, unit) || - hashmap_get(m->user_units, unit)) - return sd_bus_error_setf(error, BUS_ERROR_SESSION_BUSY, "Already running in a session"); + if (r > 0) + return sd_bus_error_setf(error, BUS_ERROR_SESSION_BUSY, "Already running in a session or user slice"); /* * Old gdm and lightdm start the user-session on the same VT as @@ -835,9 +831,8 @@ static int method_create_session(sd_bus_message *message, void *userdata, sd_bus * the audit data and let's better register a new * ID */ if (hashmap_get(m->sessions, id)) { - log_warning("Existing logind session ID %s used by new audit session, ignoring", id); + log_warning("Existing logind session ID %s used by new audit session, ignoring.", id); audit_id = AUDIT_SESSION_INVALID; - id = mfree(id); } } @@ -930,8 +925,7 @@ static int method_create_session(sd_bus_message *message, void *userdata, sd_bus session->create_message = sd_bus_message_ref(message); #if 0 /// UNNEEDED by elogind - /* Now, let's wait until the slice unit and stuff got - * created. We send the reply back from + /* Now, let's wait until the slice unit and stuff got created. We send the reply back from * session_send_create_reply(). */ #else /* We reply directly. */ @@ -2045,12 +2039,12 @@ static int method_hybrid_sleep(sd_bus_message *message, void *userdata, sd_bus_e error); } -static int method_suspend_to_hibernate(sd_bus_message *message, void *userdata, sd_bus_error *error) { +static int method_suspend_then_hibernate(sd_bus_message *message, void *userdata, sd_bus_error *error) { Manager *m = userdata; return method_do_shutdown_or_sleep( m, message, - SPECIAL_SUSPEND_TO_HIBERNATE_TARGET, + SPECIAL_SUSPEND_THEN_HIBERNATE_TARGET, #else HANDLE_HYBRID_SLEEP, #endif // 0 @@ -2542,7 +2536,7 @@ static int method_can_hybrid_sleep(sd_bus_message *message, void *userdata, sd_b error); } -static int method_can_suspend_to_hibernate(sd_bus_message *message, void *userdata, sd_bus_error *error) { +static int method_can_suspend_then_hibernate(sd_bus_message *message, void *userdata, sd_bus_error *error) { Manager *m = userdata; return method_can_shutdown_or_sleep( @@ -2551,7 +2545,7 @@ static int method_can_suspend_to_hibernate(sd_bus_message *message, void *userda "org.freedesktop.login1.hibernate", "org.freedesktop.login1.hibernate-multiple-sessions", "org.freedesktop.login1.hibernate-ignore-inhibit", - "suspend-to-hibernate", + "suspend-then-hibernate", error); } @@ -2889,14 +2883,14 @@ const sd_bus_vtable manager_vtable[] = { SD_BUS_METHOD("Suspend", "b", NULL, method_suspend, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("Hibernate", "b", NULL, method_hibernate, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("HybridSleep", "b", NULL, method_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED), - SD_BUS_METHOD("SuspendToHibernate", "b", NULL, method_suspend_to_hibernate, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("SuspendThenHibernate", "b", NULL, method_suspend_then_hibernate, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("CanPowerOff", NULL, "s", method_can_poweroff, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("CanReboot", NULL, "s", method_can_reboot, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("CanHalt", NULL, "s", method_can_halt, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("CanSuspend", NULL, "s", method_can_suspend, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("CanHibernate", NULL, "s", method_can_hibernate, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("CanHybridSleep", NULL, "s", method_can_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED), - SD_BUS_METHOD("CanSuspendToHibernate", NULL, "s", method_can_suspend_to_hibernate, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("CanSuspendThenHibernate", NULL, "s", method_can_suspend_then_hibernate, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("ScheduleShutdown", "st", NULL, method_schedule_shutdown, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("CancelScheduledShutdown", NULL, "b", method_cancel_scheduled_shutdown, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("Inhibit", "ssss", "h", method_inhibit, SD_BUS_VTABLE_UNPRIVILEGED), @@ -3253,13 +3247,8 @@ int manager_start_scope( return r; } - /* cgroup empty notification is not available in containers - * currently. To make this less problematic, let's shorten the - * stop timeout for sessions, so that we don't wait - * forever. */ - - /* Make sure that the session shells are terminated with - * SIGHUP since bash and friends tend to ignore SIGTERM */ + /* Make sure that the session shells are terminated with SIGHUP since bash and friends tend to ignore + * SIGTERM */ r = sd_bus_message_append(m, "(sv)", "SendSIGHUP", "b", true); if (r < 0) return r; diff --git a/src/login/org.freedesktop.login1.conf b/src/login/org.freedesktop.login1.conf index a25eb4401..1f81604b5 100644 --- a/src/login/org.freedesktop.login1.conf +++ b/src/login/org.freedesktop.login1.conf @@ -150,6 +150,10 @@ send_interface="org.freedesktop.login1.Manager" send_member="HybridSleep"/> + + @@ -174,6 +178,10 @@ send_interface="org.freedesktop.login1.Manager" send_member="CanHybridSleep"/> + + diff --git a/src/shared/sleep-config.c b/src/shared/sleep-config.c index 1f7792ae5..a9167fc29 100644 --- a/src/shared/sleep-config.c +++ b/src/shared/sleep-config.c @@ -97,13 +97,13 @@ int parse_sleep_config(const char *verb, char ***_modes, char ***_states, usec_t else states = strv_new("disk", NULL); - } else if (streq(verb, "suspend-to-hibernate")) + } else if (streq(verb, "suspend-then-hibernate")) modes = states = NULL; else assert_not_reached("what verb"); if ((!modes && STR_IN_SET(verb, "hibernate", "hybrid-sleep")) || - (!states && !streq(verb, "suspend-to-hibernate"))) { + (!states && !streq(verb, "suspend-then-hibernate"))) { strv_free(modes); strv_free(states); return log_oom(); @@ -319,12 +319,14 @@ int can_sleep(const char *verb) { || !can_sleep_disk(m->suspend_mode) ) ) return false; assert(STR_IN_SET(verb, "suspend", "hibernate", "hybrid-sleep", "suspend-to-hibernate")); + assert(STR_IN_SET(verb, "suspend", "hibernate", "hybrid-sleep", "suspend-then-hibernate")); if ( streq(verb, "hibernate") && ( !can_sleep_state(m->hibernate_state) || !can_sleep_disk(m->hibernate_mode) ) ) return false; if (streq(verb, "suspend-to-hibernate")) + if (streq(verb, "suspend-then-hibernate")) return can_s2h(); if ( streq(verb, "hybrid-sleep") diff --git a/src/sleep/sleep.c b/src/sleep/sleep.c index f0873c989..66c9d04fb 100644 --- a/src/sleep/sleep.c +++ b/src/sleep/sleep.c @@ -4,6 +4,7 @@ Copyright 2012 Lennart Poettering Copyright 2013 Zbigniew Jędrzejewski-Szmek + Copyright 2018 Dell Inc. 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 @@ -25,12 +26,14 @@ #include "sd-messages.h" +//#include "parse-util.h" #include "def.h" #include "exec-util.h" #include "fd-util.h" #include "fileio.h" //#include "log.h" //#include "sleep-config.h" +//#include "stdio-util.h" //#include "string-util.h" #include "strv.h" //#include "util.h" @@ -138,6 +141,83 @@ static int execute(char **modes, char **states) { return r; } +static int read_wakealarm(uint64_t *result) { + _cleanup_free_ char *t = NULL; + + if (read_one_line_file("/sys/class/rtc/rtc0/since_epoch", &t) >= 0) + return safe_atou64(t, result); + return -EBADF; +} + +static int write_wakealarm(const char *str) { + + _cleanup_fclose_ FILE *f = NULL; + int r; + + f = fopen("/sys/class/rtc/rtc0/wakealarm", "we"); + if (!f) + return log_error_errno(errno, "Failed to open /sys/class/rtc/rtc0/wakealarm: %m"); + + r = write_string_stream(f, str, 0); + if (r < 0) + return log_error_errno(r, "Failed to write '%s' to /sys/class/rtc/rtc0/wakealarm: %m", str); + + return 0; +} + +static int execute_s2h(usec_t hibernate_delay_sec) { + + _cleanup_strv_free_ char **hibernate_modes = NULL, **hibernate_states = NULL, + **suspend_modes = NULL, **suspend_states = NULL; + usec_t orig_time, cmp_time; + char time_str[DECIMAL_STR_MAX(uint64_t)]; + int r; + + r = parse_sleep_config("suspend", &suspend_modes, &suspend_states, + NULL); + if (r < 0) + return r; + + r = parse_sleep_config("hibernate", &hibernate_modes, + &hibernate_states, NULL); + if (r < 0) + return r; + + r = read_wakealarm(&orig_time); + if (r < 0) + return log_error_errno(errno, "Failed to read time: %d", r); + + orig_time += hibernate_delay_sec / USEC_PER_SEC; + xsprintf(time_str, "%" PRIu64, orig_time); + + r = write_wakealarm(time_str); + if (r < 0) + return r; + + log_debug("Set RTC wake alarm for %s", time_str); + + r = execute(suspend_modes, suspend_states); + if (r < 0) + return r; + + r = read_wakealarm(&cmp_time); + if (r < 0) + return log_error_errno(errno, "Failed to read time: %d", r); + + /* reset RTC */ + r = write_wakealarm("0"); + if (r < 0) + return r; + + log_debug("Woke up at %"PRIu64, cmp_time); + + /* if woken up after alarm time, hibernate */ + if (cmp_time >= orig_time) + r = execute(hibernate_modes, hibernate_states); + + return r; +} + #if 0 /// elogind calls execute() by itself and does not need another binary static void help(void) { printf("%s COMMAND\n\n" @@ -148,6 +228,8 @@ static void help(void) { " suspend Suspend the system\n" " hibernate Hibernate the system\n" " hybrid-sleep Both hibernate and suspend the system\n" + " suspend-then-hibernate Initially suspend and then hibernate\n" + " the system after a fixed period of time\n" , program_invocation_short_name); } @@ -193,7 +275,8 @@ static int parse_argv(int argc, char *argv[]) { if (!streq(arg_verb, "suspend") && !streq(arg_verb, "hibernate") && - !streq(arg_verb, "hybrid-sleep")) { + !streq(arg_verb, "hybrid-sleep") && + !streq(arg_verb, "suspend-then-hibernate")) { log_error("Unknown command '%s'.", arg_verb); return -EINVAL; } @@ -203,6 +286,7 @@ static int parse_argv(int argc, char *argv[]) { int main(int argc, char *argv[]) { _cleanup_strv_free_ char **modes = NULL, **states = NULL; + usec_t delay = 0; int r; log_set_target(LOG_TARGET_AUTO); @@ -213,12 +297,14 @@ int main(int argc, char *argv[]) { if (r <= 0) goto finish; - r = parse_sleep_config(arg_verb, &modes, &states); + r = parse_sleep_config(arg_verb, &modes, &states, &delay); if (r < 0) goto finish; - r = execute(modes, states); - + if (streq(arg_verb, "suspend-then-hibernate")) + r = execute_s2h(delay); + else + r = execute(modes, states); finish: return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } -- 2.30.2