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*68345Sdab static char sccsid[] = "@(#)sys_bsd.c 8.3 (Berkeley) 02/16/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 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 10833286Sminshall TerminalWrite(buf, n) 10946808Sdab char *buf; 11046808Sdab int n; 11132147Sminshall { 11233286Sminshall return write(tout, buf, n); 11332147Sminshall } 11432147Sminshall 11546808Sdab int 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 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 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 */ 20032147Sminshall 20146808Sdab void 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 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 * 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 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 */ 30538689Sborman memcpy(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 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 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); 64644361Sborman (void) sigsetmask(sigblock(0) & ~(1<<(SIGTSTP-1))); 64739529Sborman #endif /* SIGTSTP */ 64839529Sborman #ifndef USE_TERMIO 64939529Sborman ltc = oltc; 65039529Sborman tc = otc; 65139529Sborman sb = ottyb; 65244361Sborman lmode = olmode; 65344361Sborman #else 65444361Sborman tmp_tc = old_tc; 65539529Sborman #endif 65638689Sborman } 65739529Sborman #ifndef USE_TERMIO 65839529Sborman ioctl(tin, TIOCLSET, (char *)&lmode); 65939529Sborman ioctl(tin, TIOCSLTC, (char *)<c); 66039529Sborman ioctl(tin, TIOCSETC, (char *)&tc); 66145233Sborman ioctl(tin, TIOCSETN, (char *)&sb); 66239529Sborman #else 66345233Sborman if (tcsetattr(tin, TCSADRAIN, &tmp_tc) < 0) 66445233Sborman tcsetattr(tin, TCSANOW, &tmp_tc); 66539529Sborman #endif 66639529Sborman 66732147Sminshall #if (!defined(TN3270)) || ((!defined(NOT43)) || defined(PUTCHAR)) 66857213Sdab # if !defined(sysV88) 66933286Sminshall ioctl(tin, FIONBIO, (char *)&onoff); 67033286Sminshall ioctl(tout, FIONBIO, (char *)&onoff); 67157213Sdab # endif 67232147Sminshall #endif /* (!defined(TN3270)) || ((!defined(NOT43)) || defined(PUTCHAR)) */ 67332147Sminshall #if defined(TN3270) 67436242Sminshall if (noasynchtty == 0) { 67533286Sminshall ioctl(tin, FIOASYNC, (char *)&onoff); 67632147Sminshall } 67732147Sminshall #endif /* defined(TN3270) */ 67846808Sdab 67932147Sminshall } 68032147Sminshall 681*68345Sdab /* 682*68345Sdab * Try to guess whether speeds are "encoded" (4.2BSD) or just numeric (4.4BSD). 683*68345Sdab */ 684*68345Sdab #if B4800 != 4800 685*68345Sdab #define DECODE_BAUD 686*68345Sdab #endif 687*68345Sdab 688*68345Sdab #ifdef DECODE_BAUD 689*68345Sdab #ifndef B7200 690*68345Sdab #define B7200 B4800 691*68345Sdab #endif 692*68345Sdab 693*68345Sdab #ifndef B14400 694*68345Sdab #define B14400 B9600 695*68345Sdab #endif 696*68345Sdab 69739529Sborman #ifndef B19200 698*68345Sdab # define B19200 B14400 69939529Sborman #endif 70039529Sborman 701*68345Sdab #ifndef B28800 702*68345Sdab #define B28800 B19200 703*68345Sdab #endif 704*68345Sdab 70539529Sborman #ifndef B38400 706*68345Sdab # define B38400 B28800 70739529Sborman #endif 70839529Sborman 709*68345Sdab #ifndef B57600 710*68345Sdab #define B57600 B38400 711*68345Sdab #endif 712*68345Sdab 713*68345Sdab #ifndef B76800 714*68345Sdab #define B76800 B57600 715*68345Sdab #endif 716*68345Sdab 717*68345Sdab #ifndef B115200 718*68345Sdab #define B115200 B76800 719*68345Sdab #endif 720*68345Sdab 721*68345Sdab #ifndef B230400 722*68345Sdab #define B230400 B115200 723*68345Sdab #endif 724*68345Sdab 725*68345Sdab 72639529Sborman /* 72739529Sborman * This code assumes that the values B0, B50, B75... 72839529Sborman * are in ascending order. They do not have to be 72939529Sborman * contiguous. 73039529Sborman */ 73139529Sborman struct termspeeds { 73239529Sborman long speed; 73339529Sborman long value; 73439529Sborman } termspeeds[] = { 735*68345Sdab { 0, B0 }, { 50, B50 }, { 75, B75 }, 736*68345Sdab { 110, B110 }, { 134, B134 }, { 150, B150 }, 737*68345Sdab { 200, B200 }, { 300, B300 }, { 600, B600 }, 738*68345Sdab { 1200, B1200 }, { 1800, B1800 }, { 2400, B2400 }, 739*68345Sdab { 4800, B4800 }, { 7200, B7200 }, { 9600, B9600 }, 740*68345Sdab { 14400, B14400 }, { 19200, B19200 }, { 28800, B28800 }, 741*68345Sdab { 38400, B38400 }, { 57600, B57600 }, { 115200, B115200 }, 742*68345Sdab { 230400, B230400 }, { -1, B230400 } 74339529Sborman }; 744*68345Sdab #endif /* DECODE_BAUD */ 74539529Sborman 74646808Sdab void 74737219Sminshall TerminalSpeeds(ispeed, ospeed) 74846808Sdab long *ispeed; 74946808Sdab long *ospeed; 75037219Sminshall { 751*68345Sdab #ifdef DECODE_BAUD 75239529Sborman register struct termspeeds *tp; 753*68345Sdab #endif /* DECODE_BAUD */ 75445233Sborman register long in, out; 75532147Sminshall 75646808Sdab out = cfgetospeed(&old_tc); 75745233Sborman in = cfgetispeed(&old_tc); 75846808Sdab if (in == 0) 75946808Sdab in = out; 76045233Sborman 761*68345Sdab #ifdef DECODE_BAUD 76239529Sborman tp = termspeeds; 76345233Sborman while ((tp->speed != -1) && (tp->value < in)) 76439529Sborman tp++; 76539529Sborman *ispeed = tp->speed; 76639529Sborman 76739529Sborman tp = termspeeds; 76845233Sborman while ((tp->speed != -1) && (tp->value < out)) 76939529Sborman tp++; 77039529Sborman *ospeed = tp->speed; 771*68345Sdab #else /* DECODE_BAUD */ 772*68345Sdab *ispeed = in; 773*68345Sdab *ospeed = out; 774*68345Sdab #endif /* DECODE_BAUD */ 77537219Sminshall } 77637219Sminshall 77746808Sdab int 77837219Sminshall TerminalWindowSize(rows, cols) 77946808Sdab long *rows, *cols; 78037219Sminshall { 78138689Sborman #ifdef TIOCGWINSZ 78237219Sminshall struct winsize ws; 78337219Sminshall 78438689Sborman if (ioctl(fileno(stdin), TIOCGWINSZ, (char *)&ws) >= 0) { 78538689Sborman *rows = ws.ws_row; 78638689Sborman *cols = ws.ws_col; 78738689Sborman return 1; 78837219Sminshall } 78938810Sborman #endif /* TIOCGWINSZ */ 79038689Sborman return 0; 79137219Sminshall } 79237219Sminshall 79346808Sdab int 79435417Sminshall NetClose(fd) 79546808Sdab int fd; 79632147Sminshall { 79735417Sminshall return close(fd); 79832147Sminshall } 79932147Sminshall 80032147Sminshall 80146808Sdab void 80232553Sminshall NetNonblockingIO(fd, onoff) 80346808Sdab int fd; 80446808Sdab int onoff; 80532147Sminshall { 80632147Sminshall ioctl(fd, FIONBIO, (char *)&onoff); 80732147Sminshall } 80832147Sminshall 80934849Sminshall #if defined(TN3270) 81046808Sdab void 81132553Sminshall NetSigIO(fd, onoff) 81246808Sdab int fd; 81346808Sdab int onoff; 81432147Sminshall { 81532147Sminshall ioctl(fd, FIOASYNC, (char *)&onoff); /* hear about input */ 81632147Sminshall } 81732147Sminshall 81846808Sdab void 81932553Sminshall NetSetPgrp(fd) 82046808Sdab int fd; 82132147Sminshall { 82232147Sminshall int myPid; 82332147Sminshall 82432147Sminshall myPid = getpid(); 82536274Sminshall fcntl(fd, F_SETOWN, myPid); 82632147Sminshall } 82734849Sminshall #endif /*defined(TN3270)*/ 82832553Sminshall 82932553Sminshall /* 83032553Sminshall * Various signal handling routines. 83132553Sminshall */ 83232147Sminshall 83346808Sdab /* ARGSUSED */ 83465157Sdab SIG_FUNC_RET 83545233Sborman deadpeer(sig) 83646808Sdab int sig; 83732553Sminshall { 83832553Sminshall setcommandmode(); 83932553Sminshall longjmp(peerdied, -1); 84032553Sminshall } 84132147Sminshall 84246808Sdab /* ARGSUSED */ 84365157Sdab SIG_FUNC_RET 84445233Sborman intr(sig) 84546808Sdab int sig; 84632553Sminshall { 84732553Sminshall if (localchars) { 84832553Sminshall intp(); 84932553Sminshall return; 85032553Sminshall } 85132553Sminshall setcommandmode(); 85232553Sminshall longjmp(toplevel, -1); 85332553Sminshall } 85432553Sminshall 85546808Sdab /* ARGSUSED */ 85665157Sdab SIG_FUNC_RET 85745233Sborman intr2(sig) 85846808Sdab int sig; 85932553Sminshall { 86032553Sminshall if (localchars) { 86138689Sborman #ifdef KLUDGELINEMODE 86238689Sborman if (kludgelinemode) 86338689Sborman sendbrk(); 86438689Sborman else 86538689Sborman #endif 86638689Sborman sendabort(); 86732553Sminshall return; 86832553Sminshall } 86932553Sminshall } 87032553Sminshall 87145233Sborman #ifdef SIGTSTP 87246808Sdab /* ARGSUSED */ 87365157Sdab SIG_FUNC_RET 87445233Sborman susp(sig) 87546808Sdab int sig; 87640245Sborman { 87746808Sdab if ((rlogin != _POSIX_VDISABLE) && rlogin_susp()) 87846808Sdab return; 87940245Sborman if (localchars) 88040245Sborman sendsusp(); 88140245Sborman } 88245233Sborman #endif 88340245Sborman 88445233Sborman #ifdef SIGWINCH 88546808Sdab /* ARGSUSED */ 88665157Sdab SIG_FUNC_RET 88745233Sborman sendwin(sig) 88846808Sdab int sig; 88937219Sminshall { 89037219Sminshall if (connected) { 89137219Sminshall sendnaws(); 89237219Sminshall } 89337219Sminshall } 89445233Sborman #endif 89537219Sminshall 89645233Sborman #ifdef SIGINFO 89746808Sdab /* ARGSUSED */ 89865157Sdab SIG_FUNC_RET 89945233Sborman ayt(sig) 90046808Sdab int sig; 90145233Sborman { 90245233Sborman if (connected) 90345233Sborman sendayt(); 90445233Sborman else 90545233Sborman ayt_status(); 90645233Sborman } 90745233Sborman #endif 90845233Sborman 90932553Sminshall 91046808Sdab void 91132531Sminshall sys_telnet_init() 91232531Sminshall { 91345233Sborman (void) signal(SIGINT, intr); 91445233Sborman (void) signal(SIGQUIT, intr2); 91545233Sborman (void) signal(SIGPIPE, deadpeer); 91638689Sborman #ifdef SIGWINCH 91745233Sborman (void) signal(SIGWINCH, sendwin); 91838689Sborman #endif 91940245Sborman #ifdef SIGTSTP 92045233Sborman (void) signal(SIGTSTP, susp); 92140245Sborman #endif 92245233Sborman #ifdef SIGINFO 92345233Sborman (void) signal(SIGINFO, ayt); 92445233Sborman #endif 92532553Sminshall 92638689Sborman setconnmode(0); 92732531Sminshall 92832531Sminshall NetNonblockingIO(net, 1); 92932531Sminshall 93032531Sminshall #if defined(TN3270) 93136242Sminshall if (noasynchnet == 0) { /* DBX can't handle! */ 93232531Sminshall NetSigIO(net, 1); 93332531Sminshall NetSetPgrp(net); 93432531Sminshall } 93532531Sminshall #endif /* defined(TN3270) */ 93632531Sminshall 93732531Sminshall #if defined(SO_OOBINLINE) 93834849Sminshall if (SetSockOpt(net, SOL_SOCKET, SO_OOBINLINE, 1) == -1) { 93934849Sminshall perror("SetSockOpt"); 94034849Sminshall } 94132531Sminshall #endif /* defined(SO_OOBINLINE) */ 94232531Sminshall } 94332531Sminshall 94432531Sminshall /* 94532531Sminshall * Process rings - 94632531Sminshall * 94732531Sminshall * This routine tries to fill up/empty our various rings. 94832531Sminshall * 94932531Sminshall * The parameter specifies whether this is a poll operation, 95032531Sminshall * or a block-until-something-happens operation. 95132531Sminshall * 95232531Sminshall * The return value is 1 if something happened, 0 if not. 95332531Sminshall */ 95432531Sminshall 95546808Sdab int 95632531Sminshall process_rings(netin, netout, netex, ttyin, ttyout, poll) 95746808Sdab int poll; /* If 0, then block until something to do */ 95832531Sminshall { 95932531Sminshall register int c; 96032531Sminshall /* One wants to be a bit careful about setting returnValue 96132531Sminshall * to one, since a one implies we did some useful work, 96232531Sminshall * and therefore probably won't be called to block next 96332531Sminshall * time (TN3270 mode only). 96432531Sminshall */ 96532531Sminshall int returnValue = 0; 96632531Sminshall static struct timeval TimeValue = { 0 }; 96732531Sminshall 96832531Sminshall if (netout) { 96932531Sminshall FD_SET(net, &obits); 97032531Sminshall } 97132531Sminshall if (ttyout) { 97232531Sminshall FD_SET(tout, &obits); 97332531Sminshall } 97432531Sminshall #if defined(TN3270) 97532531Sminshall if (ttyin) { 97632531Sminshall FD_SET(tin, &ibits); 97732531Sminshall } 97832531Sminshall #else /* defined(TN3270) */ 97932531Sminshall if (ttyin) { 98032531Sminshall FD_SET(tin, &ibits); 98132531Sminshall } 98232531Sminshall #endif /* defined(TN3270) */ 98332531Sminshall #if defined(TN3270) 98432531Sminshall if (netin) { 98532531Sminshall FD_SET(net, &ibits); 98632531Sminshall } 98732531Sminshall # else /* !defined(TN3270) */ 98832531Sminshall if (netin) { 98932531Sminshall FD_SET(net, &ibits); 99032531Sminshall } 99132531Sminshall # endif /* !defined(TN3270) */ 99232531Sminshall if (netex) { 99332531Sminshall FD_SET(net, &xbits); 99432531Sminshall } 99532531Sminshall if ((c = select(16, &ibits, &obits, &xbits, 99632531Sminshall (poll == 0)? (struct timeval *)0 : &TimeValue)) < 0) { 99732531Sminshall if (c == -1) { 99832531Sminshall /* 99932531Sminshall * we can get EINTR if we are in line mode, 100032531Sminshall * and the user does an escape (TSTP), or 100132531Sminshall * some other signal generator. 100232531Sminshall */ 100332531Sminshall if (errno == EINTR) { 100432531Sminshall return 0; 100532531Sminshall } 100632531Sminshall # if defined(TN3270) 100732531Sminshall /* 100832531Sminshall * we can get EBADF if we were in transparent 100932531Sminshall * mode, and the transcom process died. 101032531Sminshall */ 101132531Sminshall if (errno == EBADF) { 101232531Sminshall /* 101332531Sminshall * zero the bits (even though kernel does it) 101432531Sminshall * to make sure we are selecting on the right 101532531Sminshall * ones. 101632531Sminshall */ 101732531Sminshall FD_ZERO(&ibits); 101832531Sminshall FD_ZERO(&obits); 101932531Sminshall FD_ZERO(&xbits); 102032531Sminshall return 0; 102132531Sminshall } 102232531Sminshall # endif /* defined(TN3270) */ 102332531Sminshall /* I don't like this, does it ever happen? */ 102432531Sminshall printf("sleep(5) from telnet, after select\r\n"); 102532531Sminshall sleep(5); 102632531Sminshall } 102732531Sminshall return 0; 102832531Sminshall } 102932531Sminshall 103032531Sminshall /* 103132531Sminshall * Any urgent data? 103232531Sminshall */ 103332531Sminshall if (FD_ISSET(net, &xbits)) { 103432531Sminshall FD_CLR(net, &xbits); 103532531Sminshall SYNCHing = 1; 103644361Sborman (void) ttyflush(1); /* flush already enqueued data */ 103732531Sminshall } 103832531Sminshall 103932531Sminshall /* 104032531Sminshall * Something to read from the network... 104132531Sminshall */ 104232531Sminshall if (FD_ISSET(net, &ibits)) { 104332531Sminshall int canread; 104432531Sminshall 104532531Sminshall FD_CLR(net, &ibits); 104632531Sminshall canread = ring_empty_consecutive(&netiring); 104732531Sminshall #if !defined(SO_OOBINLINE) 104832531Sminshall /* 104932531Sminshall * In 4.2 (and some early 4.3) systems, the 105032531Sminshall * OOB indication and data handling in the kernel 105132531Sminshall * is such that if two separate TCP Urgent requests 105232531Sminshall * come in, one byte of TCP data will be overlaid. 105332531Sminshall * This is fatal for Telnet, but we try to live 105432531Sminshall * with it. 105532531Sminshall * 105632531Sminshall * In addition, in 4.2 (and...), a special protocol 105732531Sminshall * is needed to pick up the TCP Urgent data in 105832531Sminshall * the correct sequence. 105932531Sminshall * 106032531Sminshall * What we do is: if we think we are in urgent 106132531Sminshall * mode, we look to see if we are "at the mark". 106232531Sminshall * If we are, we do an OOB receive. If we run 106332531Sminshall * this twice, we will do the OOB receive twice, 106432531Sminshall * but the second will fail, since the second 106532531Sminshall * time we were "at the mark", but there wasn't 106632531Sminshall * any data there (the kernel doesn't reset 106732531Sminshall * "at the mark" until we do a normal read). 106832531Sminshall * Once we've read the OOB data, we go ahead 106932531Sminshall * and do normal reads. 107032531Sminshall * 107132531Sminshall * There is also another problem, which is that 107232531Sminshall * since the OOB byte we read doesn't put us 107332531Sminshall * out of OOB state, and since that byte is most 107432531Sminshall * likely the TELNET DM (data mark), we would 107532531Sminshall * stay in the TELNET SYNCH (SYNCHing) state. 107632531Sminshall * So, clocks to the rescue. If we've "just" 107732531Sminshall * received a DM, then we test for the 107832531Sminshall * presence of OOB data when the receive OOB 107932531Sminshall * fails (and AFTER we did the normal mode read 108032531Sminshall * to clear "at the mark"). 108132531Sminshall */ 108232531Sminshall if (SYNCHing) { 108332531Sminshall int atmark; 108439652Sborman static int bogus_oob = 0, first = 1; 108532531Sminshall 108632531Sminshall ioctl(net, SIOCATMARK, (char *)&atmark); 108732531Sminshall if (atmark) { 108832531Sminshall c = recv(net, netiring.supply, canread, MSG_OOB); 108932531Sminshall if ((c == -1) && (errno == EINVAL)) { 109032531Sminshall c = recv(net, netiring.supply, canread, 0); 109132531Sminshall if (clocks.didnetreceive < clocks.gotDM) { 109232531Sminshall SYNCHing = stilloob(net); 109332531Sminshall } 109439652Sborman } else if (first && c > 0) { 109539652Sborman /* 109639652Sborman * Bogosity check. Systems based on 4.2BSD 109739652Sborman * do not return an error if you do a second 109839652Sborman * recv(MSG_OOB). So, we do one. If it 109939652Sborman * succeeds and returns exactly the same 110039652Sborman * data, then assume that we are running 110139652Sborman * on a broken system and set the bogus_oob 110239652Sborman * flag. (If the data was different, then 110339652Sborman * we probably got some valid new data, so 110439652Sborman * increment the count...) 110539652Sborman */ 110639652Sborman int i; 110739652Sborman i = recv(net, netiring.supply + c, canread - c, MSG_OOB); 110839652Sborman if (i == c && 110939652Sborman bcmp(netiring.supply, netiring.supply + c, i) == 0) { 111039652Sborman bogus_oob = 1; 111139652Sborman first = 0; 111239652Sborman } else if (i < 0) { 111339652Sborman bogus_oob = 0; 111439652Sborman first = 0; 111539652Sborman } else 111639652Sborman c += i; 111732531Sminshall } 111839652Sborman if (bogus_oob && c > 0) { 111939652Sborman int i; 112039652Sborman /* 112139652Sborman * Bogosity. We have to do the read 112239652Sborman * to clear the atmark to get out of 112339652Sborman * an infinate loop. 112439652Sborman */ 112539652Sborman i = read(net, netiring.supply + c, canread - c); 112639652Sborman if (i > 0) 112739652Sborman c += i; 112839652Sborman } 112932531Sminshall } else { 113032531Sminshall c = recv(net, netiring.supply, canread, 0); 113132531Sminshall } 113232531Sminshall } else { 113332531Sminshall c = recv(net, netiring.supply, canread, 0); 113432531Sminshall } 113532531Sminshall settimer(didnetreceive); 113632531Sminshall #else /* !defined(SO_OOBINLINE) */ 113765157Sdab c = recv(net, (char *)netiring.supply, canread, 0); 113832531Sminshall #endif /* !defined(SO_OOBINLINE) */ 113932531Sminshall if (c < 0 && errno == EWOULDBLOCK) { 114032531Sminshall c = 0; 114132531Sminshall } else if (c <= 0) { 114232531Sminshall return -1; 114332531Sminshall } 114432531Sminshall if (netdata) { 114532531Sminshall Dump('<', netiring.supply, c); 114632531Sminshall } 114732667Sminshall if (c) 114832667Sminshall ring_supplied(&netiring, c); 114932531Sminshall returnValue = 1; 115032531Sminshall } 115132531Sminshall 115232531Sminshall /* 115332531Sminshall * Something to read from the tty... 115432531Sminshall */ 115532531Sminshall if (FD_ISSET(tin, &ibits)) { 115632531Sminshall FD_CLR(tin, &ibits); 115733286Sminshall c = TerminalRead(ttyiring.supply, ring_empty_consecutive(&ttyiring)); 1158*68345Sdab if (c < 0 && errno == EIO) 1159*68345Sdab c = 0; 116032531Sminshall if (c < 0 && errno == EWOULDBLOCK) { 116132531Sminshall c = 0; 116232531Sminshall } else { 116332531Sminshall /* EOF detection for line mode!!!! */ 116433281Sminshall if ((c == 0) && MODE_LOCAL_CHARS(globalmode) && isatty(tin)) { 116532531Sminshall /* must be an EOF... */ 116632531Sminshall *ttyiring.supply = termEofChar; 116732531Sminshall c = 1; 116832531Sminshall } 116932531Sminshall if (c <= 0) { 117032531Sminshall return -1; 117132531Sminshall } 117238208Sminshall if (termdata) { 117338208Sminshall Dump('<', ttyiring.supply, c); 117438208Sminshall } 117532667Sminshall ring_supplied(&ttyiring, c); 117632531Sminshall } 117732531Sminshall returnValue = 1; /* did something useful */ 117832531Sminshall } 117932531Sminshall 118032531Sminshall if (FD_ISSET(net, &obits)) { 118132531Sminshall FD_CLR(net, &obits); 118232531Sminshall returnValue |= netflush(); 118332531Sminshall } 118432531Sminshall if (FD_ISSET(tout, &obits)) { 118532531Sminshall FD_CLR(tout, &obits); 118638689Sborman returnValue |= (ttyflush(SYNCHing|flushout) > 0); 118732531Sminshall } 118832531Sminshall 118932531Sminshall return returnValue; 119032531Sminshall } 1191