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 34114630Sobrien#if 0 3529088Smarkm#ifndef lint 3629181Smarkmstatic const char sccsid[] = "@(#)sys_bsd.c 8.4 (Berkeley) 5/30/95"; 3763248Speter#endif 38114630Sobrien#endif 39114630Sobrien#include <sys/cdefs.h> 40114630Sobrien__FBSDID("$FreeBSD$"); 4129088Smarkm 4229088Smarkm/* 4329088Smarkm * The following routines try to encapsulate what is system dependent 4429088Smarkm * (at least between 4.x and dos) which is used in telnet.c. 4529088Smarkm */ 4629088Smarkm 47103954Smarkm#include <sys/param.h> 4887139Smarkm#include <sys/socket.h> 4929088Smarkm#include <sys/time.h> 50114630Sobrien#include <err.h> 5187139Smarkm#include <errno.h> 5287139Smarkm#include <fcntl.h> 5329088Smarkm#include <signal.h> 54114630Sobrien#include <stdlib.h> 5587139Smarkm#include <unistd.h> 5629088Smarkm#include <arpa/telnet.h> 5729088Smarkm 5829088Smarkm#include "ring.h" 5929088Smarkm#include "fdset.h" 6029088Smarkm#include "defines.h" 6129088Smarkm#include "externs.h" 6229088Smarkm#include "types.h" 6329088Smarkm 6429088Smarkmint 6529088Smarkm tout, /* Output file descriptor */ 6629088Smarkm tin, /* Input file descriptor */ 6729088Smarkm net; 6829088Smarkm 6929088Smarkm#ifndef USE_TERMIO 7029088Smarkmstruct tchars otc = { 0 }, ntc = { 0 }; 7129088Smarkmstruct ltchars oltc = { 0 }, nltc = { 0 }; 7229088Smarkmstruct sgttyb ottyb = { 0 }, nttyb = { 0 }; 7329088Smarkmint olmode = 0; 7429088Smarkm# define cfgetispeed(ptr) (ptr)->sg_ispeed 7529088Smarkm# define cfgetospeed(ptr) (ptr)->sg_ospeed 7629088Smarkm# define old_tc ottyb 7729088Smarkm 7829088Smarkm#else /* USE_TERMIO */ 7987139Smarkmstruct termio old_tc = { 0, 0, 0, 0, {}, 0, 0 }; 8029088Smarkm 8129088Smarkm# ifndef TCSANOW 8229088Smarkm# ifdef TCSETS 8329088Smarkm# define TCSANOW TCSETS 8429088Smarkm# define TCSADRAIN TCSETSW 8529088Smarkm# define tcgetattr(f, t) ioctl(f, TCGETS, (char *)t) 8629088Smarkm# else 8729088Smarkm# ifdef TCSETA 8829088Smarkm# define TCSANOW TCSETA 8929088Smarkm# define TCSADRAIN TCSETAW 9029088Smarkm# define tcgetattr(f, t) ioctl(f, TCGETA, (char *)t) 9129088Smarkm# else 9229088Smarkm# define TCSANOW TIOCSETA 9329088Smarkm# define TCSADRAIN TIOCSETAW 9429088Smarkm# define tcgetattr(f, t) ioctl(f, TIOCGETA, (char *)t) 9529088Smarkm# endif 9629088Smarkm# endif 9729088Smarkm# define tcsetattr(f, a, t) ioctl(f, a, (char *)t) 9829088Smarkm# define cfgetospeed(ptr) ((ptr)->c_cflag&CBAUD) 9929088Smarkm# ifdef CIBAUD 10029088Smarkm# define cfgetispeed(ptr) (((ptr)->c_cflag&CIBAUD) >> IBSHIFT) 10129088Smarkm# else 10229088Smarkm# define cfgetispeed(ptr) cfgetospeed(ptr) 10329088Smarkm# endif 10429088Smarkm# endif /* TCSANOW */ 10529088Smarkm# ifdef sysV88 10629088Smarkm# define TIOCFLUSH TC_PX_DRAIN 10729088Smarkm# endif 10829088Smarkm#endif /* USE_TERMIO */ 10929088Smarkm 11087558Sjkhstatic fd_set *ibitsp, *obitsp, *xbitsp; 11187558Sjkhint fdsn; 11229088Smarkm 11387139Smarkm#ifdef SIGINT 11487139Smarkmstatic SIG_FUNC_RET intr(int); 11587139Smarkm#endif /* SIGINT */ 11687139Smarkm#ifdef SIGQUIT 11787139Smarkmstatic SIG_FUNC_RET intr2(int); 11887139Smarkm#endif /* SIGQUIT */ 11987139Smarkm#ifdef SIGTSTP 12087139Smarkmstatic SIG_FUNC_RET susp(int); 12187139Smarkm#endif /* SIGTSTP */ 12287139Smarkm#ifdef SIGINFO 12387139Smarkmstatic SIG_FUNC_RET ayt(int); 12487139Smarkm#endif 12529088Smarkm 12687139Smarkmvoid 12787139Smarkminit_sys(void) 12829088Smarkm{ 12929088Smarkm tout = fileno(stdout); 13029088Smarkm tin = fileno(stdin); 13129088Smarkm errno = 0; 13229088Smarkm} 13329088Smarkm 13487139Smarkmint 13587139SmarkmTerminalWrite(char *buf, int n) 13629088Smarkm{ 13729088Smarkm return write(tout, buf, n); 13829088Smarkm} 13929088Smarkm 14087139Smarkmint 14187139SmarkmTerminalRead(char *buf, int n) 14229088Smarkm{ 14329088Smarkm return read(tin, buf, n); 14429088Smarkm} 14529088Smarkm 14629088Smarkm/* 14729088Smarkm * 14829088Smarkm */ 14929088Smarkm 15087139Smarkmint 15187139SmarkmTerminalAutoFlush(void) 15229088Smarkm{ 15329088Smarkm#if defined(LNOFLSH) 15429088Smarkm int flush; 15529088Smarkm 15629088Smarkm ioctl(0, TIOCLGET, (char *)&flush); 15729088Smarkm return !(flush&LNOFLSH); /* if LNOFLSH, no autoflush */ 15829088Smarkm#else /* LNOFLSH */ 15929088Smarkm return 1; 16029088Smarkm#endif /* LNOFLSH */ 16129088Smarkm} 16229088Smarkm 16329088Smarkm#ifdef KLUDGELINEMODE 16429088Smarkmextern int kludgelinemode; 16529088Smarkm#endif 16629088Smarkm/* 16729088Smarkm * TerminalSpecialChars() 16829088Smarkm * 16929088Smarkm * Look at an input character to see if it is a special character 17029088Smarkm * and decide what to do. 17129088Smarkm * 17229088Smarkm * Output: 17329088Smarkm * 17429088Smarkm * 0 Don't add this character. 17529088Smarkm * 1 Do add this character 17629088Smarkm */ 17729088Smarkm 17887139Smarkmint 17987139SmarkmTerminalSpecialChars(int c) 18029088Smarkm{ 18129088Smarkm if (c == termIntChar) { 18229088Smarkm intp(); 18329088Smarkm return 0; 18429088Smarkm } else if (c == termQuitChar) { 18529088Smarkm#ifdef KLUDGELINEMODE 18629088Smarkm if (kludgelinemode) 18729088Smarkm sendbrk(); 18829088Smarkm else 18929088Smarkm#endif 19029088Smarkm sendabort(); 19129088Smarkm return 0; 19229088Smarkm } else if (c == termEofChar) { 19329088Smarkm if (my_want_state_is_will(TELOPT_LINEMODE)) { 19429088Smarkm sendeof(); 19529088Smarkm return 0; 19629088Smarkm } 19729088Smarkm return 1; 19829088Smarkm } else if (c == termSuspChar) { 19929088Smarkm sendsusp(); 20029088Smarkm return(0); 20129088Smarkm } else if (c == termFlushChar) { 20229088Smarkm xmitAO(); /* Transmit Abort Output */ 20329088Smarkm return 0; 20429088Smarkm } else if (!MODE_LOCAL_CHARS(globalmode)) { 20529088Smarkm if (c == termKillChar) { 20629088Smarkm xmitEL(); 20729088Smarkm return 0; 20829088Smarkm } else if (c == termEraseChar) { 20929088Smarkm xmitEC(); /* Transmit Erase Character */ 21029088Smarkm return 0; 21129088Smarkm } 21229088Smarkm } 21329088Smarkm return 1; 21429088Smarkm} 21529088Smarkm 21629088Smarkm 21729088Smarkm/* 21829088Smarkm * Flush output to the terminal 21929088Smarkm */ 22029088Smarkm 22187139Smarkmvoid 22287139SmarkmTerminalFlushOutput(void) 22329088Smarkm{ 22429088Smarkm#ifdef TIOCFLUSH 22529088Smarkm (void) ioctl(fileno(stdout), TIOCFLUSH, (char *) 0); 22629088Smarkm#else 22729088Smarkm (void) ioctl(fileno(stdout), TCFLSH, (char *) 0); 22829088Smarkm#endif 22929088Smarkm} 23029088Smarkm 23187139Smarkmvoid 23287139SmarkmTerminalSaveState(void) 23329088Smarkm{ 23429088Smarkm#ifndef USE_TERMIO 23529088Smarkm ioctl(0, TIOCGETP, (char *)&ottyb); 23629088Smarkm ioctl(0, TIOCGETC, (char *)&otc); 23729088Smarkm ioctl(0, TIOCGLTC, (char *)&oltc); 23829088Smarkm ioctl(0, TIOCLGET, (char *)&olmode); 23929088Smarkm 24029088Smarkm ntc = otc; 24129088Smarkm nltc = oltc; 24229088Smarkm nttyb = ottyb; 24329088Smarkm 24429088Smarkm#else /* USE_TERMIO */ 24529088Smarkm tcgetattr(0, &old_tc); 24629088Smarkm 24729088Smarkm new_tc = old_tc; 24829088Smarkm 24929088Smarkm#ifndef VDISCARD 25029088Smarkm termFlushChar = CONTROL('O'); 25129088Smarkm#endif 25229088Smarkm#ifndef VWERASE 25329088Smarkm termWerasChar = CONTROL('W'); 25429088Smarkm#endif 25529088Smarkm#ifndef VREPRINT 25629088Smarkm termRprntChar = CONTROL('R'); 25729088Smarkm#endif 25829088Smarkm#ifndef VLNEXT 25929088Smarkm termLiteralNextChar = CONTROL('V'); 26029088Smarkm#endif 26129088Smarkm#ifndef VSTART 26229088Smarkm termStartChar = CONTROL('Q'); 26329088Smarkm#endif 26429088Smarkm#ifndef VSTOP 26529088Smarkm termStopChar = CONTROL('S'); 26629088Smarkm#endif 26729088Smarkm#ifndef VSTATUS 26829088Smarkm termAytChar = CONTROL('T'); 26929088Smarkm#endif 27029088Smarkm#endif /* USE_TERMIO */ 27129088Smarkm} 27229088Smarkm 27387139Smarkmcc_t * 27487139Smarkmtcval(int func) 27529088Smarkm{ 27629088Smarkm switch(func) { 27729088Smarkm case SLC_IP: return(&termIntChar); 27829088Smarkm case SLC_ABORT: return(&termQuitChar); 27929088Smarkm case SLC_EOF: return(&termEofChar); 28029088Smarkm case SLC_EC: return(&termEraseChar); 28129088Smarkm case SLC_EL: return(&termKillChar); 28229088Smarkm case SLC_XON: return(&termStartChar); 28329088Smarkm case SLC_XOFF: return(&termStopChar); 28429088Smarkm case SLC_FORW1: return(&termForw1Char); 28529088Smarkm#ifdef USE_TERMIO 28629088Smarkm case SLC_FORW2: return(&termForw2Char); 28729088Smarkm# ifdef VDISCARD 28829088Smarkm case SLC_AO: return(&termFlushChar); 28929088Smarkm# endif 29029088Smarkm# ifdef VSUSP 29129088Smarkm case SLC_SUSP: return(&termSuspChar); 29229088Smarkm# endif 29329088Smarkm# ifdef VWERASE 29429088Smarkm case SLC_EW: return(&termWerasChar); 29529088Smarkm# endif 29629088Smarkm# ifdef VREPRINT 29729088Smarkm case SLC_RP: return(&termRprntChar); 29829088Smarkm# endif 29929088Smarkm# ifdef VLNEXT 30029088Smarkm case SLC_LNEXT: return(&termLiteralNextChar); 30129088Smarkm# endif 30229088Smarkm# ifdef VSTATUS 30329088Smarkm case SLC_AYT: return(&termAytChar); 30429088Smarkm# endif 30529088Smarkm#endif 30629088Smarkm 30729088Smarkm case SLC_SYNCH: 30829088Smarkm case SLC_BRK: 30929088Smarkm case SLC_EOR: 31029088Smarkm default: 31129088Smarkm return((cc_t *)0); 31229088Smarkm } 31329088Smarkm} 31429088Smarkm 31587139Smarkmvoid 31687139SmarkmTerminalDefaultChars(void) 31729088Smarkm{ 31829088Smarkm#ifndef USE_TERMIO 31929088Smarkm ntc = otc; 32029088Smarkm nltc = oltc; 32129088Smarkm nttyb.sg_kill = ottyb.sg_kill; 32229088Smarkm nttyb.sg_erase = ottyb.sg_erase; 32329088Smarkm#else /* USE_TERMIO */ 32481965Smarkm memcpy(new_tc.c_cc, old_tc.c_cc, sizeof(old_tc.c_cc)); 32529088Smarkm# ifndef VDISCARD 32629088Smarkm termFlushChar = CONTROL('O'); 32729088Smarkm# endif 32829088Smarkm# ifndef VWERASE 32929088Smarkm termWerasChar = CONTROL('W'); 33029088Smarkm# endif 33129088Smarkm# ifndef VREPRINT 33229088Smarkm termRprntChar = CONTROL('R'); 33329088Smarkm# endif 33429088Smarkm# ifndef VLNEXT 33529088Smarkm termLiteralNextChar = CONTROL('V'); 33629088Smarkm# endif 33729088Smarkm# ifndef VSTART 33829088Smarkm termStartChar = CONTROL('Q'); 33929088Smarkm# endif 34029088Smarkm# ifndef VSTOP 34129088Smarkm termStopChar = CONTROL('S'); 34229088Smarkm# endif 34329088Smarkm# ifndef VSTATUS 34429088Smarkm termAytChar = CONTROL('T'); 34529088Smarkm# endif 34629088Smarkm#endif /* USE_TERMIO */ 34729088Smarkm} 34829088Smarkm 34929088Smarkm/* 35029088Smarkm * TerminalNewMode - set up terminal to a specific mode. 35129088Smarkm * MODE_ECHO: do local terminal echo 35229088Smarkm * MODE_FLOW: do local flow control 35329088Smarkm * MODE_TRAPSIG: do local mapping to TELNET IAC sequences 35429088Smarkm * MODE_EDIT: do local line editing 35529088Smarkm * 35629088Smarkm * Command mode: 35729088Smarkm * MODE_ECHO|MODE_EDIT|MODE_FLOW|MODE_TRAPSIG 35829088Smarkm * local echo 35929088Smarkm * local editing 36029088Smarkm * local xon/xoff 36129088Smarkm * local signal mapping 36229088Smarkm * 36329088Smarkm * Linemode: 36429088Smarkm * local/no editing 36529088Smarkm * Both Linemode and Single Character mode: 36629088Smarkm * local/remote echo 36729088Smarkm * local/no xon/xoff 36829088Smarkm * local/no signal mapping 36929088Smarkm */ 37029088Smarkm 37187139Smarkmvoid 37287139SmarkmTerminalNewMode(int f) 37329088Smarkm{ 37429088Smarkm static int prevmode = 0; 37529088Smarkm#ifndef USE_TERMIO 37629088Smarkm struct tchars tc; 37729088Smarkm struct ltchars ltc; 37829088Smarkm struct sgttyb sb; 37929088Smarkm int lmode; 38029088Smarkm#else /* USE_TERMIO */ 38129088Smarkm struct termio tmp_tc; 38229088Smarkm#endif /* USE_TERMIO */ 38329088Smarkm int onoff; 38429088Smarkm int old; 38529088Smarkm cc_t esc; 38629088Smarkm 38729088Smarkm globalmode = f&~MODE_FORCE; 38829088Smarkm if (prevmode == f) 38929088Smarkm return; 39029088Smarkm 39129088Smarkm /* 39229088Smarkm * Write any outstanding data before switching modes 39329088Smarkm * ttyflush() returns 0 only when there is no more data 39429088Smarkm * left to write out, it returns -1 if it couldn't do 39529088Smarkm * anything at all, otherwise it returns 1 + the number 39629088Smarkm * of characters left to write. 39729088Smarkm#ifndef USE_TERMIO 39829088Smarkm * We would really like ask the kernel to wait for the output 39929088Smarkm * to drain, like we can do with the TCSADRAIN, but we don't have 40029088Smarkm * that option. The only ioctl that waits for the output to 40129088Smarkm * drain, TIOCSETP, also flushes the input queue, which is NOT 40229088Smarkm * what we want (TIOCSETP is like TCSADFLUSH). 40329088Smarkm#endif 40429088Smarkm */ 40529088Smarkm old = ttyflush(SYNCHing|flushout); 40629088Smarkm if (old < 0 || old > 1) { 40729088Smarkm#ifdef USE_TERMIO 40829088Smarkm tcgetattr(tin, &tmp_tc); 40929088Smarkm#endif /* USE_TERMIO */ 41029088Smarkm do { 41129088Smarkm /* 41229088Smarkm * Wait for data to drain, then flush again. 41329088Smarkm */ 41429088Smarkm#ifdef USE_TERMIO 41529088Smarkm tcsetattr(tin, TCSADRAIN, &tmp_tc); 41629088Smarkm#endif /* USE_TERMIO */ 41729088Smarkm old = ttyflush(SYNCHing|flushout); 41829088Smarkm } while (old < 0 || old > 1); 41929088Smarkm } 42029088Smarkm 42129088Smarkm old = prevmode; 42229088Smarkm prevmode = f&~MODE_FORCE; 42329088Smarkm#ifndef USE_TERMIO 42429088Smarkm sb = nttyb; 42529088Smarkm tc = ntc; 42629088Smarkm ltc = nltc; 42729088Smarkm lmode = olmode; 42829088Smarkm#else 42929088Smarkm tmp_tc = new_tc; 43029088Smarkm#endif 43129088Smarkm 43229088Smarkm if (f&MODE_ECHO) { 43329088Smarkm#ifndef USE_TERMIO 43429088Smarkm sb.sg_flags |= ECHO; 43529088Smarkm#else 43629088Smarkm tmp_tc.c_lflag |= ECHO; 43729088Smarkm tmp_tc.c_oflag |= ONLCR; 43829088Smarkm if (crlf) 43929088Smarkm tmp_tc.c_iflag |= ICRNL; 44029088Smarkm#endif 44129088Smarkm } else { 44229088Smarkm#ifndef USE_TERMIO 44329088Smarkm sb.sg_flags &= ~ECHO; 44429088Smarkm#else 44529088Smarkm tmp_tc.c_lflag &= ~ECHO; 44629088Smarkm tmp_tc.c_oflag &= ~ONLCR; 44729088Smarkm#endif 44829088Smarkm } 44929088Smarkm 45029088Smarkm if ((f&MODE_FLOW) == 0) { 45129088Smarkm#ifndef USE_TERMIO 45229088Smarkm tc.t_startc = _POSIX_VDISABLE; 45329088Smarkm tc.t_stopc = _POSIX_VDISABLE; 45429088Smarkm#else 45529088Smarkm tmp_tc.c_iflag &= ~(IXOFF|IXON); /* Leave the IXANY bit alone */ 45629088Smarkm } else { 45729088Smarkm if (restartany < 0) { 45829088Smarkm tmp_tc.c_iflag |= IXOFF|IXON; /* Leave the IXANY bit alone */ 45929088Smarkm } else if (restartany > 0) { 46029088Smarkm tmp_tc.c_iflag |= IXOFF|IXON|IXANY; 46129088Smarkm } else { 46229088Smarkm tmp_tc.c_iflag |= IXOFF|IXON; 46329088Smarkm tmp_tc.c_iflag &= ~IXANY; 46429088Smarkm } 46529088Smarkm#endif 46629088Smarkm } 46729088Smarkm 46829088Smarkm if ((f&MODE_TRAPSIG) == 0) { 46929088Smarkm#ifndef USE_TERMIO 47029088Smarkm tc.t_intrc = _POSIX_VDISABLE; 47129088Smarkm tc.t_quitc = _POSIX_VDISABLE; 47229088Smarkm tc.t_eofc = _POSIX_VDISABLE; 47329088Smarkm ltc.t_suspc = _POSIX_VDISABLE; 47429088Smarkm ltc.t_dsuspc = _POSIX_VDISABLE; 47529088Smarkm#else 47629088Smarkm tmp_tc.c_lflag &= ~ISIG; 47729088Smarkm#endif 47829088Smarkm localchars = 0; 47929088Smarkm } else { 48029088Smarkm#ifdef USE_TERMIO 48129088Smarkm tmp_tc.c_lflag |= ISIG; 48229088Smarkm#endif 48329088Smarkm localchars = 1; 48429088Smarkm } 48529088Smarkm 48629088Smarkm if (f&MODE_EDIT) { 48729088Smarkm#ifndef USE_TERMIO 48829088Smarkm sb.sg_flags &= ~CBREAK; 48929088Smarkm sb.sg_flags |= CRMOD; 49029088Smarkm#else 49129088Smarkm tmp_tc.c_lflag |= ICANON; 49229088Smarkm#endif 49329088Smarkm } else { 49429088Smarkm#ifndef USE_TERMIO 49529088Smarkm sb.sg_flags |= CBREAK; 49629088Smarkm if (f&MODE_ECHO) 49729088Smarkm sb.sg_flags |= CRMOD; 49829088Smarkm else 49929088Smarkm sb.sg_flags &= ~CRMOD; 50029088Smarkm#else 50129088Smarkm tmp_tc.c_lflag &= ~ICANON; 50229088Smarkm tmp_tc.c_iflag &= ~ICRNL; 50329088Smarkm tmp_tc.c_cc[VMIN] = 1; 50429088Smarkm tmp_tc.c_cc[VTIME] = 0; 50529088Smarkm#endif 50629088Smarkm } 50729088Smarkm 50829088Smarkm if ((f&(MODE_EDIT|MODE_TRAPSIG)) == 0) { 50929088Smarkm#ifndef USE_TERMIO 51029088Smarkm ltc.t_lnextc = _POSIX_VDISABLE; 51129088Smarkm#else 51229088Smarkm# ifdef VLNEXT 51329088Smarkm tmp_tc.c_cc[VLNEXT] = (cc_t)(_POSIX_VDISABLE); 51429088Smarkm# endif 51529088Smarkm#endif 51629088Smarkm } 51729088Smarkm 51829088Smarkm if (f&MODE_SOFT_TAB) { 51929088Smarkm#ifndef USE_TERMIO 52029088Smarkm sb.sg_flags |= XTABS; 52129088Smarkm#else 52229088Smarkm# ifdef OXTABS 52329088Smarkm tmp_tc.c_oflag |= OXTABS; 52429088Smarkm# endif 52529088Smarkm# ifdef TABDLY 52629088Smarkm tmp_tc.c_oflag &= ~TABDLY; 52729088Smarkm tmp_tc.c_oflag |= TAB3; 52829088Smarkm# endif 52929088Smarkm#endif 53029088Smarkm } else { 53129088Smarkm#ifndef USE_TERMIO 53229088Smarkm sb.sg_flags &= ~XTABS; 53329088Smarkm#else 53429088Smarkm# ifdef OXTABS 53529088Smarkm tmp_tc.c_oflag &= ~OXTABS; 53629088Smarkm# endif 53729088Smarkm# ifdef TABDLY 53829088Smarkm tmp_tc.c_oflag &= ~TABDLY; 53929088Smarkm# endif 54029088Smarkm#endif 54129088Smarkm } 54229088Smarkm 54329088Smarkm if (f&MODE_LIT_ECHO) { 54429088Smarkm#ifndef USE_TERMIO 54529088Smarkm lmode &= ~LCTLECH; 54629088Smarkm#else 54729088Smarkm# ifdef ECHOCTL 54829088Smarkm tmp_tc.c_lflag &= ~ECHOCTL; 54929088Smarkm# endif 55029088Smarkm#endif 55129088Smarkm } else { 55229088Smarkm#ifndef USE_TERMIO 55329088Smarkm lmode |= LCTLECH; 55429088Smarkm#else 55529088Smarkm# ifdef ECHOCTL 55629088Smarkm tmp_tc.c_lflag |= ECHOCTL; 55729088Smarkm# endif 55829088Smarkm#endif 55929088Smarkm } 56029088Smarkm 56129088Smarkm if (f == -1) { 56229088Smarkm onoff = 0; 56329088Smarkm } else { 56429088Smarkm#ifndef USE_TERMIO 56529088Smarkm if (f & MODE_OUTBIN) 56629088Smarkm lmode |= LLITOUT; 56729088Smarkm else 56829088Smarkm lmode &= ~LLITOUT; 56929088Smarkm 57029088Smarkm if (f & MODE_INBIN) 57129088Smarkm lmode |= LPASS8; 57229088Smarkm else 57329088Smarkm lmode &= ~LPASS8; 57429088Smarkm#else 57529088Smarkm if (f & MODE_INBIN) 57629088Smarkm tmp_tc.c_iflag &= ~ISTRIP; 57729088Smarkm else 57829088Smarkm tmp_tc.c_iflag |= ISTRIP; 57929088Smarkm if (f & MODE_OUTBIN) { 58029088Smarkm tmp_tc.c_cflag &= ~(CSIZE|PARENB); 58129088Smarkm tmp_tc.c_cflag |= CS8; 58229088Smarkm tmp_tc.c_oflag &= ~OPOST; 58329088Smarkm } else { 58429088Smarkm tmp_tc.c_cflag &= ~(CSIZE|PARENB); 58529088Smarkm tmp_tc.c_cflag |= old_tc.c_cflag & (CSIZE|PARENB); 58629088Smarkm tmp_tc.c_oflag |= OPOST; 58729088Smarkm } 58829088Smarkm#endif 58929088Smarkm onoff = 1; 59029088Smarkm } 59129088Smarkm 59229088Smarkm if (f != -1) { 59375236Snsayer#ifdef SIGINT 59475236Snsayer (void) signal(SIGINT, intr); 59575236Snsayer#endif 59675236Snsayer#ifdef SIGQUIT 59781965Smarkm (void) signal(SIGQUIT, intr2); 59875236Snsayer#endif 59929088Smarkm#ifdef SIGTSTP 60029088Smarkm (void) signal(SIGTSTP, susp); 60129088Smarkm#endif /* SIGTSTP */ 60229088Smarkm#ifdef SIGINFO 60329088Smarkm (void) signal(SIGINFO, ayt); 60429088Smarkm#endif 60529088Smarkm#if defined(USE_TERMIO) && defined(NOKERNINFO) 60629088Smarkm tmp_tc.c_lflag |= NOKERNINFO; 60729088Smarkm#endif 60829088Smarkm /* 60929088Smarkm * We don't want to process ^Y here. It's just another 61029088Smarkm * character that we'll pass on to the back end. It has 61129088Smarkm * to process it because it will be processed when the 61229088Smarkm * user attempts to read it, not when we send it. 61329088Smarkm */ 61429088Smarkm#ifndef USE_TERMIO 61529088Smarkm ltc.t_dsuspc = _POSIX_VDISABLE; 61629088Smarkm#else 61729088Smarkm# ifdef VDSUSP 61829088Smarkm tmp_tc.c_cc[VDSUSP] = (cc_t)(_POSIX_VDISABLE); 61929088Smarkm# endif 62029088Smarkm#endif 62129088Smarkm#ifdef USE_TERMIO 62229088Smarkm /* 62329088Smarkm * If the VEOL character is already set, then use VEOL2, 62429088Smarkm * otherwise use VEOL. 62529088Smarkm */ 62629088Smarkm esc = (rlogin != _POSIX_VDISABLE) ? rlogin : escape; 62729088Smarkm if ((tmp_tc.c_cc[VEOL] != esc) 62829088Smarkm# ifdef VEOL2 62929088Smarkm && (tmp_tc.c_cc[VEOL2] != esc) 63029088Smarkm# endif 63129088Smarkm ) { 63229088Smarkm if (tmp_tc.c_cc[VEOL] == (cc_t)(_POSIX_VDISABLE)) 63329088Smarkm tmp_tc.c_cc[VEOL] = esc; 63429088Smarkm# ifdef VEOL2 63529088Smarkm else if (tmp_tc.c_cc[VEOL2] == (cc_t)(_POSIX_VDISABLE)) 63629088Smarkm tmp_tc.c_cc[VEOL2] = esc; 63729088Smarkm# endif 63829088Smarkm } 63929088Smarkm#else 64029088Smarkm if (tc.t_brkc == (cc_t)(_POSIX_VDISABLE)) 64129088Smarkm tc.t_brkc = esc; 64229088Smarkm#endif 64329088Smarkm } else { 64429088Smarkm#ifdef SIGINFO 64587139Smarkm (void) signal(SIGINFO, (void (*)(int))ayt_status); 64629088Smarkm#endif 64775236Snsayer#ifdef SIGINT 64875236Snsayer (void) signal(SIGINT, SIG_DFL); 64975236Snsayer#endif 65075236Snsayer#ifdef SIGQUIT 65175236Snsayer (void) signal(SIGQUIT, SIG_DFL); 65275236Snsayer#endif 65329088Smarkm#ifdef SIGTSTP 65429088Smarkm (void) signal(SIGTSTP, SIG_DFL); 65529088Smarkm# ifndef SOLARIS 65629088Smarkm (void) sigsetmask(sigblock(0) & ~(1<<(SIGTSTP-1))); 65796385Salfred# else /* SOLARIS */ 65829088Smarkm (void) sigrelse(SIGTSTP); 65996385Salfred# endif /* SOLARIS */ 66029088Smarkm#endif /* SIGTSTP */ 66129088Smarkm#ifndef USE_TERMIO 66229088Smarkm ltc = oltc; 66329088Smarkm tc = otc; 66429088Smarkm sb = ottyb; 66529088Smarkm lmode = olmode; 66629088Smarkm#else 66729088Smarkm tmp_tc = old_tc; 66829088Smarkm#endif 66929088Smarkm } 67029088Smarkm#ifndef USE_TERMIO 67129088Smarkm ioctl(tin, TIOCLSET, (char *)&lmode); 67229088Smarkm ioctl(tin, TIOCSLTC, (char *)<c); 67329088Smarkm ioctl(tin, TIOCSETC, (char *)&tc); 67429088Smarkm ioctl(tin, TIOCSETN, (char *)&sb); 67529088Smarkm#else 67629088Smarkm if (tcsetattr(tin, TCSADRAIN, &tmp_tc) < 0) 67729088Smarkm tcsetattr(tin, TCSANOW, &tmp_tc); 67829088Smarkm#endif 67929088Smarkm 68029088Smarkm ioctl(tin, FIONBIO, (char *)&onoff); 68129088Smarkm ioctl(tout, FIONBIO, (char *)&onoff); 68229088Smarkm 68329088Smarkm} 68429088Smarkm 68529088Smarkm/* 68629088Smarkm * Try to guess whether speeds are "encoded" (4.2BSD) or just numeric (4.4BSD). 68729088Smarkm */ 68829088Smarkm#if B4800 != 4800 68929088Smarkm#define DECODE_BAUD 69029088Smarkm#endif 69129088Smarkm 69229088Smarkm#ifdef DECODE_BAUD 69329088Smarkm#ifndef B7200 69429088Smarkm#define B7200 B4800 69529088Smarkm#endif 69629088Smarkm 69729088Smarkm#ifndef B14400 69829088Smarkm#define B14400 B9600 69929088Smarkm#endif 70029088Smarkm 70129088Smarkm#ifndef B19200 70229088Smarkm# define B19200 B14400 70329088Smarkm#endif 70429088Smarkm 70529088Smarkm#ifndef B28800 70629088Smarkm#define B28800 B19200 70729088Smarkm#endif 70829088Smarkm 70929088Smarkm#ifndef B38400 71029088Smarkm# define B38400 B28800 71129088Smarkm#endif 71229088Smarkm 71329088Smarkm#ifndef B57600 71429088Smarkm#define B57600 B38400 71529088Smarkm#endif 71629088Smarkm 71729088Smarkm#ifndef B76800 71829088Smarkm#define B76800 B57600 71929088Smarkm#endif 72029088Smarkm 72129088Smarkm#ifndef B115200 72229088Smarkm#define B115200 B76800 72329088Smarkm#endif 72429088Smarkm 72529088Smarkm#ifndef B230400 72629088Smarkm#define B230400 B115200 72729088Smarkm#endif 72829088Smarkm 72929088Smarkm 73029088Smarkm/* 73129088Smarkm * This code assumes that the values B0, B50, B75... 73229088Smarkm * are in ascending order. They do not have to be 73329088Smarkm * contiguous. 73429088Smarkm */ 73529088Smarkmstruct termspeeds { 73629088Smarkm long speed; 73729088Smarkm long value; 73829088Smarkm} termspeeds[] = { 73929088Smarkm { 0, B0 }, { 50, B50 }, { 75, B75 }, 74029088Smarkm { 110, B110 }, { 134, B134 }, { 150, B150 }, 74129088Smarkm { 200, B200 }, { 300, B300 }, { 600, B600 }, 74229088Smarkm { 1200, B1200 }, { 1800, B1800 }, { 2400, B2400 }, 74329088Smarkm { 4800, B4800 }, { 7200, B7200 }, { 9600, B9600 }, 74429088Smarkm { 14400, B14400 }, { 19200, B19200 }, { 28800, B28800 }, 74529088Smarkm { 38400, B38400 }, { 57600, B57600 }, { 115200, B115200 }, 74629088Smarkm { 230400, B230400 }, { -1, B230400 } 74729088Smarkm}; 74829088Smarkm#endif /* DECODE_BAUD */ 74929088Smarkm 75087139Smarkmvoid 75187139SmarkmTerminalSpeeds(long *ispeed, long *ospeed) 75229088Smarkm{ 75329088Smarkm#ifdef DECODE_BAUD 75487139Smarkm struct termspeeds *tp; 75529088Smarkm#endif /* DECODE_BAUD */ 75687139Smarkm long in, out; 75729088Smarkm 75829088Smarkm out = cfgetospeed(&old_tc); 75929088Smarkm in = cfgetispeed(&old_tc); 76029088Smarkm if (in == 0) 76129088Smarkm in = out; 76229088Smarkm 76329088Smarkm#ifdef DECODE_BAUD 76429088Smarkm tp = termspeeds; 76529088Smarkm while ((tp->speed != -1) && (tp->value < in)) 76629088Smarkm tp++; 76729088Smarkm *ispeed = tp->speed; 76829088Smarkm 76929088Smarkm tp = termspeeds; 77029088Smarkm while ((tp->speed != -1) && (tp->value < out)) 77129088Smarkm tp++; 77229088Smarkm *ospeed = tp->speed; 77329088Smarkm#else /* DECODE_BAUD */ 77429088Smarkm *ispeed = in; 77529088Smarkm *ospeed = out; 77629088Smarkm#endif /* DECODE_BAUD */ 77729088Smarkm} 77829088Smarkm 77987139Smarkmint 78087139SmarkmTerminalWindowSize(long *rows, long *cols) 78129088Smarkm{ 78229088Smarkm#ifdef TIOCGWINSZ 78329088Smarkm struct winsize ws; 78429088Smarkm 78529088Smarkm if (ioctl(fileno(stdin), TIOCGWINSZ, (char *)&ws) >= 0) { 78629088Smarkm *rows = ws.ws_row; 78729088Smarkm *cols = ws.ws_col; 78829088Smarkm return 1; 78929088Smarkm } 79029088Smarkm#endif /* TIOCGWINSZ */ 79129088Smarkm return 0; 79229088Smarkm} 79329088Smarkm 79487139Smarkmint 79587139SmarkmNetClose(int fd) 79629088Smarkm{ 79729088Smarkm return close(fd); 79829088Smarkm} 79929088Smarkm 80087139Smarkmstatic void 80187139SmarkmNetNonblockingIO(int fd, int onoff) 80229088Smarkm{ 80329088Smarkm ioctl(fd, FIONBIO, (char *)&onoff); 80429088Smarkm} 80529088Smarkm 80629088Smarkm 80729088Smarkm/* 80829088Smarkm * Various signal handling routines. 80929088Smarkm */ 81029088Smarkm 81187139Smarkm/* ARGSUSED */ 81287139SmarkmSIG_FUNC_RET 81387139Smarkmintr(int sig __unused) 81429088Smarkm{ 81529088Smarkm if (localchars) { 81629088Smarkm intp(); 81729088Smarkm return; 81829088Smarkm } 81929088Smarkm setcommandmode(); 82029088Smarkm longjmp(toplevel, -1); 82129088Smarkm} 82229088Smarkm 82387139Smarkm/* ARGSUSED */ 82487139SmarkmSIG_FUNC_RET 82587139Smarkmintr2(int sig __unused) 82629088Smarkm{ 82729088Smarkm if (localchars) { 82829088Smarkm#ifdef KLUDGELINEMODE 82929088Smarkm if (kludgelinemode) 83029088Smarkm sendbrk(); 83129088Smarkm else 83229088Smarkm#endif 83329088Smarkm sendabort(); 83429088Smarkm return; 83529088Smarkm } 83629088Smarkm} 83729088Smarkm 83829088Smarkm#ifdef SIGTSTP 83987139Smarkm/* ARGSUSED */ 84087139SmarkmSIG_FUNC_RET 84187139Smarkmsusp(int sig __unused) 84229088Smarkm{ 84329088Smarkm if ((rlogin != _POSIX_VDISABLE) && rlogin_susp()) 84429088Smarkm return; 84529088Smarkm if (localchars) 84629088Smarkm sendsusp(); 84729088Smarkm} 84829088Smarkm#endif 84929088Smarkm 85029088Smarkm#ifdef SIGWINCH 85187139Smarkm/* ARGSUSED */ 85287139Smarkmstatic SIG_FUNC_RET 85387139Smarkmsendwin(int sig __unused) 85429088Smarkm{ 85529088Smarkm if (connected) { 85629088Smarkm sendnaws(); 85729088Smarkm } 85829088Smarkm} 85929088Smarkm#endif 86029088Smarkm 86129088Smarkm#ifdef SIGINFO 86287139Smarkm/* ARGSUSED */ 86387139SmarkmSIG_FUNC_RET 86487139Smarkmayt(int sig __unused) 86529088Smarkm{ 86629088Smarkm if (connected) 86729088Smarkm sendayt(); 86829088Smarkm else 86929088Smarkm ayt_status(); 87029088Smarkm} 87129088Smarkm#endif 87229088Smarkm 87329088Smarkm 87487139Smarkmvoid 87587139Smarkmsys_telnet_init(void) 87629088Smarkm{ 87729088Smarkm (void) signal(SIGINT, intr); 87829088Smarkm (void) signal(SIGQUIT, intr2); 879207449Sjilles (void) signal(SIGPIPE, SIG_IGN); 88029088Smarkm#ifdef SIGWINCH 88129088Smarkm (void) signal(SIGWINCH, sendwin); 88229088Smarkm#endif 88329088Smarkm#ifdef SIGTSTP 88429088Smarkm (void) signal(SIGTSTP, susp); 88529088Smarkm#endif 88629088Smarkm#ifdef SIGINFO 88729088Smarkm (void) signal(SIGINFO, ayt); 88829088Smarkm#endif 88929088Smarkm 89029088Smarkm setconnmode(0); 89129088Smarkm 89229088Smarkm NetNonblockingIO(net, 1); 89329088Smarkm 89429088Smarkm#if defined(SO_OOBINLINE) 89529088Smarkm if (SetSockOpt(net, SOL_SOCKET, SO_OOBINLINE, 1) == -1) { 89629088Smarkm perror("SetSockOpt"); 89729088Smarkm } 89829088Smarkm#endif /* defined(SO_OOBINLINE) */ 89929088Smarkm} 90029088Smarkm 90129088Smarkm/* 90229088Smarkm * Process rings - 90329088Smarkm * 90429088Smarkm * This routine tries to fill up/empty our various rings. 90529088Smarkm * 90629088Smarkm * The parameter specifies whether this is a poll operation, 90729088Smarkm * or a block-until-something-happens operation. 90829088Smarkm * 90929088Smarkm * The return value is 1 if something happened, 0 if not. 91029088Smarkm */ 91129088Smarkm 91287139Smarkmint 91387139Smarkmprocess_rings(int netin, int netout, int netex, int ttyin, int ttyout, int poll) 91429088Smarkm{ 91587139Smarkm int c; 91629088Smarkm int returnValue = 0; 91787139Smarkm static struct timeval TimeValue = { 0, 0 }; 91887558Sjkh int maxfd = -1; 91987558Sjkh int tmp; 92029088Smarkm 92187558Sjkh if ((netout || netin || netex) && net > maxfd) 92287558Sjkh maxfd = net; 92387558Sjkh 92487558Sjkh if (ttyout && tout > maxfd) 92587558Sjkh maxfd = tout; 92687558Sjkh if (ttyin && tin > maxfd) 92787558Sjkh maxfd = tin; 92887558Sjkh tmp = howmany(maxfd+1, NFDBITS) * sizeof(fd_mask); 92987558Sjkh if (tmp > fdsn) { 93087558Sjkh if (ibitsp) 93187558Sjkh free(ibitsp); 93287558Sjkh if (obitsp) 93387558Sjkh free(obitsp); 93487558Sjkh if (xbitsp) 93587558Sjkh free(xbitsp); 93687558Sjkh 93787558Sjkh fdsn = tmp; 93887558Sjkh if ((ibitsp = (fd_set *)malloc(fdsn)) == NULL) 93987558Sjkh err(1, "malloc"); 94087558Sjkh if ((obitsp = (fd_set *)malloc(fdsn)) == NULL) 94187558Sjkh err(1, "malloc"); 94287558Sjkh if ((xbitsp = (fd_set *)malloc(fdsn)) == NULL) 94387558Sjkh err(1, "malloc"); 94487558Sjkh memset(ibitsp, 0, fdsn); 94587558Sjkh memset(obitsp, 0, fdsn); 94687558Sjkh memset(xbitsp, 0, fdsn); 94729088Smarkm } 94887558Sjkh 94987558Sjkh if (netout) 95087558Sjkh FD_SET(net, obitsp); 95187558Sjkh if (ttyout) 95287558Sjkh FD_SET(tout, obitsp); 95387558Sjkh if (ttyin) 95487558Sjkh FD_SET(tin, ibitsp); 95587558Sjkh if (netin) 95687558Sjkh FD_SET(net, ibitsp); 95787558Sjkh if (netex) 95887558Sjkh FD_SET(net, xbitsp); 95987558Sjkh if ((c = select(maxfd + 1, ibitsp, obitsp, xbitsp, 96087558Sjkh (poll == 0)? (struct timeval *)0 : &TimeValue)) < 0) { 96129088Smarkm if (c == -1) { 96229088Smarkm /* 96329088Smarkm * we can get EINTR if we are in line mode, 96429088Smarkm * and the user does an escape (TSTP), or 96529088Smarkm * some other signal generator. 96629088Smarkm */ 96729088Smarkm if (errno == EINTR) { 96829088Smarkm return 0; 96929088Smarkm } 97029088Smarkm /* I don't like this, does it ever happen? */ 97129181Smarkm printf("sleep(5) from telnet, after select: %s\r\n", strerror(errno)); 97229088Smarkm sleep(5); 97329088Smarkm } 97429088Smarkm return 0; 97529088Smarkm } 97629088Smarkm 97729088Smarkm /* 97829088Smarkm * Any urgent data? 97929088Smarkm */ 98087558Sjkh if (FD_ISSET(net, xbitsp)) { 98187558Sjkh FD_CLR(net, xbitsp); 98229088Smarkm SYNCHing = 1; 98329088Smarkm (void) ttyflush(1); /* flush already enqueued data */ 98429088Smarkm } 98529088Smarkm 98629088Smarkm /* 98729088Smarkm * Something to read from the network... 98829088Smarkm */ 98987558Sjkh if (FD_ISSET(net, ibitsp)) { 99029088Smarkm int canread; 99129088Smarkm 99287558Sjkh FD_CLR(net, ibitsp); 99329088Smarkm canread = ring_empty_consecutive(&netiring); 99429088Smarkm#if !defined(SO_OOBINLINE) 99529088Smarkm /* 99629088Smarkm * In 4.2 (and some early 4.3) systems, the 99729088Smarkm * OOB indication and data handling in the kernel 99829088Smarkm * is such that if two separate TCP Urgent requests 99929088Smarkm * come in, one byte of TCP data will be overlaid. 100029088Smarkm * This is fatal for Telnet, but we try to live 100129088Smarkm * with it. 100229088Smarkm * 100329088Smarkm * In addition, in 4.2 (and...), a special protocol 100429088Smarkm * is needed to pick up the TCP Urgent data in 100529088Smarkm * the correct sequence. 100629088Smarkm * 100729088Smarkm * What we do is: if we think we are in urgent 100829088Smarkm * mode, we look to see if we are "at the mark". 100929088Smarkm * If we are, we do an OOB receive. If we run 101029088Smarkm * this twice, we will do the OOB receive twice, 101129088Smarkm * but the second will fail, since the second 101229088Smarkm * time we were "at the mark", but there wasn't 101329088Smarkm * any data there (the kernel doesn't reset 101429088Smarkm * "at the mark" until we do a normal read). 101529088Smarkm * Once we've read the OOB data, we go ahead 101629088Smarkm * and do normal reads. 101729088Smarkm * 101829088Smarkm * There is also another problem, which is that 101929088Smarkm * since the OOB byte we read doesn't put us 102029088Smarkm * out of OOB state, and since that byte is most 102129088Smarkm * likely the TELNET DM (data mark), we would 102229088Smarkm * stay in the TELNET SYNCH (SYNCHing) state. 102329088Smarkm * So, clocks to the rescue. If we've "just" 102429088Smarkm * received a DM, then we test for the 102529088Smarkm * presence of OOB data when the receive OOB 102629088Smarkm * fails (and AFTER we did the normal mode read 102729088Smarkm * to clear "at the mark"). 102829088Smarkm */ 102929088Smarkm if (SYNCHing) { 103029088Smarkm int atmark; 103129088Smarkm static int bogus_oob = 0, first = 1; 103229088Smarkm 103329088Smarkm ioctl(net, SIOCATMARK, (char *)&atmark); 103429088Smarkm if (atmark) { 103529088Smarkm c = recv(net, netiring.supply, canread, MSG_OOB); 103629088Smarkm if ((c == -1) && (errno == EINVAL)) { 103729088Smarkm c = recv(net, netiring.supply, canread, 0); 103829088Smarkm if (clocks.didnetreceive < clocks.gotDM) { 103929088Smarkm SYNCHing = stilloob(net); 104029088Smarkm } 104129088Smarkm } else if (first && c > 0) { 104229088Smarkm /* 104329088Smarkm * Bogosity check. Systems based on 4.2BSD 104429088Smarkm * do not return an error if you do a second 104529088Smarkm * recv(MSG_OOB). So, we do one. If it 104629088Smarkm * succeeds and returns exactly the same 104729088Smarkm * data, then assume that we are running 104829088Smarkm * on a broken system and set the bogus_oob 104929088Smarkm * flag. (If the data was different, then 105029088Smarkm * we probably got some valid new data, so 105129088Smarkm * increment the count...) 105229088Smarkm */ 105329088Smarkm int i; 105429088Smarkm i = recv(net, netiring.supply + c, canread - c, MSG_OOB); 105529088Smarkm if (i == c && 105681965Smarkm memcmp(netiring.supply, netiring.supply + c, i) == 0) { 105729088Smarkm bogus_oob = 1; 105829088Smarkm first = 0; 105929088Smarkm } else if (i < 0) { 106029088Smarkm bogus_oob = 0; 106129088Smarkm first = 0; 106229088Smarkm } else 106329088Smarkm c += i; 106429088Smarkm } 106529088Smarkm if (bogus_oob && c > 0) { 106629088Smarkm int i; 106729088Smarkm /* 106829088Smarkm * Bogosity. We have to do the read 106929088Smarkm * to clear the atmark to get out of 107029088Smarkm * an infinate loop. 107129088Smarkm */ 107229088Smarkm i = read(net, netiring.supply + c, canread - c); 107329088Smarkm if (i > 0) 107429088Smarkm c += i; 107529088Smarkm } 107629088Smarkm } else { 107729088Smarkm c = recv(net, netiring.supply, canread, 0); 107829088Smarkm } 107929088Smarkm } else { 108029088Smarkm c = recv(net, netiring.supply, canread, 0); 108129088Smarkm } 108229088Smarkm settimer(didnetreceive); 108329088Smarkm#else /* !defined(SO_OOBINLINE) */ 108429088Smarkm c = recv(net, (char *)netiring.supply, canread, 0); 108529088Smarkm#endif /* !defined(SO_OOBINLINE) */ 108629088Smarkm if (c < 0 && errno == EWOULDBLOCK) { 108729088Smarkm c = 0; 108829088Smarkm } else if (c <= 0) { 108929088Smarkm return -1; 109029088Smarkm } 109129088Smarkm if (netdata) { 109229088Smarkm Dump('<', netiring.supply, c); 109329088Smarkm } 109429088Smarkm if (c) 109529088Smarkm ring_supplied(&netiring, c); 109629088Smarkm returnValue = 1; 109729088Smarkm } 109829088Smarkm 109929088Smarkm /* 110029088Smarkm * Something to read from the tty... 110129088Smarkm */ 110287558Sjkh if (FD_ISSET(tin, ibitsp)) { 110387558Sjkh FD_CLR(tin, ibitsp); 110429088Smarkm c = TerminalRead(ttyiring.supply, ring_empty_consecutive(&ttyiring)); 110529088Smarkm if (c < 0 && errno == EIO) 110629088Smarkm c = 0; 110729088Smarkm if (c < 0 && errno == EWOULDBLOCK) { 110829088Smarkm c = 0; 110929088Smarkm } else { 111029088Smarkm /* EOF detection for line mode!!!! */ 111129088Smarkm if ((c == 0) && MODE_LOCAL_CHARS(globalmode) && isatty(tin)) { 111229088Smarkm /* must be an EOF... */ 111329088Smarkm *ttyiring.supply = termEofChar; 111429088Smarkm c = 1; 111529088Smarkm } 111629088Smarkm if (c <= 0) { 111729088Smarkm return -1; 111829088Smarkm } 111929088Smarkm if (termdata) { 112029088Smarkm Dump('<', ttyiring.supply, c); 112129088Smarkm } 112229088Smarkm ring_supplied(&ttyiring, c); 112329088Smarkm } 112429088Smarkm returnValue = 1; /* did something useful */ 112529088Smarkm } 112629088Smarkm 112787558Sjkh if (FD_ISSET(net, obitsp)) { 112887558Sjkh FD_CLR(net, obitsp); 112929088Smarkm returnValue |= netflush(); 113029088Smarkm } 113187558Sjkh if (FD_ISSET(tout, obitsp)) { 113287558Sjkh FD_CLR(tout, obitsp); 113329088Smarkm returnValue |= (ttyflush(SYNCHing|flushout) > 0); 113429088Smarkm } 113529088Smarkm 113629088Smarkm return returnValue; 113729088Smarkm} 1138