📄 telnet.c
字号:
static int bol = 1, local = 0;intrlogin_susp(){ if (local) { local = 0; bol = 1; command(0, "z\n", 2); return(1); } return(0);}static inttelsnd(){ int tcc; int count; int returnValue = 0; unsigned char *tbp; tcc = 0; count = 0; while (NETROOM() > 2) { register int sc; register int c; if (tcc == 0) { if (count) { ring_consumed(&ttyiring, count); returnValue = 1; count = 0; } tbp = ttyiring.consume; tcc = ring_full_consecutive(&ttyiring); if (tcc == 0) { break; } } c = *tbp++ & 0xff, sc = strip(c), tcc--; count++; if (rlogin != _POSIX_VDISABLE) { if (bol) { bol = 0; if (sc == rlogin) { local = 1; continue; } } else if (local) { local = 0; if (sc == '.' || c == termEofChar) { bol = 1; command(0, "close\n", 6); continue; } if (sc == termSuspChar) { bol = 1; command(0, "z\n", 2); continue; } if (sc == escape) { command(0, (char *)tbp, tcc); bol = 1; count += tcc; tcc = 0; flushline = 1; break; } if (sc != rlogin) { ++tcc; --tbp; --count; c = sc = rlogin; } } if ((sc == '\n') || (sc == '\r')) bol = 1; } else if (sc == escape) { /* * Double escape is a pass through of a single escape character. */ if (tcc && strip(*tbp) == escape) { tbp++; tcc--; count++; bol = 0; } else { command(0, (char *)tbp, tcc); bol = 1; count += tcc; tcc = 0; flushline = 1; break; } } else bol = 0;#ifdef KLUDGELINEMODE if (kludgelinemode && (globalmode&MODE_EDIT) && (sc == echoc)) { if (tcc > 0 && strip(*tbp) == echoc) { tcc--; tbp++; count++; } else { dontlecho = !dontlecho; settimer(echotoggle); setconnmode(0); flushline = 1; break; } }#endif if (MODE_LOCAL_CHARS(globalmode)) { if (TerminalSpecialChars(sc) == 0) { bol = 1; break; } } if (my_want_state_is_wont(TELOPT_BINARY)) { switch (c) { case '\n': /* * If we are in CRMOD mode (\r ==> \n) * on our local machine, then probably * a newline (unix) is CRLF (TELNET). */ if (MODE_LOCAL_CHARS(globalmode)) { NETADD('\r'); } NETADD('\n'); bol = flushline = 1; break; case '\r': if (!crlf) { NET2ADD('\r', '\0'); } else { NET2ADD('\r', '\n'); } bol = flushline = 1; break; case IAC: NET2ADD(IAC, IAC); break; default: NETADD(c); break; } } else if (c == IAC) { NET2ADD(IAC, IAC); } else { NETADD(c); } } if (count) ring_consumed(&ttyiring, count); return returnValue||count; /* Non-zero if we did anything */}/* * Scheduler() * * Try to do something. * * If we do something useful, return 1; else return 0. * *//* block; should we block in the select ? */intScheduler(int block){ /* 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; int netin, netout, netex, ttyin, ttyout; /* Decide which rings should be processed */ netout = ring_full_count(&netoring) && (flushline || (my_want_state_is_wont(TELOPT_LINEMODE)#ifdef KLUDGELINEMODE && (!kludgelinemode || my_want_state_is_do(TELOPT_SGA))#endif ) || my_want_state_is_will(TELOPT_BINARY)); ttyout = ring_full_count(&ttyoring);#if defined(TN3270) ttyin = ring_empty_count(&ttyiring) && (shell_active == 0);#else /* defined(TN3270) */ ttyin = ring_empty_count(&ttyiring);#endif /* defined(TN3270) */#if defined(TN3270) netin = ring_empty_count(&netiring);# else /* !defined(TN3270) */ netin = !ISend && ring_empty_count(&netiring);# endif /* !defined(TN3270) */ netex = !SYNCHing; /* If we have seen a signal recently, reset things */# if defined(TN3270) && defined(unix) if (HaveInput) { HaveInput = 0; (void) signal(SIGIO, inputAvailable); }#endif /* defined(TN3270) && defined(unix) */ /* Call to system code to process rings */ returnValue = process_rings(netin, netout, netex, ttyin, ttyout, !block); /* Now, look at the input rings, looking for work to do. */ if (ring_full_count(&ttyiring)) {# if defined(TN3270) if (In3270) { int c; c = DataFromTerminal(ttyiring.consume, ring_full_consecutive(&ttyiring)); if (c) { returnValue = 1; ring_consumed(&ttyiring, c); } } else {# endif /* defined(TN3270) */ returnValue |= telsnd();# if defined(TN3270) }# endif /* defined(TN3270) */ } if (ring_full_count(&netiring)) {# if !defined(TN3270) returnValue |= telrcv();# else /* !defined(TN3270) */ returnValue = Push3270();# endif /* !defined(TN3270) */ } return returnValue;}/* * Select from tty and network... */voidtelnet(char *user){ sys_telnet_init();#if defined(AUTHENTICATION) || defined(ENCRYPTION) { extern char *localhost (); static char *local_host = 0; if (!local_host) local_host = localhost (); auth_encrypt_init(local_host, hostname, "TELNET", 0); auth_encrypt_user(user); }#endif /* defined(AUTHENTICATION) || defined(ENCRYPTION) */# if !defined(TN3270) if (telnetport) {#if defined(AUTHENTICATION) if (autologin) send_will(TELOPT_AUTHENTICATION, 1);#endif#ifdef ENCRYPTION send_do(TELOPT_ENCRYPT, 1); send_will(TELOPT_ENCRYPT, 1);#endif /* ENCRYPTION */ send_do(TELOPT_SGA, 1); send_will(TELOPT_TTYPE, 1); send_will(TELOPT_NAWS, 1); send_will(TELOPT_TSPEED, 1); send_will(TELOPT_LFLOW, 1); send_will(TELOPT_LINEMODE, 1); send_will(TELOPT_NEW_ENVIRON, 1); send_do(TELOPT_STATUS, 1); if (env_getvalue((unsigned char *)"DISPLAY")) send_will(TELOPT_XDISPLOC, 1); if (eight) tel_enter_binary(eight); }# endif /* !defined(TN3270) */# if !defined(TN3270) for (;;) { int schedValue; while ((schedValue = Scheduler(0)) != 0) { if (schedValue == -1) { setcommandmode(); return; } } if (Scheduler(1) == -1) { setcommandmode(); return; } }# else /* !defined(TN3270) */ for (;;) { int schedValue; while (!In3270 && !shell_active) { if (Scheduler(1) == -1) { setcommandmode(); return; } } while ((schedValue = Scheduler(0)) != 0) { if (schedValue == -1) { setcommandmode(); return; } } /* If there is data waiting to go out to terminal, don't * schedule any more data for the terminal. */ if (ring_full_count(&ttyoring)) { schedValue = 1; } else { if (shell_active) { if (shell_continue() == 0) { ConnectScreen(); } } else if (In3270) { schedValue = DoTerminalOutput(); } } if (schedValue && (shell_active == 0)) { if (Scheduler(1) == -1) { setcommandmode(); return; } } }# endif /* !defined(TN3270) */}#if 0 /* XXX - this not being in is a bug *//* * nextitem() * * Return the address of the next "item" in the TELNET data * stream. This will be the address of the next character if * the current address is a user data character, or it will * be the address of the character following the TELNET command * if the current address is a TELNET IAC ("I Am a Command") * character. */static char *nextitem(char *current){ if ((*current&0xff) != IAC) { return current+1; } switch (*(current+1)&0xff) { case DO: case DONT: case WILL: case WONT: return current+3; case SB: /* loop forever looking for the SE */ { register char *look = current+2; for (;;) { if ((*look++&0xff) == IAC) { if ((*look++&0xff) == SE) { return look; } } } } default: return current+2; }}#endif /* 0 *//* * netclear() * * We are about to do a TELNET SYNCH operation. Clear * the path to the network. * * Things are a bit tricky since we may have sent the first * byte or so of a previous TELNET command into the network. * So, we have to scan the network buffer from the beginning * until we are up to where we want to be. * * A side effect of what we do, just to keep things * simple, is to clear the urgent data pointer. The principal * caller should be setting the urgent data pointer AFTER calling * us in any case. */static voidnetclear(){#if 0 /* XXX */ register char *thisitem, *next; char *good;#define wewant(p) ((nfrontp > p) && ((*p&0xff) == IAC) && \ ((*(p+1)&0xff) != EC) && ((*(p+1)&0xff) != EL)) thisitem = netobuf; while ((next = nextitem(thisitem)) <= netobuf.send) { thisitem = next; } /* Now, thisitem is first before/at boundary. */ good = netobuf; /* where the good bytes go */ while (netoring.add > thisitem) { if (wewant(thisitem)) { int length; next = thisitem; do { next = nextitem(next); } while (wewant(next) && (nfrontp > next)); length = next-thisitem; memmove(good, thisitem, length); good += length; thisitem = next; } else { thisitem = nextitem(thisitem); } }#endif /* 0 */}/* * These routines add various telnet commands to the data stream. */static voiddoflush(){ NET2ADD(IAC, DO); NETADD(TELOPT_TM); flushline = 1; flushout = 1; (void) ttyflush(1); /* Flush/drop output */ /* do printoption AFTER flush, otherwise the output gets tossed... */ printoption("SENT", DO, TELOPT_TM);}voidxmitAO(){ NET2ADD(IAC, AO); printoption("SENT", IAC, AO); if (autoflush) { doflush(); }}voidxmitEL(){ NET2ADD(IAC, EL); printoption("SENT", IAC, EL);}voidxmitEC(){ NET2ADD(IAC, EC); printoption("SENT", IAC, EC);}intdosynch(){ netclear(); /* clear the path to the network */ NETADD(IAC); setneturg(); NETADD(DM); printoption("SENT", IAC, DM); return 1;}int want_status_response = 0;intget_status(){ unsigned char tmp[16]; register unsigned char *cp; if (my_want_state_is_dont(TELOPT_STATUS)) { printf("Remote side does not support STATUS option\n"); return 0; } cp = tmp; *cp++ = IAC; *cp++ = SB; *cp++ = TELOPT_STATUS; *cp++ = TELQUAL_SEND; *cp++ = IAC; *cp++ = SE; if (NETROOM() >= cp - tmp) { ring_supply_data(&netoring, tmp, cp-tmp); printsub('>', tmp+2, cp - tmp - 2); } ++want_status_response; return 1;}voidintp(){ NET2ADD(IAC, IP); printoption("SENT", IAC, IP); flushline = 1; if (autoflush) { doflush(); } if (autosynch) { dosynch(); }}voidsendbrk(){ NET2ADD(IAC, BREAK); printoption("SENT", IAC, BREAK); flushline = 1; if (autoflush) { doflush(); } if (autosynch) { dosynch(); }}voidsendabort(){ NET2ADD(IAC, ABORT); printoption("SENT", IAC, ABORT); flushline = 1; if (autoflush) { doflush(); } if (autosynch) { dosynch(); }}voidsendsusp(){ NET2ADD(IAC, SUSP); printoption("SENT", IAC, SUSP); flushline = 1; if (autoflush) { doflush(); } if (autosynch) { dosynch(); }}voidsendeof(){ NET2ADD(IAC, xEOF); printoption("SENT", IAC, xEOF);}voidsendayt(){ NET2ADD(IAC, AYT); printoption("SENT", IAC, AYT);}/* * Send a window size update to the remote system. */voidsendnaws(){ long rows, cols; unsigned char tmp[16]; register unsigned char *cp; if (my_state_is_wont(TELOPT_NAWS)) return;#define PUTSHORT(cp, x) { if ((*cp++ = ((x)>>8)&0xff) == IAC) *cp++ = IAC; \ if ((*cp++ = ((x))&0xff) == IAC) *cp++ = IAC; } if (TerminalWindowSize(&rows, &cols) == 0) { /* Failed */ return; } cp = tmp; *cp++ = IAC; *cp++ = SB; *cp++ = TELOPT_NAWS; PUTSHORT(cp, cols); PUTSHORT(cp, rows); *cp++ = IAC; *cp++ = SE; if (NETROOM() >= cp - tmp) { ring_supply_data(&netoring, tmp, cp-tmp); printsub('>', tmp+2, cp - tmp - 2); }}voidtel_enter_binary(int rw){ if (rw&1) send_do(TELOPT_BINARY, 1); if (rw&2) send_will(TELOPT_BINARY, 1);}voidtel_leave_binary(int rw){ if (rw&1) send_dont(TELOPT_BINARY, 1); if (rw&2) send_wont(TELOPT_BINARY, 1);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -