summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--Makefile10
-rw-r--r--batwarn_daemon.c85
-rwxr-xr-xold/batwarn.sh26
-rw-r--r--old/syscalls_per_iteration.txt126
5 files changed, 249 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..cbf6ab9
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+batwarn_daemon
+compile_commands.json
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..206a678
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,10 @@
+CC = gcc
+CFLAGS = -Wall -Wextra -std=c11 -O3 -fwrapv
+TARGET = batwarn_daemon
+
+.PHONY: all clean
+
+all: $(TARGET)
+
+clean:
+ rm -f $(TARGET)
diff --git a/batwarn_daemon.c b/batwarn_daemon.c
new file mode 100644
index 0000000..1cd1d17
--- /dev/null
+++ b/batwarn_daemon.c
@@ -0,0 +1,85 @@
+// For nanosleep(), pread()
+#define _POSIX_C_SOURCE 200809L
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+#include <time.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/wait.h>
+#include <assert.h>
+
+
+// Warning when battery percentage is <= this
+static const int WARN_PERC = 10;
+
+// Time to sleep between checks
+static const struct timespec SLEEP_SPEC = {60, 0};
+
+// Format string with percentage %d
+static const char *MESSAGE_FORMAT = "Battery at %d%%!";
+
+
+static inline void parse(const char *buffer, bool *discharging, int *charge, int *full) {
+ while (true) {
+ if (memcmp(buffer, "POWER_SUPPLY_STATUS", 19) == 0) {
+ *discharging = memcmp(buffer + 20, "Discharging", 11) == 0;
+ } else if (memcmp(buffer, "POWER_SUPPLY_CHARGE_NOW", 23) == 0) {
+ *charge = strtol(buffer + 24, NULL, 10);
+ } else if (memcmp(buffer, "POWER_SUPPLY_CHARGE_FULL_DESIGN", 31) == 0) {
+ *full = strtol(buffer + 32, NULL, 10);
+ }
+ buffer = strchr(buffer, '\n');
+ if (buffer != NULL) buffer++;
+ else break;
+ }
+}
+
+int main(void) {
+ int fd = open("/sys/class/power_supply/BAT1/uevent", O_RDONLY);
+ if (fd < 0) {
+ perror("open");
+ return 1;
+ }
+
+ char buffer[1024];
+
+ while (true) {
+ ssize_t nr = pread(fd, buffer, sizeof buffer, 0);
+ if (nr < 0) {
+ perror("pread");
+ break;
+ }
+
+ bool discharging = false;
+ int charge = 1, full = 1;
+ parse(buffer, &discharging, &charge, &full);
+
+ if (full > 0 && discharging && charge * 100 / full <= WARN_PERC) {
+ pid_t pid = fork();
+ if (pid < 0) perror("fork");
+ else if (pid == 0) {
+ char msg[strlen(MESSAGE_FORMAT) + 16];
+ snprintf(msg, sizeof msg, MESSAGE_FORMAT, charge * 100 / full);
+ char *argv[4] = {"i3-nagbar", "-m", msg, NULL};
+ execv("/usr/bin/i3-nagbar", argv);
+ perror("execv");
+ exit(255);
+ } else {
+ int status;
+ do if (waitpid(pid, &status, 0) < 0 && errno == ECHILD) break;
+ while (!WIFEXITED(status) && !WIFSIGNALED(status));
+ }
+ }
+
+ (void)nanosleep(&SLEEP_SPEC, NULL);
+ }
+
+ if (close(fd) < 0) {
+ perror("close");
+ return 1;
+ }
+}
diff --git a/old/batwarn.sh b/old/batwarn.sh
new file mode 100755
index 0000000..2556a70
--- /dev/null
+++ b/old/batwarn.sh
@@ -0,0 +1,26 @@
+#!/usr/bin/env bash
+function get_props_key() {
+ local v="$(grep "$1" <<<"$props")"
+ echo "${v/*=}"
+}
+
+function do_check() {
+ while read line; do
+ key="${line/=*}"
+ value="${line/*=}"
+ [[ $key = "POWER_SUPPLY_STATUS" ]] && status="$value"
+ [[ $key = "POWER_SUPPLY_CHARGE_NOW" ]] && charge="$value"
+ [[ $key = "POWER_SUPPLY_CHARGE_FULL_DESIGN" ]] && full="$value"
+ done </sys/class/power_supply/BAT1/uevent
+
+ percent="$(( charge * 100 / full ))"
+
+ if [[ $status = "Discharging" && $percent -le 30 ]]; then
+ i3-nagbar -m "Battery is at $percent%!"
+ fi
+}
+
+while true; do
+ do_check
+ sleep 30
+done
diff --git a/old/syscalls_per_iteration.txt b/old/syscalls_per_iteration.txt
new file mode 100644
index 0000000..12e0a33
--- /dev/null
+++ b/old/syscalls_per_iteration.txt
@@ -0,0 +1,126 @@
+[{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 5448
+rt_sigaction(SIGINT, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x7f5eea52b8e0}, {sa_handler=0x5625a3152150, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x7f5eea52b8e0}, 8) = 0
+rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
+--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=5448, si_uid=1000, si_status=0, si_utime=0, si_stime=0} ---
+wait4(-1, 0x7fffb461e7d0, WNOHANG, NULL) = -1 ECHILD (No child processes)
+rt_sigreturn({mask=[]}) = 0
+rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
+rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
+openat(AT_FDCWD, "/sys/class/power_supply/BAT1/uevent", O_RDONLY) = 3
+fcntl(0, F_GETFD) = 0
+fcntl(0, F_DUPFD, 10) = 10
+fcntl(0, F_GETFD) = 0
+fcntl(10, F_SETFD, FD_CLOEXEC) = 0
+dup2(3, 0) = 0
+close(3) = 0
+ioctl(0, TCGETS, 0x7fffb461e5c0) = -1 ENOTTY (Inappropriate ioctl for device)
+lseek(0, 0, SEEK_CUR) = 0
+read(0, "POWER_SUPPLY_NAME=BAT1\nPOWER_SUP"..., 128) = 128
+lseek(0, -105, SEEK_CUR) = 23
+rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
+rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
+ioctl(0, TCGETS, 0x7fffb461e5c0) = -1 ENOTTY (Inappropriate ioctl for device)
+lseek(0, 0, SEEK_CUR) = 23
+read(0, "POWER_SUPPLY_STATUS=Charging\nPOW"..., 128) = 128
+lseek(0, -99, SEEK_CUR) = 52
+rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
+rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
+ioctl(0, TCGETS, 0x7fffb461e5c0) = -1 ENOTTY (Inappropriate ioctl for device)
+lseek(0, 0, SEEK_CUR) = 52
+read(0, "POWER_SUPPLY_PRESENT=1\nPOWER_SUP"..., 128) = 128
+lseek(0, -105, SEEK_CUR) = 75
+rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
+rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
+ioctl(0, TCGETS, 0x7fffb461e5c0) = -1 ENOTTY (Inappropriate ioctl for device)
+lseek(0, 0, SEEK_CUR) = 75
+read(0, "POWER_SUPPLY_TECHNOLOGY=Li-ion\nP"..., 128) = 128
+lseek(0, -97, SEEK_CUR) = 106
+rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
+rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
+ioctl(0, TCGETS, 0x7fffb461e5c0) = -1 ENOTTY (Inappropriate ioctl for device)
+lseek(0, 0, SEEK_CUR) = 106
+read(0, "POWER_SUPPLY_CYCLE_COUNT=0\nPOWER"..., 128) = 128
+lseek(0, -101, SEEK_CUR) = 133
+rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
+rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
+ioctl(0, TCGETS, 0x7fffb461e5c0) = -1 ENOTTY (Inappropriate ioctl for device)
+lseek(0, 0, SEEK_CUR) = 133
+read(0, "POWER_SUPPLY_VOLTAGE_MIN_DESIGN="..., 128) = 128
+lseek(0, -87, SEEK_CUR) = 174
+rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
+rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
+ioctl(0, TCGETS, 0x7fffb461e5c0) = -1 ENOTTY (Inappropriate ioctl for device)
+lseek(0, 0, SEEK_CUR) = 174
+read(0, "POWER_SUPPLY_VOLTAGE_NOW=1575300"..., 128) = 128
+lseek(0, -94, SEEK_CUR) = 208
+rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
+rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
+ioctl(0, TCGETS, 0x7fffb461e5c0) = -1 ENOTTY (Inappropriate ioctl for device)
+lseek(0, 0, SEEK_CUR) = 208
+read(0, "POWER_SUPPLY_CURRENT_NOW=1541000"..., 128) = 128
+lseek(0, -95, SEEK_CUR) = 241
+rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
+rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
+ioctl(0, TCGETS, 0x7fffb461e5c0) = -1 ENOTTY (Inappropriate ioctl for device)
+lseek(0, 0, SEEK_CUR) = 241
+read(0, "POWER_SUPPLY_CHARGE_FULL_DESIGN="..., 128) = 128
+lseek(0, -88, SEEK_CUR) = 281
+rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
+rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
+ioctl(0, TCGETS, 0x7fffb461e5c0) = -1 ENOTTY (Inappropriate ioctl for device)
+lseek(0, 0, SEEK_CUR) = 281
+read(0, "POWER_SUPPLY_CHARGE_FULL=3107000"..., 128) = 128
+lseek(0, -95, SEEK_CUR) = 314
+rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
+rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
+ioctl(0, TCGETS, 0x7fffb461e5c0) = -1 ENOTTY (Inappropriate ioctl for device)
+lseek(0, 0, SEEK_CUR) = 314
+read(0, "POWER_SUPPLY_CHARGE_NOW=895000\nP"..., 128) = 128
+lseek(0, -97, SEEK_CUR) = 345
+rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
+rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
+ioctl(0, TCGETS, 0x7fffb461e5c0) = -1 ENOTTY (Inappropriate ioctl for device)
+lseek(0, 0, SEEK_CUR) = 345
+read(0, "POWER_SUPPLY_CAPACITY=28\nPOWER_S"..., 128) = 128
+lseek(0, -103, SEEK_CUR) = 370
+rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
+rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
+ioctl(0, TCGETS, 0x7fffb461e5c0) = -1 ENOTTY (Inappropriate ioctl for device)
+lseek(0, 0, SEEK_CUR) = 370
+read(0, "POWER_SUPPLY_CAPACITY_LEVEL=Norm"..., 128) = 128
+lseek(0, -93, SEEK_CUR) = 405
+rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
+rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
+ioctl(0, TCGETS, 0x7fffb461e5c0) = -1 ENOTTY (Inappropriate ioctl for device)
+lseek(0, 0, SEEK_CUR) = 405
+read(0, "POWER_SUPPLY_MODEL_NAME=PABAS024"..., 128) = 104
+lseek(0, -67, SEEK_CUR) = 442
+rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
+rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
+ioctl(0, TCGETS, 0x7fffb461e5c0) = -1 ENOTTY (Inappropriate ioctl for device)
+lseek(0, 0, SEEK_CUR) = 442
+read(0, "POWER_SUPPLY_MANUFACTURER=COMPAL"..., 128) = 67
+lseek(0, -33, SEEK_CUR) = 476
+rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
+rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
+ioctl(0, TCGETS, 0x7fffb461e5c0) = -1 ENOTTY (Inappropriate ioctl for device)
+lseek(0, 0, SEEK_CUR) = 476
+read(0, "POWER_SUPPLY_SERIAL_NUMBER=41167"..., 128) = 33
+rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
+rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
+ioctl(0, TCGETS, 0x7fffb461e5c0) = -1 ENOTTY (Inappropriate ioctl for device)
+lseek(0, 0, SEEK_CUR) = 509
+read(0, "", 128) = 0
+rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
+rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
+dup2(10, 0) = 0
+fcntl(10, F_GETFD) = 0x1 (flags FD_CLOEXEC)
+close(10) = 0
+rt_sigprocmask(SIG_BLOCK, [INT CHLD], [], 8) = 0
+clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f5eeaeede50) = 5450
+rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
+rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
+rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
+rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
+rt_sigaction(SIGINT, {sa_handler=0x5625a3152150, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x7f5eea52b8e0}, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x7f5eea52b8e0}, 8) = 0
+wait4(-1,