commit dd19f651ac849a43e18bf59f5da1a52403be224b
parent 942e2ffd85f204bd36b6a597ae00c604bf997764
Author: Friedel Schon <[email protected]>
Date: Mon, 24 Apr 2023 12:20:30 +0200
rewriting zzz in C
Diffstat:
A | src/exec/zzz.c | | | 102 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
D | src/script/zzz.sh | | | 81 | ------------------------------------------------------------------------------- |
2 files changed, 102 insertions(+), 81 deletions(-)
diff --git a/src/exec/zzz.c b/src/exec/zzz.c
@@ -0,0 +1,101 @@
+#include "util.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#define write_state(state_fd, ident) \
+ do { \
+ if (write((state_fd), (ident), sizeof(ident) - 1) == -1) \
+ fprintf(stderr, "error writing to /sys/power/: %s\n", strerror(errno)); \
+ } while (0)
+
+typedef enum zzz_mode {
+ ZZZ_NOOP,
+ ZZZ_STANDBY,
+ ZZZ_SUSPEND,
+ ZZZ_HIBERNATE_PLATFORM,
+ ZZZ_HIBERNATE_REBOOT,
+ ZZZ_HIBERNATE_SUSPEND,
+} zzz_mode_t;
+
+int main(int argc, char** argv) {
+ int opt;
+ zzz_mode_t mode = ZZZ_SUSPEND;
+
+ while ((opt = getopt(argc, argv, "nSzZRH")) != -1) {
+ switch (opt) {
+ case 'n':
+ mode = ZZZ_NOOP;
+ break;
+ case 'S':
+ mode = ZZZ_STANDBY;
+ break;
+ case 'z':
+ mode = ZZZ_SUSPEND;
+ break;
+ case 'Z':
+ mode = ZZZ_HIBERNATE_PLATFORM;
+ break;
+ case 'R':
+ mode = ZZZ_HIBERNATE_REBOOT;
+ break;
+ case 'H':
+ mode = ZZZ_HIBERNATE_SUSPEND;
+ break;
+ default:
+ printf("zzz [-n] [-S] [-z] [-Z] [-R] [-H]\n");
+ return 1;
+ }
+ }
+
+ argc -= optind, argv += optind;
+
+ int sys_state, sys_disk;
+ if ((sys_state = open("/sys/power/state", O_WRONLY | O_TRUNC)) == -1) {
+ fprintf(stderr, "cannot open /sys/power/state: %s\n", strerror(errno));
+ return 1;
+ }
+ if ((sys_disk = open("/sys/power/disk", O_WRONLY | O_TRUNC)) == -1) {
+ fprintf(stderr, "cannot open /sys/power/disk: %s\n", strerror(errno));
+ return 1;
+ }
+
+ printf("Zzzz...\n");
+
+ switch (mode) {
+ case ZZZ_STANDBY:
+ write_state(sys_state, "freeze");
+ break;
+
+ case ZZZ_SUSPEND:
+ write_state(sys_state, "mem");
+ break;
+
+ case ZZZ_HIBERNATE_PLATFORM:
+ write_state(sys_disk, "platform");
+ write_state(sys_state, "disk");
+ break;
+ case ZZZ_HIBERNATE_REBOOT:
+ write_state(sys_disk, "reboot");
+ write_state(sys_state, "disk");
+ break;
+ case ZZZ_HIBERNATE_SUSPEND:
+ write_state(sys_disk, "suspend");
+ write_state(sys_state, "disk");
+ break;
+
+ case ZZZ_NOOP:
+ sleep(5);
+ break;
+ }
+
+ close(sys_state);
+ close(sys_disk);
+
+ printf("Yawn!\n");
+}
+\ No newline at end of file
diff --git a/src/script/zzz.sh b/src/script/zzz.sh
@@ -1,81 +0,0 @@
-#!/bin/sh
-# zzz - really simple suspend script
-
-# Define usage information
-USAGE="Usage: ${0##*/} [-nSzZR]
- -n dry run (sleep for 5s instead of suspend/hibernate)
- -S Low-power idle (ACPI S1)
- -z suspend to RAM (ACPI S3) [DEFAULT for zzz(8)]
- -Z hibernate to disk & power off (ACPI S4) [DEFAULT for ZZZ(8)]
- -R hibernate to disk & reboot
- -H hibernate to disk & suspend (aka suspend-hybrid)"
-
-# Define a function to print error messages and exit with error code 1
-fail() {
- echo "${0##*/}: $*" >&2
- exit 1
-}
-
-# Set default values for environment variables
-export ZZZ_MODE=suspend
-export ZZZ_HIBERNATE_MODE=platform
-
-# Check the name of the script to determine the default mode
-case "$0" in
- *ZZZ) ZZZ_MODE=hibernate;;
-esac
-
-# Parse command-line options
-while getopts hnSzHRZ opt; do
- case "$opt" in
- n) ZZZ_MODE=noop;;
- S) ZZZ_MODE=standby;;
- z) ZZZ_MODE=suspend;;
- Z) ZZZ_MODE=hibernate;;
- R) ZZZ_MODE=hibernate; ZZZ_HIBERNATE_MODE=reboot;;
- H) ZZZ_MODE=hibernate; ZZZ_HIBERNATE_MODE=suspend;;
- [h?]) fail "$USAGE";;
- esac
-done
-
-# Shift command-line arguments to skip processed options
-shift $((OPTIND-1))
-
-# Check if the selected mode is supported
-case "$ZZZ_MODE" in
- suspend) grep -q mem /sys/power/state || fail "suspend not supported";;
- hibernate) grep -q disk /sys/power/state || fail "hibernate not supported";;
-esac
-
-# Check if the current user has permission to sleep the system
-test -w /sys/power/state || fail "sleep permission denied"
-
-# Run the main logic in a subshell with a file lock to prevent multiple instances
-(
- flock -n 9 || fail "another instance of zzz is running"
-
- printf "Zzzz... "
-
- # Run suspend hooks
- for hook in /etc/zzz.d/suspend/*; do
- [ -x "$hook" ] && "$hook"
- done
-
- # Sleep the system according to the selected mode
- case "$ZZZ_MODE" in
- standby) printf freeze >/sys/power/state || fail "standby failed";;
- suspend) printf mem >/sys/power/state || fail "suspend failed";;
- hibernate)
- echo $ZZZ_HIBERNATE_MODE >/sys/power/disk
- printf disk >/sys/power/state || fail "hibernate failed"
- ;;
- noop) sleep 5;;
- esac
-
- # Run resume hooks
- for hook in /etc/zzz.d/resume/*; do
- [ -x "$hook" ] && "$hook"
- done
-
- echo "yawn."
-) 9</sys/power