📄 state.c
字号:
DEBUG(debug_options, 1, printsub ('<', subpointer, SB_LEN () + 2)); subchar = SB_GET (); switch (subchar) { case TELOPT_TSPEED: { register int xspeed, rspeed; if (his_state_is_wont (TELOPT_TSPEED)) /* Ignore if option disabled */ break; settimer (tspeedsubopt); if (SB_EOF () || SB_GET () != TELQUAL_IS) return; xspeed = atoi ((char *) subpointer); while (SB_GET () != ',' && !SB_EOF ()); if (SB_EOF ()) return; rspeed = atoi ((char *) subpointer); clientstat (TELOPT_TSPEED, xspeed, rspeed); break; } /* end of case TELOPT_TSPEED */ case TELOPT_TTYPE: { static struct obstack stk; char *p; if (his_state_is_wont (TELOPT_TTYPE)) /* Ignore if option disabled */ break; settimer (ttypesubopt); if (SB_EOF () || SB_GET () != TELQUAL_IS) return; /* ??? XXX but, this is the most robust */ if (terminaltype) free (terminaltype); obstack_init (&stk); while (!SB_EOF ()) { int c = tolower (SB_GET ()); obstack_1grow (&stk, c); } obstack_1grow (&stk, 0); p = obstack_finish (&stk); terminaltype = xstrdup (p); obstack_free (&stk, NULL); break; } /* end of case TELOPT_TTYPE */ case TELOPT_NAWS: { register int xwinsize, ywinsize; if (his_state_is_wont (TELOPT_NAWS)) /* Ignore if option disabled */ break; if (SB_EOF ()) return; xwinsize = SB_GET () << 8; if (SB_EOF ()) return; xwinsize |= SB_GET (); if (SB_EOF ()) return; ywinsize = SB_GET () << 8; if (SB_EOF ()) return; ywinsize |= SB_GET (); clientstat (TELOPT_NAWS, xwinsize, ywinsize); break; } /* end of case TELOPT_NAWS */ case TELOPT_LINEMODE: { register int request; /* Ignore if option disabled */ if (his_state_is_wont (TELOPT_LINEMODE)) break; /* * Process linemode suboptions. */ if (SB_EOF ()) break; /* garbage was sent */ request = SB_GET (); /* get will/wont */ if (SB_EOF ()) break; /* another garbage check */ if (request == LM_SLC) { /* SLC is not preceeded by WILL or WONT */ /* * Process suboption buffer of slc's */ start_slc (1); do_opt_slc (subpointer, subend - subpointer); end_slc (0); break; } else if (request == LM_MODE) { if (SB_EOF ()) return; useeditmode = SB_GET (); /* get mode flag */ clientstat (LM_MODE, 0, 0); break; } if (SB_EOF ()) break; switch (SB_GET ()) { /* what suboption? */ case LM_FORWARDMASK: /* * According to spec, only server can send request for * forwardmask, and client can only return a positive response. * So don't worry about it. */ default: break; } break; } /* end of case TELOPT_LINEMODE */ case TELOPT_STATUS: { int mode; if (SB_EOF ()) break; mode = SB_GET (); switch (mode) { case TELQUAL_SEND: if (my_state_is_will (TELOPT_STATUS)) send_status (); break; case TELQUAL_IS: break; default: break; } break; } /* end of case TELOPT_STATUS */ case TELOPT_XDISPLOC: { if (SB_EOF () || SB_GET () != TELQUAL_IS) return; settimer (xdisplocsubopt); subpointer[SB_LEN ()] = '\0'; setenv ("DISPLAY", (char *) subpointer, 1); break; } /* end of case TELOPT_XDISPLOC */#ifdef TELOPT_NEW_ENVIRON case TELOPT_NEW_ENVIRON:#endif case TELOPT_OLD_ENVIRON: { register int c; register char *cp, *varp, *valp; if (SB_EOF ()) return; c = SB_GET (); if (c == TELQUAL_IS) { if (subchar == TELOPT_OLD_ENVIRON) settimer (oenvironsubopt); else settimer (environsubopt); } else if (c != TELQUAL_INFO) return;#ifdef TELOPT_NEW_ENVIRON if (subchar == TELOPT_NEW_ENVIRON) { while (!SB_EOF ()) { c = SB_GET (); if ((c == NEW_ENV_VAR) || (c == ENV_USERVAR)) break; } } else#endif {#ifdef ENV_HACK /* * We only want to do this if we haven't already decided * whether or not the other side has its VALUE and VAR * reversed. */ if (env_ovar < 0) { register int last = -1; /* invalid value */ int empty = 0; int got_var = 0, got_value = 0, got_uservar = 0; /* * The other side might have its VALUE and VAR values * reversed. To be interoperable, we need to determine * which way it is. If the first recognized character * is a VAR or VALUE, then that will tell us what * type of client it is. If the fist recognized * character is a USERVAR, then we continue scanning * the suboption looking for two consecutive * VAR or VALUE fields. We should not get two * consecutive VALUE fields, so finding two * consecutive VALUE or VAR fields will tell us * what the client is. */ SB_SAVE (); while (!SB_EOF ()) { c = SB_GET (); switch (c) { case OLD_ENV_VAR: if (last < 0 || last == OLD_ENV_VAR || (empty && (last == OLD_ENV_VALUE))) goto env_ovar_ok; got_var++; last = OLD_ENV_VAR; break; case OLD_ENV_VALUE: if (last < 0 || last == OLD_ENV_VALUE || (empty && (last == OLD_ENV_VAR))) goto env_ovar_wrong; got_value++; last = OLD_ENV_VALUE; break; case ENV_USERVAR: /* count strings of USERVAR as one */ if (last != ENV_USERVAR) got_uservar++; if (empty) { if (last == OLD_ENV_VALUE) goto env_ovar_ok; if (last == OLD_ENV_VAR) goto env_ovar_wrong; } last = ENV_USERVAR; break; case ENV_ESC: if (!SB_EOF ()) c = SB_GET (); /* FALL THROUGH */ default: empty = 0; continue; } empty = 1; } if (empty) { if (last == OLD_ENV_VALUE) goto env_ovar_ok; if (last == OLD_ENV_VAR) goto env_ovar_wrong; } /* * Ok, the first thing was a USERVAR, and there * are not two consecutive VAR or VALUE commands, * and none of the VAR or VALUE commands are empty. * If the client has sent us a well-formed option, * then the number of VALUEs received should always * be less than or equal to the number of VARs and * USERVARs received. * * If we got exactly as many VALUEs as VARs and * USERVARs, the client has the same definitions. * * If we got exactly as many VARs as VALUEs and * USERVARS, the client has reversed definitions. */ if (got_uservar + got_var == got_value) { env_ovar_ok: env_ovar = OLD_ENV_VAR; env_ovalue = OLD_ENV_VALUE; } else if (got_uservar + got_value == got_var) { env_ovar_wrong: env_ovar = OLD_ENV_VALUE; env_ovalue = OLD_ENV_VAR; DEBUG(debug_options, 1, debug_output_data ( "ENVIRON VALUE and VAR are reversed!\r\n")); } } SB_RESTORE ();#endif while (!SB_EOF ()) { c = SB_GET (); if ((c == env_ovar) || (c == ENV_USERVAR)) break; } } if (SB_EOF ()) return; cp = varp = (char *) subpointer; valp = 0; while (!SB_EOF ()) { c = SB_GET (); if (subchar == TELOPT_OLD_ENVIRON) { if (c == env_ovar) c = NEW_ENV_VAR; else if (c == env_ovalue) c = NEW_ENV_VALUE; } switch (c) { case NEW_ENV_VALUE: *cp = '\0'; cp = valp = (char *) subpointer; break; case NEW_ENV_VAR: case ENV_USERVAR: *cp = '\0'; if (valp) (void) setenv (varp, valp, 1); else unsetenv (varp); cp = varp = (char *) subpointer; valp = 0; break; case ENV_ESC: if (SB_EOF ()) break; c = SB_GET (); /* FALL THROUGH */ default: *cp++ = c; break; } } *cp = '\0'; if (valp) (void) setenv (varp, valp, 1); else unsetenv (varp); break; } /* end of case TELOPT_NEW_ENVIRON */#if defined(AUTHENTICATION) case TELOPT_AUTHENTICATION: if (SB_EOF ()) break; switch (SB_GET ()) { case TELQUAL_SEND: case TELQUAL_REPLY: /* * These are sent by us and cannot be sent by * the client. */ break; case TELQUAL_IS: auth_is (subpointer, SB_LEN ()); break; case TELQUAL_NAME: auth_name (subpointer, SB_LEN ()); break; } break;#endif#ifdef ENCRYPTION case TELOPT_ENCRYPT: if (SB_EOF ()) break; switch (SB_GET ()) { case ENCRYPT_SUPPORT: encrypt_support (subpointer, SB_LEN ()); break; case ENCRYPT_IS: encrypt_is (subpointer, SB_LEN ()); break; case ENCRYPT_REPLY: encrypt_reply (subpointer, SB_LEN ()); break; case ENCRYPT_START: encrypt_start (subpointer, SB_LEN ()); break; case ENCRYPT_END: encrypt_end (); break; case ENCRYPT_REQSTART: encrypt_request_start (subpointer, SB_LEN ()); break; case ENCRYPT_REQEND: /* * We can always send an REQEND so that we cannot * get stuck encrypting. We should only get this * if we have been able to get in the correct mode * anyhow. */ encrypt_request_end (); break; case ENCRYPT_ENC_KEYID: encrypt_enc_keyid (subpointer, SB_LEN ()); break; case ENCRYPT_DEC_KEYID: encrypt_dec_keyid (subpointer, SB_LEN ()); break; default: break; } break;#endif /* ENCRYPTION */ default: break; } /* end of switch */} /* end of suboption */voiddoclientstat (){ clientstat (TELOPT_LINEMODE, WILL, 0);}voidsend_status (){#define ADD(c) \ do { \ if (ep > ncp) \ *ncp++ = c; \ else \ goto trunc; \ } while (0)#define ADD_DATA(c) \ do { \ ADD(c); if (c == SE || c == IAC) ADD(c); \ } while (0) unsigned char statusbuf[256]; unsigned char *ep; register unsigned char *ncp; register unsigned char i; ncp = statusbuf; ep = statusbuf + sizeof (statusbuf); netflush (); /* get rid of anything waiting to go out */ ADD (IAC); ADD (SB); ADD (TELOPT_STATUS); ADD (TELQUAL_IS); /* * We check the want_state rather than the current state, * because if we received a DO/WILL for an option that we * don't support, and the other side didn't send a DONT/WONT * in response to our WONT/DONT, then the "state" will be * WILL/DO, and the "want_state" will be WONT/DONT. We * need to go by the latter. */ for (i = 0; i < (unsigned char) NTELOPTS; i++) { if (my_want_state_is_will (i)) { ADD (WILL); ADD_DATA (i); } if (his_want_state_is_will (i)) { ADD (DO); ADD_DATA (i); } } if (his_want_state_is_will (TELOPT_LFLOW)) { ADD (SB); ADD (TELOPT_LFLOW); if (flowmode) ADD (LFLOW_ON); else ADD (LFLOW_OFF); ADD (SE); if (restartany >= 0) { ADD (SB); ADD (TELOPT_LFLOW); if (restartany) ADD (LFLOW_RESTART_ANY); else ADD (LFLOW_RESTART_XON); ADD (SE); } } if (his_want_state_is_will (TELOPT_LINEMODE)) { unsigned char *cp, *cpe; int len; ADD (SB); ADD (TELOPT_LINEMODE); ADD (LM_MODE); ADD_DATA (editmode); ADD (SE); ADD (SB); ADD (TELOPT_LINEMODE); ADD (LM_SLC); start_slc (0); send_slc (); len = end_slc (&cp); for (cpe = cp + len; cp < cpe; cp++) ADD_DATA (*cp); ADD (SE); } ADD (IAC); ADD (SE); net_output_datalen (statusbuf, ncp - statusbuf); netflush (); /* Send it on its way */ DEBUG(debug_options, 1, printsub ('>', statusbuf, ncp - statusbuf)); return;trunc: /* XXX bark? */ return;#undef ADD#undef ADD_DATA}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -