#include #include #include #include #include #include #include #include #include #include #define LAM_ZERO_ME(a) memset(&(a),0,sizeof((a))); int sfh_send_fd(int,int); int sfh_recv_fd(int); /* * Global so that we can kill the child if the parent barfs */ pid_t child_pid = 0; int main(int argc, char *argv[]) { int fd[2]; int status = 0; int recieved = -1; if (socketpair(AF_UNIX, SOCK_STREAM, 0, fd)) {/*socketpair failed*/ perror("pipe"); exit(1); } if ((child_pid = fork()) < 0) { /*fork failed */ perror("fork"); } else if (child_pid > 0) { /* PARENT */ if( sfh_send_fd(fd[0],0) ) {/* sfh_send_fd failed*/ kill(child_pid, 9); /* kill the child */ waitpid(child_pid, &status, 0); return (2); } waitpid(child_pid, &status, 0); /*send has worked, now wait for recv */ } else { /* CHILD */ recieved = sfh_recv_fd(fd[1]); if ( recieved == -1) { /* recieve failed */ exit(3); } } return status; } int sfh_send_fd(int stream, int fd) { struct iovec iov[1]; struct msghdr msg; char buf[1]; int r; /* * Pass one char and access rights. */ buf[0] = 0; iov[0].iov_base = buf; iov[0].iov_len = 1; LAM_ZERO_ME(msg); msg.msg_iov = iov; msg.msg_iovlen = 1; msg.msg_name = (caddr_t) 0; msg.msg_namelen = 0; msg.msg_accrights = (caddr_t) &fd; msg.msg_accrightslen = sizeof(int); do { r = sendmsg(stream, &msg, 0); if (r == 1) break; else if (r < 0 && errno == EINTR) continue; else { return(-1); } } while (1); /* Receive a handshake back indicating that the fd has been received properly. This slows things down a bit, but it seems that some OS's allow buffered sending down streams and when the sender closes, it ditches the buffered sends (SCO). So this extra sync here will prevent this. */ do { r = read(stream, buf, 1); if (r == 1) break; else if (r < 0 && errno == EINTR) continue; else { return(-1); } } while (1); return(0); } int sfh_recv_fd(int stream) { int newfd = -1; struct msghdr msg; struct iovec iov[1]; char buf[1]; int r; /* * Receive one char and access rights. */ iov[0].iov_base = buf; iov[0].iov_len = 1; LAM_ZERO_ME(msg); msg.msg_iov = iov; msg.msg_iovlen = 1; msg.msg_name = (caddr_t) 0; msg.msg_namelen = 0; msg.msg_accrights = (caddr_t) &newfd; msg.msg_accrightslen = sizeof(int); do { r = recvmsg(stream, &msg, 0); if (r == 1) break; else if (r < 0 && errno == EINTR) continue; else return(-1); } while (1); if (msg.msg_accrightslen != sizeof(int)) return(-1); /* Send a handshake back indicating that the fd has been received properly. This slows things down a bit, but it seems that some OS's allow buffered sending down streams and when the sender closes, it ditches the buffered sends (SCO). So this extra sync here will prevent this. */ do { r = write(stream, buf, 1); if (r == 1) break; else if (r < 0 && errno == EINTR) continue; else { return(-1); } } while (1); return(newfd); }