1#include <assert.h> 2#include <string.h> 3#include <stdlib.h> 4#include <unistd.h> 5#include <errno.h> 6#include <fcntl.h> 7#include <sys/socket.h> 8#include <sys/wait.h> 9 10int main(int ac, const char **av) 11{ 12 int i; 13 int data = 0; 14 struct iovec iov = { 15 .iov_base = &data, 16 .iov_len = sizeof(iov) 17 }; 18 19 while ((i = open("/dev/null", O_RDWR)) < 3) 20 assert(i >= 0); 21 (void) close(3); 22 23 int sv[2]; 24 assert(socketpair(AF_UNIX, SOCK_STREAM, 0, sv) == 0); 25 int one = 1; 26 assert(setsockopt(sv[0], SOL_SOCKET, SO_PASSCRED, &one, sizeof(one)) == 0); 27 28 pid_t pid = fork(); 29 assert(pid >= 0); 30 31 if (pid) { 32 assert(close(sv[0]) == 0); 33 assert(dup2(sv[1], 1) == 1); 34 assert(close(sv[1]) == 0); 35 36 int fds[ac]; 37 assert((fds[0] = open("/dev/null", O_RDWR)) == 3); 38 for (i = 1; i < ac; ++i) 39 assert((fds[i] = open(av[i], O_RDONLY)) == i + 3); 40 41 union { 42 struct cmsghdr cmsg; 43 char buf[CMSG_LEN(sizeof(fds))]; 44 } control; 45 46 control.cmsg.cmsg_level = SOL_SOCKET; 47 control.cmsg.cmsg_type = SCM_RIGHTS; 48 control.cmsg.cmsg_len = CMSG_LEN(sizeof(fds)); 49 memcpy(CMSG_DATA(&control.cmsg), fds, sizeof(fds)); 50 51 struct msghdr mh = { 52 .msg_iov = &iov, 53 .msg_iovlen = 1, 54 .msg_control = &control, 55 .msg_controllen = sizeof(control) 56 }; 57 58 assert(sendmsg(1, &mh, 0) == sizeof(iov)); 59 assert(close(1) == 0); 60 61 int status; 62 assert(waitpid(pid, &status, 0) == pid); 63 assert(status == 0); 64 } else { 65 assert(close(sv[1]) == 0); 66 assert(dup2(sv[0], 0) == 0); 67 assert(close(sv[0]) == 0); 68 69 struct cmsghdr control[4 + ac * sizeof(int) / sizeof(struct cmsghdr)]; 70 71 struct msghdr mh = { 72 .msg_iov = &iov, 73 .msg_iovlen = 1, 74 .msg_control = control, 75 .msg_controllen = sizeof(control) 76 }; 77 78 assert(recvmsg(0, &mh, 0) == sizeof(iov)); 79 assert(close(0) == 0); 80 } 81 82 return 0; 83} 84