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

📄 state.c

📁 经典的unix下telnetd代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Copyright (c) 1989, 1993 *	The Regents of the University of California.  All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#include "telnetd.h"#include <syslog.h>/* RCSID("$KTH: state.c,v 1.14 2000/10/02 05:06:02 assar Exp $"); */unsigned char	doopt[] = { IAC, DO, '%', 'c', 0 };unsigned char	dont[] = { IAC, DONT, '%', 'c', 0 };unsigned char	will[] = { IAC, WILL, '%', 'c', 0 };unsigned char	wont[] = { IAC, WONT, '%', 'c', 0 };int	not42 = 1;/* * Buffer for sub-options, and macros * for suboptions buffer manipulations */unsigned char subbuffer[2048], *subpointer= subbuffer, *subend= subbuffer;#define	SB_CLEAR()	subpointer = subbuffer#define	SB_TERM()	{ subend = subpointer; SB_CLEAR(); }#define	SB_ACCUM(c)	if (subpointer < (subbuffer+sizeof subbuffer)) { \    *subpointer++ = (c); \			     }#define	SB_GET()	((*subpointer++)&0xff)#define	SB_EOF()	(subpointer >= subend)#define	SB_LEN()	(subend - subpointer)#ifdef	ENV_HACKunsigned char *subsave;#define SB_SAVE()	subsave = subpointer;#define	SB_RESTORE()	subpointer = subsave;#endif/* * State for recv fsm */#define	TS_DATA		0	/* base state */#define	TS_IAC		1	/* look for double IAC's */#define	TS_CR		2	/* CR-LF ->'s CR */#define	TS_SB		3	/* throw away begin's... */#define	TS_SE		4	/* ...end's (suboption negotiation) */#define	TS_WILL		5	/* will option negotiation */#define	TS_WONT		6	/* wont -''- */#define	TS_DO		7	/* do -''- */#define	TS_DONT		8	/* dont -''- */voidtelrcv(void){    int c;    static int state = TS_DATA;    while (ncc > 0) {	if ((&ptyobuf[BUFSIZ] - pfrontp) < 2)	    break;	c = *netip++ & 0377, ncc--;#ifdef ENCRYPTION	if (decrypt_input)	    c = (*decrypt_input)(c);#endif	switch (state) {	case TS_CR:	    state = TS_DATA;	    /* Strip off \n or \0 after a \r */	    if ((c == 0) || (c == '\n')) {		break;	    }	    /* FALL THROUGH */	case TS_DATA:	    if (c == IAC) {		state = TS_IAC;		break;	    }	    /*	     * We now map \r\n ==> \r for pragmatic reasons.	     * Many client implementations send \r\n when	     * the user hits the CarriageReturn key.	     *	     * We USED to map \r\n ==> \n, since \r\n says	     * that we want to be in column 1 of the next	     * printable line, and \n is the standard	     * unix way of saying that (\r is only good	     * if CRMOD is set, which it normally is).	     */	    if ((c == '\r') && his_state_is_wont(TELOPT_BINARY)) {#ifdef ENCRYPTION		int nc = *netip;		if (decrypt_input)		    nc = (*decrypt_input)(nc & 0xff);#endif		{#ifdef ENCRYPTION		    if (decrypt_input)			(void)(*decrypt_input)(-1);#endif		    state = TS_CR;		}	    }	    *pfrontp++ = c;	    break;	case TS_IAC:	gotiac:			switch (c) {	    /*	     * Send the process on the pty side an	     * interrupt.  Do this with a NULL or	     * interrupt char; depending on the tty mode.	     */	case IP:	    DIAG(TD_OPTIONS,		 printoption("td: recv IAC", c));	    interrupt();	    break;	case BREAK:	    DIAG(TD_OPTIONS,		 printoption("td: recv IAC", c));	    sendbrk();	    break;	    /*	     * Are You There?	     */	case AYT:	    DIAG(TD_OPTIONS,		 printoption("td: recv IAC", c));	    recv_ayt();	    break;	    /*	     * Abort Output	     */	case AO:	    {		DIAG(TD_OPTIONS,		     printoption("td: recv IAC", c));		ptyflush();	/* half-hearted */		init_termbuf();		if (slctab[SLC_AO].sptr &&		    *slctab[SLC_AO].sptr != (cc_t)(_POSIX_VDISABLE)) {		    *pfrontp++ =			(unsigned char)*slctab[SLC_AO].sptr;		}		netclear();	/* clear buffer back */		output_data ("%c%c", IAC, DM);		neturg = nfrontp-1; /* off by one XXX */		DIAG(TD_OPTIONS,		     printoption("td: send IAC", DM));		break;	    }	/*	 * Erase Character and	 * Erase Line	 */	case EC:	case EL:	    {		cc_t ch;		DIAG(TD_OPTIONS,		     printoption("td: recv IAC", c));		ptyflush();	/* half-hearted */		init_termbuf();		if (c == EC)		    ch = *slctab[SLC_EC].sptr;		else		    ch = *slctab[SLC_EL].sptr;		if (ch != (cc_t)(_POSIX_VDISABLE))		    *pfrontp++ = (unsigned char)ch;		break;	    }	/*	 * Check for urgent data...	 */	case DM:	    DIAG(TD_OPTIONS,		 printoption("td: recv IAC", c));	    SYNCHing = stilloob(net);	    settimer(gotDM);	    break;	    /*	     * Begin option subnegotiation...	     */	case SB:	    state = TS_SB;	    SB_CLEAR();	    continue;	case WILL:	    state = TS_WILL;	    continue;	case WONT:	    state = TS_WONT;	    continue;	case DO:	    state = TS_DO;	    continue;	case DONT:	    state = TS_DONT;	    continue;	case EOR:	    if (his_state_is_will(TELOPT_EOR))		doeof();	    break;	    /*	     * Handle RFC 10xx Telnet linemode option additions	     * to command stream (EOF, SUSP, ABORT).	     */	case xEOF:	    doeof();	    break;	case SUSP:	    sendsusp();	    break;	case ABORT:	    sendbrk();	    break;	case IAC:	    *pfrontp++ = c;	    break;	}	state = TS_DATA;	break;	case TS_SB:	    if (c == IAC) {		state = TS_SE;	    } else {		SB_ACCUM(c);	    }	    break;	case TS_SE:	    if (c != SE) {		if (c != IAC) {		    /*		     * bad form of suboption negotiation.		     * handle it in such a way as to avoid		     * damage to local state.  Parse		     * suboption buffer found so far,		     * then treat remaining stream as		     * another command sequence.		     */		    /* for DIAGNOSTICS */		    SB_ACCUM(IAC);		    SB_ACCUM(c);		    subpointer -= 2;		    SB_TERM();		    suboption();		    state = TS_IAC;		    goto gotiac;		}		SB_ACCUM(c);		state = TS_SB;	    } else {		/* for DIAGNOSTICS */		SB_ACCUM(IAC);		SB_ACCUM(SE);		subpointer -= 2;		SB_TERM();		suboption();	/* handle sub-option */		state = TS_DATA;	    }	    break;	case TS_WILL:	    willoption(c);	    state = TS_DATA;	    continue;	case TS_WONT:	    wontoption(c);	    if (c==TELOPT_ENCRYPT && his_do_dont_is_changing(TELOPT_ENCRYPT) )                dontoption(c);	    state = TS_DATA;	    continue;	case TS_DO:	    dooption(c);	    state = TS_DATA;	    continue;	case TS_DONT:	    dontoption(c);	    state = TS_DATA;	    continue;	default:	    syslog(LOG_ERR, "telnetd: panic state=%d", state);	    printf("telnetd: panic state=%d\n", state);	    exit(1);	}    }}  /* end of telrcv *//* * The will/wont/do/dont state machines are based on Dave Borman's * Telnet option processing state machine. * * These correspond to the following states: *	my_state = the last negotiated state *	want_state = what I want the state to go to *	want_resp = how many requests I have sent * All state defaults are negative, and resp defaults to 0. * * When initiating a request to change state to new_state: * * if ((want_resp == 0 && new_state == my_state) || want_state == new_state) { *	do nothing; * } else { *	want_state = new_state; *	send new_state; *	want_resp++; * } * * When receiving new_state: * * if (want_resp) { *	want_resp--; *	if (want_resp && (new_state == my_state)) *		want_resp--; * } * if ((want_resp == 0) && (new_state != want_state)) { *	if (ok_to_switch_to new_state) *		want_state = new_state; *	else *		want_resp++; *	send want_state; * } * my_state = new_state; * * Note that new_state is implied in these functions by the function itself. * will and do imply positive new_state, wont and dont imply negative. * * Finally, there is one catch.  If we send a negative response to a * positive request, my_state will be the positive while want_state will * remain negative.  my_state will revert to negative when the negative * acknowlegment arrives from the peer.  Thus, my_state generally tells * us not only the last negotiated state, but also tells us what the peer * wants to be doing as well.  It is important to understand this difference * as we may wish to be processing data streams based on our desired state * (want_state) or based on what the peer thinks the state is (my_state). * * This all works fine because if the peer sends a positive request, the data * that we receive prior to negative acknowlegment will probably be affected * by the positive state, and we can process it as such (if we can; if we * can't then it really doesn't matter).  If it is that important, then the * peer probably should be buffering until this option state negotiation * is complete. * */voidsend_do(int option, int init){    if (init) {	if ((do_dont_resp[option] == 0 && his_state_is_will(option)) ||	    his_want_state_is_will(option))	    return;	/*	 * Special case for TELOPT_TM:  We send a DO, but pretend	 * that we sent a DONT, so that we can send more DOs if	 * we want to.	 */	if (option == TELOPT_TM)	    set_his_want_state_wont(option);	else	    set_his_want_state_will(option);	do_dont_resp[option]++;    }    output_data((const char *)doopt, option);    DIAG(TD_OPTIONS, printoption("td: send do", option));}#ifdef	AUTHENTICATIONextern void auth_request(void);#endif#ifdef	ENCRYPTIONextern void encrypt_send_support(void);#endifvoidwilloption(int option){    int changeok = 0;    void (*func)(void) = 0;    /*     * process input from peer.     */    DIAG(TD_OPTIONS, printoption("td: recv will", option));    if (do_dont_resp[option]) {	do_dont_resp[option]--;	if (do_dont_resp[option] && his_state_is_will(option))	    do_dont_resp[option]--;    }    if (do_dont_resp[option] == 0) {	if (his_want_state_is_wont(option)) {	    switch (option) {	    case TELOPT_BINARY:		init_termbuf();		tty_binaryin(1);		set_termbuf();		changeok++;		break;	    case TELOPT_ECHO:		/*		 * See comments below for more info.		 */		not42 = 0;	/* looks like a 4.2 system */		break;	    case TELOPT_TM:		/*

⌨️ 快捷键说明

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