xref: /csrg-svn/usr.bin/telnet/sys_bsd.c (revision 32531)
132147Sminshall /*
232147Sminshall  * The following routines try to encapsulate what is system dependent
332147Sminshall  * (at least between 4.x and dos) which is used in telnet.c.
432147Sminshall  */
532147Sminshall 
632147Sminshall #if	defined(unix)
732147Sminshall 
832147Sminshall #include <sys/ioctl.h>
932381Sminshall #include <sys/types.h>
1032147Sminshall #include <sys/time.h>
11*32531Sminshall #include <sys/socket.h>
1232147Sminshall #include <signal.h>
13*32531Sminshall #include <errno.h>
1432147Sminshall 
1532381Sminshall #include "ring.h"
1632381Sminshall 
1732147Sminshall #include "defines.h"
1832147Sminshall #include "externs.h"
1932147Sminshall #include "types.h"
2032147Sminshall 
21*32531Sminshall #ifndef	FD_SETSIZE
22*32531Sminshall /*
23*32531Sminshall  * The following is defined just in case someone should want to run
24*32531Sminshall  * this telnet on a 4.2 system.
25*32531Sminshall  *
26*32531Sminshall  */
27*32531Sminshall 
28*32531Sminshall #define	FD_SET(n, p)	((p)->fds_bits[0] |= (1<<(n)))
29*32531Sminshall #define	FD_CLR(n, p)	((p)->fds_bits[0] &= ~(1<<(n)))
30*32531Sminshall #define	FD_ISSET(n, p)	((p)->fds_bits[0] & (1<<(n)))
31*32531Sminshall #define FD_ZERO(p)	((p)->fds_bits[0] = 0)
32*32531Sminshall 
33*32531Sminshall #endif
34*32531Sminshall 
3532147Sminshall int
36*32531Sminshall 	tout,			/* Output file descriptor */
37*32531Sminshall 	tin,			/* Input file descriptor */
38*32531Sminshall 	net,
3932147Sminshall 	HaveInput;		/* There is input available to scan */
4032147Sminshall 
4132147Sminshall #if	defined(TN3270)
4232147Sminshall static char	tline[200];
4332147Sminshall char	*transcom = 0;	/* transparent mode command (default: none) */
4432147Sminshall #endif	/* defined(TN3270) */
4532147Sminshall 
4632147Sminshall static struct	tchars otc = { 0 }, ntc = { 0 };
4732147Sminshall static struct	ltchars oltc = { 0 }, nltc = { 0 };
4832147Sminshall static struct	sgttyb ottyb = { 0 }, nttyb = { 0 };
4932147Sminshall 
50*32531Sminshall static fd_set ibits, obits, xbits;
5132147Sminshall 
52*32531Sminshall 
53*32531Sminshall init_sys()
54*32531Sminshall {
55*32531Sminshall     tout = fileno(stdout);
56*32531Sminshall     tin = fileno(stdin);
57*32531Sminshall     FD_ZERO(&ibits);
58*32531Sminshall     FD_ZERO(&obits);
59*32531Sminshall     FD_ZERO(&xbits);
60*32531Sminshall 
61*32531Sminshall     errno = 0;
62*32531Sminshall }
63*32531Sminshall 
64*32531Sminshall 
6532147Sminshall TerminalWrite(fd, buf, n)
6632147Sminshall int	fd;
6732147Sminshall char	*buf;
6832147Sminshall int	n;
6932147Sminshall {
7032147Sminshall     return write(fd, buf, n);
7132147Sminshall }
7232147Sminshall 
7332147Sminshall TerminalRead(fd, buf, n)
7432147Sminshall int	fd;
7532147Sminshall char	*buf;
7632147Sminshall int	n;
7732147Sminshall {
7832147Sminshall     return read(fd, buf, n);
7932147Sminshall }
8032147Sminshall 
8132147Sminshall /*
8232147Sminshall  *
8332147Sminshall  */
8432147Sminshall 
8532147Sminshall int
8632147Sminshall TerminalAutoFlush()					/* unix */
8732147Sminshall {
8832147Sminshall #if	defined(LNOFLSH)
8932147Sminshall     int flush;
9032147Sminshall 
9132147Sminshall     ioctl(0, TIOCLGET, (char *)&flush);
9232147Sminshall     return !(flush&LNOFLSH);	/* if LNOFLSH, no autoflush */
9332147Sminshall #else	/* LNOFLSH */
9432147Sminshall     return 1;
9532147Sminshall #endif	/* LNOFLSH */
9632147Sminshall }
9732147Sminshall 
9832147Sminshall /*
9932147Sminshall  * TerminalSpecialChars()
10032147Sminshall  *
10132147Sminshall  * Look at an input character to see if it is a special character
10232147Sminshall  * and decide what to do.
10332147Sminshall  *
10432147Sminshall  * Output:
10532147Sminshall  *
10632147Sminshall  *	0	Don't add this character.
10732147Sminshall  *	1	Do add this character
10832147Sminshall  */
10932147Sminshall 
11032147Sminshall int
11132147Sminshall TerminalSpecialChars(c)			/* unix */
11232147Sminshall int	c;
11332147Sminshall {
11432147Sminshall     void doflush(), intp(), sendbrk();
11532147Sminshall 
11632147Sminshall     if (c == ntc.t_intrc) {
11732147Sminshall 	intp();
11832147Sminshall 	return 0;
11932147Sminshall     } else if (c == ntc.t_quitc) {
12032147Sminshall 	sendbrk();
12132147Sminshall 	return 0;
12232147Sminshall     } else if (c == nltc.t_flushc) {
12332147Sminshall 	xmitAO();		/* Transmit Abort Output */
12432147Sminshall 	return 0;
12532147Sminshall     } else if (!MODE_LOCAL_CHARS(globalmode)) {
12632147Sminshall 	if (c == nttyb.sg_kill) {
12732147Sminshall 	    xmitEL();
12832147Sminshall 	    return 0;
12932147Sminshall 	} else if (c == nttyb.sg_erase) {
13032147Sminshall 	    xmitEC();		/* Transmit Erase Character */
13132147Sminshall 	    return 0;
13232147Sminshall 	}
13332147Sminshall     }
13432147Sminshall     return 1;
13532147Sminshall }
13632147Sminshall 
13732147Sminshall 
13832147Sminshall /*
13932147Sminshall  * Flush output to the terminal
14032147Sminshall  */
14132147Sminshall 
14232147Sminshall void
14332147Sminshall TerminalFlushOutput()				/* unix */
14432147Sminshall {
14532147Sminshall     (void) ioctl(fileno(stdout), TIOCFLUSH, (char *) 0);
14632147Sminshall }
14732147Sminshall 
14832147Sminshall void
14932147Sminshall TerminalSaveState()				/* unix */
15032147Sminshall {
15132147Sminshall     ioctl(0, TIOCGETP, (char *)&ottyb);
15232147Sminshall     ioctl(0, TIOCGETC, (char *)&otc);
15332147Sminshall     ioctl(0, TIOCGLTC, (char *)&oltc);
15432147Sminshall 
15532147Sminshall     ntc = otc;
15632147Sminshall     nltc = oltc;
15732147Sminshall     nttyb = ottyb;
15832254Sminshall 
15932254Sminshall     termEofChar = ntc.t_eofc;
16032254Sminshall     termEraseChar = nttyb.sg_erase;
16132254Sminshall     termFlushChar = nltc.t_flushc;
16232254Sminshall     termIntChar = ntc.t_intrc;
16332254Sminshall     termKillChar = nttyb.sg_kill;
16432254Sminshall     termQuitChar = ntc.t_quitc;
16532147Sminshall }
16632147Sminshall 
16732147Sminshall void
16832147Sminshall TerminalRestoreState()				/* unix */
16932147Sminshall {
17032147Sminshall }
17132147Sminshall 
17232147Sminshall /*
17332147Sminshall  * TerminalNewMode - set up terminal to a specific mode.
17432147Sminshall  */
17532147Sminshall 
17632147Sminshall 
17732147Sminshall void
17832147Sminshall TerminalNewMode(fd_in, fd_out, f)			/* unix */
17932147Sminshall int	fd_in, fd_out;		/* File descriptor */
18032147Sminshall register int f;
18132147Sminshall {
18232147Sminshall     static int prevmode = 0;
18332147Sminshall     struct tchars *tc;
18432147Sminshall     struct tchars tc3;
18532147Sminshall     struct ltchars *ltc;
18632147Sminshall     struct sgttyb sb;
18732147Sminshall     int onoff;
18832147Sminshall     int old;
18932147Sminshall     struct	tchars notc2;
19032147Sminshall     struct	ltchars noltc2;
19132147Sminshall     static struct	tchars notc =	{ -1, -1, -1, -1, -1, -1 };
19232147Sminshall     static struct	ltchars noltc =	{ -1, -1, -1, -1, -1, -1 };
19332147Sminshall 
19432147Sminshall     globalmode = f;
19532147Sminshall     if (prevmode == f)
19632147Sminshall 	return;
19732147Sminshall     old = prevmode;
19832147Sminshall     prevmode = f;
19932147Sminshall     sb = nttyb;
20032147Sminshall 
20132147Sminshall     switch (f) {
20232147Sminshall 
20332147Sminshall     case 0:
20432147Sminshall 	onoff = 0;
20532147Sminshall 	tc = &otc;
20632147Sminshall 	ltc = &oltc;
20732147Sminshall 	break;
20832147Sminshall 
20932147Sminshall     case 1:		/* remote character processing, remote echo */
21032147Sminshall     case 2:		/* remote character processing, local echo */
21132147Sminshall     case 6:		/* 3270 mode - like 1, but with xon/xoff local */
21232147Sminshall 		    /* (might be nice to have "6" in telnet also...) */
21332147Sminshall 	    sb.sg_flags |= CBREAK;
21432147Sminshall 	    if ((f == 1) || (f == 6)) {
21532147Sminshall 		sb.sg_flags &= ~(ECHO|CRMOD);
21632147Sminshall 	    } else {
21732147Sminshall 		sb.sg_flags |= ECHO|CRMOD;
21832147Sminshall 	    }
21932147Sminshall 	    sb.sg_erase = sb.sg_kill = -1;
22032147Sminshall 	    if (f == 6) {
22132147Sminshall 		tc = &tc3;
22232147Sminshall 		tc3 = notc;
22332147Sminshall 		    /* get XON, XOFF characters */
22432147Sminshall 		tc3.t_startc = otc.t_startc;
22532147Sminshall 		tc3.t_stopc = otc.t_stopc;
22632147Sminshall 	    } else {
22732147Sminshall 		/*
22832147Sminshall 		 * If user hasn't specified one way or the other,
22932147Sminshall 		 * then default to not trapping signals.
23032147Sminshall 		 */
23132147Sminshall 		if (!donelclchars) {
23232147Sminshall 		    localchars = 0;
23332147Sminshall 		}
23432147Sminshall 		if (localchars) {
23532147Sminshall 		    notc2 = notc;
23632147Sminshall 		    notc2.t_intrc = ntc.t_intrc;
23732147Sminshall 		    notc2.t_quitc = ntc.t_quitc;
23832147Sminshall 		    tc = &notc2;
23932147Sminshall 		} else {
24032147Sminshall 		    tc = &notc;
24132147Sminshall 		}
24232147Sminshall 	    }
24332147Sminshall 	    ltc = &noltc;
24432147Sminshall 	    onoff = 1;
24532147Sminshall 	    break;
24632147Sminshall     case 3:		/* local character processing, remote echo */
24732147Sminshall     case 4:		/* local character processing, local echo */
24832147Sminshall     case 5:		/* local character processing, no echo */
24932147Sminshall 	    sb.sg_flags &= ~CBREAK;
25032147Sminshall 	    sb.sg_flags |= CRMOD;
25132147Sminshall 	    if (f == 4)
25232147Sminshall 		sb.sg_flags |= ECHO;
25332147Sminshall 	    else
25432147Sminshall 		sb.sg_flags &= ~ECHO;
25532147Sminshall 	    notc2 = ntc;
25632147Sminshall 	    tc = &notc2;
25732147Sminshall 	    noltc2 = oltc;
25832147Sminshall 	    ltc = &noltc2;
25932147Sminshall 	    /*
26032147Sminshall 	     * If user hasn't specified one way or the other,
26132147Sminshall 	     * then default to trapping signals.
26232147Sminshall 	     */
26332147Sminshall 	    if (!donelclchars) {
26432147Sminshall 		localchars = 1;
26532147Sminshall 	    }
26632147Sminshall 	    if (localchars) {
26732147Sminshall 		notc2.t_brkc = nltc.t_flushc;
26832147Sminshall 		noltc2.t_flushc = -1;
26932147Sminshall 	    } else {
27032147Sminshall 		notc2.t_intrc = notc2.t_quitc = -1;
27132147Sminshall 	    }
27232147Sminshall 	    noltc2.t_suspc = escape;
27332147Sminshall 	    noltc2.t_dsuspc = -1;
27432147Sminshall 	    onoff = 1;
27532147Sminshall 	    break;
27632147Sminshall 
27732147Sminshall     default:
27832147Sminshall 	    return;
27932147Sminshall     }
28032147Sminshall     ioctl(fd_in, TIOCSLTC, (char *)ltc);
28132147Sminshall     ioctl(fd_in, TIOCSETC, (char *)tc);
28232147Sminshall     ioctl(fd_in, TIOCSETP, (char *)&sb);
28332147Sminshall #if	(!defined(TN3270)) || ((!defined(NOT43)) || defined(PUTCHAR))
28432147Sminshall     ioctl(fd_in, FIONBIO, (char *)&onoff);
28532147Sminshall     ioctl(fd_out, FIONBIO, (char *)&onoff);
28632147Sminshall #endif	/* (!defined(TN3270)) || ((!defined(NOT43)) || defined(PUTCHAR)) */
28732147Sminshall #if	defined(TN3270)
28832147Sminshall     if (noasynch == 0) {
28932147Sminshall 	ioctl(fd_in, FIOASYNC, (char *)&onoff);
29032147Sminshall     }
29132147Sminshall #endif	/* defined(TN3270) */
29232147Sminshall 
29332147Sminshall     if (MODE_LINE(f)) {
29432147Sminshall 	void doescape();
29532147Sminshall 
29632147Sminshall 	signal(SIGTSTP, doescape);
29732147Sminshall     } else if (MODE_LINE(old)) {
29832147Sminshall 	signal(SIGTSTP, SIG_DFL);
29932147Sminshall 	sigsetmask(sigblock(0) & ~(1<<(SIGTSTP-1)));
30032147Sminshall     }
30132147Sminshall }
30232147Sminshall 
30332147Sminshall 
30432147Sminshall int
30532147Sminshall NetClose(net)
30632147Sminshall int	net;
30732147Sminshall {
30832147Sminshall     return close(net);
30932147Sminshall }
31032147Sminshall 
31132147Sminshall 
31232147Sminshall void
31332147Sminshall NetNonblockingIO(fd, onoff)				/* unix */
31432147Sminshall int
31532147Sminshall 	fd,
31632147Sminshall 	onoff;
31732147Sminshall {
31832147Sminshall     ioctl(fd, FIONBIO, (char *)&onoff);
31932147Sminshall }
32032147Sminshall 
32132147Sminshall void
32232147Sminshall NetSigIO(fd, onoff)				/* unix */
32332147Sminshall int
32432147Sminshall 	fd,
32532147Sminshall 	onoff;
32632147Sminshall {
32732147Sminshall     ioctl(fd, FIOASYNC, (char *)&onoff);	/* hear about input */
32832147Sminshall }
32932147Sminshall 
33032147Sminshall void
33132147Sminshall NetSetPgrp(fd)				/* unix */
33232147Sminshall int fd;
33332147Sminshall {
33432147Sminshall     int myPid;
33532147Sminshall 
33632147Sminshall     myPid = getpid();
33732147Sminshall #if	defined(NOT43)
33832147Sminshall     myPid = -myPid;
33932147Sminshall #endif	/* defined(NOT43) */
34032147Sminshall     ioctl(fd, SIOCSPGRP, (char *)&myPid);	/* set my pid */
34132147Sminshall }
34232147Sminshall 
34332147Sminshall 
344*32531Sminshall void
345*32531Sminshall sys_telnet_init()
346*32531Sminshall {
347*32531Sminshall #if	defined(TN3270) && defined(unix)
348*32531Sminshall     int myPid;
349*32531Sminshall #endif	/* defined(TN3270) */
350*32531Sminshall 
351*32531Sminshall     setconnmode();
352*32531Sminshall 
353*32531Sminshall     NetNonblockingIO(net, 1);
354*32531Sminshall 
355*32531Sminshall #if	defined(TN3270)
356*32531Sminshall     if (noasynch == 0) {			/* DBX can't handle! */
357*32531Sminshall 	NetSigIO(net, 1);
358*32531Sminshall 	NetSetPgrp(net);
359*32531Sminshall     }
360*32531Sminshall #endif	/* defined(TN3270) */
361*32531Sminshall 
362*32531Sminshall #if	defined(SO_OOBINLINE)
363*32531Sminshall     SetSockOpt(net, SOL_SOCKET, SO_OOBINLINE, 1);
364*32531Sminshall #endif	/* defined(SO_OOBINLINE) */
365*32531Sminshall }
366*32531Sminshall 
367*32531Sminshall /*
368*32531Sminshall  * Process rings -
369*32531Sminshall  *
370*32531Sminshall  *	This routine tries to fill up/empty our various rings.
371*32531Sminshall  *
372*32531Sminshall  *	The parameter specifies whether this is a poll operation,
373*32531Sminshall  *	or a block-until-something-happens operation.
374*32531Sminshall  *
375*32531Sminshall  *	The return value is 1 if something happened, 0 if not.
376*32531Sminshall  */
377*32531Sminshall 
378*32531Sminshall int
379*32531Sminshall process_rings(netin, netout, netex, ttyin, ttyout, poll)
380*32531Sminshall int poll;		/* If 0, then block until something to do */
381*32531Sminshall {
382*32531Sminshall     register int c;
383*32531Sminshall 		/* One wants to be a bit careful about setting returnValue
384*32531Sminshall 		 * to one, since a one implies we did some useful work,
385*32531Sminshall 		 * and therefore probably won't be called to block next
386*32531Sminshall 		 * time (TN3270 mode only).
387*32531Sminshall 		 */
388*32531Sminshall     int returnValue = 0;
389*32531Sminshall     static struct timeval TimeValue = { 0 };
390*32531Sminshall 
391*32531Sminshall     if (netout) {
392*32531Sminshall 	FD_SET(net, &obits);
393*32531Sminshall     }
394*32531Sminshall     if (ttyout) {
395*32531Sminshall 	FD_SET(tout, &obits);
396*32531Sminshall     }
397*32531Sminshall #if	defined(TN3270)
398*32531Sminshall     if (ttyin) {
399*32531Sminshall 	FD_SET(tin, &ibits);
400*32531Sminshall     }
401*32531Sminshall #else	/* defined(TN3270) */
402*32531Sminshall     if (ttyin) {
403*32531Sminshall 	FD_SET(tin, &ibits);
404*32531Sminshall     }
405*32531Sminshall #endif	/* defined(TN3270) */
406*32531Sminshall #if	defined(TN3270)
407*32531Sminshall     if (netin) {
408*32531Sminshall 	FD_SET(net, &ibits);
409*32531Sminshall     }
410*32531Sminshall #   else /* !defined(TN3270) */
411*32531Sminshall     if (netin) {
412*32531Sminshall 	FD_SET(net, &ibits);
413*32531Sminshall     }
414*32531Sminshall #   endif /* !defined(TN3270) */
415*32531Sminshall     if (netex) {
416*32531Sminshall 	FD_SET(net, &xbits);
417*32531Sminshall     }
418*32531Sminshall     if ((c = select(16, &ibits, &obits, &xbits,
419*32531Sminshall 			(poll == 0)? (struct timeval *)0 : &TimeValue)) < 0) {
420*32531Sminshall 	if (c == -1) {
421*32531Sminshall 		    /*
422*32531Sminshall 		     * we can get EINTR if we are in line mode,
423*32531Sminshall 		     * and the user does an escape (TSTP), or
424*32531Sminshall 		     * some other signal generator.
425*32531Sminshall 		     */
426*32531Sminshall 	    if (errno == EINTR) {
427*32531Sminshall 		return 0;
428*32531Sminshall 	    }
429*32531Sminshall #	    if defined(TN3270)
430*32531Sminshall 		    /*
431*32531Sminshall 		     * we can get EBADF if we were in transparent
432*32531Sminshall 		     * mode, and the transcom process died.
433*32531Sminshall 		    */
434*32531Sminshall 	    if (errno == EBADF) {
435*32531Sminshall 			/*
436*32531Sminshall 			 * zero the bits (even though kernel does it)
437*32531Sminshall 			 * to make sure we are selecting on the right
438*32531Sminshall 			 * ones.
439*32531Sminshall 			*/
440*32531Sminshall 		FD_ZERO(&ibits);
441*32531Sminshall 		FD_ZERO(&obits);
442*32531Sminshall 		FD_ZERO(&xbits);
443*32531Sminshall 		return 0;
444*32531Sminshall 	    }
445*32531Sminshall #	    endif /* defined(TN3270) */
446*32531Sminshall 		    /* I don't like this, does it ever happen? */
447*32531Sminshall 	    printf("sleep(5) from telnet, after select\r\n");
448*32531Sminshall #if	defined(unix)
449*32531Sminshall 	    sleep(5);
45032147Sminshall #endif	/* defined(unix) */
451*32531Sminshall 	}
452*32531Sminshall 	return 0;
453*32531Sminshall     }
454*32531Sminshall 
455*32531Sminshall     /*
456*32531Sminshall      * Any urgent data?
457*32531Sminshall      */
458*32531Sminshall     if (FD_ISSET(net, &xbits)) {
459*32531Sminshall 	FD_CLR(net, &xbits);
460*32531Sminshall 	SYNCHing = 1;
461*32531Sminshall 	ttyflush(1);	/* flush already enqueued data */
462*32531Sminshall     }
463*32531Sminshall 
464*32531Sminshall     /*
465*32531Sminshall      * Something to read from the network...
466*32531Sminshall      */
467*32531Sminshall     if (FD_ISSET(net, &ibits)) {
468*32531Sminshall 	int canread;
469*32531Sminshall 
470*32531Sminshall 	FD_CLR(net, &ibits);
471*32531Sminshall 	canread = ring_empty_consecutive(&netiring);
472*32531Sminshall #if	!defined(SO_OOBINLINE)
473*32531Sminshall 	    /*
474*32531Sminshall 	     * In 4.2 (and some early 4.3) systems, the
475*32531Sminshall 	     * OOB indication and data handling in the kernel
476*32531Sminshall 	     * is such that if two separate TCP Urgent requests
477*32531Sminshall 	     * come in, one byte of TCP data will be overlaid.
478*32531Sminshall 	     * This is fatal for Telnet, but we try to live
479*32531Sminshall 	     * with it.
480*32531Sminshall 	     *
481*32531Sminshall 	     * In addition, in 4.2 (and...), a special protocol
482*32531Sminshall 	     * is needed to pick up the TCP Urgent data in
483*32531Sminshall 	     * the correct sequence.
484*32531Sminshall 	     *
485*32531Sminshall 	     * What we do is:  if we think we are in urgent
486*32531Sminshall 	     * mode, we look to see if we are "at the mark".
487*32531Sminshall 	     * If we are, we do an OOB receive.  If we run
488*32531Sminshall 	     * this twice, we will do the OOB receive twice,
489*32531Sminshall 	     * but the second will fail, since the second
490*32531Sminshall 	     * time we were "at the mark", but there wasn't
491*32531Sminshall 	     * any data there (the kernel doesn't reset
492*32531Sminshall 	     * "at the mark" until we do a normal read).
493*32531Sminshall 	     * Once we've read the OOB data, we go ahead
494*32531Sminshall 	     * and do normal reads.
495*32531Sminshall 	     *
496*32531Sminshall 	     * There is also another problem, which is that
497*32531Sminshall 	     * since the OOB byte we read doesn't put us
498*32531Sminshall 	     * out of OOB state, and since that byte is most
499*32531Sminshall 	     * likely the TELNET DM (data mark), we would
500*32531Sminshall 	     * stay in the TELNET SYNCH (SYNCHing) state.
501*32531Sminshall 	     * So, clocks to the rescue.  If we've "just"
502*32531Sminshall 	     * received a DM, then we test for the
503*32531Sminshall 	     * presence of OOB data when the receive OOB
504*32531Sminshall 	     * fails (and AFTER we did the normal mode read
505*32531Sminshall 	     * to clear "at the mark").
506*32531Sminshall 	     */
507*32531Sminshall 	if (SYNCHing) {
508*32531Sminshall 	    int atmark;
509*32531Sminshall 
510*32531Sminshall 	    ioctl(net, SIOCATMARK, (char *)&atmark);
511*32531Sminshall 	    if (atmark) {
512*32531Sminshall 		c = recv(net, netiring.supply, canread, MSG_OOB);
513*32531Sminshall 		if ((c == -1) && (errno == EINVAL)) {
514*32531Sminshall 		    c = recv(net, netiring.supply, canread, 0);
515*32531Sminshall 		    if (clocks.didnetreceive < clocks.gotDM) {
516*32531Sminshall 			SYNCHing = stilloob(net);
517*32531Sminshall 		    }
518*32531Sminshall 		}
519*32531Sminshall 	    } else {
520*32531Sminshall 		c = recv(net, netiring.supply, canread, 0);
521*32531Sminshall 	    }
522*32531Sminshall 	} else {
523*32531Sminshall 	    c = recv(net, netiring.supply, canread, 0);
524*32531Sminshall 	}
525*32531Sminshall 	settimer(didnetreceive);
526*32531Sminshall #else	/* !defined(SO_OOBINLINE) */
527*32531Sminshall 	c = recv(net, netiring.supply, canread, 0);
528*32531Sminshall #endif	/* !defined(SO_OOBINLINE) */
529*32531Sminshall 	if (c < 0 && errno == EWOULDBLOCK) {
530*32531Sminshall 	    c = 0;
531*32531Sminshall 	} else if (c <= 0) {
532*32531Sminshall 	    return -1;
533*32531Sminshall 	}
534*32531Sminshall 	if (netdata) {
535*32531Sminshall 	    Dump('<', netiring.supply, c);
536*32531Sminshall 	}
537*32531Sminshall 	ring_supplied(&netiring, c);
538*32531Sminshall 	returnValue = 1;
539*32531Sminshall     }
540*32531Sminshall 
541*32531Sminshall     /*
542*32531Sminshall      * Something to read from the tty...
543*32531Sminshall      */
544*32531Sminshall     if (FD_ISSET(tin, &ibits)) {
545*32531Sminshall 	FD_CLR(tin, &ibits);
546*32531Sminshall 	c = TerminalRead(tin, ttyiring.supply,
547*32531Sminshall 			ring_empty_consecutive(&ttyiring));
548*32531Sminshall 	if (c < 0 && errno == EWOULDBLOCK) {
549*32531Sminshall 	    c = 0;
550*32531Sminshall 	} else {
551*32531Sminshall #if	defined(unix)
552*32531Sminshall 	    /* EOF detection for line mode!!!! */
553*32531Sminshall 	    if (c == 0 && MODE_LOCAL_CHARS(globalmode)) {
554*32531Sminshall 			/* must be an EOF... */
555*32531Sminshall 		*ttyiring.supply = termEofChar;
556*32531Sminshall 		c = 1;
557*32531Sminshall 	    }
558*32531Sminshall #endif	/* defined(unix) */
559*32531Sminshall 	    if (c <= 0) {
560*32531Sminshall 		return -1;
561*32531Sminshall 	    }
562*32531Sminshall 	}
563*32531Sminshall 	ring_supplied(&ttyiring, c);
564*32531Sminshall 	returnValue = 1;		/* did something useful */
565*32531Sminshall     }
566*32531Sminshall 
567*32531Sminshall     if (FD_ISSET(net, &obits)) {
568*32531Sminshall 	FD_CLR(net, &obits);
569*32531Sminshall 	returnValue |= netflush();
570*32531Sminshall     }
571*32531Sminshall     if (FD_ISSET(tout, &obits)) {
572*32531Sminshall 	FD_CLR(tout, &obits);
573*32531Sminshall 	returnValue |= ttyflush(SYNCHing|flushout);
574*32531Sminshall     }
575*32531Sminshall 
576*32531Sminshall     return returnValue;
577*32531Sminshall }
578*32531Sminshall #endif	/* defined(unix) */
579