欢迎来到虫虫下载站 | 资源下载 资源专辑 关于我们
虫虫下载站

state.c

早期freebsd实现
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(){    register int subchar;    DIAG(TD_OPTIONS, {netflush(); 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: {		/* Yaaaay! */	static char terminalname[41];	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 */	}	terminaltype = terminalname;	while ((terminaltype < (terminalname + sizeof terminalname-1)) &&								    !SB_EOF()) {	    register int c;	    c = SB_GET();	    if (isupper(c)) {		c = tolower(c);	    }	    *terminaltype++ = c;    /* accumulate name */	}	*terminaltype = 0;	terminaltype = terminalname;	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 */#ifdef	LINEMODE    case TELOPT_LINEMODE: {	register int request;	if (his_state_is_wont(TELOPT_LINEMODE))	/* Ignore if option disabled */		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);		(void) 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 */#endif    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';	(void)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;			DIAG(TD_OPTIONS, {sprintf(nfrontp,				"ENVIRON VALUE and VAR are reversed!\r\n");				nfrontp += strlen(nfrontp);});		}	    }	    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);}#define	ADD(c)	 *ncp++ = c;#define	ADD_DATA(c) { *ncp++ = c; if (c == SE) *ncp++ = c; }	voidsend_status(){	unsigned char statusbuf[256];	register unsigned char *ncp;	register 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 (i == IAC)				ADD(IAC);		}		if (his_want_state_is_will(i)) {			ADD(DO);			ADD_DATA(i);			if (i == IAC)				ADD(IAC);		}	}	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(SB);		}	}#ifdef	LINEMODE	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);		if (editmode == IAC)			ADD(IAC);		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);	}#endif	/* LINEMODE */	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 + -