xref: /dragonfly/test/debug/fdpassing.c (revision cd1c6085)
1 
2 /*
3  * cc -Wall fdpassing.c -o /tmp/fdp
4  */
5 #include <sys/types.h>
6 #include <sys/socket.h>
7 #include <sys/wait.h>
8 #include <sys/uio.h>
9 #include <sys/stat.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <unistd.h>
13 #include <string.h>
14 #include <fcntl.h>
15 #include <errno.h>
16 
17 void sendfd(int s, int fd);
18 int recvfd(int s);
19 
20 int
21 main(int ac, char **av)
22 {
23     struct stat st;
24     int fds[2];
25     int fd;
26     int i;
27     int dummy;
28 
29     if (socketpair(PF_LOCAL, SOCK_STREAM, 0, fds) < 0) {
30 	perror("socketpair");
31 	exit(1);
32     }
33     fcntl(fds[0], F_SETFL, 0);
34     fcntl(fds[1], F_SETFL, 0);
35     if (fork() == 0) {
36 	close(fds[1]);
37 	while ((fd = recvfd(fds[0])) >= 0) {
38 		fflush(stdout);
39 		usleep(1000000 / 10);
40 		if (fstat(fd, &st) < 0)
41 		    printf("B");
42 		else if (read(fd, &dummy, sizeof(dummy)) != sizeof(dummy))
43 		    printf("b");
44 		else
45 		    printf("r");
46 		close(fd);
47 		usleep(1000000 / 10);
48 	}
49 	printf("X\n");
50 	_exit(0);
51     }
52     close(fds[0]);
53 
54     for (;;) {
55 	for (i = 1; i < ac; ++i) {
56 	    if ((fd = open(av[i], O_RDONLY, 0666)) < 0) {
57 		fprintf(stderr, "unable to open %s\n", av[i]);
58 	    } else {
59 		sendfd(fds[1], fd);
60 		printf("w");
61 		fflush(stdout);
62 		close(fd);
63 	    }
64 	}
65 	usleep(1000000 / 5 - 10000);
66     }
67     printf("DONE\n");
68     close(fds[1]);
69     while (wait(NULL) < 0)
70 	;
71     return(0);
72 }
73 
74 void
75 sendfd(int s, int fd)
76 {
77     struct msghdr msg;
78     struct {
79 	struct cmsghdr cmsg;
80 	int fd;
81     } cmsg;
82     struct iovec iov;
83 
84     bzero(&msg, sizeof(msg));
85     bzero(&cmsg, sizeof(cmsg));
86 
87     iov.iov_base = NULL;
88     iov.iov_len = 0;
89 
90     msg.msg_iov = &iov;
91     msg.msg_iovlen = 1;
92     msg.msg_control = (caddr_t)&cmsg;
93     msg.msg_controllen = sizeof(cmsg);
94 
95     cmsg.cmsg.cmsg_level = SOL_SOCKET;
96     cmsg.cmsg.cmsg_type = SCM_RIGHTS;
97     cmsg.cmsg.cmsg_len = sizeof(cmsg);
98     cmsg.fd = fd;
99 
100     if (sendmsg(s, &msg, 0) < 0) {
101 	printf("sendfd: failed %s\n", strerror(errno));
102 	exit(1);
103     }
104 }
105 
106 int
107 recvfd(int s)
108 {
109     struct msghdr msg;
110     struct {
111 	struct cmsghdr cmsg;
112 	int fd;
113     } cmsg;
114     struct iovec iov;
115     int r;
116     int dummy;
117 
118     bzero(&msg, sizeof(msg));
119     bzero(&cmsg, sizeof(cmsg));
120 
121     iov.iov_base = &dummy;
122     iov.iov_len = sizeof(dummy);
123 
124     msg.msg_iov = &iov;
125     msg.msg_iovlen = 1;
126     msg.msg_control = (caddr_t)&cmsg;
127     msg.msg_controllen = sizeof(cmsg);
128 
129 #if 0
130     cmsg.cmsg.cmsg_level = SOL_SOCKET;
131     cmsg.cmsg.cmsg_type = SCM_RIGHTS;
132 #endif
133     cmsg.cmsg.cmsg_len = sizeof(cmsg);
134     cmsg.fd = -1;
135 
136     if ((r = recvmsg(s, &msg, MSG_EOR)) < 0) {
137 	printf("recvmsg: failed %s\n", strerror(errno));
138 	return(-1);
139     }
140     return(cmsg.fd);
141 }
142