sys_bsd.c revision 29088
129088Smarkm/* 229088Smarkm * Copyright (c) 1988, 1990, 1993 329088Smarkm * The Regents of the University of California. All rights reserved. 429088Smarkm * 529088Smarkm * Redistribution and use in source and binary forms, with or without 629088Smarkm * modification, are permitted provided that the following conditions 729088Smarkm * are met: 829088Smarkm * 1. Redistributions of source code must retain the above copyright 929088Smarkm * notice, this list of conditions and the following disclaimer. 1029088Smarkm * 2. Redistributions in binary form must reproduce the above copyright 1129088Smarkm * notice, this list of conditions and the following disclaimer in the 1229088Smarkm * documentation and/or other materials provided with the distribution. 1329088Smarkm * 3. All advertising materials mentioning features or use of this software 1429088Smarkm * must display the following acknowledgement: 1529088Smarkm * This product includes software developed by the University of 1629088Smarkm * California, Berkeley and its contributors. 1729088Smarkm * 4. Neither the name of the University nor the names of its contributors 1829088Smarkm * may be used to endorse or promote products derived from this software 1929088Smarkm * without specific prior written permission. 2029088Smarkm * 2129088Smarkm * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2229088Smarkm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2329088Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2429088Smarkm * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2529088Smarkm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2629088Smarkm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2729088Smarkm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2829088Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2929088Smarkm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3029088Smarkm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3129088Smarkm * SUCH DAMAGE. 3229088Smarkm */ 3329088Smarkm 3429088Smarkm#ifndef lint 3529088Smarkmstatic char sccsid[] = "@(#)sys_bsd.c 8.4 (Berkeley) 5/30/95"; 3629088Smarkm#endif /* not lint */ 3729088Smarkm 3829088Smarkm/* 3929088Smarkm * The following routines try to encapsulate what is system dependent 4029088Smarkm * (at least between 4.x and dos) which is used in telnet.c. 4129088Smarkm */ 4229088Smarkm 4329088Smarkm 4429088Smarkm#include <fcntl.h> 4529088Smarkm#include <sys/types.h> 4629088Smarkm#include <sys/time.h> 4729088Smarkm#include <sys/socket.h> 4829088Smarkm#include <signal.h> 4929088Smarkm#include <errno.h> 5029088Smarkm#include <arpa/telnet.h> 5129088Smarkm 5229088Smarkm#include "ring.h" 5329088Smarkm 5429088Smarkm#include "fdset.h" 5529088Smarkm 5629088Smarkm#include "defines.h" 5729088Smarkm#include "externs.h" 5829088Smarkm#include "types.h" 5929088Smarkm 6029088Smarkm#if defined(CRAY) || (defined(USE_TERMIO) && !defined(SYSV_TERMIO)) 6129088Smarkm#define SIG_FUNC_RET void 6229088Smarkm#else 6329088Smarkm#define SIG_FUNC_RET int 6429088Smarkm#endif 6529088Smarkm 6629088Smarkm#ifdef SIGINFO 6729088Smarkmextern SIG_FUNC_RET ayt_status(); 6829088Smarkm#endif 6929088Smarkm 7029088Smarkmint 7129088Smarkm tout, /* Output file descriptor */ 7229088Smarkm tin, /* Input file descriptor */ 7329088Smarkm net; 7429088Smarkm 7529088Smarkm#ifndef USE_TERMIO 7629088Smarkmstruct tchars otc = { 0 }, ntc = { 0 }; 7729088Smarkmstruct ltchars oltc = { 0 }, nltc = { 0 }; 7829088Smarkmstruct sgttyb ottyb = { 0 }, nttyb = { 0 }; 7929088Smarkmint olmode = 0; 8029088Smarkm# define cfgetispeed(ptr) (ptr)->sg_ispeed 8129088Smarkm# define cfgetospeed(ptr) (ptr)->sg_ospeed 8229088Smarkm# define old_tc ottyb 8329088Smarkm 8429088Smarkm#else /* USE_TERMIO */ 8529088Smarkmstruct termio old_tc = { 0 }; 8629088Smarkmextern struct termio new_tc; 8729088Smarkm 8829088Smarkm# ifndef TCSANOW 8929088Smarkm# ifdef TCSETS 9029088Smarkm# define TCSANOW TCSETS 9129088Smarkm# define TCSADRAIN TCSETSW 9229088Smarkm# define tcgetattr(f, t) ioctl(f, TCGETS, (char *)t) 9329088Smarkm# else 9429088Smarkm# ifdef TCSETA 9529088Smarkm# define TCSANOW TCSETA 9629088Smarkm# define TCSADRAIN TCSETAW 9729088Smarkm# define tcgetattr(f, t) ioctl(f, TCGETA, (char *)t) 9829088Smarkm# else 9929088Smarkm# define TCSANOW TIOCSETA 10029088Smarkm# define TCSADRAIN TIOCSETAW 10129088Smarkm# define tcgetattr(f, t) ioctl(f, TIOCGETA, (char *)t) 10229088Smarkm# endif 10329088Smarkm# endif 10429088Smarkm# define tcsetattr(f, a, t) ioctl(f, a, (char *)t) 10529088Smarkm# define cfgetospeed(ptr) ((ptr)->c_cflag&CBAUD) 10629088Smarkm# ifdef CIBAUD 10729088Smarkm# define cfgetispeed(ptr) (((ptr)->c_cflag&CIBAUD) >> IBSHIFT) 10829088Smarkm# else 10929088Smarkm# define cfgetispeed(ptr) cfgetospeed(ptr) 11029088Smarkm# endif 11129088Smarkm# endif /* TCSANOW */ 11229088Smarkm# ifdef sysV88 11329088Smarkm# define TIOCFLUSH TC_PX_DRAIN 11429088Smarkm# endif 11529088Smarkm#endif /* USE_TERMIO */ 11629088Smarkm 11729088Smarkmstatic fd_set ibits, obits, xbits; 11829088Smarkm 11929088Smarkm 12029088Smarkm void 12129088Smarkminit_sys() 12229088Smarkm{ 12329088Smarkm tout = fileno(stdout); 12429088Smarkm tin = fileno(stdin); 12529088Smarkm FD_ZERO(&ibits); 12629088Smarkm FD_ZERO(&obits); 12729088Smarkm FD_ZERO(&xbits); 12829088Smarkm 12929088Smarkm errno = 0; 13029088Smarkm} 13129088Smarkm 13229088Smarkm 13329088Smarkm int 13429088SmarkmTerminalWrite(buf, n) 13529088Smarkm char *buf; 13629088Smarkm int n; 13729088Smarkm{ 13829088Smarkm return write(tout, buf, n); 13929088Smarkm} 14029088Smarkm 14129088Smarkm int 14229088SmarkmTerminalRead(buf, n) 14329088Smarkm unsigned char *buf; 14429088Smarkm int n; 14529088Smarkm{ 14629088Smarkm return read(tin, buf, n); 14729088Smarkm} 14829088Smarkm 14929088Smarkm/* 15029088Smarkm * 15129088Smarkm */ 15229088Smarkm 15329088Smarkm int 15429088SmarkmTerminalAutoFlush() 15529088Smarkm{ 15629088Smarkm#if defined(LNOFLSH) 15729088Smarkm int flush; 15829088Smarkm 15929088Smarkm ioctl(0, TIOCLGET, (char *)&flush); 16029088Smarkm return !(flush&LNOFLSH); /* if LNOFLSH, no autoflush */ 16129088Smarkm#else /* LNOFLSH */ 16229088Smarkm return 1; 16329088Smarkm#endif /* LNOFLSH */ 16429088Smarkm} 16529088Smarkm 16629088Smarkm#ifdef KLUDGELINEMODE 16729088Smarkmextern int kludgelinemode; 16829088Smarkm#endif 16929088Smarkm/* 17029088Smarkm * TerminalSpecialChars() 17129088Smarkm * 17229088Smarkm * Look at an input character to see if it is a special character 17329088Smarkm * and decide what to do. 17429088Smarkm * 17529088Smarkm * Output: 17629088Smarkm * 17729088Smarkm * 0 Don't add this character. 17829088Smarkm * 1 Do add this character 17929088Smarkm */ 18029088Smarkm 18129088Smarkmextern void xmitAO(), xmitEL(), xmitEC(), intp(), sendbrk(); 18229088Smarkm 18329088Smarkm int 18429088SmarkmTerminalSpecialChars(c) 18529088Smarkm int c; 18629088Smarkm{ 18729088Smarkm if (c == termIntChar) { 18829088Smarkm intp(); 18929088Smarkm return 0; 19029088Smarkm } else if (c == termQuitChar) { 19129088Smarkm#ifdef KLUDGELINEMODE 19229088Smarkm if (kludgelinemode) 19329088Smarkm sendbrk(); 19429088Smarkm else 19529088Smarkm#endif 19629088Smarkm sendabort(); 19729088Smarkm return 0; 19829088Smarkm } else if (c == termEofChar) { 19929088Smarkm if (my_want_state_is_will(TELOPT_LINEMODE)) { 20029088Smarkm sendeof(); 20129088Smarkm return 0; 20229088Smarkm } 20329088Smarkm return 1; 20429088Smarkm } else if (c == termSuspChar) { 20529088Smarkm sendsusp(); 20629088Smarkm return(0); 20729088Smarkm } else if (c == termFlushChar) { 20829088Smarkm xmitAO(); /* Transmit Abort Output */ 20929088Smarkm return 0; 21029088Smarkm } else if (!MODE_LOCAL_CHARS(globalmode)) { 21129088Smarkm if (c == termKillChar) { 21229088Smarkm xmitEL(); 21329088Smarkm return 0; 21429088Smarkm } else if (c == termEraseChar) { 21529088Smarkm xmitEC(); /* Transmit Erase Character */ 21629088Smarkm return 0; 21729088Smarkm } 21829088Smarkm } 21929088Smarkm return 1; 22029088Smarkm} 22129088Smarkm 22229088Smarkm 22329088Smarkm/* 22429088Smarkm * Flush output to the terminal 22529088Smarkm */ 22629088Smarkm 22729088Smarkm void 22829088SmarkmTerminalFlushOutput() 22929088Smarkm{ 23029088Smarkm#ifdef TIOCFLUSH 23129088Smarkm (void) ioctl(fileno(stdout), TIOCFLUSH, (char *) 0); 23229088Smarkm#else 23329088Smarkm (void) ioctl(fileno(stdout), TCFLSH, (char *) 0); 23429088Smarkm#endif 23529088Smarkm} 23629088Smarkm 23729088Smarkm void 23829088SmarkmTerminalSaveState() 23929088Smarkm{ 24029088Smarkm#ifndef USE_TERMIO 24129088Smarkm ioctl(0, TIOCGETP, (char *)&ottyb); 24229088Smarkm ioctl(0, TIOCGETC, (char *)&otc); 24329088Smarkm ioctl(0, TIOCGLTC, (char *)&oltc); 24429088Smarkm ioctl(0, TIOCLGET, (char *)&olmode); 24529088Smarkm 24629088Smarkm ntc = otc; 24729088Smarkm nltc = oltc; 24829088Smarkm nttyb = ottyb; 24929088Smarkm 25029088Smarkm#else /* USE_TERMIO */ 25129088Smarkm tcgetattr(0, &old_tc); 25229088Smarkm 25329088Smarkm new_tc = old_tc; 25429088Smarkm 25529088Smarkm#ifndef VDISCARD 25629088Smarkm termFlushChar = CONTROL('O'); 25729088Smarkm#endif 25829088Smarkm#ifndef VWERASE 25929088Smarkm termWerasChar = CONTROL('W'); 26029088Smarkm#endif 26129088Smarkm#ifndef VREPRINT 26229088Smarkm termRprntChar = CONTROL('R'); 26329088Smarkm#endif 26429088Smarkm#ifndef VLNEXT 26529088Smarkm termLiteralNextChar = CONTROL('V'); 26629088Smarkm#endif 26729088Smarkm#ifndef VSTART 26829088Smarkm termStartChar = CONTROL('Q'); 26929088Smarkm#endif 27029088Smarkm#ifndef VSTOP 27129088Smarkm termStopChar = CONTROL('S'); 27229088Smarkm#endif 27329088Smarkm#ifndef VSTATUS 27429088Smarkm termAytChar = CONTROL('T'); 27529088Smarkm#endif 27629088Smarkm#endif /* USE_TERMIO */ 27729088Smarkm} 27829088Smarkm 27929088Smarkm cc_t * 28029088Smarkmtcval(func) 28129088Smarkm register int func; 28229088Smarkm{ 28329088Smarkm switch(func) { 28429088Smarkm case SLC_IP: return(&termIntChar); 28529088Smarkm case SLC_ABORT: return(&termQuitChar); 28629088Smarkm case SLC_EOF: return(&termEofChar); 28729088Smarkm case SLC_EC: return(&termEraseChar); 28829088Smarkm case SLC_EL: return(&termKillChar); 28929088Smarkm case SLC_XON: return(&termStartChar); 29029088Smarkm case SLC_XOFF: return(&termStopChar); 29129088Smarkm case SLC_FORW1: return(&termForw1Char); 29229088Smarkm#ifdef USE_TERMIO 29329088Smarkm case SLC_FORW2: return(&termForw2Char); 29429088Smarkm# ifdef VDISCARD 29529088Smarkm case SLC_AO: return(&termFlushChar); 29629088Smarkm# endif 29729088Smarkm# ifdef VSUSP 29829088Smarkm case SLC_SUSP: return(&termSuspChar); 29929088Smarkm# endif 30029088Smarkm# ifdef VWERASE 30129088Smarkm case SLC_EW: return(&termWerasChar); 30229088Smarkm# endif 30329088Smarkm# ifdef VREPRINT 30429088Smarkm case SLC_RP: return(&termRprntChar); 30529088Smarkm# endif 30629088Smarkm# ifdef VLNEXT 30729088Smarkm case SLC_LNEXT: return(&termLiteralNextChar); 30829088Smarkm# endif 30929088Smarkm# ifdef VSTATUS 31029088Smarkm case SLC_AYT: return(&termAytChar); 31129088Smarkm# endif 31229088Smarkm#endif 31329088Smarkm 31429088Smarkm case SLC_SYNCH: 31529088Smarkm case SLC_BRK: 31629088Smarkm case SLC_EOR: 31729088Smarkm default: 31829088Smarkm return((cc_t *)0); 31929088Smarkm } 32029088Smarkm} 32129088Smarkm 32229088Smarkm void 32329088SmarkmTerminalDefaultChars() 32429088Smarkm{ 32529088Smarkm#ifndef USE_TERMIO 32629088Smarkm ntc = otc; 32729088Smarkm nltc = oltc; 32829088Smarkm nttyb.sg_kill = ottyb.sg_kill; 32929088Smarkm nttyb.sg_erase = ottyb.sg_erase; 33029088Smarkm#else /* USE_TERMIO */ 33129088Smarkm memmove(new_tc.c_cc, old_tc.c_cc, sizeof(old_tc.c_cc)); 33229088Smarkm# ifndef VDISCARD 33329088Smarkm termFlushChar = CONTROL('O'); 33429088Smarkm# endif 33529088Smarkm# ifndef VWERASE 33629088Smarkm termWerasChar = CONTROL('W'); 33729088Smarkm# endif 33829088Smarkm# ifndef VREPRINT 33929088Smarkm termRprntChar = CONTROL('R'); 34029088Smarkm# endif 34129088Smarkm# ifndef VLNEXT 34229088Smarkm termLiteralNextChar = CONTROL('V'); 34329088Smarkm# endif 34429088Smarkm# ifndef VSTART 34529088Smarkm termStartChar = CONTROL('Q'); 34629088Smarkm# endif 34729088Smarkm# ifndef VSTOP 34829088Smarkm termStopChar = CONTROL('S'); 34929088Smarkm# endif 35029088Smarkm# ifndef VSTATUS 35129088Smarkm termAytChar = CONTROL('T'); 35229088Smarkm# endif 35329088Smarkm#endif /* USE_TERMIO */ 35429088Smarkm} 35529088Smarkm 35629088Smarkm#ifdef notdef 35729088Smarkmvoid 35829088SmarkmTerminalRestoreState() 35929088Smarkm{ 36029088Smarkm} 36129088Smarkm#endif 36229088Smarkm 36329088Smarkm/* 36429088Smarkm * TerminalNewMode - set up terminal to a specific mode. 36529088Smarkm * MODE_ECHO: do local terminal echo 36629088Smarkm * MODE_FLOW: do local flow control 36729088Smarkm * MODE_TRAPSIG: do local mapping to TELNET IAC sequences 36829088Smarkm * MODE_EDIT: do local line editing 36929088Smarkm * 37029088Smarkm * Command mode: 37129088Smarkm * MODE_ECHO|MODE_EDIT|MODE_FLOW|MODE_TRAPSIG 37229088Smarkm * local echo 37329088Smarkm * local editing 37429088Smarkm * local xon/xoff 37529088Smarkm * local signal mapping 37629088Smarkm * 37729088Smarkm * Linemode: 37829088Smarkm * local/no editing 37929088Smarkm * Both Linemode and Single Character mode: 38029088Smarkm * local/remote echo 38129088Smarkm * local/no xon/xoff 38229088Smarkm * local/no signal mapping 38329088Smarkm */ 38429088Smarkm 38529088Smarkm 38629088Smarkm void 38729088SmarkmTerminalNewMode(f) 38829088Smarkm register int f; 38929088Smarkm{ 39029088Smarkm static int prevmode = 0; 39129088Smarkm#ifndef USE_TERMIO 39229088Smarkm struct tchars tc; 39329088Smarkm struct ltchars ltc; 39429088Smarkm struct sgttyb sb; 39529088Smarkm int lmode; 39629088Smarkm#else /* USE_TERMIO */ 39729088Smarkm struct termio tmp_tc; 39829088Smarkm#endif /* USE_TERMIO */ 39929088Smarkm int onoff; 40029088Smarkm int old; 40129088Smarkm cc_t esc; 40229088Smarkm 40329088Smarkm globalmode = f&~MODE_FORCE; 40429088Smarkm if (prevmode == f) 40529088Smarkm return; 40629088Smarkm 40729088Smarkm /* 40829088Smarkm * Write any outstanding data before switching modes 40929088Smarkm * ttyflush() returns 0 only when there is no more data 41029088Smarkm * left to write out, it returns -1 if it couldn't do 41129088Smarkm * anything at all, otherwise it returns 1 + the number 41229088Smarkm * of characters left to write. 41329088Smarkm#ifndef USE_TERMIO 41429088Smarkm * We would really like ask the kernel to wait for the output 41529088Smarkm * to drain, like we can do with the TCSADRAIN, but we don't have 41629088Smarkm * that option. The only ioctl that waits for the output to 41729088Smarkm * drain, TIOCSETP, also flushes the input queue, which is NOT 41829088Smarkm * what we want (TIOCSETP is like TCSADFLUSH). 41929088Smarkm#endif 42029088Smarkm */ 42129088Smarkm old = ttyflush(SYNCHing|flushout); 42229088Smarkm if (old < 0 || old > 1) { 42329088Smarkm#ifdef USE_TERMIO 42429088Smarkm tcgetattr(tin, &tmp_tc); 42529088Smarkm#endif /* USE_TERMIO */ 42629088Smarkm do { 42729088Smarkm /* 42829088Smarkm * Wait for data to drain, then flush again. 42929088Smarkm */ 43029088Smarkm#ifdef USE_TERMIO 43129088Smarkm tcsetattr(tin, TCSADRAIN, &tmp_tc); 43229088Smarkm#endif /* USE_TERMIO */ 43329088Smarkm old = ttyflush(SYNCHing|flushout); 43429088Smarkm } while (old < 0 || old > 1); 43529088Smarkm } 43629088Smarkm 43729088Smarkm old = prevmode; 43829088Smarkm prevmode = f&~MODE_FORCE; 43929088Smarkm#ifndef USE_TERMIO 44029088Smarkm sb = nttyb; 44129088Smarkm tc = ntc; 44229088Smarkm ltc = nltc; 44329088Smarkm lmode = olmode; 44429088Smarkm#else 44529088Smarkm tmp_tc = new_tc; 44629088Smarkm#endif 44729088Smarkm 44829088Smarkm if (f&MODE_ECHO) { 44929088Smarkm#ifndef USE_TERMIO 45029088Smarkm sb.sg_flags |= ECHO; 45129088Smarkm#else 45229088Smarkm tmp_tc.c_lflag |= ECHO; 45329088Smarkm tmp_tc.c_oflag |= ONLCR; 45429088Smarkm if (crlf) 45529088Smarkm tmp_tc.c_iflag |= ICRNL; 45629088Smarkm#endif 45729088Smarkm } else { 45829088Smarkm#ifndef USE_TERMIO 45929088Smarkm sb.sg_flags &= ~ECHO; 46029088Smarkm#else 46129088Smarkm tmp_tc.c_lflag &= ~ECHO; 46229088Smarkm tmp_tc.c_oflag &= ~ONLCR; 46329088Smarkm# ifdef notdef 46429088Smarkm if (crlf) 46529088Smarkm tmp_tc.c_iflag &= ~ICRNL; 46629088Smarkm# endif 46729088Smarkm#endif 46829088Smarkm } 46929088Smarkm 47029088Smarkm if ((f&MODE_FLOW) == 0) { 47129088Smarkm#ifndef USE_TERMIO 47229088Smarkm tc.t_startc = _POSIX_VDISABLE; 47329088Smarkm tc.t_stopc = _POSIX_VDISABLE; 47429088Smarkm#else 47529088Smarkm tmp_tc.c_iflag &= ~(IXOFF|IXON); /* Leave the IXANY bit alone */ 47629088Smarkm } else { 47729088Smarkm if (restartany < 0) { 47829088Smarkm tmp_tc.c_iflag |= IXOFF|IXON; /* Leave the IXANY bit alone */ 47929088Smarkm } else if (restartany > 0) { 48029088Smarkm tmp_tc.c_iflag |= IXOFF|IXON|IXANY; 48129088Smarkm } else { 48229088Smarkm tmp_tc.c_iflag |= IXOFF|IXON; 48329088Smarkm tmp_tc.c_iflag &= ~IXANY; 48429088Smarkm } 48529088Smarkm#endif 48629088Smarkm } 48729088Smarkm 48829088Smarkm if ((f&MODE_TRAPSIG) == 0) { 48929088Smarkm#ifndef USE_TERMIO 49029088Smarkm tc.t_intrc = _POSIX_VDISABLE; 49129088Smarkm tc.t_quitc = _POSIX_VDISABLE; 49229088Smarkm tc.t_eofc = _POSIX_VDISABLE; 49329088Smarkm ltc.t_suspc = _POSIX_VDISABLE; 49429088Smarkm ltc.t_dsuspc = _POSIX_VDISABLE; 49529088Smarkm#else 49629088Smarkm tmp_tc.c_lflag &= ~ISIG; 49729088Smarkm#endif 49829088Smarkm localchars = 0; 49929088Smarkm } else { 50029088Smarkm#ifdef USE_TERMIO 50129088Smarkm tmp_tc.c_lflag |= ISIG; 50229088Smarkm#endif 50329088Smarkm localchars = 1; 50429088Smarkm } 50529088Smarkm 50629088Smarkm if (f&MODE_EDIT) { 50729088Smarkm#ifndef USE_TERMIO 50829088Smarkm sb.sg_flags &= ~CBREAK; 50929088Smarkm sb.sg_flags |= CRMOD; 51029088Smarkm#else 51129088Smarkm tmp_tc.c_lflag |= ICANON; 51229088Smarkm#endif 51329088Smarkm } else { 51429088Smarkm#ifndef USE_TERMIO 51529088Smarkm sb.sg_flags |= CBREAK; 51629088Smarkm if (f&MODE_ECHO) 51729088Smarkm sb.sg_flags |= CRMOD; 51829088Smarkm else 51929088Smarkm sb.sg_flags &= ~CRMOD; 52029088Smarkm#else 52129088Smarkm tmp_tc.c_lflag &= ~ICANON; 52229088Smarkm tmp_tc.c_iflag &= ~ICRNL; 52329088Smarkm tmp_tc.c_cc[VMIN] = 1; 52429088Smarkm tmp_tc.c_cc[VTIME] = 0; 52529088Smarkm#endif 52629088Smarkm } 52729088Smarkm 52829088Smarkm if ((f&(MODE_EDIT|MODE_TRAPSIG)) == 0) { 52929088Smarkm#ifndef USE_TERMIO 53029088Smarkm ltc.t_lnextc = _POSIX_VDISABLE; 53129088Smarkm#else 53229088Smarkm# ifdef VLNEXT 53329088Smarkm tmp_tc.c_cc[VLNEXT] = (cc_t)(_POSIX_VDISABLE); 53429088Smarkm# endif 53529088Smarkm#endif 53629088Smarkm } 53729088Smarkm 53829088Smarkm if (f&MODE_SOFT_TAB) { 53929088Smarkm#ifndef USE_TERMIO 54029088Smarkm sb.sg_flags |= XTABS; 54129088Smarkm#else 54229088Smarkm# ifdef OXTABS 54329088Smarkm tmp_tc.c_oflag |= OXTABS; 54429088Smarkm# endif 54529088Smarkm# ifdef TABDLY 54629088Smarkm tmp_tc.c_oflag &= ~TABDLY; 54729088Smarkm tmp_tc.c_oflag |= TAB3; 54829088Smarkm# endif 54929088Smarkm#endif 55029088Smarkm } else { 55129088Smarkm#ifndef USE_TERMIO 55229088Smarkm sb.sg_flags &= ~XTABS; 55329088Smarkm#else 55429088Smarkm# ifdef OXTABS 55529088Smarkm tmp_tc.c_oflag &= ~OXTABS; 55629088Smarkm# endif 55729088Smarkm# ifdef TABDLY 55829088Smarkm tmp_tc.c_oflag &= ~TABDLY; 55929088Smarkm# endif 56029088Smarkm#endif 56129088Smarkm } 56229088Smarkm 56329088Smarkm if (f&MODE_LIT_ECHO) { 56429088Smarkm#ifndef USE_TERMIO 56529088Smarkm lmode &= ~LCTLECH; 56629088Smarkm#else 56729088Smarkm# ifdef ECHOCTL 56829088Smarkm tmp_tc.c_lflag &= ~ECHOCTL; 56929088Smarkm# endif 57029088Smarkm#endif 57129088Smarkm } else { 57229088Smarkm#ifndef USE_TERMIO 57329088Smarkm lmode |= LCTLECH; 57429088Smarkm#else 57529088Smarkm# ifdef ECHOCTL 57629088Smarkm tmp_tc.c_lflag |= ECHOCTL; 57729088Smarkm# endif 57829088Smarkm#endif 57929088Smarkm } 58029088Smarkm 58129088Smarkm if (f == -1) { 58229088Smarkm onoff = 0; 58329088Smarkm } else { 58429088Smarkm#ifndef USE_TERMIO 58529088Smarkm if (f & MODE_OUTBIN) 58629088Smarkm lmode |= LLITOUT; 58729088Smarkm else 58829088Smarkm lmode &= ~LLITOUT; 58929088Smarkm 59029088Smarkm if (f & MODE_INBIN) 59129088Smarkm lmode |= LPASS8; 59229088Smarkm else 59329088Smarkm lmode &= ~LPASS8; 59429088Smarkm#else 59529088Smarkm if (f & MODE_INBIN) 59629088Smarkm tmp_tc.c_iflag &= ~ISTRIP; 59729088Smarkm else 59829088Smarkm tmp_tc.c_iflag |= ISTRIP; 59929088Smarkm if (f & MODE_OUTBIN) { 60029088Smarkm tmp_tc.c_cflag &= ~(CSIZE|PARENB); 60129088Smarkm tmp_tc.c_cflag |= CS8; 60229088Smarkm tmp_tc.c_oflag &= ~OPOST; 60329088Smarkm } else { 60429088Smarkm tmp_tc.c_cflag &= ~(CSIZE|PARENB); 60529088Smarkm tmp_tc.c_cflag |= old_tc.c_cflag & (CSIZE|PARENB); 60629088Smarkm tmp_tc.c_oflag |= OPOST; 60729088Smarkm } 60829088Smarkm#endif 60929088Smarkm onoff = 1; 61029088Smarkm } 61129088Smarkm 61229088Smarkm if (f != -1) { 61329088Smarkm#ifdef SIGTSTP 61429088Smarkm SIG_FUNC_RET susp(); 61529088Smarkm#endif /* SIGTSTP */ 61629088Smarkm#ifdef SIGINFO 61729088Smarkm SIG_FUNC_RET ayt(); 61829088Smarkm#endif 61929088Smarkm 62029088Smarkm#ifdef SIGTSTP 62129088Smarkm (void) signal(SIGTSTP, susp); 62229088Smarkm#endif /* SIGTSTP */ 62329088Smarkm#ifdef SIGINFO 62429088Smarkm (void) signal(SIGINFO, ayt); 62529088Smarkm#endif 62629088Smarkm#if defined(USE_TERMIO) && defined(NOKERNINFO) 62729088Smarkm tmp_tc.c_lflag |= NOKERNINFO; 62829088Smarkm#endif 62929088Smarkm /* 63029088Smarkm * We don't want to process ^Y here. It's just another 63129088Smarkm * character that we'll pass on to the back end. It has 63229088Smarkm * to process it because it will be processed when the 63329088Smarkm * user attempts to read it, not when we send it. 63429088Smarkm */ 63529088Smarkm#ifndef USE_TERMIO 63629088Smarkm ltc.t_dsuspc = _POSIX_VDISABLE; 63729088Smarkm#else 63829088Smarkm# ifdef VDSUSP 63929088Smarkm tmp_tc.c_cc[VDSUSP] = (cc_t)(_POSIX_VDISABLE); 64029088Smarkm# endif 64129088Smarkm#endif 64229088Smarkm#ifdef USE_TERMIO 64329088Smarkm /* 64429088Smarkm * If the VEOL character is already set, then use VEOL2, 64529088Smarkm * otherwise use VEOL. 64629088Smarkm */ 64729088Smarkm esc = (rlogin != _POSIX_VDISABLE) ? rlogin : escape; 64829088Smarkm if ((tmp_tc.c_cc[VEOL] != esc) 64929088Smarkm# ifdef VEOL2 65029088Smarkm && (tmp_tc.c_cc[VEOL2] != esc) 65129088Smarkm# endif 65229088Smarkm ) { 65329088Smarkm if (tmp_tc.c_cc[VEOL] == (cc_t)(_POSIX_VDISABLE)) 65429088Smarkm tmp_tc.c_cc[VEOL] = esc; 65529088Smarkm# ifdef VEOL2 65629088Smarkm else if (tmp_tc.c_cc[VEOL2] == (cc_t)(_POSIX_VDISABLE)) 65729088Smarkm tmp_tc.c_cc[VEOL2] = esc; 65829088Smarkm# endif 65929088Smarkm } 66029088Smarkm#else 66129088Smarkm if (tc.t_brkc == (cc_t)(_POSIX_VDISABLE)) 66229088Smarkm tc.t_brkc = esc; 66329088Smarkm#endif 66429088Smarkm } else { 66529088Smarkm#ifdef SIGINFO 66629088Smarkm SIG_FUNC_RET ayt_status(); 66729088Smarkm 66829088Smarkm (void) signal(SIGINFO, ayt_status); 66929088Smarkm#endif 67029088Smarkm#ifdef SIGTSTP 67129088Smarkm (void) signal(SIGTSTP, SIG_DFL); 67229088Smarkm# ifndef SOLARIS 67329088Smarkm (void) sigsetmask(sigblock(0) & ~(1<<(SIGTSTP-1))); 67429088Smarkm# else SOLARIS 67529088Smarkm (void) sigrelse(SIGTSTP); 67629088Smarkm# endif SOLARIS 67729088Smarkm#endif /* SIGTSTP */ 67829088Smarkm#ifndef USE_TERMIO 67929088Smarkm ltc = oltc; 68029088Smarkm tc = otc; 68129088Smarkm sb = ottyb; 68229088Smarkm lmode = olmode; 68329088Smarkm#else 68429088Smarkm tmp_tc = old_tc; 68529088Smarkm#endif 68629088Smarkm } 68729088Smarkm#ifndef USE_TERMIO 68829088Smarkm ioctl(tin, TIOCLSET, (char *)&lmode); 68929088Smarkm ioctl(tin, TIOCSLTC, (char *)<c); 69029088Smarkm ioctl(tin, TIOCSETC, (char *)&tc); 69129088Smarkm ioctl(tin, TIOCSETN, (char *)&sb); 69229088Smarkm#else 69329088Smarkm if (tcsetattr(tin, TCSADRAIN, &tmp_tc) < 0) 69429088Smarkm tcsetattr(tin, TCSANOW, &tmp_tc); 69529088Smarkm#endif 69629088Smarkm 69729088Smarkm#if (!defined(TN3270)) || ((!defined(NOT43)) || defined(PUTCHAR)) 69829088Smarkm# if !defined(sysV88) 69929088Smarkm ioctl(tin, FIONBIO, (char *)&onoff); 70029088Smarkm ioctl(tout, FIONBIO, (char *)&onoff); 70129088Smarkm# endif 70229088Smarkm#endif /* (!defined(TN3270)) || ((!defined(NOT43)) || defined(PUTCHAR)) */ 70329088Smarkm#if defined(TN3270) 70429088Smarkm if (noasynchtty == 0) { 70529088Smarkm ioctl(tin, FIOASYNC, (char *)&onoff); 70629088Smarkm } 70729088Smarkm#endif /* defined(TN3270) */ 70829088Smarkm 70929088Smarkm} 71029088Smarkm 71129088Smarkm/* 71229088Smarkm * Try to guess whether speeds are "encoded" (4.2BSD) or just numeric (4.4BSD). 71329088Smarkm */ 71429088Smarkm#if B4800 != 4800 71529088Smarkm#define DECODE_BAUD 71629088Smarkm#endif 71729088Smarkm 71829088Smarkm#ifdef DECODE_BAUD 71929088Smarkm#ifndef B7200 72029088Smarkm#define B7200 B4800 72129088Smarkm#endif 72229088Smarkm 72329088Smarkm#ifndef B14400 72429088Smarkm#define B14400 B9600 72529088Smarkm#endif 72629088Smarkm 72729088Smarkm#ifndef B19200 72829088Smarkm# define B19200 B14400 72929088Smarkm#endif 73029088Smarkm 73129088Smarkm#ifndef B28800 73229088Smarkm#define B28800 B19200 73329088Smarkm#endif 73429088Smarkm 73529088Smarkm#ifndef B38400 73629088Smarkm# define B38400 B28800 73729088Smarkm#endif 73829088Smarkm 73929088Smarkm#ifndef B57600 74029088Smarkm#define B57600 B38400 74129088Smarkm#endif 74229088Smarkm 74329088Smarkm#ifndef B76800 74429088Smarkm#define B76800 B57600 74529088Smarkm#endif 74629088Smarkm 74729088Smarkm#ifndef B115200 74829088Smarkm#define B115200 B76800 74929088Smarkm#endif 75029088Smarkm 75129088Smarkm#ifndef B230400 75229088Smarkm#define B230400 B115200 75329088Smarkm#endif 75429088Smarkm 75529088Smarkm 75629088Smarkm/* 75729088Smarkm * This code assumes that the values B0, B50, B75... 75829088Smarkm * are in ascending order. They do not have to be 75929088Smarkm * contiguous. 76029088Smarkm */ 76129088Smarkmstruct termspeeds { 76229088Smarkm long speed; 76329088Smarkm long value; 76429088Smarkm} termspeeds[] = { 76529088Smarkm { 0, B0 }, { 50, B50 }, { 75, B75 }, 76629088Smarkm { 110, B110 }, { 134, B134 }, { 150, B150 }, 76729088Smarkm { 200, B200 }, { 300, B300 }, { 600, B600 }, 76829088Smarkm { 1200, B1200 }, { 1800, B1800 }, { 2400, B2400 }, 76929088Smarkm { 4800, B4800 }, { 7200, B7200 }, { 9600, B9600 }, 77029088Smarkm { 14400, B14400 }, { 19200, B19200 }, { 28800, B28800 }, 77129088Smarkm { 38400, B38400 }, { 57600, B57600 }, { 115200, B115200 }, 77229088Smarkm { 230400, B230400 }, { -1, B230400 } 77329088Smarkm}; 77429088Smarkm#endif /* DECODE_BAUD */ 77529088Smarkm 77629088Smarkm void 77729088SmarkmTerminalSpeeds(ispeed, ospeed) 77829088Smarkm long *ispeed; 77929088Smarkm long *ospeed; 78029088Smarkm{ 78129088Smarkm#ifdef DECODE_BAUD 78229088Smarkm register struct termspeeds *tp; 78329088Smarkm#endif /* DECODE_BAUD */ 78429088Smarkm register long in, out; 78529088Smarkm 78629088Smarkm out = cfgetospeed(&old_tc); 78729088Smarkm in = cfgetispeed(&old_tc); 78829088Smarkm if (in == 0) 78929088Smarkm in = out; 79029088Smarkm 79129088Smarkm#ifdef DECODE_BAUD 79229088Smarkm tp = termspeeds; 79329088Smarkm while ((tp->speed != -1) && (tp->value < in)) 79429088Smarkm tp++; 79529088Smarkm *ispeed = tp->speed; 79629088Smarkm 79729088Smarkm tp = termspeeds; 79829088Smarkm while ((tp->speed != -1) && (tp->value < out)) 79929088Smarkm tp++; 80029088Smarkm *ospeed = tp->speed; 80129088Smarkm#else /* DECODE_BAUD */ 80229088Smarkm *ispeed = in; 80329088Smarkm *ospeed = out; 80429088Smarkm#endif /* DECODE_BAUD */ 80529088Smarkm} 80629088Smarkm 80729088Smarkm int 80829088SmarkmTerminalWindowSize(rows, cols) 80929088Smarkm long *rows, *cols; 81029088Smarkm{ 81129088Smarkm#ifdef TIOCGWINSZ 81229088Smarkm struct winsize ws; 81329088Smarkm 81429088Smarkm if (ioctl(fileno(stdin), TIOCGWINSZ, (char *)&ws) >= 0) { 81529088Smarkm *rows = ws.ws_row; 81629088Smarkm *cols = ws.ws_col; 81729088Smarkm return 1; 81829088Smarkm } 81929088Smarkm#endif /* TIOCGWINSZ */ 82029088Smarkm return 0; 82129088Smarkm} 82229088Smarkm 82329088Smarkm int 82429088SmarkmNetClose(fd) 82529088Smarkm int fd; 82629088Smarkm{ 82729088Smarkm return close(fd); 82829088Smarkm} 82929088Smarkm 83029088Smarkm 83129088Smarkm void 83229088SmarkmNetNonblockingIO(fd, onoff) 83329088Smarkm int fd; 83429088Smarkm int onoff; 83529088Smarkm{ 83629088Smarkm ioctl(fd, FIONBIO, (char *)&onoff); 83729088Smarkm} 83829088Smarkm 83929088Smarkm#if defined(TN3270) 84029088Smarkm void 84129088SmarkmNetSigIO(fd, onoff) 84229088Smarkm int fd; 84329088Smarkm int onoff; 84429088Smarkm{ 84529088Smarkm ioctl(fd, FIOASYNC, (char *)&onoff); /* hear about input */ 84629088Smarkm} 84729088Smarkm 84829088Smarkm void 84929088SmarkmNetSetPgrp(fd) 85029088Smarkm int fd; 85129088Smarkm{ 85229088Smarkm int myPid; 85329088Smarkm 85429088Smarkm myPid = getpid(); 85529088Smarkm fcntl(fd, F_SETOWN, myPid); 85629088Smarkm} 85729088Smarkm#endif /*defined(TN3270)*/ 85829088Smarkm 85929088Smarkm/* 86029088Smarkm * Various signal handling routines. 86129088Smarkm */ 86229088Smarkm 86329088Smarkm /* ARGSUSED */ 86429088Smarkm SIG_FUNC_RET 86529088Smarkmdeadpeer(sig) 86629088Smarkm int sig; 86729088Smarkm{ 86829088Smarkm setcommandmode(); 86929088Smarkm longjmp(peerdied, -1); 87029088Smarkm} 87129088Smarkm 87229088Smarkm /* ARGSUSED */ 87329088Smarkm SIG_FUNC_RET 87429088Smarkmintr(sig) 87529088Smarkm int sig; 87629088Smarkm{ 87729088Smarkm if (localchars) { 87829088Smarkm intp(); 87929088Smarkm return; 88029088Smarkm } 88129088Smarkm setcommandmode(); 88229088Smarkm longjmp(toplevel, -1); 88329088Smarkm} 88429088Smarkm 88529088Smarkm /* ARGSUSED */ 88629088Smarkm SIG_FUNC_RET 88729088Smarkmintr2(sig) 88829088Smarkm int sig; 88929088Smarkm{ 89029088Smarkm if (localchars) { 89129088Smarkm#ifdef KLUDGELINEMODE 89229088Smarkm if (kludgelinemode) 89329088Smarkm sendbrk(); 89429088Smarkm else 89529088Smarkm#endif 89629088Smarkm sendabort(); 89729088Smarkm return; 89829088Smarkm } 89929088Smarkm} 90029088Smarkm 90129088Smarkm#ifdef SIGTSTP 90229088Smarkm /* ARGSUSED */ 90329088Smarkm SIG_FUNC_RET 90429088Smarkmsusp(sig) 90529088Smarkm int sig; 90629088Smarkm{ 90729088Smarkm if ((rlogin != _POSIX_VDISABLE) && rlogin_susp()) 90829088Smarkm return; 90929088Smarkm if (localchars) 91029088Smarkm sendsusp(); 91129088Smarkm} 91229088Smarkm#endif 91329088Smarkm 91429088Smarkm#ifdef SIGWINCH 91529088Smarkm /* ARGSUSED */ 91629088Smarkm SIG_FUNC_RET 91729088Smarkmsendwin(sig) 91829088Smarkm int sig; 91929088Smarkm{ 92029088Smarkm if (connected) { 92129088Smarkm sendnaws(); 92229088Smarkm } 92329088Smarkm} 92429088Smarkm#endif 92529088Smarkm 92629088Smarkm#ifdef SIGINFO 92729088Smarkm /* ARGSUSED */ 92829088Smarkm SIG_FUNC_RET 92929088Smarkmayt(sig) 93029088Smarkm int sig; 93129088Smarkm{ 93229088Smarkm if (connected) 93329088Smarkm sendayt(); 93429088Smarkm else 93529088Smarkm ayt_status(); 93629088Smarkm} 93729088Smarkm#endif 93829088Smarkm 93929088Smarkm 94029088Smarkm void 94129088Smarkmsys_telnet_init() 94229088Smarkm{ 94329088Smarkm (void) signal(SIGINT, intr); 94429088Smarkm (void) signal(SIGQUIT, intr2); 94529088Smarkm (void) signal(SIGPIPE, deadpeer); 94629088Smarkm#ifdef SIGWINCH 94729088Smarkm (void) signal(SIGWINCH, sendwin); 94829088Smarkm#endif 94929088Smarkm#ifdef SIGTSTP 95029088Smarkm (void) signal(SIGTSTP, susp); 95129088Smarkm#endif 95229088Smarkm#ifdef SIGINFO 95329088Smarkm (void) signal(SIGINFO, ayt); 95429088Smarkm#endif 95529088Smarkm 95629088Smarkm setconnmode(0); 95729088Smarkm 95829088Smarkm NetNonblockingIO(net, 1); 95929088Smarkm 96029088Smarkm#if defined(TN3270) 96129088Smarkm if (noasynchnet == 0) { /* DBX can't handle! */ 96229088Smarkm NetSigIO(net, 1); 96329088Smarkm NetSetPgrp(net); 96429088Smarkm } 96529088Smarkm#endif /* defined(TN3270) */ 96629088Smarkm 96729088Smarkm#if defined(SO_OOBINLINE) 96829088Smarkm if (SetSockOpt(net, SOL_SOCKET, SO_OOBINLINE, 1) == -1) { 96929088Smarkm perror("SetSockOpt"); 97029088Smarkm } 97129088Smarkm#endif /* defined(SO_OOBINLINE) */ 97229088Smarkm} 97329088Smarkm 97429088Smarkm/* 97529088Smarkm * Process rings - 97629088Smarkm * 97729088Smarkm * This routine tries to fill up/empty our various rings. 97829088Smarkm * 97929088Smarkm * The parameter specifies whether this is a poll operation, 98029088Smarkm * or a block-until-something-happens operation. 98129088Smarkm * 98229088Smarkm * The return value is 1 if something happened, 0 if not. 98329088Smarkm */ 98429088Smarkm 98529088Smarkm int 98629088Smarkmprocess_rings(netin, netout, netex, ttyin, ttyout, poll) 98729088Smarkm int poll; /* If 0, then block until something to do */ 98829088Smarkm{ 98929088Smarkm register int c; 99029088Smarkm /* One wants to be a bit careful about setting returnValue 99129088Smarkm * to one, since a one implies we did some useful work, 99229088Smarkm * and therefore probably won't be called to block next 99329088Smarkm * time (TN3270 mode only). 99429088Smarkm */ 99529088Smarkm int returnValue = 0; 99629088Smarkm static struct timeval TimeValue = { 0 }; 99729088Smarkm 99829088Smarkm if (netout) { 99929088Smarkm FD_SET(net, &obits); 100029088Smarkm } 100129088Smarkm if (ttyout) { 100229088Smarkm FD_SET(tout, &obits); 100329088Smarkm } 100429088Smarkm#if defined(TN3270) 100529088Smarkm if (ttyin) { 100629088Smarkm FD_SET(tin, &ibits); 100729088Smarkm } 100829088Smarkm#else /* defined(TN3270) */ 100929088Smarkm if (ttyin) { 101029088Smarkm FD_SET(tin, &ibits); 101129088Smarkm } 101229088Smarkm#endif /* defined(TN3270) */ 101329088Smarkm#if defined(TN3270) 101429088Smarkm if (netin) { 101529088Smarkm FD_SET(net, &ibits); 101629088Smarkm } 101729088Smarkm# else /* !defined(TN3270) */ 101829088Smarkm if (netin) { 101929088Smarkm FD_SET(net, &ibits); 102029088Smarkm } 102129088Smarkm# endif /* !defined(TN3270) */ 102229088Smarkm if (netex) { 102329088Smarkm FD_SET(net, &xbits); 102429088Smarkm } 102529088Smarkm if ((c = select(16, &ibits, &obits, &xbits, 102629088Smarkm (poll == 0)? (struct timeval *)0 : &TimeValue)) < 0) { 102729088Smarkm if (c == -1) { 102829088Smarkm /* 102929088Smarkm * we can get EINTR if we are in line mode, 103029088Smarkm * and the user does an escape (TSTP), or 103129088Smarkm * some other signal generator. 103229088Smarkm */ 103329088Smarkm if (errno == EINTR) { 103429088Smarkm return 0; 103529088Smarkm } 103629088Smarkm# if defined(TN3270) 103729088Smarkm /* 103829088Smarkm * we can get EBADF if we were in transparent 103929088Smarkm * mode, and the transcom process died. 104029088Smarkm */ 104129088Smarkm if (errno == EBADF) { 104229088Smarkm /* 104329088Smarkm * zero the bits (even though kernel does it) 104429088Smarkm * to make sure we are selecting on the right 104529088Smarkm * ones. 104629088Smarkm */ 104729088Smarkm FD_ZERO(&ibits); 104829088Smarkm FD_ZERO(&obits); 104929088Smarkm FD_ZERO(&xbits); 105029088Smarkm return 0; 105129088Smarkm } 105229088Smarkm# endif /* defined(TN3270) */ 105329088Smarkm /* I don't like this, does it ever happen? */ 105429088Smarkm printf("sleep(5) from telnet, after select\r\n"); 105529088Smarkm sleep(5); 105629088Smarkm } 105729088Smarkm return 0; 105829088Smarkm } 105929088Smarkm 106029088Smarkm /* 106129088Smarkm * Any urgent data? 106229088Smarkm */ 106329088Smarkm if (FD_ISSET(net, &xbits)) { 106429088Smarkm FD_CLR(net, &xbits); 106529088Smarkm SYNCHing = 1; 106629088Smarkm (void) ttyflush(1); /* flush already enqueued data */ 106729088Smarkm } 106829088Smarkm 106929088Smarkm /* 107029088Smarkm * Something to read from the network... 107129088Smarkm */ 107229088Smarkm if (FD_ISSET(net, &ibits)) { 107329088Smarkm int canread; 107429088Smarkm 107529088Smarkm FD_CLR(net, &ibits); 107629088Smarkm canread = ring_empty_consecutive(&netiring); 107729088Smarkm#if !defined(SO_OOBINLINE) 107829088Smarkm /* 107929088Smarkm * In 4.2 (and some early 4.3) systems, the 108029088Smarkm * OOB indication and data handling in the kernel 108129088Smarkm * is such that if two separate TCP Urgent requests 108229088Smarkm * come in, one byte of TCP data will be overlaid. 108329088Smarkm * This is fatal for Telnet, but we try to live 108429088Smarkm * with it. 108529088Smarkm * 108629088Smarkm * In addition, in 4.2 (and...), a special protocol 108729088Smarkm * is needed to pick up the TCP Urgent data in 108829088Smarkm * the correct sequence. 108929088Smarkm * 109029088Smarkm * What we do is: if we think we are in urgent 109129088Smarkm * mode, we look to see if we are "at the mark". 109229088Smarkm * If we are, we do an OOB receive. If we run 109329088Smarkm * this twice, we will do the OOB receive twice, 109429088Smarkm * but the second will fail, since the second 109529088Smarkm * time we were "at the mark", but there wasn't 109629088Smarkm * any data there (the kernel doesn't reset 109729088Smarkm * "at the mark" until we do a normal read). 109829088Smarkm * Once we've read the OOB data, we go ahead 109929088Smarkm * and do normal reads. 110029088Smarkm * 110129088Smarkm * There is also another problem, which is that 110229088Smarkm * since the OOB byte we read doesn't put us 110329088Smarkm * out of OOB state, and since that byte is most 110429088Smarkm * likely the TELNET DM (data mark), we would 110529088Smarkm * stay in the TELNET SYNCH (SYNCHing) state. 110629088Smarkm * So, clocks to the rescue. If we've "just" 110729088Smarkm * received a DM, then we test for the 110829088Smarkm * presence of OOB data when the receive OOB 110929088Smarkm * fails (and AFTER we did the normal mode read 111029088Smarkm * to clear "at the mark"). 111129088Smarkm */ 111229088Smarkm if (SYNCHing) { 111329088Smarkm int atmark; 111429088Smarkm static int bogus_oob = 0, first = 1; 111529088Smarkm 111629088Smarkm ioctl(net, SIOCATMARK, (char *)&atmark); 111729088Smarkm if (atmark) { 111829088Smarkm c = recv(net, netiring.supply, canread, MSG_OOB); 111929088Smarkm if ((c == -1) && (errno == EINVAL)) { 112029088Smarkm c = recv(net, netiring.supply, canread, 0); 112129088Smarkm if (clocks.didnetreceive < clocks.gotDM) { 112229088Smarkm SYNCHing = stilloob(net); 112329088Smarkm } 112429088Smarkm } else if (first && c > 0) { 112529088Smarkm /* 112629088Smarkm * Bogosity check. Systems based on 4.2BSD 112729088Smarkm * do not return an error if you do a second 112829088Smarkm * recv(MSG_OOB). So, we do one. If it 112929088Smarkm * succeeds and returns exactly the same 113029088Smarkm * data, then assume that we are running 113129088Smarkm * on a broken system and set the bogus_oob 113229088Smarkm * flag. (If the data was different, then 113329088Smarkm * we probably got some valid new data, so 113429088Smarkm * increment the count...) 113529088Smarkm */ 113629088Smarkm int i; 113729088Smarkm i = recv(net, netiring.supply + c, canread - c, MSG_OOB); 113829088Smarkm if (i == c && 113929088Smarkm memcmp(netiring.supply, netiring.supply + c, i) == 0) { 114029088Smarkm bogus_oob = 1; 114129088Smarkm first = 0; 114229088Smarkm } else if (i < 0) { 114329088Smarkm bogus_oob = 0; 114429088Smarkm first = 0; 114529088Smarkm } else 114629088Smarkm c += i; 114729088Smarkm } 114829088Smarkm if (bogus_oob && c > 0) { 114929088Smarkm int i; 115029088Smarkm /* 115129088Smarkm * Bogosity. We have to do the read 115229088Smarkm * to clear the atmark to get out of 115329088Smarkm * an infinate loop. 115429088Smarkm */ 115529088Smarkm i = read(net, netiring.supply + c, canread - c); 115629088Smarkm if (i > 0) 115729088Smarkm c += i; 115829088Smarkm } 115929088Smarkm } else { 116029088Smarkm c = recv(net, netiring.supply, canread, 0); 116129088Smarkm } 116229088Smarkm } else { 116329088Smarkm c = recv(net, netiring.supply, canread, 0); 116429088Smarkm } 116529088Smarkm settimer(didnetreceive); 116629088Smarkm#else /* !defined(SO_OOBINLINE) */ 116729088Smarkm c = recv(net, (char *)netiring.supply, canread, 0); 116829088Smarkm#endif /* !defined(SO_OOBINLINE) */ 116929088Smarkm if (c < 0 && errno == EWOULDBLOCK) { 117029088Smarkm c = 0; 117129088Smarkm } else if (c <= 0) { 117229088Smarkm return -1; 117329088Smarkm } 117429088Smarkm if (netdata) { 117529088Smarkm Dump('<', netiring.supply, c); 117629088Smarkm } 117729088Smarkm if (c) 117829088Smarkm ring_supplied(&netiring, c); 117929088Smarkm returnValue = 1; 118029088Smarkm } 118129088Smarkm 118229088Smarkm /* 118329088Smarkm * Something to read from the tty... 118429088Smarkm */ 118529088Smarkm if (FD_ISSET(tin, &ibits)) { 118629088Smarkm FD_CLR(tin, &ibits); 118729088Smarkm c = TerminalRead(ttyiring.supply, ring_empty_consecutive(&ttyiring)); 118829088Smarkm if (c < 0 && errno == EIO) 118929088Smarkm c = 0; 119029088Smarkm if (c < 0 && errno == EWOULDBLOCK) { 119129088Smarkm c = 0; 119229088Smarkm } else { 119329088Smarkm /* EOF detection for line mode!!!! */ 119429088Smarkm if ((c == 0) && MODE_LOCAL_CHARS(globalmode) && isatty(tin)) { 119529088Smarkm /* must be an EOF... */ 119629088Smarkm *ttyiring.supply = termEofChar; 119729088Smarkm c = 1; 119829088Smarkm } 119929088Smarkm if (c <= 0) { 120029088Smarkm return -1; 120129088Smarkm } 120229088Smarkm if (termdata) { 120329088Smarkm Dump('<', ttyiring.supply, c); 120429088Smarkm } 120529088Smarkm ring_supplied(&ttyiring, c); 120629088Smarkm } 120729088Smarkm returnValue = 1; /* did something useful */ 120829088Smarkm } 120929088Smarkm 121029088Smarkm if (FD_ISSET(net, &obits)) { 121129088Smarkm FD_CLR(net, &obits); 121229088Smarkm returnValue |= netflush(); 121329088Smarkm } 121429088Smarkm if (FD_ISSET(tout, &obits)) { 121529088Smarkm FD_CLR(tout, &obits); 121629088Smarkm returnValue |= (ttyflush(SYNCHing|flushout) > 0); 121729088Smarkm } 121829088Smarkm 121929088Smarkm return returnValue; 122029088Smarkm} 1221