xref: /csrg-svn/usr.bin/telnet/sys_bsd.c (revision 45233)
132147Sminshall /*
2*45233Sborman  * 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*45233Sborman static char sccsid[] = "@(#)sys_bsd.c	5.1 (Berkeley) 09/14/90";
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 
34*45233Sborman #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;
50*45233Sborman # define cfgetispeed(ptr)	(ptr)->sg_ispeed
51*45233Sborman # define cfgetospeed(ptr)	(ptr)->sg_ospeed
52*45233Sborman # define old_tc ottyb
5332147Sminshall 
5438689Sborman #else	/* USE_TERMIO */
5538689Sborman struct	termio old_tc = { 0 };
5638689Sborman extern struct termio new_tc;
5738689Sborman 
58*45233Sborman # ifndef	TCSANOW
59*45233Sborman #  ifdef TCSETS
60*45233Sborman #   define	TCSANOW		TCSETS
61*45233Sborman #   define	TCSADRAIN	TCSETSW
62*45233Sborman #   define	tcgetattr(f, t) ioctl(f, TCGETS, t)
63*45233Sborman #  else
64*45233Sborman #   ifdef TCSETA
65*45233Sborman #    define	TCSANOW		TCSETA
66*45233Sborman #    define	TCSADRAIN	TCSETAW
67*45233Sborman #    define	tcgetattr(f, t) ioctl(f, TCGETA, t)
68*45233Sborman #   else
69*45233Sborman #    define	TCSANOW		TIOCSETA
70*45233Sborman #    define	TCSADRAIN	TIOCSETAW
71*45233Sborman #    define	tcgetattr(f, t) ioctl(f, TIOCGETA, t)
72*45233Sborman #   endif
73*45233Sborman #  endif
74*45233Sborman #  define	tcsetattr(f, a, t) ioctl(f, a, t)
75*45233Sborman #  define	cfgetospeed(ptr)	((ptr)->c_cflag&CBAUD)
76*45233Sborman #  ifdef CIBAUD
77*45233Sborman #   define	cfgetispeed(ptr)	(((ptr)->c_cflag&CIBAUD) >> IBSHIFT)
78*45233Sborman #  else
79*45233Sborman #   define	cfgetispeed(ptr)	cfgetospeed(ptr)
80*45233Sborman #  endif
81*45233Sborman # endif /* TCSANOW */
8238689Sborman #endif	/* USE_TERMIO */
8338689Sborman 
8432531Sminshall static fd_set ibits, obits, xbits;
8532147Sminshall 
8632531Sminshall 
8732531Sminshall init_sys()
8832531Sminshall {
8932531Sminshall     tout = fileno(stdout);
9032531Sminshall     tin = fileno(stdin);
9132531Sminshall     FD_ZERO(&ibits);
9232531Sminshall     FD_ZERO(&obits);
9332531Sminshall     FD_ZERO(&xbits);
9432531Sminshall 
9532531Sminshall     errno = 0;
9632531Sminshall }
9732531Sminshall 
9832531Sminshall 
9933286Sminshall TerminalWrite(buf, n)
10032147Sminshall char	*buf;
10132147Sminshall int	n;
10232147Sminshall {
10333286Sminshall     return write(tout, buf, n);
10432147Sminshall }
10532147Sminshall 
10633286Sminshall TerminalRead(buf, n)
10732147Sminshall char	*buf;
10832147Sminshall int	n;
10932147Sminshall {
11033286Sminshall     return read(tin, buf, n);
11132147Sminshall }
11232147Sminshall 
11332147Sminshall /*
11432147Sminshall  *
11532147Sminshall  */
11632147Sminshall 
11732147Sminshall int
11832553Sminshall TerminalAutoFlush()
11932147Sminshall {
12032147Sminshall #if	defined(LNOFLSH)
12132147Sminshall     int flush;
12232147Sminshall 
12332147Sminshall     ioctl(0, TIOCLGET, (char *)&flush);
12432147Sminshall     return !(flush&LNOFLSH);	/* if LNOFLSH, no autoflush */
12532147Sminshall #else	/* LNOFLSH */
12632147Sminshall     return 1;
12732147Sminshall #endif	/* LNOFLSH */
12832147Sminshall }
12932147Sminshall 
13038689Sborman #ifdef	KLUDGELINEMODE
13138689Sborman extern int kludgelinemode;
13238689Sborman #endif
13332147Sminshall /*
13432147Sminshall  * TerminalSpecialChars()
13532147Sminshall  *
13632147Sminshall  * Look at an input character to see if it is a special character
13732147Sminshall  * and decide what to do.
13832147Sminshall  *
13932147Sminshall  * Output:
14032147Sminshall  *
14132147Sminshall  *	0	Don't add this character.
14232147Sminshall  *	1	Do add this character
14332147Sminshall  */
14432147Sminshall 
14532147Sminshall int
14632553Sminshall TerminalSpecialChars(c)
14732147Sminshall int	c;
14832147Sminshall {
14932553Sminshall     void xmitAO(), xmitEL(), xmitEC(), intp(), sendbrk();
15032147Sminshall 
15138689Sborman     if (c == termIntChar) {
15232147Sminshall 	intp();
15332147Sminshall 	return 0;
15438689Sborman     } else if (c == termQuitChar) {
15538689Sborman #ifdef	KLUDGELINEMODE
15638689Sborman 	if (kludgelinemode)
15738689Sborman 	    sendbrk();
15838689Sborman 	else
15938689Sborman #endif
16038689Sborman 	    sendabort();
16132147Sminshall 	return 0;
16238689Sborman     } else if (c == termEofChar) {
16338689Sborman 	if (my_want_state_is_will(TELOPT_LINEMODE)) {
16438689Sborman 	    sendeof();
16538689Sborman 	    return 0;
16638689Sborman 	}
16738689Sborman 	return 1;
16838689Sborman     } else if (c == termSuspChar) {
16938689Sborman 	sendsusp();
17038689Sborman 	return(0);
17138689Sborman     } else if (c == termFlushChar) {
17232147Sminshall 	xmitAO();		/* Transmit Abort Output */
17332147Sminshall 	return 0;
17432147Sminshall     } else if (!MODE_LOCAL_CHARS(globalmode)) {
17538689Sborman 	if (c == termKillChar) {
17632147Sminshall 	    xmitEL();
17732147Sminshall 	    return 0;
17838689Sborman 	} else if (c == termEraseChar) {
17932147Sminshall 	    xmitEC();		/* Transmit Erase Character */
18032147Sminshall 	    return 0;
18132147Sminshall 	}
18232147Sminshall     }
18332147Sminshall     return 1;
18432147Sminshall }
18532147Sminshall 
18632147Sminshall 
18732147Sminshall /*
18832147Sminshall  * Flush output to the terminal
18932147Sminshall  */
19032147Sminshall 
19132147Sminshall void
19232553Sminshall TerminalFlushOutput()
19332147Sminshall {
19439529Sborman #ifdef	TIOCFLUSH
19532147Sminshall     (void) ioctl(fileno(stdout), TIOCFLUSH, (char *) 0);
19638689Sborman #else
19738689Sborman     (void) ioctl(fileno(stdout), TCFLSH, (char *) 0);
19838689Sborman #endif
19932147Sminshall }
20032147Sminshall 
20132147Sminshall void
20232553Sminshall TerminalSaveState()
20332147Sminshall {
20438689Sborman #ifndef	USE_TERMIO
20532147Sminshall     ioctl(0, TIOCGETP, (char *)&ottyb);
20632147Sminshall     ioctl(0, TIOCGETC, (char *)&otc);
20732147Sminshall     ioctl(0, TIOCGLTC, (char *)&oltc);
20838909Sborman     ioctl(0, TIOCLGET, (char *)&olmode);
20932147Sminshall 
21032147Sminshall     ntc = otc;
21132147Sminshall     nltc = oltc;
21232147Sminshall     nttyb = ottyb;
21332254Sminshall 
21438689Sborman #else	/* USE_TERMIO */
215*45233Sborman     tcgetattr(0, &old_tc);
21638689Sborman 
21738689Sborman     new_tc = old_tc;
21838689Sborman 
219*45233Sborman #ifndef	VDISCARD
22044361Sborman     termFlushChar = CONTROL('O');
221*45233Sborman #endif
222*45233Sborman #ifndef	VWERASE
22344361Sborman     termWerasChar = CONTROL('W');
224*45233Sborman #endif
225*45233Sborman #ifndef	VREPRINT
22644361Sborman     termRprntChar = CONTROL('R');
227*45233Sborman #endif
228*45233Sborman #ifndef	VLNEXT
22944361Sborman     termLiteralNextChar = CONTROL('V');
230*45233Sborman #endif
231*45233Sborman #ifndef	VSTART
23244361Sborman     termStartChar = CONTROL('Q');
233*45233Sborman #endif
234*45233Sborman #ifndef	VSTOP
23544361Sborman     termStopChar = CONTROL('S');
236*45233Sborman #endif
237*45233Sborman #ifndef	VSTATUS
238*45233Sborman     termAytChar = CONTROL('T');
239*45233Sborman #endif
24038689Sborman #endif	/* USE_TERMIO */
24132147Sminshall }
24232147Sminshall 
24340245Sborman cc_t *
24438689Sborman tcval(func)
24538689Sborman register int func;
24638689Sborman {
24738689Sborman     switch(func) {
24840245Sborman     case SLC_IP:	return(&termIntChar);
24940245Sborman     case SLC_ABORT:	return(&termQuitChar);
25040245Sborman     case SLC_EOF:	return(&termEofChar);
25140245Sborman     case SLC_EC:	return(&termEraseChar);
25240245Sborman     case SLC_EL:	return(&termKillChar);
25340245Sborman     case SLC_XON:	return(&termStartChar);
25440245Sborman     case SLC_XOFF:	return(&termStopChar);
25544361Sborman     case SLC_FORW1:	return(&termForw1Char);
256*45233Sborman #ifdef	USE_TERMIO
257*45233Sborman     case SLC_FORW2:	return(&termForw2Char);
258*45233Sborman # ifdef	VDISCARD
25940245Sborman     case SLC_AO:	return(&termFlushChar);
260*45233Sborman # endif
261*45233Sborman # ifdef	VSUSP
26240245Sborman     case SLC_SUSP:	return(&termSuspChar);
263*45233Sborman # endif
264*45233Sborman # ifdef	VWERASE
26540245Sborman     case SLC_EW:	return(&termWerasChar);
266*45233Sborman # endif
267*45233Sborman # ifdef	VREPRINT
26840245Sborman     case SLC_RP:	return(&termRprntChar);
269*45233Sborman # endif
270*45233Sborman # ifdef	VLNEXT
27140245Sborman     case SLC_LNEXT:	return(&termLiteralNextChar);
272*45233Sborman # endif
273*45233Sborman # ifdef	VSTATUS
274*45233Sborman     case SLC_AYT:	return(&termAytChar);
275*45233Sborman # endif
27644361Sborman #endif
27738689Sborman 
27838689Sborman     case SLC_SYNCH:
27938689Sborman     case SLC_BRK:
28038689Sborman     case SLC_EOR:
28138689Sborman     default:
28240245Sborman 	return((cc_t *)0);
28338689Sborman     }
28438689Sborman }
28538689Sborman 
28632147Sminshall void
28738689Sborman TerminalDefaultChars()
28838689Sborman {
28938689Sborman #ifndef	USE_TERMIO
29038689Sborman     ntc = otc;
29138689Sborman     nltc = oltc;
29238689Sborman     nttyb.sg_kill = ottyb.sg_kill;
29338689Sborman     nttyb.sg_erase = ottyb.sg_erase;
29438689Sborman #else	/* USE_TERMIO */
29538689Sborman     memcpy(new_tc.c_cc, old_tc.c_cc, sizeof(old_tc.c_cc));
296*45233Sborman # ifndef	VDISCARD
29744361Sborman     termFlushChar = CONTROL('O');
29839529Sborman # endif
29939529Sborman # ifndef	VWERASE
30044361Sborman     termWerasChar = CONTROL('W');
30139529Sborman # endif
30239529Sborman # ifndef	VREPRINT
30344361Sborman     termRprntChar = CONTROL('R');
30439529Sborman # endif
30539529Sborman # ifndef	VLNEXT
30644361Sborman     termLiteralNextChar = CONTROL('V');
30739529Sborman # endif
30839529Sborman # ifndef	VSTART
30944361Sborman     termStartChar = CONTROL('Q');
31039529Sborman # endif
31139529Sborman # ifndef	VSTOP
31244361Sborman     termStopChar = CONTROL('S');
31339529Sborman # endif
314*45233Sborman # ifndef	VSTATUS
315*45233Sborman     termAytChar = CONTROL('T');
316*45233Sborman # endif
31738689Sborman #endif	/* USE_TERMIO */
31838689Sborman }
31938689Sborman 
32044361Sborman #ifdef notdef
32138689Sborman void
32232553Sminshall TerminalRestoreState()
32332147Sminshall {
32432147Sminshall }
32544361Sborman #endif
32632147Sminshall 
32732147Sminshall /*
32832147Sminshall  * TerminalNewMode - set up terminal to a specific mode.
32938689Sborman  *	MODE_ECHO: do local terminal echo
33038689Sborman  *	MODE_FLOW: do local flow control
33138689Sborman  *	MODE_TRAPSIG: do local mapping to TELNET IAC sequences
33238689Sborman  *	MODE_EDIT: do local line editing
33338689Sborman  *
33438689Sborman  *	Command mode:
33538689Sborman  *		MODE_ECHO|MODE_EDIT|MODE_FLOW|MODE_TRAPSIG
33638689Sborman  *		local echo
33738689Sborman  *		local editing
33838689Sborman  *		local xon/xoff
33938689Sborman  *		local signal mapping
34038689Sborman  *
34138689Sborman  *	Linemode:
34238689Sborman  *		local/no editing
34338689Sborman  *	Both Linemode and Single Character mode:
34438689Sborman  *		local/remote echo
34538689Sborman  *		local/no xon/xoff
34638689Sborman  *		local/no signal mapping
34732147Sminshall  */
34832147Sminshall 
34932147Sminshall 
35032147Sminshall void
35133286Sminshall TerminalNewMode(f)
35232147Sminshall register int f;
35332147Sminshall {
35432147Sminshall     static int prevmode = 0;
35538689Sborman #ifndef	USE_TERMIO
35638689Sborman     struct tchars tc;
35738689Sborman     struct ltchars ltc;
35832147Sminshall     struct sgttyb sb;
35938909Sborman     int lmode;
36038689Sborman #else	/* USE_TERMIO */
36138689Sborman     struct termio tmp_tc;
36238689Sborman #endif	/* USE_TERMIO */
36332147Sminshall     int onoff;
36432147Sminshall     int old;
36532147Sminshall 
36638689Sborman     globalmode = f&~MODE_FORCE;
36732147Sminshall     if (prevmode == f)
36832147Sminshall 	return;
36938689Sborman 
37038689Sborman     /*
37138689Sborman      * Write any outstanding data before switching modes
37238689Sborman      * ttyflush() returns 0 only when there is no more data
37338689Sborman      * left to write out, it returns -1 if it couldn't do
37438689Sborman      * anything at all, otherwise it returns 1 + the number
37538689Sborman      * of characters left to write.
376*45233Sborman #ifndef	USE_TERMIO
377*45233Sborman      * We would really like ask the kernel to wait for the output
378*45233Sborman      * to drain, like we can do with the TCSADRAIN, but we don't have
379*45233Sborman      * that option.  The only ioctl that waits for the output to
380*45233Sborman      * drain, TIOCSETP, also flushes the input queue, which is NOT
381*45233Sborman      * what we want (TIOCSETP is like TCSADFLUSH).
382*45233Sborman #endif
38338689Sborman      */
38438689Sborman     old = ttyflush(SYNCHing|flushout);
38538689Sborman     if (old < 0 || old > 1) {
386*45233Sborman #ifdef	USE_TERMIO
387*45233Sborman 	tcgetattr(tin, (char *)&tmp_tc);
38838689Sborman #endif	/* USE_TERMIO */
38938689Sborman 	do {
39038689Sborman 	    /*
39138689Sborman 	     * Wait for data to drain, then flush again.
39238689Sborman 	     */
393*45233Sborman #ifdef	USE_TERMIO
394*45233Sborman 	    tcsetattr(tin, TCSADRAIN, (char *)&tmp_tc);
39538689Sborman #endif	/* USE_TERMIO */
39638689Sborman 	    old = ttyflush(SYNCHing|flushout);
39738689Sborman 	} while (old < 0 || old > 1);
39838689Sborman     }
39938689Sborman 
40032147Sminshall     old = prevmode;
40138689Sborman     prevmode = f&~MODE_FORCE;
40238689Sborman #ifndef	USE_TERMIO
40332147Sminshall     sb = nttyb;
40438689Sborman     tc = ntc;
40538689Sborman     ltc = nltc;
40638909Sborman     lmode = olmode;
40738689Sborman #else
40838689Sborman     tmp_tc = new_tc;
40938689Sborman #endif
41032147Sminshall 
41138689Sborman     if (f&MODE_ECHO) {
41238689Sborman #ifndef	USE_TERMIO
41338689Sborman 	sb.sg_flags |= ECHO;
41438689Sborman #else
41538689Sborman 	tmp_tc.c_lflag |= ECHO;
41638689Sborman 	tmp_tc.c_oflag |= ONLCR;
41739529Sborman # ifdef notdef
41838689Sborman 	tmp_tc.c_iflag |= ICRNL;
41939529Sborman # endif
42038689Sborman #endif
42138689Sborman     } else {
42238689Sborman #ifndef	USE_TERMIO
42338689Sborman 	sb.sg_flags &= ~ECHO;
42438689Sborman #else
42538689Sborman 	tmp_tc.c_lflag &= ~ECHO;
42638689Sborman 	tmp_tc.c_oflag &= ~ONLCR;
42739529Sborman # ifdef notdef
42838689Sborman 	tmp_tc.c_iflag &= ~ICRNL;
42939529Sborman # endif
43038689Sborman #endif
43138689Sborman     }
43232147Sminshall 
43338689Sborman     if ((f&MODE_FLOW) == 0) {
43438689Sborman #ifndef	USE_TERMIO
435*45233Sborman 	tc.t_startc = _POSIX_VDISABLE;
436*45233Sborman 	tc.t_stopc = _POSIX_VDISABLE;
43738689Sborman #else
43838689Sborman 	tmp_tc.c_iflag &= ~(IXANY|IXOFF|IXON);
43938689Sborman     } else {
44038689Sborman 	tmp_tc.c_iflag |= IXANY|IXOFF|IXON;
44138689Sborman #endif
44238689Sborman     }
44332147Sminshall 
44438689Sborman     if ((f&MODE_TRAPSIG) == 0) {
44538689Sborman #ifndef	USE_TERMIO
446*45233Sborman 	tc.t_intrc = _POSIX_VDISABLE;
447*45233Sborman 	tc.t_quitc = _POSIX_VDISABLE;
448*45233Sborman 	tc.t_eofc = _POSIX_VDISABLE;
449*45233Sborman 	ltc.t_suspc = _POSIX_VDISABLE;
450*45233Sborman 	ltc.t_dsuspc = _POSIX_VDISABLE;
45138689Sborman #else
45238689Sborman 	tmp_tc.c_lflag &= ~ISIG;
45338689Sborman #endif
45438689Sborman 	localchars = 0;
45538689Sborman     } else {
45638689Sborman #ifdef	USE_TERMIO
45738689Sborman 	tmp_tc.c_lflag |= ISIG;
45838689Sborman #endif
45938689Sborman 	localchars = 1;
46038689Sborman     }
46138689Sborman 
46238689Sborman     if (f&MODE_EDIT) {
46338689Sborman #ifndef	USE_TERMIO
46438689Sborman 	sb.sg_flags &= ~CBREAK;
46538689Sborman 	sb.sg_flags |= CRMOD;
46638689Sborman #else
46738689Sborman 	tmp_tc.c_lflag |= ICANON;
46838689Sborman #endif
46938689Sborman     } else {
47038689Sborman #ifndef	USE_TERMIO
47138689Sborman 	sb.sg_flags |= CBREAK;
47238689Sborman 	if (f&MODE_ECHO)
47332147Sminshall 	    sb.sg_flags |= CRMOD;
47438689Sborman 	else
47538689Sborman 	    sb.sg_flags &= ~CRMOD;
47638689Sborman #else
47738689Sborman 	tmp_tc.c_lflag &= ~ICANON;
47838689Sborman 	tmp_tc.c_iflag &= ~ICRNL;
47938689Sborman 	tmp_tc.c_cc[VMIN] = 1;
48038689Sborman 	tmp_tc.c_cc[VTIME] = 0;
48138689Sborman #endif
48238689Sborman     }
48332147Sminshall 
48444361Sborman     if ((f&(MODE_EDIT|MODE_TRAPSIG)) == 0) {
48544361Sborman #ifndef	USE_TERMIO
486*45233Sborman 	ltc.t_lnextc = _POSIX_VDISABLE;
48744361Sborman #else
48844361Sborman # ifdef VLNEXT
489*45233Sborman 	tmp_tc.c_cc[VLNEXT] = (cc_t)(_POSIX_VDISABLE);
49044361Sborman # endif
49144361Sborman #endif
49244361Sborman     }
49344361Sborman 
49444361Sborman     if (f&MODE_SOFT_TAB) {
49544361Sborman #ifndef USE_TERMIO
49644361Sborman 	sb.sg_flags |= XTABS;
49744361Sborman #else
49844361Sborman # ifdef	OXTABS
49944361Sborman 	tmp_tc.c_oflag |= OXTABS;
50044361Sborman # endif
50144361Sborman # ifdef	TABDLY
50244361Sborman 	tmp_tc.c_oflag &= ~TABDLY;
50344361Sborman 	tmp_tc.c_oflag |= TAB3;
50444361Sborman # endif
50544361Sborman #endif
50644361Sborman     } else {
50744361Sborman #ifndef USE_TERMIO
50844361Sborman 	sb.sg_flags &= ~XTABS;
50944361Sborman #else
51044361Sborman # ifdef	OXTABS
51144361Sborman 	tmp_tc.c_oflag &= ~OXTABS;
51244361Sborman # endif
51344361Sborman # ifdef	TABDLY
51444361Sborman 	tmp_tc.c_oflag &= ~TABDLY;
51544361Sborman # endif
51644361Sborman #endif
51744361Sborman     }
51844361Sborman 
51944361Sborman     if (f&MODE_LIT_ECHO) {
52044361Sborman #ifndef USE_TERMIO
52144361Sborman 	sb.sg_flags &= ~CTLECH;
52244361Sborman #else
52344361Sborman # ifdef	ECHOCTL
52444361Sborman 	tmp_tc.c_lflag &= ~ECHOCTL;
52544361Sborman # endif
52644361Sborman #endif
52744361Sborman     } else {
52844361Sborman #ifndef USE_TERMIO
52944361Sborman 	sb.sg_flags |= CTLECH;
53044361Sborman #else
53144361Sborman # ifdef	ECHOCTL
53244361Sborman 	tmp_tc.c_lflag |= ECHOCTL;
53344361Sborman # endif
53444361Sborman #endif
53544361Sborman     }
53644361Sborman 
53738689Sborman     if (f == -1) {
53838689Sborman 	onoff = 0;
53938689Sborman     } else {
54038909Sborman #ifndef	USE_TERMIO
54139529Sborman 	if (f & MODE_OUTBIN)
54238909Sborman 		lmode |= LLITOUT;
54338909Sborman 	else
54438909Sborman 		lmode &= ~LLITOUT;
54539529Sborman 
54639529Sborman 	if (f & MODE_INBIN)
54738909Sborman 		lmode |= LPASS8;
54838909Sborman 	else
54938909Sborman 		lmode &= ~LPASS8;
55038909Sborman #else
551*45233Sborman 	if (f & MODE_INBIN)
552*45233Sborman 		tmp_tc.c_iflag &= ~ISTRIP;
55338909Sborman 	else
554*45233Sborman 		tmp_tc.c_iflag |= ISTRIP;
555*45233Sborman 	if (f & MODE_OUTBIN) {
55639529Sborman 		tmp_tc.c_cflag &= ~(CSIZE|PARENB);
55739529Sborman 		tmp_tc.c_cflag |= CS8;
558*45233Sborman 		tmp_tc.c_oflag &= ~OPOST;
55939529Sborman 	} else {
560*45233Sborman 		tmp_tc.c_cflag &= ~(CSIZE|PARENB);
561*45233Sborman 		tmp_tc.c_cflag |= old_tc.c_cflag & (CSIZE|PARENB);
562*45233Sborman 		tmp_tc.c_oflag |= OPOST;
56339529Sborman 	}
56438909Sborman #endif
56538689Sborman 	onoff = 1;
56632147Sminshall     }
56738689Sborman 
56838689Sborman     if (f != -1) {
56939529Sborman #ifdef	SIGTSTP
570*45233Sborman 	static SIG_FUNC_RET susp();
571*45233Sborman #endif	/* SIGTSTP */
572*45233Sborman #ifdef	SIGINFO
573*45233Sborman 	static SIG_FUNC_RET ayt();
574*45233Sborman #endif	SIGINFO
57538689Sborman 
576*45233Sborman #ifdef	SIGTSTP
577*45233Sborman 	(void) signal(SIGTSTP, susp);
57839529Sborman #endif	/* SIGTSTP */
579*45233Sborman #ifdef	SIGINFO
580*45233Sborman 	(void) signal(SIGINFO, ayt);
581*45233Sborman #endif	SIGINFO
582*45233Sborman #if	defined(USE_TERMIO) && defined(NOKERNINFO)
583*45233Sborman 	tmp_tc.c_lflag |= NOKERNINFO;
584*45233Sborman #endif
58544361Sborman 	/*
58644361Sborman 	 * We don't want to process ^Y here.  It's just another
58744361Sborman 	 * character that we'll pass on to the back end.  It has
58844361Sborman 	 * to process it because it will be processed when the
58944361Sborman 	 * user attempts to read it, not when we send it.
59044361Sborman 	 */
59144361Sborman #ifndef	USE_TERMIO
592*45233Sborman 	ltc.t_dsuspc = _POSIX_VDISABLE;
59344361Sborman #else
59444361Sborman # ifdef	VDSUSP
595*45233Sborman 	tmp_tc.c_cc[VDSUSP] = (cc_t)(_POSIX_VDISABLE);
59644361Sborman # endif
59744361Sborman #endif
59840245Sborman #ifdef	USE_TERMIO
59940245Sborman 	/*
60040245Sborman 	 * If the VEOL character is already set, then use VEOL2,
60140245Sborman 	 * otherwise use VEOL.
60240245Sborman 	 */
603*45233Sborman 	if ((tmp_tc.c_cc[VEOL] != escape)
60444361Sborman # ifdef	VEOL2
605*45233Sborman 	    && (tmp_tc.c_cc[VEOL2] != escape)
60644361Sborman # endif
607*45233Sborman 	   ) {
608*45233Sborman 		if (tmp_tc.c_cc[VEOL] == (cc_t)(_POSIX_VDISABLE))
609*45233Sborman 			tmp_tc.c_cc[VEOL] = escape;
610*45233Sborman # ifdef	VEOL2
611*45233Sborman 		else if (tmp_tc.c_cc[VEOL2] == (cc_t)(_POSIX_VDISABLE))
612*45233Sborman 			tmp_tc.c_cc[VEOL2] = escape;
613*45233Sborman # endif
614*45233Sborman 	}
61540245Sborman #else
616*45233Sborman 	if (tc.t_brkc == (cc_t)(_POSIX_VDISABLE))
61744361Sborman 		tc.t_brkc = escape;
61840245Sborman #endif
61938689Sborman     } else {
620*45233Sborman #ifdef	SIGINFO
621*45233Sborman 	SIG_FUNC_RET ayt_status();
622*45233Sborman 
623*45233Sborman 	(void) signal(SIGINFO, ayt_status);
624*45233Sborman #endif	SIGINFO
62539529Sborman #ifdef	SIGTSTP
62638689Sborman 	(void) signal(SIGTSTP, SIG_DFL);
62744361Sborman 	(void) sigsetmask(sigblock(0) & ~(1<<(SIGTSTP-1)));
62839529Sborman #endif	/* SIGTSTP */
62939529Sborman #ifndef USE_TERMIO
63039529Sborman 	ltc = oltc;
63139529Sborman 	tc = otc;
63239529Sborman 	sb = ottyb;
63344361Sborman 	lmode = olmode;
63444361Sborman #else
63544361Sborman 	tmp_tc = old_tc;
63639529Sborman #endif
63738689Sborman     }
63839529Sborman #ifndef USE_TERMIO
63939529Sborman     ioctl(tin, TIOCLSET, (char *)&lmode);
64039529Sborman     ioctl(tin, TIOCSLTC, (char *)&ltc);
64139529Sborman     ioctl(tin, TIOCSETC, (char *)&tc);
642*45233Sborman     ioctl(tin, TIOCSETN, (char *)&sb);
64339529Sborman #else
644*45233Sborman     if (tcsetattr(tin, TCSADRAIN, &tmp_tc) < 0)
645*45233Sborman 	tcsetattr(tin, TCSANOW, &tmp_tc);
64639529Sborman #endif
64739529Sborman 
64832147Sminshall #if	(!defined(TN3270)) || ((!defined(NOT43)) || defined(PUTCHAR))
64933286Sminshall     ioctl(tin, FIONBIO, (char *)&onoff);
65033286Sminshall     ioctl(tout, FIONBIO, (char *)&onoff);
65132147Sminshall #endif	/* (!defined(TN3270)) || ((!defined(NOT43)) || defined(PUTCHAR)) */
65232147Sminshall #if	defined(TN3270)
65336242Sminshall     if (noasynchtty == 0) {
65433286Sminshall 	ioctl(tin, FIOASYNC, (char *)&onoff);
65532147Sminshall     }
65632147Sminshall #endif	/* defined(TN3270) */
65732147Sminshall }
65832147Sminshall 
65939529Sborman #ifndef	B19200
66039529Sborman # define B19200 B9600
66139529Sborman #endif
66239529Sborman 
66339529Sborman #ifndef	B38400
66439529Sborman # define B38400 B19200
66539529Sborman #endif
66639529Sborman 
66739529Sborman /*
66839529Sborman  * This code assumes that the values B0, B50, B75...
66939529Sborman  * are in ascending order.  They do not have to be
67039529Sborman  * contiguous.
67139529Sborman  */
67239529Sborman struct termspeeds {
67339529Sborman 	long speed;
67439529Sborman 	long value;
67539529Sborman } termspeeds[] = {
67639529Sborman 	{ 0,     B0 },     { 50,    B50 },   { 75,    B75 },
67739529Sborman 	{ 110,   B110 },   { 134,   B134 },  { 150,   B150 },
67839529Sborman 	{ 200,   B200 },   { 300,   B300 },  { 600,   B600 },
67939529Sborman 	{ 1200,  B1200 },  { 1800,  B1800 }, { 2400,  B2400 },
68039529Sborman 	{ 4800,  B4800 },  { 9600,  B9600 }, { 19200, B19200 },
68139529Sborman 	{ 38400, B38400 }, { -1,    B38400 }
68239529Sborman };
68339529Sborman 
68437219Sminshall void
68537219Sminshall TerminalSpeeds(ispeed, ospeed)
68637219Sminshall long *ispeed;
68737219Sminshall long *ospeed;
68837219Sminshall {
68939529Sborman     register struct termspeeds *tp;
690*45233Sborman     register long in, out;
69132147Sminshall 
692*45233Sborman     in = cfgetispeed(&old_tc);
693*45233Sborman     out = cfgetospeed(&old_tc);
694*45233Sborman 
69539529Sborman     tp = termspeeds;
696*45233Sborman     while ((tp->speed != -1) && (tp->value < in))
69739529Sborman 	tp++;
69839529Sborman     *ispeed = tp->speed;
69939529Sborman 
70039529Sborman     tp = termspeeds;
701*45233Sborman     while ((tp->speed != -1) && (tp->value < out))
70239529Sborman 	tp++;
70339529Sborman     *ospeed = tp->speed;
70437219Sminshall }
70537219Sminshall 
70632147Sminshall int
70737219Sminshall TerminalWindowSize(rows, cols)
70837219Sminshall long *rows, *cols;
70937219Sminshall {
71038689Sborman #ifdef	TIOCGWINSZ
71137219Sminshall     struct winsize ws;
71237219Sminshall 
71338689Sborman     if (ioctl(fileno(stdin), TIOCGWINSZ, (char *)&ws) >= 0) {
71438689Sborman 	*rows = ws.ws_row;
71538689Sborman 	*cols = ws.ws_col;
71638689Sborman 	return 1;
71737219Sminshall     }
71838810Sborman #endif	/* TIOCGWINSZ */
71938689Sborman     return 0;
72037219Sminshall }
72137219Sminshall 
72237219Sminshall int
72335417Sminshall NetClose(fd)
72435417Sminshall int	fd;
72532147Sminshall {
72635417Sminshall     return close(fd);
72732147Sminshall }
72832147Sminshall 
72932147Sminshall 
73032147Sminshall void
73132553Sminshall NetNonblockingIO(fd, onoff)
73232147Sminshall int
73332147Sminshall 	fd,
73432147Sminshall 	onoff;
73532147Sminshall {
73632147Sminshall     ioctl(fd, FIONBIO, (char *)&onoff);
73732147Sminshall }
73832147Sminshall 
73934849Sminshall #if	defined(TN3270)
74032147Sminshall void
74132553Sminshall NetSigIO(fd, onoff)
74232147Sminshall int
74332147Sminshall 	fd,
74432147Sminshall 	onoff;
74532147Sminshall {
74632147Sminshall     ioctl(fd, FIOASYNC, (char *)&onoff);	/* hear about input */
74732147Sminshall }
74832147Sminshall 
74932147Sminshall void
75032553Sminshall NetSetPgrp(fd)
75132147Sminshall int fd;
75232147Sminshall {
75332147Sminshall     int myPid;
75432147Sminshall 
75532147Sminshall     myPid = getpid();
75636274Sminshall     fcntl(fd, F_SETOWN, myPid);
75732147Sminshall }
75834849Sminshall #endif	/*defined(TN3270)*/
75932553Sminshall 
76032553Sminshall /*
76132553Sminshall  * Various signal handling routines.
76232553Sminshall  */
76332147Sminshall 
764*45233Sborman /* ARGSUSED */
765*45233Sborman static SIG_FUNC_RET
766*45233Sborman deadpeer(sig)
767*45233Sborman int sig;
76832553Sminshall {
76932553Sminshall 	setcommandmode();
77032553Sminshall 	longjmp(peerdied, -1);
77132553Sminshall }
77232147Sminshall 
773*45233Sborman /* ARGSUSED */
774*45233Sborman static SIG_FUNC_RET
775*45233Sborman intr(sig)
776*45233Sborman int sig;
77732553Sminshall {
77832553Sminshall     if (localchars) {
77932553Sminshall 	intp();
78032553Sminshall 	return;
78132553Sminshall     }
78232553Sminshall     setcommandmode();
78332553Sminshall     longjmp(toplevel, -1);
78432553Sminshall }
78532553Sminshall 
786*45233Sborman /* ARGSUSED */
787*45233Sborman static SIG_FUNC_RET
788*45233Sborman intr2(sig)
789*45233Sborman int sig;
79032553Sminshall {
79132553Sminshall     if (localchars) {
79238689Sborman #ifdef	KLUDGELINEMODE
79338689Sborman 	if (kludgelinemode)
79438689Sborman 	    sendbrk();
79538689Sborman 	else
79638689Sborman #endif
79738689Sborman 	    sendabort();
79832553Sminshall 	return;
79932553Sminshall     }
80032553Sminshall }
80132553Sminshall 
802*45233Sborman #ifdef	SIGTSTP
803*45233Sborman /* ARGSUSED */
804*45233Sborman static SIG_FUNC_RET
805*45233Sborman susp(sig)
806*45233Sborman int sig;
80740245Sborman {
80840245Sborman     if (localchars)
80940245Sborman 	sendsusp();
81040245Sborman }
811*45233Sborman #endif
81240245Sborman 
813*45233Sborman #ifdef	SIGWINCH
814*45233Sborman /* ARGSUSED */
815*45233Sborman static SIG_FUNC_RET
816*45233Sborman sendwin(sig)
817*45233Sborman int sig;
81837219Sminshall {
81937219Sminshall     if (connected) {
82037219Sminshall 	sendnaws();
82137219Sminshall     }
82237219Sminshall }
823*45233Sborman #endif
82437219Sminshall 
825*45233Sborman #ifdef	SIGINFO
826*45233Sborman /* ARGSUSED */
827*45233Sborman static SIG_FUNC_RET
828*45233Sborman ayt(sig)
829*45233Sborman int sig;
830*45233Sborman {
831*45233Sborman     if (connected)
832*45233Sborman 	sendayt();
833*45233Sborman     else
834*45233Sborman 	ayt_status();
835*45233Sborman }
836*45233Sborman #endif
837*45233Sborman 
83832553Sminshall 
83932553Sminshall void
84032531Sminshall sys_telnet_init()
84132531Sminshall {
842*45233Sborman     (void) signal(SIGINT, intr);
843*45233Sborman     (void) signal(SIGQUIT, intr2);
844*45233Sborman     (void) signal(SIGPIPE, deadpeer);
84538689Sborman #ifdef	SIGWINCH
846*45233Sborman     (void) signal(SIGWINCH, sendwin);
84738689Sborman #endif
84840245Sborman #ifdef	SIGTSTP
849*45233Sborman     (void) signal(SIGTSTP, susp);
85040245Sborman #endif
851*45233Sborman #ifdef	SIGINFO
852*45233Sborman     (void) signal(SIGINFO, ayt);
853*45233Sborman #endif
85432553Sminshall 
85538689Sborman     setconnmode(0);
85632531Sminshall 
85732531Sminshall     NetNonblockingIO(net, 1);
85832531Sminshall 
85932531Sminshall #if	defined(TN3270)
86036242Sminshall     if (noasynchnet == 0) {			/* DBX can't handle! */
86132531Sminshall 	NetSigIO(net, 1);
86232531Sminshall 	NetSetPgrp(net);
86332531Sminshall     }
86432531Sminshall #endif	/* defined(TN3270) */
86532531Sminshall 
86632531Sminshall #if	defined(SO_OOBINLINE)
86734849Sminshall     if (SetSockOpt(net, SOL_SOCKET, SO_OOBINLINE, 1) == -1) {
86834849Sminshall 	perror("SetSockOpt");
86934849Sminshall     }
87032531Sminshall #endif	/* defined(SO_OOBINLINE) */
87132531Sminshall }
87232531Sminshall 
87332531Sminshall /*
87432531Sminshall  * Process rings -
87532531Sminshall  *
87632531Sminshall  *	This routine tries to fill up/empty our various rings.
87732531Sminshall  *
87832531Sminshall  *	The parameter specifies whether this is a poll operation,
87932531Sminshall  *	or a block-until-something-happens operation.
88032531Sminshall  *
88132531Sminshall  *	The return value is 1 if something happened, 0 if not.
88232531Sminshall  */
88332531Sminshall 
88432531Sminshall int
88532531Sminshall process_rings(netin, netout, netex, ttyin, ttyout, poll)
88632531Sminshall int poll;		/* If 0, then block until something to do */
88732531Sminshall {
88832531Sminshall     register int c;
88932531Sminshall 		/* One wants to be a bit careful about setting returnValue
89032531Sminshall 		 * to one, since a one implies we did some useful work,
89132531Sminshall 		 * and therefore probably won't be called to block next
89232531Sminshall 		 * time (TN3270 mode only).
89332531Sminshall 		 */
89432531Sminshall     int returnValue = 0;
89532531Sminshall     static struct timeval TimeValue = { 0 };
89632531Sminshall 
89732531Sminshall     if (netout) {
89832531Sminshall 	FD_SET(net, &obits);
89932531Sminshall     }
90032531Sminshall     if (ttyout) {
90132531Sminshall 	FD_SET(tout, &obits);
90232531Sminshall     }
90332531Sminshall #if	defined(TN3270)
90432531Sminshall     if (ttyin) {
90532531Sminshall 	FD_SET(tin, &ibits);
90632531Sminshall     }
90732531Sminshall #else	/* defined(TN3270) */
90832531Sminshall     if (ttyin) {
90932531Sminshall 	FD_SET(tin, &ibits);
91032531Sminshall     }
91132531Sminshall #endif	/* defined(TN3270) */
91232531Sminshall #if	defined(TN3270)
91332531Sminshall     if (netin) {
91432531Sminshall 	FD_SET(net, &ibits);
91532531Sminshall     }
91632531Sminshall #   else /* !defined(TN3270) */
91732531Sminshall     if (netin) {
91832531Sminshall 	FD_SET(net, &ibits);
91932531Sminshall     }
92032531Sminshall #   endif /* !defined(TN3270) */
92132531Sminshall     if (netex) {
92232531Sminshall 	FD_SET(net, &xbits);
92332531Sminshall     }
92432531Sminshall     if ((c = select(16, &ibits, &obits, &xbits,
92532531Sminshall 			(poll == 0)? (struct timeval *)0 : &TimeValue)) < 0) {
92632531Sminshall 	if (c == -1) {
92732531Sminshall 		    /*
92832531Sminshall 		     * we can get EINTR if we are in line mode,
92932531Sminshall 		     * and the user does an escape (TSTP), or
93032531Sminshall 		     * some other signal generator.
93132531Sminshall 		     */
93232531Sminshall 	    if (errno == EINTR) {
93332531Sminshall 		return 0;
93432531Sminshall 	    }
93532531Sminshall #	    if defined(TN3270)
93632531Sminshall 		    /*
93732531Sminshall 		     * we can get EBADF if we were in transparent
93832531Sminshall 		     * mode, and the transcom process died.
93932531Sminshall 		    */
94032531Sminshall 	    if (errno == EBADF) {
94132531Sminshall 			/*
94232531Sminshall 			 * zero the bits (even though kernel does it)
94332531Sminshall 			 * to make sure we are selecting on the right
94432531Sminshall 			 * ones.
94532531Sminshall 			*/
94632531Sminshall 		FD_ZERO(&ibits);
94732531Sminshall 		FD_ZERO(&obits);
94832531Sminshall 		FD_ZERO(&xbits);
94932531Sminshall 		return 0;
95032531Sminshall 	    }
95132531Sminshall #	    endif /* defined(TN3270) */
95232531Sminshall 		    /* I don't like this, does it ever happen? */
95332531Sminshall 	    printf("sleep(5) from telnet, after select\r\n");
95432531Sminshall 	    sleep(5);
95532531Sminshall 	}
95632531Sminshall 	return 0;
95732531Sminshall     }
95832531Sminshall 
95932531Sminshall     /*
96032531Sminshall      * Any urgent data?
96132531Sminshall      */
96232531Sminshall     if (FD_ISSET(net, &xbits)) {
96332531Sminshall 	FD_CLR(net, &xbits);
96432531Sminshall 	SYNCHing = 1;
96544361Sborman 	(void) ttyflush(1);	/* flush already enqueued data */
96632531Sminshall     }
96732531Sminshall 
96832531Sminshall     /*
96932531Sminshall      * Something to read from the network...
97032531Sminshall      */
97132531Sminshall     if (FD_ISSET(net, &ibits)) {
97232531Sminshall 	int canread;
97332531Sminshall 
97432531Sminshall 	FD_CLR(net, &ibits);
97532531Sminshall 	canread = ring_empty_consecutive(&netiring);
97632531Sminshall #if	!defined(SO_OOBINLINE)
97732531Sminshall 	    /*
97832531Sminshall 	     * In 4.2 (and some early 4.3) systems, the
97932531Sminshall 	     * OOB indication and data handling in the kernel
98032531Sminshall 	     * is such that if two separate TCP Urgent requests
98132531Sminshall 	     * come in, one byte of TCP data will be overlaid.
98232531Sminshall 	     * This is fatal for Telnet, but we try to live
98332531Sminshall 	     * with it.
98432531Sminshall 	     *
98532531Sminshall 	     * In addition, in 4.2 (and...), a special protocol
98632531Sminshall 	     * is needed to pick up the TCP Urgent data in
98732531Sminshall 	     * the correct sequence.
98832531Sminshall 	     *
98932531Sminshall 	     * What we do is:  if we think we are in urgent
99032531Sminshall 	     * mode, we look to see if we are "at the mark".
99132531Sminshall 	     * If we are, we do an OOB receive.  If we run
99232531Sminshall 	     * this twice, we will do the OOB receive twice,
99332531Sminshall 	     * but the second will fail, since the second
99432531Sminshall 	     * time we were "at the mark", but there wasn't
99532531Sminshall 	     * any data there (the kernel doesn't reset
99632531Sminshall 	     * "at the mark" until we do a normal read).
99732531Sminshall 	     * Once we've read the OOB data, we go ahead
99832531Sminshall 	     * and do normal reads.
99932531Sminshall 	     *
100032531Sminshall 	     * There is also another problem, which is that
100132531Sminshall 	     * since the OOB byte we read doesn't put us
100232531Sminshall 	     * out of OOB state, and since that byte is most
100332531Sminshall 	     * likely the TELNET DM (data mark), we would
100432531Sminshall 	     * stay in the TELNET SYNCH (SYNCHing) state.
100532531Sminshall 	     * So, clocks to the rescue.  If we've "just"
100632531Sminshall 	     * received a DM, then we test for the
100732531Sminshall 	     * presence of OOB data when the receive OOB
100832531Sminshall 	     * fails (and AFTER we did the normal mode read
100932531Sminshall 	     * to clear "at the mark").
101032531Sminshall 	     */
101132531Sminshall 	if (SYNCHing) {
101232531Sminshall 	    int atmark;
101339652Sborman 	    static int bogus_oob = 0, first = 1;
101432531Sminshall 
101532531Sminshall 	    ioctl(net, SIOCATMARK, (char *)&atmark);
101632531Sminshall 	    if (atmark) {
101732531Sminshall 		c = recv(net, netiring.supply, canread, MSG_OOB);
101832531Sminshall 		if ((c == -1) && (errno == EINVAL)) {
101932531Sminshall 		    c = recv(net, netiring.supply, canread, 0);
102032531Sminshall 		    if (clocks.didnetreceive < clocks.gotDM) {
102132531Sminshall 			SYNCHing = stilloob(net);
102232531Sminshall 		    }
102339652Sborman 		} else if (first && c > 0) {
102439652Sborman 		    /*
102539652Sborman 		     * Bogosity check.  Systems based on 4.2BSD
102639652Sborman 		     * do not return an error if you do a second
102739652Sborman 		     * recv(MSG_OOB).  So, we do one.  If it
102839652Sborman 		     * succeeds and returns exactly the same
102939652Sborman 		     * data, then assume that we are running
103039652Sborman 		     * on a broken system and set the bogus_oob
103139652Sborman 		     * flag.  (If the data was different, then
103239652Sborman 		     * we probably got some valid new data, so
103339652Sborman 		     * increment the count...)
103439652Sborman 		     */
103539652Sborman 		    int i;
103639652Sborman 		    i = recv(net, netiring.supply + c, canread - c, MSG_OOB);
103739652Sborman 		    if (i == c &&
103839652Sborman 			  bcmp(netiring.supply, netiring.supply + c, i) == 0) {
103939652Sborman 			bogus_oob = 1;
104039652Sborman 			first = 0;
104139652Sborman 		    } else if (i < 0) {
104239652Sborman 			bogus_oob = 0;
104339652Sborman 			first = 0;
104439652Sborman 		    } else
104539652Sborman 			c += i;
104632531Sminshall 		}
104739652Sborman 		if (bogus_oob && c > 0) {
104839652Sborman 		    int i;
104939652Sborman 		    /*
105039652Sborman 		     * Bogosity.  We have to do the read
105139652Sborman 		     * to clear the atmark to get out of
105239652Sborman 		     * an infinate loop.
105339652Sborman 		     */
105439652Sborman 		    i = read(net, netiring.supply + c, canread - c);
105539652Sborman 		    if (i > 0)
105639652Sborman 			c += i;
105739652Sborman 		}
105832531Sminshall 	    } else {
105932531Sminshall 		c = recv(net, netiring.supply, canread, 0);
106032531Sminshall 	    }
106132531Sminshall 	} else {
106232531Sminshall 	    c = recv(net, netiring.supply, canread, 0);
106332531Sminshall 	}
106432531Sminshall 	settimer(didnetreceive);
106532531Sminshall #else	/* !defined(SO_OOBINLINE) */
106632531Sminshall 	c = recv(net, netiring.supply, canread, 0);
106732531Sminshall #endif	/* !defined(SO_OOBINLINE) */
106832531Sminshall 	if (c < 0 && errno == EWOULDBLOCK) {
106932531Sminshall 	    c = 0;
107032531Sminshall 	} else if (c <= 0) {
107132531Sminshall 	    return -1;
107232531Sminshall 	}
107332531Sminshall 	if (netdata) {
107432531Sminshall 	    Dump('<', netiring.supply, c);
107532531Sminshall 	}
107632667Sminshall 	if (c)
107732667Sminshall 	    ring_supplied(&netiring, c);
107832531Sminshall 	returnValue = 1;
107932531Sminshall     }
108032531Sminshall 
108132531Sminshall     /*
108232531Sminshall      * Something to read from the tty...
108332531Sminshall      */
108432531Sminshall     if (FD_ISSET(tin, &ibits)) {
108532531Sminshall 	FD_CLR(tin, &ibits);
108633286Sminshall 	c = TerminalRead(ttyiring.supply, ring_empty_consecutive(&ttyiring));
108732531Sminshall 	if (c < 0 && errno == EWOULDBLOCK) {
108832531Sminshall 	    c = 0;
108932531Sminshall 	} else {
109032531Sminshall 	    /* EOF detection for line mode!!!! */
109133281Sminshall 	    if ((c == 0) && MODE_LOCAL_CHARS(globalmode) && isatty(tin)) {
109232531Sminshall 			/* must be an EOF... */
109332531Sminshall 		*ttyiring.supply = termEofChar;
109432531Sminshall 		c = 1;
109532531Sminshall 	    }
109632531Sminshall 	    if (c <= 0) {
109732531Sminshall 		return -1;
109832531Sminshall 	    }
109938208Sminshall 	    if (termdata) {
110038208Sminshall 		Dump('<', ttyiring.supply, c);
110138208Sminshall 	    }
110232667Sminshall 	    ring_supplied(&ttyiring, c);
110332531Sminshall 	}
110432531Sminshall 	returnValue = 1;		/* did something useful */
110532531Sminshall     }
110632531Sminshall 
110732531Sminshall     if (FD_ISSET(net, &obits)) {
110832531Sminshall 	FD_CLR(net, &obits);
110932531Sminshall 	returnValue |= netflush();
111032531Sminshall     }
111132531Sminshall     if (FD_ISSET(tout, &obits)) {
111232531Sminshall 	FD_CLR(tout, &obits);
111338689Sborman 	returnValue |= (ttyflush(SYNCHing|flushout) > 0);
111432531Sminshall     }
111532531Sminshall 
111632531Sminshall     return returnValue;
111732531Sminshall }
1118