]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/sleep/sleep.c
networkd: update logging macros for parameter order, and errno, to match rest of...
[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
19adb8a3
ZJS
51 log_debug("Failed to write '%s' to /sys/power/disk: %s",
52 *mode, strerror(-k));
53 if (r == 0)
54 r = k;
55 }
6edd7d0a 56
19adb8a3
ZJS
57 if (r < 0)
58 log_error("Failed to write mode to /sys/power/disk: %s",
59 strerror(-r));
6edd7d0a 60
19adb8a3
ZJS
61 return r;
62}
6edd7d0a 63
2fd069b1 64static int write_state(FILE **f, char **states) {
19adb8a3
ZJS
65 char **state;
66 int r = 0;
67
68 STRV_FOREACH(state, states) {
69 int k;
70
717603e3 71 k = write_string_stream(*f, *state);
19adb8a3
ZJS
72 if (k == 0)
73 return 0;
74 log_debug("Failed to write '%s' to /sys/power/state: %s",
75 *state, strerror(-k));
76 if (r == 0)
77 r = k;
78
2fd069b1
ZJS
79 fclose(*f);
80 *f = fopen("/sys/power/state", "we");
81 if (!*f) {
19adb8a3
ZJS
82 log_error("Failed to open /sys/power/state: %m");
83 return -errno;
84 }
6edd7d0a
LP
85 }
86
19adb8a3
ZJS
87 return r;
88}
6edd7d0a 89
19adb8a3
ZJS
90static int execute(char **modes, char **states) {
91 char* arguments[4];
92 int r;
2fd069b1 93 _cleanup_fclose_ FILE *f = NULL;
19adb8a3 94 const char* note = strappenda("SLEEP=", arg_verb);
6524990f 95
19adb8a3 96 /* This file is opened first, so that if we hit an error,
09692409 97 * we can abort before modifying any state. */
6edd7d0a
LP
98 f = fopen("/sys/power/state", "we");
99 if (!f) {
100 log_error("Failed to open /sys/power/state: %m");
19adb8a3 101 return -errno;
6edd7d0a
LP
102 }
103
19adb8a3
ZJS
104 /* Configure the hibernation mode */
105 r = write_mode(modes);
106 if (r < 0)
107 return r;
108
6edd7d0a
LP
109 arguments[0] = NULL;
110 arguments[1] = (char*) "pre";
19adb8a3 111 arguments[2] = arg_verb;
6edd7d0a 112 arguments[3] = NULL;
e2680723 113 execute_directory(SYSTEM_SLEEP_PATH, NULL, DEFAULT_TIMEOUT_USEC, arguments);
6edd7d0a 114
19adb8a3
ZJS
115 log_struct(LOG_INFO,
116 MESSAGE_ID(SD_MESSAGE_SLEEP_START),
117 "MESSAGE=Suspending system...",
118 note,
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,
126 MESSAGE_ID(SD_MESSAGE_SLEEP_STOP),
127 "MESSAGE=System resumed.",
128 note,
129 NULL);
eb267289 130
6edd7d0a 131 arguments[1] = (char*) "post";
e2680723 132 execute_directory(SYSTEM_SLEEP_PATH, NULL, DEFAULT_TIMEOUT_USEC, 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:
172 puts(PACKAGE_STRING);
173 puts(SYSTEMD_FEATURES);
174 return 0 /* done */;
175
176 case '?':
177 return -EINVAL;
178
179 default:
eb9da376 180 assert_not_reached("Unhandled option");
19adb8a3
ZJS
181 }
182
183 if (argc - optind != 1) {
184 log_error("Usage: %s COMMAND",
185 program_invocation_short_name);
186 return -EINVAL;
187 }
188
189 arg_verb = argv[optind];
6edd7d0a 190
19adb8a3
ZJS
191 if (!streq(arg_verb, "suspend") &&
192 !streq(arg_verb, "hibernate") &&
193 !streq(arg_verb, "hybrid-sleep")) {
194 log_error("Unknown command '%s'.", arg_verb);
195 return -EINVAL;
196 }
197
198 return 1 /* work to do */;
199}
200
201int main(int argc, char *argv[]) {
202 _cleanup_strv_free_ char **modes = NULL, **states = NULL;
203 int r;
204
205 log_set_target(LOG_TARGET_AUTO);
206 log_parse_environment();
207 log_open();
208
209 r = parse_argv(argc, argv);
210 if (r <= 0)
211 goto finish;
212
213 r = parse_sleep_config(arg_verb, &modes, &states);
214 if (r < 0)
215 goto finish;
216
217 r = execute(modes, states);
218
219finish:
220 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
6edd7d0a 221}