fiss

Friedel's Initialization and Service Supervision
Log | Files | Refs | LICENSE

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 }