summaryrefslogtreecommitdiffstats
path: root/src/daemon.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/daemon.c')
-rw-r--r--src/daemon.c89
1 files changed, 76 insertions, 13 deletions
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 <errno.h>
#include <fcntl.h>
+#include <limits.h>
#include <pwd.h>
#include <signal.h>
#include <stdarg.h>
@@ -12,6 +13,7 @@
#include <stdlib.h>
#include <string.h>
#include <strings.h>
+#include <sys/inotify.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <sys/stat.h>
@@ -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;
}