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
+        );
 }