sys_bsd.c
资源名称:socks5.zip [点击查看]
上传用户:sddyfurun
上传日期:2007-01-04
资源大小:525k
文件大小:28k
源码类别:
代理服务器
开发平台:
Unix_Linux
- /* Copyright (c) 1988, 1990, 1993 */
- /* The Regents of the University of California. All rights reserved. */
- /* */
- /* Redistribution and use in source and binary forms, with or without */
- /* modification, are permitted provided that the following conditions */
- /* are met: */
- /* 1. Redistributions of source code must retain the above copyright */
- /* notice, this list of conditions and the following disclaimer. */
- /* 2. Redistributions in binary form must reproduce the above copyright */
- /* notice, this list of conditions and the following disclaimer in the */
- /* documentation and/or other materials provided with the distribution. */
- /* 3. All advertising materials mentioning features or use of this */
- /* software must display the following acknowledgement: */
- /* This product includes software developed by the University of */
- /* California, Berkeley and its contributors. */
- /* 4. Neither the name of the University nor the names of its contributors */
- /* may be used to endorse or promote products derived from this software */
- /* without specific prior written permission. */
- /* */
- /* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND */
- /* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE */
- /* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR */
- /* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE */
- /* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR */
- /* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF */
- /* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS */
- /* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN */
- /* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) */
- /* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF */
- /* THE POSSIBILITY OF SUCH DAMAGE. */
- #ifdef SHOW_SCCSIDS
- static char sccsid[] = "@(#)sys_bsd.c 8.4 (Berkeley) 5/30/95";
- #endif
- /* The following routines try to encapsulate what is system dependent */
- /* (at least between 4.x and dos) which is used in telnet.c. */
- #include "config.h"
- #include <fcntl.h>
- #include <sys/types.h>
- #include <sys/time.h>
- #include <sys/socket.h>
- #ifdef HAVE_SYS_SELECT_H
- #include <sys/select.h>
- #endif
- #include <signal.h>
- #include <errno.h>
- #include <arpa/telnet.h>
- #include "ring.h"
- #include "fdset.h"
- #include "defines.h"
- #include "externs.h"
- #include "types.h"
- #define DONT_NEED_SIGBLOCK
- #define DONT_NEED_SIGUNBLOCK
- #define DONT_NEED_SIGPAUSE
- #define DONT_NEED_SIGPENDING
- #include "sigfix.h"
- extern RETSIGTYPE ayt_status(), ayt(), susp();
- int tout; /* Output file descriptor */
- int tin; /* Input file descriptor */
- int net;
- #ifndef USE_TERMIO
- struct tchars otc = { 0 }, ntc = { 0 };
- struct ltchars oltc = { 0 }, nltc = { 0 };
- struct sgttyb ottyb = { 0 }, nttyb = { 0 };
- int olmode = 0;
- # define cfgetispeed(ptr) (ptr)->sg_ispeed
- # define cfgetospeed(ptr) (ptr)->sg_ospeed
- # define old_tc ottyb
- #else /* USE_TERMIO */
- struct termio old_tc = { 0 };
- extern struct termio new_tc;
- # ifndef TCSANOW
- # ifdef TCSETS
- # define TCSANOW TCSETS
- # define TCSADRAIN TCSETSW
- # define tcgetattr(f, t) ioctl(f, TCGETS, (char *)t)
- # else
- # ifdef TCSETA
- # define TCSANOW TCSETA
- # define TCSADRAIN TCSETAW
- # define tcgetattr(f, t) ioctl(f, TCGETA, (char *)t)
- # else
- # define TCSANOW TIOCSETA
- # define TCSADRAIN TIOCSETAW
- # define tcgetattr(f, t) ioctl(f, TIOCGETA, (char *)t)
- # endif
- # endif
- # define tcsetattr(f, a, t) ioctl(f, a, (char *)t)
- # define cfgetospeed(ptr) ((ptr)->c_cflag&CBAUD)
- # ifdef CIBAUD
- # define cfgetispeed(ptr) (((ptr)->c_cflag&CIBAUD) >> IBSHIFT)
- # else
- # define cfgetispeed(ptr) cfgetospeed(ptr)
- # endif
- # endif /* TCSANOW */
- # ifdef sysV88
- # define TIOCFLUSH TC_PX_DRAIN
- # endif
- #endif /* USE_TERMIO */
- static fd_set ibits, obits, xbits;
- void init_sys() {
- tout = fileno(stdout);
- tin = fileno(stdin);
- FD_ZERO(&ibits);
- FD_ZERO(&obits);
- FD_ZERO(&xbits);
- errno = 0;
- }
- int TerminalWrite(unsigned char *buf, int n) {
- return write(tout, buf, n);
- }
- int TerminalRead(unsigned char *buf, int n) {
- return read(tin, buf, n);
- }
- int TerminalAutoFlush() {
- #ifdef LNOFLSH
- int flush;
- ioctl(0, TIOCLGET, (char *)&flush);
- return !(flush & LNOFLSH); /* if LNOFLSH, no autoflush */
- #else
- return 1;
- #endif
- }
- #ifdef KLUDGELINEMODE
- extern int kludgelinemode;
- #endif
- /* TerminalSpecialChars() */
- /* */
- /* Look at an input character to see if it is a special character */
- /* and decide what to do. */
- /* */
- /* Output: */
- /* * 0 Don't add this character. */
- /* * 1 Do add this character */
- extern void xmitAO(), xmitEL(), xmitEC(), intp(), sendbrk();
- int TerminalSpecialChars(int c) {
- if (c == termIntChar) {
- intp();
- return 0;
- } else if (c == termQuitChar) {
- #ifdef KLUDGELINEMODE
- if (kludgelinemode) sendbrk();
- else
- #endif
- sendabort();
- return 0;
- } else if (c == termEofChar) {
- if (my_want_state_is_will(TELOPT_LINEMODE)) {
- sendeof();
- return 0;
- }
- return 1;
- } else if (c == termSuspChar) {
- sendsusp();
- return(0);
- } else if (c == termFlushChar) {
- xmitAO(); /* Transmit Abort Output */
- return 0;
- } else if (!MODE_LOCAL_CHARS(globalmode)) {
- if (c == termKillChar) {
- xmitEL();
- return 0;
- } else if (c == termEraseChar) {
- xmitEC(); /* Transmit Erase Character */
- return 0;
- }
- }
- return 1;
- }
- /* Flush output to the terminal */
- void TerminalFlushOutput() {
- #ifdef TIOCFLUSH
- ioctl(fileno(stdout), TIOCFLUSH, (char *) 0);
- #else
- ioctl(fileno(stdout), TCFLSH, (char *) 0);
- #endif
- }
- void TerminalSaveState() {
- #ifndef USE_TERMIO
- ioctl(0, TIOCGETP, (char *)&ottyb);
- ioctl(0, TIOCGETC, (char *)&otc);
- ioctl(0, TIOCGLTC, (char *)&oltc);
- ioctl(0, TIOCLGET, (char *)&olmode);
- ntc = otc;
- nltc = oltc;
- nttyb = ottyb;
- #else /* USE_TERMIO */
- tcgetattr(0, &old_tc);
- new_tc = old_tc;
- #ifndef VDISCARD
- termFlushChar = CONTROL('O');
- #endif
- #ifndef VWERASE
- termWerasChar = CONTROL('W');
- #endif
- #ifndef VREPRINT
- termRprntChar = CONTROL('R');
- #endif
- #ifndef VLNEXT
- termLiteralNextChar = CONTROL('V');
- #endif
- #ifndef VSTART
- termStartChar = CONTROL('Q');
- #endif
- #ifndef VSTOP
- termStopChar = CONTROL('S');
- #endif
- #ifndef VSTATUS
- termAytChar = CONTROL('T');
- #endif
- #endif /* USE_TERMIO */
- }
- cc_t *tcval(register int func) {
- switch(func) {
- case SLC_IP: return(&termIntChar);
- case SLC_ABORT: return(&termQuitChar);
- case SLC_EOF: return(&termEofChar);
- case SLC_EC: return(&termEraseChar);
- case SLC_EL: return(&termKillChar);
- case SLC_XON: return(&termStartChar);
- case SLC_XOFF: return(&termStopChar);
- case SLC_FORW1: return(&termForw1Char);
- #ifdef USE_TERMIO
- case SLC_FORW2: return(&termForw2Char);
- # ifdef VDISCARD
- case SLC_AO: return(&termFlushChar);
- # endif
- # ifdef VSUSP
- case SLC_SUSP: return(&termSuspChar);
- # endif
- # ifdef VWERASE
- case SLC_EW: return(&termWerasChar);
- # endif
- # ifdef VREPRINT
- case SLC_RP: return(&termRprntChar);
- # endif
- # ifdef VLNEXT
- case SLC_LNEXT: return(&termLiteralNextChar);
- # endif
- # ifdef VSTATUS
- case SLC_AYT: return(&termAytChar);
- # endif
- #endif
- case SLC_SYNCH:
- case SLC_BRK:
- case SLC_EOR:
- default: return((cc_t *)0);
- }
- }
- void TerminalDefaultChars() {
- #ifndef USE_TERMIO
- ntc = otc;
- nltc = oltc;
- nttyb.sg_kill = ottyb.sg_kill;
- nttyb.sg_erase = ottyb.sg_erase;
- #else /* USE_TERMIO */
- memmove(new_tc.c_cc, old_tc.c_cc, sizeof(old_tc.c_cc));
- # ifndef VDISCARD
- termFlushChar = CONTROL('O');
- # endif
- # ifndef VWERASE
- termWerasChar = CONTROL('W');
- # endif
- # ifndef VREPRINT
- termRprntChar = CONTROL('R');
- # endif
- # ifndef VLNEXT
- termLiteralNextChar = CONTROL('V');
- # endif
- # ifndef VSTART
- termStartChar = CONTROL('Q');
- # endif
- # ifndef VSTOP
- termStopChar = CONTROL('S');
- # endif
- # ifndef VSTATUS
- termAytChar = CONTROL('T');
- # endif
- #endif /* USE_TERMIO */
- }
- #ifdef notdef
- void TerminalRestoreState()
- {
- }
- #endif
- /* TerminalNewMode - set up terminal to a specific mode. */
- /* * MODE_ECHO: do local terminal echo */
- /* * MODE_FLOW: do local flow control */
- /* * MODE_TRAPSIG: do local mapping to TELNET IAC sequences */
- /* * MODE_EDIT: do local line editing */
- /* */
- /* Command mode: */
- /* * MODE_ECHO|MODE_EDIT|MODE_FLOW|MODE_TRAPSIG */
- /* * local echo */
- /* * local editing */
- /* * local xon/xoff */
- /* * local signal mapping */
- /* */
- /* Linemode: */
- /* * local/no editing */
- /* * Both Linemode and Single Character mode: */
- /* * local/remote echo */
- /* * local/no xon/xoff */
- /* * local/no signal mapping */
- void TerminalNewMode(register int f) {
- static int prevmode = 0;
- #ifndef USE_TERMIO
- struct tchars tc;
- struct ltchars ltc;
- struct sgttyb sb;
- int lmode;
- #else /* USE_TERMIO */
- struct termio tmp_tc;
- #endif /* USE_TERMIO */
- int onoff;
- int old;
- cc_t esc;
- globalmode = f & ~MODE_FORCE;
- if (prevmode == f) return;
- /* Write any outstanding data before switching modes ttyflush() returns */
- /* 0 only when there is no more data left to write out, it returns -1 if */
- /* it couldn't do anything at all, otherwise it returns 1 + the number */
- /* of characters left to write. */
- #ifndef USE_TERMIO
- /* We would really like ask the kernel to wait for the output to drain, */
- /* like we can do with the TCSADRAIN, but we don't have that option. */
- /* The only ioctl that waits for the output to drain, TIOCSETP, also */
- /* flushes the input queue, which is NOT what we want (TIOCSETP is like */
- /* TCSADFLUSH). */
- #endif
- old = ttyflush(SYNCHing|flushout);
- if (old < 0 || old > 1) {
- #ifdef USE_TERMIO
- tcgetattr(tin, &tmp_tc);
- #endif
- /* Wait for data to drain, then flush again. */
- do {
- #ifdef USE_TERMIO
- tcsetattr(tin, TCSADRAIN, &tmp_tc);
- #endif
- old = ttyflush(SYNCHing|flushout);
- } while (old < 0 || old > 1);
- }
- old = prevmode;
- prevmode = f&~MODE_FORCE;
- #ifndef USE_TERMIO
- sb = nttyb;
- tc = ntc;
- ltc = nltc;
- lmode = olmode;
- #else
- tmp_tc = new_tc;
- #endif
- if (f&MODE_ECHO) {
- #ifndef USE_TERMIO
- sb.sg_flags |= ECHO;
- #else
- tmp_tc.c_lflag |= ECHO;
- tmp_tc.c_oflag |= ONLCR;
- if (crlf) tmp_tc.c_iflag |= ICRNL;
- #endif
- } else {
- #ifndef USE_TERMIO
- sb.sg_flags &= ~ECHO;
- #else
- tmp_tc.c_lflag &= ~ECHO;
- tmp_tc.c_oflag &= ~ONLCR;
- # ifdef notdef
- if (crlf) tmp_tc.c_iflag &= ~ICRNL;
- # endif
- #endif
- }
- if ((f&MODE_FLOW) == 0) {
- #ifndef USE_TERMIO
- tc.t_startc = _POSIX_VDISABLE;
- tc.t_stopc = _POSIX_VDISABLE;
- #else
- tmp_tc.c_iflag &= ~(IXOFF|IXON); /* Leave the IXANY bit alone */
- } else {
- if (restartany < 0) {
- tmp_tc.c_iflag |= IXOFF|IXON; /* Leave the IXANY bit alone */
- } else if (restartany > 0) {
- tmp_tc.c_iflag |= IXOFF|IXON|IXANY;
- } else {
- tmp_tc.c_iflag |= IXOFF|IXON;
- tmp_tc.c_iflag &= ~IXANY;
- }
- #endif
- }
- if ((f&MODE_TRAPSIG) == 0) {
- #ifndef USE_TERMIO
- tc.t_intrc = _POSIX_VDISABLE;
- tc.t_quitc = _POSIX_VDISABLE;
- tc.t_eofc = _POSIX_VDISABLE;
- ltc.t_suspc = _POSIX_VDISABLE;
- ltc.t_dsuspc = _POSIX_VDISABLE;
- #else
- tmp_tc.c_lflag &= ~ISIG;
- #endif
- localchars = 0;
- } else {
- #ifdef USE_TERMIO
- tmp_tc.c_lflag |= ISIG;
- #endif
- localchars = 1;
- }
- if (f&MODE_EDIT) {
- #ifndef USE_TERMIO
- sb.sg_flags &= ~CBREAK;
- sb.sg_flags |= CRMOD;
- #else
- tmp_tc.c_lflag |= ICANON;
- #endif
- } else {
- #ifndef USE_TERMIO
- sb.sg_flags |= CBREAK;
- if (f&MODE_ECHO) sb.sg_flags |= CRMOD;
- else sb.sg_flags &= ~CRMOD;
- #else
- tmp_tc.c_lflag &= ~ICANON;
- tmp_tc.c_iflag &= ~ICRNL;
- tmp_tc.c_cc[VMIN] = 1;
- tmp_tc.c_cc[VTIME] = 0;
- #endif
- }
- if ((f&(MODE_EDIT|MODE_TRAPSIG)) == 0) {
- #ifndef USE_TERMIO
- ltc.t_lnextc = _POSIX_VDISABLE;
- #else
- # ifdef VLNEXT
- tmp_tc.c_cc[VLNEXT] = (cc_t)(_POSIX_VDISABLE);
- # endif
- #endif
- }
- if (f & MODE_SOFT_TAB) {
- #ifndef USE_TERMIO
- sb.sg_flags |= XTABS;
- #else
- # ifdef OXTABS
- tmp_tc.c_oflag |= OXTABS;
- # endif
- # ifdef TABDLY
- tmp_tc.c_oflag &= ~TABDLY;
- tmp_tc.c_oflag |= TAB3;
- # endif
- #endif
- } else {
- #ifndef USE_TERMIO
- sb.sg_flags &= ~XTABS;
- #else
- # ifdef OXTABS
- tmp_tc.c_oflag &= ~OXTABS;
- # endif
- # ifdef TABDLY
- tmp_tc.c_oflag &= ~TABDLY;
- # endif
- #endif
- }
- #ifndef USE_TERMIO
- if (f & MODE_LIT_ECHO) lmode &= ~LCTLECH;
- else lmode |= LCTLECH;
- #elif defined(ECHOCTL)
- if (f & MODE_LIT_ECHO) tmp_tc.c_lflag &= ~ECHOCTL;
- else tmp_tc.c_lflag |= ECHOCTL;
- #endif
- if (f == -1) {
- onoff = 0;
- } else {
- #ifndef USE_TERMIO
- if (f & MODE_OUTBIN) lmode |= LLITOUT;
- else lmode &= ~LLITOUT;
- if (f & MODE_INBIN) lmode |= LPASS8;
- else lmode &= ~LPASS8;
- #else
- if (f & MODE_INBIN) tmp_tc.c_iflag &= ~ISTRIP;
- else tmp_tc.c_iflag |= ISTRIP;
- if (f & MODE_OUTBIN) {
- tmp_tc.c_cflag &= ~(CSIZE|PARENB);
- tmp_tc.c_cflag |= CS8;
- tmp_tc.c_oflag &= ~OPOST;
- } else {
- tmp_tc.c_cflag &= ~(CSIZE|PARENB);
- tmp_tc.c_cflag |= old_tc.c_cflag & (CSIZE|PARENB);
- tmp_tc.c_oflag |= OPOST;
- }
- #endif
- onoff = 1;
- }
- if (f != -1) {
- #ifdef SIGTSTP
- Signal(SIGTSTP, susp);
- #endif
- #ifdef SIGINFO
- Signal(SIGINFO, ayt);
- #endif
- #if defined(USE_TERMIO) && defined(NOKERNINFO)
- tmp_tc.c_lflag |= NOKERNINFO;
- #endif
- /* We don't want to process ^Y here. It's just another character */
- /* that we'll pass on to the back end. It has to process it because */
- /* it will be processed when the user attempts to read it, not when */
- /* we send it. */
- #ifndef USE_TERMIO
- ltc.t_dsuspc = _POSIX_VDISABLE;
- #else
- # ifdef VDSUSP
- tmp_tc.c_cc[VDSUSP] = (cc_t)(_POSIX_VDISABLE);
- # endif
- #endif
- #ifdef USE_TERMIO
- /* If the VEOL character is already set, then use VEOL2, otherwise */
- /* use VEOL. */
- esc = (rlogin != _POSIX_VDISABLE) ? rlogin : escape;
- if ((tmp_tc.c_cc[VEOL] != esc)
- # ifdef VEOL2
- && (tmp_tc.c_cc[VEOL2] != esc)
- # endif
- ) {
- if (tmp_tc.c_cc[VEOL] == (cc_t)(_POSIX_VDISABLE))
- tmp_tc.c_cc[VEOL] = esc;
- # ifdef VEOL2
- else if (tmp_tc.c_cc[VEOL2] == (cc_t)(_POSIX_VDISABLE))
- tmp_tc.c_cc[VEOL2] = esc;
- # endif
- }
- #else
- if (tc.t_brkc == (cc_t)(_POSIX_VDISABLE))
- tc.t_brkc = esc;
- #endif
- } else {
- #ifdef SIGINFO
- Signal(SIGINFO, ayt_status);
- #endif
- #ifdef SIGTSTP
- Signal(SIGTSTP, SIG_DFL);
- # ifdef HAVE_SIGPROCMASK
- {
- sigset_t tmask;
- sigemptyset(&tmask);
- sigaddset(&tmask, SIGTSTP);
- sigprocmask(SIG_UNBLOCK, &tmask, (sigset_t*)0);
- }
- # else
- sigsetmask(sigblock(0) & ~(1<<(SIGTSTP-1)));
- # endif
- #endif
- #ifndef USE_TERMIO
- ltc = oltc;
- tc = otc;
- sb = ottyb;
- lmode = olmode;
- #else
- tmp_tc = old_tc;
- #endif
- }
- #ifndef USE_TERMIO
- ioctl(tin, TIOCLSET, (char *)&lmode);
- ioctl(tin, TIOCSLTC, (char *)<c);
- ioctl(tin, TIOCSETC, (char *)&tc);
- ioctl(tin, TIOCSETN, (char *)&sb);
- #else
- if (tcsetattr(tin, TCSADRAIN, &tmp_tc) < 0)
- tcsetattr(tin, TCSANOW, &tmp_tc);
- #endif
- #if ((!defined(TN3270)) || ((!defined(NOT43)) || defined(PUTCHAR))) && !defined(sysV88)
- ioctl(tin, FIONBIO, (char *)&onoff);
- ioctl(tout, FIONBIO, (char *)&onoff);
- #endif
- #ifdef TN3270
- if (noasynchtty == 0) {
- ioctl(tin, FIOASYNC, (char *)&onoff);
- }
- #endif
- }
- /*
- * Try to guess whether speeds are "encoded" (4.2BSD) or just numeric (4.4BSD).
- */
- #if B4800 != 4800
- #define DECODE_BAUD
- #endif
- #ifdef DECODE_BAUD
- #ifndef B7200
- #define B7200 B4800
- #endif
- #ifndef B14400
- #define B14400 B9600
- #endif
- #ifndef B19200
- # define B19200 B14400
- #endif
- #ifndef B28800
- #define B28800 B19200
- #endif
- #ifndef B38400
- # define B38400 B28800
- #endif
- #ifndef B57600
- #define B57600 B38400
- #endif
- #ifndef B76800
- #define B76800 B57600
- #endif
- #ifndef B115200
- #define B115200 B76800
- #endif
- #ifndef B230400
- #define B230400 B115200
- #endif
- /*
- * This code assumes that the values B0, B50, B75...
- * are in ascending order. They do not have to be
- * contiguous.
- */
- struct termspeeds {
- long speed;
- long value;
- } termspeeds[] = {
- { 0, B0 }, { 50, B50 }, { 75, B75 },
- { 110, B110 }, { 134, B134 }, { 150, B150 },
- { 200, B200 }, { 300, B300 }, { 600, B600 },
- { 1200, B1200 }, { 1800, B1800 }, { 2400, B2400 },
- { 4800, B4800 }, { 7200, B7200 }, { 9600, B9600 },
- { 14400, B14400 }, { 19200, B19200 }, { 28800, B28800 },
- { 38400, B38400 }, { 57600, B57600 }, { 115200, B115200 },
- { 230400, B230400 }, { -1, B230400 }
- };
- #endif /* DECODE_BAUD */
- void TerminalSpeeds(long *ispeed, long *ospeed) {
- #ifdef DECODE_BAUD
- register struct termspeeds *tp;
- #endif
- register long in, out;
- out = cfgetospeed(&old_tc);
- in = cfgetispeed(&old_tc);
- if (in == 0) in = out;
- #ifdef DECODE_BAUD
- tp = termspeeds;
- while ((tp->speed != -1) && (tp->value < in)) tp++;
- *ispeed = tp->speed;
- tp = termspeeds;
- while ((tp->speed != -1) && (tp->value < out)) tp++;
- *ospeed = tp->speed;
- #else
- *ispeed = in;
- *ospeed = out;
- #endif
- }
- int TerminalWindowSize(long *rows, long *cols) {
- #ifdef TIOCGWINSZ
- struct winsize ws;
- if (ioctl(fileno(stdin), TIOCGWINSZ, (char *)&ws) >= 0) {
- *rows = ws.ws_row;
- *cols = ws.ws_col;
- return 1;
- }
- #endif
- return 0;
- }
- int NetClose(int fd) {
- return close(fd);
- }
- void NetNonblockingIO(int fd, int onoff) {
- ioctl(fd, FIONBIO, (char *)&onoff);
- }
- #ifdef TN3270
- void NetSigIO(int fd, int onoff) {
- /* hear about input */
- ioctl(fd, FIOASYNC, (char *)&onoff);
- }
- void NetSetPgrp(int fd) {
- int myPid;
- myPid = getpid();
- fcntl(fd, F_SETOWN, myPid);
- }
- #endif
- /* Various signal handling routines. */
- RETSIGTYPE deadpeer(int sig) {
- setcommandmode();
- longjmp(peerdied, -1);
- }
- RETSIGTYPE intr(int sig) {
- if (localchars) {
- intp();
- return;
- }
- setcommandmode();
- longjmp(toplevel, -1);
- }
- RETSIGTYPE intr2(int sig) {
- if (localchars) {
- #ifdef KLUDGELINEMODE
- if (kludgelinemode) sendbrk();
- else
- #endif
- sendabort();
- return;
- }
- }
- #ifdef SIGTSTP
- RETSIGTYPE susp(int sig) {
- if ((rlogin != _POSIX_VDISABLE) && rlogin_susp()) return;
- if (localchars) sendsusp();
- }
- #endif
- #ifdef SIGWINCH
- RETSIGTYPE sendwin(int sig) {
- if (connected) sendnaws();
- }
- #endif
- #ifdef SIGINFO
- RETSIGTYPE ayt(int sig) {
- if (connected) sendayt();
- else ayt_status();
- }
- #endif
- void sys_telnet_init() {
- Signal(SIGINT, intr);
- Signal(SIGQUIT, intr2);
- Signal(SIGPIPE, deadpeer);
- #ifdef SIGWINCH
- Signal(SIGWINCH, sendwin);
- #endif
- #ifdef SIGTSTP
- Signal(SIGTSTP, susp);
- #endif
- #ifdef SIGINFO
- Signal(SIGINFO, ayt);
- #endif
- setconnmode(0);
- NetNonblockingIO(net, 1);
- #ifdef TN3270
- if (noasynchnet == 0) { /* DBX can't handle! */
- NetSigIO(net, 1);
- NetSetPgrp(net);
- }
- #endif
- #ifdef SO_OOBINLINE
- if (SetSockOpt(net, SOL_SOCKET, SO_OOBINLINE, 1) == -1) {
- perror("SetSockOpt");
- }
- #endif
- }
- /* Process rings - */
- /* */
- /* This routine tries to fill up/empty our various rings. */
- /* */
- /* The parameter specifies whether this is a poll operation, or a */
- /* block-until-something-happens operation. */
- /* */
- /* The return value is 1 if something happened, 0 if not. */
- int process_rings(int netin, int netout, int netex, int ttyin, int ttyout, int poll) {
- static struct timeval TimeValue = { 0 };
- register int c;
- /* One wants to be a bit careful about setting returnValue to one, since */
- /* a one implies we did some useful work, and therefore probably won't */
- /* be called to block next time (TN3270 mode only). */
- int returnValue = 0;
- if (netout) FD_SET(net, &obits);
- if (ttyout) FD_SET(tout, &obits);
- if (netin) FD_SET(net, &ibits);
- if (ttyin) FD_SET(tin, &ibits);
- if (netex) FD_SET(net, &xbits);
- if ((c = select(16, &ibits, &obits, &xbits, (poll == 0)?NULL:&TimeValue)) < 0) {
- if (c == -1) {
- /* We can get EINTR if we are in line mode, and the user does an */
- /* escape (TSTP), or some other signal generator. */
- if (errno == EINTR) return 0;
- #ifdef TN3270
- /* We can get EBADF if we were in transparent mode, and the */
- /* transcom process died. */
- if (errno == EBADF) {
- /* Zero the bits (even though kernel does it) to make sure */
- /* we are selecting on the right ones. */
- FD_ZERO(&ibits);
- FD_ZERO(&obits);
- FD_ZERO(&xbits);
- return 0;
- }
- #endif
- /* I don't like this, does it ever happen? */
- printf("sleep(5) from telnet, after selectrn");
- sleep(5);
- }
- return 0;
- }
- /* Any urgent data? */
- if (FD_ISSET(net, &xbits)) {
- FD_CLR(net, &xbits);
- SYNCHing = 1;
- ttyflush(1); /* flush already enqueued data */
- }
- /* Something to read from the network... */
- if (FD_ISSET(net, &ibits)) {
- int canread;
- FD_CLR(net, &ibits);
- canread = ring_empty_consecutive(&netiring);
- #ifndef SO_OOBINLINE
- /* In 4.2 (and some early 4.3) systems, the OOB indication and data */
- /* handling in the kernel is such that if two separate TCP Urgent */
- /* requests come in, one byte of TCP data will be overlaid. This is */
- /* fatal for Telnet, but we try to live with it. */
- /* */
- /* In addition, in 4.2 (and...), a special protocol is needed to */
- /* pick up the TCP Urgent data in the correct sequence. */
- /* */
- /* What we do is: if we think we are in urgent mode, we look to see */
- /* if we are "at the mark". If we are, we do an OOB receive. If we */
- /* run this twice, we will do the OOB receive twice, but the second */
- /* will fail, since the second time we were "at the mark", but there */
- /* wasn't any data there (the kernel doesn't reset "at the mark" */
- /* until we do a normal read). Once we've read the OOB data, we go */
- /* ahead and do normal reads. */
- /* */
- /* There is also another problem, which is that since the OOB byte */
- /* we read doesn't put us out of OOB state, and since that byte is */
- /* most likely the TELNET DM (data mark), we would stay in the */
- /* TELNET SYNCH (SYNCHing) state. So, clocks to the rescue. If */
- /* we've "just" received a DM, then we test for the presence of OOB */
- /* data when the receive OOB fails (and AFTER we did the normal mode */
- /* read to clear "at the mark"). */
- if (SYNCHing) {
- static int bogus_oob = 0, first = 1;
- int atmark;
- ioctl(net, SIOCATMARK, (char *)&atmark);
- if (atmark) {
- c = recv(net, netiring.supply, canread, MSG_OOB);
- if ((c == -1) && (errno == EINVAL)) {
- c = recv(net, netiring.supply, canread, 0);
- if (clocks.didnetreceive < clocks.gotDM) {
- SYNCHing = stilloob(net);
- }
- } else if (first && c > 0) {
- /* Bogosity check. Systems based on 4.2BSD do not */
- /* return an error if you do a second recv(MSG_OOB). */
- /* So, we do one. If it succeeds and returns exactly */
- /* the same data, then assume that we are running on a */
- /* broken system and set the bogus_oob flag. (If the */
- /* data was different, then we probably got some valid */
- /* new data, so increment the count...) */
- int i = recv(net, netiring.supply+c, canread-c, MSG_OOB);
- if (i == c && memcmp(netiring.supply, netiring.supply + c, i) == 0) {
- bogus_oob = 1;
- first = 0;
- } else if (i < 0) {
- bogus_oob = 0;
- first = 0;
- } else {
- c += i;
- }
- }
- if (bogus_oob && c > 0) {
- int i = read(net, netiring.supply+c, canread-c);
- /* Bogosity. We have to do the read to clear the atmark */
- /* to get out of an infinate loop. */
- if (i > 0) c += i;
- }
- } else {
- c = recv(net, netiring.supply, canread, 0);
- }
- } else {
- c = recv(net, netiring.supply, canread, 0);
- }
- settimer(didnetreceive);
- #else
- c = recv(net, (char *)netiring.supply, canread, 0);
- #endif
- if (c < 0 && errno == EWOULDBLOCK) {
- c = 0;
- } else if (c <= 0) {
- return -1;
- }
- if (netdata) {
- Dump('<', netiring.supply, c);
- }
- if (c) {
- ring_supplied(&netiring, c);
- }
- returnValue = 1;
- }
- /*
- * Something to read from the tty...
- */
- if (FD_ISSET(tin, &ibits)) {
- FD_CLR(tin, &ibits);
- c = TerminalRead(ttyiring.supply, ring_empty_consecutive(&ttyiring));
- if (c < 0 && errno == EIO) {
- c = 0;
- }
- if (c < 0 && errno == EWOULDBLOCK) {
- c = 0;
- } else {
- /* EOF detection for line mode!!!! */
- if ((c == 0) && MODE_LOCAL_CHARS(globalmode) && isatty(tin)) {
- /* must be an EOF... */
- *ttyiring.supply = termEofChar;
- c = 1;
- }
- if (c <= 0) {
- return -1;
- }
- if (termdata) {
- Dump('<', ttyiring.supply, c);
- }
- ring_supplied(&ttyiring, c);
- }
- returnValue = 1; /* did something useful */
- }
- if (FD_ISSET(net, &obits)) {
- FD_CLR(net, &obits);
- returnValue |= netflush();
- }
- if (FD_ISSET(tout, &obits)) {
- FD_CLR(tout, &obits);
- returnValue |= (ttyflush(SYNCHing|flushout) > 0);
- }
- return returnValue;
- }