~rootmos/action

a46a8824924c9264b876dbed3c6a8163f6ac1012 — Gustav Behm 5 months ago cefef69
Receive triggers
1 files changed, 52 insertions(+), 0 deletions(-)

M c-impl/action.c
M c-impl/action.c => c-impl/action.c +52 -0
@@ 1,8 1,12 @@
#define _GNU_SOURCE

#include <poll.h>
#include <signal.h>
#include <sys/signalfd.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/stat.h>
#include <string.h>

#define LIBR_IMPLEMENTATION
#include "r.h"


@@ 147,6 151,25 @@ const char* iso8601_timespec(const struct timespec* ts)
    return buf;
}

static void prepare_socket_path(const char* sp)
{
    struct stat st;
    int r = stat(sp, &st);
    if(r == 0) {
        if((st.st_mode & S_IFMT) == S_IFSOCK) {
            debug("socket already exists, trying to unlink: %s", sp);
            r = unlink(sp);
            CHECK(r, "unlink(%s)", sp);
        } else {
            failwith("socket path already exists (and is not a socket): %s", sp);
        }
    } else if(r == -1 && errno != ENOENT) {
        CHECK(r, "stat(%s)", sp);
    } else {
        xdg_makedirs(dirname(strdupa(sp)));
    }
}

int main(int argc, char* argv[])
{
    struct options o;


@@ 197,6 220,13 @@ int main(int argc, char* argv[])
        return 0;
    }

    prepare_socket_path(socket_path);

    int r = bind(fd, (const struct sockaddr*)&addr, sizeof(addr));
    CHECK(r, "bind(%s)", socket_path);

    set_blocking(fd, 0);

    struct state st = {
        .running = 1,
    };


@@ 205,6 235,7 @@ int main(int argc, char* argv[])

    struct pollfd fds[] = {
        { .fd = signalfd_fd(&st), .events = POLLIN },
        { .fd = fd, .events = POLLIN },
    };

    while(st.running) {


@@ 216,6 247,23 @@ int main(int argc, char* argv[])
            fds[0].revents &= ~POLLIN;
        }

        if(fds[1].revents & POLLIN) {
            struct msg msg;
            ssize_t s = recvfrom(fd, &msg, sizeof(msg), 0, NULL, NULL);
            CHECK(s, "recvfrom(%s)", socket_path);

            if(s != sizeof(msg)) {
                failwith("unexpected partial recvfrom");
            }

            if(strncmp(msg.action, o.action, sizeof(msg.action)) == 0) {
                info("triggered: %s (%s)", o.action, iso8601_timespec(&msg.timestamp));
                st.running = 0;
            }

            fds[1].revents &= ~POLLIN;
        }

        for(size_t i = 0; i < LENGTH(fds); i++) {
            if(fds[i].revents != 0) {
                failwith("unhandled poll events: "


@@ 228,6 276,10 @@ int main(int argc, char* argv[])
    debug("graceful shutdown");
    signalfd_deinit(&st);

    r = close(fd); CHECK(r, "close");
    r = unlink(socket_path);
    CHECK(r, "unlink(%s)", socket_path);

exit:
    xdg_free(xdg);