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

📄 telnet.c

📁 压缩包中包含LINUX下多个命令的源码
💻 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. * 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. */#ifndef lintstatic char sccsid[] = "@(#)telnet.c	8.4 (Berkeley) 5/30/95";#endif /* not lint */#ifdef HAVE_CONFIG_H#include <config.h>#endif#include <sys/types.h>#if	defined(unix)#include <signal.h>/* By the way, we need to include curses.h before telnet.h since, * among other things, telnet.h #defines 'DO', which is a variable * declared in curses.h. */#endif	/* defined(unix) */#include <arpa/telnet.h>#include <ctype.h>#if defined(STDC_HEADERS) || defined(HAVE_STDLIB_H)#include <stdlib.h>#endif#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>)? */#if	defined(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;jmp_buf	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. */voidinit_telnet(){    env_init();    SB_CLEAR();    ClearArray(options);    connected = In3270 = ISend = localflow = donebinarytoggle = 0;#if	defined(AUTHENTICATION) || defined(ENCRYPTION)    auth_encrypt_connect(connected);#endif	/* defined(AUTHENTICATION) || defined(ENCRYPTION)  */    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 voidprintring(va_alist)    va_dcl{    va_list ap;    char buffer[100];		/* where things go */    char *ptr;    char *format;    char *string;    Ring *ring;    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. */voidsend_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);}voidsend_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);}voidsend_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);}voidsend_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);}voidwilloption(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:#	    if defined(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	    /* defined(TN3270) */	    case TELOPT_BINARY:	    case TELOPT_SGA:		settimer(modenegotiated);		/* FALL THROUGH */	    case TELOPT_STATUS:#if	defined(AUTHENTICATION)	    case TELOPT_AUTHENTICATION:#endif#ifdef	ENCRYPTION	    case TELOPT_ENCRYPT:#endif /* ENCRYPTION */		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);#ifdef	ENCRYPTION	if (option == TELOPT_ENCRYPT)		encrypt_send_support();#endif	/* ENCRYPTION */}voidwontoption(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 voiddooption(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;#	if defined(TN3270)	    case TELOPT_EOR:		/* end of record */#	endif	/* defined(TN3270) */	    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 */#ifdef	ENCRYPTION	    case TELOPT_ENCRYPT:	/* encryption variable option */#endif	/* ENCRYPTION */		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;#if	defined(AUTHENTICATION)	    case TELOPT_AUTHENTICATION:		if (autologin)			new_state_ok = 1;		break;#endif	    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 voiddontoption(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 one.		 */		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);}/* * 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 int n;	register char c, *cp, **argvp, *cp2, **argv, **avt;	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

⌨️ 快捷键说明

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