@@ 76,9 76,65 @@ static void parse_options(struct options* o, int argc, char* argv[])
}
}
+struct msg {
+ char action[ACTION_MAX];
+ struct timespec timestamp;
+};
+
+static 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;
+}
+
+static void prepare_sockaddr(struct sockaddr_un* addr, const char* socket_path)
+{
+ 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);
+}
+
+static int cmd_trigger(const struct options* o, const char* socket_path)
+{
+ debug("triggering: %s", o->action);
+
+ int fd = socket(AF_UNIX, SOCK_DGRAM, 0);
+
+ struct sockaddr_un addr;
+ prepare_sockaddr(&addr, socket_path);
+
+ 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 {
int running;
-
+ int exit_code;
int sfd;
};
@@ 100,11 156,6 @@ static int signalfd_init(struct state* st)
return fd;
}
-static int signalfd_fd(const struct state* st)
-{
- return st->sfd;
-}
-
static void signalfd_deinit(struct state* st)
{
int r = close(st->sfd); CHECK(r, "close");
@@ 129,96 180,43 @@ static void signalfd_handle_event(struct state* st)
if(si.ssi_signo == SIGINT) {
debug("SIGINT");
st->running = 0;
+ st->exit_code = 1;
} else if(si.ssi_signo == SIGTERM) {
debug("SIGTERM");
st->running = 0;
+ st->exit_code = 1;
} else {
warning("unhandled signal: %u", si.ssi_signo);
}
}
}
-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;
-}
-
-static void prepare_socket_path(const char* sp)
+static void prepare_socket_path(const char* socket_path)
{
struct stat st;
- int r = stat(sp, &st);
+ int r = stat(socket_path, &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);
+ debug("socket already exists, trying to unlink: %s", socket_path);
+ r = unlink(socket_path);
+ CHECK(r, "unlink(%s)", socket_path);
} else {
- failwith("socket path already exists (and is not a socket): %s", sp);
+ failwith("socket path already exists (and is not a socket): %s", socket_path);
}
} else if(r == -1 && errno != ENOENT) {
- CHECK(r, "stat(%s)", sp);
+ CHECK(r, "stat(%s)", socket_path);
} else {
- xdg_makedirs(dirname(strdupa(sp)));
+ xdg_makedirs(dirname(strdupa(socket_path)));
}
}
-int main(int argc, char* argv[])
+static int cmd_bind(const struct options* o, const char* socket_path)
{
- struct options o;
- parse_options(&o, argc, 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\n", socket_path);
- goto exit;
- }
-
int fd = socket(AF_UNIX, SOCK_DGRAM, 0);
+ CHECK(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 sockaddr_un addr;
+ prepare_sockaddr(&addr, socket_path);
prepare_socket_path(socket_path);
@@ 229,12 227,11 @@ int main(int argc, char* argv[])
struct state st = {
.running = 1,
+ .exit_code = 255,
};
- signalfd_init(&st);
-
struct pollfd fds[] = {
- { .fd = signalfd_fd(&st), .events = POLLIN },
+ { .fd = signalfd_init(&st), .events = POLLIN },
{ .fd = fd, .events = POLLIN },
};
@@ 256,9 253,10 @@ int main(int argc, char* argv[])
failwith("unexpected partial recvfrom");
}
- if(strncmp(msg.action, o.action, sizeof(msg.action)) == 0) {
- info("triggered: %s (%s)", o.action, iso8601_timespec(&msg.timestamp));
+ if(strncmp(msg.action, o->action, sizeof(msg.action)) == 0) {
+ info("triggered: %s (%s)", o->action, iso8601_timespec(&msg.timestamp));
st.running = 0;
+ st.exit_code = 0;
}
fds[1].revents &= ~POLLIN;
@@ 280,8 278,36 @@ int main(int argc, char* argv[])
r = unlink(socket_path);
CHECK(r, "unlink(%s)", socket_path);
-exit:
+ return st.exit_code;
+}
+
+int main(int argc, char* argv[])
+{
+ struct options o;
+ parse_options(&o, argc, 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);
+
+ int ec = 255;
+
+ if(o.cmd == PRINT_PATH) {
+ // ensure the path is a valid socket address
+ struct sockaddr_un addr;
+ prepare_sockaddr(&addr, socket_path);
+
+ printf("%s\n", socket_path);
+ ec = 0;
+ } else if(o.cmd == TRIGGER) {
+ ec = cmd_trigger(&o, socket_path);
+ } else if(o.cmd == BIND) {
+ ec = cmd_bind(&o, socket_path);
+ }
+
xdg_free(xdg);
- return 0;
+ return ec;
}