#include #include #include #include #include #include void fatal(char *s) { perror(s); exit(1); } int main(){ int n, fd, pair[2]; char fdbuf[CMSG_SPACE(sizeof(int))]; struct cmsghdr *cmsg; struct msghdr msg; char buf[1024]; /* dummy */ struct iovec vec; char ch = '\0'; memset(&msg, 0, sizeof(msg)); /* having zero msg_iovlen or iov_len doesnt seem to work */ vec.iov_base = &ch; vec.iov_len = 1; msg.msg_iov = &vec; msg.msg_iovlen = 1; msg.msg_control = fdbuf; msg.msg_controllen = CMSG_LEN(sizeof(int)); cmsg = CMSG_FIRSTHDR(&msg); cmsg->cmsg_len = CMSG_LEN(sizeof(int)); if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair)) fatal("socketpair"); switch (fork()) { case -1: fatal("fork"); case 0: fd = open("/etc/passwd", O_RDONLY); if (fd < 0) { perror("/etc/passwd"); exit(1); } printf("child: sending fd=%d for /etc/passwd\n", fd); cmsg->cmsg_level = SOL_SOCKET; cmsg->cmsg_type = SCM_RIGHTS; *(int *)CMSG_DATA(cmsg) = fd; if (sendmsg(pair[0], &msg, 0) < 0) fatal("sendmsg"); exit(0); default: fd = open("/etc/motd", O_RDONLY); printf("parent: got fd=%d for /etc/motd\n", fd); if (recvmsg(pair[1], &msg, 0) < 0) fatal("recvmsg"); if (cmsg->cmsg_type != SCM_RIGHTS) fatal("didnt get a fd?\n"); fd = *(int *)CMSG_DATA(cmsg); printf("parent: received fd=%d\n", fd); n = read(fd, buf, sizeof(buf)); if (n < 0) perror("read"); printf("read %d bytes\n\n", n); fflush(stdout); write(1,buf,n); } return 0; }