Compare commits

..

3 commits

Author SHA1 Message Date
0a88ca1b8c
check that paths exist before using them 2026-01-08 14:50:28 -05:00
1456db633d
remove unused macro 2026-01-07 16:07:07 -05:00
d4c1c34016
a :retab a day keeps the doctor away 2026-01-07 16:06:42 -05:00
4 changed files with 127 additions and 100 deletions

View file

@ -1,7 +1,5 @@
#pragma once #pragma once
#define LED_BLINK_TRIGGER_DISABLED 101
/** /**
* @brief parse the config file * @brief parse the config file
* *
@ -14,6 +12,11 @@ void parse_config_file(char *path);
*/ */
void setup_led_formula(void); void setup_led_formula(void);
/**
* @brief ensure that the config paths are valid
*/
void check_config();
extern char *battery_status_path; extern char *battery_status_path;
extern char *battery_power_source; extern char *battery_power_source;

View file

@ -3,33 +3,42 @@
#include <stdlib.h> #include <stdlib.h>
#include <log.h> #include <log.h>
#include <sys/stat.h>
#include <toml.h> #include <toml.h>
#include <tinyexpr.h> #include <tinyexpr.h>
#include "config.h" #include "config.h"
#define table(tt, v, vn) do { \ #define table(tt, v, vn) do { \
v = toml_table_in(tt, vn); \ v = toml_table_in(tt, vn); \
if (!v) { \ if (!v) { \
log_warn("missing [%s]", vn); \ log_warn("missing [%s]", vn); \
} \ } \
} while (0); } while (0)
#define set_str_conf(op, tt, v) do { \ #define set_str_conf(op, tt, v) do { \
toml_datum_t val; \ toml_datum_t val; \
val = toml_string_in(tt, v); \ val = toml_string_in(tt, v); \
if (val.ok) { \ if (val.ok) { \
op = val.u.s; \ op = val.u.s; \
} \ } \
} while (0); } while (0)
#define set_int_conf(op, tt, v) do { \ #define set_int_conf(op, tt, v) do { \
toml_datum_t val; \ toml_datum_t val; \
val = toml_int_in(tt, v); \ val = toml_int_in(tt, v); \
if (val.ok) { \ if (val.ok) { \
op = val.u.i; \ op = val.u.i; \
} \ } \
} while (0); } while (0)
#define check_path(path) do { \
struct stat sb; \
if (stat(path, &sb) == -1) { \
log_fatal("path does not exist: %s", path); \
exit(1); \
} \
} while (0)
static te_expr *expr; static te_expr *expr;
static double percentage; static double percentage;
@ -47,63 +56,74 @@ char *acpi_daemon_socket_path = "/run/acpid.socket";
double double
led_blink_timing_func(int percent) led_blink_timing_func(int percent)
{ {
percentage = percent; percentage = percent;
return te_eval(expr); return te_eval(expr);
} }
static void static void
free_eval(int sig) free_eval(int sig)
{ {
te_free(expr); te_free(expr);
} }
void void
setup_led_formula(void) setup_led_formula(void)
{ {
int err; int err;
te_variable vars[] = { { "p", &percentage } }; te_variable vars[] = { { "p", &percentage } };
expr = te_compile(led_blink_timing_formula, vars, 1, &err); expr = te_compile(led_blink_timing_formula, vars, 1, &err);
if (!expr) { if (!expr) {
log_fatal("%s", led_blink_timing_formula); log_fatal("%s", led_blink_timing_formula);
log_fatal("%*s^ Error near here", err - 1, ""); log_fatal("%*s^ Error near here", err - 1, "");
exit(1); exit(1);
} }
signal(SIGINT, free_eval); signal(SIGINT, free_eval);
} }
void void
parse_config_file(char *path) parse_config_file(char *path)
{ {
FILE *f; FILE *f;
toml_table_t *config, *battery, *led, *led_blink, *acpi_daemon; toml_table_t *config, *battery, *led, *led_blink, *acpi_daemon;
char errbuf[200]; char errbuf[200];
f = fopen(path, "r"); f = fopen(path, "r");
if (!f) { if (!f) {
log_fatal("Failed to open config file: %s", path); log_fatal("Failed to open config file: %s", path);
return; return;
} }
config = toml_parse_file(f, errbuf, sizeof(errbuf)); config = toml_parse_file(f, errbuf, sizeof(errbuf));
fclose(f); fclose(f);
if (!config) { if (!config) {
log_fatal("error: %s", errbuf); log_fatal("error: %s", errbuf);
} }
table(config, battery, "battery"); table(config, battery, "battery");
table(config, led, "led"); table(config, led, "led");
table(led, led_blink, "blink"); table(led, led_blink, "blink");
table(config, acpi_daemon, "acpi_daemon"); table(config, acpi_daemon, "acpi_daemon");
set_str_conf(battery_status_path, battery, "status_path"); set_str_conf(battery_status_path, battery, "status_path");
set_str_conf(battery_power_source, battery, "power_source"); set_str_conf(battery_power_source, battery, "power_source");
set_str_conf(led_brightness_path, led, "brightness_path"); set_str_conf(led_brightness_path, led, "brightness_path");
set_int_conf(led_blink_trigger_level, led_blink, "power_source"); set_int_conf(led_blink_trigger_level, led_blink, "power_source");
set_str_conf(led_blink_timing_formula, led_blink, "timing_formula"); set_str_conf(led_blink_timing_formula, led_blink, "timing_formula");
set_str_conf(acpi_daemon_socket_path, acpi_daemon, "socket_path"); set_str_conf(acpi_daemon_socket_path, acpi_daemon, "socket_path");
check_config();
toml_free(config); toml_free(config);
} }
void
check_config()
{
check_path(battery_status_path);
check_path(battery_power_source);
check_path(led_brightness_path);
check_path(acpi_daemon_socket_path);
}

View file

@ -86,7 +86,7 @@ int
main(int argc, char *argv[]) main(int argc, char *argv[])
{ {
cag_option_context context; cag_option_context context;
bool plugged = plugged_in(battery_power_source); bool plugged;
char buffer[MAX_BUFLEN], *out[4], *config_path, *percent; char buffer[MAX_BUFLEN], *out[4], *config_path, *percent;
int sock_fd; int sock_fd;
bool debug = false; bool debug = false;
@ -113,6 +113,10 @@ main(int argc, char *argv[])
break; break;
} }
} }
check_config();
/* get current plugged in state */
plugged = plugged_in(battery_power_source);
/* configure the led blinking formula */ /* configure the led blinking formula */
setup_led_formula(); setup_led_formula();

View file

@ -18,12 +18,12 @@
struct Data { struct Data {
int idle_lock; int idle_lock;
struct wl_compositor *compositor; struct wl_compositor *compositor;
struct wl_display *display; struct wl_display *display;
struct wl_registry *registry; struct wl_registry *registry;
struct wl_surface *surface; struct wl_surface *surface;
struct zwp_idle_inhibitor_v1 *inhibitor; struct zwp_idle_inhibitor_v1 *inhibitor;
struct zwp_idle_inhibit_manager_v1 *inhibitmanager; struct zwp_idle_inhibit_manager_v1 *inhibitmanager;
}; };
/* global data accessed by all threads */ /* global data accessed by all threads */
@ -38,12 +38,12 @@ static void
reghandler(void *data, struct wl_registry *registry, uint32_t id, reghandler(void *data, struct wl_registry *registry, uint32_t id,
const char *interface, uint32_t version) const char *interface, uint32_t version)
{ {
struct Data *d = (struct Data *)data; struct Data *d = (struct Data *)data;
if (strcmp(interface, wl_compositor_interface.name) == 0) { if (strcmp(interface, wl_compositor_interface.name) == 0) {
d->compositor = wl_registry_bind(registry, id, &wl_compositor_interface, 1); d->compositor = wl_registry_bind(registry, id, &wl_compositor_interface, 1);
} else if (strcmp(interface, zwp_idle_inhibit_manager_v1_interface.name) == 0) { } else if (strcmp(interface, zwp_idle_inhibit_manager_v1_interface.name) == 0) {
d->inhibitmanager = wl_registry_bind(registry, id, &zwp_idle_inhibit_manager_v1_interface, 1); d->inhibitmanager = wl_registry_bind(registry, id, &zwp_idle_inhibit_manager_v1_interface, 1);
} }
} }
static const struct wl_registry_listener reglistener = { static const struct wl_registry_listener reglistener = {
@ -59,13 +59,13 @@ static const struct wl_registry_listener reglistener = {
static inline void static inline void
idle_lock_set(int lock, struct Data *d) idle_lock_set(int lock, struct Data *d)
{ {
if (lock) { if (lock) {
d->inhibitor = zwp_idle_inhibit_manager_v1_create_inhibitor(d->inhibitmanager, d->surface); d->inhibitor = zwp_idle_inhibit_manager_v1_create_inhibitor(d->inhibitmanager, d->surface);
} else if (d->inhibitor) { } else if (d->inhibitor) {
zwp_idle_inhibitor_v1_destroy(d->inhibitor); zwp_idle_inhibitor_v1_destroy(d->inhibitor);
d->inhibitor = NULL; d->inhibitor = NULL;
} }
wl_display_roundtrip(d->display); wl_display_roundtrip(d->display);
} }
/** /**
@ -86,8 +86,8 @@ static void
log_fatal("pthread_cond_wait: %s", strerror(err)); log_fatal("pthread_cond_wait: %s", strerror(err));
pthread_exit(0); pthread_exit(0);
} else { } else {
break; break;
} }
} }
/* exit if we're told to */ /* exit if we're told to */
@ -99,7 +99,7 @@ static void
idle_lock_set(d->idle_lock, d); idle_lock_set(d->idle_lock, d);
} }
pthread_exit(0); pthread_exit(0);
} }
/** /**
@ -111,7 +111,7 @@ static void
static void static void
pre_exit(int signal) pre_exit(int signal)
{ {
idle_lock_set(false, data); idle_lock_set(false, data);
wayland_set_idle_lock(-1); wayland_set_idle_lock(-1);
pthread_cond_destroy(&cv); pthread_cond_destroy(&cv);
pthread_mutex_destroy(&mp); pthread_mutex_destroy(&mp);
@ -120,7 +120,7 @@ pre_exit(int signal)
wl_registry_destroy(data->registry); wl_registry_destroy(data->registry);
// wl_display_destroy(data->display); // wl_display_destroy(data->display);
wl_compositor_destroy(data->compositor); wl_compositor_destroy(data->compositor);
wl_surface_destroy(data->surface); wl_surface_destroy(data->surface);
/* make sure to cleanup the allocated data */ /* make sure to cleanup the allocated data */
free(data); free(data);
@ -142,39 +142,39 @@ wayland_create_thread(void)
/* setup data */ /* setup data */
data = calloc(1, sizeof(struct Data)); data = calloc(1, sizeof(struct Data));
/* connect to wayland */ /* connect to wayland */
data->display = wl_display_connect(NULL); data->display = wl_display_connect(NULL);
if (!data->display) { if (!data->display) {
log_fatal("failed to connect to wayland display"); log_fatal("failed to connect to wayland display");
return -1; return -1;
} }
data->registry = wl_display_get_registry(data->display); data->registry = wl_display_get_registry(data->display);
if (wl_registry_add_listener(data->registry, &reglistener, data) < 0) { if (wl_registry_add_listener(data->registry, &reglistener, data) < 0) {
log_fatal("failed to connect to the wayland registry"); log_fatal("failed to connect to the wayland registry");
return -1; return -1;
} }
/* roundtrip so that the registry listener collects all the data */ /* roundtrip so that the registry listener collects all the data */
wl_display_roundtrip(data->display); wl_display_roundtrip(data->display);
if (!data->compositor) { if (!data->compositor) {
log_fatal("wayland needs a compositor to run"); log_fatal("wayland needs a compositor to run");
return -1; return -1;
} }
if (!data->inhibitmanager) { if (!data->inhibitmanager) {
log_fatal("compositor doesn't support the idle inhibit protocol"); log_fatal("compositor doesn't support the idle inhibit protocol");
return -1; return -1;
} }
data->surface = wl_compositor_create_surface(data->compositor); data->surface = wl_compositor_create_surface(data->compositor);
if (!data->surface) { if (!data->surface) {
log_fatal("wayland couldn't create a surface"); log_fatal("wayland couldn't create a surface");
return -1; return -1;
} }
data->idle_lock = false; data->idle_lock = false;
data->inhibitor = NULL; data->inhibitor = NULL;
/* zero the array, and setup sig handler and exit handler */ /* zero the array, and setup sig handler and exit handler */
memset(&act, 0, sizeof(act)); memset(&act, 0, sizeof(act));
@ -222,7 +222,7 @@ wayland_set_idle_lock(int lock)
/* set the idle lock */ /* set the idle lock */
data->idle_lock = lock; data->idle_lock = lock;
log_debug("%s wayland idle lock", lock ? "enabled" : "disabled"); log_debug("%s wayland idle lock", lock ? "enabled" : "disabled");
pthread_cond_signal(&cv); pthread_cond_signal(&cv);
if (!locked) { if (!locked) {