zzz.c (2811B) download
1#include "config.h"
2#include "util.h"
3
4#include <errno.h>
5#include <fcntl.h>
6#include <getopt.h>
7#include <string.h>
8#include <sys/stat.h>
9#include <sys/wait.h>
10#include <unistd.h>
11
12
13const char* current_prog(void) {
14 return "zzz";
15}
16
17static int open_write(const char* path, const char* string) {
18 int fd;
19
20 if ((fd = open(path, O_WRONLY | O_TRUNC)) == -1) {
21 print_errno("cannot open %s: %s\n", path);
22 return -1;
23 }
24 if (write(fd, string, strlen(string)) == -1) {
25 print_errno("error writing to %s: %s\n", path);
26 close(fd);
27 return -1;
28 }
29 return close(fd);
30}
31
32
33int main(int argc, char** argv) {
34 int opt;
35 pid_t pid;
36 struct stat st;
37
38 const char *new_state = NULL,
39 *new_disk = NULL;
40
41 if (streq(argv[0], "zzz")) {
42 new_state = "mem";
43 new_disk = NULL;
44 } else if (streq(argv[0], "ZZZ")) {
45 new_state = "disk";
46 new_disk = "platform";
47 } else {
48 fprint(1, "error: program-name `%s` invalid\n", argv[0]);
49 return 1;
50 }
51
52 struct option long_options[] = {
53 { "noop", no_argument, 0, 'n' },
54 { "freeze", no_argument, 0, 'S' },
55 { "suspend", no_argument, 0, 'z' },
56 { "hibernate", no_argument, 0, 'Z' },
57 { "reboot", no_argument, 0, 'R' },
58 { "hybrid", no_argument, 0, 'H' },
59 { 0 },
60 };
61
62 while ((opt = getopt_long(argc, argv, "nSzZRH", long_options, NULL)) != -1) {
63 switch (opt) {
64 case 'n':
65 new_state = NULL;
66 new_disk = NULL;
67 break;
68 case 's':
69 new_state = "suspend";
70 new_disk = NULL;
71 break;
72 case 'S':
73 new_state = "freeze";
74 new_disk = NULL;
75 break;
76 case 'z':
77 new_state = "mem";
78 new_disk = NULL;
79 break;
80 case 'Z':
81 new_state = "disk";
82 new_disk = "platform";
83 break;
84 case 'R':
85 new_state = "disk";
86 new_disk = "reboot";
87 break;
88 case 'H':
89 new_state = "disk";
90 new_disk = "suspend";
91 break;
92 default:
93 print("zzz [-n] [-S] [-z] [-Z] [-R] [-H]\n");
94 return 1;
95 }
96 }
97
98 argc -= optind, argv += optind;
99
100
101 if (stat(SV_SUSPEND_EXEC, &st) == 0 && st.st_mode & S_IXUSR) {
102 if ((pid = fork()) == -1) {
103 fprint(1, "failed to fork for " SV_SUSPEND_EXEC ": %r\n");
104 return 1;
105 } else if (pid == 0) { // child
106 execl(SV_SUSPEND_EXEC, SV_SUSPEND_EXEC, NULL);
107 fprint(1, "failed to execute " SV_SUSPEND_EXEC ": %r\n");
108 _exit(1);
109 }
110
111 wait(NULL);
112 }
113
114 if (new_disk) {
115 open_write("/sys/power/disk", new_disk);
116 }
117
118 if (new_state) {
119 open_write("/sys/power/state", new_state);
120 } else {
121 sleep(5);
122 }
123
124 if (stat(SV_RESUME_EXEC, &st) == 0 && st.st_mode & S_IXUSR) {
125 if ((pid = fork()) == -1) {
126 fprint(1, "failed to fork for " SV_RESUME_EXEC ": %r\n");
127 return 1;
128 } else if (pid == 0) { // child
129 execl(SV_RESUME_EXEC, SV_RESUME_EXEC, NULL);
130 fprint(1, "failed to execute " SV_RESUME_EXEC ": %r\n");
131 _exit(1);
132 }
133
134 wait(NULL);
135 }
136}