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

📄 telnet.c

📁 socket5 代理服务代码 socket5 代理服务代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* Copyright (c) 1988, 1990, 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. 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.                                           */#ifdef SHOW_SCCSIDSstatic char sccsid[] = "@(#)telnet.c	8.4 (Berkeley) 5/30/95";#endif#include <sys/types.h>#include <signal.h>#include <arpa/telnet.h>#include <ctype.h>#include "ring.h"#include "defines.h"#include "externs.h"#include "types.h"#include "general.h"#define	strip(x) ((my_want_state_is_wont(TELOPT_BINARY)) ? ((x)&0x7f) : (x))static unsigned char	subbuffer[SUBBUFSIZE],			*subpointer, *subend;	 /* buffer for sub-options */#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_PEEK()	((*subpointer)&0xff)#define	SB_EOF()	(subpointer >= subend)#define	SB_LEN()	(subend - subpointer)char	options[256];		/* The combined options */char	do_dont_resp[256];char	will_wont_resp[256];int	eight = 0,	autologin = 0,	/* Autologin anyone? */	skiprc = 0,	connected,	showoptions,	In3270,		/* Are we in 3270 mode? */	ISend,		/* trying to send network data in */	debug = 0,	crmod,	netdata,	/* Print out network data flow */	crlf,		/* Should '\r' be mapped to <CR><LF> (or <CR><NUL>)? */#ifdef TN3270	noasynchtty = 0,/* User specified "-noasynch" on command line */	noasynchnet = 0,/* User specified "-noasynch" on command line */	askedSGA = 0,	/* We have talked about suppress go ahead */#endif	/* defined(TN3270) */	telnetport,	SYNCHing,	/* we are in TELNET SYNCH mode */	flushout,	/* flush output */	autoflush = 0,	/* flush output when interrupting? */	autosynch,	/* send interrupt characters with SYNCH? */	localflow,	/* we handle flow control locally */	restartany,	/* if flow control enabled, restart on any character */	localchars,	/* we recognize interrupt/quit */	donelclchars,	/* the user has set "localchars" */	donebinarytoggle,	/* the user has put us in binary */	dontlecho,	/* do we suppress local echoing right now? */	globalmode;char *prompt = 0;cc_t escape;cc_t rlogin;#ifdef	KLUDGELINEMODEcc_t echoc;#endif/* * Telnet receiver states for fsm */#define	TS_DATA		0#define	TS_IAC		1#define	TS_WILL		2#define	TS_WONT		3#define	TS_DO		4#define	TS_DONT		5#define	TS_CR		6#define	TS_SB		7		/* sub-option collection */#define	TS_SE		8		/* looking for sub-option end */static int	telrcv_state;#ifdef	OLD_ENVIRONunsigned char telopt_environ = TELOPT_NEW_ENVIRON;#else# define telopt_environ TELOPT_NEW_ENVIRON#endifjmp_buf	toplevel, peerdied;int	flushline;int	linemode;#ifdef	KLUDGELINEMODEint	kludgelinemode = 1;#endif/* * The following are some clocks used to decide how to interpret * the relationship between various variables. */Clocks clocks;#ifdef	notdefModelist modelist[] = {	{ "telnet command mode", COMMAND_LINE },	{ "character-at-a-time mode", 0 },	{ "character-at-a-time mode (local echo)", LOCAL_ECHO|LOCAL_CHARS },	{ "line-by-line mode (remote echo)", LINE | LOCAL_CHARS },	{ "line-by-line mode", LINE | LOCAL_ECHO | LOCAL_CHARS },	{ "line-by-line mode (local echoing suppressed)", LINE | LOCAL_CHARS },	{ "3270 mode", 0 },};#endif/* * Initialize telnet environment. */void init_telnet() {    env_init();    SB_CLEAR();    ClearArray(options);    connected = In3270 = ISend = localflow = donebinarytoggle = 0;    restartany = -1;    SYNCHing = 0;    /* Don't change NetTrace */    escape = CONTROL(']');    rlogin = _POSIX_VDISABLE;#ifdef KLUDGELINEMODE    echoc = CONTROL('E');#endif    flushline = 1;    telrcv_state = TS_DATA;}#ifdef	notdef#include <varargs.h>/*VARARGS*/static void printring(va_alist) va_dcl {    char buffer[100], char *ptr, char *format, char *string;    Ring *ring;    va_list ap;    int i;    va_start(ap);    ring   = va_arg(ap, Ring *);    format = va_arg(ap, char *);    ptr    = buffer;    while ((i = *format++) != 0) {	if (i == '%') {	    i = *format++;	    switch (i) {	    case 'c':		*ptr++ = va_arg(ap, int);		break;	    case 's':		string = va_arg(ap, char *);		ring_supply_data(ring, buffer, ptr-buffer);		ring_supply_data(ring, string, strlen(string));		ptr = buffer;		break;	    case 0:		ExitString("printring: trailing %%.\n", 1);		/*NOTREACHED*/	    default:		ExitString("printring: unknown format character.\n", 1);		/*NOTREACHED*/	    }	} else {	    *ptr++ = i;	}    }    ring_supply_data(ring, buffer, ptr-buffer);}#endif/* These routines are in charge of sending option negotiations               *//* to the other side.                                                        *//*                                                                           *//* The basic idea is that we send the negotiation if either side             *//* is in disagreement as to what the current state should be.                */void send_do(register int c, register int init) {    if (init) {	if (((do_dont_resp[c] == 0) && my_state_is_do(c)) || my_want_state_is_do(c)) return;	set_my_want_state_do(c);	do_dont_resp[c]++;    }    NET2ADD(IAC, DO);    NETADD(c);    printoption("SENT", DO, c);}void send_dont(register int c, register int init) {    if (init) {	if (((do_dont_resp[c] == 0) && my_state_is_dont(c)) || my_want_state_is_dont(c)) return;	set_my_want_state_dont(c);	do_dont_resp[c]++;    }    NET2ADD(IAC, DONT);    NETADD(c);    printoption("SENT", DONT, c);}void send_will(register int c, register int init) {    if (init) {	if (((will_wont_resp[c] == 0) && my_state_is_will(c)) || my_want_state_is_will(c)) return;	set_my_want_state_will(c);	will_wont_resp[c]++;    }    NET2ADD(IAC, WILL);    NETADD(c);    printoption("SENT", WILL, c);}void send_wont(register int c, register int init) {    if (init) {	if (((will_wont_resp[c] == 0) && my_state_is_wont(c)) || my_want_state_is_wont(c)) return;	set_my_want_state_wont(c);	will_wont_resp[c]++;    }    NET2ADD(IAC, WONT);    NETADD(c);    printoption("SENT", WONT, c);}void willoption(int option) {    int new_state_ok = 0;    if (do_dont_resp[option]) {	--do_dont_resp[option];	if (do_dont_resp[option] && my_state_is_do(option))	    --do_dont_resp[option];    }        if ((do_dont_resp[option] == 0) && my_want_state_is_dont(option)) {	switch (option) {	    case TELOPT_ECHO:#ifdef TN3270		/* The following is a pain in the rear-end.  Various IBM     */		/* servers (some versions of Wiscnet, possibly Fibronics     */		/* Spartacus, and who knows who else) will NOT allow us to   */		/* send "DO SGA" too early in the setup proceedings.  On the */		/* other hand, 4.2 servers (telnetd) won't set SGA           */		/* correctly. So, we are stuck.  Empirically (but, based on  */		/* a VERY small sample), the IBM servers don't send out      */		/* anything about ECHO, so we postpone our sending "DO SGA"  */		/* until we see "WILL ECHO" (which 4.2 servers DO send).     */		{		    if (askedSGA == 0) {			askedSGA = 1;			if (my_want_state_is_dont(TELOPT_SGA))			    send_do(TELOPT_SGA, 1);		    }		}	        /* Fall through */	    case TELOPT_EOR:#endif	    case TELOPT_BINARY:	    case TELOPT_SGA:		settimer(modenegotiated);		/* FALL THROUGH */	    case TELOPT_STATUS:		new_state_ok = 1;		break;	    case TELOPT_TM:		if (flushout) flushout = 0;		/* Special case for TM.  If we get back a WILL, pretend we   */		/* got back a WONT.                                          */		set_my_want_state_dont(option);		set_my_state_dont(option);		return;			/* Never reply to TM will's/wont's   */	    case TELOPT_LINEMODE:	    default:		break;	}	if (new_state_ok) {	    set_my_want_state_do(option);	    send_do(option, 0);	    setconnmode(0);		/* possibly set new tty mode         */	} else {	    do_dont_resp[option]++;	    send_dont(option, 0);	}    }    set_my_state_do(option);}void wontoption(int option) {    if (do_dont_resp[option]) {	--do_dont_resp[option];	if (do_dont_resp[option] && my_state_is_dont(option))	    --do_dont_resp[option];    }    if ((do_dont_resp[option] == 0) && my_want_state_is_do(option)) {	    switch (option) {#ifdef	KLUDGELINEMODE		case TELOPT_SGA:		    if (!kludgelinemode) break;		    /* FALL THROUGH */#endif		case TELOPT_ECHO:		    settimer(modenegotiated);		    break;		case TELOPT_TM:		    if (flushout) flushout = 0;		    set_my_want_state_dont(option);		    set_my_state_dont(option);		    return;		/* Never reply to TM will's/wont's   */		default:		    break;	    }	    set_my_want_state_dont(option);	    if (my_state_is_do(option)) send_dont(option, 0);	    setconnmode(0);		/* Set new tty mode                  */    } else if (option == TELOPT_TM) {	/* Special case for TM.  */	if (flushout) flushout = 0;	set_my_want_state_dont(option);    }    set_my_state_dont(option);}static void dooption(int option) {    int new_state_ok = 0;    if (will_wont_resp[option]) {	--will_wont_resp[option];	if (will_wont_resp[option] && my_state_is_will(option))	    --will_wont_resp[option];    }    if (will_wont_resp[option] == 0) {	if (my_want_state_is_wont(option)) {	    switch (option) {		case TELOPT_TM:		    /* Special case for TM.  We send a WILL, but pretend we  */		    /* sent WONT.                                            */		    send_will(option, 0);		    set_my_want_state_wont(TELOPT_TM);		    set_my_state_wont(TELOPT_TM);		    return;#ifdef TN3270		case TELOPT_EOR:		/* end of record */#endif		case TELOPT_BINARY:		/* binary mode */		case TELOPT_NAWS:		/* window size */		case TELOPT_TSPEED:		/* terminal speed */		case TELOPT_LFLOW:		/* local flow control */		case TELOPT_TTYPE:		/* terminal type option */		case TELOPT_SGA:		/* no big deal */		    new_state_ok = 1;		    break;		case TELOPT_NEW_ENVIRON:	/* New environment variable option */#ifdef OLD_ENVIRON		    if (my_state_is_will(TELOPT_OLD_ENVIRON)) send_wont(TELOPT_OLD_ENVIRON, 1); /* turn off the old */		    goto env_common;		case TELOPT_OLD_ENVIRON:	/* Old environment variable option */		    if (my_state_is_will(TELOPT_NEW_ENVIRON)) break; /* Don't enable if new one is in use! */	    env_common:		    telopt_environ = option;#endif		    new_state_ok = 1;		    break;		case TELOPT_XDISPLOC:	/* X Display location */		    if (env_getvalue((unsigned char *)"DISPLAY")) new_state_ok = 1;		    break;		case TELOPT_LINEMODE:#ifdef	KLUDGELINEMODE		    kludgelinemode = 0;		    send_do(TELOPT_SGA, 1);#endif		    set_my_want_state_will(TELOPT_LINEMODE);		    send_will(option, 0);		    set_my_state_will(TELOPT_LINEMODE);		    slc_init();		    return;		case TELOPT_ECHO:		/* We're never going to echo... */		default:		    break;	    }	    if (new_state_ok) {		set_my_want_state_will(option);		send_will(option, 0);		setconnmode(0);			/* Set new tty mode */	    } else {		will_wont_resp[option]++;		send_wont(option, 0);	    }	} else {	    /* Handle options that need more things done after the other     */	    /* side has acknowledged the option.                             */	    switch (option) {		case TELOPT_LINEMODE:#ifdef	KLUDGELINEMODE		    kludgelinemode = 0;		    send_do(TELOPT_SGA, 1);#endif		    set_my_state_will(option);		    slc_init();		    send_do(TELOPT_SGA, 0);		    return;	    }	}    }    set_my_state_will(option);}static void dontoption(int option) {    if (will_wont_resp[option]) {	--will_wont_resp[option];	if (will_wont_resp[option] && my_state_is_wont(option))	    --will_wont_resp[option];    }    if ((will_wont_resp[option] == 0) && my_want_state_is_will(option)) {	switch (option) {	    case TELOPT_LINEMODE:		linemode = 0;	/* put us back to the default state */		break;#ifdef	OLD_ENVIRON	    case TELOPT_NEW_ENVIRON:		/* The new environ option wasn't recognized, try the old     */		send_will(TELOPT_OLD_ENVIRON, 1);		telopt_environ = TELOPT_OLD_ENVIRON;		break;#endif	}	/* we always accept a DONT */	set_my_want_state_wont(option);	if (my_state_is_will(option)) send_wont(option, 0);	setconnmode(0);			/* Set new tty mode */    }    set_my_state_wont(option);}static int is_unique(register char *name, register char **as, register char **ae) {    register char **ap;    register int n;    n = strlen(name) + 1;    for (ap = as; ap < ae; ap++)	if (strncasecmp(*ap, name, n) == 0)	    return 0;    return 1;}/* Given a buffer returned by tgetent(), this routine will turn              *//* the pipe seperated list of names in the buffer into an array              *//* of pointers to null terminated names.  We toss out any bad,               *//* duplicate, or verbose names (names with spaces).                          *//*                                                                           */static char *name_unknown = "UNKNOWN";static char *unknown[] = { 0, 0 };char ** mklist(char *buf, char *name) {    register char c, *cp, **argvp, *cp2, **argv, **avt;    register int n;    if (name) {	if ((int)strlen(name) > 40) {	    name = 0;	    unknown[0] = name_unknown;	} else {	    unknown[0] = name;	    upcase(name);	}    } else {	unknown[0] = name_unknown;    }    /* Count up the number of names.                                         */    for (n = 1, cp = buf; *cp && *cp != ':'; cp++) {	if (*cp == '|') n++;    }    /* Allocate an array to put the name pointers into                       */    argv = (char **)malloc((n+3)*sizeof(char *));    if (argv == 0) return(unknown);    /* Fill up the array of pointers to names.                               */    *argv = 0;    argvp = argv+1;    n = 0;    for (cp = cp2 = buf; (c = *cp);  cp++) {	if (c == '|' || c == ':') {	    *cp++ = '\0';	    /* Skip entries that have spaces or are over 40 characters long. */	    /* If this is our environment name, then put it up front.        */	    /* Otherwise, as long as this is not a duplicate name (case      */	    /* insensitive) add it to the list.                              */	    if (n || (cp - cp2 > 41)) ;	    else if (name && (strncasecmp(name, cp2, cp-cp2) == 0)) *argv = cp2;	    else if (is_unique(cp2, argv+1, argvp)) *argvp++ = cp2;	    if (c == ':') break;	    /* Skip multiple delimiters. Reset cp2 to the beginning of the   */	    /* next name. Reset n, the flag for names with spaces.           */	    while ((c = *cp) == '|') cp++;	    cp2 = cp;	    n = 0;	}	/* Skip entries with spaces or non-ascii values.  Convert lower case */	/* letters to upper case.                                            */	if ((c == ' ') || !isascii(c)) n = 1;	else if (islower((unsigned char)c)) *cp = toupper(c);    }    /* Check for an old V6 2 character name.  If the second name points to   */    /* the beginning of the buffer, and is only 2 characters long, move it   */    /* to the end of the array.                                              */    if ((argv[1] == buf) && (strlen(argv[1]) == 2)) {	for (--argvp, avt = &argv[1]; avt < argvp; avt++) *avt = *(avt+1);	*argvp++ = buf;    }    /* Duplicate last name, for TTYPE option, and null terminate the array.  */    /* If we didn't find a match on our terminal name, put that name at the  */    /* beginning.                                                                    */    cp = *(argvp-1);    *argvp++ = cp;    *argvp = 0;    

⌨️ 快捷键说明

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