#include <err.h>
#include <errno.h>
#include <poll.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#define SOCK_PATH "/tmp/kissbot"
int
read_print(int s) {
char buf[100];
ssize_t n;
while ((n = recv(s, buf, sizeof buf, 0)) > 0)
write(1, buf, n);
if (n < 0)
perror("recv");
return 0;
}
int
start_listening(void) {
struct sockaddr_un my_addr = {.sun_family = AF_UNIX};
int s = socket(AF_UNIX, SOCK_STREAM, 0);
if (s == -1)
err(1, "socket");
unlink(SOCK_PATH);
strlcpy(my_addr.sun_path, SOCK_PATH,
sizeof(my_addr.sun_path)-1);
if (bind(s, (struct sockaddr *)&my_addr,
sizeof(struct sockaddr_un)) == -1)
err(1, "bind");
if (listen(s, 10) == -1)
err(1, "listen");
return s;
}
int
accept_one(int s) {
struct sockaddr_un peer_addr;
socklen_t slen = sizeof(peer_addr);
return accept(s, (struct sockaddr *)&peer_addr, &slen);
}
int
main(void) {
struct pollfd fds[3]; /* UNIX socket, IRC socket, client on UNIX socket */
fds[0].fd = start_listening();
fds[0].events = POLLIN;
fds[1].fd = -1;
fds[2].fd = -1;
while (1) {
fds[0].revents = 0;
fds[1].revents = 0;
fds[2].revents = 0;
if (poll(fds, 3, -1) < 0) {
if (errno == EAGAIN)
continue;
err(1, "poll");
}
if ((fds[0].revents & POLLIN)
&& fds[2].fd != -1) {
int s_recv = accept_one(fds[0].fd);
if (s_recv != -1) {
fds[0].events = 0; /* don't want to accept any more currently */
fds[2].fd = s_recv;
fds[2].events = POLLIN;
}
}
if (fds[2].revents & POLLIN) {
read_print(fds[2].fd);
close(fds[2].fd);
fds[2].fd = -1;
fds[0].events = POLLIN;
}
if (fds[2].revents & POLLHUP) {
close(fds[2].fd);
fds[2].fd = -1;
fds[0].events = POLLIN;
}
}
close(fds[0].fd);
}