/* * reader: read from remote: line -> 1 */ static int reader(int oldmask) { /* * 4.3bsd or later and SunOS 4.0 or later use the posiitive * pid; otherwise use the negative. */ pid_t pid = getpid(); int n, remaining; char *bufp = rcvbuf; (void) sigset(SIGTTOU, SIG_IGN); (void) sigset(SIGURG, (void (*)())oob); ppid = getppid(); if (fcntl(rem, F_SETOWN, pid) == -1) perror("fcntl F_SETOWN"); /* * A SIGURG may have been posted before we were completely forked, * which means we may not have received it. To insure we do not miss * any urgent data, we force the signal. The signal hander will be * able to determine if in fact there is urgent data or not. */ (void) kill(pid, SIGURG); (void) setjmp(rcvtop); sigsetmask(oldmask); for (;;) { while ((remaining = rcvcnt - (bufp - rcvbuf)) > 0) { rcvstate = WRITING; n = write(STDOUT_FILENO, bufp, remaining); if (n < 0) { if (errno != EINTR) { prf(gettext( "Write error to terminal: %s"), strerror(errno)); return (-1); } continue; } bufp += n; } bufp = rcvbuf; rcvcnt = 0; rcvstate = READING; rcvcnt = desread(rem, rcvbuf, sizeof (rcvbuf), 0); if (rcvcnt == 0) return (0); if (rcvcnt < 0) { if (errno == EINTR) continue; prf(gettext("Read error from network: %s"), strerror(errno)); return (-1); } } }
static int desrshread(int fd, char *buf, int len) { return (desread(fd, buf, len, readiv ? 1 : 0)); }
static void oob(void) { int out = FWRITE, atmark, n; int rcvd = 0; char waste[4*BUFSIZ], mark; struct sgttyb sb; fd_set exceptfds; struct timeval tv; int ret; FD_ZERO(&exceptfds); FD_SET(rem, &exceptfds); timerclear(&tv); ret = select(rem+1, NULL, NULL, &exceptfds, &tv); /* * We may get an extra signal at start up time since we are trying * to take all precautions not to miss the urgent byte. This * means we may get here without any urgent data to process, in which * case we do nothing and just return. */ if (ret <= 0) return; do { if (ioctl(rem, SIOCATMARK, &atmark) < 0) { break; } if (!atmark) { /* * Urgent data not here yet. * It may not be possible to send it yet * if we are blocked for output * and our input buffer is full. */ if (rcvcnt < sizeof (rcvbuf)) { n = desread(rem, rcvbuf + rcvcnt, sizeof (rcvbuf) - rcvcnt, 0); if (n <= 0) return; rcvd += n; rcvcnt += n; } else { /* * We still haven't gotten to the urgent mark * and we're out of buffer space. Since we * must clear our receive window to allow it * to arrive, we will have to throw away * these bytes. */ n = desread(rem, waste, sizeof (waste), 0); if (n <= 0) return; } } } while (atmark == 0); while (recv(rem, &mark, 1, MSG_OOB) < 0) { switch (errno) { case EWOULDBLOCK: /* * We've reached the urgent mark, so the next * data to arrive will be the urgent, but it must * not have arrived yet. */ (void) sleep(1); continue; default: return; } } if (mark & TIOCPKT_WINDOW) { /* * Let server know about window size changes */ (void) kill(ppid, SIGUSR1); } if (!eight && (mark & TIOCPKT_NOSTOP)) { if (ioctl(STDIN_FILENO, TIOCGETP, (char *)&sb) == -1) perror("ioctl TIOCGETP"); sb.sg_flags &= ~O_CBREAK; sb.sg_flags |= O_RAW; if (compat_ioctl(STDIN_FILENO, TIOCSETP, &sb) == -1) perror("ioctl TIOCSETP 1"); notc.t_stopc = -1; notc.t_startc = -1; if (compat_ioctl(STDIN_FILENO, TIOCSETC, ¬c) == -1) perror("ioctl TIOCSETC"); } if (!eight && (mark & TIOCPKT_DOSTOP)) { if (ioctl(STDIN_FILENO, TIOCGETP, (char *)&sb) == -1) perror("ioctl TIOCGETP"); sb.sg_flags &= ~O_RAW; sb.sg_flags |= O_CBREAK; if (compat_ioctl(STDIN_FILENO, TIOCSETP, &sb) == -1) perror("ioctl TIOCSETP 2"); notc.t_stopc = deftc.t_stopc; notc.t_startc = deftc.t_startc; if (compat_ioctl(STDIN_FILENO, TIOCSETC, ¬c) == -1) perror("ioctl TIOCSETC"); } if (mark & TIOCPKT_FLUSHWRITE) { if (ioctl(STDOUT_FILENO, TIOCFLUSH, (char *)&out) == -1) perror("ioctl TIOCFLUSH"); for (;;) { if (ioctl(rem, SIOCATMARK, &atmark) < 0) { perror("ioctl SIOCATMARK"); break; } if (atmark) break; n = desread(rem, waste, sizeof (waste), 0); if (n <= 0) { if (n < 0) prf(gettext( "Read error from network: %s"), strerror(errno)); break; } } /* * Don't want any pending data to be output, * so clear the recv buffer. * If we were hanging on a write when interrupted, * don't want it to restart. If we were reading, * restart anyway. */ rcvcnt = 0; longjmp(rcvtop, 1); } /* * If we filled the receive buffer while a read was pending, * longjmp to the top to restart appropriately. Don't abort * a pending write, however, or we won't know how much was written. */ if (rcvd && rcvstate == READING) longjmp(rcvtop, 1); }