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