132147Sminshall /*
262313Sbostic * Copyright (c) 1988, 1990, 1993
362313Sbostic * The Regents of the University of California. All rights reserved.
433685Sbostic *
542770Sbostic * %sccs.include.redist.c%
633685Sbostic */
733685Sbostic
833685Sbostic #ifndef lint
9*69785Sdab static char sccsid[] = "@(#)sys_bsd.c 8.4 (Berkeley) 05/30/95";
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
4058972Sdab #ifdef SIGINFO
4158972Sdab extern SIG_FUNC_RET ayt_status();
4265157Sdab #endif
4358972Sdab
4432147Sminshall int
4532531Sminshall tout, /* Output file descriptor */
4632531Sminshall tin, /* Input file descriptor */
4736242Sminshall net;
4832147Sminshall
4938689Sborman #ifndef USE_TERMIO
5038689Sborman struct tchars otc = { 0 }, ntc = { 0 };
5138689Sborman struct ltchars oltc = { 0 }, nltc = { 0 };
5238689Sborman struct sgttyb ottyb = { 0 }, nttyb = { 0 };
5338909Sborman int olmode = 0;
5445233Sborman # define cfgetispeed(ptr) (ptr)->sg_ispeed
5545233Sborman # define cfgetospeed(ptr) (ptr)->sg_ospeed
5645233Sborman # define old_tc ottyb
5732147Sminshall
5838689Sborman #else /* USE_TERMIO */
5938689Sborman struct termio old_tc = { 0 };
6038689Sborman extern struct termio new_tc;
6138689Sborman
6245233Sborman # ifndef TCSANOW
6345233Sborman # ifdef TCSETS
6445233Sborman # define TCSANOW TCSETS
6545233Sborman # define TCSADRAIN TCSETSW
6646808Sdab # define tcgetattr(f, t) ioctl(f, TCGETS, (char *)t)
6745233Sborman # else
6845233Sborman # ifdef TCSETA
6945233Sborman # define TCSANOW TCSETA
7045233Sborman # define TCSADRAIN TCSETAW
7146808Sdab # define tcgetattr(f, t) ioctl(f, TCGETA, (char *)t)
7245233Sborman # else
7345233Sborman # define TCSANOW TIOCSETA
7445233Sborman # define TCSADRAIN TIOCSETAW
7546808Sdab # define tcgetattr(f, t) ioctl(f, TIOCGETA, (char *)t)
7645233Sborman # endif
7745233Sborman # endif
7846808Sdab # define tcsetattr(f, a, t) ioctl(f, a, (char *)t)
7945233Sborman # define cfgetospeed(ptr) ((ptr)->c_cflag&CBAUD)
8045233Sborman # ifdef CIBAUD
8145233Sborman # define cfgetispeed(ptr) (((ptr)->c_cflag&CIBAUD) >> IBSHIFT)
8245233Sborman # else
8345233Sborman # define cfgetispeed(ptr) cfgetospeed(ptr)
8445233Sborman # endif
8545233Sborman # endif /* TCSANOW */
8657213Sdab # ifdef sysV88
8757213Sdab # define TIOCFLUSH TC_PX_DRAIN
8857213Sdab # endif
8938689Sborman #endif /* USE_TERMIO */
9038689Sborman
9132531Sminshall static fd_set ibits, obits, xbits;
9232147Sminshall
9332531Sminshall
9446808Sdab void
init_sys()9532531Sminshall init_sys()
9632531Sminshall {
9732531Sminshall tout = fileno(stdout);
9832531Sminshall tin = fileno(stdin);
9932531Sminshall FD_ZERO(&ibits);
10032531Sminshall FD_ZERO(&obits);
10132531Sminshall FD_ZERO(&xbits);
10232531Sminshall
10332531Sminshall errno = 0;
10432531Sminshall }
10532531Sminshall
10632531Sminshall
10746808Sdab int
TerminalWrite(buf,n)10833286Sminshall TerminalWrite(buf, n)
10946808Sdab char *buf;
11046808Sdab int n;
11132147Sminshall {
11233286Sminshall return write(tout, buf, n);
11332147Sminshall }
11432147Sminshall
11546808Sdab int
TerminalRead(buf,n)11633286Sminshall TerminalRead(buf, n)
11746808Sdab char *buf;
11846808Sdab int n;
11932147Sminshall {
12033286Sminshall return read(tin, buf, n);
12132147Sminshall }
12232147Sminshall
12332147Sminshall /*
12432147Sminshall *
12532147Sminshall */
12632147Sminshall
12746808Sdab int
TerminalAutoFlush()12832553Sminshall TerminalAutoFlush()
12932147Sminshall {
13032147Sminshall #if defined(LNOFLSH)
13132147Sminshall int flush;
13232147Sminshall
13332147Sminshall ioctl(0, TIOCLGET, (char *)&flush);
13432147Sminshall return !(flush&LNOFLSH); /* if LNOFLSH, no autoflush */
13532147Sminshall #else /* LNOFLSH */
13632147Sminshall return 1;
13732147Sminshall #endif /* LNOFLSH */
13832147Sminshall }
13932147Sminshall
14038689Sborman #ifdef KLUDGELINEMODE
14138689Sborman extern int kludgelinemode;
14238689Sborman #endif
14332147Sminshall /*
14432147Sminshall * TerminalSpecialChars()
14532147Sminshall *
14632147Sminshall * Look at an input character to see if it is a special character
14732147Sminshall * and decide what to do.
14832147Sminshall *
14932147Sminshall * Output:
15032147Sminshall *
15132147Sminshall * 0 Don't add this character.
15232147Sminshall * 1 Do add this character
15332147Sminshall */
15432147Sminshall
15558972Sdab extern void xmitAO(), xmitEL(), xmitEC(), intp(), sendbrk();
15658972Sdab
15746808Sdab int
TerminalSpecialChars(c)15832553Sminshall TerminalSpecialChars(c)
15946808Sdab int c;
16032147Sminshall {
16138689Sborman if (c == termIntChar) {
16232147Sminshall intp();
16332147Sminshall return 0;
16438689Sborman } else if (c == termQuitChar) {
16538689Sborman #ifdef KLUDGELINEMODE
16638689Sborman if (kludgelinemode)
16738689Sborman sendbrk();
16838689Sborman else
16938689Sborman #endif
17038689Sborman sendabort();
17132147Sminshall return 0;
17238689Sborman } else if (c == termEofChar) {
17338689Sborman if (my_want_state_is_will(TELOPT_LINEMODE)) {
17438689Sborman sendeof();
17538689Sborman return 0;
17638689Sborman }
17738689Sborman return 1;
17838689Sborman } else if (c == termSuspChar) {
17938689Sborman sendsusp();
18038689Sborman return(0);
18138689Sborman } else if (c == termFlushChar) {
18232147Sminshall xmitAO(); /* Transmit Abort Output */
18332147Sminshall return 0;
18432147Sminshall } else if (!MODE_LOCAL_CHARS(globalmode)) {
18538689Sborman if (c == termKillChar) {
18632147Sminshall xmitEL();
18732147Sminshall return 0;
18838689Sborman } else if (c == termEraseChar) {
18932147Sminshall xmitEC(); /* Transmit Erase Character */
19032147Sminshall return 0;
19132147Sminshall }
19232147Sminshall }
19332147Sminshall return 1;
19432147Sminshall }
19532147Sminshall
19632147Sminshall
19732147Sminshall /*
19832147Sminshall * Flush output to the terminal
19932147Sminshall */
200*69785Sdab
20146808Sdab void
TerminalFlushOutput()20232553Sminshall TerminalFlushOutput()
20332147Sminshall {
20439529Sborman #ifdef TIOCFLUSH
20532147Sminshall (void) ioctl(fileno(stdout), TIOCFLUSH, (char *) 0);
20638689Sborman #else
20738689Sborman (void) ioctl(fileno(stdout), TCFLSH, (char *) 0);
20838689Sborman #endif
20932147Sminshall }
21032147Sminshall
21146808Sdab void
TerminalSaveState()21232553Sminshall TerminalSaveState()
21332147Sminshall {
21438689Sborman #ifndef USE_TERMIO
21532147Sminshall ioctl(0, TIOCGETP, (char *)&ottyb);
21632147Sminshall ioctl(0, TIOCGETC, (char *)&otc);
21732147Sminshall ioctl(0, TIOCGLTC, (char *)&oltc);
21838909Sborman ioctl(0, TIOCLGET, (char *)&olmode);
21932147Sminshall
22032147Sminshall ntc = otc;
22132147Sminshall nltc = oltc;
22232147Sminshall nttyb = ottyb;
22332254Sminshall
22438689Sborman #else /* USE_TERMIO */
22545233Sborman tcgetattr(0, &old_tc);
22638689Sborman
22738689Sborman new_tc = old_tc;
22838689Sborman
22945233Sborman #ifndef VDISCARD
23044361Sborman termFlushChar = CONTROL('O');
23145233Sborman #endif
23245233Sborman #ifndef VWERASE
23344361Sborman termWerasChar = CONTROL('W');
23445233Sborman #endif
23545233Sborman #ifndef VREPRINT
23644361Sborman termRprntChar = CONTROL('R');
23745233Sborman #endif
23845233Sborman #ifndef VLNEXT
23944361Sborman termLiteralNextChar = CONTROL('V');
24045233Sborman #endif
24145233Sborman #ifndef VSTART
24244361Sborman termStartChar = CONTROL('Q');
24345233Sborman #endif
24445233Sborman #ifndef VSTOP
24544361Sborman termStopChar = CONTROL('S');
24645233Sborman #endif
24745233Sborman #ifndef VSTATUS
24845233Sborman termAytChar = CONTROL('T');
24945233Sborman #endif
25038689Sborman #endif /* USE_TERMIO */
25132147Sminshall }
25232147Sminshall
25346808Sdab cc_t *
tcval(func)25438689Sborman tcval(func)
25546808Sdab register int func;
25638689Sborman {
25738689Sborman switch(func) {
25840245Sborman case SLC_IP: return(&termIntChar);
25940245Sborman case SLC_ABORT: return(&termQuitChar);
26040245Sborman case SLC_EOF: return(&termEofChar);
26140245Sborman case SLC_EC: return(&termEraseChar);
26240245Sborman case SLC_EL: return(&termKillChar);
26340245Sborman case SLC_XON: return(&termStartChar);
26440245Sborman case SLC_XOFF: return(&termStopChar);
26544361Sborman case SLC_FORW1: return(&termForw1Char);
26645233Sborman #ifdef USE_TERMIO
26745233Sborman case SLC_FORW2: return(&termForw2Char);
26845233Sborman # ifdef VDISCARD
26940245Sborman case SLC_AO: return(&termFlushChar);
27045233Sborman # endif
27145233Sborman # ifdef VSUSP
27240245Sborman case SLC_SUSP: return(&termSuspChar);
27345233Sborman # endif
27445233Sborman # ifdef VWERASE
27540245Sborman case SLC_EW: return(&termWerasChar);
27645233Sborman # endif
27745233Sborman # ifdef VREPRINT
27840245Sborman case SLC_RP: return(&termRprntChar);
27945233Sborman # endif
28045233Sborman # ifdef VLNEXT
28140245Sborman case SLC_LNEXT: return(&termLiteralNextChar);
28245233Sborman # endif
28345233Sborman # ifdef VSTATUS
28445233Sborman case SLC_AYT: return(&termAytChar);
28545233Sborman # endif
28644361Sborman #endif
28738689Sborman
28838689Sborman case SLC_SYNCH:
28938689Sborman case SLC_BRK:
29038689Sborman case SLC_EOR:
29138689Sborman default:
29240245Sborman return((cc_t *)0);
29338689Sborman }
29438689Sborman }
29538689Sborman
29646808Sdab void
TerminalDefaultChars()29738689Sborman TerminalDefaultChars()
29838689Sborman {
29938689Sborman #ifndef USE_TERMIO
30038689Sborman ntc = otc;
30138689Sborman nltc = oltc;
30238689Sborman nttyb.sg_kill = ottyb.sg_kill;
30338689Sborman nttyb.sg_erase = ottyb.sg_erase;
30438689Sborman #else /* USE_TERMIO */
305*69785Sdab memmove(new_tc.c_cc, old_tc.c_cc, sizeof(old_tc.c_cc));
30645233Sborman # ifndef VDISCARD
30744361Sborman termFlushChar = CONTROL('O');
30839529Sborman # endif
30939529Sborman # ifndef VWERASE
31044361Sborman termWerasChar = CONTROL('W');
31139529Sborman # endif
31239529Sborman # ifndef VREPRINT
31344361Sborman termRprntChar = CONTROL('R');
31439529Sborman # endif
31539529Sborman # ifndef VLNEXT
31644361Sborman termLiteralNextChar = CONTROL('V');
31739529Sborman # endif
31839529Sborman # ifndef VSTART
31944361Sborman termStartChar = CONTROL('Q');
32039529Sborman # endif
32139529Sborman # ifndef VSTOP
32244361Sborman termStopChar = CONTROL('S');
32339529Sborman # endif
32445233Sborman # ifndef VSTATUS
32545233Sborman termAytChar = CONTROL('T');
32645233Sborman # endif
32738689Sborman #endif /* USE_TERMIO */
32838689Sborman }
32938689Sborman
33044361Sborman #ifdef notdef
33138689Sborman void
TerminalRestoreState()33232553Sminshall TerminalRestoreState()
33332147Sminshall {
33432147Sminshall }
33544361Sborman #endif
33632147Sminshall
33732147Sminshall /*
33832147Sminshall * TerminalNewMode - set up terminal to a specific mode.
33938689Sborman * MODE_ECHO: do local terminal echo
34038689Sborman * MODE_FLOW: do local flow control
34138689Sborman * MODE_TRAPSIG: do local mapping to TELNET IAC sequences
34238689Sborman * MODE_EDIT: do local line editing
34338689Sborman *
34438689Sborman * Command mode:
34538689Sborman * MODE_ECHO|MODE_EDIT|MODE_FLOW|MODE_TRAPSIG
34638689Sborman * local echo
34738689Sborman * local editing
34838689Sborman * local xon/xoff
34938689Sborman * local signal mapping
35038689Sborman *
35138689Sborman * Linemode:
35238689Sborman * local/no editing
35338689Sborman * Both Linemode and Single Character mode:
35438689Sborman * local/remote echo
35538689Sborman * local/no xon/xoff
35638689Sborman * local/no signal mapping
35732147Sminshall */
35832147Sminshall
35932147Sminshall
36046808Sdab void
TerminalNewMode(f)36133286Sminshall TerminalNewMode(f)
36246808Sdab register int f;
36332147Sminshall {
36432147Sminshall static int prevmode = 0;
36538689Sborman #ifndef USE_TERMIO
36638689Sborman struct tchars tc;
36738689Sborman struct ltchars ltc;
36832147Sminshall struct sgttyb sb;
36938909Sborman int lmode;
37038689Sborman #else /* USE_TERMIO */
37138689Sborman struct termio tmp_tc;
37238689Sborman #endif /* USE_TERMIO */
37332147Sminshall int onoff;
37432147Sminshall int old;
37546808Sdab cc_t esc;
37632147Sminshall
37738689Sborman globalmode = f&~MODE_FORCE;
37832147Sminshall if (prevmode == f)
37932147Sminshall return;
38038689Sborman
38138689Sborman /*
38238689Sborman * Write any outstanding data before switching modes
38338689Sborman * ttyflush() returns 0 only when there is no more data
38438689Sborman * left to write out, it returns -1 if it couldn't do
38538689Sborman * anything at all, otherwise it returns 1 + the number
38638689Sborman * of characters left to write.
38745233Sborman #ifndef USE_TERMIO
38845233Sborman * We would really like ask the kernel to wait for the output
38945233Sborman * to drain, like we can do with the TCSADRAIN, but we don't have
39045233Sborman * that option. The only ioctl that waits for the output to
39145233Sborman * drain, TIOCSETP, also flushes the input queue, which is NOT
39245233Sborman * what we want (TIOCSETP is like TCSADFLUSH).
39345233Sborman #endif
39438689Sborman */
39538689Sborman old = ttyflush(SYNCHing|flushout);
39638689Sborman if (old < 0 || old > 1) {
39745233Sborman #ifdef USE_TERMIO
39846808Sdab tcgetattr(tin, &tmp_tc);
39938689Sborman #endif /* USE_TERMIO */
40038689Sborman do {
40138689Sborman /*
40238689Sborman * Wait for data to drain, then flush again.
40338689Sborman */
40445233Sborman #ifdef USE_TERMIO
40546808Sdab tcsetattr(tin, TCSADRAIN, &tmp_tc);
40638689Sborman #endif /* USE_TERMIO */
40738689Sborman old = ttyflush(SYNCHing|flushout);
40838689Sborman } while (old < 0 || old > 1);
40938689Sborman }
41038689Sborman
41132147Sminshall old = prevmode;
41238689Sborman prevmode = f&~MODE_FORCE;
41338689Sborman #ifndef USE_TERMIO
41432147Sminshall sb = nttyb;
41538689Sborman tc = ntc;
41638689Sborman ltc = nltc;
41738909Sborman lmode = olmode;
41838689Sborman #else
41938689Sborman tmp_tc = new_tc;
42038689Sborman #endif
42132147Sminshall
42238689Sborman if (f&MODE_ECHO) {
42338689Sborman #ifndef USE_TERMIO
42438689Sborman sb.sg_flags |= ECHO;
42538689Sborman #else
42638689Sborman tmp_tc.c_lflag |= ECHO;
42738689Sborman tmp_tc.c_oflag |= ONLCR;
42846808Sdab if (crlf)
42946808Sdab tmp_tc.c_iflag |= ICRNL;
43038689Sborman #endif
43138689Sborman } else {
43238689Sborman #ifndef USE_TERMIO
43338689Sborman sb.sg_flags &= ~ECHO;
43438689Sborman #else
43538689Sborman tmp_tc.c_lflag &= ~ECHO;
43638689Sborman tmp_tc.c_oflag &= ~ONLCR;
43739529Sborman # ifdef notdef
43846808Sdab if (crlf)
43946808Sdab tmp_tc.c_iflag &= ~ICRNL;
44039529Sborman # endif
44138689Sborman #endif
44238689Sborman }
44332147Sminshall
44438689Sborman if ((f&MODE_FLOW) == 0) {
44538689Sborman #ifndef USE_TERMIO
44645233Sborman tc.t_startc = _POSIX_VDISABLE;
44745233Sborman tc.t_stopc = _POSIX_VDISABLE;
44838689Sborman #else
44957213Sdab tmp_tc.c_iflag &= ~(IXOFF|IXON); /* Leave the IXANY bit alone */
45038689Sborman } else {
45157213Sdab if (restartany < 0) {
45257213Sdab tmp_tc.c_iflag |= IXOFF|IXON; /* Leave the IXANY bit alone */
45357213Sdab } else if (restartany > 0) {
45457213Sdab tmp_tc.c_iflag |= IXOFF|IXON|IXANY;
45557213Sdab } else {
45657213Sdab tmp_tc.c_iflag |= IXOFF|IXON;
45757213Sdab tmp_tc.c_iflag &= ~IXANY;
45857213Sdab }
45938689Sborman #endif
46038689Sborman }
46132147Sminshall
46238689Sborman if ((f&MODE_TRAPSIG) == 0) {
46338689Sborman #ifndef USE_TERMIO
46445233Sborman tc.t_intrc = _POSIX_VDISABLE;
46545233Sborman tc.t_quitc = _POSIX_VDISABLE;
46645233Sborman tc.t_eofc = _POSIX_VDISABLE;
46745233Sborman ltc.t_suspc = _POSIX_VDISABLE;
46845233Sborman ltc.t_dsuspc = _POSIX_VDISABLE;
46938689Sborman #else
47038689Sborman tmp_tc.c_lflag &= ~ISIG;
47138689Sborman #endif
47238689Sborman localchars = 0;
47338689Sborman } else {
47438689Sborman #ifdef USE_TERMIO
47538689Sborman tmp_tc.c_lflag |= ISIG;
47638689Sborman #endif
47738689Sborman localchars = 1;
47838689Sborman }
47938689Sborman
48038689Sborman if (f&MODE_EDIT) {
48138689Sborman #ifndef USE_TERMIO
48238689Sborman sb.sg_flags &= ~CBREAK;
48338689Sborman sb.sg_flags |= CRMOD;
48438689Sborman #else
48538689Sborman tmp_tc.c_lflag |= ICANON;
48638689Sborman #endif
48738689Sborman } else {
48838689Sborman #ifndef USE_TERMIO
48938689Sborman sb.sg_flags |= CBREAK;
49038689Sborman if (f&MODE_ECHO)
49132147Sminshall sb.sg_flags |= CRMOD;
49238689Sborman else
49338689Sborman sb.sg_flags &= ~CRMOD;
49438689Sborman #else
49538689Sborman tmp_tc.c_lflag &= ~ICANON;
49638689Sborman tmp_tc.c_iflag &= ~ICRNL;
49738689Sborman tmp_tc.c_cc[VMIN] = 1;
49838689Sborman tmp_tc.c_cc[VTIME] = 0;
49938689Sborman #endif
50038689Sborman }
50132147Sminshall
50244361Sborman if ((f&(MODE_EDIT|MODE_TRAPSIG)) == 0) {
50344361Sborman #ifndef USE_TERMIO
50445233Sborman ltc.t_lnextc = _POSIX_VDISABLE;
50544361Sborman #else
50644361Sborman # ifdef VLNEXT
50745233Sborman tmp_tc.c_cc[VLNEXT] = (cc_t)(_POSIX_VDISABLE);
50844361Sborman # endif
50944361Sborman #endif
51044361Sborman }
51144361Sborman
51244361Sborman if (f&MODE_SOFT_TAB) {
51344361Sborman #ifndef USE_TERMIO
51444361Sborman sb.sg_flags |= XTABS;
51544361Sborman #else
51644361Sborman # ifdef OXTABS
51744361Sborman tmp_tc.c_oflag |= OXTABS;
51844361Sborman # endif
51944361Sborman # ifdef TABDLY
52044361Sborman tmp_tc.c_oflag &= ~TABDLY;
52144361Sborman tmp_tc.c_oflag |= TAB3;
52244361Sborman # endif
52344361Sborman #endif
52444361Sborman } else {
52544361Sborman #ifndef USE_TERMIO
52644361Sborman sb.sg_flags &= ~XTABS;
52744361Sborman #else
52844361Sborman # ifdef OXTABS
52944361Sborman tmp_tc.c_oflag &= ~OXTABS;
53044361Sborman # endif
53144361Sborman # ifdef TABDLY
53244361Sborman tmp_tc.c_oflag &= ~TABDLY;
53344361Sborman # endif
53444361Sborman #endif
53544361Sborman }
53644361Sborman
53744361Sborman if (f&MODE_LIT_ECHO) {
53844361Sborman #ifndef USE_TERMIO
53946808Sdab lmode &= ~LCTLECH;
54044361Sborman #else
54144361Sborman # ifdef ECHOCTL
54244361Sborman tmp_tc.c_lflag &= ~ECHOCTL;
54344361Sborman # endif
54444361Sborman #endif
54544361Sborman } else {
54644361Sborman #ifndef USE_TERMIO
54746808Sdab lmode |= LCTLECH;
54844361Sborman #else
54944361Sborman # ifdef ECHOCTL
55044361Sborman tmp_tc.c_lflag |= ECHOCTL;
55144361Sborman # endif
55244361Sborman #endif
55344361Sborman }
55444361Sborman
55538689Sborman if (f == -1) {
55638689Sborman onoff = 0;
55738689Sborman } else {
55838909Sborman #ifndef USE_TERMIO
55939529Sborman if (f & MODE_OUTBIN)
56038909Sborman lmode |= LLITOUT;
56138909Sborman else
56238909Sborman lmode &= ~LLITOUT;
56339529Sborman
56439529Sborman if (f & MODE_INBIN)
56538909Sborman lmode |= LPASS8;
56638909Sborman else
56738909Sborman lmode &= ~LPASS8;
56838909Sborman #else
56945233Sborman if (f & MODE_INBIN)
57045233Sborman tmp_tc.c_iflag &= ~ISTRIP;
57138909Sborman else
57245233Sborman tmp_tc.c_iflag |= ISTRIP;
57345233Sborman if (f & MODE_OUTBIN) {
57439529Sborman tmp_tc.c_cflag &= ~(CSIZE|PARENB);
57539529Sborman tmp_tc.c_cflag |= CS8;
57645233Sborman tmp_tc.c_oflag &= ~OPOST;
57739529Sborman } else {
57845233Sborman tmp_tc.c_cflag &= ~(CSIZE|PARENB);
57945233Sborman tmp_tc.c_cflag |= old_tc.c_cflag & (CSIZE|PARENB);
58045233Sborman tmp_tc.c_oflag |= OPOST;
58139529Sborman }
58238909Sborman #endif
58338689Sborman onoff = 1;
58432147Sminshall }
58538689Sborman
58638689Sborman if (f != -1) {
58739529Sborman #ifdef SIGTSTP
58865157Sdab SIG_FUNC_RET susp();
58945233Sborman #endif /* SIGTSTP */
59045233Sborman #ifdef SIGINFO
59165157Sdab SIG_FUNC_RET ayt();
59265157Sdab #endif
59338689Sborman
59445233Sborman #ifdef SIGTSTP
59545233Sborman (void) signal(SIGTSTP, susp);
59639529Sborman #endif /* SIGTSTP */
59745233Sborman #ifdef SIGINFO
59845233Sborman (void) signal(SIGINFO, ayt);
59965157Sdab #endif
60045233Sborman #if defined(USE_TERMIO) && defined(NOKERNINFO)
60145233Sborman tmp_tc.c_lflag |= NOKERNINFO;
60245233Sborman #endif
60344361Sborman /*
60444361Sborman * We don't want to process ^Y here. It's just another
60544361Sborman * character that we'll pass on to the back end. It has
60644361Sborman * to process it because it will be processed when the
60744361Sborman * user attempts to read it, not when we send it.
60844361Sborman */
60944361Sborman #ifndef USE_TERMIO
61045233Sborman ltc.t_dsuspc = _POSIX_VDISABLE;
61144361Sborman #else
61244361Sborman # ifdef VDSUSP
61345233Sborman tmp_tc.c_cc[VDSUSP] = (cc_t)(_POSIX_VDISABLE);
61444361Sborman # endif
61544361Sborman #endif
61640245Sborman #ifdef USE_TERMIO
61740245Sborman /*
61840245Sborman * If the VEOL character is already set, then use VEOL2,
61940245Sborman * otherwise use VEOL.
62040245Sborman */
62146808Sdab esc = (rlogin != _POSIX_VDISABLE) ? rlogin : escape;
62246808Sdab if ((tmp_tc.c_cc[VEOL] != esc)
62344361Sborman # ifdef VEOL2
62446808Sdab && (tmp_tc.c_cc[VEOL2] != esc)
62544361Sborman # endif
62646808Sdab ) {
62745233Sborman if (tmp_tc.c_cc[VEOL] == (cc_t)(_POSIX_VDISABLE))
62846808Sdab tmp_tc.c_cc[VEOL] = esc;
62945233Sborman # ifdef VEOL2
63045233Sborman else if (tmp_tc.c_cc[VEOL2] == (cc_t)(_POSIX_VDISABLE))
63146808Sdab tmp_tc.c_cc[VEOL2] = esc;
63245233Sborman # endif
63345233Sborman }
63440245Sborman #else
63545233Sborman if (tc.t_brkc == (cc_t)(_POSIX_VDISABLE))
63646808Sdab tc.t_brkc = esc;
63740245Sborman #endif
63838689Sborman } else {
63945233Sborman #ifdef SIGINFO
64060149Sdab SIG_FUNC_RET ayt_status();
64160149Sdab
64245233Sborman (void) signal(SIGINFO, ayt_status);
64365157Sdab #endif
64439529Sborman #ifdef SIGTSTP
64538689Sborman (void) signal(SIGTSTP, SIG_DFL);
646*69785Sdab # ifndef SOLARIS
64744361Sborman (void) sigsetmask(sigblock(0) & ~(1<<(SIGTSTP-1)));
648*69785Sdab # else SOLARIS
649*69785Sdab (void) sigrelse(SIGTSTP);
650*69785Sdab # endif SOLARIS
65139529Sborman #endif /* SIGTSTP */
65239529Sborman #ifndef USE_TERMIO
65339529Sborman ltc = oltc;
65439529Sborman tc = otc;
65539529Sborman sb = ottyb;
65644361Sborman lmode = olmode;
65744361Sborman #else
65844361Sborman tmp_tc = old_tc;
65939529Sborman #endif
66038689Sborman }
66139529Sborman #ifndef USE_TERMIO
66239529Sborman ioctl(tin, TIOCLSET, (char *)&lmode);
66339529Sborman ioctl(tin, TIOCSLTC, (char *)<c);
66439529Sborman ioctl(tin, TIOCSETC, (char *)&tc);
66545233Sborman ioctl(tin, TIOCSETN, (char *)&sb);
66639529Sborman #else
66745233Sborman if (tcsetattr(tin, TCSADRAIN, &tmp_tc) < 0)
66845233Sborman tcsetattr(tin, TCSANOW, &tmp_tc);
66939529Sborman #endif
67039529Sborman
67132147Sminshall #if (!defined(TN3270)) || ((!defined(NOT43)) || defined(PUTCHAR))
67257213Sdab # if !defined(sysV88)
67333286Sminshall ioctl(tin, FIONBIO, (char *)&onoff);
67433286Sminshall ioctl(tout, FIONBIO, (char *)&onoff);
67557213Sdab # endif
67632147Sminshall #endif /* (!defined(TN3270)) || ((!defined(NOT43)) || defined(PUTCHAR)) */
67732147Sminshall #if defined(TN3270)
67836242Sminshall if (noasynchtty == 0) {
67933286Sminshall ioctl(tin, FIOASYNC, (char *)&onoff);
68032147Sminshall }
68132147Sminshall #endif /* defined(TN3270) */
68246808Sdab
68332147Sminshall }
68432147Sminshall
68568345Sdab /*
68668345Sdab * Try to guess whether speeds are "encoded" (4.2BSD) or just numeric (4.4BSD).
68768345Sdab */
68868345Sdab #if B4800 != 4800
68968345Sdab #define DECODE_BAUD
69068345Sdab #endif
69168345Sdab
69268345Sdab #ifdef DECODE_BAUD
69368345Sdab #ifndef B7200
69468345Sdab #define B7200 B4800
69568345Sdab #endif
69668345Sdab
69768345Sdab #ifndef B14400
69868345Sdab #define B14400 B9600
69968345Sdab #endif
70068345Sdab
70139529Sborman #ifndef B19200
70268345Sdab # define B19200 B14400
70339529Sborman #endif
70439529Sborman
70568345Sdab #ifndef B28800
70668345Sdab #define B28800 B19200
70768345Sdab #endif
70868345Sdab
70939529Sborman #ifndef B38400
71068345Sdab # define B38400 B28800
71139529Sborman #endif
71239529Sborman
713*69785Sdab #ifndef B57600
71468345Sdab #define B57600 B38400
71568345Sdab #endif
71668345Sdab
717*69785Sdab #ifndef B76800
71868345Sdab #define B76800 B57600
71968345Sdab #endif
72068345Sdab
72168345Sdab #ifndef B115200
72268345Sdab #define B115200 B76800
72368345Sdab #endif
72468345Sdab
72568345Sdab #ifndef B230400
72668345Sdab #define B230400 B115200
72768345Sdab #endif
72868345Sdab
72968345Sdab
73039529Sborman /*
73139529Sborman * This code assumes that the values B0, B50, B75...
73239529Sborman * are in ascending order. They do not have to be
73339529Sborman * contiguous.
73439529Sborman */
73539529Sborman struct termspeeds {
73639529Sborman long speed;
73739529Sborman long value;
73839529Sborman } termspeeds[] = {
73968345Sdab { 0, B0 }, { 50, B50 }, { 75, B75 },
74068345Sdab { 110, B110 }, { 134, B134 }, { 150, B150 },
74168345Sdab { 200, B200 }, { 300, B300 }, { 600, B600 },
74268345Sdab { 1200, B1200 }, { 1800, B1800 }, { 2400, B2400 },
74368345Sdab { 4800, B4800 }, { 7200, B7200 }, { 9600, B9600 },
74468345Sdab { 14400, B14400 }, { 19200, B19200 }, { 28800, B28800 },
74568345Sdab { 38400, B38400 }, { 57600, B57600 }, { 115200, B115200 },
74668345Sdab { 230400, B230400 }, { -1, B230400 }
74739529Sborman };
74868345Sdab #endif /* DECODE_BAUD */
74939529Sborman
75046808Sdab void
TerminalSpeeds(ispeed,ospeed)75137219Sminshall TerminalSpeeds(ispeed, ospeed)
75246808Sdab long *ispeed;
75346808Sdab long *ospeed;
75437219Sminshall {
75568345Sdab #ifdef DECODE_BAUD
75639529Sborman register struct termspeeds *tp;
75768345Sdab #endif /* DECODE_BAUD */
75845233Sborman register long in, out;
75932147Sminshall
76046808Sdab out = cfgetospeed(&old_tc);
76145233Sborman in = cfgetispeed(&old_tc);
76246808Sdab if (in == 0)
76346808Sdab in = out;
76445233Sborman
76568345Sdab #ifdef DECODE_BAUD
76639529Sborman tp = termspeeds;
76745233Sborman while ((tp->speed != -1) && (tp->value < in))
76839529Sborman tp++;
76939529Sborman *ispeed = tp->speed;
77039529Sborman
77139529Sborman tp = termspeeds;
77245233Sborman while ((tp->speed != -1) && (tp->value < out))
77339529Sborman tp++;
77439529Sborman *ospeed = tp->speed;
77568345Sdab #else /* DECODE_BAUD */
77668345Sdab *ispeed = in;
77768345Sdab *ospeed = out;
77868345Sdab #endif /* DECODE_BAUD */
77937219Sminshall }
78037219Sminshall
78146808Sdab int
TerminalWindowSize(rows,cols)78237219Sminshall TerminalWindowSize(rows, cols)
78346808Sdab long *rows, *cols;
78437219Sminshall {
78538689Sborman #ifdef TIOCGWINSZ
78637219Sminshall struct winsize ws;
78737219Sminshall
78838689Sborman if (ioctl(fileno(stdin), TIOCGWINSZ, (char *)&ws) >= 0) {
78938689Sborman *rows = ws.ws_row;
79038689Sborman *cols = ws.ws_col;
79138689Sborman return 1;
79237219Sminshall }
79338810Sborman #endif /* TIOCGWINSZ */
79438689Sborman return 0;
79537219Sminshall }
79637219Sminshall
79746808Sdab int
NetClose(fd)79835417Sminshall NetClose(fd)
79946808Sdab int fd;
80032147Sminshall {
80135417Sminshall return close(fd);
80232147Sminshall }
80332147Sminshall
80432147Sminshall
80546808Sdab void
NetNonblockingIO(fd,onoff)80632553Sminshall NetNonblockingIO(fd, onoff)
80746808Sdab int fd;
80846808Sdab int onoff;
80932147Sminshall {
81032147Sminshall ioctl(fd, FIONBIO, (char *)&onoff);
81132147Sminshall }
81232147Sminshall
81334849Sminshall #if defined(TN3270)
81446808Sdab void
NetSigIO(fd,onoff)81532553Sminshall NetSigIO(fd, onoff)
81646808Sdab int fd;
81746808Sdab int onoff;
81832147Sminshall {
81932147Sminshall ioctl(fd, FIOASYNC, (char *)&onoff); /* hear about input */
82032147Sminshall }
82132147Sminshall
82246808Sdab void
NetSetPgrp(fd)82332553Sminshall NetSetPgrp(fd)
82446808Sdab int fd;
82532147Sminshall {
82632147Sminshall int myPid;
82732147Sminshall
82832147Sminshall myPid = getpid();
82936274Sminshall fcntl(fd, F_SETOWN, myPid);
83032147Sminshall }
83134849Sminshall #endif /*defined(TN3270)*/
83232553Sminshall
83332553Sminshall /*
83432553Sminshall * Various signal handling routines.
83532553Sminshall */
83632147Sminshall
83746808Sdab /* ARGSUSED */
83865157Sdab SIG_FUNC_RET
deadpeer(sig)83945233Sborman deadpeer(sig)
84046808Sdab int sig;
84132553Sminshall {
84232553Sminshall setcommandmode();
84332553Sminshall longjmp(peerdied, -1);
84432553Sminshall }
84532147Sminshall
84646808Sdab /* ARGSUSED */
84765157Sdab SIG_FUNC_RET
intr(sig)84845233Sborman intr(sig)
84946808Sdab int sig;
85032553Sminshall {
85132553Sminshall if (localchars) {
85232553Sminshall intp();
85332553Sminshall return;
85432553Sminshall }
85532553Sminshall setcommandmode();
85632553Sminshall longjmp(toplevel, -1);
85732553Sminshall }
85832553Sminshall
85946808Sdab /* ARGSUSED */
86065157Sdab SIG_FUNC_RET
intr2(sig)86145233Sborman intr2(sig)
86246808Sdab int sig;
86332553Sminshall {
86432553Sminshall if (localchars) {
86538689Sborman #ifdef KLUDGELINEMODE
86638689Sborman if (kludgelinemode)
86738689Sborman sendbrk();
86838689Sborman else
86938689Sborman #endif
87038689Sborman sendabort();
87132553Sminshall return;
87232553Sminshall }
87332553Sminshall }
87432553Sminshall
87545233Sborman #ifdef SIGTSTP
87646808Sdab /* ARGSUSED */
87765157Sdab SIG_FUNC_RET
susp(sig)87845233Sborman susp(sig)
87946808Sdab int sig;
88040245Sborman {
88146808Sdab if ((rlogin != _POSIX_VDISABLE) && rlogin_susp())
88246808Sdab return;
88340245Sborman if (localchars)
88440245Sborman sendsusp();
88540245Sborman }
88645233Sborman #endif
88740245Sborman
88845233Sborman #ifdef SIGWINCH
88946808Sdab /* ARGSUSED */
89065157Sdab SIG_FUNC_RET
sendwin(sig)89145233Sborman sendwin(sig)
89246808Sdab int sig;
89337219Sminshall {
89437219Sminshall if (connected) {
89537219Sminshall sendnaws();
89637219Sminshall }
89737219Sminshall }
89845233Sborman #endif
89937219Sminshall
90045233Sborman #ifdef SIGINFO
90146808Sdab /* ARGSUSED */
90265157Sdab SIG_FUNC_RET
ayt(sig)90345233Sborman ayt(sig)
90446808Sdab int sig;
90545233Sborman {
90645233Sborman if (connected)
90745233Sborman sendayt();
90845233Sborman else
90945233Sborman ayt_status();
91045233Sborman }
91145233Sborman #endif
91245233Sborman
91332553Sminshall
91446808Sdab void
sys_telnet_init()91532531Sminshall sys_telnet_init()
91632531Sminshall {
91745233Sborman (void) signal(SIGINT, intr);
91845233Sborman (void) signal(SIGQUIT, intr2);
91945233Sborman (void) signal(SIGPIPE, deadpeer);
92038689Sborman #ifdef SIGWINCH
92145233Sborman (void) signal(SIGWINCH, sendwin);
92238689Sborman #endif
92340245Sborman #ifdef SIGTSTP
92445233Sborman (void) signal(SIGTSTP, susp);
92540245Sborman #endif
92645233Sborman #ifdef SIGINFO
92745233Sborman (void) signal(SIGINFO, ayt);
92845233Sborman #endif
92932553Sminshall
93038689Sborman setconnmode(0);
93132531Sminshall
93232531Sminshall NetNonblockingIO(net, 1);
93332531Sminshall
93432531Sminshall #if defined(TN3270)
93536242Sminshall if (noasynchnet == 0) { /* DBX can't handle! */
93632531Sminshall NetSigIO(net, 1);
93732531Sminshall NetSetPgrp(net);
93832531Sminshall }
93932531Sminshall #endif /* defined(TN3270) */
94032531Sminshall
94132531Sminshall #if defined(SO_OOBINLINE)
94234849Sminshall if (SetSockOpt(net, SOL_SOCKET, SO_OOBINLINE, 1) == -1) {
94334849Sminshall perror("SetSockOpt");
94434849Sminshall }
94532531Sminshall #endif /* defined(SO_OOBINLINE) */
94632531Sminshall }
94732531Sminshall
94832531Sminshall /*
94932531Sminshall * Process rings -
95032531Sminshall *
95132531Sminshall * This routine tries to fill up/empty our various rings.
95232531Sminshall *
95332531Sminshall * The parameter specifies whether this is a poll operation,
95432531Sminshall * or a block-until-something-happens operation.
95532531Sminshall *
95632531Sminshall * The return value is 1 if something happened, 0 if not.
95732531Sminshall */
95832531Sminshall
95946808Sdab int
process_rings(netin,netout,netex,ttyin,ttyout,poll)96032531Sminshall process_rings(netin, netout, netex, ttyin, ttyout, poll)
96146808Sdab int poll; /* If 0, then block until something to do */
96232531Sminshall {
96332531Sminshall register int c;
96432531Sminshall /* One wants to be a bit careful about setting returnValue
96532531Sminshall * to one, since a one implies we did some useful work,
96632531Sminshall * and therefore probably won't be called to block next
96732531Sminshall * time (TN3270 mode only).
96832531Sminshall */
96932531Sminshall int returnValue = 0;
97032531Sminshall static struct timeval TimeValue = { 0 };
97132531Sminshall
97232531Sminshall if (netout) {
97332531Sminshall FD_SET(net, &obits);
974*69785Sdab }
97532531Sminshall if (ttyout) {
97632531Sminshall FD_SET(tout, &obits);
97732531Sminshall }
97832531Sminshall #if defined(TN3270)
97932531Sminshall if (ttyin) {
98032531Sminshall FD_SET(tin, &ibits);
98132531Sminshall }
98232531Sminshall #else /* defined(TN3270) */
98332531Sminshall if (ttyin) {
98432531Sminshall FD_SET(tin, &ibits);
98532531Sminshall }
98632531Sminshall #endif /* defined(TN3270) */
98732531Sminshall #if defined(TN3270)
98832531Sminshall if (netin) {
98932531Sminshall FD_SET(net, &ibits);
99032531Sminshall }
99132531Sminshall # else /* !defined(TN3270) */
99232531Sminshall if (netin) {
99332531Sminshall FD_SET(net, &ibits);
99432531Sminshall }
99532531Sminshall # endif /* !defined(TN3270) */
99632531Sminshall if (netex) {
99732531Sminshall FD_SET(net, &xbits);
99832531Sminshall }
99932531Sminshall if ((c = select(16, &ibits, &obits, &xbits,
100032531Sminshall (poll == 0)? (struct timeval *)0 : &TimeValue)) < 0) {
100132531Sminshall if (c == -1) {
100232531Sminshall /*
100332531Sminshall * we can get EINTR if we are in line mode,
100432531Sminshall * and the user does an escape (TSTP), or
100532531Sminshall * some other signal generator.
100632531Sminshall */
100732531Sminshall if (errno == EINTR) {
100832531Sminshall return 0;
100932531Sminshall }
101032531Sminshall # if defined(TN3270)
101132531Sminshall /*
101232531Sminshall * we can get EBADF if we were in transparent
101332531Sminshall * mode, and the transcom process died.
101432531Sminshall */
101532531Sminshall if (errno == EBADF) {
101632531Sminshall /*
101732531Sminshall * zero the bits (even though kernel does it)
101832531Sminshall * to make sure we are selecting on the right
101932531Sminshall * ones.
102032531Sminshall */
102132531Sminshall FD_ZERO(&ibits);
102232531Sminshall FD_ZERO(&obits);
102332531Sminshall FD_ZERO(&xbits);
102432531Sminshall return 0;
102532531Sminshall }
102632531Sminshall # endif /* defined(TN3270) */
102732531Sminshall /* I don't like this, does it ever happen? */
102832531Sminshall printf("sleep(5) from telnet, after select\r\n");
102932531Sminshall sleep(5);
103032531Sminshall }
103132531Sminshall return 0;
103232531Sminshall }
103332531Sminshall
103432531Sminshall /*
103532531Sminshall * Any urgent data?
103632531Sminshall */
103732531Sminshall if (FD_ISSET(net, &xbits)) {
103832531Sminshall FD_CLR(net, &xbits);
103932531Sminshall SYNCHing = 1;
104044361Sborman (void) ttyflush(1); /* flush already enqueued data */
104132531Sminshall }
104232531Sminshall
104332531Sminshall /*
104432531Sminshall * Something to read from the network...
104532531Sminshall */
104632531Sminshall if (FD_ISSET(net, &ibits)) {
104732531Sminshall int canread;
104832531Sminshall
104932531Sminshall FD_CLR(net, &ibits);
105032531Sminshall canread = ring_empty_consecutive(&netiring);
105132531Sminshall #if !defined(SO_OOBINLINE)
105232531Sminshall /*
105332531Sminshall * In 4.2 (and some early 4.3) systems, the
105432531Sminshall * OOB indication and data handling in the kernel
105532531Sminshall * is such that if two separate TCP Urgent requests
105632531Sminshall * come in, one byte of TCP data will be overlaid.
105732531Sminshall * This is fatal for Telnet, but we try to live
105832531Sminshall * with it.
105932531Sminshall *
106032531Sminshall * In addition, in 4.2 (and...), a special protocol
106132531Sminshall * is needed to pick up the TCP Urgent data in
106232531Sminshall * the correct sequence.
106332531Sminshall *
106432531Sminshall * What we do is: if we think we are in urgent
106532531Sminshall * mode, we look to see if we are "at the mark".
106632531Sminshall * If we are, we do an OOB receive. If we run
106732531Sminshall * this twice, we will do the OOB receive twice,
106832531Sminshall * but the second will fail, since the second
106932531Sminshall * time we were "at the mark", but there wasn't
107032531Sminshall * any data there (the kernel doesn't reset
107132531Sminshall * "at the mark" until we do a normal read).
107232531Sminshall * Once we've read the OOB data, we go ahead
107332531Sminshall * and do normal reads.
107432531Sminshall *
107532531Sminshall * There is also another problem, which is that
107632531Sminshall * since the OOB byte we read doesn't put us
107732531Sminshall * out of OOB state, and since that byte is most
107832531Sminshall * likely the TELNET DM (data mark), we would
107932531Sminshall * stay in the TELNET SYNCH (SYNCHing) state.
108032531Sminshall * So, clocks to the rescue. If we've "just"
108132531Sminshall * received a DM, then we test for the
108232531Sminshall * presence of OOB data when the receive OOB
108332531Sminshall * fails (and AFTER we did the normal mode read
108432531Sminshall * to clear "at the mark").
108532531Sminshall */
108632531Sminshall if (SYNCHing) {
108732531Sminshall int atmark;
108839652Sborman static int bogus_oob = 0, first = 1;
108932531Sminshall
109032531Sminshall ioctl(net, SIOCATMARK, (char *)&atmark);
109132531Sminshall if (atmark) {
109232531Sminshall c = recv(net, netiring.supply, canread, MSG_OOB);
109332531Sminshall if ((c == -1) && (errno == EINVAL)) {
109432531Sminshall c = recv(net, netiring.supply, canread, 0);
109532531Sminshall if (clocks.didnetreceive < clocks.gotDM) {
109632531Sminshall SYNCHing = stilloob(net);
109732531Sminshall }
109839652Sborman } else if (first && c > 0) {
109939652Sborman /*
110039652Sborman * Bogosity check. Systems based on 4.2BSD
110139652Sborman * do not return an error if you do a second
110239652Sborman * recv(MSG_OOB). So, we do one. If it
110339652Sborman * succeeds and returns exactly the same
110439652Sborman * data, then assume that we are running
110539652Sborman * on a broken system and set the bogus_oob
110639652Sborman * flag. (If the data was different, then
110739652Sborman * we probably got some valid new data, so
110839652Sborman * increment the count...)
110939652Sborman */
111039652Sborman int i;
111139652Sborman i = recv(net, netiring.supply + c, canread - c, MSG_OOB);
111239652Sborman if (i == c &&
1113*69785Sdab memcmp(netiring.supply, netiring.supply + c, i) == 0) {
111439652Sborman bogus_oob = 1;
111539652Sborman first = 0;
111639652Sborman } else if (i < 0) {
111739652Sborman bogus_oob = 0;
111839652Sborman first = 0;
111939652Sborman } else
112039652Sborman c += i;
112132531Sminshall }
112239652Sborman if (bogus_oob && c > 0) {
112339652Sborman int i;
112439652Sborman /*
112539652Sborman * Bogosity. We have to do the read
112639652Sborman * to clear the atmark to get out of
112739652Sborman * an infinate loop.
112839652Sborman */
112939652Sborman i = read(net, netiring.supply + c, canread - c);
113039652Sborman if (i > 0)
113139652Sborman c += i;
113239652Sborman }
113332531Sminshall } else {
113432531Sminshall c = recv(net, netiring.supply, canread, 0);
113532531Sminshall }
113632531Sminshall } else {
113732531Sminshall c = recv(net, netiring.supply, canread, 0);
113832531Sminshall }
113932531Sminshall settimer(didnetreceive);
114032531Sminshall #else /* !defined(SO_OOBINLINE) */
114165157Sdab c = recv(net, (char *)netiring.supply, canread, 0);
114232531Sminshall #endif /* !defined(SO_OOBINLINE) */
114332531Sminshall if (c < 0 && errno == EWOULDBLOCK) {
114432531Sminshall c = 0;
114532531Sminshall } else if (c <= 0) {
114632531Sminshall return -1;
114732531Sminshall }
114832531Sminshall if (netdata) {
114932531Sminshall Dump('<', netiring.supply, c);
115032531Sminshall }
115132667Sminshall if (c)
115232667Sminshall ring_supplied(&netiring, c);
115332531Sminshall returnValue = 1;
115432531Sminshall }
115532531Sminshall
115632531Sminshall /*
115732531Sminshall * Something to read from the tty...
115832531Sminshall */
115932531Sminshall if (FD_ISSET(tin, &ibits)) {
116032531Sminshall FD_CLR(tin, &ibits);
116133286Sminshall c = TerminalRead(ttyiring.supply, ring_empty_consecutive(&ttyiring));
116268345Sdab if (c < 0 && errno == EIO)
116368345Sdab c = 0;
116432531Sminshall if (c < 0 && errno == EWOULDBLOCK) {
116532531Sminshall c = 0;
116632531Sminshall } else {
116732531Sminshall /* EOF detection for line mode!!!! */
116833281Sminshall if ((c == 0) && MODE_LOCAL_CHARS(globalmode) && isatty(tin)) {
116932531Sminshall /* must be an EOF... */
117032531Sminshall *ttyiring.supply = termEofChar;
117132531Sminshall c = 1;
117232531Sminshall }
117332531Sminshall if (c <= 0) {
117432531Sminshall return -1;
117532531Sminshall }
117638208Sminshall if (termdata) {
117738208Sminshall Dump('<', ttyiring.supply, c);
117838208Sminshall }
117932667Sminshall ring_supplied(&ttyiring, c);
118032531Sminshall }
118132531Sminshall returnValue = 1; /* did something useful */
118232531Sminshall }
118332531Sminshall
118432531Sminshall if (FD_ISSET(net, &obits)) {
118532531Sminshall FD_CLR(net, &obits);
118632531Sminshall returnValue |= netflush();
118732531Sminshall }
118832531Sminshall if (FD_ISSET(tout, &obits)) {
118932531Sminshall FD_CLR(tout, &obits);
119038689Sborman returnValue |= (ttyflush(SYNCHing|flushout) > 0);
119132531Sminshall }
119232531Sminshall
119332531Sminshall return returnValue;
119432531Sminshall }
1195