⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 state.c

📁 经典的unix下telnetd代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * suboption() * *	Look at the sub-option buffer, and try to be helpful to the other * side. * *	Currently we recognize: * *	Terminal type is *	Linemode *	Window size *	Terminal speed */voidsuboption(void){    int subchar;    DIAG(TD_OPTIONS, {netflush(); printsub('<', subpointer, SB_LEN()+2);});    subchar = SB_GET();    switch (subchar) {    case TELOPT_TSPEED: {	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: {		/* Yaaaay! */	char *tt;	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 */	}	tt = terminaltype;	while ((tt < (terminaltype + sizeof terminaltype-1)) &&	       !SB_EOF()) {	    int c;	    c = SB_GET();	    if (isupper(c)) {		c = tolower(c);	    }	    *tt++ = c;    /* accumulate name */	}	*tt = 0;	break;    }  /* end of case TELOPT_TTYPE */    case TELOPT_NAWS: {	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_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';	esetenv("DISPLAY", (char *)subpointer, 1);	break;    }  /* end of case TELOPT_XDISPLOC */#ifdef	TELOPT_NEW_ENVIRON    case TELOPT_NEW_ENVIRON:#endif    case TELOPT_OLD_ENVIRON: {	int c;	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) {		    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;			DIAG(TD_OPTIONS, {			    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(envvarok(varp)) {		    if (valp)			esetenv(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(envvarok(varp)) {	    if (valp)		esetenv(varp, valp, 1);	    else		unsetenv(varp);	}	break;    }  /* end of case TELOPT_NEW_ENVIRON */#ifdef 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    default:	break;    }  /* end of switch */}  /* end of suboption */voiddoclientstat(void){    clientstat(TELOPT_LINEMODE, WILL, 0);}#define	ADD(c)	 *ncp++ = c#define	ADD_DATA(c) { *ncp++ = c; if (c == SE || c == IAC) *ncp++ = c; }voidsend_status(void){    unsigned char statusbuf[256];    unsigned char *ncp;    unsigned char i;    ncp = 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);	}    }    ADD(IAC);    ADD(SE);    writenet(statusbuf, ncp - statusbuf);    netflush();	/* Send it on its way */    DIAG(TD_OPTIONS,	 {printsub('>', statusbuf, ncp - statusbuf); netflush();});}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -