#include #include #include #include #include #include #include #include #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); }