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(void)
11{
12	union {
13		struct cmsghdr cmsghdr;
14		char buf[CMSG_SPACE(sizeof(int))];
15	} control = {};
16
17	int fd;
18	int data = 0;
19	struct iovec iov = {
20		.iov_base = &data,
21		.iov_len = sizeof(iov)
22	};
23
24	struct msghdr mh = {
25		.msg_iov = &iov,
26		.msg_iovlen = 1,
27		.msg_control = &control,
28		.msg_controllen = sizeof(control)
29	};
30
31	while ((fd = open("/dev/null", O_RDWR)) < 3)
32		assert(fd >= 0);
33	(void) close(3);
34
35	int sv[2];
36	assert(socketpair(AF_UNIX, SOCK_STREAM, 0, sv) == 0);
37
38	pid_t pid = fork();
39	assert(pid >= 0);
40
41	if (pid) {
42		assert(close(sv[0]) == 0);
43		assert(dup2(sv[1], 1) == 1);
44		assert(close(sv[1]) == 0);
45
46		assert((fd = open("/dev/null", O_RDWR)) == 3);
47
48		struct cmsghdr *cmsg = CMSG_FIRSTHDR(&mh);
49		cmsg->cmsg_level = SOL_SOCKET;
50		cmsg->cmsg_type = SCM_RIGHTS;
51		cmsg->cmsg_len = CMSG_LEN(sizeof fd);
52		memcpy(CMSG_DATA(cmsg), &fd, sizeof fd);
53		mh.msg_controllen = cmsg->cmsg_len;
54
55		assert(sendmsg(1, &mh, 0) == sizeof(iov));
56		assert(close(1) == 0);
57
58                int status;
59		assert(waitpid(pid, &status, 0) == pid);
60		assert(status == 0);
61	} else {
62		assert(close(sv[1]) == 0);
63		assert(dup2(sv[0], 0) == 0);
64		assert(close(sv[0]) == 0);
65
66		assert(recvmsg(0, &mh, 0) == sizeof(iov));
67		assert(close(0) == 0);
68	}
69
70	return 0;
71}
72