From cefef69a4f1e348d5f10c0a1e415dbfc4fa98efe Mon Sep 17 00:00:00 2001 From: Gustav Behm Date: Fri, 29 Mar 2024 06:34:38 +0100 Subject: [PATCH] Trigger action --- c-impl/action.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 62 insertions(+), 3 deletions(-) diff --git a/c-impl/action.c b/c-impl/action.c index 06adbe3..1d002ea 100644 --- a/c-impl/action.c +++ b/c-impl/action.c @@ -1,12 +1,16 @@ #include #include #include +#include +#include #define LIBR_IMPLEMENTATION #include "r.h" +#define ACTION_MAX (NAME_MAX) + struct options { - const char* action; + char action[ACTION_MAX+1]; enum { NOOP = 0, @@ -45,7 +49,11 @@ static void parse_options(struct options* o, int argc, char* argv[]) } if(optind + 1 == argc) { - o->action = argv[optind]; + if(strnlen(argv[optind], ACTION_MAX) > ACTION_MAX) { + dprintf(2, "error: action too long\n"); + exit(2); + } + strncpy(o->action, argv[optind], ACTION_MAX); debug("action: %s", o->action); } else { if(optind >= argc) { @@ -126,6 +134,19 @@ static void signalfd_handle_event(struct state* st) } } +struct msg { + char action[ACTION_MAX]; + struct timespec timestamp; +}; + +const char* iso8601_timespec(const struct timespec* ts) +{ + static char buf[21]; + size_t r = strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%SZ", gmtime(&ts->tv_sec)); + if(r <= 0) abort(); + return buf; +} + int main(int argc, char* argv[]) { struct options o; @@ -133,11 +154,49 @@ int main(int argc, char* argv[]) struct xdg* xdg = xdg_new("action"); + char socket_path[PATH_MAX]; + xdg_resolve(xdg, XDG_RUNTIME, LIT(socket_path), o.action, NULL); + debug("socket path: %s", socket_path); + + struct sockaddr_un addr; + memset(&addr, 0, sizeof(addr)); + addr.sun_family = AF_UNIX; + if(strlen(socket_path) >= sizeof(addr.sun_path)) { + failwith("socket path too long"); + } + strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path) - 1); + if(o.cmd == PRINT_PATH) { - printf("%s/%s\n", xdg_runtime(xdg), o.action); + printf("%s\n", socket_path); goto exit; } + int fd = socket(AF_UNIX, SOCK_DGRAM, 0); + + if(o.cmd == TRIGGER) { + debug("triggering: %s", o.action); + + struct msg msg = {0}; + strncpy(msg.action, o.action, sizeof(msg.action)); + int r = clock_gettime(CLOCK_REALTIME, &msg.timestamp); + CHECK(r, "clock_gettime(CLOCK_REALTIME)"); + + ssize_t s = sendto(fd, + &msg, sizeof(msg), + 0, + (const struct sockaddr*)&addr, sizeof(addr)); + CHECK(s, "sendto(%s)", socket_path); + + if(s != sizeof(msg)) { + failwith("unexpected partial sendto"); + } + + info("triggered: %s (%s)", o.action, iso8601_timespec(&msg.timestamp)); + + r = close(fd); CHECK(r, "close"); + return 0; + } + struct state st = { .running = 1, }; -- 2.45.2