#include #include #include #include #include #include #include #include #include #define FIFO_IN "/tmp/pipe.in" #define FIFO_OUT "/tmp/pipe.out" #define FALSE 0 #define TRUE 1 typedef int bool; void openpipes(void); void closepipes(void); int startpipe(char *name, bool inputpipe); void endpipe(char *name, int fd); int infd; int outfd; int count = 0; int main(void) { int nsel; bool done = FALSE; char const *msg = "You sent: "; int mlen = strlen(msg); fd_set readfds; FD_ZERO(&readfds); openpipes(); do { FD_SET(infd, &readfds); do { nsel = select(infd + 1, &readfds, 0, 0, 0); } while (nsel == -1 && (errno == EINTR || errno == EAGAIN)); if (nsel == -1) { perror("select"); exit(4); } if (FD_ISSET(infd, &readfds)) { char buf[100] = "You sent: "; int status; int count = 0; strcpy(buf, msg); while ((status = read(infd, buf + mlen, sizeof(buf) - mlen - 1))) { if (status > 0) { buf[mlen + status] = '\0'; if (write(outfd, buf, strlen(buf)) < 0) { if (buf[mlen + status - 1] == '\n') buf[mlen + status - 1] = '\0'; fprintf(stderr, "Error sending message: '%s': %s\n", buf, strerror(errno)); } if (strncasecmp(buf + mlen, "quit", 4) == 0) done = TRUE; } else if (errno == EAGAIN) { /* Nothing to read, continue */ break; } else { /* An error occurred, bail out */ perror("read"); done = TRUE; break; } } if (!done) { sleep(3); closepipes(); openpipes(); errno = 0; } } } while (!done); closepipes(); return 0; } void openpipes(void) { fprintf(stderr, "%d) Opening pipes\n", ++count); infd = startpipe(FIFO_IN, TRUE); if (infd == -1) exit(1); outfd = startpipe(FIFO_OUT, FALSE); if (outfd == -1) exit(2); if (fcntl(outfd, F_SETFL, O_NONBLOCK) < 0) { fprintf(stderr, "Could not set flags on pipe %s: %s\n", FIFO_OUT, strerror(errno)); exit(3); } } void closepipes() { fprintf(stderr, "%d) Closing pipes\n", count); endpipe(FIFO_IN, infd); endpipe(FIFO_OUT, outfd); } int startpipe(char *name, bool inputpipe) { static bool stalepipe = FALSE; int fd; if (access(name, F_OK) == 0) { if (inputpipe) { /* Let's see whether we have a stale pipe */ fd = open(name, O_WRONLY | O_NONBLOCK); if (fd >= 0) { /* pipe exists and is used by another process */ close(fd); } else if (errno == ENXIO) { /* No process is reading from the other end */ stalepipe = TRUE; endpipe(name, -1); } } else if (stalepipe) { endpipe(name, -1); stalepipe = FALSE; } if (access(name, F_OK) == 0) { fprintf(stderr, "Pipe %s already exists and is in use.\n", name); return -1; } } if (mkfifo(name, 0600) < 0) { fprintf(stderr, "Could not create pipe %s: %s\n", name, strerror(errno)); return -1; } fd = open(name, inputpipe ? (O_RDONLY | O_NONBLOCK) : O_RDWR); if (fd < 0) { fprintf(stderr, "Could not open pipe %s: %s\n", name, strerror(errno)); endpipe(name, -1); return -1; } return fd; } void endpipe(char *name, int fd) { if (fd >= 0 && close(fd) < 0) fprintf(stderr, "Could not close pipe %s: %s\n", name, strerror(errno)); if (remove(name) < 0) fprintf(stderr, "Could not remove pipe %s: %s\n", name, strerror(errno)); }