xref: /csrg-svn/usr.bin/telnet/sys_bsd.c (revision 57213)
132147Sminshall /*
245233Sborman  * Copyright (c) 1988, 1990 Regents of the University of California.
333685Sbostic  * All rights reserved.
433685Sbostic  *
542770Sbostic  * %sccs.include.redist.c%
633685Sbostic  */
733685Sbostic 
833685Sbostic #ifndef lint
9*57213Sdab static char sccsid[] = "@(#)sys_bsd.c	5.3 (Berkeley) 12/18/92";
1033685Sbostic #endif /* not lint */
1133685Sbostic 
1233685Sbostic /*
1332147Sminshall  * The following routines try to encapsulate what is system dependent
1432147Sminshall  * (at least between 4.x and dos) which is used in telnet.c.
1532147Sminshall  */
1632147Sminshall 
1732147Sminshall 
1836274Sminshall #include <fcntl.h>
1932381Sminshall #include <sys/types.h>
2032147Sminshall #include <sys/time.h>
2132531Sminshall #include <sys/socket.h>
2232147Sminshall #include <signal.h>
2332531Sminshall #include <errno.h>
2438689Sborman #include <arpa/telnet.h>
2532147Sminshall 
2632381Sminshall #include "ring.h"
2732381Sminshall 
2832657Sminshall #include "fdset.h"
2932657Sminshall 
3032147Sminshall #include "defines.h"
3132147Sminshall #include "externs.h"
3232147Sminshall #include "types.h"
3332147Sminshall 
3445233Sborman #if	defined(CRAY) || (defined(USE_TERMIO) && !defined(SYSV_TERMIO))
3540245Sborman #define	SIG_FUNC_RET	void
3640245Sborman #else
3740245Sborman #define	SIG_FUNC_RET	int
3840245Sborman #endif
3940245Sborman 
4032147Sminshall int
4132531Sminshall 	tout,			/* Output file descriptor */
4232531Sminshall 	tin,			/* Input file descriptor */
4336242Sminshall 	net;
4432147Sminshall 
4538689Sborman #ifndef	USE_TERMIO
4638689Sborman struct	tchars otc = { 0 }, ntc = { 0 };
4738689Sborman struct	ltchars oltc = { 0 }, nltc = { 0 };
4838689Sborman struct	sgttyb ottyb = { 0 }, nttyb = { 0 };
4938909Sborman int	olmode = 0;
5045233Sborman # define cfgetispeed(ptr)	(ptr)->sg_ispeed
5145233Sborman # define cfgetospeed(ptr)	(ptr)->sg_ospeed
5245233Sborman # define old_tc ottyb
5332147Sminshall 
5438689Sborman #else	/* USE_TERMIO */
5538689Sborman struct	termio old_tc = { 0 };
5638689Sborman extern struct termio new_tc;
5738689Sborman 
5845233Sborman # ifndef	TCSANOW
5945233Sborman #  ifdef TCSETS
6045233Sborman #   define	TCSANOW		TCSETS
6145233Sborman #   define	TCSADRAIN	TCSETSW
6246808Sdab #   define	tcgetattr(f, t) ioctl(f, TCGETS, (char *)t)
6345233Sborman #  else
6445233Sborman #   ifdef TCSETA
6545233Sborman #    define	TCSANOW		TCSETA
6645233Sborman #    define	TCSADRAIN	TCSETAW
6746808Sdab #    define	tcgetattr(f, t) ioctl(f, TCGETA, (char *)t)
6845233Sborman #   else
6945233Sborman #    define	TCSANOW		TIOCSETA
7045233Sborman #    define	TCSADRAIN	TIOCSETAW
7146808Sdab #    define	tcgetattr(f, t) ioctl(f, TIOCGETA, (char *)t)
7245233Sborman #   endif
7345233Sborman #  endif
7446808Sdab #  define	tcsetattr(f, a, t) ioctl(f, a, (char *)t)
7545233Sborman #  define	cfgetospeed(ptr)	((ptr)->c_cflag&CBAUD)
7645233Sborman #  ifdef CIBAUD
7745233Sborman #   define	cfgetispeed(ptr)	(((ptr)->c_cflag&CIBAUD) >> IBSHIFT)
7845233Sborman #  else
7945233Sborman #   define	cfgetispeed(ptr)	cfgetospeed(ptr)
8045233Sborman #  endif
8145233Sborman # endif /* TCSANOW */
82*57213Sdab # ifdef	sysV88
83*57213Sdab # define TIOCFLUSH TC_PX_DRAIN
84*57213Sdab # endif
8538689Sborman #endif	/* USE_TERMIO */
8638689Sborman 
8732531Sminshall static fd_set ibits, obits, xbits;
8832147Sminshall 
8932531Sminshall 
9046808Sdab     void
9132531Sminshall init_sys()
9232531Sminshall {
9332531Sminshall     tout = fileno(stdout);
9432531Sminshall     tin = fileno(stdin);
9532531Sminshall     FD_ZERO(&ibits);
9632531Sminshall     FD_ZERO(&obits);
9732531Sminshall     FD_ZERO(&xbits);
9832531Sminshall 
9932531Sminshall     errno = 0;
10032531Sminshall }
10132531Sminshall 
10232531Sminshall 
10346808Sdab     int
10433286Sminshall TerminalWrite(buf, n)
10546808Sdab     char *buf;
10646808Sdab     int  n;
10732147Sminshall {
10833286Sminshall     return write(tout, buf, n);
10932147Sminshall }
11032147Sminshall 
11146808Sdab     int
11233286Sminshall TerminalRead(buf, n)
11346808Sdab     char *buf;
11446808Sdab     int  n;
11532147Sminshall {
11633286Sminshall     return read(tin, buf, n);
11732147Sminshall }
11832147Sminshall 
11932147Sminshall /*
12032147Sminshall  *
12132147Sminshall  */
12232147Sminshall 
12346808Sdab     int
12432553Sminshall TerminalAutoFlush()
12532147Sminshall {
12632147Sminshall #if	defined(LNOFLSH)
12732147Sminshall     int flush;
12832147Sminshall 
12932147Sminshall     ioctl(0, TIOCLGET, (char *)&flush);
13032147Sminshall     return !(flush&LNOFLSH);	/* if LNOFLSH, no autoflush */
13132147Sminshall #else	/* LNOFLSH */
13232147Sminshall     return 1;
13332147Sminshall #endif	/* LNOFLSH */
13432147Sminshall }
13532147Sminshall 
13638689Sborman #ifdef	KLUDGELINEMODE
13738689Sborman extern int kludgelinemode;
13838689Sborman #endif
13932147Sminshall /*
14032147Sminshall  * TerminalSpecialChars()
14132147Sminshall  *
14232147Sminshall  * Look at an input character to see if it is a special character
14332147Sminshall  * and decide what to do.
14432147Sminshall  *
14532147Sminshall  * Output:
14632147Sminshall  *
14732147Sminshall  *	0	Don't add this character.
14832147Sminshall  *	1	Do add this character
14932147Sminshall  */
15032147Sminshall 
15146808Sdab     int
15232553Sminshall TerminalSpecialChars(c)
15346808Sdab     int	c;
15432147Sminshall {
15532553Sminshall     void xmitAO(), xmitEL(), xmitEC(), intp(), sendbrk();
15632147Sminshall 
15738689Sborman     if (c == termIntChar) {
15832147Sminshall 	intp();
15932147Sminshall 	return 0;
16038689Sborman     } else if (c == termQuitChar) {
16138689Sborman #ifdef	KLUDGELINEMODE
16238689Sborman 	if (kludgelinemode)
16338689Sborman 	    sendbrk();
16438689Sborman 	else
16538689Sborman #endif
16638689Sborman 	    sendabort();
16732147Sminshall 	return 0;
16838689Sborman     } else if (c == termEofChar) {
16938689Sborman 	if (my_want_state_is_will(TELOPT_LINEMODE)) {
17038689Sborman 	    sendeof();
17138689Sborman 	    return 0;
17238689Sborman 	}
17338689Sborman 	return 1;
17438689Sborman     } else if (c == termSuspChar) {
17538689Sborman 	sendsusp();
17638689Sborman 	return(0);
17738689Sborman     } else if (c == termFlushChar) {
17832147Sminshall 	xmitAO();		/* Transmit Abort Output */
17932147Sminshall 	return 0;
18032147Sminshall     } else if (!MODE_LOCAL_CHARS(globalmode)) {
18138689Sborman 	if (c == termKillChar) {
18232147Sminshall 	    xmitEL();
18332147Sminshall 	    return 0;
18438689Sborman 	} else if (c == termEraseChar) {
18532147Sminshall 	    xmitEC();		/* Transmit Erase Character */
18632147Sminshall 	    return 0;
18732147Sminshall 	}
18832147Sminshall     }
18932147Sminshall     return 1;
19032147Sminshall }
19132147Sminshall 
19232147Sminshall 
19332147Sminshall /*
19432147Sminshall  * Flush output to the terminal
19532147Sminshall  */
19632147Sminshall 
19746808Sdab     void
19832553Sminshall TerminalFlushOutput()
19932147Sminshall {
20039529Sborman #ifdef	TIOCFLUSH
20132147Sminshall     (void) ioctl(fileno(stdout), TIOCFLUSH, (char *) 0);
20238689Sborman #else
20338689Sborman     (void) ioctl(fileno(stdout), TCFLSH, (char *) 0);
20438689Sborman #endif
20532147Sminshall }
20632147Sminshall 
20746808Sdab     void
20832553Sminshall TerminalSaveState()
20932147Sminshall {
21038689Sborman #ifndef	USE_TERMIO
21132147Sminshall     ioctl(0, TIOCGETP, (char *)&ottyb);
21232147Sminshall     ioctl(0, TIOCGETC, (char *)&otc);
21332147Sminshall     ioctl(0, TIOCGLTC, (char *)&oltc);
21438909Sborman     ioctl(0, TIOCLGET, (char *)&olmode);
21532147Sminshall 
21632147Sminshall     ntc = otc;
21732147Sminshall     nltc = oltc;
21832147Sminshall     nttyb = ottyb;
21932254Sminshall 
22038689Sborman #else	/* USE_TERMIO */
22145233Sborman     tcgetattr(0, &old_tc);
22238689Sborman 
22338689Sborman     new_tc = old_tc;
22438689Sborman 
22545233Sborman #ifndef	VDISCARD
22644361Sborman     termFlushChar = CONTROL('O');
22745233Sborman #endif
22845233Sborman #ifndef	VWERASE
22944361Sborman     termWerasChar = CONTROL('W');
23045233Sborman #endif
23145233Sborman #ifndef	VREPRINT
23244361Sborman     termRprntChar = CONTROL('R');
23345233Sborman #endif
23445233Sborman #ifndef	VLNEXT
23544361Sborman     termLiteralNextChar = CONTROL('V');
23645233Sborman #endif
23745233Sborman #ifndef	VSTART
23844361Sborman     termStartChar = CONTROL('Q');
23945233Sborman #endif
24045233Sborman #ifndef	VSTOP
24144361Sborman     termStopChar = CONTROL('S');
24245233Sborman #endif
24345233Sborman #ifndef	VSTATUS
24445233Sborman     termAytChar = CONTROL('T');
24545233Sborman #endif
24638689Sborman #endif	/* USE_TERMIO */
24732147Sminshall }
24832147Sminshall 
24946808Sdab     cc_t *
25038689Sborman tcval(func)
25146808Sdab     register int func;
25238689Sborman {
25338689Sborman     switch(func) {
25440245Sborman     case SLC_IP:	return(&termIntChar);
25540245Sborman     case SLC_ABORT:	return(&termQuitChar);
25640245Sborman     case SLC_EOF:	return(&termEofChar);
25740245Sborman     case SLC_EC:	return(&termEraseChar);
25840245Sborman     case SLC_EL:	return(&termKillChar);
25940245Sborman     case SLC_XON:	return(&termStartChar);
26040245Sborman     case SLC_XOFF:	return(&termStopChar);
26144361Sborman     case SLC_FORW1:	return(&termForw1Char);
26245233Sborman #ifdef	USE_TERMIO
26345233Sborman     case SLC_FORW2:	return(&termForw2Char);
26445233Sborman # ifdef	VDISCARD
26540245Sborman     case SLC_AO:	return(&termFlushChar);
26645233Sborman # endif
26745233Sborman # ifdef	VSUSP
26840245Sborman     case SLC_SUSP:	return(&termSuspChar);
26945233Sborman # endif
27045233Sborman # ifdef	VWERASE
27140245Sborman     case SLC_EW:	return(&termWerasChar);
27245233Sborman # endif
27345233Sborman # ifdef	VREPRINT
27440245Sborman     case SLC_RP:	return(&termRprntChar);
27545233Sborman # endif
27645233Sborman # ifdef	VLNEXT
27740245Sborman     case SLC_LNEXT:	return(&termLiteralNextChar);
27845233Sborman # endif
27945233Sborman # ifdef	VSTATUS
28045233Sborman     case SLC_AYT:	return(&termAytChar);
28145233Sborman # endif
28244361Sborman #endif
28338689Sborman 
28438689Sborman     case SLC_SYNCH:
28538689Sborman     case SLC_BRK:
28638689Sborman     case SLC_EOR:
28738689Sborman     default:
28840245Sborman 	return((cc_t *)0);
28938689Sborman     }
29038689Sborman }
29138689Sborman 
29246808Sdab     void
29338689Sborman TerminalDefaultChars()
29438689Sborman {
29538689Sborman #ifndef	USE_TERMIO
29638689Sborman     ntc = otc;
29738689Sborman     nltc = oltc;
29838689Sborman     nttyb.sg_kill = ottyb.sg_kill;
29938689Sborman     nttyb.sg_erase = ottyb.sg_erase;
30038689Sborman #else	/* USE_TERMIO */
30138689Sborman     memcpy(new_tc.c_cc, old_tc.c_cc, sizeof(old_tc.c_cc));
30245233Sborman # ifndef	VDISCARD
30344361Sborman     termFlushChar = CONTROL('O');
30439529Sborman # endif
30539529Sborman # ifndef	VWERASE
30644361Sborman     termWerasChar = CONTROL('W');
30739529Sborman # endif
30839529Sborman # ifndef	VREPRINT
30944361Sborman     termRprntChar = CONTROL('R');
31039529Sborman # endif
31139529Sborman # ifndef	VLNEXT
31244361Sborman     termLiteralNextChar = CONTROL('V');
31339529Sborman # endif
31439529Sborman # ifndef	VSTART
31544361Sborman     termStartChar = CONTROL('Q');
31639529Sborman # endif
31739529Sborman # ifndef	VSTOP
31844361Sborman     termStopChar = CONTROL('S');
31939529Sborman # endif
32045233Sborman # ifndef	VSTATUS
32145233Sborman     termAytChar = CONTROL('T');
32245233Sborman # endif
32338689Sborman #endif	/* USE_TERMIO */
32438689Sborman }
32538689Sborman 
32644361Sborman #ifdef notdef
32738689Sborman void
32832553Sminshall TerminalRestoreState()
32932147Sminshall {
33032147Sminshall }
33144361Sborman #endif
33232147Sminshall 
33332147Sminshall /*
33432147Sminshall  * TerminalNewMode - set up terminal to a specific mode.
33538689Sborman  *	MODE_ECHO: do local terminal echo
33638689Sborman  *	MODE_FLOW: do local flow control
33738689Sborman  *	MODE_TRAPSIG: do local mapping to TELNET IAC sequences
33838689Sborman  *	MODE_EDIT: do local line editing
33938689Sborman  *
34038689Sborman  *	Command mode:
34138689Sborman  *		MODE_ECHO|MODE_EDIT|MODE_FLOW|MODE_TRAPSIG
34238689Sborman  *		local echo
34338689Sborman  *		local editing
34438689Sborman  *		local xon/xoff
34538689Sborman  *		local signal mapping
34638689Sborman  *
34738689Sborman  *	Linemode:
34838689Sborman  *		local/no editing
34938689Sborman  *	Both Linemode and Single Character mode:
35038689Sborman  *		local/remote echo
35138689Sborman  *		local/no xon/xoff
35238689Sborman  *		local/no signal mapping
35332147Sminshall  */
35432147Sminshall 
35532147Sminshall 
35646808Sdab     void
35733286Sminshall TerminalNewMode(f)
35846808Sdab     register int f;
35932147Sminshall {
36032147Sminshall     static int prevmode = 0;
36138689Sborman #ifndef	USE_TERMIO
36238689Sborman     struct tchars tc;
36338689Sborman     struct ltchars ltc;
36432147Sminshall     struct sgttyb sb;
36538909Sborman     int lmode;
36638689Sborman #else	/* USE_TERMIO */
36738689Sborman     struct termio tmp_tc;
36838689Sborman #endif	/* USE_TERMIO */
36932147Sminshall     int onoff;
37032147Sminshall     int old;
37146808Sdab     cc_t esc;
37232147Sminshall 
37338689Sborman     globalmode = f&~MODE_FORCE;
37432147Sminshall     if (prevmode == f)
37532147Sminshall 	return;
37638689Sborman 
37738689Sborman     /*
37838689Sborman      * Write any outstanding data before switching modes
37938689Sborman      * ttyflush() returns 0 only when there is no more data
38038689Sborman      * left to write out, it returns -1 if it couldn't do
38138689Sborman      * anything at all, otherwise it returns 1 + the number
38238689Sborman      * of characters left to write.
38345233Sborman #ifndef	USE_TERMIO
38445233Sborman      * We would really like ask the kernel to wait for the output
38545233Sborman      * to drain, like we can do with the TCSADRAIN, but we don't have
38645233Sborman      * that option.  The only ioctl that waits for the output to
38745233Sborman      * drain, TIOCSETP, also flushes the input queue, which is NOT
38845233Sborman      * what we want (TIOCSETP is like TCSADFLUSH).
38945233Sborman #endif
39038689Sborman      */
39138689Sborman     old = ttyflush(SYNCHing|flushout);
39238689Sborman     if (old < 0 || old > 1) {
39345233Sborman #ifdef	USE_TERMIO
39446808Sdab 	tcgetattr(tin, &tmp_tc);
39538689Sborman #endif	/* USE_TERMIO */
39638689Sborman 	do {
39738689Sborman 	    /*
39838689Sborman 	     * Wait for data to drain, then flush again.
39938689Sborman 	     */
40045233Sborman #ifdef	USE_TERMIO
40146808Sdab 	    tcsetattr(tin, TCSADRAIN, &tmp_tc);
40238689Sborman #endif	/* USE_TERMIO */
40338689Sborman 	    old = ttyflush(SYNCHing|flushout);
40438689Sborman 	} while (old < 0 || old > 1);
40538689Sborman     }
40638689Sborman 
40732147Sminshall     old = prevmode;
40838689Sborman     prevmode = f&~MODE_FORCE;
40938689Sborman #ifndef	USE_TERMIO
41032147Sminshall     sb = nttyb;
41138689Sborman     tc = ntc;
41238689Sborman     ltc = nltc;
41338909Sborman     lmode = olmode;
41438689Sborman #else
41538689Sborman     tmp_tc = new_tc;
41638689Sborman #endif
41732147Sminshall 
41838689Sborman     if (f&MODE_ECHO) {
41938689Sborman #ifndef	USE_TERMIO
42038689Sborman 	sb.sg_flags |= ECHO;
42138689Sborman #else
42238689Sborman 	tmp_tc.c_lflag |= ECHO;
42338689Sborman 	tmp_tc.c_oflag |= ONLCR;
42446808Sdab 	if (crlf)
42546808Sdab 		tmp_tc.c_iflag |= ICRNL;
42638689Sborman #endif
42738689Sborman     } else {
42838689Sborman #ifndef	USE_TERMIO
42938689Sborman 	sb.sg_flags &= ~ECHO;
43038689Sborman #else
43138689Sborman 	tmp_tc.c_lflag &= ~ECHO;
43238689Sborman 	tmp_tc.c_oflag &= ~ONLCR;
43339529Sborman # ifdef notdef
43446808Sdab 	if (crlf)
43546808Sdab 		tmp_tc.c_iflag &= ~ICRNL;
43639529Sborman # endif
43738689Sborman #endif
43838689Sborman     }
43932147Sminshall 
44038689Sborman     if ((f&MODE_FLOW) == 0) {
44138689Sborman #ifndef	USE_TERMIO
44245233Sborman 	tc.t_startc = _POSIX_VDISABLE;
44345233Sborman 	tc.t_stopc = _POSIX_VDISABLE;
44438689Sborman #else
445*57213Sdab 	tmp_tc.c_iflag &= ~(IXOFF|IXON);	/* Leave the IXANY bit alone */
44638689Sborman     } else {
447*57213Sdab 	if (restartany < 0) {
448*57213Sdab 		tmp_tc.c_iflag |= IXOFF|IXON;	/* Leave the IXANY bit alone */
449*57213Sdab 	} else if (restartany > 0) {
450*57213Sdab 		tmp_tc.c_iflag |= IXOFF|IXON|IXANY;
451*57213Sdab 	} else {
452*57213Sdab 		tmp_tc.c_iflag |= IXOFF|IXON;
453*57213Sdab 		tmp_tc.c_iflag &= ~IXANY;
454*57213Sdab 	}
45538689Sborman #endif
45638689Sborman     }
45732147Sminshall 
45838689Sborman     if ((f&MODE_TRAPSIG) == 0) {
45938689Sborman #ifndef	USE_TERMIO
46045233Sborman 	tc.t_intrc = _POSIX_VDISABLE;
46145233Sborman 	tc.t_quitc = _POSIX_VDISABLE;
46245233Sborman 	tc.t_eofc = _POSIX_VDISABLE;
46345233Sborman 	ltc.t_suspc = _POSIX_VDISABLE;
46445233Sborman 	ltc.t_dsuspc = _POSIX_VDISABLE;
46538689Sborman #else
46638689Sborman 	tmp_tc.c_lflag &= ~ISIG;
46738689Sborman #endif
46838689Sborman 	localchars = 0;
46938689Sborman     } else {
47038689Sborman #ifdef	USE_TERMIO
47138689Sborman 	tmp_tc.c_lflag |= ISIG;
47238689Sborman #endif
47338689Sborman 	localchars = 1;
47438689Sborman     }
47538689Sborman 
47638689Sborman     if (f&MODE_EDIT) {
47738689Sborman #ifndef	USE_TERMIO
47838689Sborman 	sb.sg_flags &= ~CBREAK;
47938689Sborman 	sb.sg_flags |= CRMOD;
48038689Sborman #else
48138689Sborman 	tmp_tc.c_lflag |= ICANON;
48238689Sborman #endif
48338689Sborman     } else {
48438689Sborman #ifndef	USE_TERMIO
48538689Sborman 	sb.sg_flags |= CBREAK;
48638689Sborman 	if (f&MODE_ECHO)
48732147Sminshall 	    sb.sg_flags |= CRMOD;
48838689Sborman 	else
48938689Sborman 	    sb.sg_flags &= ~CRMOD;
49038689Sborman #else
49138689Sborman 	tmp_tc.c_lflag &= ~ICANON;
49238689Sborman 	tmp_tc.c_iflag &= ~ICRNL;
49338689Sborman 	tmp_tc.c_cc[VMIN] = 1;
49438689Sborman 	tmp_tc.c_cc[VTIME] = 0;
49538689Sborman #endif
49638689Sborman     }
49732147Sminshall 
49844361Sborman     if ((f&(MODE_EDIT|MODE_TRAPSIG)) == 0) {
49944361Sborman #ifndef	USE_TERMIO
50045233Sborman 	ltc.t_lnextc = _POSIX_VDISABLE;
50144361Sborman #else
50244361Sborman # ifdef VLNEXT
50345233Sborman 	tmp_tc.c_cc[VLNEXT] = (cc_t)(_POSIX_VDISABLE);
50444361Sborman # endif
50544361Sborman #endif
50644361Sborman     }
50744361Sborman 
50844361Sborman     if (f&MODE_SOFT_TAB) {
50944361Sborman #ifndef USE_TERMIO
51044361Sborman 	sb.sg_flags |= XTABS;
51144361Sborman #else
51244361Sborman # ifdef	OXTABS
51344361Sborman 	tmp_tc.c_oflag |= OXTABS;
51444361Sborman # endif
51544361Sborman # ifdef	TABDLY
51644361Sborman 	tmp_tc.c_oflag &= ~TABDLY;
51744361Sborman 	tmp_tc.c_oflag |= TAB3;
51844361Sborman # endif
51944361Sborman #endif
52044361Sborman     } else {
52144361Sborman #ifndef USE_TERMIO
52244361Sborman 	sb.sg_flags &= ~XTABS;
52344361Sborman #else
52444361Sborman # ifdef	OXTABS
52544361Sborman 	tmp_tc.c_oflag &= ~OXTABS;
52644361Sborman # endif
52744361Sborman # ifdef	TABDLY
52844361Sborman 	tmp_tc.c_oflag &= ~TABDLY;
52944361Sborman # endif
53044361Sborman #endif
53144361Sborman     }
53244361Sborman 
53344361Sborman     if (f&MODE_LIT_ECHO) {
53444361Sborman #ifndef USE_TERMIO
53546808Sdab 	lmode &= ~LCTLECH;
53644361Sborman #else
53744361Sborman # ifdef	ECHOCTL
53844361Sborman 	tmp_tc.c_lflag &= ~ECHOCTL;
53944361Sborman # endif
54044361Sborman #endif
54144361Sborman     } else {
54244361Sborman #ifndef USE_TERMIO
54346808Sdab 	lmode |= LCTLECH;
54444361Sborman #else
54544361Sborman # ifdef	ECHOCTL
54644361Sborman 	tmp_tc.c_lflag |= ECHOCTL;
54744361Sborman # endif
54844361Sborman #endif
54944361Sborman     }
55044361Sborman 
55138689Sborman     if (f == -1) {
55238689Sborman 	onoff = 0;
55338689Sborman     } else {
55438909Sborman #ifndef	USE_TERMIO
55539529Sborman 	if (f & MODE_OUTBIN)
55638909Sborman 		lmode |= LLITOUT;
55738909Sborman 	else
55838909Sborman 		lmode &= ~LLITOUT;
55939529Sborman 
56039529Sborman 	if (f & MODE_INBIN)
56138909Sborman 		lmode |= LPASS8;
56238909Sborman 	else
56338909Sborman 		lmode &= ~LPASS8;
56438909Sborman #else
56545233Sborman 	if (f & MODE_INBIN)
56645233Sborman 		tmp_tc.c_iflag &= ~ISTRIP;
56738909Sborman 	else
56845233Sborman 		tmp_tc.c_iflag |= ISTRIP;
56945233Sborman 	if (f & MODE_OUTBIN) {
57039529Sborman 		tmp_tc.c_cflag &= ~(CSIZE|PARENB);
57139529Sborman 		tmp_tc.c_cflag |= CS8;
57245233Sborman 		tmp_tc.c_oflag &= ~OPOST;
57339529Sborman 	} else {
57445233Sborman 		tmp_tc.c_cflag &= ~(CSIZE|PARENB);
57545233Sborman 		tmp_tc.c_cflag |= old_tc.c_cflag & (CSIZE|PARENB);
57645233Sborman 		tmp_tc.c_oflag |= OPOST;
57739529Sborman 	}
57838909Sborman #endif
57938689Sborman 	onoff = 1;
58032147Sminshall     }
58138689Sborman 
58238689Sborman     if (f != -1) {
58339529Sborman #ifdef	SIGTSTP
58445233Sborman 	static SIG_FUNC_RET susp();
58545233Sborman #endif	/* SIGTSTP */
58645233Sborman #ifdef	SIGINFO
58745233Sborman 	static SIG_FUNC_RET ayt();
58845233Sborman #endif	SIGINFO
58938689Sborman 
59045233Sborman #ifdef	SIGTSTP
59145233Sborman 	(void) signal(SIGTSTP, susp);
59239529Sborman #endif	/* SIGTSTP */
59345233Sborman #ifdef	SIGINFO
59445233Sborman 	(void) signal(SIGINFO, ayt);
59545233Sborman #endif	SIGINFO
59645233Sborman #if	defined(USE_TERMIO) && defined(NOKERNINFO)
59745233Sborman 	tmp_tc.c_lflag |= NOKERNINFO;
59845233Sborman #endif
59944361Sborman 	/*
60044361Sborman 	 * We don't want to process ^Y here.  It's just another
60144361Sborman 	 * character that we'll pass on to the back end.  It has
60244361Sborman 	 * to process it because it will be processed when the
60344361Sborman 	 * user attempts to read it, not when we send it.
60444361Sborman 	 */
60544361Sborman #ifndef	USE_TERMIO
60645233Sborman 	ltc.t_dsuspc = _POSIX_VDISABLE;
60744361Sborman #else
60844361Sborman # ifdef	VDSUSP
60945233Sborman 	tmp_tc.c_cc[VDSUSP] = (cc_t)(_POSIX_VDISABLE);
61044361Sborman # endif
61144361Sborman #endif
61240245Sborman #ifdef	USE_TERMIO
61340245Sborman 	/*
61440245Sborman 	 * If the VEOL character is already set, then use VEOL2,
61540245Sborman 	 * otherwise use VEOL.
61640245Sborman 	 */
61746808Sdab 	esc = (rlogin != _POSIX_VDISABLE) ? rlogin : escape;
61846808Sdab 	if ((tmp_tc.c_cc[VEOL] != esc)
61944361Sborman # ifdef	VEOL2
62046808Sdab 	    && (tmp_tc.c_cc[VEOL2] != esc)
62144361Sborman # endif
62246808Sdab 	    ) {
62345233Sborman 		if (tmp_tc.c_cc[VEOL] == (cc_t)(_POSIX_VDISABLE))
62446808Sdab 		    tmp_tc.c_cc[VEOL] = esc;
62545233Sborman # ifdef	VEOL2
62645233Sborman 		else if (tmp_tc.c_cc[VEOL2] == (cc_t)(_POSIX_VDISABLE))
62746808Sdab 		    tmp_tc.c_cc[VEOL2] = esc;
62845233Sborman # endif
62945233Sborman 	}
63040245Sborman #else
63145233Sborman 	if (tc.t_brkc == (cc_t)(_POSIX_VDISABLE))
63246808Sdab 		tc.t_brkc = esc;
63340245Sborman #endif
63438689Sborman     } else {
63545233Sborman #ifdef	SIGINFO
63645233Sborman 	SIG_FUNC_RET ayt_status();
63745233Sborman 
63845233Sborman 	(void) signal(SIGINFO, ayt_status);
63945233Sborman #endif	SIGINFO
64039529Sborman #ifdef	SIGTSTP
64138689Sborman 	(void) signal(SIGTSTP, SIG_DFL);
64244361Sborman 	(void) sigsetmask(sigblock(0) & ~(1<<(SIGTSTP-1)));
64339529Sborman #endif	/* SIGTSTP */
64439529Sborman #ifndef USE_TERMIO
64539529Sborman 	ltc = oltc;
64639529Sborman 	tc = otc;
64739529Sborman 	sb = ottyb;
64844361Sborman 	lmode = olmode;
64944361Sborman #else
65044361Sborman 	tmp_tc = old_tc;
65139529Sborman #endif
65238689Sborman     }
65339529Sborman #ifndef USE_TERMIO
65439529Sborman     ioctl(tin, TIOCLSET, (char *)&lmode);
65539529Sborman     ioctl(tin, TIOCSLTC, (char *)&ltc);
65639529Sborman     ioctl(tin, TIOCSETC, (char *)&tc);
65745233Sborman     ioctl(tin, TIOCSETN, (char *)&sb);
65839529Sborman #else
65945233Sborman     if (tcsetattr(tin, TCSADRAIN, &tmp_tc) < 0)
66045233Sborman 	tcsetattr(tin, TCSANOW, &tmp_tc);
66139529Sborman #endif
66239529Sborman 
66332147Sminshall #if	(!defined(TN3270)) || ((!defined(NOT43)) || defined(PUTCHAR))
664*57213Sdab # if	!defined(sysV88)
66533286Sminshall     ioctl(tin, FIONBIO, (char *)&onoff);
66633286Sminshall     ioctl(tout, FIONBIO, (char *)&onoff);
667*57213Sdab # endif
66832147Sminshall #endif	/* (!defined(TN3270)) || ((!defined(NOT43)) || defined(PUTCHAR)) */
66932147Sminshall #if	defined(TN3270)
67036242Sminshall     if (noasynchtty == 0) {
67133286Sminshall 	ioctl(tin, FIOASYNC, (char *)&onoff);
67232147Sminshall     }
67332147Sminshall #endif	/* defined(TN3270) */
67446808Sdab 
67532147Sminshall }
67632147Sminshall 
67739529Sborman #ifndef	B19200
67839529Sborman # define B19200 B9600
67939529Sborman #endif
68039529Sborman 
68139529Sborman #ifndef	B38400
68239529Sborman # define B38400 B19200
68339529Sborman #endif
68439529Sborman 
68539529Sborman /*
68639529Sborman  * This code assumes that the values B0, B50, B75...
68739529Sborman  * are in ascending order.  They do not have to be
68839529Sborman  * contiguous.
68939529Sborman  */
69039529Sborman struct termspeeds {
69139529Sborman 	long speed;
69239529Sborman 	long value;
69339529Sborman } termspeeds[] = {
69439529Sborman 	{ 0,     B0 },     { 50,    B50 },   { 75,    B75 },
69539529Sborman 	{ 110,   B110 },   { 134,   B134 },  { 150,   B150 },
69639529Sborman 	{ 200,   B200 },   { 300,   B300 },  { 600,   B600 },
69739529Sborman 	{ 1200,  B1200 },  { 1800,  B1800 }, { 2400,  B2400 },
69839529Sborman 	{ 4800,  B4800 },  { 9600,  B9600 }, { 19200, B19200 },
69939529Sborman 	{ 38400, B38400 }, { -1,    B38400 }
70039529Sborman };
70139529Sborman 
70246808Sdab     void
70337219Sminshall TerminalSpeeds(ispeed, ospeed)
70446808Sdab     long *ispeed;
70546808Sdab     long *ospeed;
70637219Sminshall {
70739529Sborman     register struct termspeeds *tp;
70845233Sborman     register long in, out;
70932147Sminshall 
71046808Sdab     out = cfgetospeed(&old_tc);
71145233Sborman     in = cfgetispeed(&old_tc);
71246808Sdab     if (in == 0)
71346808Sdab 	in = out;
71445233Sborman 
71539529Sborman     tp = termspeeds;
71645233Sborman     while ((tp->speed != -1) && (tp->value < in))
71739529Sborman 	tp++;
71839529Sborman     *ispeed = tp->speed;
71939529Sborman 
72039529Sborman     tp = termspeeds;
72145233Sborman     while ((tp->speed != -1) && (tp->value < out))
72239529Sborman 	tp++;
72339529Sborman     *ospeed = tp->speed;
72437219Sminshall }
72537219Sminshall 
72646808Sdab     int
72737219Sminshall TerminalWindowSize(rows, cols)
72846808Sdab     long *rows, *cols;
72937219Sminshall {
73038689Sborman #ifdef	TIOCGWINSZ
73137219Sminshall     struct winsize ws;
73237219Sminshall 
73338689Sborman     if (ioctl(fileno(stdin), TIOCGWINSZ, (char *)&ws) >= 0) {
73438689Sborman 	*rows = ws.ws_row;
73538689Sborman 	*cols = ws.ws_col;
73638689Sborman 	return 1;
73737219Sminshall     }
73838810Sborman #endif	/* TIOCGWINSZ */
73938689Sborman     return 0;
74037219Sminshall }
74137219Sminshall 
74246808Sdab     int
74335417Sminshall NetClose(fd)
74446808Sdab     int	fd;
74532147Sminshall {
74635417Sminshall     return close(fd);
74732147Sminshall }
74832147Sminshall 
74932147Sminshall 
75046808Sdab     void
75132553Sminshall NetNonblockingIO(fd, onoff)
75246808Sdab     int fd;
75346808Sdab     int onoff;
75432147Sminshall {
75532147Sminshall     ioctl(fd, FIONBIO, (char *)&onoff);
75632147Sminshall }
75732147Sminshall 
75834849Sminshall #if	defined(TN3270)
75946808Sdab     void
76032553Sminshall NetSigIO(fd, onoff)
76146808Sdab     int fd;
76246808Sdab     int onoff;
76332147Sminshall {
76432147Sminshall     ioctl(fd, FIOASYNC, (char *)&onoff);	/* hear about input */
76532147Sminshall }
76632147Sminshall 
76746808Sdab     void
76832553Sminshall NetSetPgrp(fd)
76946808Sdab     int fd;
77032147Sminshall {
77132147Sminshall     int myPid;
77232147Sminshall 
77332147Sminshall     myPid = getpid();
77436274Sminshall     fcntl(fd, F_SETOWN, myPid);
77532147Sminshall }
77634849Sminshall #endif	/*defined(TN3270)*/
77732553Sminshall 
77832553Sminshall /*
77932553Sminshall  * Various signal handling routines.
78032553Sminshall  */
78132147Sminshall 
78246808Sdab     /* ARGSUSED */
78346808Sdab     static SIG_FUNC_RET
78445233Sborman deadpeer(sig)
78546808Sdab     int sig;
78632553Sminshall {
78732553Sminshall 	setcommandmode();
78832553Sminshall 	longjmp(peerdied, -1);
78932553Sminshall }
79032147Sminshall 
79146808Sdab     /* ARGSUSED */
79246808Sdab     static SIG_FUNC_RET
79345233Sborman intr(sig)
79446808Sdab     int sig;
79532553Sminshall {
79632553Sminshall     if (localchars) {
79732553Sminshall 	intp();
79832553Sminshall 	return;
79932553Sminshall     }
80032553Sminshall     setcommandmode();
80132553Sminshall     longjmp(toplevel, -1);
80232553Sminshall }
80332553Sminshall 
80446808Sdab     /* ARGSUSED */
80546808Sdab     static SIG_FUNC_RET
80645233Sborman intr2(sig)
80746808Sdab     int sig;
80832553Sminshall {
80932553Sminshall     if (localchars) {
81038689Sborman #ifdef	KLUDGELINEMODE
81138689Sborman 	if (kludgelinemode)
81238689Sborman 	    sendbrk();
81338689Sborman 	else
81438689Sborman #endif
81538689Sborman 	    sendabort();
81632553Sminshall 	return;
81732553Sminshall     }
81832553Sminshall }
81932553Sminshall 
82045233Sborman #ifdef	SIGTSTP
82146808Sdab     /* ARGSUSED */
82246808Sdab     static SIG_FUNC_RET
82345233Sborman susp(sig)
82446808Sdab     int sig;
82540245Sborman {
82646808Sdab     if ((rlogin != _POSIX_VDISABLE) && rlogin_susp())
82746808Sdab 	return;
82840245Sborman     if (localchars)
82940245Sborman 	sendsusp();
83040245Sborman }
83145233Sborman #endif
83240245Sborman 
83345233Sborman #ifdef	SIGWINCH
83446808Sdab     /* ARGSUSED */
83546808Sdab     static SIG_FUNC_RET
83645233Sborman sendwin(sig)
83746808Sdab     int sig;
83837219Sminshall {
83937219Sminshall     if (connected) {
84037219Sminshall 	sendnaws();
84137219Sminshall     }
84237219Sminshall }
84345233Sborman #endif
84437219Sminshall 
84545233Sborman #ifdef	SIGINFO
84646808Sdab     /* ARGSUSED */
84746808Sdab     static SIG_FUNC_RET
84845233Sborman ayt(sig)
84946808Sdab     int sig;
85045233Sborman {
85145233Sborman     if (connected)
85245233Sborman 	sendayt();
85345233Sborman     else
85445233Sborman 	ayt_status();
85545233Sborman }
85645233Sborman #endif
85745233Sborman 
85832553Sminshall 
85946808Sdab     void
86032531Sminshall sys_telnet_init()
86132531Sminshall {
86245233Sborman     (void) signal(SIGINT, intr);
86345233Sborman     (void) signal(SIGQUIT, intr2);
86445233Sborman     (void) signal(SIGPIPE, deadpeer);
86538689Sborman #ifdef	SIGWINCH
86645233Sborman     (void) signal(SIGWINCH, sendwin);
86738689Sborman #endif
86840245Sborman #ifdef	SIGTSTP
86945233Sborman     (void) signal(SIGTSTP, susp);
87040245Sborman #endif
87145233Sborman #ifdef	SIGINFO
87245233Sborman     (void) signal(SIGINFO, ayt);
87345233Sborman #endif
87432553Sminshall 
87538689Sborman     setconnmode(0);
87632531Sminshall 
87732531Sminshall     NetNonblockingIO(net, 1);
87832531Sminshall 
87932531Sminshall #if	defined(TN3270)
88036242Sminshall     if (noasynchnet == 0) {			/* DBX can't handle! */
88132531Sminshall 	NetSigIO(net, 1);
88232531Sminshall 	NetSetPgrp(net);
88332531Sminshall     }
88432531Sminshall #endif	/* defined(TN3270) */
88532531Sminshall 
88632531Sminshall #if	defined(SO_OOBINLINE)
88734849Sminshall     if (SetSockOpt(net, SOL_SOCKET, SO_OOBINLINE, 1) == -1) {
88834849Sminshall 	perror("SetSockOpt");
88934849Sminshall     }
89032531Sminshall #endif	/* defined(SO_OOBINLINE) */
89132531Sminshall }
89232531Sminshall 
89332531Sminshall /*
89432531Sminshall  * Process rings -
89532531Sminshall  *
89632531Sminshall  *	This routine tries to fill up/empty our various rings.
89732531Sminshall  *
89832531Sminshall  *	The parameter specifies whether this is a poll operation,
89932531Sminshall  *	or a block-until-something-happens operation.
90032531Sminshall  *
90132531Sminshall  *	The return value is 1 if something happened, 0 if not.
90232531Sminshall  */
90332531Sminshall 
90446808Sdab     int
90532531Sminshall process_rings(netin, netout, netex, ttyin, ttyout, poll)
90646808Sdab     int poll;		/* If 0, then block until something to do */
90732531Sminshall {
90832531Sminshall     register int c;
90932531Sminshall 		/* One wants to be a bit careful about setting returnValue
91032531Sminshall 		 * to one, since a one implies we did some useful work,
91132531Sminshall 		 * and therefore probably won't be called to block next
91232531Sminshall 		 * time (TN3270 mode only).
91332531Sminshall 		 */
91432531Sminshall     int returnValue = 0;
91532531Sminshall     static struct timeval TimeValue = { 0 };
91632531Sminshall 
91732531Sminshall     if (netout) {
91832531Sminshall 	FD_SET(net, &obits);
91932531Sminshall     }
92032531Sminshall     if (ttyout) {
92132531Sminshall 	FD_SET(tout, &obits);
92232531Sminshall     }
92332531Sminshall #if	defined(TN3270)
92432531Sminshall     if (ttyin) {
92532531Sminshall 	FD_SET(tin, &ibits);
92632531Sminshall     }
92732531Sminshall #else	/* defined(TN3270) */
92832531Sminshall     if (ttyin) {
92932531Sminshall 	FD_SET(tin, &ibits);
93032531Sminshall     }
93132531Sminshall #endif	/* defined(TN3270) */
93232531Sminshall #if	defined(TN3270)
93332531Sminshall     if (netin) {
93432531Sminshall 	FD_SET(net, &ibits);
93532531Sminshall     }
93632531Sminshall #   else /* !defined(TN3270) */
93732531Sminshall     if (netin) {
93832531Sminshall 	FD_SET(net, &ibits);
93932531Sminshall     }
94032531Sminshall #   endif /* !defined(TN3270) */
94132531Sminshall     if (netex) {
94232531Sminshall 	FD_SET(net, &xbits);
94332531Sminshall     }
94432531Sminshall     if ((c = select(16, &ibits, &obits, &xbits,
94532531Sminshall 			(poll == 0)? (struct timeval *)0 : &TimeValue)) < 0) {
94632531Sminshall 	if (c == -1) {
94732531Sminshall 		    /*
94832531Sminshall 		     * we can get EINTR if we are in line mode,
94932531Sminshall 		     * and the user does an escape (TSTP), or
95032531Sminshall 		     * some other signal generator.
95132531Sminshall 		     */
95232531Sminshall 	    if (errno == EINTR) {
95332531Sminshall 		return 0;
95432531Sminshall 	    }
95532531Sminshall #	    if defined(TN3270)
95632531Sminshall 		    /*
95732531Sminshall 		     * we can get EBADF if we were in transparent
95832531Sminshall 		     * mode, and the transcom process died.
95932531Sminshall 		    */
96032531Sminshall 	    if (errno == EBADF) {
96132531Sminshall 			/*
96232531Sminshall 			 * zero the bits (even though kernel does it)
96332531Sminshall 			 * to make sure we are selecting on the right
96432531Sminshall 			 * ones.
96532531Sminshall 			*/
96632531Sminshall 		FD_ZERO(&ibits);
96732531Sminshall 		FD_ZERO(&obits);
96832531Sminshall 		FD_ZERO(&xbits);
96932531Sminshall 		return 0;
97032531Sminshall 	    }
97132531Sminshall #	    endif /* defined(TN3270) */
97232531Sminshall 		    /* I don't like this, does it ever happen? */
97332531Sminshall 	    printf("sleep(5) from telnet, after select\r\n");
97432531Sminshall 	    sleep(5);
97532531Sminshall 	}
97632531Sminshall 	return 0;
97732531Sminshall     }
97832531Sminshall 
97932531Sminshall     /*
98032531Sminshall      * Any urgent data?
98132531Sminshall      */
98232531Sminshall     if (FD_ISSET(net, &xbits)) {
98332531Sminshall 	FD_CLR(net, &xbits);
98432531Sminshall 	SYNCHing = 1;
98544361Sborman 	(void) ttyflush(1);	/* flush already enqueued data */
98632531Sminshall     }
98732531Sminshall 
98832531Sminshall     /*
98932531Sminshall      * Something to read from the network...
99032531Sminshall      */
99132531Sminshall     if (FD_ISSET(net, &ibits)) {
99232531Sminshall 	int canread;
99332531Sminshall 
99432531Sminshall 	FD_CLR(net, &ibits);
99532531Sminshall 	canread = ring_empty_consecutive(&netiring);
99632531Sminshall #if	!defined(SO_OOBINLINE)
99732531Sminshall 	    /*
99832531Sminshall 	     * In 4.2 (and some early 4.3) systems, the
99932531Sminshall 	     * OOB indication and data handling in the kernel
100032531Sminshall 	     * is such that if two separate TCP Urgent requests
100132531Sminshall 	     * come in, one byte of TCP data will be overlaid.
100232531Sminshall 	     * This is fatal for Telnet, but we try to live
100332531Sminshall 	     * with it.
100432531Sminshall 	     *
100532531Sminshall 	     * In addition, in 4.2 (and...), a special protocol
100632531Sminshall 	     * is needed to pick up the TCP Urgent data in
100732531Sminshall 	     * the correct sequence.
100832531Sminshall 	     *
100932531Sminshall 	     * What we do is:  if we think we are in urgent
101032531Sminshall 	     * mode, we look to see if we are "at the mark".
101132531Sminshall 	     * If we are, we do an OOB receive.  If we run
101232531Sminshall 	     * this twice, we will do the OOB receive twice,
101332531Sminshall 	     * but the second will fail, since the second
101432531Sminshall 	     * time we were "at the mark", but there wasn't
101532531Sminshall 	     * any data there (the kernel doesn't reset
101632531Sminshall 	     * "at the mark" until we do a normal read).
101732531Sminshall 	     * Once we've read the OOB data, we go ahead
101832531Sminshall 	     * and do normal reads.
101932531Sminshall 	     *
102032531Sminshall 	     * There is also another problem, which is that
102132531Sminshall 	     * since the OOB byte we read doesn't put us
102232531Sminshall 	     * out of OOB state, and since that byte is most
102332531Sminshall 	     * likely the TELNET DM (data mark), we would
102432531Sminshall 	     * stay in the TELNET SYNCH (SYNCHing) state.
102532531Sminshall 	     * So, clocks to the rescue.  If we've "just"
102632531Sminshall 	     * received a DM, then we test for the
102732531Sminshall 	     * presence of OOB data when the receive OOB
102832531Sminshall 	     * fails (and AFTER we did the normal mode read
102932531Sminshall 	     * to clear "at the mark").
103032531Sminshall 	     */
103132531Sminshall 	if (SYNCHing) {
103232531Sminshall 	    int atmark;
103339652Sborman 	    static int bogus_oob = 0, first = 1;
103432531Sminshall 
103532531Sminshall 	    ioctl(net, SIOCATMARK, (char *)&atmark);
103632531Sminshall 	    if (atmark) {
103732531Sminshall 		c = recv(net, netiring.supply, canread, MSG_OOB);
103832531Sminshall 		if ((c == -1) && (errno == EINVAL)) {
103932531Sminshall 		    c = recv(net, netiring.supply, canread, 0);
104032531Sminshall 		    if (clocks.didnetreceive < clocks.gotDM) {
104132531Sminshall 			SYNCHing = stilloob(net);
104232531Sminshall 		    }
104339652Sborman 		} else if (first && c > 0) {
104439652Sborman 		    /*
104539652Sborman 		     * Bogosity check.  Systems based on 4.2BSD
104639652Sborman 		     * do not return an error if you do a second
104739652Sborman 		     * recv(MSG_OOB).  So, we do one.  If it
104839652Sborman 		     * succeeds and returns exactly the same
104939652Sborman 		     * data, then assume that we are running
105039652Sborman 		     * on a broken system and set the bogus_oob
105139652Sborman 		     * flag.  (If the data was different, then
105239652Sborman 		     * we probably got some valid new data, so
105339652Sborman 		     * increment the count...)
105439652Sborman 		     */
105539652Sborman 		    int i;
105639652Sborman 		    i = recv(net, netiring.supply + c, canread - c, MSG_OOB);
105739652Sborman 		    if (i == c &&
105839652Sborman 			  bcmp(netiring.supply, netiring.supply + c, i) == 0) {
105939652Sborman 			bogus_oob = 1;
106039652Sborman 			first = 0;
106139652Sborman 		    } else if (i < 0) {
106239652Sborman 			bogus_oob = 0;
106339652Sborman 			first = 0;
106439652Sborman 		    } else
106539652Sborman 			c += i;
106632531Sminshall 		}
106739652Sborman 		if (bogus_oob && c > 0) {
106839652Sborman 		    int i;
106939652Sborman 		    /*
107039652Sborman 		     * Bogosity.  We have to do the read
107139652Sborman 		     * to clear the atmark to get out of
107239652Sborman 		     * an infinate loop.
107339652Sborman 		     */
107439652Sborman 		    i = read(net, netiring.supply + c, canread - c);
107539652Sborman 		    if (i > 0)
107639652Sborman 			c += i;
107739652Sborman 		}
107832531Sminshall 	    } else {
107932531Sminshall 		c = recv(net, netiring.supply, canread, 0);
108032531Sminshall 	    }
108132531Sminshall 	} else {
108232531Sminshall 	    c = recv(net, netiring.supply, canread, 0);
108332531Sminshall 	}
108432531Sminshall 	settimer(didnetreceive);
108532531Sminshall #else	/* !defined(SO_OOBINLINE) */
108632531Sminshall 	c = recv(net, netiring.supply, canread, 0);
108732531Sminshall #endif	/* !defined(SO_OOBINLINE) */
108832531Sminshall 	if (c < 0 && errno == EWOULDBLOCK) {
108932531Sminshall 	    c = 0;
109032531Sminshall 	} else if (c <= 0) {
109132531Sminshall 	    return -1;
109232531Sminshall 	}
109332531Sminshall 	if (netdata) {
109432531Sminshall 	    Dump('<', netiring.supply, c);
109532531Sminshall 	}
109632667Sminshall 	if (c)
109732667Sminshall 	    ring_supplied(&netiring, c);
109832531Sminshall 	returnValue = 1;
109932531Sminshall     }
110032531Sminshall 
110132531Sminshall     /*
110232531Sminshall      * Something to read from the tty...
110332531Sminshall      */
110432531Sminshall     if (FD_ISSET(tin, &ibits)) {
110532531Sminshall 	FD_CLR(tin, &ibits);
110633286Sminshall 	c = TerminalRead(ttyiring.supply, ring_empty_consecutive(&ttyiring));
110732531Sminshall 	if (c < 0 && errno == EWOULDBLOCK) {
110832531Sminshall 	    c = 0;
110932531Sminshall 	} else {
111032531Sminshall 	    /* EOF detection for line mode!!!! */
111133281Sminshall 	    if ((c == 0) && MODE_LOCAL_CHARS(globalmode) && isatty(tin)) {
111232531Sminshall 			/* must be an EOF... */
111332531Sminshall 		*ttyiring.supply = termEofChar;
111432531Sminshall 		c = 1;
111532531Sminshall 	    }
111632531Sminshall 	    if (c <= 0) {
111732531Sminshall 		return -1;
111832531Sminshall 	    }
111938208Sminshall 	    if (termdata) {
112038208Sminshall 		Dump('<', ttyiring.supply, c);
112138208Sminshall 	    }
112232667Sminshall 	    ring_supplied(&ttyiring, c);
112332531Sminshall 	}
112432531Sminshall 	returnValue = 1;		/* did something useful */
112532531Sminshall     }
112632531Sminshall 
112732531Sminshall     if (FD_ISSET(net, &obits)) {
112832531Sminshall 	FD_CLR(net, &obits);
112932531Sminshall 	returnValue |= netflush();
113032531Sminshall     }
113132531Sminshall     if (FD_ISSET(tout, &obits)) {
113232531Sminshall 	FD_CLR(tout, &obits);
113338689Sborman 	returnValue |= (ttyflush(SYNCHing|flushout) > 0);
113432531Sminshall     }
113532531Sminshall 
113632531Sminshall     return returnValue;
113732531Sminshall }
1138