diff --git a/13-postbox/domain.c b/13-postbox/domain.c
index 8db3cda..e5d0207 100644
--- a/13-postbox/domain.c
+++ b/13-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/13-postbox/fifo.c b/13-postbox/fifo.c
index 3947a76..27bb1a9 100644
--- a/13-postbox/fifo.c
+++ b/13-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);
+ }
}
diff --git a/13-postbox/mqueue.c b/13-postbox/mqueue.c
index 03d7c46..808bbe0 100644
--- a/13-postbox/mqueue.c
+++ b/13-postbox/mqueue.c
@@ -1,8 +1,25 @@
int mqueue_prepare(int epoll_fd) {
printf("... by mq_send: ./mq_send 4 (see also `cat /dev/mqueue/postbox`)\n");
- return -1;
+ struct mq_attr attr;
+ attr.mq_maxmsg = 10;
+ attr.mq_msgsize = 128;
+ int msg_fd = mq_open("/postbox", O_RDONLY | O_CREAT, 0666, &attr);
+ if (msg_fd < 0) die("mq_open");
+
+ epoll_add(epoll_fd, msg_fd, EPOLLIN);
+
+ return msg_fd;
}
void mqueue_handle(int epoll_fd, int msg_fd, int events) {
+ unsigned int prio;
+ static char buf[128];
+ int len = mq_receive(msg_fd, buf, sizeof(buf), &prio);
+ if (len < 0) die("mq_receive");
+
+ while (len > 0 && buf[len-1] == '\n') len --;
+ buf[len] = 0;
+
+ printf("mqueue[prio=%d]: %s\n", prio, buf);
}
diff --git a/13-postbox/signalfd.c b/13-postbox/signalfd.c
index d33f9d7..0547f26 100644
--- a/13-postbox/signalfd.c
+++ b/13-postbox/signalfd.c
@@ -1,7 +1,34 @@
int signalfd_prepare(int epoll_fd) {
printf("... by signal: /bin/kill -USR1 -q 3 %d \n", getpid());
- return -1;
+ sigset_t mask;
+ sigemptyset(&mask);
+ sigaddset(&mask, SIGUSR1);
+ sigaddset(&mask, SIGUSR2);
+
+ int signal_fd = signalfd(-1, &mask, 0);
+ if (signal_fd < 0) die("signal_fd");
+
+ if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1)
+ die("sigprocmask");
+
+ epoll_add(epoll_fd, signal_fd, EPOLLIN);
+
+ return signal_fd;
}
void signalfd_handle(int epoll_fd, int signal_fd, int events) {
+ struct signalfd_siginfo info;
+ if (events & EPOLLIN) {
+ int len = read(signal_fd, &info, sizeof(info));
+ if (len != sizeof(info )) die("read");
+ } else {
+ die("invalid singal on signal_fd");
+ }
+
+ printf("signalfd[uid=%d,pid=%d] signal=%d, data=%x\n",
+ info.ssi_pid,
+ info.ssi_uid,
+ info.ssi_signo,
+ info.ssi_int
+ );
}