]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/sleep/sleep.c
util-lib: split our string related calls from util.[ch] into its own file 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
6edd7d0a 23#include <errno.h>
19adb8a3 24#include <getopt.h>
3f6fd1ba 25#include <stdio.h>
6edd7d0a 26
aa62a893 27#include "sd-messages.h"
3f6fd1ba
LP
28
29#include "def.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
40beecdb 69 k = write_string_stream(*f, *state, true);
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 };
e801700e 94 static const char* const dirs[] = {SYSTEM_SLEEP_PATH, NULL};
e2cc6eca 95
19adb8a3 96 int r;
2fd069b1 97 _cleanup_fclose_ FILE *f = NULL;
6524990f 98
19adb8a3 99 /* This file is opened first, so that if we hit an error,
09692409 100 * we can abort before modifying any state. */
6edd7d0a 101 f = fopen("/sys/power/state", "we");
4a62c710
MS
102 if (!f)
103 return log_error_errno(errno, "Failed to open /sys/power/state: %m");
6edd7d0a 104
19adb8a3
ZJS
105 /* Configure the hibernation mode */
106 r = write_mode(modes);
107 if (r < 0)
108 return r;
109
e801700e 110 execute_directories(dirs, DEFAULT_TIMEOUT_USEC, arguments);
6edd7d0a 111
19adb8a3 112 log_struct(LOG_INFO,
e2cc6eca
LP
113 LOG_MESSAGE_ID(SD_MESSAGE_SLEEP_START),
114 LOG_MESSAGE("Suspending system..."),
115 "SLEEP=%s", arg_verb,
19adb8a3
ZJS
116 NULL);
117
2fd069b1 118 r = write_state(&f, states);
19adb8a3
ZJS
119 if (r < 0)
120 return r;
121
122 log_struct(LOG_INFO,
e2cc6eca 123 LOG_MESSAGE_ID(SD_MESSAGE_SLEEP_STOP),
a5ccdb98 124 LOG_MESSAGE("System resumed."),
e2cc6eca 125 "SLEEP=%s", arg_verb,
19adb8a3 126 NULL);
eb267289 127
6edd7d0a 128 arguments[1] = (char*) "post";
e801700e 129 execute_directories(dirs, DEFAULT_TIMEOUT_USEC, arguments);
6edd7d0a 130
19adb8a3
ZJS
131 return r;
132}
6edd7d0a 133
601185b4 134static void help(void) {
19adb8a3
ZJS
135 printf("%s COMMAND\n\n"
136 "Suspend the system, hibernate the system, or both.\n\n"
137 "Commands:\n"
138 " -h --help Show this help and exit\n"
139 " --version Print version string and exit\n"
140 " suspend Suspend the system\n"
141 " hibernate Hibernate the system\n"
142 " hybrid-sleep Both hibernate and suspend the system\n"
601185b4 143 , program_invocation_short_name);
19adb8a3 144}
6edd7d0a 145
19adb8a3
ZJS
146static int parse_argv(int argc, char *argv[]) {
147 enum {
148 ARG_VERSION = 0x100,
149 };
150
151 static const struct option options[] = {
152 { "help", no_argument, NULL, 'h' },
153 { "version", no_argument, NULL, ARG_VERSION },
eb9da376 154 {}
19adb8a3
ZJS
155 };
156
157 int c;
158
159 assert(argc >= 0);
160 assert(argv);
161
601185b4 162 while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
19adb8a3
ZJS
163 switch(c) {
164 case 'h':
601185b4
ZJS
165 help();
166 return 0; /* done */
19adb8a3
ZJS
167
168 case ARG_VERSION:
3f6fd1ba 169 return version();
19adb8a3
ZJS
170
171 case '?':
172 return -EINVAL;
173
174 default:
eb9da376 175 assert_not_reached("Unhandled option");
19adb8a3
ZJS
176 }
177
178 if (argc - optind != 1) {
179 log_error("Usage: %s COMMAND",
180 program_invocation_short_name);
181 return -EINVAL;
182 }
183
184 arg_verb = argv[optind];
6edd7d0a 185
19adb8a3
ZJS
186 if (!streq(arg_verb, "suspend") &&
187 !streq(arg_verb, "hibernate") &&
188 !streq(arg_verb, "hybrid-sleep")) {
189 log_error("Unknown command '%s'.", arg_verb);
190 return -EINVAL;
191 }
192
193 return 1 /* work to do */;
194}
195
196int main(int argc, char *argv[]) {
197 _cleanup_strv_free_ char **modes = NULL, **states = NULL;
198 int r;
199
200 log_set_target(LOG_TARGET_AUTO);
201 log_parse_environment();
202 log_open();
203
204 r = parse_argv(argc, argv);
205 if (r <= 0)
206 goto finish;
207
208 r = parse_sleep_config(arg_verb, &modes, &states);
209 if (r < 0)
210 goto finish;
211
212 r = execute(modes, states);
213
214finish:
215 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
6edd7d0a 216}