@@ 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);