zzz.c (2811B)
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 13 const char* current_prog(void) { 14 return "zzz"; 15 } 16 17 static 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 33 int 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 }