#include #include #include #include #include #include #include #include void sendfd(int sockfd, int fd) { char dummybuf; struct iovec iov; struct msghdr mh; struct cmsghdr *cmp = malloc(CMSG_LEN(sizeof(int))); if (cmp == NULL) { fprintf(stderr, "can't malloc: %s\n", strerror(errno)); exit(1); } iov.iov_base = &dummybuf; iov.iov_len = 1; mh.msg_iov = &iov; mh.msg_iovlen = 1; mh.msg_name = NULL; mh.msg_namelen = 0; mh.msg_control = cmp; mh.msg_controllen = CMSG_LEN(sizeof(int)); cmp->cmsg_level = SOL_SOCKET; cmp->cmsg_type = SCM_RIGHTS; cmp->cmsg_len = CMSG_LEN(sizeof(int)); *(int *)CMSG_DATA(cmp) = fd; if (sendmsg(sockfd, &mh, 0) < 0) { fprintf(stderr, "sendmsg failed: %s\n", strerror(errno)); exit(1); } free(cmp); } int recvfd(int sockfd) { struct msghdr mh; int nfd; char dummybuf; struct iovec iov; long csz = CMSG_LEN(sizeof(int)); struct cmsghdr *cmp = malloc(csz); if (cmp == NULL) { fprintf(stderr, "can't malloc: %s\n", strerror(errno)); exit(1); } iov.iov_base = &dummybuf; iov.iov_len = 1; mh.msg_iov = &iov; mh.msg_iovlen = 1; mh.msg_name = NULL; mh.msg_namelen = 0; mh.msg_control = cmp; mh.msg_controllen = csz; if (recvmsg(sockfd, &mh, 0) < 0) { fprintf(stderr, "recvmsg failed: %s\n", strerror(errno)); exit(1); } if (mh.msg_controllen == 0) { fprintf(stderr, "no control data in message\n"); exit(1); } if (mh.msg_controllen != csz) fprintf(stderr, "WARNING: controllen %ld, should be %ld\n", mh.msg_controllen, csz); nfd = *(int *)CMSG_DATA(cmp); free(cmp); return(nfd); } int main() { int nfd, nfd2; int fd[2]; struct stat sbuf[2]; printf("sizeof(int) = %d\n", (int)sizeof(int)); printf("sizeof(long) = %d\n", (int)sizeof(long)); printf("sizeof(size_t) = %d\n", (int)sizeof(size_t)); printf("CMSG_LEN(sizeof(int)) = %d\n", (int)CMSG_LEN(sizeof(int))); printf("CMSG_SPACE(sizeof(int)) = %d\n", (int)CMSG_SPACE(sizeof(int))); if (socketpair(AF_UNIX, SOCK_STREAM, 0, fd) < 0) { fprintf(stderr, "can't create socket pair: %s\n", strerror(errno)); exit(1); } if ((nfd = open("/etc/services", O_RDONLY)) < 0) { fprintf(stderr, "can't open /etc/services: %s", strerror(errno)); exit(1); } sendfd(fd[0], nfd); nfd2 = recvfd(fd[1]); if (fstat(nfd, &sbuf[0]) < 0 || fstat(nfd2, &sbuf[1]) < 0) { fprintf(stderr, "fstat failed: %s\n", strerror(errno)); exit(1); } if (sbuf[0].st_dev == sbuf[1].st_dev && sbuf[0].st_ino == sbuf[1].st_ino) printf("the files are the same\n"); else printf("the files are different\n"); exit(0); }