xref: /csrg-svn/usr.bin/telnet/commands.c (revision 38689)
133685Sbostic /*
233685Sbostic  * Copyright (c) 1988 Regents of the University of California.
333685Sbostic  * All rights reserved.
433685Sbostic  *
533685Sbostic  * Redistribution and use in source and binary forms are permitted
634898Sbostic  * provided that the above copyright notice and this paragraph are
734898Sbostic  * duplicated in all such forms and that any documentation,
834898Sbostic  * advertising materials, and other materials related to such
934898Sbostic  * distribution and use acknowledge that the software was developed
1034898Sbostic  * by the University of California, Berkeley.  The name of the
1134898Sbostic  * University may not be used to endorse or promote products derived
1234898Sbostic  * from this software without specific prior written permission.
1334898Sbostic  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1434898Sbostic  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1534898Sbostic  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1633685Sbostic  */
1733685Sbostic 
1833685Sbostic #ifndef lint
19*38689Sborman static char sccsid[] = "@(#)commands.c	1.19 (Berkeley) 08/21/89";
2033685Sbostic #endif /* not lint */
2133685Sbostic 
2232144Sminshall #include <sys/types.h>
2336274Sminshall #if	defined(unix)
2436274Sminshall #include <sys/file.h>
2536274Sminshall #endif	/* defined(unix) */
2632144Sminshall #include <sys/socket.h>
2732144Sminshall #include <netinet/in.h>
28*38689Sborman #ifdef	CRAY
29*38689Sborman #include <sys/fcntl.h>
30*38689Sborman #endif	CRAY
3132144Sminshall 
3232144Sminshall #include <signal.h>
3332144Sminshall #include <netdb.h>
3432144Sminshall #include <ctype.h>
3535298Sminshall #include <varargs.h>
3632144Sminshall 
3732144Sminshall #include <arpa/telnet.h>
3832144Sminshall 
3934305Sminshall #include "general.h"
4034305Sminshall 
4132381Sminshall #include "ring.h"
4232381Sminshall 
4332144Sminshall #include "externs.h"
4432144Sminshall #include "defines.h"
4532144Sminshall #include "types.h"
4632144Sminshall 
47*38689Sborman #ifdef	SRCRT
48*38689Sborman #if	!defined(CRAY)
49*38689Sborman #include <netinet/in_systm.h>
50*38689Sborman #if	!defined(sun)
51*38689Sborman #include <machine/endian.h>
52*38689Sborman #endif
53*38689Sborman #endif
54*38689Sborman #include <netinet/ip.h>
55*38689Sborman #endif
56*38689Sborman 
57*38689Sborman 
5832144Sminshall char	*hostname;
59*38689Sborman extern char *getenv();
6032144Sminshall 
6136180Sminshall #define Ambiguous(s)	((char **)s == &ambiguous)
6232144Sminshall static char *ambiguous;		/* special return value for command routines */
6332144Sminshall 
6432144Sminshall typedef struct {
6532144Sminshall 	char	*name;		/* command name */
66*38689Sborman 	char	*help;		/* help string (NULL for no help) */
6732144Sminshall 	int	(*handler)();	/* routine which executes command */
6832144Sminshall 	int	needconnect;	/* Do we need to be connected to execute? */
6932144Sminshall } Command;
7032144Sminshall 
71*38689Sborman static char line[256];
72*38689Sborman static char saveline[256];
7332144Sminshall static int margc;
7432144Sminshall static char *margv[20];
7532144Sminshall 
7632144Sminshall /*
7732144Sminshall  * Various utility routines.
7832144Sminshall  */
7932144Sminshall 
8036180Sminshall #if	!defined(BSD) || (BSD <= 43)
8136180Sminshall 
8236180Sminshall char	*h_errlist[] = {
8336180Sminshall 	"Error 0",
8436180Sminshall 	"Unknown host",				/* 1 HOST_NOT_FOUND */
8536180Sminshall 	"Host name lookup failure",		/* 2 TRY_AGAIN */
8636180Sminshall 	"Unknown server error",			/* 3 NO_RECOVERY */
8736180Sminshall 	"No address associated with name",	/* 4 NO_ADDRESS */
8836180Sminshall };
8936180Sminshall int	h_nerr = { sizeof(h_errlist)/sizeof(h_errlist[0]) };
9036180Sminshall 
9136274Sminshall int h_errno;		/* In some version of SunOS this is necessary */
9236180Sminshall 
9336180Sminshall /*
9436180Sminshall  * herror --
9536180Sminshall  *	print the error indicated by the h_errno value.
9636180Sminshall  */
9736180Sminshall herror(s)
9836180Sminshall 	char *s;
9936180Sminshall {
10036180Sminshall 	if (s && *s) {
10136180Sminshall 		fprintf(stderr, "%s: ", s);
10236180Sminshall 	}
10336180Sminshall 	if ((h_errno < 0) || (h_errno >= h_nerr)) {
10436180Sminshall 		fprintf(stderr, "Unknown error\n");
10536274Sminshall 	} else if (h_errno == 0) {
10636274Sminshall #if	defined(sun)
10736274Sminshall 		fprintf(stderr, "Host unknown\n");
10836274Sminshall #endif	/* defined(sun) */
10936180Sminshall 	} else {
11036180Sminshall 		fprintf(stderr, "%s\n", h_errlist[h_errno]);
11136180Sminshall 	}
11236180Sminshall }
11336180Sminshall #endif	/* !define(BSD) || (BSD <= 43) */
11436180Sminshall 
11532144Sminshall static void
11632144Sminshall makeargv()
11732144Sminshall {
11832144Sminshall     register char *cp;
11932144Sminshall     register char **argp = margv;
12032144Sminshall 
12132144Sminshall     margc = 0;
12232144Sminshall     cp = line;
12332144Sminshall     if (*cp == '!') {		/* Special case shell escape */
124*38689Sborman 	strcpy(saveline, line);	/* save for shell command */
12532144Sminshall 	*argp++ = "!";		/* No room in string to get this */
12632144Sminshall 	margc++;
12732144Sminshall 	cp++;
12832144Sminshall     }
12932144Sminshall     while (*cp) {
13032144Sminshall 	while (isspace(*cp))
13132144Sminshall 	    cp++;
13232144Sminshall 	if (*cp == '\0')
13332144Sminshall 	    break;
13432144Sminshall 	*argp++ = cp;
13532144Sminshall 	margc += 1;
13632144Sminshall 	while (*cp != '\0' && !isspace(*cp))
13732144Sminshall 	    cp++;
13832144Sminshall 	if (*cp == '\0')
13932144Sminshall 	    break;
14032144Sminshall 	*cp++ = '\0';
14132144Sminshall     }
14232144Sminshall     *argp++ = 0;
14332144Sminshall }
14432144Sminshall 
14532144Sminshall 
14632144Sminshall static char **
14732144Sminshall genget(name, table, next)
14832144Sminshall char	*name;		/* name to match */
14932144Sminshall char	**table;		/* name entry in table */
15032144Sminshall char	**(*next)();	/* routine to return next entry in table */
15132144Sminshall {
15232144Sminshall 	register char *p, *q;
15332144Sminshall 	register char **c, **found;
15432144Sminshall 	register int nmatches, longest;
15532144Sminshall 
15632144Sminshall 	if (name == 0) {
15732144Sminshall 	    return 0;
15832144Sminshall 	}
15932144Sminshall 	longest = 0;
16032144Sminshall 	nmatches = 0;
16132144Sminshall 	found = 0;
16232144Sminshall 	for (c = table; (p = *c) != 0; c = (*next)(c)) {
16332144Sminshall 		for (q = name;
16432144Sminshall 		    (*q == *p) || (isupper(*q) && tolower(*q) == *p); p++, q++)
16532144Sminshall 			if (*q == 0)		/* exact match? */
16632144Sminshall 				return (c);
16732144Sminshall 		if (!*q) {			/* the name was a prefix */
16832144Sminshall 			if (q - name > longest) {
16932144Sminshall 				longest = q - name;
17032144Sminshall 				nmatches = 1;
17132144Sminshall 				found = c;
17232144Sminshall 			} else if (q - name == longest)
17332144Sminshall 				nmatches++;
17432144Sminshall 		}
17532144Sminshall 	}
17632144Sminshall 	if (nmatches > 1)
17736180Sminshall 		return &ambiguous;
17832144Sminshall 	return (found);
17932144Sminshall }
18032144Sminshall 
18132144Sminshall /*
18232144Sminshall  * Make a character string into a number.
18332144Sminshall  *
18432144Sminshall  * Todo:  1.  Could take random integers (12, 0x12, 012, 0b1).
18532144Sminshall  */
18632144Sminshall 
18732144Sminshall static
18832144Sminshall special(s)
18932144Sminshall register char *s;
19032144Sminshall {
19132144Sminshall 	register char c;
19232144Sminshall 	char b;
19332144Sminshall 
19432144Sminshall 	switch (*s) {
19532144Sminshall 	case '^':
19632144Sminshall 		b = *++s;
19732144Sminshall 		if (b == '?') {
19832144Sminshall 		    c = b | 0x40;		/* DEL */
19932144Sminshall 		} else {
20032144Sminshall 		    c = b & 0x1f;
20132144Sminshall 		}
20232144Sminshall 		break;
20332144Sminshall 	default:
20432144Sminshall 		c = *s;
20532144Sminshall 		break;
20632144Sminshall 	}
20732144Sminshall 	return c;
20832144Sminshall }
20932144Sminshall 
21032144Sminshall /*
21132144Sminshall  * Construct a control character sequence
21232144Sminshall  * for a special character.
21332144Sminshall  */
21432144Sminshall static char *
21532144Sminshall control(c)
21632144Sminshall 	register int c;
21732144Sminshall {
21832144Sminshall 	static char buf[3];
21932144Sminshall 
22032144Sminshall 	if (c == 0x7f)
22132144Sminshall 		return ("^?");
22232144Sminshall 	if (c == '\377') {
22332144Sminshall 		return "off";
22432144Sminshall 	}
22532144Sminshall 	if (c >= 0x20) {
22632144Sminshall 		buf[0] = c;
22732144Sminshall 		buf[1] = 0;
22832144Sminshall 	} else {
22932144Sminshall 		buf[0] = '^';
23032144Sminshall 		buf[1] = '@'+c;
23132144Sminshall 		buf[2] = 0;
23232144Sminshall 	}
23332144Sminshall 	return (buf);
23432144Sminshall }
23532144Sminshall 
23632144Sminshall 
23732144Sminshall 
23832144Sminshall /*
23932144Sminshall  *	The following are data structures and routines for
24032144Sminshall  *	the "send" command.
24132144Sminshall  *
24232144Sminshall  */
24332144Sminshall 
24432144Sminshall struct sendlist {
24532144Sminshall     char	*name;		/* How user refers to it (case independent) */
24632144Sminshall     char	*help;		/* Help information (0 ==> no help) */
24732144Sminshall #if	defined(NOT43)
248*38689Sborman     int		(*handler)();	/* Routine to perform (for special ops) */
24932144Sminshall #else	/* defined(NOT43) */
250*38689Sborman     void	(*handler)();	/* Routine to perform (for special ops) */
25132144Sminshall #endif	/* defined(NOT43) */
252*38689Sborman     int		what;		/* Character to be sent (<0 ==> special) */
25332144Sminshall };
25432144Sminshall 
25532144Sminshall #define	SENDQUESTION	-1
25632144Sminshall #define	SENDESCAPE	-3
25732144Sminshall 
25832144Sminshall static struct sendlist Sendlist[] = {
259*38689Sborman     { "ao",	"Send Telnet Abort output",		0,	AO },
260*38689Sborman     { "ayt",	"Send Telnet 'Are You There'",		0,	AYT },
261*38689Sborman     { "brk",	"Send Telnet Break",			0,	BREAK },
262*38689Sborman     { "ec",	"Send Telnet Erase Character",		0,	EC },
263*38689Sborman     { "el",	"Send Telnet Erase Line",		0,	EL },
264*38689Sborman     { "escape",	"Send current escape character",	0,	SENDESCAPE },
265*38689Sborman     { "ga",	"Send Telnet 'Go Ahead' sequence",	0,	GA },
266*38689Sborman     { "ip",	"Send Telnet Interrupt Process",	0,	IP },
267*38689Sborman     { "nop",	"Send Telnet 'No operation'",		0,	NOP },
268*38689Sborman     { "eor",	"Send Telnet 'End of Record'",		0,	EOR },
269*38689Sborman     { "abort",	"Send Telnet 'Abort Process'",		0,	ABORT },
270*38689Sborman     { "susp",	"Send Telnet 'Suspend Process'",	0,	SUSP },
271*38689Sborman     { "eof",	"Send Telnet End of File Character",	0,	xEOF },
272*38689Sborman     { "synch",	"Perform Telnet 'Synch operation'",	dosynch, SYNCH },
273*38689Sborman     { "?",	"Display send options",			0,	SENDQUESTION },
27432144Sminshall     { 0 }
27532144Sminshall };
27632144Sminshall 
27732144Sminshall static struct sendlist Sendlist2[] = {		/* some synonyms */
278*38689Sborman     { "break",		0, 0, BREAK },
27932144Sminshall 
280*38689Sborman     { "intp",		0, 0, IP },
281*38689Sborman     { "interrupt",	0, 0, IP },
282*38689Sborman     { "intr",		0, 0, IP },
28332144Sminshall 
284*38689Sborman     { "help",		0, 0, SENDQUESTION },
28532144Sminshall 
286*38689Sborman     { 0 }
28732144Sminshall };
28832144Sminshall 
28932144Sminshall static char **
29032144Sminshall getnextsend(name)
29132144Sminshall char *name;
29232144Sminshall {
29332144Sminshall     struct sendlist *c = (struct sendlist *) name;
29432144Sminshall 
29532144Sminshall     return (char **) (c+1);
29632144Sminshall }
29732144Sminshall 
29832144Sminshall static struct sendlist *
29932144Sminshall getsend(name)
30032144Sminshall char *name;
30132144Sminshall {
30232144Sminshall     struct sendlist *sl;
30332144Sminshall 
30432144Sminshall     if ((sl = (struct sendlist *)
30532144Sminshall 			genget(name, (char **) Sendlist, getnextsend)) != 0) {
30632144Sminshall 	return sl;
30732144Sminshall     } else {
30832144Sminshall 	return (struct sendlist *)
30932144Sminshall 				genget(name, (char **) Sendlist2, getnextsend);
31032144Sminshall     }
31132144Sminshall }
31232144Sminshall 
31332144Sminshall static
31432144Sminshall sendcmd(argc, argv)
31532144Sminshall int	argc;
31632144Sminshall char	**argv;
31732144Sminshall {
31832144Sminshall     int what;		/* what we are sending this time */
31932144Sminshall     int count;		/* how many bytes we are going to need to send */
32032144Sminshall     int i;
32132144Sminshall     int question = 0;	/* was at least one argument a question */
32232144Sminshall     struct sendlist *s;	/* pointer to current command */
32332144Sminshall 
32432144Sminshall     if (argc < 2) {
32532144Sminshall 	printf("need at least one argument for 'send' command\n");
32632144Sminshall 	printf("'send ?' for help\n");
32732144Sminshall 	return 0;
32832144Sminshall     }
32932144Sminshall     /*
33032144Sminshall      * First, validate all the send arguments.
33132144Sminshall      * In addition, we see how much space we are going to need, and
33232144Sminshall      * whether or not we will be doing a "SYNCH" operation (which
33332144Sminshall      * flushes the network queue).
33432144Sminshall      */
33532144Sminshall     count = 0;
33632144Sminshall     for (i = 1; i < argc; i++) {
33732144Sminshall 	s = getsend(argv[i]);
33832144Sminshall 	if (s == 0) {
33932144Sminshall 	    printf("Unknown send argument '%s'\n'send ?' for help.\n",
34032144Sminshall 			argv[i]);
34132144Sminshall 	    return 0;
34232144Sminshall 	} else if (Ambiguous(s)) {
34332144Sminshall 	    printf("Ambiguous send argument '%s'\n'send ?' for help.\n",
34432144Sminshall 			argv[i]);
34532144Sminshall 	    return 0;
34632144Sminshall 	}
34732144Sminshall 	switch (s->what) {
34832144Sminshall 	case SENDQUESTION:
349*38689Sborman 	    question = 1;
35032144Sminshall 	    break;
35132144Sminshall 	case SENDESCAPE:
35232144Sminshall 	    count += 1;
35332144Sminshall 	    break;
35432144Sminshall 	case SYNCH:
35532144Sminshall 	    count += 2;
35632144Sminshall 	    break;
35732144Sminshall 	default:
35832144Sminshall 	    count += 2;
35932144Sminshall 	    break;
36032144Sminshall 	}
36132144Sminshall     }
362*38689Sborman     if (!connected) {
363*38689Sborman 	if (count)
364*38689Sborman 	    printf("?Need to be connected first.\n");
365*38689Sborman 	if (question) {
366*38689Sborman 	    for (s = Sendlist; s->name; s++)
367*38689Sborman 		if (s->help)
368*38689Sborman 		    printf("%-15s %s\n", s->name, s->help);
369*38689Sborman 	} else
370*38689Sborman 	    printf("'send ?' for help\n");
371*38689Sborman 	return !question;
372*38689Sborman     }
37332144Sminshall     /* Now, do we have enough room? */
37432144Sminshall     if (NETROOM() < count) {
37532144Sminshall 	printf("There is not enough room in the buffer TO the network\n");
37632144Sminshall 	printf("to process your request.  Nothing will be done.\n");
37732144Sminshall 	printf("('send synch' will throw away most data in the network\n");
37832144Sminshall 	printf("buffer, if this might help.)\n");
37932144Sminshall 	return 0;
38032144Sminshall     }
38132144Sminshall     /* OK, they are all OK, now go through again and actually send */
38232144Sminshall     for (i = 1; i < argc; i++) {
38332144Sminshall 	if ((s = getsend(argv[i])) == 0) {
38432144Sminshall 	    fprintf(stderr, "Telnet 'send' error - argument disappeared!\n");
38532144Sminshall 	    quit();
38632144Sminshall 	    /*NOTREACHED*/
38732144Sminshall 	}
388*38689Sborman 	if (s->handler) {
389*38689Sborman 	    (*s->handler)(s);
39032144Sminshall 	} else {
39132144Sminshall 	    switch (what = s->what) {
39232144Sminshall 	    case SYNCH:
39332144Sminshall 		dosynch();
39432144Sminshall 		break;
39532144Sminshall 	    case SENDQUESTION:
39632144Sminshall 		for (s = Sendlist; s->name; s++) {
397*38689Sborman 		    if (s->help)
398*38689Sborman 			printf("%-15s %s\n", s->name, s->help);
39932144Sminshall 		}
40032144Sminshall 		question = 1;
40132144Sminshall 		break;
40232144Sminshall 	    case SENDESCAPE:
40332144Sminshall 		NETADD(escape);
40432144Sminshall 		break;
40532144Sminshall 	    default:
40632144Sminshall 		NET2ADD(IAC, what);
40732144Sminshall 		break;
40832144Sminshall 	    }
40932144Sminshall 	}
41032144Sminshall     }
41132144Sminshall     return !question;
41232144Sminshall }
41332144Sminshall 
41432144Sminshall /*
41532144Sminshall  * The following are the routines and data structures referred
41632144Sminshall  * to by the arguments to the "toggle" command.
41732144Sminshall  */
41832144Sminshall 
41932144Sminshall static
42032144Sminshall lclchars()
42132144Sminshall {
42232144Sminshall     donelclchars = 1;
42332144Sminshall     return 1;
42432144Sminshall }
42532144Sminshall 
42632144Sminshall static
42732144Sminshall togdebug()
42832144Sminshall {
42932144Sminshall #ifndef	NOT43
43032144Sminshall     if (net > 0 &&
43132144Sminshall 	(SetSockOpt(net, SOL_SOCKET, SO_DEBUG, debug)) < 0) {
43232144Sminshall 	    perror("setsockopt (SO_DEBUG)");
43332144Sminshall     }
43432144Sminshall #else	/* NOT43 */
43532144Sminshall     if (debug) {
43632144Sminshall 	if (net > 0 && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 0, 0) < 0)
43732144Sminshall 	    perror("setsockopt (SO_DEBUG)");
43832144Sminshall     } else
43932144Sminshall 	printf("Cannot turn off socket debugging\n");
44032144Sminshall #endif	/* NOT43 */
44132144Sminshall     return 1;
44232144Sminshall }
44332144Sminshall 
44432144Sminshall 
44532144Sminshall static int
44632144Sminshall togcrlf()
44732144Sminshall {
44832144Sminshall     if (crlf) {
44932144Sminshall 	printf("Will send carriage returns as telnet <CR><LF>.\n");
45032144Sminshall     } else {
45132144Sminshall 	printf("Will send carriage returns as telnet <CR><NUL>.\n");
45232144Sminshall     }
45332144Sminshall     return 1;
45432144Sminshall }
45532144Sminshall 
45632144Sminshall 
45732144Sminshall static int
458*38689Sborman togbinary(val)
459*38689Sborman int val;
46032144Sminshall {
46132144Sminshall     donebinarytoggle = 1;
46232144Sminshall 
463*38689Sborman     if (my_want_state_is_will(TELOPT_BINARY) ||
464*38689Sborman 	my_want_state_is_do(TELOPT_BINARY)) {
465*38689Sborman 	if (val == 1)
466*38689Sborman 	    printf("Already operating in binary mode with remote host.\n");
467*38689Sborman 	else {
468*38689Sborman 	    /* leave binary mode */
469*38689Sborman 	    printf("Negotiating network ascii mode with remote host.\n");
470*38689Sborman 	    tel_leave_binary();
471*38689Sborman 	}
47237226Sminshall     } else {				/* Turn off binary mode */
473*38689Sborman 	if (val == 0)
474*38689Sborman 	    printf("Already in network ascii mode with remote host.\n");
475*38689Sborman 	else {
476*38689Sborman 	    printf("Negotiating binary mode with remote host.\n");
477*38689Sborman 	    tel_enter_binary();
478*38689Sborman 	}
47932144Sminshall     }
48032144Sminshall     return 1;
48132144Sminshall }
48232144Sminshall 
48332144Sminshall 
48432144Sminshall 
48532144Sminshall extern int togglehelp();
486*38689Sborman extern int slc_check();
48732144Sminshall 
48832144Sminshall struct togglelist {
48932144Sminshall     char	*name;		/* name of toggle */
49032144Sminshall     char	*help;		/* help message */
49132144Sminshall     int		(*handler)();	/* routine to do actual setting */
49232144Sminshall     int		*variable;
49332144Sminshall     char	*actionexplanation;
49432144Sminshall };
49532144Sminshall 
49632144Sminshall static struct togglelist Togglelist[] = {
49732144Sminshall     { "autoflush",
498*38689Sborman 	"flushing of output when sending interrupt characters",
49932144Sminshall 	    0,
500*38689Sborman 		&autoflush,
501*38689Sborman 		    "flush output when sending interrupt characters" },
50232144Sminshall     { "autosynch",
503*38689Sborman 	"automatic sending of interrupt characters in urgent mode",
50432144Sminshall 	    0,
505*38689Sborman 		&autosynch,
506*38689Sborman 		    "send interrupt characters in urgent mode" },
50732144Sminshall     { "binary",
508*38689Sborman 	"sending and receiving of binary data",
50932144Sminshall 	    togbinary,
510*38689Sborman 		0,
511*38689Sborman 		    0 },
51232144Sminshall     { "crlf",
513*38689Sborman 	"sending carriage returns as telnet <CR><LF>",
51432144Sminshall 	    togcrlf,
515*38689Sborman 		&crlf,
516*38689Sborman 		    0 },
51732144Sminshall     { "crmod",
518*38689Sborman 	"mapping of received carriage returns",
51932144Sminshall 	    0,
520*38689Sborman 		&crmod,
521*38689Sborman 		    "map carriage return on output" },
52232144Sminshall     { "localchars",
523*38689Sborman 	"local recognition of certain control characters",
52432144Sminshall 	    lclchars,
525*38689Sborman 		&localchars,
526*38689Sborman 		    "recognize certain control characters" },
527*38689Sborman     { " ", "", 0 },		/* empty line */
52838208Sminshall #if	defined(unix) && defined(TN3270)
52938208Sminshall     { "cursesdata",
53038208Sminshall 	"(debugging) toggle printing of hexadecimal curses data",
53138208Sminshall 	    0,
532*38689Sborman 		&cursesdata,
533*38689Sborman 		    "print hexadecimal representation of curses data" },
53438208Sminshall #endif	/* defined(unix) && defined(TN3270) */
53532144Sminshall     { "debug",
536*38689Sborman 	"debugging",
53732144Sminshall 	    togdebug,
538*38689Sborman 		&debug,
539*38689Sborman 		    "turn on socket level debugging" },
54032144Sminshall     { "netdata",
541*38689Sborman 	"printing of hexadecimal network data (debugging)",
54232144Sminshall 	    0,
543*38689Sborman 		&netdata,
544*38689Sborman 		    "print hexadecimal representation of network traffic" },
545*38689Sborman     { "prettydump",
546*38689Sborman 	"output of \"netdata\" to user readable format (debugging)",
547*38689Sborman 	    0,
548*38689Sborman 		&prettydump,
549*38689Sborman 		    "print user readable output for \"netdata\"" },
55032144Sminshall     { "options",
551*38689Sborman 	"viewing of options processing (debugging)",
55232144Sminshall 	    0,
553*38689Sborman 		&showoptions,
554*38689Sborman 		    "show option processing" },
55538208Sminshall #if	defined(unix)
55638208Sminshall     { "termdata",
55738208Sminshall 	"(debugging) toggle printing of hexadecimal terminal data",
55838208Sminshall 	    0,
559*38689Sborman 		&termdata,
560*38689Sborman 		    "print hexadecimal representation of terminal traffic" },
56138208Sminshall #endif	/* defined(unix) */
56232144Sminshall     { "?",
563*38689Sborman 	0,
564*38689Sborman 	    togglehelp },
56532144Sminshall     { "help",
566*38689Sborman 	0,
567*38689Sborman 	    togglehelp },
56832144Sminshall     { 0 }
56932144Sminshall };
57032144Sminshall 
57132144Sminshall static
57232144Sminshall togglehelp()
57332144Sminshall {
57432144Sminshall     struct togglelist *c;
57532144Sminshall 
57632144Sminshall     for (c = Togglelist; c->name; c++) {
577*38689Sborman 	if (c->help) {
578*38689Sborman 	    if (*c->help)
579*38689Sborman 		printf("%-15s toggle %s\n", c->name, c->help);
580*38689Sborman 	    else
581*38689Sborman 		printf("\n");
58232144Sminshall 	}
58332144Sminshall     }
584*38689Sborman     printf("\n");
585*38689Sborman     printf("%-15s %s\n", "?", "display help information");
58632144Sminshall     return 0;
58732144Sminshall }
58832144Sminshall 
589*38689Sborman static
590*38689Sborman settogglehelp(set)
591*38689Sborman int set;
592*38689Sborman {
593*38689Sborman     struct togglelist *c;
594*38689Sborman 
595*38689Sborman     for (c = Togglelist; c->name; c++) {
596*38689Sborman 	if (c->help) {
597*38689Sborman 	    if (*c->help)
598*38689Sborman 		printf("%-15s %s %s\n", c->name, set ? "enable" : "disable",
599*38689Sborman 						c->help);
600*38689Sborman 	    else
601*38689Sborman 		printf("\n");
602*38689Sborman 	}
603*38689Sborman     }
604*38689Sborman }
605*38689Sborman 
60632144Sminshall static char **
60732144Sminshall getnexttoggle(name)
60832144Sminshall char *name;
60932144Sminshall {
61032144Sminshall     struct togglelist *c = (struct togglelist *) name;
61132144Sminshall 
61232144Sminshall     return (char **) (c+1);
61332144Sminshall }
61432144Sminshall 
61532144Sminshall static struct togglelist *
61632144Sminshall gettoggle(name)
61732144Sminshall char *name;
61832144Sminshall {
61932144Sminshall     return (struct togglelist *)
62032144Sminshall 			genget(name, (char **) Togglelist, getnexttoggle);
62132144Sminshall }
62232144Sminshall 
62332144Sminshall static
62432144Sminshall toggle(argc, argv)
62532144Sminshall int	argc;
62632144Sminshall char	*argv[];
62732144Sminshall {
62832144Sminshall     int retval = 1;
62932144Sminshall     char *name;
63032144Sminshall     struct togglelist *c;
63132144Sminshall 
63232144Sminshall     if (argc < 2) {
63332144Sminshall 	fprintf(stderr,
63432144Sminshall 	    "Need an argument to 'toggle' command.  'toggle ?' for help.\n");
63532144Sminshall 	return 0;
63632144Sminshall     }
63732144Sminshall     argc--;
63832144Sminshall     argv++;
63932144Sminshall     while (argc--) {
64032144Sminshall 	name = *argv++;
64132144Sminshall 	c = gettoggle(name);
64232144Sminshall 	if (Ambiguous(c)) {
64332144Sminshall 	    fprintf(stderr, "'%s': ambiguous argument ('toggle ?' for help).\n",
64432144Sminshall 					name);
64532144Sminshall 	    return 0;
64632144Sminshall 	} else if (c == 0) {
64732144Sminshall 	    fprintf(stderr, "'%s': unknown argument ('toggle ?' for help).\n",
64832144Sminshall 					name);
64932144Sminshall 	    return 0;
65032144Sminshall 	} else {
65132144Sminshall 	    if (c->variable) {
65232144Sminshall 		*c->variable = !*c->variable;		/* invert it */
65332144Sminshall 		if (c->actionexplanation) {
65432144Sminshall 		    printf("%s %s.\n", *c->variable? "Will" : "Won't",
65532144Sminshall 							c->actionexplanation);
65632144Sminshall 		}
65732144Sminshall 	    }
65832144Sminshall 	    if (c->handler) {
659*38689Sborman 		retval &= (*c->handler)(-1);
66032144Sminshall 	    }
66132144Sminshall 	}
66232144Sminshall     }
66332144Sminshall     return retval;
66432144Sminshall }
66532144Sminshall 
66632144Sminshall /*
66732144Sminshall  * The following perform the "set" command.
66832144Sminshall  */
66932144Sminshall 
670*38689Sborman #ifdef	USE_TERMIO
671*38689Sborman struct termio new_tc = { 0 };
672*38689Sborman #endif
673*38689Sborman 
67432144Sminshall struct setlist {
67532144Sminshall     char *name;				/* name */
67632144Sminshall     char *help;				/* help information */
677*38689Sborman     void (*handler)();
67832144Sminshall     char *charp;			/* where it is located at */
67932144Sminshall };
68032144Sminshall 
68132144Sminshall static struct setlist Setlist[] = {
682*38689Sborman     { "echo", 	"character to toggle local echoing on/off", 0, &echoc },
683*38689Sborman     { "escape",	"character to escape back to telnet command mode", 0, &escape },
684*38689Sborman     { "tracefile", "file to write trace intormation to", SetNetTrace, NetTraceFile},
68532144Sminshall     { " ", "" },
686*38689Sborman     { " ", "The following need 'localchars' to be toggled true", 0, 0 },
687*38689Sborman #ifndef	CRAY
688*38689Sborman     { "flushoutput", "character to cause an Abort Oubput", 0, termFlushCharp },
689*38689Sborman #endif
690*38689Sborman     { "interrupt", "character to cause an Interrupt Process", 0, termIntCharp },
691*38689Sborman     { "quit",	"character to cause an Abort process", 0, termQuitCharp },
692*38689Sborman     { "eof",	"character to cause an EOF ", 0, termEofCharp },
693*38689Sborman     { " ", "" },
694*38689Sborman     { " ", "The following are for local editing in linemode", 0, 0 },
695*38689Sborman     { "erase",	"character to use to erase a character", 0, termEraseCharp },
696*38689Sborman     { "kill",	"character to use to erase a line", 0, termKillCharp },
697*38689Sborman #ifndef	CRAY
698*38689Sborman     { "lnext",	"character to use for literal next", 0, termLiteralNextCharp },
699*38689Sborman     { "susp",	"character to cuase a Suspend Process", 0, termSuspCharp },
700*38689Sborman     { "reprint", "character to use for line reprint", 0, termRprntCharp },
701*38689Sborman     { "worderase", "character to use to erase a word", 0, termWerasCharp },
702*38689Sborman     { "start",	"character to use for XON", 0, termStartCharp },
703*38689Sborman     { "stop",	"character to sue for XOFF", 0, termStopCharp },
704*38689Sborman #endif
70532144Sminshall     { 0 }
70632144Sminshall };
70732144Sminshall 
708*38689Sborman #ifdef	CRAY
709*38689Sborman /* Work around compiler bug */
710*38689Sborman _setlist_init()
711*38689Sborman {
712*38689Sborman 	Setlist[6].charp = &termIntChar;
713*38689Sborman 	Setlist[7].charp = &termQuitChar;
714*38689Sborman 	Setlist[8].charp = &termEofChar;
715*38689Sborman 	Setlist[11].charp = &termEraseChar;
716*38689Sborman 	Setlist[12].charp = &termKillChar;
717*38689Sborman }
718*38689Sborman #endif	CRAY
719*38689Sborman 
72032144Sminshall static char **
72132144Sminshall getnextset(name)
72232144Sminshall char *name;
72332144Sminshall {
72432144Sminshall     struct setlist *c = (struct setlist *)name;
72532144Sminshall 
72632144Sminshall     return (char **) (c+1);
72732144Sminshall }
72832144Sminshall 
72932144Sminshall static struct setlist *
73032144Sminshall getset(name)
73132144Sminshall char *name;
73232144Sminshall {
73332144Sminshall     return (struct setlist *) genget(name, (char **) Setlist, getnextset);
73432144Sminshall }
73532144Sminshall 
73632144Sminshall static
73732144Sminshall setcmd(argc, argv)
73832144Sminshall int	argc;
73932144Sminshall char	*argv[];
74032144Sminshall {
74132144Sminshall     int value;
74232144Sminshall     struct setlist *ct;
743*38689Sborman     struct togglelist *c;
74432144Sminshall 
745*38689Sborman     if (argc < 2 || argc > 3) {
746*38689Sborman 	printf("Format is 'set Name Value'\n'set ?' for help.\n");
74732144Sminshall 	return 0;
74832144Sminshall     }
749*38689Sborman     if ((argc == 2) &&
750*38689Sborman 		((!strcmp(argv[1], "?")) || (!strcmp(argv[1], "help")))) {
751*38689Sborman 	for (ct = Setlist; ct->name; ct++)
752*38689Sborman 	    printf("%-15s %s\n", ct->name, ct->help);
753*38689Sborman 	printf("\n");
754*38689Sborman 	settogglehelp(1);
755*38689Sborman 	printf("%-15s %s\n", "?", "display help information");
756*38689Sborman 	return 0;
757*38689Sborman     }
75832144Sminshall 
75932144Sminshall     ct = getset(argv[1]);
76032144Sminshall     if (ct == 0) {
761*38689Sborman 	c = gettoggle(argv[1]);
762*38689Sborman 	if (c == 0) {
763*38689Sborman 	    fprintf(stderr, "'%s': unknown argument ('set ?' for help).\n",
76432144Sminshall 			argv[1]);
765*38689Sborman 	    return 0;
766*38689Sborman 	} else if (Ambiguous(c)) {
767*38689Sborman 	    fprintf(stderr, "'%s': ambiguous argument ('set ?' for help).\n",
768*38689Sborman 			argv[1]);
769*38689Sborman 	    return 0;
770*38689Sborman 	}
771*38689Sborman 	if (c->variable) {
772*38689Sborman 	    if ((argc == 2) || (strcmp("on", argv[2]) == 0))
773*38689Sborman 		*c->variable = 1;
774*38689Sborman 	    else if (strcmp("off", argv[2]) == 0)
775*38689Sborman 		*c->variable = 0;
776*38689Sborman 	    else {
777*38689Sborman 		printf("Format is 'set togglename [on|off]'\n'set ?' for help.\n");
778*38689Sborman 		return 0;
779*38689Sborman 	    }
780*38689Sborman 	    if (c->actionexplanation) {
781*38689Sborman 		printf("%s %s.\n", *c->variable? "Will" : "Won't",
782*38689Sborman 							c->actionexplanation);
783*38689Sborman 	    }
784*38689Sborman 	}
785*38689Sborman 	if (c->handler)
786*38689Sborman 	    (*c->handler)(1);
787*38689Sborman     } else if (argc != 3) {
788*38689Sborman 	printf("Format is 'set Name Value'\n'set ?' for help.\n");
78932144Sminshall 	return 0;
79032144Sminshall     } else if (Ambiguous(ct)) {
79132144Sminshall 	fprintf(stderr, "'%s': ambiguous argument ('set ?' for help).\n",
79232144Sminshall 			argv[1]);
79332144Sminshall 	return 0;
794*38689Sborman     } else if (ct->handler) {
795*38689Sborman 	(*ct->handler)(argv[2]);
796*38689Sborman 	printf("%s set to \"%s\".\n", ct->name, ct->charp);
79732144Sminshall     } else {
79832144Sminshall 	if (strcmp("off", argv[2])) {
79932144Sminshall 	    value = special(argv[2]);
80032144Sminshall 	} else {
80132144Sminshall 	    value = -1;
80232144Sminshall 	}
80332144Sminshall 	*(ct->charp) = value;
80432144Sminshall 	printf("%s character is '%s'.\n", ct->name, control(*(ct->charp)));
80532144Sminshall     }
806*38689Sborman     slc_check();
80732144Sminshall     return 1;
80832144Sminshall }
809*38689Sborman 
810*38689Sborman static
811*38689Sborman unsetcmd(argc, argv)
812*38689Sborman int	argc;
813*38689Sborman char	*argv[];
814*38689Sborman {
815*38689Sborman     int value;
816*38689Sborman     struct setlist *ct;
817*38689Sborman     struct togglelist *c;
818*38689Sborman     register char *name;
819*38689Sborman 
820*38689Sborman     if (argc < 2) {
821*38689Sborman 	fprintf(stderr,
822*38689Sborman 	    "Need an argument to 'unset' command.  'unset ?' for help.\n");
823*38689Sborman 	return 0;
824*38689Sborman     }
825*38689Sborman     if ((!strcmp(argv[1], "?")) || (!strcmp(argv[1], "help"))) {
826*38689Sborman 	for (ct = Setlist; ct->name; ct++)
827*38689Sborman 	    printf("%-15s %s\n", ct->name, ct->help);
828*38689Sborman 	printf("\n");
829*38689Sborman 	settogglehelp(0);
830*38689Sborman 	printf("%-15s %s\n", "?", "display help information");
831*38689Sborman 	return 0;
832*38689Sborman     }
833*38689Sborman 
834*38689Sborman     argc--;
835*38689Sborman     argv++;
836*38689Sborman     while (argc--) {
837*38689Sborman 	name = *argv++;
838*38689Sborman 	ct = getset(name);
839*38689Sborman 	if (ct == 0) {
840*38689Sborman 	    c = gettoggle(name);
841*38689Sborman 	    if (c == 0) {
842*38689Sborman 		fprintf(stderr, "'%s': unknown argument ('unset ?' for help).\n",
843*38689Sborman 			name);
844*38689Sborman 		return 0;
845*38689Sborman 	    } else if (Ambiguous(c)) {
846*38689Sborman 		fprintf(stderr, "'%s': ambiguous argument ('unset ?' for help).\n",
847*38689Sborman 			name);
848*38689Sborman 		return 0;
849*38689Sborman 	    }
850*38689Sborman 	    if (c->variable) {
851*38689Sborman 		*c->variable = 0;
852*38689Sborman 		if (c->actionexplanation) {
853*38689Sborman 		    printf("%s %s.\n", *c->variable? "Will" : "Won't",
854*38689Sborman 							c->actionexplanation);
855*38689Sborman 		}
856*38689Sborman 	    }
857*38689Sborman 	    if (c->handler)
858*38689Sborman 		(*c->handler)(0);
859*38689Sborman 	} else if (Ambiguous(ct)) {
860*38689Sborman 	    fprintf(stderr, "'%s': ambiguous argument ('unset ?' for help).\n",
861*38689Sborman 			name);
862*38689Sborman 	    return 0;
863*38689Sborman 	} else if (ct->handler) {
864*38689Sborman 	    (*ct->handler)(0);
865*38689Sborman 	    printf("%s reset to \"%s\".\n", ct->name, ct->charp);
866*38689Sborman 	} else {
867*38689Sborman 	    value = -1;
868*38689Sborman 	    *(ct->charp) = -1;
869*38689Sborman 	    printf("%s character is '%s'.\n", ct->name, control(*(ct->charp)));
870*38689Sborman 	}
871*38689Sborman     }
872*38689Sborman     return 1;
873*38689Sborman }
87432144Sminshall 
87532144Sminshall /*
87632144Sminshall  * The following are the data structures and routines for the
87732144Sminshall  * 'mode' command.
87832144Sminshall  */
879*38689Sborman #ifdef	KLUDGELINEMODE
880*38689Sborman extern int kludgelinemode;
881*38689Sborman #endif
88232144Sminshall 
88332144Sminshall static
88432144Sminshall dolinemode()
88532144Sminshall {
886*38689Sborman #ifdef	KLUDGELINEMODE
887*38689Sborman     if (kludgelinemode)
888*38689Sborman 	send_dont(TELOPT_SGA, 1);
889*38689Sborman #endif
890*38689Sborman     send_will(TELOPT_LINEMODE, 1);
891*38689Sborman     send_dont(TELOPT_ECHO, 1);
89232144Sminshall     return 1;
89332144Sminshall }
89432144Sminshall 
89532144Sminshall static
89632144Sminshall docharmode()
89732144Sminshall {
898*38689Sborman #ifdef	KLUDGELINEMODE
899*38689Sborman     if (kludgelinemode)
900*38689Sborman 	send_do(TELOPT_SGA, 1);
901*38689Sborman     else
902*38689Sborman #endif
903*38689Sborman     send_wont(TELOPT_LINEMODE, 1);
904*38689Sborman     send_do(TELOPT_ECHO, 1);
905*38689Sborman     return 1;
906*38689Sborman }
907*38689Sborman 
908*38689Sborman setmode(bit)
909*38689Sborman {
910*38689Sborman     return dolmmode(bit, 1);
911*38689Sborman }
912*38689Sborman 
913*38689Sborman clearmode(bit)
914*38689Sborman {
915*38689Sborman     return dolmmode(bit, 0);
916*38689Sborman }
917*38689Sborman 
918*38689Sborman dolmmode(bit, on)
919*38689Sborman int bit, on;
920*38689Sborman {
921*38689Sborman     char c;
922*38689Sborman     extern int linemode;
923*38689Sborman 
924*38689Sborman     if (my_want_state_is_wont(TELOPT_LINEMODE)) {
925*38689Sborman 	printf("?Need to have LINEMODE option enabled first.\n");
926*38689Sborman 	printf("'mode ?' for help.\n");
927*38689Sborman 	return 0;
92832144Sminshall     }
929*38689Sborman 
930*38689Sborman     if (on)
931*38689Sborman 	c = (linemode | bit);
932*38689Sborman     else
933*38689Sborman 	c = (linemode & ~bit);
934*38689Sborman     lm_mode(&c, 1, 1);
93532144Sminshall     return 1;
93632144Sminshall }
93732144Sminshall 
938*38689Sborman struct modelist {
939*38689Sborman 	char	*name;		/* command name */
940*38689Sborman 	char	*help;		/* help string */
941*38689Sborman 	int	(*handler)();	/* routine which executes command */
942*38689Sborman 	int	needconnect;	/* Do we need to be connected to execute? */
943*38689Sborman 	int	arg1;
944*38689Sborman };
945*38689Sborman 
946*38689Sborman extern int modehelp();
947*38689Sborman 
948*38689Sborman static struct modelist ModeList[] = {
949*38689Sborman     { "character", "Disable LINEMODE option",	docharmode, 1 },
950*38689Sborman #ifdef	KLUDEGLINEMODE
951*38689Sborman     { "",	"(or disable obsolete line-by-line mode)", 0 };
952*38689Sborman #endif
953*38689Sborman     { "line",	"Enable LINEMODE option",	dolinemode, 1 },
954*38689Sborman #ifdef	KLUDEGLINEMODE
955*38689Sborman     { "",	"(or enable obsolete line-by-line mode)", 0 };
956*38689Sborman #endif
957*38689Sborman     { "", "", 0 },
958*38689Sborman     { "",	"These require the LINEMODE option to be enabled", 0 },
959*38689Sborman     { "isig",	"Enable signal trapping",	setmode, 1, MODE_TRAPSIG },
960*38689Sborman     { "+isig",	0,				setmode, 1, MODE_TRAPSIG },
961*38689Sborman     { "-isig",	"Disable signal trapping",	clearmode, 1, MODE_TRAPSIG },
962*38689Sborman     { "edit",	"Enable character editing",	setmode, 1, MODE_EDIT },
963*38689Sborman     { "+edit",	0,				setmode, 1, MODE_EDIT },
964*38689Sborman     { "-edit",	"Disable character editing",	clearmode, 1, MODE_EDIT },
965*38689Sborman     { "help",	0,				modehelp, 0 },
966*38689Sborman     { "?",	"Print help information",	modehelp, 0 },
96732144Sminshall     { 0 },
96832144Sminshall };
96932144Sminshall 
97032144Sminshall static char **
97132144Sminshall getnextmode(name)
97232144Sminshall char *name;
97332144Sminshall {
974*38689Sborman     return (char **) (((struct modelist *)name)+1);
97532144Sminshall }
97632144Sminshall 
977*38689Sborman static struct modelist *
97832144Sminshall getmodecmd(name)
97932144Sminshall char *name;
98032144Sminshall {
981*38689Sborman     return (struct modelist *) genget(name, (char **) ModeList, getnextmode);
98232144Sminshall }
98332144Sminshall 
984*38689Sborman modehelp()
985*38689Sborman {
986*38689Sborman     struct modelist *mt;
987*38689Sborman 
988*38689Sborman     printf("format is:  'mode Mode', where 'Mode' is one of:\n\n");
989*38689Sborman     for (mt = ModeList; mt->name; mt++) {
990*38689Sborman 	if (mt->help) {
991*38689Sborman 	    if (*mt->help)
992*38689Sborman 		printf("%-15s %s\n", mt->name, mt->help);
993*38689Sborman 	    else
994*38689Sborman 		printf("\n");
995*38689Sborman 	}
996*38689Sborman     }
997*38689Sborman     return 0;
998*38689Sborman }
999*38689Sborman 
100032144Sminshall static
100132144Sminshall modecmd(argc, argv)
100232144Sminshall int	argc;
100332144Sminshall char	*argv[];
100432144Sminshall {
1005*38689Sborman     struct modelist *mt;
100632144Sminshall 
1007*38689Sborman     if (argc != 2) {
1008*38689Sborman 	printf("'mode' command requires an argument\n");
1009*38689Sborman 	printf("'mode ?' for help.\n");
1010*38689Sborman     } else if ((mt = getmodecmd(argv[1])) == 0) {
101132144Sminshall 	fprintf(stderr, "Unknown mode '%s' ('mode ?' for help).\n", argv[1]);
101232144Sminshall     } else if (Ambiguous(mt)) {
101332144Sminshall 	fprintf(stderr, "Ambiguous mode '%s' ('mode ?' for help).\n", argv[1]);
1014*38689Sborman     } else if (mt->needconnect && !connected) {
1015*38689Sborman 	printf("?Need to be connected first.\n");
1016*38689Sborman 	printf("'mode ?' for help.\n");
1017*38689Sborman     } else if (mt->handler) {
1018*38689Sborman 	return (*mt->handler)(mt->arg1);
101932144Sminshall     }
1020*38689Sborman     return 0;
102132144Sminshall }
102232144Sminshall 
102332144Sminshall /*
102432144Sminshall  * The following data structures and routines implement the
102532144Sminshall  * "display" command.
102632144Sminshall  */
102732144Sminshall 
102832144Sminshall static
102932144Sminshall display(argc, argv)
103032144Sminshall int	argc;
103132144Sminshall char	*argv[];
103232144Sminshall {
103332144Sminshall #define	dotog(tl)	if (tl->variable && tl->actionexplanation) { \
103432144Sminshall 			    if (*tl->variable) { \
103532144Sminshall 				printf("will"); \
103632144Sminshall 			    } else { \
103732144Sminshall 				printf("won't"); \
103832144Sminshall 			    } \
103932144Sminshall 			    printf(" %s.\n", tl->actionexplanation); \
104032144Sminshall 			}
104132144Sminshall 
104232144Sminshall #define	doset(sl)   if (sl->name && *sl->name != ' ') { \
1043*38689Sborman 			if (sl->handler == 0) \
1044*38689Sborman 			    printf("%-15s [%s]\n", sl->name, control(*sl->charp)); \
1045*38689Sborman 			else \
1046*38689Sborman 			    printf("%-15s \"%s\"\n", sl->name, sl->charp); \
104732144Sminshall 		    }
104832144Sminshall 
104932144Sminshall     struct togglelist *tl;
105032144Sminshall     struct setlist *sl;
105132144Sminshall 
105232144Sminshall     if (argc == 1) {
105332144Sminshall 	for (tl = Togglelist; tl->name; tl++) {
105432144Sminshall 	    dotog(tl);
105532144Sminshall 	}
105632144Sminshall 	printf("\n");
105732144Sminshall 	for (sl = Setlist; sl->name; sl++) {
105832144Sminshall 	    doset(sl);
105932144Sminshall 	}
106032144Sminshall     } else {
106132144Sminshall 	int i;
106232144Sminshall 
106332144Sminshall 	for (i = 1; i < argc; i++) {
106432144Sminshall 	    sl = getset(argv[i]);
106532144Sminshall 	    tl = gettoggle(argv[i]);
106632144Sminshall 	    if (Ambiguous(sl) || Ambiguous(tl)) {
106732144Sminshall 		printf("?Ambiguous argument '%s'.\n", argv[i]);
106832144Sminshall 		return 0;
106932144Sminshall 	    } else if (!sl && !tl) {
107032144Sminshall 		printf("?Unknown argument '%s'.\n", argv[i]);
107132144Sminshall 		return 0;
107232144Sminshall 	    } else {
107332144Sminshall 		if (tl) {
107432144Sminshall 		    dotog(tl);
107532144Sminshall 		}
107632144Sminshall 		if (sl) {
107732144Sminshall 		    doset(sl);
107832144Sminshall 		}
107932144Sminshall 	    }
108032144Sminshall 	}
108132144Sminshall     }
1082*38689Sborman /*@*/optionstatus();
108332144Sminshall     return 1;
108432144Sminshall #undef	doset
108532144Sminshall #undef	dotog
108632144Sminshall }
108732144Sminshall 
108832144Sminshall /*
108932144Sminshall  * The following are the data structures, and many of the routines,
109032144Sminshall  * relating to command processing.
109132144Sminshall  */
109232144Sminshall 
109332144Sminshall /*
109432144Sminshall  * Set the escape character.
109532144Sminshall  */
109632144Sminshall static
109732144Sminshall setescape(argc, argv)
109832144Sminshall 	int argc;
109932144Sminshall 	char *argv[];
110032144Sminshall {
110132144Sminshall 	register char *arg;
110232144Sminshall 	char buf[50];
110332144Sminshall 
110432144Sminshall 	printf(
110532144Sminshall 	    "Deprecated usage - please use 'set escape%s%s' in the future.\n",
110632144Sminshall 				(argc > 2)? " ":"", (argc > 2)? argv[1]: "");
110732144Sminshall 	if (argc > 2)
110832144Sminshall 		arg = argv[1];
110932144Sminshall 	else {
111032144Sminshall 		printf("new escape character: ");
111134849Sminshall 		(void) gets(buf);
111232144Sminshall 		arg = buf;
111332144Sminshall 	}
111432144Sminshall 	if (arg[0] != '\0')
111532144Sminshall 		escape = arg[0];
111632144Sminshall 	if (!In3270) {
111732144Sminshall 		printf("Escape character is '%s'.\n", control(escape));
111832144Sminshall 	}
111934849Sminshall 	(void) fflush(stdout);
112032144Sminshall 	return 1;
112132144Sminshall }
112232144Sminshall 
112332144Sminshall /*VARARGS*/
112432144Sminshall static
112532144Sminshall togcrmod()
112632144Sminshall {
112732144Sminshall     crmod = !crmod;
112832144Sminshall     printf("Deprecated usage - please use 'toggle crmod' in the future.\n");
112932144Sminshall     printf("%s map carriage return on output.\n", crmod ? "Will" : "Won't");
113034849Sminshall     (void) fflush(stdout);
113132144Sminshall     return 1;
113232144Sminshall }
113332144Sminshall 
113432144Sminshall /*VARARGS*/
113532144Sminshall suspend()
113632144Sminshall {
1137*38689Sborman #ifdef	SIGTSTP
113837219Sminshall     setcommandmode();
113937219Sminshall     {
114037219Sminshall 	long oldrows, oldcols, newrows, newcols;
114137219Sminshall 
114237219Sminshall 	TerminalWindowSize(&oldrows, &oldcols);
114334849Sminshall 	(void) kill(0, SIGTSTP);
114437219Sminshall 	TerminalWindowSize(&newrows, &newcols);
114537219Sminshall 	if ((oldrows != newrows) || (oldcols != newcols)) {
114637219Sminshall 	    if (connected) {
114737219Sminshall 		sendnaws();
114837219Sminshall 	    }
114937219Sminshall 	}
115037219Sminshall     }
115137219Sminshall     /* reget parameters in case they were changed */
115237219Sminshall     TerminalSaveState();
1153*38689Sborman     setconnmode(0);
1154*38689Sborman #else
1155*38689Sborman     printf("Suspend is not supported.  Try the '!' command instead\n");
1156*38689Sborman #endif
115737219Sminshall     return 1;
115832144Sminshall }
115932144Sminshall 
1160*38689Sborman #if	!defined(TN3270)
1161*38689Sborman #ifdef	CRAY
1162*38689Sborman #define	vfork	fork
1163*38689Sborman #endif
1164*38689Sborman shell(argc, argv)
1165*38689Sborman int argc;
1166*38689Sborman char *argv[];
1167*38689Sborman {
1168*38689Sborman     extern char *rindex();
1169*38689Sborman     char cmdbuf[256];
1170*38689Sborman 
1171*38689Sborman     setcommandmode();
1172*38689Sborman     switch(vfork()) {
1173*38689Sborman     case -1:
1174*38689Sborman 	perror("Fork failed\n");
1175*38689Sborman 	break;
1176*38689Sborman 
1177*38689Sborman     case 0:
1178*38689Sborman 	{
1179*38689Sborman 	    /*
1180*38689Sborman 	     * Fire up the shell in the child.
1181*38689Sborman 	     */
1182*38689Sborman 	    register char *shell, *shellname;
1183*38689Sborman 
1184*38689Sborman 	    shell = getenv("SHELL");
1185*38689Sborman 	    if (shell == NULL)
1186*38689Sborman 		shell = "/bin/sh";
1187*38689Sborman 	    if ((shellname = rindex(shell, '/')) == 0)
1188*38689Sborman 		shellname = shell;
1189*38689Sborman 	    else
1190*38689Sborman 		shellname++;
1191*38689Sborman 	    if (argc > 1)
1192*38689Sborman 		execl(shell, shellname, "-c", &saveline[1], 0);
1193*38689Sborman 	    else
1194*38689Sborman 		execl(shell, shellname, 0);
1195*38689Sborman 	    perror("Execl");
1196*38689Sborman 	    _exit(1);
1197*38689Sborman 	}
1198*38689Sborman     default:
1199*38689Sborman 	    wait((int *)0);	/* Wait for the shell to complete */
1200*38689Sborman     }
1201*38689Sborman }
1202*38689Sborman #endif	/* !defined(TN3270) */
1203*38689Sborman 
120432144Sminshall /*VARARGS*/
120532144Sminshall static
120632144Sminshall bye(argc, argv)
120732144Sminshall int	argc;		/* Number of arguments */
120832144Sminshall char	*argv[];	/* arguments */
120932144Sminshall {
121032144Sminshall     if (connected) {
121134849Sminshall 	(void) shutdown(net, 2);
121232144Sminshall 	printf("Connection closed.\n");
121334849Sminshall 	(void) NetClose(net);
121432144Sminshall 	connected = 0;
121532144Sminshall 	/* reset options */
121632144Sminshall 	tninit();
121732144Sminshall #if	defined(TN3270)
121832144Sminshall 	SetIn3270();		/* Get out of 3270 mode */
121932144Sminshall #endif	/* defined(TN3270) */
122032144Sminshall     }
122132144Sminshall     if ((argc != 2) || (strcmp(argv[1], "fromquit") != 0)) {
122232144Sminshall 	longjmp(toplevel, 1);
122332144Sminshall 	/* NOTREACHED */
122432144Sminshall     }
122532144Sminshall     return 1;			/* Keep lint, etc., happy */
122632144Sminshall }
122732144Sminshall 
122832144Sminshall /*VARARGS*/
122932144Sminshall quit()
123032144Sminshall {
123132144Sminshall 	(void) call(bye, "bye", "fromquit", 0);
123232144Sminshall 	Exit(0);
123332144Sminshall 	return 1;			/* just to keep lint happy */
123432144Sminshall }
1235*38689Sborman 
1236*38689Sborman /*
1237*38689Sborman  * The SLC command.
1238*38689Sborman  */
123932144Sminshall 
1240*38689Sborman struct slclist {
1241*38689Sborman 	char	*name;
1242*38689Sborman 	char	*help;
1243*38689Sborman 	int	(*handler)();
1244*38689Sborman 	int	arg;
1245*38689Sborman };
1246*38689Sborman 
1247*38689Sborman extern int slc_help();
1248*38689Sborman extern int slc_mode_export(), slc_mode_import(), slcstate();
1249*38689Sborman 
1250*38689Sborman struct slclist SlcList[] = {
1251*38689Sborman     { "export",	"Use local special character definitions",
1252*38689Sborman 						slc_mode_export,	0 },
1253*38689Sborman     { "import",	"Use remote special character definitions",
1254*38689Sborman 						slc_mode_import,	1 },
1255*38689Sborman     { "check",	"Verify remote special character definitions",
1256*38689Sborman 						slc_mode_import,	0 },
1257*38689Sborman     { "help",	0,				slc_help,		0 },
1258*38689Sborman     { "?",	"Print help information",	slc_help,		0 },
1259*38689Sborman     { 0 },
1260*38689Sborman };
1261*38689Sborman 
1262*38689Sborman static
1263*38689Sborman slc_help()
1264*38689Sborman {
1265*38689Sborman     struct slclist *c;
1266*38689Sborman 
1267*38689Sborman     for (c = SlcList; c->name; c++) {
1268*38689Sborman 	if (c->help) {
1269*38689Sborman 	    if (*c->help)
1270*38689Sborman 		printf("%-15s %s\n", c->name, c->help);
1271*38689Sborman 	    else
1272*38689Sborman 		printf("\n");
1273*38689Sborman 	}
1274*38689Sborman     }
1275*38689Sborman }
1276*38689Sborman 
1277*38689Sborman static char **
1278*38689Sborman getnextslc(name)
1279*38689Sborman char *name;
1280*38689Sborman {
1281*38689Sborman     return (char **)(((struct slclist *)name)+1);
1282*38689Sborman }
1283*38689Sborman 
1284*38689Sborman static struct slclist *
1285*38689Sborman getslc(name)
1286*38689Sborman char *name;
1287*38689Sborman {
1288*38689Sborman     return (struct slclist *)genget(name, (char **) SlcList, getnextslc);
1289*38689Sborman }
1290*38689Sborman 
1291*38689Sborman static
1292*38689Sborman slccmd(argc, argv)
1293*38689Sborman int	argc;
1294*38689Sborman char	*argv[];
1295*38689Sborman {
1296*38689Sborman     struct slclist *c;
1297*38689Sborman 
1298*38689Sborman     if (argc != 2) {
1299*38689Sborman 	fprintf(stderr,
1300*38689Sborman 	    "Need an argument to 'slc' command.  'slc ?' for help.\n");
1301*38689Sborman 	return 0;
1302*38689Sborman     }
1303*38689Sborman     c = getslc(argv[1]);
1304*38689Sborman     if (c == 0) {
1305*38689Sborman         fprintf(stderr, "'%s': unknown argument ('slc ?' for help).\n",
1306*38689Sborman     				argv[1]);
1307*38689Sborman         return 0;
1308*38689Sborman     }
1309*38689Sborman     if (Ambiguous(c)) {
1310*38689Sborman         fprintf(stderr, "'%s': ambiguous argument ('slc ?' for help).\n",
1311*38689Sborman     				argv[1]);
1312*38689Sborman         return 0;
1313*38689Sborman     }
1314*38689Sborman     (*c->handler)(c->arg);
1315*38689Sborman     slcstate();
1316*38689Sborman     return 1;
1317*38689Sborman }
1318*38689Sborman 
131936274Sminshall #if	defined(unix)
132032144Sminshall /*
132136274Sminshall  * Some information about our file descriptors.
132236274Sminshall  */
132336274Sminshall 
132436274Sminshall char *
132536274Sminshall decodeflags(mask)
132636274Sminshall int mask;
132736274Sminshall {
132836274Sminshall     static char buffer[100];
132936274Sminshall #define do(m,s) \
133036274Sminshall 	if (mask&(m)) { \
133136274Sminshall 	    strcat(buffer, (s)); \
133236274Sminshall 	}
133336274Sminshall 
133436274Sminshall     buffer[0] = 0;			/* Terminate it */
133536274Sminshall 
133636274Sminshall #ifdef FREAD
133736274Sminshall     do(FREAD, " FREAD");
133836274Sminshall #endif
133936274Sminshall #ifdef FWRITE
134036274Sminshall     do(FWRITE, " FWRITE");
134136274Sminshall #endif
134236274Sminshall #ifdef F_DUPFP
134336274Sminshall     do(F_DUPFD, " F_DUPFD");
134436274Sminshall #endif
134536274Sminshall #ifdef FNDELAY
134636274Sminshall     do(FNDELAY, " FNDELAY");
134736274Sminshall #endif
134836274Sminshall #ifdef FAPPEND
134936274Sminshall     do(FAPPEND, " FAPPEND");
135036274Sminshall #endif
135136274Sminshall #ifdef FMARK
135236274Sminshall     do(FMARK, " FMARK");
135336274Sminshall #endif
135436274Sminshall #ifdef FDEFER
135536274Sminshall     do(FDEFER, " FDEFER");
135636274Sminshall #endif
135736274Sminshall #ifdef FASYNC
135836274Sminshall     do(FASYNC, " FASYNC");
135936274Sminshall #endif
136036274Sminshall #ifdef FSHLOCK
136136274Sminshall     do(FSHLOCK, " FSHLOCK");
136236274Sminshall #endif
136336274Sminshall #ifdef FEXLOCK
136436274Sminshall     do(FEXLOCK, " FEXLOCK");
136536274Sminshall #endif
136636274Sminshall #ifdef FCREAT
136736274Sminshall     do(FCREAT, " FCREAT");
136836274Sminshall #endif
136936274Sminshall #ifdef FTRUNC
137036274Sminshall     do(FTRUNC, " FTRUNC");
137136274Sminshall #endif
137236274Sminshall #ifdef FEXCL
137336274Sminshall     do(FEXCL, " FEXCL");
137436274Sminshall #endif
137536274Sminshall 
137636274Sminshall     return buffer;
137736274Sminshall }
137836274Sminshall #undef do
137936274Sminshall 
138036274Sminshall static void
138136274Sminshall filestuff(fd)
138236274Sminshall int fd;
138336274Sminshall {
138436274Sminshall     int res;
138536274Sminshall 
1386*38689Sborman #ifdef	F_GETOWN
1387*38689Sborman     setconnmode(0);
138836274Sminshall     res = fcntl(fd, F_GETOWN, 0);
138936274Sminshall     setcommandmode();
139036274Sminshall 
139136274Sminshall     if (res == -1) {
139236274Sminshall 	perror("fcntl");
139336274Sminshall 	return;
139436274Sminshall     }
139536274Sminshall     printf("\tOwner is %d.\n", res);
1396*38689Sborman #endif
139736274Sminshall 
1398*38689Sborman     setconnmode(0);
139936274Sminshall     res = fcntl(fd, F_GETFL, 0);
140036274Sminshall     setcommandmode();
140136274Sminshall 
140236274Sminshall     if (res == -1) {
140336274Sminshall 	perror("fcntl");
140436274Sminshall 	return;
140536274Sminshall     }
140636274Sminshall     printf("\tFlags are 0x%x: %s\n", res, decodeflags(res));
140736274Sminshall }
140836274Sminshall 
140936274Sminshall 
141036274Sminshall #endif	/* defined(unix) */
141136274Sminshall 
141236274Sminshall /*
141332144Sminshall  * Print status about the connection.
141432144Sminshall  */
141534849Sminshall /*ARGSUSED*/
141632144Sminshall static
141732144Sminshall status(argc, argv)
141832144Sminshall int	argc;
141932144Sminshall char	*argv[];
142032144Sminshall {
142132144Sminshall     if (connected) {
142232144Sminshall 	printf("Connected to %s.\n", hostname);
142336242Sminshall 	if ((argc < 2) || strcmp(argv[1], "notmuch")) {
1424*38689Sborman 	    int mode = getconnmode();
1425*38689Sborman 
1426*38689Sborman 	    if (my_want_state_is_will(TELOPT_LINEMODE)) {
1427*38689Sborman 		printf("Operating with LINEMODE option\n");
1428*38689Sborman 		printf("%s line editing\n", (mode&MODE_EDIT) ? "Local" : "No");
1429*38689Sborman 		printf("%s catching of signals\n",
1430*38689Sborman 					(mode&MODE_TRAPSIG) ? "Local" : "No");
1431*38689Sborman 		slcstate();
1432*38689Sborman #ifdef	KLUDGELINEMODE
1433*38689Sborman 	    } else if (kludgelinemode && my_want_state_is_wont(TELOPT_SGA)) {
1434*38689Sborman 		printf("Operating in obsolete linemode\n");
1435*38689Sborman #endif
1436*38689Sborman 	    } else {
1437*38689Sborman 		printf("Operating in single character mode\n");
1438*38689Sborman 		if (localchars)
1439*38689Sborman 		    printf("Catching signals locally\n");
144032144Sminshall 	    }
1441*38689Sborman 	    printf("%s character echo\n", (mode&MODE_ECHO) ? "Local" : "Remote");
1442*38689Sborman 	    if (my_want_state_is_will(TELOPT_LFLOW))
1443*38689Sborman 		printf("%s flow control\n", (mode&MODE_FLOW) ? "Local" : "No");
144432144Sminshall 	}
144532144Sminshall     } else {
144632144Sminshall 	printf("No connection.\n");
144732144Sminshall     }
144832144Sminshall #   if !defined(TN3270)
144932144Sminshall     printf("Escape character is '%s'.\n", control(escape));
145034849Sminshall     (void) fflush(stdout);
145132144Sminshall #   else /* !defined(TN3270) */
145232144Sminshall     if ((!In3270) && ((argc < 2) || strcmp(argv[1], "notmuch"))) {
145332144Sminshall 	printf("Escape character is '%s'.\n", control(escape));
145432144Sminshall     }
145532144Sminshall #   if defined(unix)
145636242Sminshall     if ((argc >= 2) && !strcmp(argv[1], "everything")) {
145736242Sminshall 	printf("SIGIO received %d time%s.\n",
145836242Sminshall 				sigiocount, (sigiocount == 1)? "":"s");
145936274Sminshall 	if (In3270) {
146036274Sminshall 	    printf("Process ID %d, process group %d.\n",
146136274Sminshall 					    getpid(), getpgrp(getpid()));
146236274Sminshall 	    printf("Terminal input:\n");
146336274Sminshall 	    filestuff(tin);
146436274Sminshall 	    printf("Terminal output:\n");
146536274Sminshall 	    filestuff(tout);
146636274Sminshall 	    printf("Network socket:\n");
146736274Sminshall 	    filestuff(net);
146836274Sminshall 	}
146936242Sminshall     }
147032144Sminshall     if (In3270 && transcom) {
147132144Sminshall        printf("Transparent mode command is '%s'.\n", transcom);
147232144Sminshall     }
147332144Sminshall #   endif /* defined(unix) */
147434849Sminshall     (void) fflush(stdout);
147532144Sminshall     if (In3270) {
147632144Sminshall 	return 0;
147732144Sminshall     }
147832144Sminshall #   endif /* defined(TN3270) */
147932144Sminshall     return 1;
148032144Sminshall }
148132144Sminshall 
148232144Sminshall 
148332144Sminshall 
148432144Sminshall int
148532144Sminshall tn(argc, argv)
148632144Sminshall 	int argc;
148732144Sminshall 	char *argv[];
148832144Sminshall {
148932144Sminshall     register struct hostent *host = 0;
149032144Sminshall     struct sockaddr_in sin;
149132144Sminshall     struct servent *sp = 0;
149232144Sminshall     static char	hnamebuf[32];
1493*38689Sborman     unsigned long temp, inet_addr();
149437219Sminshall     extern char *inet_ntoa();
1495*38689Sborman #if	defined(SRCRT) && defined(IPPROTO_IP)
1496*38689Sborman     char *srp = 0, *strrchr();
1497*38689Sborman     unsigned long sourceroute(), srlen;
1498*38689Sborman #endif
149932144Sminshall 
150032144Sminshall 
150132144Sminshall #if defined(MSDOS)
150232144Sminshall     char *cp;
150332144Sminshall #endif	/* defined(MSDOS) */
150432144Sminshall 
150532144Sminshall     if (connected) {
150632144Sminshall 	printf("?Already connected to %s\n", hostname);
150732144Sminshall 	return 0;
150832144Sminshall     }
150932144Sminshall     if (argc < 2) {
151032144Sminshall 	(void) strcpy(line, "Connect ");
151132144Sminshall 	printf("(to) ");
151234849Sminshall 	(void) gets(&line[strlen(line)]);
151332144Sminshall 	makeargv();
151432144Sminshall 	argc = margc;
151532144Sminshall 	argv = margv;
151632144Sminshall     }
151732144Sminshall     if ((argc < 2) || (argc > 3)) {
151832144Sminshall 	printf("usage: %s host-name [port]\n", argv[0]);
151932144Sminshall 	return 0;
152032144Sminshall     }
152132144Sminshall #if	defined(MSDOS)
152232144Sminshall     for (cp = argv[1]; *cp; cp++) {
152332144Sminshall 	if (isupper(*cp)) {
152432144Sminshall 	    *cp = tolower(*cp);
152532144Sminshall 	}
152632144Sminshall     }
152732144Sminshall #endif	/* defined(MSDOS) */
1528*38689Sborman #if	defined(SRCRT) && defined(IPPROTO_IP)
1529*38689Sborman     if (argv[1][0] == '@' || argv[1][0] == '!') {
1530*38689Sborman 	if ((hostname = strrchr(argv[1], ':')) == NULL)
1531*38689Sborman 	    hostname = strrchr(argv[1], '@');
1532*38689Sborman 	hostname++;
1533*38689Sborman 	srp = 0;
1534*38689Sborman 	temp = sourceroute(argv[1], &srp, &srlen);
1535*38689Sborman 	if (temp == 0) {
1536*38689Sborman 	    herror(srp);
1537*38689Sborman 	    return 0;
1538*38689Sborman 	} else if (temp == -1) {
1539*38689Sborman 	    printf("Bad source route option: %s\n", argv[1]);
1540*38689Sborman 	    return 0;
1541*38689Sborman 	} else {
1542*38689Sborman 	    sin.sin_addr.s_addr = temp;
1543*38689Sborman 	    sin.sin_family = AF_INET;
1544*38689Sborman 	}
154532144Sminshall     } else {
1546*38689Sborman #endif
1547*38689Sborman 	temp = inet_addr(argv[1]);
1548*38689Sborman 	if (temp != (unsigned long) -1) {
1549*38689Sborman 	    sin.sin_addr.s_addr = temp;
1550*38689Sborman 	    sin.sin_family = AF_INET;
1551*38689Sborman 	    (void) strcpy(hnamebuf, argv[1]);
1552*38689Sborman 	    hostname = hnamebuf;
1553*38689Sborman 	} else {
1554*38689Sborman 	    host = gethostbyname(argv[1]);
1555*38689Sborman 	    if (host) {
1556*38689Sborman 		sin.sin_family = host->h_addrtype;
155732144Sminshall #if	defined(h_addr)		/* In 4.3, this is a #define */
1558*38689Sborman 		memcpy((caddr_t)&sin.sin_addr,
155932144Sminshall 				host->h_addr_list[0], host->h_length);
156032144Sminshall #else	/* defined(h_addr) */
1561*38689Sborman 		memcpy((caddr_t)&sin.sin_addr, host->h_addr, host->h_length);
156232144Sminshall #endif	/* defined(h_addr) */
1563*38689Sborman 		hostname = host->h_name;
1564*38689Sborman 	    } else {
1565*38689Sborman 		herror(argv[1]);
1566*38689Sborman 		return 0;
1567*38689Sborman 	    }
156832144Sminshall 	}
1569*38689Sborman #if	defined(SRCRT) && defined(IPPROTO_IP)
157032144Sminshall     }
1571*38689Sborman #endif
157232144Sminshall     if (argc == 3) {
1573*38689Sborman 	int tmp;
1574*38689Sborman 
1575*38689Sborman 	if (*argv[2] == '-') {
1576*38689Sborman 	    argv[2]++;
1577*38689Sborman 	    telnetport = 1;
1578*38689Sborman 	} else
1579*38689Sborman 	    telnetport = 0;
158032144Sminshall 	sin.sin_port = atoi(argv[2]);
158132144Sminshall 	if (sin.sin_port == 0) {
158232144Sminshall 	    sp = getservbyname(argv[2], "tcp");
158332144Sminshall 	    if (sp)
158432144Sminshall 		sin.sin_port = sp->s_port;
158532144Sminshall 	    else {
158632144Sminshall 		printf("%s: bad port number\n", argv[2]);
158732144Sminshall 		return 0;
158832144Sminshall 	    }
158932144Sminshall 	} else {
159034849Sminshall #if	!defined(htons)
159134849Sminshall 	    u_short htons();
159234849Sminshall #endif	/* !defined(htons) */
159332144Sminshall 	    sin.sin_port = htons(sin.sin_port);
159432144Sminshall 	}
159532144Sminshall     } else {
159632144Sminshall 	if (sp == 0) {
159732144Sminshall 	    sp = getservbyname("telnet", "tcp");
159832144Sminshall 	    if (sp == 0) {
159934849Sminshall 		fprintf(stderr, "telnet: tcp/telnet: unknown service\n");
160032144Sminshall 		return 0;
160132144Sminshall 	    }
160232144Sminshall 	    sin.sin_port = sp->s_port;
160332144Sminshall 	}
160432144Sminshall 	telnetport = 1;
160532144Sminshall     }
160637219Sminshall     printf("Trying %s...\n", inet_ntoa(sin.sin_addr));
160732144Sminshall     do {
160832144Sminshall 	net = socket(AF_INET, SOCK_STREAM, 0);
160932144Sminshall 	if (net < 0) {
161032144Sminshall 	    perror("telnet: socket");
161132144Sminshall 	    return 0;
161232144Sminshall 	}
1613*38689Sborman #if	defined(SRCRT) && defined(IPPROTO_IP)
1614*38689Sborman 	if (srp && setsockopt(net, IPPROTO_IP, IP_OPTIONS, (char *)srp, srlen) < 0)
1615*38689Sborman 		perror("setsockopt (IP_OPTIONS)");
1616*38689Sborman #endif
161732144Sminshall 	if (debug && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 1) < 0) {
161832144Sminshall 		perror("setsockopt (SO_DEBUG)");
161932144Sminshall 	}
162032144Sminshall 
162132144Sminshall 	if (connect(net, (struct sockaddr *)&sin, sizeof (sin)) < 0) {
162232144Sminshall #if	defined(h_addr)		/* In 4.3, this is a #define */
162332144Sminshall 	    if (host && host->h_addr_list[1]) {
162432144Sminshall 		int oerrno = errno;
162532144Sminshall 
162632144Sminshall 		fprintf(stderr, "telnet: connect to address %s: ",
162732144Sminshall 						inet_ntoa(sin.sin_addr));
162832144Sminshall 		errno = oerrno;
162932144Sminshall 		perror((char *)0);
163032144Sminshall 		host->h_addr_list++;
163132144Sminshall 		memcpy((caddr_t)&sin.sin_addr,
163232144Sminshall 			host->h_addr_list[0], host->h_length);
163332144Sminshall 		(void) NetClose(net);
163432144Sminshall 		continue;
163532144Sminshall 	    }
163632144Sminshall #endif	/* defined(h_addr) */
163732144Sminshall 	    perror("telnet: Unable to connect to remote host");
163832144Sminshall 	    return 0;
163937219Sminshall 	}
164032144Sminshall 	connected++;
164132144Sminshall     } while (connected == 0);
1642*38689Sborman     cmdrc(argv[1], hostname);
164334849Sminshall     (void) call(status, "status", "notmuch", 0);
164432144Sminshall     if (setjmp(peerdied) == 0)
164532144Sminshall 	telnet();
164634849Sminshall     (void) NetClose(net);
164732381Sminshall     ExitString("Connection closed by foreign host.\n",1);
164832144Sminshall     /*NOTREACHED*/
164932144Sminshall }
165032144Sminshall 
165132144Sminshall 
165232144Sminshall #define HELPINDENT (sizeof ("connect"))
165332144Sminshall 
165432144Sminshall static char
165532144Sminshall 	openhelp[] =	"connect to a site",
165632144Sminshall 	closehelp[] =	"close current connection",
165732144Sminshall 	quithelp[] =	"exit telnet",
165832144Sminshall 	statushelp[] =	"print status information",
165932144Sminshall 	helphelp[] =	"print help information",
166032144Sminshall 	sendhelp[] =	"transmit special characters ('send ?' for more)",
166132144Sminshall 	sethelp[] = 	"set operating parameters ('set ?' for more)",
1662*38689Sborman 	unsethelp[] = 	"unset operating parameters ('unset ?' for more)",
166332144Sminshall 	togglestring[] ="toggle operating parameters ('toggle ?' for more)",
1664*38689Sborman 	slchelp[] =	"change state of special charaters ('slc ?' for more)",
166532144Sminshall 	displayhelp[] =	"display operating parameters",
166632144Sminshall #if	defined(TN3270) && defined(unix)
166732144Sminshall 	transcomhelp[] = "specify Unix command for transparent mode pipe",
166832144Sminshall #endif	/* defined(TN3270) && defined(unix) */
166932144Sminshall #if	defined(unix)
167032144Sminshall 	zhelp[] =	"suspend telnet",
167132144Sminshall #endif	/* defined(unix */
167232144Sminshall 	shellhelp[] =	"invoke a subshell",
1673*38689Sborman 	modestring[] = "try to enter line-by-line or character-at-a-time mode";
167432144Sminshall 
167532144Sminshall extern int	help(), shell();
167632144Sminshall 
167732144Sminshall static Command cmdtab[] = {
1678*38689Sborman 	{ "close",	closehelp,	bye,		1 },
1679*38689Sborman 	{ "display",	displayhelp,	display,	0 },
1680*38689Sborman 	{ "mode",	modestring,	modecmd,	0 },
1681*38689Sborman 	{ "open",	openhelp,	tn,		0 },
1682*38689Sborman 	{ "quit",	quithelp,	quit,		0 },
1683*38689Sborman 	{ "send",	sendhelp,	sendcmd,	0 },
1684*38689Sborman 	{ "set",	sethelp,	setcmd,		0 },
1685*38689Sborman 	{ "unset",	unsethelp,	unsetcmd,	0 },
1686*38689Sborman 	{ "status",	statushelp,	status,		0 },
1687*38689Sborman 	{ "toggle",	togglestring,	toggle,		0 },
1688*38689Sborman 	{ "slc",	slchelp,	slccmd,		0 },
168932144Sminshall #if	defined(TN3270) && defined(unix)
1690*38689Sborman 	{ "transcom",	transcomhelp,	settranscom,	0 },
169132144Sminshall #endif	/* defined(TN3270) && defined(unix) */
169232144Sminshall #if	defined(unix)
1693*38689Sborman 	{ "z",		zhelp,		suspend,	0 },
169432144Sminshall #endif	/* defined(unix) */
169532144Sminshall #if	defined(TN3270)
1696*38689Sborman 	{ "!",		shellhelp,	shell,		1 },
1697*38689Sborman #else
1698*38689Sborman 	{ "!",		shellhelp,	shell,		0 },
1699*38689Sborman #endif
1700*38689Sborman 	{ "?",		helphelp,	help,		0 },
170132144Sminshall 	0
170232144Sminshall };
170332144Sminshall 
170432144Sminshall static char	crmodhelp[] =	"deprecated command -- use 'toggle crmod' instead";
170532144Sminshall static char	escapehelp[] =	"deprecated command -- use 'set escape' instead";
170632144Sminshall 
170732144Sminshall static Command cmdtab2[] = {
1708*38689Sborman 	{ "help",	0,		help,		0 },
1709*38689Sborman 	{ "escape",	escapehelp,	setescape,	0 },
1710*38689Sborman 	{ "crmod",	crmodhelp,	togcrmod,	0 },
171132144Sminshall 	0
171232144Sminshall };
171332144Sminshall 
171435298Sminshall 
171532144Sminshall /*
171632144Sminshall  * Call routine with argc, argv set from args (terminated by 0).
171732144Sminshall  */
171835298Sminshall 
171935417Sminshall /*VARARGS1*/
172032144Sminshall static
172135298Sminshall call(va_alist)
172235298Sminshall va_dcl
172332144Sminshall {
172435298Sminshall     va_list ap;
172535298Sminshall     typedef int (*intrtn_t)();
172635298Sminshall     intrtn_t routine;
172735298Sminshall     char *args[100];
172835298Sminshall     int argno = 0;
172935298Sminshall 
173035298Sminshall     va_start(ap);
173135298Sminshall     routine = (va_arg(ap, intrtn_t));
173235495Sminshall     while ((args[argno++] = va_arg(ap, char *)) != 0) {
173335298Sminshall 	;
173435495Sminshall     }
173535298Sminshall     va_end(ap);
173635495Sminshall     return (*routine)(argno-1, args);
173732144Sminshall }
173832144Sminshall 
173935298Sminshall 
174032144Sminshall static char **
174132144Sminshall getnextcmd(name)
174232144Sminshall char *name;
174332144Sminshall {
174432144Sminshall     Command *c = (Command *) name;
174532144Sminshall 
174632144Sminshall     return (char **) (c+1);
174732144Sminshall }
174832144Sminshall 
174932144Sminshall static Command *
175032144Sminshall getcmd(name)
175132144Sminshall char *name;
175232144Sminshall {
175332144Sminshall     Command *cm;
175432144Sminshall 
175532144Sminshall     if ((cm = (Command *) genget(name, (char **) cmdtab, getnextcmd)) != 0) {
175632144Sminshall 	return cm;
175732144Sminshall     } else {
175832144Sminshall 	return (Command *) genget(name, (char **) cmdtab2, getnextcmd);
175932144Sminshall     }
176032144Sminshall }
176132144Sminshall 
176232144Sminshall void
1763*38689Sborman command(top, tbuf, cnt)
176432144Sminshall 	int top;
1765*38689Sborman 	char *tbuf;
1766*38689Sborman 	int cnt;
176732144Sminshall {
176832144Sminshall     register Command *c;
176932144Sminshall 
177032144Sminshall     setcommandmode();
177132144Sminshall     if (!top) {
177232144Sminshall 	putchar('\n');
177337219Sminshall #if	defined(unix)
177432144Sminshall     } else {
177532144Sminshall 	signal(SIGINT, SIG_DFL);
177632144Sminshall 	signal(SIGQUIT, SIG_DFL);
177732144Sminshall #endif	/* defined(unix) */
177832144Sminshall     }
177932144Sminshall     for (;;) {
178032144Sminshall 	printf("%s> ", prompt);
1781*38689Sborman 	if (tbuf) {
1782*38689Sborman 	    register char *cp;
1783*38689Sborman 	    cp = line;
1784*38689Sborman 	    while (cnt > 0 && (*cp++ = *tbuf++) != '\n')
1785*38689Sborman 		cnt--;
1786*38689Sborman 	    tbuf = 0;
1787*38689Sborman 	    if (cp == line || *--cp != '\n' || cp == line)
1788*38689Sborman 		goto getline;
1789*38689Sborman 	    *cp = '\0';
1790*38689Sborman 	    printf("%s\n", line);
1791*38689Sborman 	} else {
1792*38689Sborman 	getline:
1793*38689Sborman 	    if (gets(line) == NULL) {
1794*38689Sborman 		if (feof(stdin) || ferror(stdin))
1795*38689Sborman 		    quit();
1796*38689Sborman 		break;
1797*38689Sborman 	    }
179832144Sminshall 	}
179932144Sminshall 	if (line[0] == 0)
180032144Sminshall 	    break;
180132144Sminshall 	makeargv();
180237219Sminshall 	if (margv[0] == 0) {
180337219Sminshall 	    break;
180437219Sminshall 	}
180532144Sminshall 	c = getcmd(margv[0]);
180632144Sminshall 	if (Ambiguous(c)) {
180732144Sminshall 	    printf("?Ambiguous command\n");
180832144Sminshall 	    continue;
180932144Sminshall 	}
181032144Sminshall 	if (c == 0) {
181132144Sminshall 	    printf("?Invalid command\n");
181232144Sminshall 	    continue;
181332144Sminshall 	}
181432144Sminshall 	if (c->needconnect && !connected) {
181532144Sminshall 	    printf("?Need to be connected first.\n");
181632144Sminshall 	    continue;
181732144Sminshall 	}
181832144Sminshall 	if ((*c->handler)(margc, margv)) {
181932144Sminshall 	    break;
182032144Sminshall 	}
182132144Sminshall     }
182232144Sminshall     if (!top) {
182332144Sminshall 	if (!connected) {
182432144Sminshall 	    longjmp(toplevel, 1);
182532144Sminshall 	    /*NOTREACHED*/
182632144Sminshall 	}
182732144Sminshall #if	defined(TN3270)
182832144Sminshall 	if (shell_active == 0) {
1829*38689Sborman 	    setconnmode(0);
183032144Sminshall 	}
183132144Sminshall #else	/* defined(TN3270) */
1832*38689Sborman 	setconnmode(0);
183332144Sminshall #endif	/* defined(TN3270) */
183432144Sminshall     }
183532144Sminshall }
183632144Sminshall 
183732144Sminshall /*
183832144Sminshall  * Help command.
183932144Sminshall  */
184032144Sminshall static
184132144Sminshall help(argc, argv)
184232144Sminshall 	int argc;
184332144Sminshall 	char *argv[];
184432144Sminshall {
184532144Sminshall 	register Command *c;
184632144Sminshall 
184732144Sminshall 	if (argc == 1) {
184832144Sminshall 		printf("Commands may be abbreviated.  Commands are:\n\n");
184932144Sminshall 		for (c = cmdtab; c->name; c++)
1850*38689Sborman 			if (c->help) {
185132144Sminshall 				printf("%-*s\t%s\n", HELPINDENT, c->name,
185232144Sminshall 								    c->help);
185332144Sminshall 			}
185432144Sminshall 		return 0;
185532144Sminshall 	}
185632144Sminshall 	while (--argc > 0) {
185732144Sminshall 		register char *arg;
185832144Sminshall 		arg = *++argv;
185932144Sminshall 		c = getcmd(arg);
186032144Sminshall 		if (Ambiguous(c))
186132144Sminshall 			printf("?Ambiguous help command %s\n", arg);
186232144Sminshall 		else if (c == (Command *)0)
186332144Sminshall 			printf("?Invalid help command %s\n", arg);
186432144Sminshall 		else
186532144Sminshall 			printf("%s\n", c->help);
186632144Sminshall 	}
186732144Sminshall 	return 0;
186832144Sminshall }
1869*38689Sborman 
1870*38689Sborman static char *rcname = 0;
1871*38689Sborman static char rcbuf[128];
1872*38689Sborman 
1873*38689Sborman cmdrc(m1, m2)
1874*38689Sborman 	char *m1, *m2;
1875*38689Sborman {
1876*38689Sborman     register Command *c;
1877*38689Sborman     FILE *rcfile;
1878*38689Sborman     int gotmachine = 0;
1879*38689Sborman     int l1 = strlen(m1);
1880*38689Sborman     int l2 = strlen(m2);
1881*38689Sborman     char m1save[64];
1882*38689Sborman 
1883*38689Sborman     strcpy(m1save, m1);
1884*38689Sborman     m1 = m1save;
1885*38689Sborman 
1886*38689Sborman     if (rcname == 0) {
1887*38689Sborman 	rcname = getenv("HOME");
1888*38689Sborman 	if (rcname)
1889*38689Sborman 	    strcpy(rcbuf, rcname);
1890*38689Sborman 	else
1891*38689Sborman 	    rcbuf[0] = '\0';
1892*38689Sborman 	strcat(rcbuf, "/.telnetrc");
1893*38689Sborman 	rcname = rcbuf;
1894*38689Sborman     }
1895*38689Sborman 
1896*38689Sborman     if ((rcfile = fopen(rcname, "r")) == 0) {
1897*38689Sborman 	return;
1898*38689Sborman     }
1899*38689Sborman 
1900*38689Sborman     for (;;) {
1901*38689Sborman 	if (fgets(line, sizeof(line), rcfile) == NULL)
1902*38689Sborman 	    break;
1903*38689Sborman 	if (line[0] == 0)
1904*38689Sborman 	    break;
1905*38689Sborman 	if (line[0] == '#')
1906*38689Sborman 	    continue;
1907*38689Sborman 	if (gotmachine == 0) {
1908*38689Sborman 	    if (isspace(line[0]))
1909*38689Sborman 		continue;
1910*38689Sborman 	    if (strncasecmp(line, m1, l1) == 0)
1911*38689Sborman 		strncpy(line, &line[l1], sizeof(line) - l1);
1912*38689Sborman 	    else if (strncasecmp(line, m2, l2) == 0)
1913*38689Sborman 		strncpy(line, &line[l2], sizeof(line) - l2);
1914*38689Sborman 	    else
1915*38689Sborman 		continue;
1916*38689Sborman 	    gotmachine = 1;
1917*38689Sborman 	} else {
1918*38689Sborman 	    if (!isspace(line[0])) {
1919*38689Sborman 		gotmachine = 0;
1920*38689Sborman 		continue;
1921*38689Sborman 	    }
1922*38689Sborman 	}
1923*38689Sborman 	makeargv();
1924*38689Sborman 	if (margv[0] == 0)
1925*38689Sborman 	    continue;
1926*38689Sborman 	c = getcmd(margv[0]);
1927*38689Sborman 	if (Ambiguous(c)) {
1928*38689Sborman 	    printf("?Ambiguous command: %s\n", margv[0]);
1929*38689Sborman 	    continue;
1930*38689Sborman 	}
1931*38689Sborman 	if (c == 0) {
1932*38689Sborman 	    printf("?Invalid command: %s\n", margv[0]);
1933*38689Sborman 	    continue;
1934*38689Sborman 	}
1935*38689Sborman 	/*
1936*38689Sborman 	 * This should never happen...
1937*38689Sborman 	 */
1938*38689Sborman 	if (c->needconnect && !connected) {
1939*38689Sborman 	    printf("?Need to be connected first for %s.\n", margv[0]);
1940*38689Sborman 	    continue;
1941*38689Sborman 	}
1942*38689Sborman 	(*c->handler)(margc, margv);
1943*38689Sborman     }
1944*38689Sborman     fclose(rcfile);
1945*38689Sborman }
1946*38689Sborman 
1947*38689Sborman #if	defined(SRCRT) && defined(IPPROTO_IP)
1948*38689Sborman 
1949*38689Sborman /*
1950*38689Sborman  * Source route is handed in as
1951*38689Sborman  *	[!]@hop1@hop2...[@|:]dst
1952*38689Sborman  * If the leading ! is present, it is a
1953*38689Sborman  * strict source route, otherwise it is
1954*38689Sborman  * assmed to be a loose source route.
1955*38689Sborman  *
1956*38689Sborman  * We fill in the source route option as
1957*38689Sborman  *	hop1,hop2,hop3...dest
1958*38689Sborman  * and return a pointer to hop1, which will
1959*38689Sborman  * be the address to connect() to.
1960*38689Sborman  *
1961*38689Sborman  * Arguments:
1962*38689Sborman  *	arg:	pointer to route list to decipher
1963*38689Sborman  *
1964*38689Sborman  *	cpp: 	If *cpp is not equal to NULL, this is a
1965*38689Sborman  *		pointer to a pointer to a character array
1966*38689Sborman  *		that should be filled in with the option.
1967*38689Sborman  *
1968*38689Sborman  *	lenp:	pointer to an integer that contains the
1969*38689Sborman  *		length of *cpp if *cpp != NULL.
1970*38689Sborman  *
1971*38689Sborman  * Return values:
1972*38689Sborman  *
1973*38689Sborman  *	Returns the address of the host to connect to.  If the
1974*38689Sborman  *	return value is -1, there was a syntax error in the
1975*38689Sborman  *	option, either unknown characters, or too many hosts.
1976*38689Sborman  *	If the return value is 0, one of the hostnames in the
1977*38689Sborman  *	path is unknown, and *cpp is set to point to the bad
1978*38689Sborman  *	hostname.
1979*38689Sborman  *
1980*38689Sborman  *	*cpp:	If *cpp was equal to NULL, it will be filled
1981*38689Sborman  *		in with a pointer to our static area that has
1982*38689Sborman  *		the option filled in.  This will be 32bit aligned.
1983*38689Sborman  *
1984*38689Sborman  *	*lenp:	This will be filled in with how long the option
1985*38689Sborman  *		pointed to by *cpp is.
1986*38689Sborman  *
1987*38689Sborman  */
1988*38689Sborman unsigned long
1989*38689Sborman sourceroute(arg, cpp, lenp)
1990*38689Sborman char	*arg;
1991*38689Sborman char	**cpp;
1992*38689Sborman int	*lenp;
1993*38689Sborman {
1994*38689Sborman 	static char lsr[44];
1995*38689Sborman 	char *cp, *cp2, *lsrp, *lsrep, *index();
1996*38689Sborman 	register int tmp;
1997*38689Sborman 	struct in_addr sin_addr;
1998*38689Sborman 	register struct hostent *host = 0;
1999*38689Sborman 	register char c;
2000*38689Sborman 
2001*38689Sborman 	/*
2002*38689Sborman 	 * Verify the arguments, and make sure we have
2003*38689Sborman 	 * at least 7 bytes for the option.
2004*38689Sborman 	 */
2005*38689Sborman 	if (cpp == NULL || lenp == NULL)
2006*38689Sborman 		return((unsigned long)-1);
2007*38689Sborman 	if (*cpp != NULL && *lenp < 7)
2008*38689Sborman 		return((unsigned long)-1);
2009*38689Sborman 	/*
2010*38689Sborman 	 * Decide whether we have a buffer passed to us,
2011*38689Sborman 	 * or if we need to use our own static buffer.
2012*38689Sborman 	 */
2013*38689Sborman 	if (*cpp) {
2014*38689Sborman 		lsrp = *cpp;
2015*38689Sborman 		lsrep = lsrp + *lenp;
2016*38689Sborman 	} else {
2017*38689Sborman 		*cpp = lsrp = lsr;
2018*38689Sborman 		lsrep = lsrp + 44;
2019*38689Sborman 	}
2020*38689Sborman 
2021*38689Sborman 	cp = arg;
2022*38689Sborman 
2023*38689Sborman 	/*
2024*38689Sborman 	 * Next, decide whether we have a loose source
2025*38689Sborman 	 * route or a strict source route, and fill in
2026*38689Sborman 	 * the begining of the option.
2027*38689Sborman 	 */
2028*38689Sborman 	if (*cp == '!') {
2029*38689Sborman 		cp++;
2030*38689Sborman 		*lsrp++ = IPOPT_SSRR;
2031*38689Sborman 	} else
2032*38689Sborman 		*lsrp++ = IPOPT_LSRR;
2033*38689Sborman 
2034*38689Sborman 	if (*cp != '@')
2035*38689Sborman 		return((unsigned long)-1);
2036*38689Sborman 
2037*38689Sborman 	lsrp++;		/* skip over length, we'll fill it in later */
2038*38689Sborman 	*lsrp++ = 4;
2039*38689Sborman 
2040*38689Sborman 	cp++;
2041*38689Sborman 
2042*38689Sborman 	sin_addr.s_addr = 0;
2043*38689Sborman 
2044*38689Sborman 	for (c = 0;;) {
2045*38689Sborman 		if (c == ':')
2046*38689Sborman 			cp2 = 0;
2047*38689Sborman 		else for (cp2 = cp; c = *cp2; cp2++) {
2048*38689Sborman 			if (c == ',') {
2049*38689Sborman 				*cp2++ = '\0';
2050*38689Sborman 				if (*cp2 == '@')
2051*38689Sborman 					cp2++;
2052*38689Sborman 			} else if (c == '@') {
2053*38689Sborman 				*cp2++ = '\0';
2054*38689Sborman 			} else if (c == ':') {
2055*38689Sborman 				*cp2++ = '\0';
2056*38689Sborman 			} else
2057*38689Sborman 				continue;
2058*38689Sborman 			break;
2059*38689Sborman 		}
2060*38689Sborman 		if (!c)
2061*38689Sborman 			cp2 = 0;
2062*38689Sborman 
2063*38689Sborman 		if ((tmp = inet_addr(cp)) != -1) {
2064*38689Sborman 			sin_addr.s_addr = tmp;
2065*38689Sborman 		} else if (host = gethostbyname(cp)) {
2066*38689Sborman #if	defined(h_addr)
2067*38689Sborman 			memcpy((caddr_t)&sin_addr,
2068*38689Sborman 				host->h_addr_list[0], host->h_length);
2069*38689Sborman #else
2070*38689Sborman 			memcpy((caddr_t)&sin_addr, host->h_addr, host->h_length);
2071*38689Sborman #endif
2072*38689Sborman 		} else {
2073*38689Sborman 			*cpp = cp;
2074*38689Sborman 			return(0);
2075*38689Sborman 		}
2076*38689Sborman 		memcpy(lsrp, (char *)&sin_addr, 4);
2077*38689Sborman 		lsrp += 4;
2078*38689Sborman 		if (cp2)
2079*38689Sborman 			cp = cp2;
2080*38689Sborman 		else
2081*38689Sborman 			break;
2082*38689Sborman 		/*
2083*38689Sborman 		 * Check to make sure there is space for next address
2084*38689Sborman 		 */
2085*38689Sborman 		if (lsrp + 4 > lsrep)
2086*38689Sborman 			return((unsigned long)-1);
2087*38689Sborman 	}
2088*38689Sborman 	if ((*(*cpp+IPOPT_OLEN) = lsrp - *cpp) <= 7) {
2089*38689Sborman 		*cpp = 0;
2090*38689Sborman 		*lenp = 0;
2091*38689Sborman 		return((unsigned long)-1);
2092*38689Sborman 	}
2093*38689Sborman 	*lsrp++ = IPOPT_NOP; /* 32 bit word align it */
2094*38689Sborman 	*lenp = lsrp - *cpp;
2095*38689Sborman 	return(sin_addr.s_addr);
2096*38689Sborman }
2097*38689Sborman #endif
2098*38689Sborman 
2099*38689Sborman #if	defined(sun)
2100*38689Sborman strncasecmp(p1, p2, len)
2101*38689Sborman register char *p1, *p2;
2102*38689Sborman int len;
2103*38689Sborman {
2104*38689Sborman     while (len--) {
2105*38689Sborman 	if (tolower(*p1) != tolower(*p2))
2106*38689Sborman 	   return(tolower(*p1) - tolower(*p2));
2107*38689Sborman 	if (*p1 == '\0')
2108*38689Sborman 	    return(0);
2109*38689Sborman 	p1++, p2++;
2110*38689Sborman     }
2111*38689Sborman     return(0);
2112*38689Sborman }
2113*38689Sborman #endif
2114