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