Esempio n. 1
0
/*
 * 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);
		}
	}
}
Esempio n. 2
0
static int
desrshread(int fd, char *buf, int len)
{
    return (desread(fd, buf, len, readiv ? 1 : 0));
}
Esempio n. 3
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, &notc) == -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, &notc) == -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);
}