#include #include #include #include #include #include #include "common.h" #define FIFO_MODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH) /* Receive a file descriptor from another process (a server). * In addition, any data received from the server is passed * to (*userfunc)(STDERR_FILENO, buf, nbytes). We have a * 2-byte protocol for receiving the fd from send_fd(). */ int my_recv_fd(int servfd) { int newfd, nread, flag, status; char *ptr, buf[MAXLINE]; struct strbuf dat; struct strrecvfd recvfd; status = -1; dat.buf = buf; dat.maxlen = MAXLINE; flag = 0; if (getmsg(servfd, NULL, &dat, &flag) < 0) { fprintf(stderr,"getmsg error\n"); return(-1); } nread = dat.len; if (nread == 0) { fprintf(stderr,"connection closed by server"); return(-1); } /* See if this is the final data with null & status. Null must be next to last byte of buffer, status byte is last byte. Zero status means there must be a file descriptor to receive. */ for (ptr = buf; ptr < &buf[nread]; ) { if (*ptr++ == 0) { if (ptr != &buf[nread-1]) { fprintf(stderr,"message format error"); return(-1); } status = *ptr & 255; if (status == 0) { if (ioctl(servfd, I_RECVFD, &recvfd) < 0) return(-1); newfd = recvfd.fd; /* new descriptor */ } else newfd = -status; nread -= 2; } } if (nread > 0) if (write(STDERR_FILENO, buf, nread) != nread) return(-1); if (status >= 0) return(newfd); /* final data has arrived - descriptor, or -status */ } /* Pass a file descriptor to another process. * If fd<0, then -fd is sent back instead as the error status. */ int my_send_fd(int clifd, int fd) { char buf[2]; /* send_fd()/recv_fd() 2-byte protocol */ buf[0] = 0; /* null byte flag to recv_fd() */ if (fd < 0) { buf[1] = -fd; /* nonzero status means error */ if (buf[1] == 0) buf[1] = 1; /* -256, etc. would screw up protocol */ } else { buf[1] = 0; /* zero status means OK */ } if (write(clifd, buf, 2) != 2) return(-1); if (fd >= 0) if (ioctl(clifd, I_SENDFD, fd) < 0) return(-1); return(0); } /* Create a client endpoint and connect to a server. * returns fd if all OK, <0 on error */ int cli_conn(const char *name) { int fd; if ( (fd = open(name, O_RDWR)) < 0) return(-1); /* open the mounted stream */ if (isastream(fd) == 0) return(-2); return(fd); } /* Wait for a client connection to arrive, and accept it. * We also obtain the client's user ID. * returns new fd if all OK, -1 on error */ int my_serv_accept(int listenfd) { struct strrecvfd recvfd; if (ioctl(listenfd, I_RECVFD, &recvfd) < 0) return(-1); /* could be EINTR if signal caught */ return(recvfd.fd); /* return the new descriptor */ } int bind_to_fs(int fd,const char *name) { int tempfd; if ( (tempfd = creat(name, FIFO_MODE)) < 0) return 0; if (close(tempfd) < 0) return 0; if (ioctl(fd, I_PUSH, "connld") < 0) return 0; if (fattach(fd, name) < 0) return 0; return 1; } int my_isastream(int fd) { return isastream(fd); } int my_getfl(int fd) { return fcntl(fd,F_GETFL); }