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*46808Sdab static char sccsid[] = "@(#)sys_bsd.c 5.2 (Berkeley) 03/01/91"; 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 62*46808Sdab # define tcgetattr(f, t) ioctl(f, TCGETS, (char *)t) 6345233Sborman # else 6445233Sborman # ifdef TCSETA 6545233Sborman # define TCSANOW TCSETA 6645233Sborman # define TCSADRAIN TCSETAW 67*46808Sdab # define tcgetattr(f, t) ioctl(f, TCGETA, (char *)t) 6845233Sborman # else 6945233Sborman # define TCSANOW TIOCSETA 7045233Sborman # define TCSADRAIN TIOCSETAW 71*46808Sdab # define tcgetattr(f, t) ioctl(f, TIOCGETA, (char *)t) 7245233Sborman # endif 7345233Sborman # endif 74*46808Sdab # 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 */ 8238689Sborman #endif /* USE_TERMIO */ 8338689Sborman 8432531Sminshall static fd_set ibits, obits, xbits; 8532147Sminshall 8632531Sminshall 87*46808Sdab void 8832531Sminshall init_sys() 8932531Sminshall { 9032531Sminshall tout = fileno(stdout); 9132531Sminshall tin = fileno(stdin); 9232531Sminshall FD_ZERO(&ibits); 9332531Sminshall FD_ZERO(&obits); 9432531Sminshall FD_ZERO(&xbits); 9532531Sminshall 9632531Sminshall errno = 0; 9732531Sminshall } 9832531Sminshall 9932531Sminshall 100*46808Sdab int 10133286Sminshall TerminalWrite(buf, n) 102*46808Sdab char *buf; 103*46808Sdab int n; 10432147Sminshall { 10533286Sminshall return write(tout, buf, n); 10632147Sminshall } 10732147Sminshall 108*46808Sdab int 10933286Sminshall TerminalRead(buf, n) 110*46808Sdab char *buf; 111*46808Sdab int n; 11232147Sminshall { 11333286Sminshall return read(tin, buf, n); 11432147Sminshall } 11532147Sminshall 11632147Sminshall /* 11732147Sminshall * 11832147Sminshall */ 11932147Sminshall 120*46808Sdab int 12132553Sminshall TerminalAutoFlush() 12232147Sminshall { 12332147Sminshall #if defined(LNOFLSH) 12432147Sminshall int flush; 12532147Sminshall 12632147Sminshall ioctl(0, TIOCLGET, (char *)&flush); 12732147Sminshall return !(flush&LNOFLSH); /* if LNOFLSH, no autoflush */ 12832147Sminshall #else /* LNOFLSH */ 12932147Sminshall return 1; 13032147Sminshall #endif /* LNOFLSH */ 13132147Sminshall } 13232147Sminshall 13338689Sborman #ifdef KLUDGELINEMODE 13438689Sborman extern int kludgelinemode; 13538689Sborman #endif 13632147Sminshall /* 13732147Sminshall * TerminalSpecialChars() 13832147Sminshall * 13932147Sminshall * Look at an input character to see if it is a special character 14032147Sminshall * and decide what to do. 14132147Sminshall * 14232147Sminshall * Output: 14332147Sminshall * 14432147Sminshall * 0 Don't add this character. 14532147Sminshall * 1 Do add this character 14632147Sminshall */ 14732147Sminshall 148*46808Sdab int 14932553Sminshall TerminalSpecialChars(c) 150*46808Sdab int c; 15132147Sminshall { 15232553Sminshall void xmitAO(), xmitEL(), xmitEC(), intp(), sendbrk(); 15332147Sminshall 15438689Sborman if (c == termIntChar) { 15532147Sminshall intp(); 15632147Sminshall return 0; 15738689Sborman } else if (c == termQuitChar) { 15838689Sborman #ifdef KLUDGELINEMODE 15938689Sborman if (kludgelinemode) 16038689Sborman sendbrk(); 16138689Sborman else 16238689Sborman #endif 16338689Sborman sendabort(); 16432147Sminshall return 0; 16538689Sborman } else if (c == termEofChar) { 16638689Sborman if (my_want_state_is_will(TELOPT_LINEMODE)) { 16738689Sborman sendeof(); 16838689Sborman return 0; 16938689Sborman } 17038689Sborman return 1; 17138689Sborman } else if (c == termSuspChar) { 17238689Sborman sendsusp(); 17338689Sborman return(0); 17438689Sborman } else if (c == termFlushChar) { 17532147Sminshall xmitAO(); /* Transmit Abort Output */ 17632147Sminshall return 0; 17732147Sminshall } else if (!MODE_LOCAL_CHARS(globalmode)) { 17838689Sborman if (c == termKillChar) { 17932147Sminshall xmitEL(); 18032147Sminshall return 0; 18138689Sborman } else if (c == termEraseChar) { 18232147Sminshall xmitEC(); /* Transmit Erase Character */ 18332147Sminshall return 0; 18432147Sminshall } 18532147Sminshall } 18632147Sminshall return 1; 18732147Sminshall } 18832147Sminshall 18932147Sminshall 19032147Sminshall /* 19132147Sminshall * Flush output to the terminal 19232147Sminshall */ 19332147Sminshall 194*46808Sdab void 19532553Sminshall TerminalFlushOutput() 19632147Sminshall { 19739529Sborman #ifdef TIOCFLUSH 19832147Sminshall (void) ioctl(fileno(stdout), TIOCFLUSH, (char *) 0); 19938689Sborman #else 20038689Sborman (void) ioctl(fileno(stdout), TCFLSH, (char *) 0); 20138689Sborman #endif 20232147Sminshall } 20332147Sminshall 204*46808Sdab void 20532553Sminshall TerminalSaveState() 20632147Sminshall { 20738689Sborman #ifndef USE_TERMIO 20832147Sminshall ioctl(0, TIOCGETP, (char *)&ottyb); 20932147Sminshall ioctl(0, TIOCGETC, (char *)&otc); 21032147Sminshall ioctl(0, TIOCGLTC, (char *)&oltc); 21138909Sborman ioctl(0, TIOCLGET, (char *)&olmode); 21232147Sminshall 21332147Sminshall ntc = otc; 21432147Sminshall nltc = oltc; 21532147Sminshall nttyb = ottyb; 21632254Sminshall 21738689Sborman #else /* USE_TERMIO */ 21845233Sborman tcgetattr(0, &old_tc); 21938689Sborman 22038689Sborman new_tc = old_tc; 22138689Sborman 22245233Sborman #ifndef VDISCARD 22344361Sborman termFlushChar = CONTROL('O'); 22445233Sborman #endif 22545233Sborman #ifndef VWERASE 22644361Sborman termWerasChar = CONTROL('W'); 22745233Sborman #endif 22845233Sborman #ifndef VREPRINT 22944361Sborman termRprntChar = CONTROL('R'); 23045233Sborman #endif 23145233Sborman #ifndef VLNEXT 23244361Sborman termLiteralNextChar = CONTROL('V'); 23345233Sborman #endif 23445233Sborman #ifndef VSTART 23544361Sborman termStartChar = CONTROL('Q'); 23645233Sborman #endif 23745233Sborman #ifndef VSTOP 23844361Sborman termStopChar = CONTROL('S'); 23945233Sborman #endif 24045233Sborman #ifndef VSTATUS 24145233Sborman termAytChar = CONTROL('T'); 24245233Sborman #endif 24338689Sborman #endif /* USE_TERMIO */ 24432147Sminshall } 24532147Sminshall 246*46808Sdab cc_t * 24738689Sborman tcval(func) 248*46808Sdab register int func; 24938689Sborman { 25038689Sborman switch(func) { 25140245Sborman case SLC_IP: return(&termIntChar); 25240245Sborman case SLC_ABORT: return(&termQuitChar); 25340245Sborman case SLC_EOF: return(&termEofChar); 25440245Sborman case SLC_EC: return(&termEraseChar); 25540245Sborman case SLC_EL: return(&termKillChar); 25640245Sborman case SLC_XON: return(&termStartChar); 25740245Sborman case SLC_XOFF: return(&termStopChar); 25844361Sborman case SLC_FORW1: return(&termForw1Char); 25945233Sborman #ifdef USE_TERMIO 26045233Sborman case SLC_FORW2: return(&termForw2Char); 26145233Sborman # ifdef VDISCARD 26240245Sborman case SLC_AO: return(&termFlushChar); 26345233Sborman # endif 26445233Sborman # ifdef VSUSP 26540245Sborman case SLC_SUSP: return(&termSuspChar); 26645233Sborman # endif 26745233Sborman # ifdef VWERASE 26840245Sborman case SLC_EW: return(&termWerasChar); 26945233Sborman # endif 27045233Sborman # ifdef VREPRINT 27140245Sborman case SLC_RP: return(&termRprntChar); 27245233Sborman # endif 27345233Sborman # ifdef VLNEXT 27440245Sborman case SLC_LNEXT: return(&termLiteralNextChar); 27545233Sborman # endif 27645233Sborman # ifdef VSTATUS 27745233Sborman case SLC_AYT: return(&termAytChar); 27845233Sborman # endif 27944361Sborman #endif 28038689Sborman 28138689Sborman case SLC_SYNCH: 28238689Sborman case SLC_BRK: 28338689Sborman case SLC_EOR: 28438689Sborman default: 28540245Sborman return((cc_t *)0); 28638689Sborman } 28738689Sborman } 28838689Sborman 289*46808Sdab void 29038689Sborman TerminalDefaultChars() 29138689Sborman { 29238689Sborman #ifndef USE_TERMIO 29338689Sborman ntc = otc; 29438689Sborman nltc = oltc; 29538689Sborman nttyb.sg_kill = ottyb.sg_kill; 29638689Sborman nttyb.sg_erase = ottyb.sg_erase; 29738689Sborman #else /* USE_TERMIO */ 29838689Sborman memcpy(new_tc.c_cc, old_tc.c_cc, sizeof(old_tc.c_cc)); 29945233Sborman # ifndef VDISCARD 30044361Sborman termFlushChar = CONTROL('O'); 30139529Sborman # endif 30239529Sborman # ifndef VWERASE 30344361Sborman termWerasChar = CONTROL('W'); 30439529Sborman # endif 30539529Sborman # ifndef VREPRINT 30644361Sborman termRprntChar = CONTROL('R'); 30739529Sborman # endif 30839529Sborman # ifndef VLNEXT 30944361Sborman termLiteralNextChar = CONTROL('V'); 31039529Sborman # endif 31139529Sborman # ifndef VSTART 31244361Sborman termStartChar = CONTROL('Q'); 31339529Sborman # endif 31439529Sborman # ifndef VSTOP 31544361Sborman termStopChar = CONTROL('S'); 31639529Sborman # endif 31745233Sborman # ifndef VSTATUS 31845233Sborman termAytChar = CONTROL('T'); 31945233Sborman # endif 32038689Sborman #endif /* USE_TERMIO */ 32138689Sborman } 32238689Sborman 32344361Sborman #ifdef notdef 32438689Sborman void 32532553Sminshall TerminalRestoreState() 32632147Sminshall { 32732147Sminshall } 32844361Sborman #endif 32932147Sminshall 33032147Sminshall /* 33132147Sminshall * TerminalNewMode - set up terminal to a specific mode. 33238689Sborman * MODE_ECHO: do local terminal echo 33338689Sborman * MODE_FLOW: do local flow control 33438689Sborman * MODE_TRAPSIG: do local mapping to TELNET IAC sequences 33538689Sborman * MODE_EDIT: do local line editing 33638689Sborman * 33738689Sborman * Command mode: 33838689Sborman * MODE_ECHO|MODE_EDIT|MODE_FLOW|MODE_TRAPSIG 33938689Sborman * local echo 34038689Sborman * local editing 34138689Sborman * local xon/xoff 34238689Sborman * local signal mapping 34338689Sborman * 34438689Sborman * Linemode: 34538689Sborman * local/no editing 34638689Sborman * Both Linemode and Single Character mode: 34738689Sborman * local/remote echo 34838689Sborman * local/no xon/xoff 34938689Sborman * local/no signal mapping 35032147Sminshall */ 35132147Sminshall 35232147Sminshall 353*46808Sdab void 35433286Sminshall TerminalNewMode(f) 355*46808Sdab register int f; 35632147Sminshall { 35732147Sminshall static int prevmode = 0; 35838689Sborman #ifndef USE_TERMIO 35938689Sborman struct tchars tc; 36038689Sborman struct ltchars ltc; 36132147Sminshall struct sgttyb sb; 36238909Sborman int lmode; 36338689Sborman #else /* USE_TERMIO */ 36438689Sborman struct termio tmp_tc; 36538689Sborman #endif /* USE_TERMIO */ 36632147Sminshall int onoff; 36732147Sminshall int old; 368*46808Sdab cc_t esc; 36932147Sminshall 37038689Sborman globalmode = f&~MODE_FORCE; 37132147Sminshall if (prevmode == f) 37232147Sminshall return; 37338689Sborman 37438689Sborman /* 37538689Sborman * Write any outstanding data before switching modes 37638689Sborman * ttyflush() returns 0 only when there is no more data 37738689Sborman * left to write out, it returns -1 if it couldn't do 37838689Sborman * anything at all, otherwise it returns 1 + the number 37938689Sborman * of characters left to write. 38045233Sborman #ifndef USE_TERMIO 38145233Sborman * We would really like ask the kernel to wait for the output 38245233Sborman * to drain, like we can do with the TCSADRAIN, but we don't have 38345233Sborman * that option. The only ioctl that waits for the output to 38445233Sborman * drain, TIOCSETP, also flushes the input queue, which is NOT 38545233Sborman * what we want (TIOCSETP is like TCSADFLUSH). 38645233Sborman #endif 38738689Sborman */ 38838689Sborman old = ttyflush(SYNCHing|flushout); 38938689Sborman if (old < 0 || old > 1) { 39045233Sborman #ifdef USE_TERMIO 391*46808Sdab tcgetattr(tin, &tmp_tc); 39238689Sborman #endif /* USE_TERMIO */ 39338689Sborman do { 39438689Sborman /* 39538689Sborman * Wait for data to drain, then flush again. 39638689Sborman */ 39745233Sborman #ifdef USE_TERMIO 398*46808Sdab tcsetattr(tin, TCSADRAIN, &tmp_tc); 39938689Sborman #endif /* USE_TERMIO */ 40038689Sborman old = ttyflush(SYNCHing|flushout); 40138689Sborman } while (old < 0 || old > 1); 40238689Sborman } 40338689Sborman 40432147Sminshall old = prevmode; 40538689Sborman prevmode = f&~MODE_FORCE; 40638689Sborman #ifndef USE_TERMIO 40732147Sminshall sb = nttyb; 40838689Sborman tc = ntc; 40938689Sborman ltc = nltc; 41038909Sborman lmode = olmode; 41138689Sborman #else 41238689Sborman tmp_tc = new_tc; 41338689Sborman #endif 41432147Sminshall 41538689Sborman if (f&MODE_ECHO) { 41638689Sborman #ifndef USE_TERMIO 41738689Sborman sb.sg_flags |= ECHO; 41838689Sborman #else 41938689Sborman tmp_tc.c_lflag |= ECHO; 42038689Sborman tmp_tc.c_oflag |= ONLCR; 421*46808Sdab if (crlf) 422*46808Sdab tmp_tc.c_iflag |= ICRNL; 42338689Sborman #endif 42438689Sborman } else { 42538689Sborman #ifndef USE_TERMIO 42638689Sborman sb.sg_flags &= ~ECHO; 42738689Sborman #else 42838689Sborman tmp_tc.c_lflag &= ~ECHO; 42938689Sborman tmp_tc.c_oflag &= ~ONLCR; 43039529Sborman # ifdef notdef 431*46808Sdab if (crlf) 432*46808Sdab tmp_tc.c_iflag &= ~ICRNL; 43339529Sborman # endif 43438689Sborman #endif 43538689Sborman } 43632147Sminshall 43738689Sborman if ((f&MODE_FLOW) == 0) { 43838689Sborman #ifndef USE_TERMIO 43945233Sborman tc.t_startc = _POSIX_VDISABLE; 44045233Sborman tc.t_stopc = _POSIX_VDISABLE; 44138689Sborman #else 44238689Sborman tmp_tc.c_iflag &= ~(IXANY|IXOFF|IXON); 44338689Sborman } else { 44438689Sborman tmp_tc.c_iflag |= IXANY|IXOFF|IXON; 44538689Sborman #endif 44638689Sborman } 44732147Sminshall 44838689Sborman if ((f&MODE_TRAPSIG) == 0) { 44938689Sborman #ifndef USE_TERMIO 45045233Sborman tc.t_intrc = _POSIX_VDISABLE; 45145233Sborman tc.t_quitc = _POSIX_VDISABLE; 45245233Sborman tc.t_eofc = _POSIX_VDISABLE; 45345233Sborman ltc.t_suspc = _POSIX_VDISABLE; 45445233Sborman ltc.t_dsuspc = _POSIX_VDISABLE; 45538689Sborman #else 45638689Sborman tmp_tc.c_lflag &= ~ISIG; 45738689Sborman #endif 45838689Sborman localchars = 0; 45938689Sborman } else { 46038689Sborman #ifdef USE_TERMIO 46138689Sborman tmp_tc.c_lflag |= ISIG; 46238689Sborman #endif 46338689Sborman localchars = 1; 46438689Sborman } 46538689Sborman 46638689Sborman if (f&MODE_EDIT) { 46738689Sborman #ifndef USE_TERMIO 46838689Sborman sb.sg_flags &= ~CBREAK; 46938689Sborman sb.sg_flags |= CRMOD; 47038689Sborman #else 47138689Sborman tmp_tc.c_lflag |= ICANON; 47238689Sborman #endif 47338689Sborman } else { 47438689Sborman #ifndef USE_TERMIO 47538689Sborman sb.sg_flags |= CBREAK; 47638689Sborman if (f&MODE_ECHO) 47732147Sminshall sb.sg_flags |= CRMOD; 47838689Sborman else 47938689Sborman sb.sg_flags &= ~CRMOD; 48038689Sborman #else 48138689Sborman tmp_tc.c_lflag &= ~ICANON; 48238689Sborman tmp_tc.c_iflag &= ~ICRNL; 48338689Sborman tmp_tc.c_cc[VMIN] = 1; 48438689Sborman tmp_tc.c_cc[VTIME] = 0; 48538689Sborman #endif 48638689Sborman } 48732147Sminshall 48844361Sborman if ((f&(MODE_EDIT|MODE_TRAPSIG)) == 0) { 48944361Sborman #ifndef USE_TERMIO 49045233Sborman ltc.t_lnextc = _POSIX_VDISABLE; 49144361Sborman #else 49244361Sborman # ifdef VLNEXT 49345233Sborman tmp_tc.c_cc[VLNEXT] = (cc_t)(_POSIX_VDISABLE); 49444361Sborman # endif 49544361Sborman #endif 49644361Sborman } 49744361Sborman 49844361Sborman if (f&MODE_SOFT_TAB) { 49944361Sborman #ifndef USE_TERMIO 50044361Sborman sb.sg_flags |= XTABS; 50144361Sborman #else 50244361Sborman # ifdef OXTABS 50344361Sborman tmp_tc.c_oflag |= OXTABS; 50444361Sborman # endif 50544361Sborman # ifdef TABDLY 50644361Sborman tmp_tc.c_oflag &= ~TABDLY; 50744361Sborman tmp_tc.c_oflag |= TAB3; 50844361Sborman # endif 50944361Sborman #endif 51044361Sborman } else { 51144361Sborman #ifndef USE_TERMIO 51244361Sborman sb.sg_flags &= ~XTABS; 51344361Sborman #else 51444361Sborman # ifdef OXTABS 51544361Sborman tmp_tc.c_oflag &= ~OXTABS; 51644361Sborman # endif 51744361Sborman # ifdef TABDLY 51844361Sborman tmp_tc.c_oflag &= ~TABDLY; 51944361Sborman # endif 52044361Sborman #endif 52144361Sborman } 52244361Sborman 52344361Sborman if (f&MODE_LIT_ECHO) { 52444361Sborman #ifndef USE_TERMIO 525*46808Sdab lmode &= ~LCTLECH; 52644361Sborman #else 52744361Sborman # ifdef ECHOCTL 52844361Sborman tmp_tc.c_lflag &= ~ECHOCTL; 52944361Sborman # endif 53044361Sborman #endif 53144361Sborman } else { 53244361Sborman #ifndef USE_TERMIO 533*46808Sdab lmode |= LCTLECH; 53444361Sborman #else 53544361Sborman # ifdef ECHOCTL 53644361Sborman tmp_tc.c_lflag |= ECHOCTL; 53744361Sborman # endif 53844361Sborman #endif 53944361Sborman } 54044361Sborman 54138689Sborman if (f == -1) { 54238689Sborman onoff = 0; 54338689Sborman } else { 54438909Sborman #ifndef USE_TERMIO 54539529Sborman if (f & MODE_OUTBIN) 54638909Sborman lmode |= LLITOUT; 54738909Sborman else 54838909Sborman lmode &= ~LLITOUT; 54939529Sborman 55039529Sborman if (f & MODE_INBIN) 55138909Sborman lmode |= LPASS8; 55238909Sborman else 55338909Sborman lmode &= ~LPASS8; 55438909Sborman #else 55545233Sborman if (f & MODE_INBIN) 55645233Sborman tmp_tc.c_iflag &= ~ISTRIP; 55738909Sborman else 55845233Sborman tmp_tc.c_iflag |= ISTRIP; 55945233Sborman if (f & MODE_OUTBIN) { 56039529Sborman tmp_tc.c_cflag &= ~(CSIZE|PARENB); 56139529Sborman tmp_tc.c_cflag |= CS8; 56245233Sborman tmp_tc.c_oflag &= ~OPOST; 56339529Sborman } else { 56445233Sborman tmp_tc.c_cflag &= ~(CSIZE|PARENB); 56545233Sborman tmp_tc.c_cflag |= old_tc.c_cflag & (CSIZE|PARENB); 56645233Sborman tmp_tc.c_oflag |= OPOST; 56739529Sborman } 56838909Sborman #endif 56938689Sborman onoff = 1; 57032147Sminshall } 57138689Sborman 57238689Sborman if (f != -1) { 57339529Sborman #ifdef SIGTSTP 57445233Sborman static SIG_FUNC_RET susp(); 57545233Sborman #endif /* SIGTSTP */ 57645233Sborman #ifdef SIGINFO 57745233Sborman static SIG_FUNC_RET ayt(); 57845233Sborman #endif SIGINFO 57938689Sborman 58045233Sborman #ifdef SIGTSTP 58145233Sborman (void) signal(SIGTSTP, susp); 58239529Sborman #endif /* SIGTSTP */ 58345233Sborman #ifdef SIGINFO 58445233Sborman (void) signal(SIGINFO, ayt); 58545233Sborman #endif SIGINFO 58645233Sborman #if defined(USE_TERMIO) && defined(NOKERNINFO) 58745233Sborman tmp_tc.c_lflag |= NOKERNINFO; 58845233Sborman #endif 58944361Sborman /* 59044361Sborman * We don't want to process ^Y here. It's just another 59144361Sborman * character that we'll pass on to the back end. It has 59244361Sborman * to process it because it will be processed when the 59344361Sborman * user attempts to read it, not when we send it. 59444361Sborman */ 59544361Sborman #ifndef USE_TERMIO 59645233Sborman ltc.t_dsuspc = _POSIX_VDISABLE; 59744361Sborman #else 59844361Sborman # ifdef VDSUSP 59945233Sborman tmp_tc.c_cc[VDSUSP] = (cc_t)(_POSIX_VDISABLE); 60044361Sborman # endif 60144361Sborman #endif 60240245Sborman #ifdef USE_TERMIO 60340245Sborman /* 60440245Sborman * If the VEOL character is already set, then use VEOL2, 60540245Sborman * otherwise use VEOL. 60640245Sborman */ 607*46808Sdab esc = (rlogin != _POSIX_VDISABLE) ? rlogin : escape; 608*46808Sdab if ((tmp_tc.c_cc[VEOL] != esc) 60944361Sborman # ifdef VEOL2 610*46808Sdab && (tmp_tc.c_cc[VEOL2] != esc) 61144361Sborman # endif 612*46808Sdab ) { 61345233Sborman if (tmp_tc.c_cc[VEOL] == (cc_t)(_POSIX_VDISABLE)) 614*46808Sdab tmp_tc.c_cc[VEOL] = esc; 61545233Sborman # ifdef VEOL2 61645233Sborman else if (tmp_tc.c_cc[VEOL2] == (cc_t)(_POSIX_VDISABLE)) 617*46808Sdab tmp_tc.c_cc[VEOL2] = esc; 61845233Sborman # endif 61945233Sborman } 62040245Sborman #else 62145233Sborman if (tc.t_brkc == (cc_t)(_POSIX_VDISABLE)) 622*46808Sdab tc.t_brkc = esc; 62340245Sborman #endif 62438689Sborman } else { 62545233Sborman #ifdef SIGINFO 62645233Sborman SIG_FUNC_RET ayt_status(); 62745233Sborman 62845233Sborman (void) signal(SIGINFO, ayt_status); 62945233Sborman #endif SIGINFO 63039529Sborman #ifdef SIGTSTP 63138689Sborman (void) signal(SIGTSTP, SIG_DFL); 63244361Sborman (void) sigsetmask(sigblock(0) & ~(1<<(SIGTSTP-1))); 63339529Sborman #endif /* SIGTSTP */ 63439529Sborman #ifndef USE_TERMIO 63539529Sborman ltc = oltc; 63639529Sborman tc = otc; 63739529Sborman sb = ottyb; 63844361Sborman lmode = olmode; 63944361Sborman #else 64044361Sborman tmp_tc = old_tc; 64139529Sborman #endif 64238689Sborman } 64339529Sborman #ifndef USE_TERMIO 64439529Sborman ioctl(tin, TIOCLSET, (char *)&lmode); 64539529Sborman ioctl(tin, TIOCSLTC, (char *)<c); 64639529Sborman ioctl(tin, TIOCSETC, (char *)&tc); 64745233Sborman ioctl(tin, TIOCSETN, (char *)&sb); 64839529Sborman #else 64945233Sborman if (tcsetattr(tin, TCSADRAIN, &tmp_tc) < 0) 65045233Sborman tcsetattr(tin, TCSANOW, &tmp_tc); 65139529Sborman #endif 65239529Sborman 65332147Sminshall #if (!defined(TN3270)) || ((!defined(NOT43)) || defined(PUTCHAR)) 65433286Sminshall ioctl(tin, FIONBIO, (char *)&onoff); 65533286Sminshall ioctl(tout, FIONBIO, (char *)&onoff); 65632147Sminshall #endif /* (!defined(TN3270)) || ((!defined(NOT43)) || defined(PUTCHAR)) */ 65732147Sminshall #if defined(TN3270) 65836242Sminshall if (noasynchtty == 0) { 65933286Sminshall ioctl(tin, FIOASYNC, (char *)&onoff); 66032147Sminshall } 66132147Sminshall #endif /* defined(TN3270) */ 662*46808Sdab 66332147Sminshall } 66432147Sminshall 66539529Sborman #ifndef B19200 66639529Sborman # define B19200 B9600 66739529Sborman #endif 66839529Sborman 66939529Sborman #ifndef B38400 67039529Sborman # define B38400 B19200 67139529Sborman #endif 67239529Sborman 67339529Sborman /* 67439529Sborman * This code assumes that the values B0, B50, B75... 67539529Sborman * are in ascending order. They do not have to be 67639529Sborman * contiguous. 67739529Sborman */ 67839529Sborman struct termspeeds { 67939529Sborman long speed; 68039529Sborman long value; 68139529Sborman } termspeeds[] = { 68239529Sborman { 0, B0 }, { 50, B50 }, { 75, B75 }, 68339529Sborman { 110, B110 }, { 134, B134 }, { 150, B150 }, 68439529Sborman { 200, B200 }, { 300, B300 }, { 600, B600 }, 68539529Sborman { 1200, B1200 }, { 1800, B1800 }, { 2400, B2400 }, 68639529Sborman { 4800, B4800 }, { 9600, B9600 }, { 19200, B19200 }, 68739529Sborman { 38400, B38400 }, { -1, B38400 } 68839529Sborman }; 68939529Sborman 690*46808Sdab void 69137219Sminshall TerminalSpeeds(ispeed, ospeed) 692*46808Sdab long *ispeed; 693*46808Sdab long *ospeed; 69437219Sminshall { 69539529Sborman register struct termspeeds *tp; 69645233Sborman register long in, out; 69732147Sminshall 698*46808Sdab out = cfgetospeed(&old_tc); 69945233Sborman in = cfgetispeed(&old_tc); 700*46808Sdab if (in == 0) 701*46808Sdab in = out; 70245233Sborman 70339529Sborman tp = termspeeds; 70445233Sborman while ((tp->speed != -1) && (tp->value < in)) 70539529Sborman tp++; 70639529Sborman *ispeed = tp->speed; 70739529Sborman 70839529Sborman tp = termspeeds; 70945233Sborman while ((tp->speed != -1) && (tp->value < out)) 71039529Sborman tp++; 71139529Sborman *ospeed = tp->speed; 71237219Sminshall } 71337219Sminshall 714*46808Sdab int 71537219Sminshall TerminalWindowSize(rows, cols) 716*46808Sdab long *rows, *cols; 71737219Sminshall { 71838689Sborman #ifdef TIOCGWINSZ 71937219Sminshall struct winsize ws; 72037219Sminshall 72138689Sborman if (ioctl(fileno(stdin), TIOCGWINSZ, (char *)&ws) >= 0) { 72238689Sborman *rows = ws.ws_row; 72338689Sborman *cols = ws.ws_col; 72438689Sborman return 1; 72537219Sminshall } 72638810Sborman #endif /* TIOCGWINSZ */ 72738689Sborman return 0; 72837219Sminshall } 72937219Sminshall 730*46808Sdab int 73135417Sminshall NetClose(fd) 732*46808Sdab int fd; 73332147Sminshall { 73435417Sminshall return close(fd); 73532147Sminshall } 73632147Sminshall 73732147Sminshall 738*46808Sdab void 73932553Sminshall NetNonblockingIO(fd, onoff) 740*46808Sdab int fd; 741*46808Sdab int onoff; 74232147Sminshall { 74332147Sminshall ioctl(fd, FIONBIO, (char *)&onoff); 74432147Sminshall } 74532147Sminshall 74634849Sminshall #if defined(TN3270) 747*46808Sdab void 74832553Sminshall NetSigIO(fd, onoff) 749*46808Sdab int fd; 750*46808Sdab int onoff; 75132147Sminshall { 75232147Sminshall ioctl(fd, FIOASYNC, (char *)&onoff); /* hear about input */ 75332147Sminshall } 75432147Sminshall 755*46808Sdab void 75632553Sminshall NetSetPgrp(fd) 757*46808Sdab int fd; 75832147Sminshall { 75932147Sminshall int myPid; 76032147Sminshall 76132147Sminshall myPid = getpid(); 76236274Sminshall fcntl(fd, F_SETOWN, myPid); 76332147Sminshall } 76434849Sminshall #endif /*defined(TN3270)*/ 76532553Sminshall 76632553Sminshall /* 76732553Sminshall * Various signal handling routines. 76832553Sminshall */ 76932147Sminshall 770*46808Sdab /* ARGSUSED */ 771*46808Sdab static SIG_FUNC_RET 77245233Sborman deadpeer(sig) 773*46808Sdab int sig; 77432553Sminshall { 77532553Sminshall setcommandmode(); 77632553Sminshall longjmp(peerdied, -1); 77732553Sminshall } 77832147Sminshall 779*46808Sdab /* ARGSUSED */ 780*46808Sdab static SIG_FUNC_RET 78145233Sborman intr(sig) 782*46808Sdab int sig; 78332553Sminshall { 78432553Sminshall if (localchars) { 78532553Sminshall intp(); 78632553Sminshall return; 78732553Sminshall } 78832553Sminshall setcommandmode(); 78932553Sminshall longjmp(toplevel, -1); 79032553Sminshall } 79132553Sminshall 792*46808Sdab /* ARGSUSED */ 793*46808Sdab static SIG_FUNC_RET 79445233Sborman intr2(sig) 795*46808Sdab int sig; 79632553Sminshall { 79732553Sminshall if (localchars) { 79838689Sborman #ifdef KLUDGELINEMODE 79938689Sborman if (kludgelinemode) 80038689Sborman sendbrk(); 80138689Sborman else 80238689Sborman #endif 80338689Sborman sendabort(); 80432553Sminshall return; 80532553Sminshall } 80632553Sminshall } 80732553Sminshall 80845233Sborman #ifdef SIGTSTP 809*46808Sdab /* ARGSUSED */ 810*46808Sdab static SIG_FUNC_RET 81145233Sborman susp(sig) 812*46808Sdab int sig; 81340245Sborman { 814*46808Sdab if ((rlogin != _POSIX_VDISABLE) && rlogin_susp()) 815*46808Sdab return; 81640245Sborman if (localchars) 81740245Sborman sendsusp(); 81840245Sborman } 81945233Sborman #endif 82040245Sborman 82145233Sborman #ifdef SIGWINCH 822*46808Sdab /* ARGSUSED */ 823*46808Sdab static SIG_FUNC_RET 82445233Sborman sendwin(sig) 825*46808Sdab int sig; 82637219Sminshall { 82737219Sminshall if (connected) { 82837219Sminshall sendnaws(); 82937219Sminshall } 83037219Sminshall } 83145233Sborman #endif 83237219Sminshall 83345233Sborman #ifdef SIGINFO 834*46808Sdab /* ARGSUSED */ 835*46808Sdab static SIG_FUNC_RET 83645233Sborman ayt(sig) 837*46808Sdab int sig; 83845233Sborman { 83945233Sborman if (connected) 84045233Sborman sendayt(); 84145233Sborman else 84245233Sborman ayt_status(); 84345233Sborman } 84445233Sborman #endif 84545233Sborman 84632553Sminshall 847*46808Sdab void 84832531Sminshall sys_telnet_init() 84932531Sminshall { 85045233Sborman (void) signal(SIGINT, intr); 85145233Sborman (void) signal(SIGQUIT, intr2); 85245233Sborman (void) signal(SIGPIPE, deadpeer); 85338689Sborman #ifdef SIGWINCH 85445233Sborman (void) signal(SIGWINCH, sendwin); 85538689Sborman #endif 85640245Sborman #ifdef SIGTSTP 85745233Sborman (void) signal(SIGTSTP, susp); 85840245Sborman #endif 85945233Sborman #ifdef SIGINFO 86045233Sborman (void) signal(SIGINFO, ayt); 86145233Sborman #endif 86232553Sminshall 86338689Sborman setconnmode(0); 86432531Sminshall 86532531Sminshall NetNonblockingIO(net, 1); 86632531Sminshall 86732531Sminshall #if defined(TN3270) 86836242Sminshall if (noasynchnet == 0) { /* DBX can't handle! */ 86932531Sminshall NetSigIO(net, 1); 87032531Sminshall NetSetPgrp(net); 87132531Sminshall } 87232531Sminshall #endif /* defined(TN3270) */ 87332531Sminshall 87432531Sminshall #if defined(SO_OOBINLINE) 87534849Sminshall if (SetSockOpt(net, SOL_SOCKET, SO_OOBINLINE, 1) == -1) { 87634849Sminshall perror("SetSockOpt"); 87734849Sminshall } 87832531Sminshall #endif /* defined(SO_OOBINLINE) */ 87932531Sminshall } 88032531Sminshall 88132531Sminshall /* 88232531Sminshall * Process rings - 88332531Sminshall * 88432531Sminshall * This routine tries to fill up/empty our various rings. 88532531Sminshall * 88632531Sminshall * The parameter specifies whether this is a poll operation, 88732531Sminshall * or a block-until-something-happens operation. 88832531Sminshall * 88932531Sminshall * The return value is 1 if something happened, 0 if not. 89032531Sminshall */ 89132531Sminshall 892*46808Sdab int 89332531Sminshall process_rings(netin, netout, netex, ttyin, ttyout, poll) 894*46808Sdab int poll; /* If 0, then block until something to do */ 89532531Sminshall { 89632531Sminshall register int c; 89732531Sminshall /* One wants to be a bit careful about setting returnValue 89832531Sminshall * to one, since a one implies we did some useful work, 89932531Sminshall * and therefore probably won't be called to block next 90032531Sminshall * time (TN3270 mode only). 90132531Sminshall */ 90232531Sminshall int returnValue = 0; 90332531Sminshall static struct timeval TimeValue = { 0 }; 90432531Sminshall 90532531Sminshall if (netout) { 90632531Sminshall FD_SET(net, &obits); 90732531Sminshall } 90832531Sminshall if (ttyout) { 90932531Sminshall FD_SET(tout, &obits); 91032531Sminshall } 91132531Sminshall #if defined(TN3270) 91232531Sminshall if (ttyin) { 91332531Sminshall FD_SET(tin, &ibits); 91432531Sminshall } 91532531Sminshall #else /* defined(TN3270) */ 91632531Sminshall if (ttyin) { 91732531Sminshall FD_SET(tin, &ibits); 91832531Sminshall } 91932531Sminshall #endif /* defined(TN3270) */ 92032531Sminshall #if defined(TN3270) 92132531Sminshall if (netin) { 92232531Sminshall FD_SET(net, &ibits); 92332531Sminshall } 92432531Sminshall # else /* !defined(TN3270) */ 92532531Sminshall if (netin) { 92632531Sminshall FD_SET(net, &ibits); 92732531Sminshall } 92832531Sminshall # endif /* !defined(TN3270) */ 92932531Sminshall if (netex) { 93032531Sminshall FD_SET(net, &xbits); 93132531Sminshall } 93232531Sminshall if ((c = select(16, &ibits, &obits, &xbits, 93332531Sminshall (poll == 0)? (struct timeval *)0 : &TimeValue)) < 0) { 93432531Sminshall if (c == -1) { 93532531Sminshall /* 93632531Sminshall * we can get EINTR if we are in line mode, 93732531Sminshall * and the user does an escape (TSTP), or 93832531Sminshall * some other signal generator. 93932531Sminshall */ 94032531Sminshall if (errno == EINTR) { 94132531Sminshall return 0; 94232531Sminshall } 94332531Sminshall # if defined(TN3270) 94432531Sminshall /* 94532531Sminshall * we can get EBADF if we were in transparent 94632531Sminshall * mode, and the transcom process died. 94732531Sminshall */ 94832531Sminshall if (errno == EBADF) { 94932531Sminshall /* 95032531Sminshall * zero the bits (even though kernel does it) 95132531Sminshall * to make sure we are selecting on the right 95232531Sminshall * ones. 95332531Sminshall */ 95432531Sminshall FD_ZERO(&ibits); 95532531Sminshall FD_ZERO(&obits); 95632531Sminshall FD_ZERO(&xbits); 95732531Sminshall return 0; 95832531Sminshall } 95932531Sminshall # endif /* defined(TN3270) */ 96032531Sminshall /* I don't like this, does it ever happen? */ 96132531Sminshall printf("sleep(5) from telnet, after select\r\n"); 96232531Sminshall sleep(5); 96332531Sminshall } 96432531Sminshall return 0; 96532531Sminshall } 96632531Sminshall 96732531Sminshall /* 96832531Sminshall * Any urgent data? 96932531Sminshall */ 97032531Sminshall if (FD_ISSET(net, &xbits)) { 97132531Sminshall FD_CLR(net, &xbits); 97232531Sminshall SYNCHing = 1; 97344361Sborman (void) ttyflush(1); /* flush already enqueued data */ 97432531Sminshall } 97532531Sminshall 97632531Sminshall /* 97732531Sminshall * Something to read from the network... 97832531Sminshall */ 97932531Sminshall if (FD_ISSET(net, &ibits)) { 98032531Sminshall int canread; 98132531Sminshall 98232531Sminshall FD_CLR(net, &ibits); 98332531Sminshall canread = ring_empty_consecutive(&netiring); 98432531Sminshall #if !defined(SO_OOBINLINE) 98532531Sminshall /* 98632531Sminshall * In 4.2 (and some early 4.3) systems, the 98732531Sminshall * OOB indication and data handling in the kernel 98832531Sminshall * is such that if two separate TCP Urgent requests 98932531Sminshall * come in, one byte of TCP data will be overlaid. 99032531Sminshall * This is fatal for Telnet, but we try to live 99132531Sminshall * with it. 99232531Sminshall * 99332531Sminshall * In addition, in 4.2 (and...), a special protocol 99432531Sminshall * is needed to pick up the TCP Urgent data in 99532531Sminshall * the correct sequence. 99632531Sminshall * 99732531Sminshall * What we do is: if we think we are in urgent 99832531Sminshall * mode, we look to see if we are "at the mark". 99932531Sminshall * If we are, we do an OOB receive. If we run 100032531Sminshall * this twice, we will do the OOB receive twice, 100132531Sminshall * but the second will fail, since the second 100232531Sminshall * time we were "at the mark", but there wasn't 100332531Sminshall * any data there (the kernel doesn't reset 100432531Sminshall * "at the mark" until we do a normal read). 100532531Sminshall * Once we've read the OOB data, we go ahead 100632531Sminshall * and do normal reads. 100732531Sminshall * 100832531Sminshall * There is also another problem, which is that 100932531Sminshall * since the OOB byte we read doesn't put us 101032531Sminshall * out of OOB state, and since that byte is most 101132531Sminshall * likely the TELNET DM (data mark), we would 101232531Sminshall * stay in the TELNET SYNCH (SYNCHing) state. 101332531Sminshall * So, clocks to the rescue. If we've "just" 101432531Sminshall * received a DM, then we test for the 101532531Sminshall * presence of OOB data when the receive OOB 101632531Sminshall * fails (and AFTER we did the normal mode read 101732531Sminshall * to clear "at the mark"). 101832531Sminshall */ 101932531Sminshall if (SYNCHing) { 102032531Sminshall int atmark; 102139652Sborman static int bogus_oob = 0, first = 1; 102232531Sminshall 102332531Sminshall ioctl(net, SIOCATMARK, (char *)&atmark); 102432531Sminshall if (atmark) { 102532531Sminshall c = recv(net, netiring.supply, canread, MSG_OOB); 102632531Sminshall if ((c == -1) && (errno == EINVAL)) { 102732531Sminshall c = recv(net, netiring.supply, canread, 0); 102832531Sminshall if (clocks.didnetreceive < clocks.gotDM) { 102932531Sminshall SYNCHing = stilloob(net); 103032531Sminshall } 103139652Sborman } else if (first && c > 0) { 103239652Sborman /* 103339652Sborman * Bogosity check. Systems based on 4.2BSD 103439652Sborman * do not return an error if you do a second 103539652Sborman * recv(MSG_OOB). So, we do one. If it 103639652Sborman * succeeds and returns exactly the same 103739652Sborman * data, then assume that we are running 103839652Sborman * on a broken system and set the bogus_oob 103939652Sborman * flag. (If the data was different, then 104039652Sborman * we probably got some valid new data, so 104139652Sborman * increment the count...) 104239652Sborman */ 104339652Sborman int i; 104439652Sborman i = recv(net, netiring.supply + c, canread - c, MSG_OOB); 104539652Sborman if (i == c && 104639652Sborman bcmp(netiring.supply, netiring.supply + c, i) == 0) { 104739652Sborman bogus_oob = 1; 104839652Sborman first = 0; 104939652Sborman } else if (i < 0) { 105039652Sborman bogus_oob = 0; 105139652Sborman first = 0; 105239652Sborman } else 105339652Sborman c += i; 105432531Sminshall } 105539652Sborman if (bogus_oob && c > 0) { 105639652Sborman int i; 105739652Sborman /* 105839652Sborman * Bogosity. We have to do the read 105939652Sborman * to clear the atmark to get out of 106039652Sborman * an infinate loop. 106139652Sborman */ 106239652Sborman i = read(net, netiring.supply + c, canread - c); 106339652Sborman if (i > 0) 106439652Sborman c += i; 106539652Sborman } 106632531Sminshall } else { 106732531Sminshall c = recv(net, netiring.supply, canread, 0); 106832531Sminshall } 106932531Sminshall } else { 107032531Sminshall c = recv(net, netiring.supply, canread, 0); 107132531Sminshall } 107232531Sminshall settimer(didnetreceive); 107332531Sminshall #else /* !defined(SO_OOBINLINE) */ 107432531Sminshall c = recv(net, netiring.supply, canread, 0); 107532531Sminshall #endif /* !defined(SO_OOBINLINE) */ 107632531Sminshall if (c < 0 && errno == EWOULDBLOCK) { 107732531Sminshall c = 0; 107832531Sminshall } else if (c <= 0) { 107932531Sminshall return -1; 108032531Sminshall } 108132531Sminshall if (netdata) { 108232531Sminshall Dump('<', netiring.supply, c); 108332531Sminshall } 108432667Sminshall if (c) 108532667Sminshall ring_supplied(&netiring, c); 108632531Sminshall returnValue = 1; 108732531Sminshall } 108832531Sminshall 108932531Sminshall /* 109032531Sminshall * Something to read from the tty... 109132531Sminshall */ 109232531Sminshall if (FD_ISSET(tin, &ibits)) { 109332531Sminshall FD_CLR(tin, &ibits); 109433286Sminshall c = TerminalRead(ttyiring.supply, ring_empty_consecutive(&ttyiring)); 109532531Sminshall if (c < 0 && errno == EWOULDBLOCK) { 109632531Sminshall c = 0; 109732531Sminshall } else { 109832531Sminshall /* EOF detection for line mode!!!! */ 109933281Sminshall if ((c == 0) && MODE_LOCAL_CHARS(globalmode) && isatty(tin)) { 110032531Sminshall /* must be an EOF... */ 110132531Sminshall *ttyiring.supply = termEofChar; 110232531Sminshall c = 1; 110332531Sminshall } 110432531Sminshall if (c <= 0) { 110532531Sminshall return -1; 110632531Sminshall } 110738208Sminshall if (termdata) { 110838208Sminshall Dump('<', ttyiring.supply, c); 110938208Sminshall } 111032667Sminshall ring_supplied(&ttyiring, c); 111132531Sminshall } 111232531Sminshall returnValue = 1; /* did something useful */ 111332531Sminshall } 111432531Sminshall 111532531Sminshall if (FD_ISSET(net, &obits)) { 111632531Sminshall FD_CLR(net, &obits); 111732531Sminshall returnValue |= netflush(); 111832531Sminshall } 111932531Sminshall if (FD_ISSET(tout, &obits)) { 112032531Sminshall FD_CLR(tout, &obits); 112138689Sborman returnValue |= (ttyflush(SYNCHing|flushout) > 0); 112232531Sminshall } 112332531Sminshall 112432531Sminshall return returnValue; 112532531Sminshall } 1126