📄 sys_bsd.c
字号:
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 RETSIGTYPE susp();#endif /* SIGTSTP */#ifdef SIGINFO RETSIGTYPE ayt();#endif#ifdef SIGTSTP (void) signal(SIGTSTP, susp);#endif /* SIGTSTP */#ifdef SIGINFO (void) 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 RETSIGTYPE ayt_status(); (void) signal(SIGINFO, ayt_status);#endif#ifdef SIGTSTP (void) signal(SIGTSTP, SIG_DFL);# ifdef HAVE_SIGACTION { sigset_t sigs; sigemptyset(&sigs); sigaddset(&sigs, SIGTSTP); sigprocmask(SIG_UNBLOCK, &sigs, 0); }# else (void) sigsetmask(sigblock(0) & ~(1<<(SIGTSTP-1)));# endif /* HAVE_SIGACTION */#endif /* SIGTSTP */#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))# if !defined(sysV88) ioctl(tin, FIONBIO, (char *)&onoff); ioctl(tout, FIONBIO, (char *)&onoff);# endif#endif /* (!defined(TN3270)) || ((!defined(NOT43)) || defined(PUTCHAR)) */#if defined(TN3270) if (noasynchtty == 0) { ioctl(tin, FIOASYNC, (char *)&onoff); }#endif /* defined(TN3270) */}/* * 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 */voidTerminalSpeeds(long *ispeed, long *ospeed){#ifdef DECODE_BAUD register struct termspeeds *tp;#endif /* DECODE_BAUD */ 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 /* DECODE_BAUD */ *ispeed = in; *ospeed = out;#endif /* DECODE_BAUD */}intTerminalWindowSize(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 /* TIOCGWINSZ */ return 0;}intNetClose(int fd){ return close(fd);}voidNetNonblockingIO(int fd, int onoff){ ioctl(fd, FIONBIO, (char *)&onoff);}#if defined(TN3270)voidNetSigIO(int fd, int onoff){ ioctl(fd, FIOASYNC, (char *)&onoff); /* hear about input */}voidNetSetPgrp(int fd){ int myPid; myPid = getpid(); fcntl(fd, F_SETOWN, myPid);}#endif /*defined(TN3270)*//* * Various signal handling routines. */ /* ARGSUSED */RETSIGTYPEdeadpeer(int sig){ setcommandmode(); longjmp(peerdied, -1);} /* ARGSUSED */RETSIGTYPEintr(int sig){ if (localchars) { intp(); return; } setcommandmode(); longjmp(toplevel, -1);} /* ARGSUSED */RETSIGTYPEintr2(int sig){ if (localchars) {#ifdef KLUDGELINEMODE if (kludgelinemode) sendbrk(); else#endif sendabort(); return; }}#ifdef SIGTSTP /* ARGSUSED */RETSIGTYPEsusp(int sig){ if ((rlogin != _POSIX_VDISABLE) && rlogin_susp()) return; if (localchars) sendsusp();}#endif#ifdef SIGWINCH /* ARGSUSED */RETSIGTYPEsendwin(int sig){ if (connected) { sendnaws(); }}#endif#ifdef SIGINFO /* ARGSUSED */RETSIGTYPEayt(int sig){ if (connected) sendayt(); else ayt_status();}#endifvoidsys_telnet_init(){ (void) signal(SIGINT, intr); (void) signal(SIGQUIT, intr2); (void) signal(SIGPIPE, deadpeer);#ifdef SIGWINCH (void) signal(SIGWINCH, sendwin);#endif#ifdef SIGTSTP (void) signal(SIGTSTP, susp);#endif#ifdef SIGINFO (void) signal(SIGINFO, ayt);#endif setconnmode(0); NetNonblockingIO(net, 1);#if defined(TN3270) if (noasynchnet == 0) { /* DBX can't handle! */ NetSigIO(net, 1); NetSetPgrp(net); }#endif /* defined(TN3270) */#if defined(SO_OOBINLINE) if (SetSockOpt(net, SOL_SOCKET, SO_OOBINLINE, 1) == -1) { perror("SetSockOpt"); }#endif /* defined(SO_OOBINLINE) */}/* * 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. *//* poll; If 0, then block until something to do */intprocess_rings(int netin, int netout, int netex, int ttyin, int ttyout, int poll){ 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; static struct timeval TimeValue = { 0 }; if (netout) { FD_SET(net, &obits); } if (ttyout) { FD_SET(tout, &obits); }#if defined(TN3270) if (ttyin) { FD_SET(tin, &ibits); }#else /* defined(TN3270) */ if (ttyin) { FD_SET(tin, &ibits); }#endif /* defined(TN3270) */#if defined(TN3270) if (netin) { FD_SET(net, &ibits); }# else /* !defined(TN3270) */ if (netin) { FD_SET(net, &ibits); }# endif /* !defined(TN3270) */ if (netex) { FD_SET(net, &xbits); } if ((c = select(16, &ibits, &obits, &xbits, (poll == 0)? (struct timeval *)0 : &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; }# if defined(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 /* defined(TN3270) */ /* I don't like this, does it ever happen? */ printf("sleep(5) from telnet, after select\r\n"); sleep(5); } return 0; } /* * Any urgent data? */ if (FD_ISSET(net, &xbits)) { FD_CLR(net, &xbits); SYNCHing = 1; (void) 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);#if !defined(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) { int atmark; static int bogus_oob = 0, first = 1; 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; 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; /* * Bogosity. We have to do the read * to clear the atmark to get out of * an infinate loop. */ i = read(net, netiring.supply + c, canread - c); if (i > 0) c += i; } } else { c = recv(net, netiring.supply, canread, 0); } } else { c = recv(net, netiring.supply, canread, 0); } settimer(didnetreceive);#else /* !defined(SO_OOBINLINE) */ c = recv(net, (char *)netiring.supply, canread, 0);#endif /* !defined(SO_OOBINLINE) */ 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;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -