132147Sminshall /* 2*45233Sborman * 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*45233Sborman static char sccsid[] = "@(#)sys_bsd.c 5.1 (Berkeley) 09/14/90"; 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 34*45233Sborman #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; 50*45233Sborman # define cfgetispeed(ptr) (ptr)->sg_ispeed 51*45233Sborman # define cfgetospeed(ptr) (ptr)->sg_ospeed 52*45233Sborman # define old_tc ottyb 5332147Sminshall 5438689Sborman #else /* USE_TERMIO */ 5538689Sborman struct termio old_tc = { 0 }; 5638689Sborman extern struct termio new_tc; 5738689Sborman 58*45233Sborman # ifndef TCSANOW 59*45233Sborman # ifdef TCSETS 60*45233Sborman # define TCSANOW TCSETS 61*45233Sborman # define TCSADRAIN TCSETSW 62*45233Sborman # define tcgetattr(f, t) ioctl(f, TCGETS, t) 63*45233Sborman # else 64*45233Sborman # ifdef TCSETA 65*45233Sborman # define TCSANOW TCSETA 66*45233Sborman # define TCSADRAIN TCSETAW 67*45233Sborman # define tcgetattr(f, t) ioctl(f, TCGETA, t) 68*45233Sborman # else 69*45233Sborman # define TCSANOW TIOCSETA 70*45233Sborman # define TCSADRAIN TIOCSETAW 71*45233Sborman # define tcgetattr(f, t) ioctl(f, TIOCGETA, t) 72*45233Sborman # endif 73*45233Sborman # endif 74*45233Sborman # define tcsetattr(f, a, t) ioctl(f, a, t) 75*45233Sborman # define cfgetospeed(ptr) ((ptr)->c_cflag&CBAUD) 76*45233Sborman # ifdef CIBAUD 77*45233Sborman # define cfgetispeed(ptr) (((ptr)->c_cflag&CIBAUD) >> IBSHIFT) 78*45233Sborman # else 79*45233Sborman # define cfgetispeed(ptr) cfgetospeed(ptr) 80*45233Sborman # endif 81*45233Sborman # endif /* TCSANOW */ 8238689Sborman #endif /* USE_TERMIO */ 8338689Sborman 8432531Sminshall static fd_set ibits, obits, xbits; 8532147Sminshall 8632531Sminshall 8732531Sminshall init_sys() 8832531Sminshall { 8932531Sminshall tout = fileno(stdout); 9032531Sminshall tin = fileno(stdin); 9132531Sminshall FD_ZERO(&ibits); 9232531Sminshall FD_ZERO(&obits); 9332531Sminshall FD_ZERO(&xbits); 9432531Sminshall 9532531Sminshall errno = 0; 9632531Sminshall } 9732531Sminshall 9832531Sminshall 9933286Sminshall TerminalWrite(buf, n) 10032147Sminshall char *buf; 10132147Sminshall int n; 10232147Sminshall { 10333286Sminshall return write(tout, buf, n); 10432147Sminshall } 10532147Sminshall 10633286Sminshall TerminalRead(buf, n) 10732147Sminshall char *buf; 10832147Sminshall int n; 10932147Sminshall { 11033286Sminshall return read(tin, buf, n); 11132147Sminshall } 11232147Sminshall 11332147Sminshall /* 11432147Sminshall * 11532147Sminshall */ 11632147Sminshall 11732147Sminshall int 11832553Sminshall TerminalAutoFlush() 11932147Sminshall { 12032147Sminshall #if defined(LNOFLSH) 12132147Sminshall int flush; 12232147Sminshall 12332147Sminshall ioctl(0, TIOCLGET, (char *)&flush); 12432147Sminshall return !(flush&LNOFLSH); /* if LNOFLSH, no autoflush */ 12532147Sminshall #else /* LNOFLSH */ 12632147Sminshall return 1; 12732147Sminshall #endif /* LNOFLSH */ 12832147Sminshall } 12932147Sminshall 13038689Sborman #ifdef KLUDGELINEMODE 13138689Sborman extern int kludgelinemode; 13238689Sborman #endif 13332147Sminshall /* 13432147Sminshall * TerminalSpecialChars() 13532147Sminshall * 13632147Sminshall * Look at an input character to see if it is a special character 13732147Sminshall * and decide what to do. 13832147Sminshall * 13932147Sminshall * Output: 14032147Sminshall * 14132147Sminshall * 0 Don't add this character. 14232147Sminshall * 1 Do add this character 14332147Sminshall */ 14432147Sminshall 14532147Sminshall int 14632553Sminshall TerminalSpecialChars(c) 14732147Sminshall int c; 14832147Sminshall { 14932553Sminshall void xmitAO(), xmitEL(), xmitEC(), intp(), sendbrk(); 15032147Sminshall 15138689Sborman if (c == termIntChar) { 15232147Sminshall intp(); 15332147Sminshall return 0; 15438689Sborman } else if (c == termQuitChar) { 15538689Sborman #ifdef KLUDGELINEMODE 15638689Sborman if (kludgelinemode) 15738689Sborman sendbrk(); 15838689Sborman else 15938689Sborman #endif 16038689Sborman sendabort(); 16132147Sminshall return 0; 16238689Sborman } else if (c == termEofChar) { 16338689Sborman if (my_want_state_is_will(TELOPT_LINEMODE)) { 16438689Sborman sendeof(); 16538689Sborman return 0; 16638689Sborman } 16738689Sborman return 1; 16838689Sborman } else if (c == termSuspChar) { 16938689Sborman sendsusp(); 17038689Sborman return(0); 17138689Sborman } else if (c == termFlushChar) { 17232147Sminshall xmitAO(); /* Transmit Abort Output */ 17332147Sminshall return 0; 17432147Sminshall } else if (!MODE_LOCAL_CHARS(globalmode)) { 17538689Sborman if (c == termKillChar) { 17632147Sminshall xmitEL(); 17732147Sminshall return 0; 17838689Sborman } else if (c == termEraseChar) { 17932147Sminshall xmitEC(); /* Transmit Erase Character */ 18032147Sminshall return 0; 18132147Sminshall } 18232147Sminshall } 18332147Sminshall return 1; 18432147Sminshall } 18532147Sminshall 18632147Sminshall 18732147Sminshall /* 18832147Sminshall * Flush output to the terminal 18932147Sminshall */ 19032147Sminshall 19132147Sminshall void 19232553Sminshall TerminalFlushOutput() 19332147Sminshall { 19439529Sborman #ifdef TIOCFLUSH 19532147Sminshall (void) ioctl(fileno(stdout), TIOCFLUSH, (char *) 0); 19638689Sborman #else 19738689Sborman (void) ioctl(fileno(stdout), TCFLSH, (char *) 0); 19838689Sborman #endif 19932147Sminshall } 20032147Sminshall 20132147Sminshall void 20232553Sminshall TerminalSaveState() 20332147Sminshall { 20438689Sborman #ifndef USE_TERMIO 20532147Sminshall ioctl(0, TIOCGETP, (char *)&ottyb); 20632147Sminshall ioctl(0, TIOCGETC, (char *)&otc); 20732147Sminshall ioctl(0, TIOCGLTC, (char *)&oltc); 20838909Sborman ioctl(0, TIOCLGET, (char *)&olmode); 20932147Sminshall 21032147Sminshall ntc = otc; 21132147Sminshall nltc = oltc; 21232147Sminshall nttyb = ottyb; 21332254Sminshall 21438689Sborman #else /* USE_TERMIO */ 215*45233Sborman tcgetattr(0, &old_tc); 21638689Sborman 21738689Sborman new_tc = old_tc; 21838689Sborman 219*45233Sborman #ifndef VDISCARD 22044361Sborman termFlushChar = CONTROL('O'); 221*45233Sborman #endif 222*45233Sborman #ifndef VWERASE 22344361Sborman termWerasChar = CONTROL('W'); 224*45233Sborman #endif 225*45233Sborman #ifndef VREPRINT 22644361Sborman termRprntChar = CONTROL('R'); 227*45233Sborman #endif 228*45233Sborman #ifndef VLNEXT 22944361Sborman termLiteralNextChar = CONTROL('V'); 230*45233Sborman #endif 231*45233Sborman #ifndef VSTART 23244361Sborman termStartChar = CONTROL('Q'); 233*45233Sborman #endif 234*45233Sborman #ifndef VSTOP 23544361Sborman termStopChar = CONTROL('S'); 236*45233Sborman #endif 237*45233Sborman #ifndef VSTATUS 238*45233Sborman termAytChar = CONTROL('T'); 239*45233Sborman #endif 24038689Sborman #endif /* USE_TERMIO */ 24132147Sminshall } 24232147Sminshall 24340245Sborman cc_t * 24438689Sborman tcval(func) 24538689Sborman register int func; 24638689Sborman { 24738689Sborman switch(func) { 24840245Sborman case SLC_IP: return(&termIntChar); 24940245Sborman case SLC_ABORT: return(&termQuitChar); 25040245Sborman case SLC_EOF: return(&termEofChar); 25140245Sborman case SLC_EC: return(&termEraseChar); 25240245Sborman case SLC_EL: return(&termKillChar); 25340245Sborman case SLC_XON: return(&termStartChar); 25440245Sborman case SLC_XOFF: return(&termStopChar); 25544361Sborman case SLC_FORW1: return(&termForw1Char); 256*45233Sborman #ifdef USE_TERMIO 257*45233Sborman case SLC_FORW2: return(&termForw2Char); 258*45233Sborman # ifdef VDISCARD 25940245Sborman case SLC_AO: return(&termFlushChar); 260*45233Sborman # endif 261*45233Sborman # ifdef VSUSP 26240245Sborman case SLC_SUSP: return(&termSuspChar); 263*45233Sborman # endif 264*45233Sborman # ifdef VWERASE 26540245Sborman case SLC_EW: return(&termWerasChar); 266*45233Sborman # endif 267*45233Sborman # ifdef VREPRINT 26840245Sborman case SLC_RP: return(&termRprntChar); 269*45233Sborman # endif 270*45233Sborman # ifdef VLNEXT 27140245Sborman case SLC_LNEXT: return(&termLiteralNextChar); 272*45233Sborman # endif 273*45233Sborman # ifdef VSTATUS 274*45233Sborman case SLC_AYT: return(&termAytChar); 275*45233Sborman # endif 27644361Sborman #endif 27738689Sborman 27838689Sborman case SLC_SYNCH: 27938689Sborman case SLC_BRK: 28038689Sborman case SLC_EOR: 28138689Sborman default: 28240245Sborman return((cc_t *)0); 28338689Sborman } 28438689Sborman } 28538689Sborman 28632147Sminshall void 28738689Sborman TerminalDefaultChars() 28838689Sborman { 28938689Sborman #ifndef USE_TERMIO 29038689Sborman ntc = otc; 29138689Sborman nltc = oltc; 29238689Sborman nttyb.sg_kill = ottyb.sg_kill; 29338689Sborman nttyb.sg_erase = ottyb.sg_erase; 29438689Sborman #else /* USE_TERMIO */ 29538689Sborman memcpy(new_tc.c_cc, old_tc.c_cc, sizeof(old_tc.c_cc)); 296*45233Sborman # ifndef VDISCARD 29744361Sborman termFlushChar = CONTROL('O'); 29839529Sborman # endif 29939529Sborman # ifndef VWERASE 30044361Sborman termWerasChar = CONTROL('W'); 30139529Sborman # endif 30239529Sborman # ifndef VREPRINT 30344361Sborman termRprntChar = CONTROL('R'); 30439529Sborman # endif 30539529Sborman # ifndef VLNEXT 30644361Sborman termLiteralNextChar = CONTROL('V'); 30739529Sborman # endif 30839529Sborman # ifndef VSTART 30944361Sborman termStartChar = CONTROL('Q'); 31039529Sborman # endif 31139529Sborman # ifndef VSTOP 31244361Sborman termStopChar = CONTROL('S'); 31339529Sborman # endif 314*45233Sborman # ifndef VSTATUS 315*45233Sborman termAytChar = CONTROL('T'); 316*45233Sborman # endif 31738689Sborman #endif /* USE_TERMIO */ 31838689Sborman } 31938689Sborman 32044361Sborman #ifdef notdef 32138689Sborman void 32232553Sminshall TerminalRestoreState() 32332147Sminshall { 32432147Sminshall } 32544361Sborman #endif 32632147Sminshall 32732147Sminshall /* 32832147Sminshall * TerminalNewMode - set up terminal to a specific mode. 32938689Sborman * MODE_ECHO: do local terminal echo 33038689Sborman * MODE_FLOW: do local flow control 33138689Sborman * MODE_TRAPSIG: do local mapping to TELNET IAC sequences 33238689Sborman * MODE_EDIT: do local line editing 33338689Sborman * 33438689Sborman * Command mode: 33538689Sborman * MODE_ECHO|MODE_EDIT|MODE_FLOW|MODE_TRAPSIG 33638689Sborman * local echo 33738689Sborman * local editing 33838689Sborman * local xon/xoff 33938689Sborman * local signal mapping 34038689Sborman * 34138689Sborman * Linemode: 34238689Sborman * local/no editing 34338689Sborman * Both Linemode and Single Character mode: 34438689Sborman * local/remote echo 34538689Sborman * local/no xon/xoff 34638689Sborman * local/no signal mapping 34732147Sminshall */ 34832147Sminshall 34932147Sminshall 35032147Sminshall void 35133286Sminshall TerminalNewMode(f) 35232147Sminshall register int f; 35332147Sminshall { 35432147Sminshall static int prevmode = 0; 35538689Sborman #ifndef USE_TERMIO 35638689Sborman struct tchars tc; 35738689Sborman struct ltchars ltc; 35832147Sminshall struct sgttyb sb; 35938909Sborman int lmode; 36038689Sborman #else /* USE_TERMIO */ 36138689Sborman struct termio tmp_tc; 36238689Sborman #endif /* USE_TERMIO */ 36332147Sminshall int onoff; 36432147Sminshall int old; 36532147Sminshall 36638689Sborman globalmode = f&~MODE_FORCE; 36732147Sminshall if (prevmode == f) 36832147Sminshall return; 36938689Sborman 37038689Sborman /* 37138689Sborman * Write any outstanding data before switching modes 37238689Sborman * ttyflush() returns 0 only when there is no more data 37338689Sborman * left to write out, it returns -1 if it couldn't do 37438689Sborman * anything at all, otherwise it returns 1 + the number 37538689Sborman * of characters left to write. 376*45233Sborman #ifndef USE_TERMIO 377*45233Sborman * We would really like ask the kernel to wait for the output 378*45233Sborman * to drain, like we can do with the TCSADRAIN, but we don't have 379*45233Sborman * that option. The only ioctl that waits for the output to 380*45233Sborman * drain, TIOCSETP, also flushes the input queue, which is NOT 381*45233Sborman * what we want (TIOCSETP is like TCSADFLUSH). 382*45233Sborman #endif 38338689Sborman */ 38438689Sborman old = ttyflush(SYNCHing|flushout); 38538689Sborman if (old < 0 || old > 1) { 386*45233Sborman #ifdef USE_TERMIO 387*45233Sborman tcgetattr(tin, (char *)&tmp_tc); 38838689Sborman #endif /* USE_TERMIO */ 38938689Sborman do { 39038689Sborman /* 39138689Sborman * Wait for data to drain, then flush again. 39238689Sborman */ 393*45233Sborman #ifdef USE_TERMIO 394*45233Sborman tcsetattr(tin, TCSADRAIN, (char *)&tmp_tc); 39538689Sborman #endif /* USE_TERMIO */ 39638689Sborman old = ttyflush(SYNCHing|flushout); 39738689Sborman } while (old < 0 || old > 1); 39838689Sborman } 39938689Sborman 40032147Sminshall old = prevmode; 40138689Sborman prevmode = f&~MODE_FORCE; 40238689Sborman #ifndef USE_TERMIO 40332147Sminshall sb = nttyb; 40438689Sborman tc = ntc; 40538689Sborman ltc = nltc; 40638909Sborman lmode = olmode; 40738689Sborman #else 40838689Sborman tmp_tc = new_tc; 40938689Sborman #endif 41032147Sminshall 41138689Sborman if (f&MODE_ECHO) { 41238689Sborman #ifndef USE_TERMIO 41338689Sborman sb.sg_flags |= ECHO; 41438689Sborman #else 41538689Sborman tmp_tc.c_lflag |= ECHO; 41638689Sborman tmp_tc.c_oflag |= ONLCR; 41739529Sborman # ifdef notdef 41838689Sborman tmp_tc.c_iflag |= ICRNL; 41939529Sborman # endif 42038689Sborman #endif 42138689Sborman } else { 42238689Sborman #ifndef USE_TERMIO 42338689Sborman sb.sg_flags &= ~ECHO; 42438689Sborman #else 42538689Sborman tmp_tc.c_lflag &= ~ECHO; 42638689Sborman tmp_tc.c_oflag &= ~ONLCR; 42739529Sborman # ifdef notdef 42838689Sborman tmp_tc.c_iflag &= ~ICRNL; 42939529Sborman # endif 43038689Sborman #endif 43138689Sborman } 43232147Sminshall 43338689Sborman if ((f&MODE_FLOW) == 0) { 43438689Sborman #ifndef USE_TERMIO 435*45233Sborman tc.t_startc = _POSIX_VDISABLE; 436*45233Sborman tc.t_stopc = _POSIX_VDISABLE; 43738689Sborman #else 43838689Sborman tmp_tc.c_iflag &= ~(IXANY|IXOFF|IXON); 43938689Sborman } else { 44038689Sborman tmp_tc.c_iflag |= IXANY|IXOFF|IXON; 44138689Sborman #endif 44238689Sborman } 44332147Sminshall 44438689Sborman if ((f&MODE_TRAPSIG) == 0) { 44538689Sborman #ifndef USE_TERMIO 446*45233Sborman tc.t_intrc = _POSIX_VDISABLE; 447*45233Sborman tc.t_quitc = _POSIX_VDISABLE; 448*45233Sborman tc.t_eofc = _POSIX_VDISABLE; 449*45233Sborman ltc.t_suspc = _POSIX_VDISABLE; 450*45233Sborman ltc.t_dsuspc = _POSIX_VDISABLE; 45138689Sborman #else 45238689Sborman tmp_tc.c_lflag &= ~ISIG; 45338689Sborman #endif 45438689Sborman localchars = 0; 45538689Sborman } else { 45638689Sborman #ifdef USE_TERMIO 45738689Sborman tmp_tc.c_lflag |= ISIG; 45838689Sborman #endif 45938689Sborman localchars = 1; 46038689Sborman } 46138689Sborman 46238689Sborman if (f&MODE_EDIT) { 46338689Sborman #ifndef USE_TERMIO 46438689Sborman sb.sg_flags &= ~CBREAK; 46538689Sborman sb.sg_flags |= CRMOD; 46638689Sborman #else 46738689Sborman tmp_tc.c_lflag |= ICANON; 46838689Sborman #endif 46938689Sborman } else { 47038689Sborman #ifndef USE_TERMIO 47138689Sborman sb.sg_flags |= CBREAK; 47238689Sborman if (f&MODE_ECHO) 47332147Sminshall sb.sg_flags |= CRMOD; 47438689Sborman else 47538689Sborman sb.sg_flags &= ~CRMOD; 47638689Sborman #else 47738689Sborman tmp_tc.c_lflag &= ~ICANON; 47838689Sborman tmp_tc.c_iflag &= ~ICRNL; 47938689Sborman tmp_tc.c_cc[VMIN] = 1; 48038689Sborman tmp_tc.c_cc[VTIME] = 0; 48138689Sborman #endif 48238689Sborman } 48332147Sminshall 48444361Sborman if ((f&(MODE_EDIT|MODE_TRAPSIG)) == 0) { 48544361Sborman #ifndef USE_TERMIO 486*45233Sborman ltc.t_lnextc = _POSIX_VDISABLE; 48744361Sborman #else 48844361Sborman # ifdef VLNEXT 489*45233Sborman tmp_tc.c_cc[VLNEXT] = (cc_t)(_POSIX_VDISABLE); 49044361Sborman # endif 49144361Sborman #endif 49244361Sborman } 49344361Sborman 49444361Sborman if (f&MODE_SOFT_TAB) { 49544361Sborman #ifndef USE_TERMIO 49644361Sborman sb.sg_flags |= XTABS; 49744361Sborman #else 49844361Sborman # ifdef OXTABS 49944361Sborman tmp_tc.c_oflag |= OXTABS; 50044361Sborman # endif 50144361Sborman # ifdef TABDLY 50244361Sborman tmp_tc.c_oflag &= ~TABDLY; 50344361Sborman tmp_tc.c_oflag |= TAB3; 50444361Sborman # endif 50544361Sborman #endif 50644361Sborman } else { 50744361Sborman #ifndef USE_TERMIO 50844361Sborman sb.sg_flags &= ~XTABS; 50944361Sborman #else 51044361Sborman # ifdef OXTABS 51144361Sborman tmp_tc.c_oflag &= ~OXTABS; 51244361Sborman # endif 51344361Sborman # ifdef TABDLY 51444361Sborman tmp_tc.c_oflag &= ~TABDLY; 51544361Sborman # endif 51644361Sborman #endif 51744361Sborman } 51844361Sborman 51944361Sborman if (f&MODE_LIT_ECHO) { 52044361Sborman #ifndef USE_TERMIO 52144361Sborman sb.sg_flags &= ~CTLECH; 52244361Sborman #else 52344361Sborman # ifdef ECHOCTL 52444361Sborman tmp_tc.c_lflag &= ~ECHOCTL; 52544361Sborman # endif 52644361Sborman #endif 52744361Sborman } else { 52844361Sborman #ifndef USE_TERMIO 52944361Sborman sb.sg_flags |= CTLECH; 53044361Sborman #else 53144361Sborman # ifdef ECHOCTL 53244361Sborman tmp_tc.c_lflag |= ECHOCTL; 53344361Sborman # endif 53444361Sborman #endif 53544361Sborman } 53644361Sborman 53738689Sborman if (f == -1) { 53838689Sborman onoff = 0; 53938689Sborman } else { 54038909Sborman #ifndef USE_TERMIO 54139529Sborman if (f & MODE_OUTBIN) 54238909Sborman lmode |= LLITOUT; 54338909Sborman else 54438909Sborman lmode &= ~LLITOUT; 54539529Sborman 54639529Sborman if (f & MODE_INBIN) 54738909Sborman lmode |= LPASS8; 54838909Sborman else 54938909Sborman lmode &= ~LPASS8; 55038909Sborman #else 551*45233Sborman if (f & MODE_INBIN) 552*45233Sborman tmp_tc.c_iflag &= ~ISTRIP; 55338909Sborman else 554*45233Sborman tmp_tc.c_iflag |= ISTRIP; 555*45233Sborman if (f & MODE_OUTBIN) { 55639529Sborman tmp_tc.c_cflag &= ~(CSIZE|PARENB); 55739529Sborman tmp_tc.c_cflag |= CS8; 558*45233Sborman tmp_tc.c_oflag &= ~OPOST; 55939529Sborman } else { 560*45233Sborman tmp_tc.c_cflag &= ~(CSIZE|PARENB); 561*45233Sborman tmp_tc.c_cflag |= old_tc.c_cflag & (CSIZE|PARENB); 562*45233Sborman tmp_tc.c_oflag |= OPOST; 56339529Sborman } 56438909Sborman #endif 56538689Sborman onoff = 1; 56632147Sminshall } 56738689Sborman 56838689Sborman if (f != -1) { 56939529Sborman #ifdef SIGTSTP 570*45233Sborman static SIG_FUNC_RET susp(); 571*45233Sborman #endif /* SIGTSTP */ 572*45233Sborman #ifdef SIGINFO 573*45233Sborman static SIG_FUNC_RET ayt(); 574*45233Sborman #endif SIGINFO 57538689Sborman 576*45233Sborman #ifdef SIGTSTP 577*45233Sborman (void) signal(SIGTSTP, susp); 57839529Sborman #endif /* SIGTSTP */ 579*45233Sborman #ifdef SIGINFO 580*45233Sborman (void) signal(SIGINFO, ayt); 581*45233Sborman #endif SIGINFO 582*45233Sborman #if defined(USE_TERMIO) && defined(NOKERNINFO) 583*45233Sborman tmp_tc.c_lflag |= NOKERNINFO; 584*45233Sborman #endif 58544361Sborman /* 58644361Sborman * We don't want to process ^Y here. It's just another 58744361Sborman * character that we'll pass on to the back end. It has 58844361Sborman * to process it because it will be processed when the 58944361Sborman * user attempts to read it, not when we send it. 59044361Sborman */ 59144361Sborman #ifndef USE_TERMIO 592*45233Sborman ltc.t_dsuspc = _POSIX_VDISABLE; 59344361Sborman #else 59444361Sborman # ifdef VDSUSP 595*45233Sborman tmp_tc.c_cc[VDSUSP] = (cc_t)(_POSIX_VDISABLE); 59644361Sborman # endif 59744361Sborman #endif 59840245Sborman #ifdef USE_TERMIO 59940245Sborman /* 60040245Sborman * If the VEOL character is already set, then use VEOL2, 60140245Sborman * otherwise use VEOL. 60240245Sborman */ 603*45233Sborman if ((tmp_tc.c_cc[VEOL] != escape) 60444361Sborman # ifdef VEOL2 605*45233Sborman && (tmp_tc.c_cc[VEOL2] != escape) 60644361Sborman # endif 607*45233Sborman ) { 608*45233Sborman if (tmp_tc.c_cc[VEOL] == (cc_t)(_POSIX_VDISABLE)) 609*45233Sborman tmp_tc.c_cc[VEOL] = escape; 610*45233Sborman # ifdef VEOL2 611*45233Sborman else if (tmp_tc.c_cc[VEOL2] == (cc_t)(_POSIX_VDISABLE)) 612*45233Sborman tmp_tc.c_cc[VEOL2] = escape; 613*45233Sborman # endif 614*45233Sborman } 61540245Sborman #else 616*45233Sborman if (tc.t_brkc == (cc_t)(_POSIX_VDISABLE)) 61744361Sborman tc.t_brkc = escape; 61840245Sborman #endif 61938689Sborman } else { 620*45233Sborman #ifdef SIGINFO 621*45233Sborman SIG_FUNC_RET ayt_status(); 622*45233Sborman 623*45233Sborman (void) signal(SIGINFO, ayt_status); 624*45233Sborman #endif SIGINFO 62539529Sborman #ifdef SIGTSTP 62638689Sborman (void) signal(SIGTSTP, SIG_DFL); 62744361Sborman (void) sigsetmask(sigblock(0) & ~(1<<(SIGTSTP-1))); 62839529Sborman #endif /* SIGTSTP */ 62939529Sborman #ifndef USE_TERMIO 63039529Sborman ltc = oltc; 63139529Sborman tc = otc; 63239529Sborman sb = ottyb; 63344361Sborman lmode = olmode; 63444361Sborman #else 63544361Sborman tmp_tc = old_tc; 63639529Sborman #endif 63738689Sborman } 63839529Sborman #ifndef USE_TERMIO 63939529Sborman ioctl(tin, TIOCLSET, (char *)&lmode); 64039529Sborman ioctl(tin, TIOCSLTC, (char *)<c); 64139529Sborman ioctl(tin, TIOCSETC, (char *)&tc); 642*45233Sborman ioctl(tin, TIOCSETN, (char *)&sb); 64339529Sborman #else 644*45233Sborman if (tcsetattr(tin, TCSADRAIN, &tmp_tc) < 0) 645*45233Sborman tcsetattr(tin, TCSANOW, &tmp_tc); 64639529Sborman #endif 64739529Sborman 64832147Sminshall #if (!defined(TN3270)) || ((!defined(NOT43)) || defined(PUTCHAR)) 64933286Sminshall ioctl(tin, FIONBIO, (char *)&onoff); 65033286Sminshall ioctl(tout, FIONBIO, (char *)&onoff); 65132147Sminshall #endif /* (!defined(TN3270)) || ((!defined(NOT43)) || defined(PUTCHAR)) */ 65232147Sminshall #if defined(TN3270) 65336242Sminshall if (noasynchtty == 0) { 65433286Sminshall ioctl(tin, FIOASYNC, (char *)&onoff); 65532147Sminshall } 65632147Sminshall #endif /* defined(TN3270) */ 65732147Sminshall } 65832147Sminshall 65939529Sborman #ifndef B19200 66039529Sborman # define B19200 B9600 66139529Sborman #endif 66239529Sborman 66339529Sborman #ifndef B38400 66439529Sborman # define B38400 B19200 66539529Sborman #endif 66639529Sborman 66739529Sborman /* 66839529Sborman * This code assumes that the values B0, B50, B75... 66939529Sborman * are in ascending order. They do not have to be 67039529Sborman * contiguous. 67139529Sborman */ 67239529Sborman struct termspeeds { 67339529Sborman long speed; 67439529Sborman long value; 67539529Sborman } termspeeds[] = { 67639529Sborman { 0, B0 }, { 50, B50 }, { 75, B75 }, 67739529Sborman { 110, B110 }, { 134, B134 }, { 150, B150 }, 67839529Sborman { 200, B200 }, { 300, B300 }, { 600, B600 }, 67939529Sborman { 1200, B1200 }, { 1800, B1800 }, { 2400, B2400 }, 68039529Sborman { 4800, B4800 }, { 9600, B9600 }, { 19200, B19200 }, 68139529Sborman { 38400, B38400 }, { -1, B38400 } 68239529Sborman }; 68339529Sborman 68437219Sminshall void 68537219Sminshall TerminalSpeeds(ispeed, ospeed) 68637219Sminshall long *ispeed; 68737219Sminshall long *ospeed; 68837219Sminshall { 68939529Sborman register struct termspeeds *tp; 690*45233Sborman register long in, out; 69132147Sminshall 692*45233Sborman in = cfgetispeed(&old_tc); 693*45233Sborman out = cfgetospeed(&old_tc); 694*45233Sborman 69539529Sborman tp = termspeeds; 696*45233Sborman while ((tp->speed != -1) && (tp->value < in)) 69739529Sborman tp++; 69839529Sborman *ispeed = tp->speed; 69939529Sborman 70039529Sborman tp = termspeeds; 701*45233Sborman while ((tp->speed != -1) && (tp->value < out)) 70239529Sborman tp++; 70339529Sborman *ospeed = tp->speed; 70437219Sminshall } 70537219Sminshall 70632147Sminshall int 70737219Sminshall TerminalWindowSize(rows, cols) 70837219Sminshall long *rows, *cols; 70937219Sminshall { 71038689Sborman #ifdef TIOCGWINSZ 71137219Sminshall struct winsize ws; 71237219Sminshall 71338689Sborman if (ioctl(fileno(stdin), TIOCGWINSZ, (char *)&ws) >= 0) { 71438689Sborman *rows = ws.ws_row; 71538689Sborman *cols = ws.ws_col; 71638689Sborman return 1; 71737219Sminshall } 71838810Sborman #endif /* TIOCGWINSZ */ 71938689Sborman return 0; 72037219Sminshall } 72137219Sminshall 72237219Sminshall int 72335417Sminshall NetClose(fd) 72435417Sminshall int fd; 72532147Sminshall { 72635417Sminshall return close(fd); 72732147Sminshall } 72832147Sminshall 72932147Sminshall 73032147Sminshall void 73132553Sminshall NetNonblockingIO(fd, onoff) 73232147Sminshall int 73332147Sminshall fd, 73432147Sminshall onoff; 73532147Sminshall { 73632147Sminshall ioctl(fd, FIONBIO, (char *)&onoff); 73732147Sminshall } 73832147Sminshall 73934849Sminshall #if defined(TN3270) 74032147Sminshall void 74132553Sminshall NetSigIO(fd, onoff) 74232147Sminshall int 74332147Sminshall fd, 74432147Sminshall onoff; 74532147Sminshall { 74632147Sminshall ioctl(fd, FIOASYNC, (char *)&onoff); /* hear about input */ 74732147Sminshall } 74832147Sminshall 74932147Sminshall void 75032553Sminshall NetSetPgrp(fd) 75132147Sminshall int fd; 75232147Sminshall { 75332147Sminshall int myPid; 75432147Sminshall 75532147Sminshall myPid = getpid(); 75636274Sminshall fcntl(fd, F_SETOWN, myPid); 75732147Sminshall } 75834849Sminshall #endif /*defined(TN3270)*/ 75932553Sminshall 76032553Sminshall /* 76132553Sminshall * Various signal handling routines. 76232553Sminshall */ 76332147Sminshall 764*45233Sborman /* ARGSUSED */ 765*45233Sborman static SIG_FUNC_RET 766*45233Sborman deadpeer(sig) 767*45233Sborman int sig; 76832553Sminshall { 76932553Sminshall setcommandmode(); 77032553Sminshall longjmp(peerdied, -1); 77132553Sminshall } 77232147Sminshall 773*45233Sborman /* ARGSUSED */ 774*45233Sborman static SIG_FUNC_RET 775*45233Sborman intr(sig) 776*45233Sborman int sig; 77732553Sminshall { 77832553Sminshall if (localchars) { 77932553Sminshall intp(); 78032553Sminshall return; 78132553Sminshall } 78232553Sminshall setcommandmode(); 78332553Sminshall longjmp(toplevel, -1); 78432553Sminshall } 78532553Sminshall 786*45233Sborman /* ARGSUSED */ 787*45233Sborman static SIG_FUNC_RET 788*45233Sborman intr2(sig) 789*45233Sborman int sig; 79032553Sminshall { 79132553Sminshall if (localchars) { 79238689Sborman #ifdef KLUDGELINEMODE 79338689Sborman if (kludgelinemode) 79438689Sborman sendbrk(); 79538689Sborman else 79638689Sborman #endif 79738689Sborman sendabort(); 79832553Sminshall return; 79932553Sminshall } 80032553Sminshall } 80132553Sminshall 802*45233Sborman #ifdef SIGTSTP 803*45233Sborman /* ARGSUSED */ 804*45233Sborman static SIG_FUNC_RET 805*45233Sborman susp(sig) 806*45233Sborman int sig; 80740245Sborman { 80840245Sborman if (localchars) 80940245Sborman sendsusp(); 81040245Sborman } 811*45233Sborman #endif 81240245Sborman 813*45233Sborman #ifdef SIGWINCH 814*45233Sborman /* ARGSUSED */ 815*45233Sborman static SIG_FUNC_RET 816*45233Sborman sendwin(sig) 817*45233Sborman int sig; 81837219Sminshall { 81937219Sminshall if (connected) { 82037219Sminshall sendnaws(); 82137219Sminshall } 82237219Sminshall } 823*45233Sborman #endif 82437219Sminshall 825*45233Sborman #ifdef SIGINFO 826*45233Sborman /* ARGSUSED */ 827*45233Sborman static SIG_FUNC_RET 828*45233Sborman ayt(sig) 829*45233Sborman int sig; 830*45233Sborman { 831*45233Sborman if (connected) 832*45233Sborman sendayt(); 833*45233Sborman else 834*45233Sborman ayt_status(); 835*45233Sborman } 836*45233Sborman #endif 837*45233Sborman 83832553Sminshall 83932553Sminshall void 84032531Sminshall sys_telnet_init() 84132531Sminshall { 842*45233Sborman (void) signal(SIGINT, intr); 843*45233Sborman (void) signal(SIGQUIT, intr2); 844*45233Sborman (void) signal(SIGPIPE, deadpeer); 84538689Sborman #ifdef SIGWINCH 846*45233Sborman (void) signal(SIGWINCH, sendwin); 84738689Sborman #endif 84840245Sborman #ifdef SIGTSTP 849*45233Sborman (void) signal(SIGTSTP, susp); 85040245Sborman #endif 851*45233Sborman #ifdef SIGINFO 852*45233Sborman (void) signal(SIGINFO, ayt); 853*45233Sborman #endif 85432553Sminshall 85538689Sborman setconnmode(0); 85632531Sminshall 85732531Sminshall NetNonblockingIO(net, 1); 85832531Sminshall 85932531Sminshall #if defined(TN3270) 86036242Sminshall if (noasynchnet == 0) { /* DBX can't handle! */ 86132531Sminshall NetSigIO(net, 1); 86232531Sminshall NetSetPgrp(net); 86332531Sminshall } 86432531Sminshall #endif /* defined(TN3270) */ 86532531Sminshall 86632531Sminshall #if defined(SO_OOBINLINE) 86734849Sminshall if (SetSockOpt(net, SOL_SOCKET, SO_OOBINLINE, 1) == -1) { 86834849Sminshall perror("SetSockOpt"); 86934849Sminshall } 87032531Sminshall #endif /* defined(SO_OOBINLINE) */ 87132531Sminshall } 87232531Sminshall 87332531Sminshall /* 87432531Sminshall * Process rings - 87532531Sminshall * 87632531Sminshall * This routine tries to fill up/empty our various rings. 87732531Sminshall * 87832531Sminshall * The parameter specifies whether this is a poll operation, 87932531Sminshall * or a block-until-something-happens operation. 88032531Sminshall * 88132531Sminshall * The return value is 1 if something happened, 0 if not. 88232531Sminshall */ 88332531Sminshall 88432531Sminshall int 88532531Sminshall process_rings(netin, netout, netex, ttyin, ttyout, poll) 88632531Sminshall int poll; /* If 0, then block until something to do */ 88732531Sminshall { 88832531Sminshall register int c; 88932531Sminshall /* One wants to be a bit careful about setting returnValue 89032531Sminshall * to one, since a one implies we did some useful work, 89132531Sminshall * and therefore probably won't be called to block next 89232531Sminshall * time (TN3270 mode only). 89332531Sminshall */ 89432531Sminshall int returnValue = 0; 89532531Sminshall static struct timeval TimeValue = { 0 }; 89632531Sminshall 89732531Sminshall if (netout) { 89832531Sminshall FD_SET(net, &obits); 89932531Sminshall } 90032531Sminshall if (ttyout) { 90132531Sminshall FD_SET(tout, &obits); 90232531Sminshall } 90332531Sminshall #if defined(TN3270) 90432531Sminshall if (ttyin) { 90532531Sminshall FD_SET(tin, &ibits); 90632531Sminshall } 90732531Sminshall #else /* defined(TN3270) */ 90832531Sminshall if (ttyin) { 90932531Sminshall FD_SET(tin, &ibits); 91032531Sminshall } 91132531Sminshall #endif /* defined(TN3270) */ 91232531Sminshall #if defined(TN3270) 91332531Sminshall if (netin) { 91432531Sminshall FD_SET(net, &ibits); 91532531Sminshall } 91632531Sminshall # else /* !defined(TN3270) */ 91732531Sminshall if (netin) { 91832531Sminshall FD_SET(net, &ibits); 91932531Sminshall } 92032531Sminshall # endif /* !defined(TN3270) */ 92132531Sminshall if (netex) { 92232531Sminshall FD_SET(net, &xbits); 92332531Sminshall } 92432531Sminshall if ((c = select(16, &ibits, &obits, &xbits, 92532531Sminshall (poll == 0)? (struct timeval *)0 : &TimeValue)) < 0) { 92632531Sminshall if (c == -1) { 92732531Sminshall /* 92832531Sminshall * we can get EINTR if we are in line mode, 92932531Sminshall * and the user does an escape (TSTP), or 93032531Sminshall * some other signal generator. 93132531Sminshall */ 93232531Sminshall if (errno == EINTR) { 93332531Sminshall return 0; 93432531Sminshall } 93532531Sminshall # if defined(TN3270) 93632531Sminshall /* 93732531Sminshall * we can get EBADF if we were in transparent 93832531Sminshall * mode, and the transcom process died. 93932531Sminshall */ 94032531Sminshall if (errno == EBADF) { 94132531Sminshall /* 94232531Sminshall * zero the bits (even though kernel does it) 94332531Sminshall * to make sure we are selecting on the right 94432531Sminshall * ones. 94532531Sminshall */ 94632531Sminshall FD_ZERO(&ibits); 94732531Sminshall FD_ZERO(&obits); 94832531Sminshall FD_ZERO(&xbits); 94932531Sminshall return 0; 95032531Sminshall } 95132531Sminshall # endif /* defined(TN3270) */ 95232531Sminshall /* I don't like this, does it ever happen? */ 95332531Sminshall printf("sleep(5) from telnet, after select\r\n"); 95432531Sminshall sleep(5); 95532531Sminshall } 95632531Sminshall return 0; 95732531Sminshall } 95832531Sminshall 95932531Sminshall /* 96032531Sminshall * Any urgent data? 96132531Sminshall */ 96232531Sminshall if (FD_ISSET(net, &xbits)) { 96332531Sminshall FD_CLR(net, &xbits); 96432531Sminshall SYNCHing = 1; 96544361Sborman (void) ttyflush(1); /* flush already enqueued data */ 96632531Sminshall } 96732531Sminshall 96832531Sminshall /* 96932531Sminshall * Something to read from the network... 97032531Sminshall */ 97132531Sminshall if (FD_ISSET(net, &ibits)) { 97232531Sminshall int canread; 97332531Sminshall 97432531Sminshall FD_CLR(net, &ibits); 97532531Sminshall canread = ring_empty_consecutive(&netiring); 97632531Sminshall #if !defined(SO_OOBINLINE) 97732531Sminshall /* 97832531Sminshall * In 4.2 (and some early 4.3) systems, the 97932531Sminshall * OOB indication and data handling in the kernel 98032531Sminshall * is such that if two separate TCP Urgent requests 98132531Sminshall * come in, one byte of TCP data will be overlaid. 98232531Sminshall * This is fatal for Telnet, but we try to live 98332531Sminshall * with it. 98432531Sminshall * 98532531Sminshall * In addition, in 4.2 (and...), a special protocol 98632531Sminshall * is needed to pick up the TCP Urgent data in 98732531Sminshall * the correct sequence. 98832531Sminshall * 98932531Sminshall * What we do is: if we think we are in urgent 99032531Sminshall * mode, we look to see if we are "at the mark". 99132531Sminshall * If we are, we do an OOB receive. If we run 99232531Sminshall * this twice, we will do the OOB receive twice, 99332531Sminshall * but the second will fail, since the second 99432531Sminshall * time we were "at the mark", but there wasn't 99532531Sminshall * any data there (the kernel doesn't reset 99632531Sminshall * "at the mark" until we do a normal read). 99732531Sminshall * Once we've read the OOB data, we go ahead 99832531Sminshall * and do normal reads. 99932531Sminshall * 100032531Sminshall * There is also another problem, which is that 100132531Sminshall * since the OOB byte we read doesn't put us 100232531Sminshall * out of OOB state, and since that byte is most 100332531Sminshall * likely the TELNET DM (data mark), we would 100432531Sminshall * stay in the TELNET SYNCH (SYNCHing) state. 100532531Sminshall * So, clocks to the rescue. If we've "just" 100632531Sminshall * received a DM, then we test for the 100732531Sminshall * presence of OOB data when the receive OOB 100832531Sminshall * fails (and AFTER we did the normal mode read 100932531Sminshall * to clear "at the mark"). 101032531Sminshall */ 101132531Sminshall if (SYNCHing) { 101232531Sminshall int atmark; 101339652Sborman static int bogus_oob = 0, first = 1; 101432531Sminshall 101532531Sminshall ioctl(net, SIOCATMARK, (char *)&atmark); 101632531Sminshall if (atmark) { 101732531Sminshall c = recv(net, netiring.supply, canread, MSG_OOB); 101832531Sminshall if ((c == -1) && (errno == EINVAL)) { 101932531Sminshall c = recv(net, netiring.supply, canread, 0); 102032531Sminshall if (clocks.didnetreceive < clocks.gotDM) { 102132531Sminshall SYNCHing = stilloob(net); 102232531Sminshall } 102339652Sborman } else if (first && c > 0) { 102439652Sborman /* 102539652Sborman * Bogosity check. Systems based on 4.2BSD 102639652Sborman * do not return an error if you do a second 102739652Sborman * recv(MSG_OOB). So, we do one. If it 102839652Sborman * succeeds and returns exactly the same 102939652Sborman * data, then assume that we are running 103039652Sborman * on a broken system and set the bogus_oob 103139652Sborman * flag. (If the data was different, then 103239652Sborman * we probably got some valid new data, so 103339652Sborman * increment the count...) 103439652Sborman */ 103539652Sborman int i; 103639652Sborman i = recv(net, netiring.supply + c, canread - c, MSG_OOB); 103739652Sborman if (i == c && 103839652Sborman bcmp(netiring.supply, netiring.supply + c, i) == 0) { 103939652Sborman bogus_oob = 1; 104039652Sborman first = 0; 104139652Sborman } else if (i < 0) { 104239652Sborman bogus_oob = 0; 104339652Sborman first = 0; 104439652Sborman } else 104539652Sborman c += i; 104632531Sminshall } 104739652Sborman if (bogus_oob && c > 0) { 104839652Sborman int i; 104939652Sborman /* 105039652Sborman * Bogosity. We have to do the read 105139652Sborman * to clear the atmark to get out of 105239652Sborman * an infinate loop. 105339652Sborman */ 105439652Sborman i = read(net, netiring.supply + c, canread - c); 105539652Sborman if (i > 0) 105639652Sborman c += i; 105739652Sborman } 105832531Sminshall } else { 105932531Sminshall c = recv(net, netiring.supply, canread, 0); 106032531Sminshall } 106132531Sminshall } else { 106232531Sminshall c = recv(net, netiring.supply, canread, 0); 106332531Sminshall } 106432531Sminshall settimer(didnetreceive); 106532531Sminshall #else /* !defined(SO_OOBINLINE) */ 106632531Sminshall c = recv(net, netiring.supply, canread, 0); 106732531Sminshall #endif /* !defined(SO_OOBINLINE) */ 106832531Sminshall if (c < 0 && errno == EWOULDBLOCK) { 106932531Sminshall c = 0; 107032531Sminshall } else if (c <= 0) { 107132531Sminshall return -1; 107232531Sminshall } 107332531Sminshall if (netdata) { 107432531Sminshall Dump('<', netiring.supply, c); 107532531Sminshall } 107632667Sminshall if (c) 107732667Sminshall ring_supplied(&netiring, c); 107832531Sminshall returnValue = 1; 107932531Sminshall } 108032531Sminshall 108132531Sminshall /* 108232531Sminshall * Something to read from the tty... 108332531Sminshall */ 108432531Sminshall if (FD_ISSET(tin, &ibits)) { 108532531Sminshall FD_CLR(tin, &ibits); 108633286Sminshall c = TerminalRead(ttyiring.supply, ring_empty_consecutive(&ttyiring)); 108732531Sminshall if (c < 0 && errno == EWOULDBLOCK) { 108832531Sminshall c = 0; 108932531Sminshall } else { 109032531Sminshall /* EOF detection for line mode!!!! */ 109133281Sminshall if ((c == 0) && MODE_LOCAL_CHARS(globalmode) && isatty(tin)) { 109232531Sminshall /* must be an EOF... */ 109332531Sminshall *ttyiring.supply = termEofChar; 109432531Sminshall c = 1; 109532531Sminshall } 109632531Sminshall if (c <= 0) { 109732531Sminshall return -1; 109832531Sminshall } 109938208Sminshall if (termdata) { 110038208Sminshall Dump('<', ttyiring.supply, c); 110138208Sminshall } 110232667Sminshall ring_supplied(&ttyiring, c); 110332531Sminshall } 110432531Sminshall returnValue = 1; /* did something useful */ 110532531Sminshall } 110632531Sminshall 110732531Sminshall if (FD_ISSET(net, &obits)) { 110832531Sminshall FD_CLR(net, &obits); 110932531Sminshall returnValue |= netflush(); 111032531Sminshall } 111132531Sminshall if (FD_ISSET(tout, &obits)) { 111232531Sminshall FD_CLR(tout, &obits); 111338689Sborman returnValue |= (ttyflush(SYNCHing|flushout) > 0); 111432531Sminshall } 111532531Sminshall 111632531Sminshall return returnValue; 111732531Sminshall } 1118