[alt.sources] teleplay - play with telnet via socket

wht@tridom.uucp (Warren Tucker) (07/17/89)

#!/bin/sh
# shar:	Shell Archiver  (v1.22)
#
#	Run the following text with /bin/sh to create:
#	  README
#	  Makefile
#	  apply.c
#	  hexdump.c
#	  teleplay.c
#	  teleplay.log
#	  MANIFEST
#
if test -f README; then echo "File README exists"; else
sed 's/^X//' << 'SHAR_EOF' > README &&
XWe've got a Pyramid and a Stratus and I've been working on
Xsome automated thingies for our development environment that
Xneeded to play telnet from the Pyramid to the Stratus over
XEthernet.  I, being a mostly System V type, hadn't had any
Xexperience with sockets, but needed to learn.  Then, low and
Xbehold, along came nntp.c from nelson@clutx.clarkson.edu.
XThank you, sir!  Anyway, I thought someone else might be
Xinterested in this stuff.  It's sorta raw, an experiment,
Xbut parts and pieces might be useful.
X-------------------------------------------------------------------
XWarren Tucker, Tridom Corporation       ...!gatech!emory!tridom!wht 
SHAR_EOF
chmod 0644 README || echo "restore of README fails"
fi
if test -f Makefile; then echo "File Makefile exists"; else
sed 's/^X//' << 'SHAR_EOF' > Makefile &&
X#  CHK=0xD543
XCFLAGS = -gx -DDEBUG
XLDFLAGS = -gx
XOBJ = \
X	teleplay.o\
X	apply.o\
X	hexdump.o
X
Xteleplay: $(OBJ)
X	cc $(LDFLAGS) $(OBJ) -o teleplay
SHAR_EOF
chmod 0644 Makefile || echo "restore of Makefile fails"
fi
if test -f apply.c; then echo "File apply.c exists"; else
sed 's/^X//' << 'SHAR_EOF' > apply.c &&
X/*+-------------------------------------------------------------------------
X	apply.c - sample application for 'teleplay'
X	...!gatech!emory!tridom!wht
X
X  Defined functions:
X	application()
X	application_hangup(code)
X	application_init(argc,argv)
X	get_opt(argc,argv,opts)
X	get_opt_ERR(s,c)
X
X--------------------------------------------------------------------------*/
X/*+:EDITS:*/
X/*:07-16-1989-19:19-wht-creation */
X
X#include <stdio.h>
X
Xextern char *index();
X
Xextern char *hostname;
X
X#if defined(DEBUG)
Xextern int debug;
Xchar *options = "Dd:h";
X#else
Xchar *options = ":h";
X#endif
X
Xstatic int optind = 1;
Xstatic int optopt;
Xstatic char *optarg;
X
X/*+-------------------------------------------------------------------------
X	get_opt_ERR(s,c)
X--------------------------------------------------------------------------*/
Xstatic void
Xget_opt_ERR(s,c)
Xchar *s;
Xchar c;
X{
X	fputs(s,stderr);
X	fputc(c,stderr);
X	fputc('\n',stderr);
X	exit(255);
X}	/* end of get_opt_ERR */
X
X/*+-------------------------------------------------------------------------
X	get_opt(argc,argv,opts) - almost standard, but ...
X--------------------------------------------------------------------------*/
Xstatic int
Xget_opt(argc,argv,opts)
Xint argc;
Xchar **argv;
Xchar *opts;
X{
Xstatic int sp = 1;
Xregister c;
Xregister char *cp;
Xchar errbuf[2];
X
X	if(sp == 1)
X	{
X		if(optind >= argc || argv[optind][0] != '-' || argv[optind][1] == '\0')
X			return(EOF);
X		else if(!strcmp(argv[optind],"--"))
X		{
X			optind++;
X			return(EOF);
X		}
X	}
X	optopt = c = argv[optind][sp];
X	if(c == ':' || (cp=index(opts,c)) == NULL)
X	{
X		get_opt_ERR(": unknown option, -",c);
X		if(argv[optind][++sp] == '\0')
X		{
X			optind++;
X			sp = 1;
X		}
X		return('?');
X	}
X	if(*++cp == ':')
X	{
X		if(argv[optind][sp+1] != '\0')
X			optarg = &argv[optind++][sp+1];
X		else if(++optind >= argc)
X		{
X			get_opt_ERR(": argument missing for -",c);
X			sp = 1;
X			return('?');
X		}
X		else
X			optarg = argv[optind++];
X		sp = 1;
X	}
X	else 
X	{
X		if(argv[optind][++sp] == '\0')
X		{
X			sp = 1;
X			optind++;
X		}
X		optarg = NULL;
X	}
X	return(c);
X}	/* end of get_opt */
X
X/*+-------------------------------------------------------------------------
X	application_init(argc,argv) - initialize application
X
X1.  process argv (terminate program if unsatisfactory)
X2.  initialize application environment
X--------------------------------------------------------------------------*/
Xapplication_init(argc,argv)
Xint argc;
Xchar **argv;
X{
Xregister itmp = 0;
X
X	hostname = (char *)0;
X
X	while(itmp != EOF)
X	{
X		switch(itmp = get_opt(argc,argv,options))
X		{
X			case 'D':
X				debug = 3;
X				break;
X			case 'd':
X				debug++;
X				break;
X			case 'h':
X				hostname = optarg;
X				break;
X		}
X	}
X
X#if defined(pyr)		/* you probably want to change this */
X	if(!hostname)
X		hostname = "tridom";
X#endif
X
X}	/* end of application_init */
X
X/*+-------------------------------------------------------------------------
X	application()
X--------------------------------------------------------------------------*/
Xvoid
Xapplication()
X{
X	login("wht","testpwd","dumb",1);
X	telputs("ps -au\r");
X	telsearch(100,"% ",15,"% ",1);
X	telputs("logout\r");	/* moot, really ... */
X	sleep(2);				/* ... but just for form */
X	puts("");
X}	/* end of application */
X
X/*+-------------------------------------------------------------------------
X	application_hangup(code)
X--------------------------------------------------------------------------*/
Xvoid
Xapplication_hangup(code)
Xint code;
X{
X	;	/* not needed for this application */
X}	/* end of application_hangup */
X
X/* vi: set tabstop=4 shiftwidth=4: */
X/* end of apply.c */
SHAR_EOF
chmod 0644 apply.c || echo "restore of apply.c fails"
fi
if test -f hexdump.c; then echo "File hexdump.c exists"; else
sed 's/^X//' << 'SHAR_EOF' > hexdump.c &&
X/*+-----------------------------------------------------------------------
X	hexdump.c  -- very generic hex/graphics dump development aid
X
X  Defined functions:
X	hex_dump(str,len,title,terse_flag)
X	hex_dump_fp(fp,str,len,title,terse_flag)
X	hex_dump16(int16)
X	hex_dump32(int32)
X	hex_dump4(int4)
X	hex_dump8(int8)
X
X------------------------------------------------------------------------*/
X/*+:EDITS:*/
X/*:07-11-1989-16:52-wht-no carriage returns output if dumpfp != stderr */
X/*:05-01-1986-22:57-wht-creation */
X
X#include <stdio.h>
X
X#ifndef uchar
X#define uchar unsigned char
X#define ushort unsigned short
X#define ulong unsigned long
X#endif
X
Xstatic FILE *dumpfp;
X
X#define dump_putc(ch)		fputc((ch),dumpfp)
X#define dump_puts(str)		fputs(str,dumpfp)
X
X/*+-----------------------------------------------------------------------
X	hex_dump#... subservient routines
X------------------------------------------------------------------------*/
Xvoid hex_dump4(int4)
Xuchar int4;
X{
X	int4 &= 15;
X	dump_putc((int4 >= 10) ? (int4 + 'A' - 10) : (int4 + '0'));
X}
X
Xvoid hex_dump8(int8)
Xuchar int8;
X{
X	hex_dump4(int8 >> 4);
X	hex_dump4(int8);
X}
X
Xvoid hex_dump16(int16)
Xushort int16;
X{
X	hex_dump8(int16 >> 8);
X	hex_dump8(int16);
X}
X
Xvoid hex_dump32(int32)
Xulong int32;
X{
X	hex_dump16(int32 >> 16);
X	hex_dump16(int32);
X}
X
X
X/*+-----------------------------------------------------------------
X	hex_dump_fp(fp,str,len,title,terse_flag)
X
X  if 'title' not NULL, title is printed... 'terse_flag'
X  controls whether or not the title is "conspicuous" with
X  hyphens before and after it making title line >70 chars long
X------------------------------------------------------------------*/
Xvoid
Xhex_dump_fp(fp,str,len,title,terse_flag)
XFILE *fp;
Xchar *str;
Xint len;
Xchar *title;
Xint terse_flag;
X{
Xint istr = 0;
Xregister ipos;
Xregister itmp;
X
X	dumpfp = fp;
X
X	if(strlen(title))
X	{
X		if(!terse_flag)
X		{
X			ipos = (73 - strlen(title)) / 2;
X			itmp = ipos;
X			while(itmp--)
X				dump_putc('-');
X			dump_putc(' ');
X		}
X		dump_puts(title);
X		if(!terse_flag)
X		{
X			dump_putc(' ');
X			while(ipos--)
X				dump_putc('-');
X		}
X		if(dumpfp == stderr)
X			dump_puts("\r\n");
X		else
X			dump_puts("\n");
X
X	}
X
X	while(istr < len)
X	{
X		hex_dump16(istr);
X		dump_putc(' ');
X		for(itmp = 0; itmp < 16; ++itmp)
X		{
X			ipos = istr + itmp;
X			if(ipos >= len)
X			{
X				if(!terse_flag)
X					dump_puts("   ");
X				continue;
X			}
X			dump_putc(' ');
X			hex_dump8(str[ipos]);
X		}
X		dump_puts(" | ");
X		for(itmp = 0; itmp < 16; ++itmp)
X		{
X			ipos = istr + itmp;
X			if( (ipos) >= len)
X			{
X				if(!terse_flag)
X					dump_putc(' ');
X			}
X			else
X			{
X				dump_putc((str[ipos] >= ' ' && str[ipos] < 0x7f)
X		 			? str[ipos] : '.' );
X			}
X		}
X		if(dumpfp == stderr)
X			dump_puts(" |\r\n");
X		else
X			dump_puts(" |\n");
X		istr += 16;
X	}   /* end of while(istr < len) */
X
X}	/* end of hex_dump_fp */
X
X/*+-------------------------------------------------------------------------
X	hex_dump(str,len,title,terse_flag)
X--------------------------------------------------------------------------*/
Xvoid
Xhex_dump(str,len,title,terse_flag)
Xchar *str;
Xint len;
Xchar *title;
Xint terse_flag;
X{
X	hex_dump_fp(stdout,str,len,title,terse_flag);
X}	/* end of hex_dump_fp */
X
X/* end of hexdump.c */
X/* vi: set tabstop=4 shiftwidth=4: */
SHAR_EOF
chmod 0644 hexdump.c || echo "restore of hexdump.c fails"
fi
if test -f teleplay.c; then echo "File teleplay.c exists"; else
sed 's/^X//' << 'SHAR_EOF' > teleplay.c &&
X/* CHK=0x7F92 */
X/*+-------------------------------------------------------------------------
X	teleplay.c - play with telnet by socket
X	...!gatech!emory!tridom!wht
X	thanks for inspiration and jumpstart to nelson@clutx.clarkson.edu
X
X  Error exit codes:
X	  1 - login failure
X	128 - socket I/O error
X	129 - connect or telnet protocol error
X	130 - timeout
X	131 - system resource error
X	255 - usage - (hostname error)
X
X  Defined functions:
X	_xmit_opt(tcmd,topt)
X	_xmit_ttype()
X	d_hostent(he)
X	d_servent(se)
X	d_sockaddr_in(sin)
X	do_use(topt)
X	dont_use(topt)
X	family_text(family)
X	hangup(code)
X	issubstr(target,search)
X	login(username,password,termtype,showit)
X	login_failure(reason)
X	main(argc,argv,envp)
X	sperror(txt)
X	telgetc()
X	telgetc_raw()
X	telgets(buf,timeout,delim,raw_flag)
X	telnet_cmd()
X	telnet_cmd_text(tcmd)
X	telnet_option(tcmd,topt)
X	telnet_option_text(topt)
X	telnet_subnegotiate()
X	telputc(schar)
X	telputcs(schars,count)
X	telputs(sstr)
X	telsearch(maxlines,searchstr,timeout,delim,showit)
X	will_use(topt)
X	wont_use(topt)
X
X--------------------------------------------------------------------------*/
X/*+:EDITS:*/
X/*:07-14-1989-13:05-wht-creation */
X
X#if defined(pyr)
X#define BSD43
X#endif
X
X#define CR 0x0D
X#define LF 0x0A
X
X#include <sys/types.h>
X#include <sys/socket.h>
X#include <sys/stat.h>
X#include <sys/ioctl.h>
X#include <sys/time.h>
X#include <sys/resource.h>
X
X#include <net/if.h>
X#include <netinet/in.h>
X#include <netinet/tcp.h>
X#include <arpa/telnet.h>
X
X#include <stdio.h>
X#include <errno.h>
X#include <ctype.h>
X#include <netdb.h>
X#include <signal.h>
X
Xchar *index();
Xu_long inet_addr();
X
Xextern int errno;
X
Xchar *hostname = (char *)0;
Xint ts = -1;		/* stream socket to telnet */
Xint debug = 9;		/* true if we're debugging. */
X
Xu_char Oecho = DO;				/* echo xmit data? */
Xu_char Ottype[] = "ANSI43";		/* terminal type */
X
X/*+-------------------------------------------------------------------------
X	sperror(txt) - stdout equivalent of 'perror'
X--------------------------------------------------------------------------*/
Xvoid
Xsperror(txt)
Xchar *txt;
X{
Xextern int errno;
Xextern int sys_nerr;
Xextern char *sys_errlist[];
X
X	fputs(txt,stdout);
X	fputs(": ",stdout);
X	if(errno >= sys_nerr)
X		printf("Error %d (unknown error)\n",errno);
X	else
X		puts(sys_errlist[errno]);
X}	/* end of sperror */
X
X/*+-------------------------------------------------------------------------
X	hangup(code) - clean up application and exit
X--------------------------------------------------------------------------*/
Xvoid
Xhangup(code)
Xint code;
X{
X	application_hangup(code);
X	if(ts >= 0)
X		close(ts);
X	if(code != 0)
X		printf("abnormal termination: code %d\n",code);
X	exit(code);
X
X}	/* end of hangup */
X
X/*+-------------------------------------------------------------------------
X	issubstr(target,search) - find 'search' in 'target'?
Xreturn 1 if found, else 0
X--------------------------------------------------------------------------*/
Xint
Xissubstr(target,search)
Xchar *target;
Xregister char *search;
X{
Xregister len = strlen(search);
X
X	while((target = index(target,*search)) != NULL)
X	{
X		if(!strncmp(search,target,len))
X			return(1);
X		target++;
X	}
X	return(0);
X}	/* end of issubstr */
X
X/*+-------------------------------------------------------------------------
X	telnet_cmd_text(tcmd)
X
X		EOR ...........ef
X		SE             f0
X		NOP ...........f1
X		DM/SYNCH       f2
X		BREAK .........f3
X		IP             f4
X		AO ............f5
X		AYT            f6
X		EC ............f7
X		EL             f8
X		GA ............f9
X		SB             fa
X		WILL ..........fb
X		WONT           fc
X		DO ............fd
X		DONT           fe
X		IAC ...........ff
X--------------------------------------------------------------------------*/
Xchar *
Xtelnet_cmd_text(tcmd)
Xu_char tcmd;
X{
Xstatic char static6[6];
X
X	switch(tcmd)
X	{
X		case IAC:		return("IAC");
X		case DONT:		return("DONT");
X		case DO:		return("DO");
X		case WONT:		return("WONT");
X		case WILL:		return("WILL");
X		case SB:		return("SB");
X		case GA:		return("GA");
X		case EL:		return("EL");
X		case EC:		return("EC");
X		case AYT:		return("AYT");
X		case AO:		return("AO");
X		case IP:		return("IP");
X		case BREAK:		return("BREAK");
X		case DM:		return("DM/SYNCH");
X		case NOP:		return("NOP");
X		case SE:		return("SE");
X		case EOR:		return("EOR");
X		default:
X			sprintf(static6,"?%02x?",tcmd);
X			return(static6);
X	}
X
X}	/* end of telnet_cmd_text */
X
X/*+-------------------------------------------------------------------------
X	telnet_option_text(topt)
X--------------------------------------------------------------------------*/
Xchar *
Xtelnet_option_text(topt)
Xu_char topt;
X{
Xstatic char static6[6];
X
X	switch(topt)
X	{
X		case TELOPT_BINARY:			return("BINARY");
X		case TELOPT_ECHO:			return("ECHO");
X		case TELOPT_RCP:			return("RCP");
X		case TELOPT_SGA:			return("SGA");
X		case TELOPT_NAMS:			return("NAMS");
X		case TELOPT_STATUS:			return("STATUS");
X		case TELOPT_TM:				return("TM");
X		case TELOPT_RCTE:			return("RCTE");
X		case TELOPT_NAOL:			return("NAOL");
X		case TELOPT_NAOP:			return("NAOP");
X		case TELOPT_NAOCRD:			return("NAOCRD");
X		case TELOPT_NAOHTS:			return("NAOHTS");
X		case TELOPT_NAOHTD:			return("NAOHTD");
X		case TELOPT_NAOFFD:			return("NAOFFD");
X		case TELOPT_NAOVTS:			return("NAOVTS");
X		case TELOPT_NAOVTD:			return("NAOVTD");
X		case TELOPT_NAOLFD:			return("NAOLFD");
X		case TELOPT_XASCII:			return("XASCII");
X		case TELOPT_LOGOUT:			return("LOGOUT");
X		case TELOPT_BM:				return("BM");
X		case TELOPT_DET:			return("DET");
X		case TELOPT_SUPDUP:			return("SUPDUP");
X		case TELOPT_SUPDUPOUTPUT:	return("SUPDUPOUTPUT");
X		case TELOPT_SNDLOC:			return("SNDLOC");
X		case TELOPT_TTYPE:			return("TTYPE");
X		case TELOPT_EOR:			return("EOR");
X		case TELOPT_EXOPL:			return("EXOPL");
X		default:
X			sprintf(static6,"?%02x?",topt);
X			return(static6);
X	}
X}	/* end of telnet_option_text */
X
X/*+-------------------------------------------------------------------------
X	telgetc_raw() - read character from telnet socket (waiting "forever")
X--------------------------------------------------------------------------*/
Xint
Xtelgetc_raw()
X{
Xint erc;
Xu_char schar;
X
X	while(1)
X	{
X		if(read(ts,&schar,1) <= 0)
X		{
X			if(errno == EINTR)
X				continue;
X			sperror("telgetc_raw");
X			hangup(128);
X		}
X
X#if defined(DEBUG)
X		if(debug > 9)
X			printf("<< %02x\n",schar);
X#endif
X		return((int)schar);
X
X	}
X	/*NOTREACHED*/
X}	/* end of telgetc_raw */
X
X/*+-------------------------------------------------------------------------
X	telnet_option(tcmd,topt)
X--------------------------------------------------------------------------*/
Xvoid
Xtelnet_option(tcmd,topt)
Xu_char tcmd;
Xu_char topt;
X{
X#if defined(DEBUG)
X	if(debug > 1)
X		printf("remote said %s %s\n",telnet_cmd_text(tcmd),
X			telnet_option_text(topt));
X#endif
X}	/* end of telnet_option */
X
X/*+-------------------------------------------------------------------------
X	_xmit_ttype()
X--------------------------------------------------------------------------*/
Xvoid
X_xmit_ttype()
X{
Xu_char buf[64];
Xu_char *cptr;
Xvoid telputcs();
X
X	cptr = buf;
X	*cptr++ = IAC;
X	*cptr++ = SB;
X	*cptr++ = TELOPT_TTYPE;
X	*cptr++ = TELQUAL_IS;
X	strcpy(cptr,Ottype);
X	cptr += strlen(Ottype);
X	*cptr++ = IAC;
X	*cptr++ = SE;
X	telputcs(buf,(int)(cptr - buf));
X}	/* end of _xmit_ttype */
X
X/*+-------------------------------------------------------------------------
X	telnet_subnegotiate()
X--------------------------------------------------------------------------*/
Xtelnet_subnegotiate()
X{
Xu_char topt_list[20];
Xregister u_char *topt_ptr = topt_list;
Xregister u_char *cptr;
Xint topt_count = 0;
Xu_int itmp;
Xu_char buf[64];
Xvoid telputcs();
X
X	while((*topt_ptr = telgetc_raw()) != IAC)
X	{
X		topt_ptr++;
X		topt_count++;
X	}
X	if((itmp = telgetc_raw()) != SE)
X	{
X		printf("subnegotiate: expected SE, got 0x%02x",itmp);
X		hangup(129);
X	}
X	topt_ptr = topt_list;
X	switch(*topt_ptr)
X	{
X		case TELOPT_BINARY:			itmp = DONT; break;
X		case TELOPT_ECHO:			itmp = Oecho; break;
X		case TELOPT_RCP:			itmp = -1;   break;
X		case TELOPT_SGA:			itmp = DONT; break;
X		case TELOPT_NAMS:			itmp = -1;   break;
X		case TELOPT_STATUS:			itmp = -1;   break;
X		case TELOPT_TM:				itmp = -1;   break;
X		case TELOPT_RCTE:			itmp = -1;   break;
X		case TELOPT_NAOL:			itmp = -1;   break;
X		case TELOPT_NAOP:			itmp = -1;   break;
X		case TELOPT_NAOCRD:			itmp = -1;   break;
X		case TELOPT_NAOHTS:			itmp = -1;   break;
X		case TELOPT_NAOHTD:			itmp = -1;   break;
X		case TELOPT_NAOFFD:			itmp = -1;   break;
X		case TELOPT_NAOVTS:			itmp = -1;   break;
X		case TELOPT_NAOVTD:			itmp = -1;   break;
X		case TELOPT_NAOLFD:			itmp = -1;   break;
X		case TELOPT_XASCII:			itmp = DONT; break;
X		case TELOPT_LOGOUT:			itmp = DONT; break;
X		case TELOPT_BM:				itmp = -1;   break;
X		case TELOPT_DET:			itmp = -1;   break;
X		case TELOPT_SUPDUP:			itmp = -1;   break;
X		case TELOPT_SUPDUPOUTPUT:	itmp = -1;   break;
X		case TELOPT_SNDLOC:			itmp = -1;   break;
X		case TELOPT_TTYPE:
X			if(*(topt_ptr + 1) == TELQUAL_SEND)
X			{
X				_xmit_ttype();
X				itmp = 0;
X#if defined(DEBUG)
X				if(debug > 1)
X					printf("> subnegotiate: our ttype %s\n",Ottype);
X#endif
X			}
X			break;
X		case TELOPT_EOR:			itmp = DONT; break;
X		case TELOPT_EXOPL:			itmp = DONT; break;
X	}
X
X	if(*(topt_ptr + 1) == TELQUAL_SEND)
X	{
X		if(itmp)		/* if not handled in switch statement */
X		{
X			if(itmp == -1)
X				printf("dont know how to subnegotiate %s\n",
X					telnet_option_text(*topt_ptr));
X			else
X			{
X				_xmit_opt((u_char)itmp,*topt_ptr);
X#if defined(DEBUG)
X				if(debug > 1)
X					printf("> subnegotiate %s %s\n",
X						telnet_cmd_text((u_char)itmp),
X						telnet_option_text(*topt_ptr));
X#endif
X			}
X		}
X	}
X#if defined(DEBUG)
X	else
X	{
X		sprintf(buf,"<< %s",telnet_option_text(*topt_ptr));
X		hex_dump(topt_ptr + 2,topt_count - 2,buf,1);
X	}
X#endif
X
X}	/* end of telnet_subnegotiate */
X
X/*+-------------------------------------------------------------------------
X	telnet_cmd() - IAC received: read and process command
X--------------------------------------------------------------------------*/
Xvoid
Xtelnet_cmd()
X{
Xint cmd;
X
X	switch(cmd = telgetc_raw())
X	{
X		case DONT:
X		case DO:
X		case WONT:
X		case WILL:
X			telnet_option(cmd,telgetc_raw());
X			break;
X		case SB:
X			telnet_subnegotiate();
X			break;
X		case GA:
X		case EL:
X		case EC:
X		case AYT:
X		case AO:
X		case IP:
X		case BREAK:
X		case DM:
X		case NOP:
X		case SE:
X		case EOR:
X#if defined(DEBUG)
X			if(debug > 3)
X				printf("< %s: ignored",telnet_cmd_text(cmd));
X#endif
X			break;
X
X	}
X}	/* end of telnet_cmd */
X
X/*+-------------------------------------------------------------------------
X	telgetc() - read character from telnet socket (waiting "forever")
Xif IAC (0xFF) received, process command
X--------------------------------------------------------------------------*/
Xint
Xtelgetc()
X{
Xint schar;
X
X	if((schar = telgetc_raw()) == IAC)
X	{
X		telnet_cmd();
X		return(-2);
X	}
X	return(schar);
X}	/* end of telgetc */
X
X/*+-------------------------------------------------------------------------
X	telgets(buf,timeout,delim,raw_flag) - read string from telnet socket
X
X1.  process IAC commands as found
X2.  timeout and die if timeout exceeded
X3.  if 'delim' != NULL and strlen(delim) != 0, look for delimiter string
X4.  otherwise, read and accumulate up to newline (omit newline)
X--------------------------------------------------------------------------*/
Xint
Xtelgets(buf,timeout,delim,raw_flag)
Xu_char *buf;
Xint timeout;
Xu_char *delim;
Xint raw_flag;
X{
Xregister read_count = 0;
Xregister delim_len = 0;
X#if defined(BSD43)
Xfd_set fdmask;
X#else
Xint fdmask;
X#endif
Xstruct timeval tv;
Xint erc;
Xu_char *read_ptr = buf;
Xint rdchar;
X
X	if(delim)
X		delim_len = strlen(delim);
X
X	while(1)
X	{
X		tv.tv_sec = (long)timeout;
X		tv.tv_usec = 0L;
X#if defined(BSD43)
X		FD_ZERO(&fdmask);
X		FD_SET(ts,&fdmask);
X#else
X		fdmask = 1 << ts;
X#endif
X		erc = select(32,(fd_set *)&fdmask,(fd_set *)0,(fd_set *)&fdmask,&tv);
X
X		if(erc < 0)
X		{
X			if(errno == EINTR)
X				continue;
X			sperror("telgets select");
X			hangup(128);
X		}
X		if(erc == 0)
X		{
X			printf("telgets timed out\n");
X			hangup(130);
X		}
X
X		if((rdchar = telgetc()) < 0)
X		{
X			if(rdchar == -2)	/* if select succeded for cmd (IAC) */
X				continue;
X			sperror("telgets");
X			hangup(128);
X		}
X
X		rdchar &= 0x7F;
X		if(!rdchar || (!raw_flag && (rdchar == CR)))
X			continue;
X
X		*read_ptr = rdchar;
X
X		/* look for delimiter */
X		if(delim_len && (read_count + 1 >= delim_len))
X		{
X			if(!strncmp(delim,read_ptr - delim_len + 1,delim_len))
X			{
X				*++read_ptr = 0;
X				return(strlen(buf));
X			}
X		}
X
X		/* look for end of line */
X		if(*read_ptr == LF)
X		{
X			if(raw_flag)
X				*read_ptr++ = LF;
X			*read_ptr = 0;
X			return(strlen(buf));
X		}
X
X		read_count++; 
X		read_ptr++;
X	}
X	/* NOTREACHED */
X}	/* end of telgets */
X
X/*+-------------------------------------------------------------------------
X	telputc(schar) - send character to telnet socket
X--------------------------------------------------------------------------*/
Xvoid
Xtelputc(schar)
Xu_char schar;
X{
X	if(write(ts,&schar,1) != 1)
X	{
X		sperror("write error on telnet socket\n");
X		hangup(128);
X	}
X}	/* end of telputc */
X
X/*+-------------------------------------------------------------------------
X	telputcs(schars,count) - send characters to telnet socket
X
XThis function did NOT work when write(ts,schars,count) was used,
Xthough the write succeeded; this is a puzzle.  Does telnet do a recv()
Xcall, throwing away "packets" > 1 in length.
X--------------------------------------------------------------------------*/
Xvoid
Xtelputcs(schars,count)
Xu_char *schars;
Xint count;
X{
Xregister u_char *cptr = schars;
Xregister icount = count;
X
X	while(icount--)
X		telputc(*cptr++);
X
X#if defined(DEBUG)
X	if(debug < 10)
X		return;
X	hex_dump(schars,count,">> telputcs",1);
X#endif
X}	/* end of telputcs */
X
X/*+-------------------------------------------------------------------------
X	telputs(sstr) - send null-terminated string to telnet socket
X--------------------------------------------------------------------------*/
Xvoid
Xtelputs(sstr)
Xchar *sstr;
X{
X	telputcs(sstr,strlen(sstr));
X}	/* end of telputs */
X
X/*+-------------------------------------------------------------------------
X	_xmit_opt(tcmd,topt) - common "send option" routine
X--------------------------------------------------------------------------*/
Xvoid
X_xmit_opt(tcmd,topt)
Xu_char tcmd;
Xu_char topt;
X{
Xu_char optbuf[8];
Xu_char *optptr = optbuf;
X
X	*optptr++ = IAC;
X	*optptr++ = tcmd;
X	*optptr++ = topt;
X	telputcs(optbuf,(int)(optptr - optbuf));
X
X	if(debug)
X		printf("> we say %s %s\n",telnet_cmd_text(tcmd),
X			telnet_option_text(topt));
X}	/* end of _xmit_opt */
X
X/*+-------------------------------------------------------------------------
X	will_use(topt) - send to remote system that we will use an option
X--------------------------------------------------------------------------*/
Xvoid
Xwill_use(topt)
Xu_char topt;
X{
X	_xmit_opt(WILL,topt);
X}	/* end of will_use */
X
X/*+-------------------------------------------------------------------------
X	wont_use(topt) - send to remote system that we wont use an option
X--------------------------------------------------------------------------*/
Xvoid
Xwont_use(topt)
Xu_char topt;
X{
X	_xmit_opt(WONT,topt);
X}	/* end of wont_use */
X
X/*+-------------------------------------------------------------------------
X	do_use(topt) - ask remote system to use an option
X--------------------------------------------------------------------------*/
Xvoid
Xdo_use(topt)
Xu_char topt;
X{
X	_xmit_opt(DO,topt);
X}	/* end of do_use */
X
X/*+-------------------------------------------------------------------------
X	dont_use(topt) - ask remote system not to use an option
X--------------------------------------------------------------------------*/
Xvoid
Xdont_use(topt)
Xu_char topt;
X{
X	_xmit_opt(DONT,topt);
X}	/* end of dont_use */
X
X/*+-------------------------------------------------------------------------
X	family_text(family)
X--------------------------------------------------------------------------*/
X#if defined(DEBUG)
Xchar *
Xfamily_text(family)
Xshort family;
X{
Xstatic char static32[32];
X
X	switch(family)
X	{
X		case AF_UNSPEC:		return("Unspecified");
X		case AF_UNIX:		return("UNIX");
X		case AF_INET:		return("INTERNET");
X		case AF_IMPLINK:	return("ARPANET/IMP");
X		case AF_PUP:		return("PUP");
X		case AF_CHAOS:		return("MIT CHAOS");
X		case AF_NS:			return("XEROX NS");
X		case AF_NBS:		return("NBS");
X		case AF_ECMA:		return("EUROPEAN");
X		case AF_DATAKIT:	return("DATAKIT");
X		case AF_CCITT:		return("CCITT");
X		case AF_SNA:		return("SNA");
X		case AF_DECnet:		return("DECnet");
X		case AF_DLI:		return("DATA LINK INTERFACE");
X		case AF_LAT:		return("LAT");
X		case AF_HYLINK:		return("NSC Hyperchannel");
X		case AF_APPLETALK:	return("Apple Talk");
X		case AF_ISO:		return("ISO");
X		default:
X			sprintf(static32,"number %d\n",family);
X			return(static32);
X	}
X	/*NOTREACHED*/
X
X}	/* end of family_text */
X#endif
X
X/*+-------------------------------------------------------------------------
X	d_sockaddr_in(sin) display INTERNET socket address
X--------------------------------------------------------------------------*/
X#if defined(DEBUG)
Xvoid
Xd_sockaddr_in(sin)
Xstruct sockaddr_in *sin;
X{
Xregister itmp;
X
X	printf("sockaddr_in @ %08lx family: %s port: 0x%04x\n",sin,
X		family_text(sin->sin_family),sin->sin_port);
X	printf("            port 0x%08lx",sin->sin_addr.s_addr);
X	fputs(" zero:",stdout);
X	for(itmp = 0; itmp < sizeof(sin->sin_zero); itmp++)
X		printf(" %02x",sin->sin_zero[itmp]);
X	fputs("\n\n",stdout);
X}	/* end of d_sockaddr_in */
X#endif
X
X/*+-------------------------------------------------------------------------
X	d_hostent(he) - display host entry
X--------------------------------------------------------------------------*/
X#if defined(DEBUG)
Xvoid
Xd_hostent(he)
Xstruct hostent *he;
X{
Xregister itmp;
Xu_char *haddr;
X
X	printf("hostent @ %08lx name: %s family: %s address:",he,
X		he->h_name,family_text(he->h_addrtype));
X#if defined(BSD43)
X	haddr = (u_char *)he->h_addr_list[0];
X#else
X	haddr = (u_char *)he->h_addr;
X#endif
X	itmp = he->h_length;
X	while(itmp--)
X		printf(" %02x",*haddr++);
X	fputs("\n\n",stdout);
X
X}	/* end of d_hostent */
X#endif
X
X/*+-------------------------------------------------------------------------
X	d_servent(se) - display server entry
X--------------------------------------------------------------------------*/
X#if defined(DEBUG)
Xvoid
Xd_servent(se)
Xstruct servent *se;
X{
X	printf("servent @ %08lx name: %s port: 0x%08x protocol: %s\n\n",se,
X		se->s_name,se->s_port,se->s_proto);
X}	/* end of d_servent */
X#endif
X
X/*+-------------------------------------------------------------------------
X	telsearch(maxlines,searchstr,timeout,delim,showit)
X
X1. read socket, for 'maxlines', looking for line containing 'searchstr'
X2. if 'timeout' seconds pass before completion, kill program
X3. use 'delim' for early termination of socket reads (before NL)
X4. if 'showit' non-zero, display socket data on stdout
X
Xreturn 1 if 'searchstr' found, else 0
X--------------------------------------------------------------------------*/
Xint
Xtelsearch(maxlines,searchstr,timeout,delim,showit)
Xint maxlines;
Xchar *searchstr;
Xint timeout;
Xchar *delim;
Xint showit;
X{
Xchar buf[256];
X
X	while(maxlines--)
X	{
X		telgets(buf,timeout,delim,1);
X		if(showit)
X			fputs(buf,stdout);
X		if(issubstr(buf,searchstr))
X			return(1);
X	}
X	return(0);
X}	/* end of telsearch */
X
X/*+-------------------------------------------------------------------------
X	login_failure(reason)
X--------------------------------------------------------------------------*/
Xvoid
Xlogin_failure(reason)
Xchar *reason;
X{
X	fputs("===> LOGIN FAILURE",stdout);
X	if(*reason)
X		printf(": %s\n",stdout);
X	else
X		puts("");
X	hangup(1);
X}	/* end of login_failure */
X
X/*+-------------------------------------------------------------------------
X	login(username,password,termtype,showit) - given extant session, login
X
Xlogin to remote UNIX system using 'username' and 'password'
Xif 'termtype' != 0 and non-null, look for tset prompt and supply termtype
X
XNote: login expected to present csh prompt ending with "% "
Xafter optional tset sequence
X--------------------------------------------------------------------------*/
Xvoid
Xlogin(username,password,termtype,showit)
Xchar *username;
Xchar *password;
Xchar *termtype;
Xint showit;
X{
Xint maxlines;
Xchar buf[256];
Xchar *searchstr;
Xchar *delim;
Xint send_termtype;
X
X/* ------- login --------------------------------------------- */
X	if(!telsearch(10,"login:",20,"in: ",1))
X		login_failure("search for 'login: ' failed");
X	telputs(username); telputc('\r');
X
X/* ------- password ------------------------------------------ */
X	if(!telsearch(5,"word:",20,"rd:",1))
X		login_failure("search for 'Password:' failed");
X	telputs(password); telputc('\r');
X
X/* ------- check for incorrect login -- set up for tset ------ */
X	if(send_termtype = (termtype && *termtype))
X	{
X		searchstr = "TERM";
X		delim = ") ";
X	}
X	else
X		searchstr = delim = "% ";
X
X	maxlines = 40;		/* plenty (wordy motd's do happen) */
X	while(maxlines--)
X	{
X		telgets(buf,15,delim,1);
X		if(showit)
X			fputs(buf,stdout);
X		if(issubstr(buf,searchstr))
X			break;
X		if(issubstr(buf,"incorrect"))
X			login_failure("");
X	}
X	if(!maxlines)
X		login_failure( (send_termtype)
X			? "tset request not seen" : "'% ' prompt not seen");
X
X/* ------- if tset requested, do it now ---------------------- */
X	if(!send_termtype)
X		return;
X	telputs(termtype); telputc('\r');
X	if(!telsearch(10,"% ",20,"% ",1))
X		login_failure();
X
X}	/* end of login */
X
X/*+-------------------------------------------------------------------------
X	main(argc,argv,envp)
X--------------------------------------------------------------------------*/
Xmain(argc,argv,envp)
Xint argc;
Xchar **argv;
Xchar **envp;
X{
Xregister char *cptr;
Xchar buf[BUFSIZ];
Xint connected = 0;		/* 1 = connected */
Xint itmp;
Xint proto_num;
Xstruct hostent *he;
Xstruct servent *se;
Xstruct sockaddr_in sin;
Xchar telnet1[3];
X
X
X	application_init(argc,argv);
X	if(!hostname || !*hostname)
X	{
X		printf("no hostname specified\n");
X		hangup(255);
X	}
X
X	sin.sin_addr.s_addr = inet_addr(hostname);
X	if(sin.sin_addr.s_addr != -1)
X	{
X		sin.sin_family = AF_INET;
X#if defined(DEBUG)
X		if(debug > 4)
X		{
X			printf("inet_addr success: %s\n",hostname);
X			d_sockaddr_in(&sin);
X		}
X#endif
X	}
X	else 
X	{
X		he = gethostbyname(hostname);
X		if(he == NULL)
X		{
X			printf("unknown host: %s\n",hostname);
X			hangup(255);
X		}
X
X#if defined(DEBUG)
X		if(debug > 4)
X		{
X			printf("gethostbyname success: %s\n",hostname);
X			d_hostent(he);
X		}
X#endif
X
X		sin.sin_family = he->h_addrtype;
X#if defined(BSD43)
X		bcopy(he->h_addr_list[0],(caddr_t)&sin.sin_addr,
X		    he->h_length);
X#else
X		bcopy(he->h_addr,(caddr_t)&sin.sin_addr,
X		    he->h_length);
X#endif
X	}
X
X	if(!(se = getservbyname("telnet","tcp")))
X	{
X		perror("getservbyname telnet/tcp");
X		hangup(131);
X	}
X
X	sin.sin_port = se->s_port;
X
X#if defined(DEBUG)
X	if(debug > 4)
X	{
X		printf("getservbyname success: telnet/tcp\n");
X		d_servent(se);
X	}
X#endif
X
X	do	
X	{
X		ts = socket(PF_INET,SOCK_STREAM,0);
X		if(ts < 0)
X		{
X			perror("socket()");
X			hangup(131);
X		}
X#if defined(DEBUG)
X		if(debug > 6)
X		{
X			printf("socket id %d\n",ts);
X			getsockopt(ts,SOL_SOCKET,SO_SNDBUF,(char *)&itmp,sizeof(int));
X			printf("send bufsize %d ",itmp,sizeof(int));
X			getsockopt(ts,SOL_SOCKET,SO_RCVBUF,(char *)&itmp,sizeof(int));
X			printf("receive bufsize %d ",itmp,sizeof(int));
X			getsockopt(ts,SOL_SOCKET,SO_TYPE,(char *)&itmp,sizeof(int));
X			printf("type %d \n",itmp,sizeof(int));
X			puts("");
X		}
X#endif
X
X		if(connect(ts,(struct sockaddr *)&sin,sizeof(sin)) < 0)
X		{
X#if defined(BSD43)
X			if(he && he->h_addr_list[1])
X			{
X				he->h_addr_list++;
X				bcopy(he->h_addr_list[0],(caddr_t)&sin.sin_addr,he->h_length);
X				close(ts);
X				continue;
X			}
X#endif
X			perror("connect()");
X			hangup(129);
X		}
X		connected++;
X	}	while(connected == 0);
X
X#if defined(DEBUG)
X	if(debug)
X		printf("connected to telnet at %s\n\n",hostname);
X#endif
X
X	do_use(TELOPT_SGA);
X	will_use(TELOPT_TTYPE);
X
X	application();
X
X	hangup(0);
X}	/* end of main */
X
X/* vi: set tabstop=4 shiftwidth=4: */
X/* end of teleplay.c */
SHAR_EOF
chmod 0644 teleplay.c || echo "restore of teleplay.c fails"
fi
if test -f teleplay.log; then echo "File teleplay.log exists"; else
sed 's/^X//' << 'SHAR_EOF' > teleplay.log &&
Xgethostbyname success: tridom
Xhostent @ 00016a30 name: pyramid family: INTERNET address: c0 01 01 02
X
Xgetservbyname success: telnet/tcp
Xservent @ 00016900 name: telnet port: 0x00000017 protocol: tcp
X
Xsocket id 3
Xsend bufsize 8192 receive bufsize 8192 type 1 
X
Xconnected to telnet at tridom
X
X> we say DO SGA
X> we say WILL TTYPE
Xremote said DO TTYPE
Xremote said WILL SGA
X> subnegotiate: our ttype ANSI43
Xremote said WILL ECHO
Xremote said DO ECHO
X
X
X4.3 BSD UNIX (tridom)
X
Xlogin: wht
XPassword:
XLast login: Sun Jul 16 20:34:25 on ttyp1
XTERM = (ansi43) dumb
Xwht logged in Sun 07-16-1989 20:35:11 EDT (julian 89197, UTC 00:35:11)
Xpyr_wht /u3/sd/wht % ps -au
XUSER       PID %CPU %MEM   SZ  RSS TTY STAT  TIME COMMAND
Xwht      12833 12.2  0.8  188   66 p1  S     0:02 -tcsh (tcsh)
Xwht      12830  3.4  1.0  130   80 i29 S     0:00 teleplay
Xwht      12841  2.3  1.0  158   86 p1  R     0:00 ps -au
Xwht      12831  0.1  0.2   16   12 i29 S     0:00 tee teleplay.log
Xcma      24734  0.0  0.8   86   70 i14 I     0:01 less build/mux_test.smap
Xpyr_wht /u3/sd/wht % 
SHAR_EOF
chmod 0644 teleplay.log || echo "restore of teleplay.log fails"
fi
if test -f MANIFEST; then echo "File MANIFEST exists"; else
sed 's/^X//' << 'SHAR_EOF' > MANIFEST &&
XREADME
XMakefile
Xapply.c
Xhexdump.c
Xteleplay.c
Xteleplay.log
XMANIFEST
SHAR_EOF
chmod 0644 MANIFEST || echo "restore of MANIFEST fails"
fi
exit 0