--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/rust/chg/src/sendfds.c Mon Sep 24 16:14:35 2018 +0900
@@ -0,0 +1,51 @@
+/*
+ * Utility to send fds via Unix domain socket
+ *
+ * Copyright 2011, 2018 Yuya Nishihara <yuya@tcha.org>
+ *
+ * This software may be used and distributed according to the terms of the
+ * GNU General Public License version 2 or any later version.
+ */
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+
+#define MAX_FD_LEN 10
+
+/*
+ * Sends the given fds with 1-byte dummy payload.
+ *
+ * Returns the number of bytes sent on success, -1 on error and errno is set
+ * appropriately.
+ */
+ssize_t sendfds(int sockfd, const int *fds, size_t fdlen)
+{
+ char dummy[1] = {0};
+ struct iovec iov = {dummy, sizeof(dummy)};
+ char fdbuf[CMSG_SPACE(sizeof(fds[0]) * MAX_FD_LEN)];
+ struct msghdr msgh;
+ struct cmsghdr *cmsg;
+
+ /* just use a fixed-size buffer since we'll never send tons of fds */
+ if (fdlen > MAX_FD_LEN) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ memset(&msgh, 0, sizeof(msgh));
+ msgh.msg_iov = &iov;
+ msgh.msg_iovlen = 1;
+ msgh.msg_control = fdbuf;
+ msgh.msg_controllen = CMSG_SPACE(sizeof(fds[0]) * fdlen);
+
+ cmsg = CMSG_FIRSTHDR(&msgh);
+ cmsg->cmsg_level = SOL_SOCKET;
+ cmsg->cmsg_type = SCM_RIGHTS;
+ cmsg->cmsg_len = CMSG_LEN(sizeof(fds[0]) * fdlen);
+ memcpy(CMSG_DATA(cmsg), fds, sizeof(fds[0]) * fdlen);
+ msgh.msg_controllen = cmsg->cmsg_len;
+ return sendmsg(sockfd, &msgh, 0);
+}