+char *randhex(void) {
+ char *ret = malloc(33);
+ if (!ret)
+ errx(1, "unable to malloc");
+ int fd = open("/dev/urandom", O_RDONLY);
+ if (fd == -1)
+ err(1, "unable to open urandom");
+ if (read(fd, ret, 32) != 32)
+ errx(1, "read from urandom failed");
+ close(fd);
+ for (int i=0; i<32; i++) {
+ ret[i] = (ret[i] & 0xf) + 'A';
+ }
+ ret[32] = 0;
+ return ret;
+}
+
+int recvfd(int sock) {
+ int len = sizeof(struct cmsghdr) + sizeof(int);
+ struct cmsghdr *hdr = alloca(len);
+ char ch = '\0';
+ struct iovec vec = {
+ .iov_base = &ch,
+ .iov_len = 1
+ };
+ struct msghdr msg = {
+ .msg_control = hdr,
+ .msg_controllen = len,
+ .msg_iov = &vec,
+ .msg_iovlen = 1
+ };
+ if (recvmsg(sock, &msg, 0) < 0)
+ err(1, "unable to receive fd");
+ if (hdr->cmsg_len != len || hdr->cmsg_level != SOL_SOCKET || hdr->cmsg_type != SCM_RIGHTS)
+ errx(1, "got bad message");
+ return *(int*)CMSG_DATA(hdr);
+}
+
+void sendfd(int sock, int fd) {
+ int len = sizeof(struct cmsghdr) + sizeof(int);
+ struct cmsghdr *hdr = alloca(len);
+ *hdr = (struct cmsghdr) {
+ .cmsg_len = len,
+ .cmsg_level = SOL_SOCKET,
+ .cmsg_type = SCM_RIGHTS
+ };
+ *(int*)CMSG_DATA(hdr) = fd;
+ char ch = '\0';
+ struct iovec vec = {
+ .iov_base = &ch,
+ .iov_len = 1
+ };
+ struct msghdr msg = {
+ .msg_control = hdr,
+ .msg_controllen = len,
+ .msg_iov = &vec,
+ .msg_iovlen = 1
+ };
+ if (sendmsg(sock, &msg, 0) < 0)
+ err(1, "unable to send fd");
+}
+