From 0193f647eff03696308377d0847967b51ed0db47 Mon Sep 17 00:00:00 2001 From: coast Date: Fri, 27 Feb 2026 10:02:25 +0330 Subject: auto reload --- src/daemon.c | 89 +++++++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 76 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/daemon.c b/src/daemon.c index 293aeee..82154db 100644 --- a/src/daemon.c +++ b/src/daemon.c @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -12,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -51,6 +53,8 @@ static int bind_count = 0; static volatile sig_atomic_t g_quit = 0; +static char g_cfg[512]; + static void die(const char *fmt, ...) { va_list ap; va_start(ap, fmt); @@ -232,14 +236,13 @@ static int add_binding(char *msg) { strncpy(bindings[bind_count].cmd, cmd, MAX_CMD_LEN - 1); bindings[bind_count].cmd[MAX_CMD_LEN - 1] = '\0'; - int grabbed = grab_key(mod, kc); - if (grabbed == -1) + if (grab_key(mod, kc) == -1) warn("stored binding but grab failed for '%s+%s'", combo, keyname); bind_count++; xcb_flush(conn); fprintf(stderr, "piss: bound '%s+%s' → %s\n", combo, keyname, cmd); - return grabbed; + return 0; } static void spawn(const char *cmd) { @@ -358,6 +361,39 @@ static void ensure_executable(const char *path) { } } +static void reload_config(int inotify_fd, int *watch_wd) { + fprintf(stderr, "piss: config changed, reloading\n"); + + ungrab_all(); + bind_count = 0; + + if (*watch_wd >= 0) { + inotify_rm_watch(inotify_fd, *watch_wd); + *watch_wd = -1; + } + + ensure_executable(g_cfg); + + *watch_wd = + inotify_add_watch(inotify_fd, g_cfg, IN_CLOSE_WRITE | IN_MOVED_TO); + if (*watch_wd < 0) + warn("inotify_add_watch(%s): %s", g_cfg, strerror(errno)); + + spawn("notify-send -i input-keyboard 'piss' 'Config reloaded'"); + + pid_t pid = fork(); + if (pid < 0) { + warn("fork (reload): %s", strerror(errno)); + return; + } + if (pid == 0) { + char *args[] = {g_cfg, NULL}; + execvp(g_cfg, args); + fprintf(stderr, "piss: execvp(%s): %s\n", g_cfg, strerror(errno)); + _exit(1); + } +} + int main(int argc, char *argv[]) { if (argc >= 2 && strcmp(argv[1], "wait") == 0) @@ -450,14 +486,23 @@ int main(int argc, char *argv[]) { } } - char cfg[512]; if (argc > 1) { - strncpy(cfg, argv[1], sizeof(cfg) - 1); - cfg[sizeof(cfg) - 1] = '\0'; + strncpy(g_cfg, argv[1], sizeof(g_cfg) - 1); + g_cfg[sizeof(g_cfg) - 1] = '\0'; } else { - get_default_config(cfg, sizeof(cfg)); + get_default_config(g_cfg, sizeof(g_cfg)); } - ensure_executable(cfg); + ensure_executable(g_cfg); + + int inotify_fd = inotify_init1(IN_NONBLOCK | IN_CLOEXEC); + if (inotify_fd < 0) + die("inotify_init1: %s", strerror(errno)); + + int watch_wd = + inotify_add_watch(inotify_fd, g_cfg, IN_CLOSE_WRITE | IN_MOVED_TO); + if (watch_wd < 0) + warn("inotify_add_watch(%s): %s — live reload disabled", g_cfg, + strerror(errno)); xcb_flush(conn); @@ -466,9 +511,9 @@ int main(int argc, char *argv[]) { if (pid < 0) die("fork: %s", strerror(errno)); if (pid == 0) { - char *args[] = {cfg, NULL}; - execvp(cfg, args); - fprintf(stderr, "piss: execvp(%s): %s\n", cfg, strerror(errno)); + char *args[] = {g_cfg, NULL}; + execvp(g_cfg, args); + fprintf(stderr, "piss: execvp(%s): %s\n", g_cfg, strerror(errno)); _exit(1); } } @@ -483,7 +528,14 @@ int main(int argc, char *argv[]) { FD_ZERO(&rfds); FD_SET(xcb_fd, &rfds); FD_SET(serv, &rfds); - int maxfd = (xcb_fd > serv) ? xcb_fd : serv; + if (inotify_fd >= 0) + FD_SET(inotify_fd, &rfds); + + int maxfd = xcb_fd; + if (serv > maxfd) + maxfd = serv; + if (inotify_fd > maxfd) + maxfd = inotify_fd; int r = select(maxfd + 1, &rfds, NULL, NULL, NULL); if (r < 0) { @@ -493,6 +545,14 @@ int main(int argc, char *argv[]) { continue; } + if (inotify_fd >= 0 && FD_ISSET(inotify_fd, &rfds)) { + char ibuf[sizeof(struct inotify_event) + NAME_MAX + 1]; + ssize_t nr; + while ((nr = read(inotify_fd, ibuf, sizeof(ibuf))) > 0) + (void)nr; + reload_config(inotify_fd, &watch_wd); + } + if (FD_ISSET(serv, &rfds)) { int cli = accept(serv, NULL, NULL); if (cli < 0) { @@ -508,7 +568,8 @@ int main(int argc, char *argv[]) { buf[nr] = '\0'; int ok = add_binding(buf); const char *ack = (ok == 0) ? "ok\n" : "err\n"; - (void)write(cli, ack, strlen(ack)); + if (write(cli, ack, strlen(ack)) < 0) + warn("write(client): %s", strerror(errno)); } else if (nr < 0) { warn("read(client): %s", strerror(errno)); } @@ -567,6 +628,8 @@ int main(int argc, char *argv[]) { xcb_disconnect(conn); unlink(SOCK_PATH); close(serv); + if (inotify_fd >= 0) + close(inotify_fd); return 0; } -- cgit v1.3