📄 telnet.cc
字号:
case TELOPT_LINEMODE: linemode = 0; /* put us back to the default state */ break; } /* we always accept a DONT */ set_my_want_state_wont(option); if (my_state_is_will(option)) send_wont(option, 0); setconnmode(0); /* Set new tty mode */ } set_my_state_wont(option);}/* * Given a buffer returned by tgetent(), this routine will turn * the pipe seperated list of names in the buffer into an array * of pointers to null terminated names. We toss out any bad, * duplicate, or verbose names (names with spaces). */typedef ptrarray<const char> stringarray;static int is_unique(const char *name, const stringarray &ar) { for (int i=0; i<ar.num(); i++) if (!strcasecmp(ar[i], name)) return 0; return 1;}static void mklist(char *buf, const char *name, stringarray &fill) { char *cp; fill.setsize(0); cp = strchr(buf, ':'); if (cp) *cp = 0; for (cp = strtok(buf, "|:"); cp; cp = strtok(NULL, "|:")) { /* * Skip entries longer than 40 characters. * Skip entries with spaces or non-ascii values. * Convert lower case letters to upper case. */ if (strlen(cp)>40) continue; int bad = 0; for (int i=0; cp[i]; i++) if (!isascii(cp[i]) || cp[i]==' ') bad=1; if (bad) continue; upcase(cp); if (is_unique(cp, fill)) fill.add(cp); } /* * Move the name we were passed to the beginning if it's not already * there. */ for (int j=1; j<fill.num(); j++) if (!strcasecmp(name, fill[j])) { const char *temp = fill[j]; fill[j] = fill[0]; fill[0] = temp; } /* * Check for an old V6 2 character name. If present, * move it to the end of the array. */ for (int k=1; k<fill.num()-1; k++) { if (strlen(fill[k])==2 && fill[k]==buf) { const char *temp = fill[fill.num()-1]; fill[fill.num()-1] = fill[k]; fill[k] = temp; } } /* * If we got nothing, add in what we were passed */ if (fill.num()==0) { if (name && strlen(name)<40) fill.add(name); else fill.add("UNKNOWN"); } /* * Duplicate last name, for TTYPE option, and null * terminate the array. If we didn't find a match on * our terminal name, put that name at the beginning. */ fill.add(fill[fill.num()-1]); /* dholland 21-May-2000 I think this is bogus */ /*fill.add(NULL);*/}char termbuf[2048];static int my_setupterm(const char *tname, int /*fd*/, int *errp) { if (tgetent(termbuf, tname) == 1) { /* its Sun Mar 15 00:03:36 PST 1998 this could never have worked with * ncurses. The ncurses tgetent() ignores its first parameter */ #ifndef USE_NCURSES termbuf[1023] = '\0';#else strncpy(termbuf, CUR term_names, sizeof(termbuf));#endif if (errp) *errp = 1; return 0; } if (errp) *errp = 0; return -1;}int resettermname = 1;static const char *gettermname(void) { static stringarray termtypes; static int next; const char *tname; int err; if (resettermname) { resettermname = 0; tname = env_getvalue("TERM", 0); if (!tname || my_setupterm(tname, 1, &err)) { termbuf[0] = 0; tname = "UNKNOWN"; } mklist(termbuf, tname, termtypes); next = 0; } if (next==termtypes.num()) next = 0; return termtypes[next++];}/* * suboption() * * Look at the sub-option buffer, and try to be helpful to the other * side. * * Currently we recognize: * * Terminal type, send request. * Terminal speed (send request). * Local flow control (is request). * Linemode */static void suboption(void) { printsub('<', subbuffer, SB_LEN()+2); switch (SB_GET()) { case TELOPT_TTYPE: if (my_want_state_is_wont(TELOPT_TTYPE)) return; if (SB_EOF() || SB_GET() != TELQUAL_SEND) { return; } else { const char *name; #if defined(TN3270) if (tn3270_ttype()) { return; }#endif /* TN3270 */ name = gettermname(); netoring.printf("%c%c%c%c%s%c%c", IAC, SB, TELOPT_TTYPE, TELQUAL_IS, name, IAC, SE); } break; case TELOPT_TSPEED: if (my_want_state_is_wont(TELOPT_TSPEED)) return; if (SB_EOF()) return; if (SB_GET() == TELQUAL_SEND) { long oospeed, iispeed; TerminalSpeeds(&iispeed, &oospeed); netoring.printf("%c%c%c%c%ld,%ld%c%c", IAC, SB, TELOPT_TSPEED, TELQUAL_IS, oospeed, iispeed, IAC, SE); } break; case TELOPT_LFLOW: if (my_want_state_is_wont(TELOPT_LFLOW)) return; if (SB_EOF()) return; switch(SB_GET()) { case 1: localflow = 1; break; case 0: localflow = 0; break; default: return; } setcommandmode(); setconnmode(0); break; case TELOPT_LINEMODE: if (my_want_state_is_wont(TELOPT_LINEMODE)) return; if (SB_EOF()) return; switch (SB_GET()) { case WILL: lm_will(subpointer, SB_LEN()); break; case WONT: lm_wont(subpointer, SB_LEN()); break; case DO: lm_do(subpointer, SB_LEN()); break; case DONT: lm_dont(subpointer, SB_LEN()); break; case LM_SLC: slc(subpointer, SB_LEN()); break; case LM_MODE: lm_mode(subpointer, SB_LEN(), 0); break; default: break; } break; case TELOPT_ENVIRON: if (SB_EOF()) return; switch(SB_PEEK()) { case TELQUAL_IS: case TELQUAL_INFO: if (my_want_state_is_dont(TELOPT_ENVIRON)) return; break; case TELQUAL_SEND: if (my_want_state_is_wont(TELOPT_ENVIRON)) { return; } break; default: return; } env_opt(subpointer, SB_LEN()); break; case TELOPT_XDISPLOC: if (my_want_state_is_wont(TELOPT_XDISPLOC)) return; if (SB_EOF()) return; if (SB_GET() == TELQUAL_SEND) { const char *dp = env_getvalue("DISPLAY", 0); if (dp == NULL) { /* * Something happened, we no longer have a DISPLAY * variable. So, turn off the option. */ send_wont(TELOPT_XDISPLOC, 1); break; } netoring.printf("%c%c%c%c%s%c%c", IAC, SB, TELOPT_XDISPLOC, TELQUAL_IS, dp, IAC, SE); } break; default: break; }}//static char str_lm[] = { IAC, SB, TELOPT_LINEMODE, 0, 0, IAC, SE };void lm_will(unsigned char *cmd, int len) { if (len < 1) { /*@*/ printf("lm_will: no command!!!\n"); /* Should not happen... */ return; } netoring.printf("%c%c%c%c%c%c%c", IAC, SB, TELOPT_LINEMODE, DONT, cmd[0], IAC, SE);}void lm_wont(unsigned char * /*cmd*/, int len) { if (len < 1) { /*@*/ printf("lm_wont: no command!!!\n"); /* Should not happen... */ return; } /* We are always DONT, so don't respond */}void lm_do(unsigned char *cmd, int len) { if (len < 1) { /*@*/ printf("lm_do: no command!!!\n"); /* Should not happen... */ return; } netoring.printf("%c%c%c%c%c%c%c", IAC, SB, TELOPT_LINEMODE, WONT, cmd[0], IAC, SE);}void lm_dont(unsigned char * /*cmd*/, int len) { if (len < 1) { /*@*/ printf("lm_dont: no command!!!\n"); /* Should not happen... */ return; } /* we are always WONT, so don't respond */}void lm_mode(unsigned char *cmd, int len, int init) { if (len != 1) return; if ((linemode&MODE_MASK&~MODE_ACK) == *cmd) return; if (*cmd&MODE_ACK) return; linemode = *cmd&(MODE_MASK&~MODE_ACK); int k = linemode; if (!init) { k |= MODE_ACK; } netoring.printf("%c%c%c%c%c%c%c", IAC, SB, TELOPT_LINEMODE, LM_MODE, k, IAC, SE); setconnmode(0); /* set changed mode */}/* * slc() * Handle special character suboption of LINEMODE. */struct spc { cc_t val; cc_t *valp; char flags; /* Current flags & level */ char mylevel; /* Maximum level & flags */} spc_data[NSLC+1];#define SLC_IMPORT 0#define SLC_EXPORT 1#define SLC_RVALUE 2static int slc_mode = SLC_EXPORT;void slc_init(void) { register struct spc *spcp; localchars = 1; for (spcp = spc_data; spcp < &spc_data[NSLC+1]; spcp++) { spcp->val = 0; spcp->valp = 0; spcp->flags = spcp->mylevel = SLC_NOSUPPORT; } #define initfunc(func, flags) { \ spcp = &spc_data[func]; \ if ((spcp->valp = tcval(func))) { \ spcp->val = *spcp->valp; \ spcp->mylevel = SLC_VARIABLE|flags; \ } else { \ spcp->val = 0; \ spcp->mylevel = SLC_DEFAULT; \ } \ } initfunc(SLC_SYNCH, 0); /* No BRK */ initfunc(SLC_AO, 0); initfunc(SLC_AYT, 0); /* No EOR */ initfunc(SLC_ABORT, SLC_FLUSHIN|SLC_FLUSHOUT); initfunc(SLC_EOF, 0); initfunc(SLC_SUSP, SLC_FLUSHIN); initfunc(SLC_EC, 0); initfunc(SLC_EL, 0); initfunc(SLC_XON, 0); initfunc(SLC_XOFF, 0); initfunc(SLC_FORW1, 0); initfunc(SLC_FORW2, 0); /* No FORW2 */ initfunc(SLC_IP, SLC_FLUSHIN|SLC_FLUSHOUT);#undef initfunc if (slc_mode == SLC_EXPORT) slc_export(); else slc_import(1); }void slcstate(void) { printf("Special characters are %s values\n", slc_mode == SLC_IMPORT ? "remote default" : slc_mode == SLC_EXPORT ? "local" : "remote");}void slc_mode_export(void) { slc_mode = SLC_EXPORT; if (my_state_is_will(TELOPT_LINEMODE)) slc_export();}void slc_mode_import(int def) { slc_mode = def ? SLC_IMPORT : SLC_RVALUE; if (my_state_is_will(TELOPT_LINEMODE)) slc_import(def);}void slc_import(int def) { if (def) { netoring.printf("%c%c%c%c%c%c%c%c%c", IAC, SB, TELOPT_LINEMODE, LM_SLC, 0, SLC_DEFAULT, 0, IAC, SE); } else { netoring.printf("%c%c%c%c%c%c%c%c%c", IAC, SB, TELOPT_LINEMODE, LM_SLC, 0, SLC_VARIABLE, 0, IAC, SE); }}void slc_export(void) { register struct spc *spcp; TerminalDefaultChars(); slc_start_reply(); for (spcp = &spc_data[1]; spcp < &spc_data[NSLC+1]; spcp++) { if (spcp->mylevel != SLC_NOSUPPORT) { if (spcp->val == (cc_t)(_POSIX_VDISABLE)) spcp->flags = SLC_NOSUPPORT; else spcp->flags = spcp->mylevel; if (spcp->valp) spcp->val = *spcp->valp; slc_add_reply(spcp - spc_data, spcp->flags, spcp->val); } } slc_end_reply(); (void)slc_update(); setconnmode(1); /* Make sure the character values are set */}void slc(unsigned char *cp, int len) { register struct spc *spcp; register int func,level; slc_start_reply(); for (; len >= 3; len -=3, cp +=3) { func = cp[SLC_FUNC]; if (func == 0) { /* * Client side: always ignore 0 function. */ continue; } if (func > NSLC) { if ((cp[SLC_FLAGS] & SLC_LEVELBITS) != SLC_NOSUPPORT) slc_add_reply(func, SLC_NOSUPPORT, 0); continue; } spcp = &spc_data[func]; level = cp[SLC_FLAGS]&(SLC_LEVELBITS|SLC_ACK); if ((cp[SLC_VALUE] == spcp->val) && ((level&SLC_LEVELBITS) == (spcp->flags&SLC_LEVELBITS))) { continue; } if (level == (SLC_DEFAULT|SLC_ACK)) { /* * This is an error condition, the SLC_ACK * bit should never be set for the SLC_DEFAULT * level. Our best guess to recover is to * ignore the SLC_ACK bit. */ cp[SLC_FLAGS] &= ~SLC_ACK; } if (level == ((spcp->flags&SLC_LEVELBITS)|SLC_ACK)) { spcp->val = (cc_t)cp[SLC_VALUE]; spcp->flags = cp[SLC_FLAGS]; /* include SLC_ACK */ continue; } level &= ~SLC_ACK; if (level <= (spcp->mylevel&SLC_LEVELBITS)) { spcp->flags = cp[SLC_FLAGS]|SLC_ACK; spcp->val = (cc_t)cp[SLC_VALUE]; } if (level == SLC_DEFAULT) { if ((spcp->mylevel&SLC_LEVELBITS) != SLC_DEFAULT) spcp->flags = spcp->mylevel; else spcp->flags = SLC_NOSUPPORT; } slc_add_reply(func, spcp->flags, spcp->val); } slc_end_reply(); if (slc_update()) setconnmode(1); /* set the new character values */}void slc_check(void) { register struct spc *spcp; slc_start_reply();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -