]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/sleep/sleep.c
Merge pull request #7388 from keszybz/doc-tweak
[thirdparty/systemd.git] / src / sleep / sleep.c
CommitLineData
6edd7d0a
LP
1/***
2 This file is part of systemd.
3
4 Copyright 2012 Lennart Poettering
19adb8a3 5 Copyright 2013 Zbigniew Jędrzejewski-Szmek
6edd7d0a
LP
6
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
11
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
19***/
20
6edd7d0a 21#include <errno.h>
19adb8a3 22#include <getopt.h>
3f6fd1ba 23#include <stdio.h>
6edd7d0a 24
aa62a893 25#include "sd-messages.h"
3f6fd1ba
LP
26
27#include "def.h"
89711996 28#include "exec-util.h"
3ffd4af2 29#include "fd-util.h"
a5c32cff 30#include "fileio.h"
3f6fd1ba 31#include "log.h"
19adb8a3 32#include "sleep-config.h"
07630cea 33#include "string-util.h"
3f6fd1ba
LP
34#include "strv.h"
35#include "util.h"
19adb8a3
ZJS
36
37static char* arg_verb = NULL;
38
39static int write_mode(char **modes) {
40 int r = 0;
41 char **mode;
42
43 STRV_FOREACH(mode, modes) {
aa62a893
LP
44 int k;
45
4c1fc3e4 46 k = write_string_file("/sys/power/disk", *mode, 0);
19adb8a3
ZJS
47 if (k == 0)
48 return 0;
aa62a893 49
c33b3297
MS
50 log_debug_errno(k, "Failed to write '%s' to /sys/power/disk: %m",
51 *mode);
19adb8a3
ZJS
52 if (r == 0)
53 r = k;
54 }
6edd7d0a 55
19adb8a3 56 if (r < 0)
c33b3297 57 log_error_errno(r, "Failed to write mode to /sys/power/disk: %m");
6edd7d0a 58
19adb8a3
ZJS
59 return r;
60}
6edd7d0a 61
2fd069b1 62static int write_state(FILE **f, char **states) {
19adb8a3
ZJS
63 char **state;
64 int r = 0;
65
66 STRV_FOREACH(state, states) {
67 int k;
68
b1837133 69 k = write_string_stream(*f, *state, 0);
19adb8a3
ZJS
70 if (k == 0)
71 return 0;
c33b3297
MS
72 log_debug_errno(k, "Failed to write '%s' to /sys/power/state: %m",
73 *state);
19adb8a3
ZJS
74 if (r == 0)
75 r = k;
76
2fd069b1
ZJS
77 fclose(*f);
78 *f = fopen("/sys/power/state", "we");
4a62c710
MS
79 if (!*f)
80 return log_error_errno(errno, "Failed to open /sys/power/state: %m");
6edd7d0a
LP
81 }
82
19adb8a3
ZJS
83 return r;
84}
6edd7d0a 85
19adb8a3 86static int execute(char **modes, char **states) {
e2cc6eca
LP
87
88 char *arguments[] = {
89 NULL,
90 (char*) "pre",
91 arg_verb,
92 NULL
93 };
b5084605
LP
94 static const char* const dirs[] = {
95 SYSTEM_SLEEP_PATH,
96 NULL
97 };
e2cc6eca 98
19adb8a3 99 int r;
2fd069b1 100 _cleanup_fclose_ FILE *f = NULL;
6524990f 101
19adb8a3 102 /* This file is opened first, so that if we hit an error,
09692409 103 * we can abort before modifying any state. */
6edd7d0a 104 f = fopen("/sys/power/state", "we");
4a62c710
MS
105 if (!f)
106 return log_error_errno(errno, "Failed to open /sys/power/state: %m");
6edd7d0a 107
19adb8a3
ZJS
108 /* Configure the hibernation mode */
109 r = write_mode(modes);
110 if (r < 0)
111 return r;
112
c6e47247 113 execute_directories(dirs, DEFAULT_TIMEOUT_USEC, NULL, NULL, arguments);
6edd7d0a 114
19adb8a3 115 log_struct(LOG_INFO,
2b044526 116 "MESSAGE_ID=" SD_MESSAGE_SLEEP_START_STR,
e2cc6eca
LP
117 LOG_MESSAGE("Suspending system..."),
118 "SLEEP=%s", arg_verb,
19adb8a3
ZJS
119 NULL);
120
2fd069b1 121 r = write_state(&f, states);
19adb8a3
ZJS
122 if (r < 0)
123 return r;
124
125 log_struct(LOG_INFO,
2b044526 126 "MESSAGE_ID=" SD_MESSAGE_SLEEP_STOP_STR,
a5ccdb98 127 LOG_MESSAGE("System resumed."),
e2cc6eca 128 "SLEEP=%s", arg_verb,
19adb8a3 129 NULL);
eb267289 130
6edd7d0a 131 arguments[1] = (char*) "post";
c6e47247 132 execute_directories(dirs, DEFAULT_TIMEOUT_USEC, NULL, NULL, arguments);
6edd7d0a 133
19adb8a3
ZJS
134 return r;
135}
6edd7d0a 136
601185b4 137static void help(void) {
19adb8a3
ZJS
138 printf("%s COMMAND\n\n"
139 "Suspend the system, hibernate the system, or both.\n\n"
140 "Commands:\n"
141 " -h --help Show this help and exit\n"
142 " --version Print version string and exit\n"
143 " suspend Suspend the system\n"
144 " hibernate Hibernate the system\n"
145 " hybrid-sleep Both hibernate and suspend the system\n"
601185b4 146 , program_invocation_short_name);
19adb8a3 147}
6edd7d0a 148
19adb8a3
ZJS
149static int parse_argv(int argc, char *argv[]) {
150 enum {
151 ARG_VERSION = 0x100,
152 };
153
154 static const struct option options[] = {
155 { "help", no_argument, NULL, 'h' },
156 { "version", no_argument, NULL, ARG_VERSION },
eb9da376 157 {}
19adb8a3
ZJS
158 };
159
160 int c;
161
162 assert(argc >= 0);
163 assert(argv);
164
601185b4 165 while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
19adb8a3
ZJS
166 switch(c) {
167 case 'h':
601185b4
ZJS
168 help();
169 return 0; /* done */
19adb8a3
ZJS
170
171 case ARG_VERSION:
3f6fd1ba 172 return version();
19adb8a3
ZJS
173
174 case '?':
175 return -EINVAL;
176
177 default:
eb9da376 178 assert_not_reached("Unhandled option");
19adb8a3
ZJS
179 }
180
181 if (argc - optind != 1) {
182 log_error("Usage: %s COMMAND",
183 program_invocation_short_name);
184 return -EINVAL;
185 }
186
187 arg_verb = argv[optind];
6edd7d0a 188
19adb8a3
ZJS
189 if (!streq(arg_verb, "suspend") &&
190 !streq(arg_verb, "hibernate") &&
191 !streq(arg_verb, "hybrid-sleep")) {
192 log_error("Unknown command '%s'.", arg_verb);
193 return -EINVAL;
194 }
195
196 return 1 /* work to do */;
197}
198
199int main(int argc, char *argv[]) {
200 _cleanup_strv_free_ char **modes = NULL, **states = NULL;
201 int r;
202
203 log_set_target(LOG_TARGET_AUTO);
204 log_parse_environment();
205 log_open();
206
207 r = parse_argv(argc, argv);
208 if (r <= 0)
209 goto finish;
210
211 r = parse_sleep_config(arg_verb, &modes, &states);
212 if (r < 0)
213 goto finish;
214
215 r = execute(modes, states);
216
217finish:
218 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
6edd7d0a 219}