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