diff --git a/12-postbox/domain.c b/12-postbox/domain.c
index 8db3cda..e5d0207 100644
--- a/12-postbox/domain.c
+++ b/12-postbox/domain.c
@@ -1,12 +1,55 @@
int domain_prepare(int epoll_fd) {
printf("... by socket: echo 2 | nc -U socket\n");
- return -1;
+ int sock_fd = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (sock_fd < 0) die("socket");
+
+ char *sock_name = "socket";
+ struct sockaddr_un server_sockaddr;
+ server_sockaddr.sun_family = AF_UNIX;
+ strcpy(server_sockaddr.sun_path, sock_name);
+
+ int rc = unlink(sock_name);
+ if (rc < 0 && errno != ENOENT) die("unlink/socket");
+
+ rc = bind(sock_fd, (struct sockaddr *) &server_sockaddr, sizeof(server_sockaddr));
+ if (rc == -1) die("bind/socket");
+
+ rc = listen(sock_fd, 10);
+ if (rc < 0) die("listen/socket");
+
+ epoll_add(epoll_fd, sock_fd, EPOLLIN);
+
+ return sock_fd;
}
void domain_accept(int epoll_fd, int sock_fd, int events) {
+ int client_fd = accept(sock_fd, NULL, NULL);
+ epoll_add(epoll_fd, client_fd, EPOLLIN);
}
void domain_recv(int epoll_fd, int sock_fd, int events) {
+ static char buf[128];
+ if (events & EPOLLIN) {
+ int len = recv(sock_fd, buf, sizeof(buf), 0);
+ if (len < 0) die("recvfrom");
+
+ while (len > 0 && buf[len-1] == '\n') len --;
+ buf[len] = 0;
+
+ struct ucred ucred;
+ {
+ socklen_t len = sizeof(struct ucred);
+ int rc = getsockopt(sock_fd, SOL_SOCKET, SO_PEERCRED, &ucred, &len);
+ if (rc < 0) die("getsockopt");
+ }
+
+ printf("socket[pid=%d,uid=%d,gid=%d]: %s\n", ucred.pid, ucred.uid, ucred.gid, buf);
+ epoll_del(epoll_fd, sock_fd);
+ close(sock_fd);
+ } else if (events & EPOLLHUP) {
+ epoll_del(epoll_fd, sock_fd);
+ close(sock_fd);
+ }
}
diff --git a/12-postbox/fifo.c b/12-postbox/fifo.c
index 3947a76..27bb1a9 100644
--- a/12-postbox/fifo.c
+++ b/12-postbox/fifo.c
@@ -1,8 +1,39 @@
+static int open_fifo() {
+ int fd = open("fifo", O_RDONLY|O_NONBLOCK);
+ if (fd < 0) die("open/fifo");
+ return fd;
+}
int fifo_prepare(int epoll_fd) {
printf("... by fifo: echo 1 > fifo\n");
- return -1;
+ int rc = unlink("fifo");
+ if (rc < 0 && errno != ENOENT) die("unlink/fifo");
+ rc = mknod("fifo", 0666 | S_IFIFO, 0);
+ if (rc < 0) die("mknod/fifo");
+
+ int fifo_fd = open_fifo();
+ epoll_add(epoll_fd, fifo_fd, EPOLLIN);
+
+ return fifo_fd;
}
void fifo_handle(int epoll_fd, int fifo_fd, int events) {
+ static char buf[128];
+
+ if (events & EPOLLIN) {
+ int len = read(fifo_fd, buf, sizeof(buf));
+ if (len < 0) die("read/fifo");
+ if (len == 0)
+ goto close;
+ while (len > 1 && buf[len-1] == '\n') len --;
+ buf[len] = 0;
+ printf("fifo: %s\n", buf);
+ } else if (events & EPOLLHUP) {
+ close:
+ epoll_del(epoll_fd, fifo_fd);
+ close(fifo_fd);
+
+ fifo_fd = open_fifo();
+ epoll_add(epoll_fd, fifo_fd, EPOLLIN);
+ }
}