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