132147Sminshall /* 2*62313Sbostic * Copyright (c) 1988, 1990, 1993 3*62313Sbostic * The Regents of the University of California. All rights reserved. 433685Sbostic * 542770Sbostic * %sccs.include.redist.c% 633685Sbostic */ 733685Sbostic 833685Sbostic #ifndef lint 9*62313Sbostic static char sccsid[] = "@(#)sys_bsd.c 8.1 (Berkeley) 06/06/93"; 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(); 4258972Sdab #endif SIGINFO 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 58845233Sborman static SIG_FUNC_RET susp(); 58945233Sborman #endif /* SIGTSTP */ 59045233Sborman #ifdef SIGINFO 59145233Sborman static SIG_FUNC_RET ayt(); 59245233Sborman #endif SIGINFO 59338689Sborman 59445233Sborman #ifdef SIGTSTP 59545233Sborman (void) signal(SIGTSTP, susp); 59639529Sborman #endif /* SIGTSTP */ 59745233Sborman #ifdef SIGINFO 59845233Sborman (void) signal(SIGINFO, ayt); 59945233Sborman #endif SIGINFO 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); 64345233Sborman #endif SIGINFO 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 68139529Sborman #ifndef B19200 68239529Sborman # define B19200 B9600 68339529Sborman #endif 68439529Sborman 68539529Sborman #ifndef B38400 68639529Sborman # define B38400 B19200 68739529Sborman #endif 68839529Sborman 68939529Sborman /* 69039529Sborman * This code assumes that the values B0, B50, B75... 69139529Sborman * are in ascending order. They do not have to be 69239529Sborman * contiguous. 69339529Sborman */ 69439529Sborman struct termspeeds { 69539529Sborman long speed; 69639529Sborman long value; 69739529Sborman } termspeeds[] = { 69839529Sborman { 0, B0 }, { 50, B50 }, { 75, B75 }, 69939529Sborman { 110, B110 }, { 134, B134 }, { 150, B150 }, 70039529Sborman { 200, B200 }, { 300, B300 }, { 600, B600 }, 70139529Sborman { 1200, B1200 }, { 1800, B1800 }, { 2400, B2400 }, 70239529Sborman { 4800, B4800 }, { 9600, B9600 }, { 19200, B19200 }, 70339529Sborman { 38400, B38400 }, { -1, B38400 } 70439529Sborman }; 70539529Sborman 70646808Sdab void 70737219Sminshall TerminalSpeeds(ispeed, ospeed) 70846808Sdab long *ispeed; 70946808Sdab long *ospeed; 71037219Sminshall { 71139529Sborman register struct termspeeds *tp; 71245233Sborman register long in, out; 71332147Sminshall 71446808Sdab out = cfgetospeed(&old_tc); 71545233Sborman in = cfgetispeed(&old_tc); 71646808Sdab if (in == 0) 71746808Sdab in = out; 71845233Sborman 71939529Sborman tp = termspeeds; 72045233Sborman while ((tp->speed != -1) && (tp->value < in)) 72139529Sborman tp++; 72239529Sborman *ispeed = tp->speed; 72339529Sborman 72439529Sborman tp = termspeeds; 72545233Sborman while ((tp->speed != -1) && (tp->value < out)) 72639529Sborman tp++; 72739529Sborman *ospeed = tp->speed; 72837219Sminshall } 72937219Sminshall 73046808Sdab int 73137219Sminshall TerminalWindowSize(rows, cols) 73246808Sdab long *rows, *cols; 73337219Sminshall { 73438689Sborman #ifdef TIOCGWINSZ 73537219Sminshall struct winsize ws; 73637219Sminshall 73738689Sborman if (ioctl(fileno(stdin), TIOCGWINSZ, (char *)&ws) >= 0) { 73838689Sborman *rows = ws.ws_row; 73938689Sborman *cols = ws.ws_col; 74038689Sborman return 1; 74137219Sminshall } 74238810Sborman #endif /* TIOCGWINSZ */ 74338689Sborman return 0; 74437219Sminshall } 74537219Sminshall 74646808Sdab int 74735417Sminshall NetClose(fd) 74846808Sdab int fd; 74932147Sminshall { 75035417Sminshall return close(fd); 75132147Sminshall } 75232147Sminshall 75332147Sminshall 75446808Sdab void 75532553Sminshall NetNonblockingIO(fd, onoff) 75646808Sdab int fd; 75746808Sdab int onoff; 75832147Sminshall { 75932147Sminshall ioctl(fd, FIONBIO, (char *)&onoff); 76032147Sminshall } 76132147Sminshall 76234849Sminshall #if defined(TN3270) 76346808Sdab void 76432553Sminshall NetSigIO(fd, onoff) 76546808Sdab int fd; 76646808Sdab int onoff; 76732147Sminshall { 76832147Sminshall ioctl(fd, FIOASYNC, (char *)&onoff); /* hear about input */ 76932147Sminshall } 77032147Sminshall 77146808Sdab void 77232553Sminshall NetSetPgrp(fd) 77346808Sdab int fd; 77432147Sminshall { 77532147Sminshall int myPid; 77632147Sminshall 77732147Sminshall myPid = getpid(); 77836274Sminshall fcntl(fd, F_SETOWN, myPid); 77932147Sminshall } 78034849Sminshall #endif /*defined(TN3270)*/ 78132553Sminshall 78232553Sminshall /* 78332553Sminshall * Various signal handling routines. 78432553Sminshall */ 78532147Sminshall 78646808Sdab /* ARGSUSED */ 78746808Sdab static SIG_FUNC_RET 78845233Sborman deadpeer(sig) 78946808Sdab int sig; 79032553Sminshall { 79132553Sminshall setcommandmode(); 79232553Sminshall longjmp(peerdied, -1); 79332553Sminshall } 79432147Sminshall 79546808Sdab /* ARGSUSED */ 79646808Sdab static SIG_FUNC_RET 79745233Sborman intr(sig) 79846808Sdab int sig; 79932553Sminshall { 80032553Sminshall if (localchars) { 80132553Sminshall intp(); 80232553Sminshall return; 80332553Sminshall } 80432553Sminshall setcommandmode(); 80532553Sminshall longjmp(toplevel, -1); 80632553Sminshall } 80732553Sminshall 80846808Sdab /* ARGSUSED */ 80946808Sdab static SIG_FUNC_RET 81045233Sborman intr2(sig) 81146808Sdab int sig; 81232553Sminshall { 81332553Sminshall if (localchars) { 81438689Sborman #ifdef KLUDGELINEMODE 81538689Sborman if (kludgelinemode) 81638689Sborman sendbrk(); 81738689Sborman else 81838689Sborman #endif 81938689Sborman sendabort(); 82032553Sminshall return; 82132553Sminshall } 82232553Sminshall } 82332553Sminshall 82445233Sborman #ifdef SIGTSTP 82546808Sdab /* ARGSUSED */ 82646808Sdab static SIG_FUNC_RET 82745233Sborman susp(sig) 82846808Sdab int sig; 82940245Sborman { 83046808Sdab if ((rlogin != _POSIX_VDISABLE) && rlogin_susp()) 83146808Sdab return; 83240245Sborman if (localchars) 83340245Sborman sendsusp(); 83440245Sborman } 83545233Sborman #endif 83640245Sborman 83745233Sborman #ifdef SIGWINCH 83846808Sdab /* ARGSUSED */ 83946808Sdab static SIG_FUNC_RET 84045233Sborman sendwin(sig) 84146808Sdab int sig; 84237219Sminshall { 84337219Sminshall if (connected) { 84437219Sminshall sendnaws(); 84537219Sminshall } 84637219Sminshall } 84745233Sborman #endif 84837219Sminshall 84945233Sborman #ifdef SIGINFO 85046808Sdab /* ARGSUSED */ 85146808Sdab static SIG_FUNC_RET 85245233Sborman ayt(sig) 85346808Sdab int sig; 85445233Sborman { 85545233Sborman if (connected) 85645233Sborman sendayt(); 85745233Sborman else 85845233Sborman ayt_status(); 85945233Sborman } 86045233Sborman #endif 86145233Sborman 86232553Sminshall 86346808Sdab void 86432531Sminshall sys_telnet_init() 86532531Sminshall { 86645233Sborman (void) signal(SIGINT, intr); 86745233Sborman (void) signal(SIGQUIT, intr2); 86845233Sborman (void) signal(SIGPIPE, deadpeer); 86938689Sborman #ifdef SIGWINCH 87045233Sborman (void) signal(SIGWINCH, sendwin); 87138689Sborman #endif 87240245Sborman #ifdef SIGTSTP 87345233Sborman (void) signal(SIGTSTP, susp); 87440245Sborman #endif 87545233Sborman #ifdef SIGINFO 87645233Sborman (void) signal(SIGINFO, ayt); 87745233Sborman #endif 87832553Sminshall 87938689Sborman setconnmode(0); 88032531Sminshall 88132531Sminshall NetNonblockingIO(net, 1); 88232531Sminshall 88332531Sminshall #if defined(TN3270) 88436242Sminshall if (noasynchnet == 0) { /* DBX can't handle! */ 88532531Sminshall NetSigIO(net, 1); 88632531Sminshall NetSetPgrp(net); 88732531Sminshall } 88832531Sminshall #endif /* defined(TN3270) */ 88932531Sminshall 89032531Sminshall #if defined(SO_OOBINLINE) 89134849Sminshall if (SetSockOpt(net, SOL_SOCKET, SO_OOBINLINE, 1) == -1) { 89234849Sminshall perror("SetSockOpt"); 89334849Sminshall } 89432531Sminshall #endif /* defined(SO_OOBINLINE) */ 89532531Sminshall } 89632531Sminshall 89732531Sminshall /* 89832531Sminshall * Process rings - 89932531Sminshall * 90032531Sminshall * This routine tries to fill up/empty our various rings. 90132531Sminshall * 90232531Sminshall * The parameter specifies whether this is a poll operation, 90332531Sminshall * or a block-until-something-happens operation. 90432531Sminshall * 90532531Sminshall * The return value is 1 if something happened, 0 if not. 90632531Sminshall */ 90732531Sminshall 90846808Sdab int 90932531Sminshall process_rings(netin, netout, netex, ttyin, ttyout, poll) 91046808Sdab int poll; /* If 0, then block until something to do */ 91132531Sminshall { 91232531Sminshall register int c; 91332531Sminshall /* One wants to be a bit careful about setting returnValue 91432531Sminshall * to one, since a one implies we did some useful work, 91532531Sminshall * and therefore probably won't be called to block next 91632531Sminshall * time (TN3270 mode only). 91732531Sminshall */ 91832531Sminshall int returnValue = 0; 91932531Sminshall static struct timeval TimeValue = { 0 }; 92032531Sminshall 92132531Sminshall if (netout) { 92232531Sminshall FD_SET(net, &obits); 92332531Sminshall } 92432531Sminshall if (ttyout) { 92532531Sminshall FD_SET(tout, &obits); 92632531Sminshall } 92732531Sminshall #if defined(TN3270) 92832531Sminshall if (ttyin) { 92932531Sminshall FD_SET(tin, &ibits); 93032531Sminshall } 93132531Sminshall #else /* defined(TN3270) */ 93232531Sminshall if (ttyin) { 93332531Sminshall FD_SET(tin, &ibits); 93432531Sminshall } 93532531Sminshall #endif /* defined(TN3270) */ 93632531Sminshall #if defined(TN3270) 93732531Sminshall if (netin) { 93832531Sminshall FD_SET(net, &ibits); 93932531Sminshall } 94032531Sminshall # else /* !defined(TN3270) */ 94132531Sminshall if (netin) { 94232531Sminshall FD_SET(net, &ibits); 94332531Sminshall } 94432531Sminshall # endif /* !defined(TN3270) */ 94532531Sminshall if (netex) { 94632531Sminshall FD_SET(net, &xbits); 94732531Sminshall } 94832531Sminshall if ((c = select(16, &ibits, &obits, &xbits, 94932531Sminshall (poll == 0)? (struct timeval *)0 : &TimeValue)) < 0) { 95032531Sminshall if (c == -1) { 95132531Sminshall /* 95232531Sminshall * we can get EINTR if we are in line mode, 95332531Sminshall * and the user does an escape (TSTP), or 95432531Sminshall * some other signal generator. 95532531Sminshall */ 95632531Sminshall if (errno == EINTR) { 95732531Sminshall return 0; 95832531Sminshall } 95932531Sminshall # if defined(TN3270) 96032531Sminshall /* 96132531Sminshall * we can get EBADF if we were in transparent 96232531Sminshall * mode, and the transcom process died. 96332531Sminshall */ 96432531Sminshall if (errno == EBADF) { 96532531Sminshall /* 96632531Sminshall * zero the bits (even though kernel does it) 96732531Sminshall * to make sure we are selecting on the right 96832531Sminshall * ones. 96932531Sminshall */ 97032531Sminshall FD_ZERO(&ibits); 97132531Sminshall FD_ZERO(&obits); 97232531Sminshall FD_ZERO(&xbits); 97332531Sminshall return 0; 97432531Sminshall } 97532531Sminshall # endif /* defined(TN3270) */ 97632531Sminshall /* I don't like this, does it ever happen? */ 97732531Sminshall printf("sleep(5) from telnet, after select\r\n"); 97832531Sminshall sleep(5); 97932531Sminshall } 98032531Sminshall return 0; 98132531Sminshall } 98232531Sminshall 98332531Sminshall /* 98432531Sminshall * Any urgent data? 98532531Sminshall */ 98632531Sminshall if (FD_ISSET(net, &xbits)) { 98732531Sminshall FD_CLR(net, &xbits); 98832531Sminshall SYNCHing = 1; 98944361Sborman (void) ttyflush(1); /* flush already enqueued data */ 99032531Sminshall } 99132531Sminshall 99232531Sminshall /* 99332531Sminshall * Something to read from the network... 99432531Sminshall */ 99532531Sminshall if (FD_ISSET(net, &ibits)) { 99632531Sminshall int canread; 99732531Sminshall 99832531Sminshall FD_CLR(net, &ibits); 99932531Sminshall canread = ring_empty_consecutive(&netiring); 100032531Sminshall #if !defined(SO_OOBINLINE) 100132531Sminshall /* 100232531Sminshall * In 4.2 (and some early 4.3) systems, the 100332531Sminshall * OOB indication and data handling in the kernel 100432531Sminshall * is such that if two separate TCP Urgent requests 100532531Sminshall * come in, one byte of TCP data will be overlaid. 100632531Sminshall * This is fatal for Telnet, but we try to live 100732531Sminshall * with it. 100832531Sminshall * 100932531Sminshall * In addition, in 4.2 (and...), a special protocol 101032531Sminshall * is needed to pick up the TCP Urgent data in 101132531Sminshall * the correct sequence. 101232531Sminshall * 101332531Sminshall * What we do is: if we think we are in urgent 101432531Sminshall * mode, we look to see if we are "at the mark". 101532531Sminshall * If we are, we do an OOB receive. If we run 101632531Sminshall * this twice, we will do the OOB receive twice, 101732531Sminshall * but the second will fail, since the second 101832531Sminshall * time we were "at the mark", but there wasn't 101932531Sminshall * any data there (the kernel doesn't reset 102032531Sminshall * "at the mark" until we do a normal read). 102132531Sminshall * Once we've read the OOB data, we go ahead 102232531Sminshall * and do normal reads. 102332531Sminshall * 102432531Sminshall * There is also another problem, which is that 102532531Sminshall * since the OOB byte we read doesn't put us 102632531Sminshall * out of OOB state, and since that byte is most 102732531Sminshall * likely the TELNET DM (data mark), we would 102832531Sminshall * stay in the TELNET SYNCH (SYNCHing) state. 102932531Sminshall * So, clocks to the rescue. If we've "just" 103032531Sminshall * received a DM, then we test for the 103132531Sminshall * presence of OOB data when the receive OOB 103232531Sminshall * fails (and AFTER we did the normal mode read 103332531Sminshall * to clear "at the mark"). 103432531Sminshall */ 103532531Sminshall if (SYNCHing) { 103632531Sminshall int atmark; 103739652Sborman static int bogus_oob = 0, first = 1; 103832531Sminshall 103932531Sminshall ioctl(net, SIOCATMARK, (char *)&atmark); 104032531Sminshall if (atmark) { 104132531Sminshall c = recv(net, netiring.supply, canread, MSG_OOB); 104232531Sminshall if ((c == -1) && (errno == EINVAL)) { 104332531Sminshall c = recv(net, netiring.supply, canread, 0); 104432531Sminshall if (clocks.didnetreceive < clocks.gotDM) { 104532531Sminshall SYNCHing = stilloob(net); 104632531Sminshall } 104739652Sborman } else if (first && c > 0) { 104839652Sborman /* 104939652Sborman * Bogosity check. Systems based on 4.2BSD 105039652Sborman * do not return an error if you do a second 105139652Sborman * recv(MSG_OOB). So, we do one. If it 105239652Sborman * succeeds and returns exactly the same 105339652Sborman * data, then assume that we are running 105439652Sborman * on a broken system and set the bogus_oob 105539652Sborman * flag. (If the data was different, then 105639652Sborman * we probably got some valid new data, so 105739652Sborman * increment the count...) 105839652Sborman */ 105939652Sborman int i; 106039652Sborman i = recv(net, netiring.supply + c, canread - c, MSG_OOB); 106139652Sborman if (i == c && 106239652Sborman bcmp(netiring.supply, netiring.supply + c, i) == 0) { 106339652Sborman bogus_oob = 1; 106439652Sborman first = 0; 106539652Sborman } else if (i < 0) { 106639652Sborman bogus_oob = 0; 106739652Sborman first = 0; 106839652Sborman } else 106939652Sborman c += i; 107032531Sminshall } 107139652Sborman if (bogus_oob && c > 0) { 107239652Sborman int i; 107339652Sborman /* 107439652Sborman * Bogosity. We have to do the read 107539652Sborman * to clear the atmark to get out of 107639652Sborman * an infinate loop. 107739652Sborman */ 107839652Sborman i = read(net, netiring.supply + c, canread - c); 107939652Sborman if (i > 0) 108039652Sborman c += i; 108139652Sborman } 108232531Sminshall } else { 108332531Sminshall c = recv(net, netiring.supply, canread, 0); 108432531Sminshall } 108532531Sminshall } else { 108632531Sminshall c = recv(net, netiring.supply, canread, 0); 108732531Sminshall } 108832531Sminshall settimer(didnetreceive); 108932531Sminshall #else /* !defined(SO_OOBINLINE) */ 109032531Sminshall c = recv(net, netiring.supply, canread, 0); 109132531Sminshall #endif /* !defined(SO_OOBINLINE) */ 109232531Sminshall if (c < 0 && errno == EWOULDBLOCK) { 109332531Sminshall c = 0; 109432531Sminshall } else if (c <= 0) { 109532531Sminshall return -1; 109632531Sminshall } 109732531Sminshall if (netdata) { 109832531Sminshall Dump('<', netiring.supply, c); 109932531Sminshall } 110032667Sminshall if (c) 110132667Sminshall ring_supplied(&netiring, c); 110232531Sminshall returnValue = 1; 110332531Sminshall } 110432531Sminshall 110532531Sminshall /* 110632531Sminshall * Something to read from the tty... 110732531Sminshall */ 110832531Sminshall if (FD_ISSET(tin, &ibits)) { 110932531Sminshall FD_CLR(tin, &ibits); 111033286Sminshall c = TerminalRead(ttyiring.supply, ring_empty_consecutive(&ttyiring)); 111132531Sminshall if (c < 0 && errno == EWOULDBLOCK) { 111232531Sminshall c = 0; 111332531Sminshall } else { 111432531Sminshall /* EOF detection for line mode!!!! */ 111533281Sminshall if ((c == 0) && MODE_LOCAL_CHARS(globalmode) && isatty(tin)) { 111632531Sminshall /* must be an EOF... */ 111732531Sminshall *ttyiring.supply = termEofChar; 111832531Sminshall c = 1; 111932531Sminshall } 112032531Sminshall if (c <= 0) { 112132531Sminshall return -1; 112232531Sminshall } 112338208Sminshall if (termdata) { 112438208Sminshall Dump('<', ttyiring.supply, c); 112538208Sminshall } 112632667Sminshall ring_supplied(&ttyiring, c); 112732531Sminshall } 112832531Sminshall returnValue = 1; /* did something useful */ 112932531Sminshall } 113032531Sminshall 113132531Sminshall if (FD_ISSET(net, &obits)) { 113232531Sminshall FD_CLR(net, &obits); 113332531Sminshall returnValue |= netflush(); 113432531Sminshall } 113532531Sminshall if (FD_ISSET(tout, &obits)) { 113632531Sminshall FD_CLR(tout, &obits); 113738689Sborman returnValue |= (ttyflush(SYNCHing|flushout) > 0); 113832531Sminshall } 113932531Sminshall 114032531Sminshall return returnValue; 114132531Sminshall } 1142