]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/sleep/sleep.c
logind: support for hybrid sleep (i.e. suspend+hibernate at the same time)
[thirdparty/systemd.git] / src / sleep / sleep.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2012 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <stdio.h>
23 #include <errno.h>
24 #include <string.h>
25
26 #include "log.h"
27 #include "util.h"
28 #include "systemd/sd-id128.h"
29 #include "systemd/sd-messages.h"
30
31 int main(int argc, char *argv[]) {
32 const char *verb;
33 char* arguments[4];
34 int r;
35 FILE *f;
36
37 log_set_target(LOG_TARGET_AUTO);
38 log_parse_environment();
39 log_open();
40
41 if (argc != 2) {
42 log_error("Invalid number of arguments.");
43 r = -EINVAL;
44 goto finish;
45 }
46
47 if (streq(argv[1], "suspend"))
48 verb = "mem";
49 else if (streq(argv[1], "hibernate") || streq(argv[1], "hybrid-sleep"))
50 verb = "disk";
51 else {
52 log_error("Unknown action '%s'.", argv[1]);
53 r = -EINVAL;
54 goto finish;
55 }
56
57 /* Configure the hibernation mode */
58 if (streq(argv[1], "hibernate")) {
59 if (write_one_line_file("/sys/power/disk", "platform") < 0)
60 write_one_line_file("/sys/power/disk", "shutdown");
61 } else if (streq(argv[1], "hybrid-sleep")) {
62 if (write_one_line_file("/sys/power/disk", "suspend") < 0)
63 if (write_one_line_file("/sys/power/disk", "platform") < 0)
64 write_one_line_file("/sys/power/disk", "shutdown");
65 }
66
67 f = fopen("/sys/power/state", "we");
68 if (!f) {
69 log_error("Failed to open /sys/power/state: %m");
70 r = -errno;
71 goto finish;
72 }
73
74 arguments[0] = NULL;
75 arguments[1] = (char*) "pre";
76 arguments[2] = argv[1];
77 arguments[3] = NULL;
78 execute_directory(SYSTEM_SLEEP_PATH, NULL, arguments);
79
80 if (streq(argv[1], "suspend"))
81 log_struct(LOG_INFO,
82 MESSAGE_ID(SD_MESSAGE_SLEEP_START),
83 "MESSAGE=Suspending system...",
84 "SLEEP=suspend",
85 NULL);
86 else if (streq(argv[1], "hibernate"))
87 log_struct(LOG_INFO,
88 MESSAGE_ID(SD_MESSAGE_SLEEP_START),
89 "MESSAGE=Hibernating system...",
90 "SLEEP=hibernate",
91 NULL);
92 else
93 log_struct(LOG_INFO,
94 MESSAGE_ID(SD_MESSAGE_SLEEP_START),
95 "MESSAGE=Hibernating and suspending system...",
96 "SLEEP=hybrid-sleep",
97 NULL);
98
99 fputs(verb, f);
100 fputc('\n', f);
101 fflush(f);
102
103 r = ferror(f) ? -errno : 0;
104
105 if (streq(argv[1], "suspend"))
106 log_struct(LOG_INFO,
107 MESSAGE_ID(SD_MESSAGE_SLEEP_STOP),
108 "MESSAGE=System resumed.",
109 "SLEEP=suspend",
110 NULL);
111 else
112 log_struct(LOG_INFO,
113 MESSAGE_ID(SD_MESSAGE_SLEEP_STOP),
114 "MESSAGE=System thawed.",
115 "SLEEP=hibernate",
116 NULL);
117
118 arguments[1] = (char*) "post";
119 execute_directory(SYSTEM_SLEEP_PATH, NULL, arguments);
120
121 fclose(f);
122
123 finish:
124
125 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
126
127 }