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

📄 state.c

📁 里面包含了telnet的客户端和服务器端
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Copyright (c) 1989 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. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by the University of *	California, Berkeley and its contributors. * 4. 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. *//* * From: @(#)state.c	5.10 (Berkeley) 3/22/91 */char state_rcsid[] =   "$Id: state.c,v 1.12 1999/12/12 19:41:44 dholland Exp $";#include "telnetd.h"int not42 = 1;static int envvarok(char *varp);static unsigned char doopt[] = { IAC, DO, '%', 'c', 0 };static unsigned char dont[] = { IAC, DONT, '%', 'c', 0 };unsigned char	will[] = { IAC, WILL, '%', 'c', 0 };unsigned char	wont[] = { IAC, WONT, '%', 'c', 0 };/* * Buffer for sub-options, and macros * for suboptions buffer manipulations */unsigned char subbuffer[512], *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)-1)) { \				*subpointer++ = (c); \			}#define	SB_GET()	((*subpointer++)&0xff)#define	SB_EOF()	(subpointer >= subend)#define	SB_LEN()	(subend - subpointer)/* * 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 " */void telrcv(void) {    register int c;    static int state = TS_DATA;    while (ncc > 0) {	if ((&ptyobuf[BUFSIZ] - pfrontp) < 2) break;	c = *netip++ & 0377;	ncc--;#if defined(ENCRYPT)	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)) {#if defined(ENCRYPT)		 int nc = *netip;		 if (decrypt_input) {		     nc = (*decrypt_input)(nc & 0xff);		 }#endif#ifdef	LINEMODE		 /*		  * If we are operating in linemode,		  * convert to local end-of-line.		  */		 if (linemode && (ncc > 0) && (('\n' == nc) ||					       ((0 == nc) && tty_iscrnl())) ) {		     netip++; ncc--;		     c = '\n';		 } 		 else #endif		 {#if defined(ENCRYPT)		     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 */		      *nfrontp++ = (char)IAC;		      *nfrontp++ = (char)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);	     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\n", state);	     printf("telnetd: panic state=%d\n", state);	     exit(1);	}    }}/* * 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. * */void send_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]++;    }    netoprintf((char *)doopt, option);        DIAG(TD_OPTIONS, printoption("td: send do", option));}#ifdef	AUTHENTICATEextern void auth_request();#endif#ifdef	LINEMODEstatic void doclientstat(void);#endif#ifdef	ENCRYPTextern void encrypt_send_support();#endifvoid willoption(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.

⌨️ 快捷键说明

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