unix/fiss

rewriting zzz in C (dd19f651ac849a43e18bf59f5da1a52403be224b)
Repositories | LICENSE

commit dd19f651ac849a43e18bf59f5da1a52403be224b
parent 942e2ffd85f204bd36b6a597ae00c604bf997764
Author: Friedel Schon <[email protected]>
Date:   Mon, 24 Apr 2023 12:20:30 +0200

rewriting zzz in C

Diffstat:
Asrc/exec/zzz.c102+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dsrc/script/zzz.sh81-------------------------------------------------------------------------------
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