xref: /csrg-svn/usr.bin/telnet/commands.c (revision 45233)
133685Sbostic /*
2*45233Sborman  * Copyright (c) 1988, 1990 Regents of the University of California.
333685Sbostic  * All rights reserved.
433685Sbostic  *
542770Sbostic  * %sccs.include.redist.c%
633685Sbostic  */
733685Sbostic 
833685Sbostic #ifndef lint
9*45233Sborman static char sccsid[] = "@(#)commands.c	5.1 (Berkeley) 09/14/90";
1033685Sbostic #endif /* not lint */
1133685Sbostic 
1244361Sborman #include <sys/types.h>
1336274Sminshall #if	defined(unix)
1436274Sminshall #include <sys/file.h>
1536274Sminshall #endif	/* defined(unix) */
1632144Sminshall #include <sys/socket.h>
1732144Sminshall #include <netinet/in.h>
1838689Sborman #ifdef	CRAY
1938689Sborman #include <sys/fcntl.h>
2038810Sborman #endif	/* CRAY */
2132144Sminshall 
2232144Sminshall #include <signal.h>
2332144Sminshall #include <netdb.h>
2432144Sminshall #include <ctype.h>
2545008Skarels #include <pwd.h>
2635298Sminshall #include <varargs.h>
2732144Sminshall 
2832144Sminshall #include <arpa/telnet.h>
2932144Sminshall 
3034305Sminshall #include "general.h"
3134305Sminshall 
3232381Sminshall #include "ring.h"
3332381Sminshall 
3432144Sminshall #include "externs.h"
3532144Sminshall #include "defines.h"
3632144Sminshall #include "types.h"
3732144Sminshall 
3844361Sborman #ifdef	SRCRT
3944361Sborman # ifndef CRAY
4044361Sborman # include <netinet/in_systm.h>
4144361Sborman #  if (defined(vax) || defined(tahoe) || defined(hp300)) && !defined(ultrix)
4244361Sborman #  include <machine/endian.h>
4344361Sborman #  endif /* vax */
4444361Sborman # endif /* CRAY */
4544361Sborman #include <netinet/ip.h>
4644361Sborman #endif /* SRCRT */
4738689Sborman 
4840248Sborman #if defined(CRAY) && defined(IP_TOS) && !defined(HAS_IP_TOS)
4944361Sborman # define HAS_IP_TOS
5040248Sborman #endif
5138689Sborman 
5240248Sborman 
5332144Sminshall char	*hostname;
5438689Sborman extern char *getenv();
5532144Sminshall 
5636180Sminshall #define Ambiguous(s)	((char **)s == &ambiguous)
5732144Sminshall static char *ambiguous;		/* special return value for command routines */
5844361Sborman static call();
5932144Sminshall 
6032144Sminshall typedef struct {
6132144Sminshall 	char	*name;		/* command name */
6238689Sborman 	char	*help;		/* help string (NULL for no help) */
6332144Sminshall 	int	(*handler)();	/* routine which executes command */
6432144Sminshall 	int	needconnect;	/* Do we need to be connected to execute? */
6532144Sminshall } Command;
6632144Sminshall 
6738689Sborman static char line[256];
6838689Sborman static char saveline[256];
6932144Sminshall static int margc;
7032144Sminshall static char *margv[20];
7132144Sminshall 
7232144Sminshall /*
7332144Sminshall  * Various utility routines.
7432144Sminshall  */
7532144Sminshall 
7636180Sminshall #if	!defined(BSD) || (BSD <= 43)
7736180Sminshall 
7836180Sminshall char	*h_errlist[] = {
7936180Sminshall 	"Error 0",
8036180Sminshall 	"Unknown host",				/* 1 HOST_NOT_FOUND */
8136180Sminshall 	"Host name lookup failure",		/* 2 TRY_AGAIN */
8236180Sminshall 	"Unknown server error",			/* 3 NO_RECOVERY */
8336180Sminshall 	"No address associated with name",	/* 4 NO_ADDRESS */
8436180Sminshall };
8536180Sminshall int	h_nerr = { sizeof(h_errlist)/sizeof(h_errlist[0]) };
8636180Sminshall 
8736274Sminshall int h_errno;		/* In some version of SunOS this is necessary */
8836180Sminshall 
8936180Sminshall /*
9036180Sminshall  * herror --
9136180Sminshall  *	print the error indicated by the h_errno value.
9236180Sminshall  */
9336180Sminshall herror(s)
9436180Sminshall 	char *s;
9536180Sminshall {
9636180Sminshall 	if (s && *s) {
9736180Sminshall 		fprintf(stderr, "%s: ", s);
9836180Sminshall 	}
9936180Sminshall 	if ((h_errno < 0) || (h_errno >= h_nerr)) {
10036180Sminshall 		fprintf(stderr, "Unknown error\n");
10136274Sminshall 	} else if (h_errno == 0) {
10236274Sminshall #if	defined(sun)
10336274Sminshall 		fprintf(stderr, "Host unknown\n");
10436274Sminshall #endif	/* defined(sun) */
10536180Sminshall 	} else {
10636180Sminshall 		fprintf(stderr, "%s\n", h_errlist[h_errno]);
10736180Sminshall 	}
10836180Sminshall }
10936180Sminshall #endif	/* !define(BSD) || (BSD <= 43) */
11036180Sminshall 
11132144Sminshall static void
11232144Sminshall makeargv()
11332144Sminshall {
11444361Sborman     register char *cp, *cp2, c;
11532144Sminshall     register char **argp = margv;
11632144Sminshall 
11732144Sminshall     margc = 0;
11832144Sminshall     cp = line;
11932144Sminshall     if (*cp == '!') {		/* Special case shell escape */
12038689Sborman 	strcpy(saveline, line);	/* save for shell command */
12132144Sminshall 	*argp++ = "!";		/* No room in string to get this */
12232144Sminshall 	margc++;
12332144Sminshall 	cp++;
12432144Sminshall     }
12544361Sborman     while (c = *cp) {
12644361Sborman 	register int inquote = 0;
12744361Sborman 	while (isspace(c))
12844361Sborman 	    c = *++cp;
12944361Sborman 	if (c == '\0')
13032144Sminshall 	    break;
13132144Sminshall 	*argp++ = cp;
13232144Sminshall 	margc += 1;
13344361Sborman 	for (cp2 = cp; c != '\0'; c = *++cp) {
13444361Sborman 	    if (inquote) {
13544361Sborman 		if (c == inquote) {
13644361Sborman 		    inquote = 0;
13744361Sborman 		    continue;
13844361Sborman 		}
13944361Sborman 	    } else {
14044361Sborman 		if (c == '\\') {
14144361Sborman 		    if ((c = *++cp) == '\0')
14244361Sborman 			break;
14344361Sborman 		} else if (c == '"') {
14444361Sborman 		    inquote = '"';
14544361Sborman 		    continue;
14644361Sborman 		} else if (c == '\'') {
14744361Sborman 		    inquote = '\'';
14844361Sborman 		    continue;
14944361Sborman 		} else if (isspace(c))
15044361Sborman 		    break;
15144361Sborman 	    }
15244361Sborman 	    *cp2++ = c;
15344361Sborman 	}
15444361Sborman 	*cp2 = '\0';
15544361Sborman 	if (c == '\0')
15632144Sminshall 	    break;
15744361Sborman 	cp++;
15832144Sminshall     }
15932144Sminshall     *argp++ = 0;
16032144Sminshall }
16132144Sminshall 
16232144Sminshall 
16332144Sminshall static char **
16432144Sminshall genget(name, table, next)
16532144Sminshall char	*name;		/* name to match */
16632144Sminshall char	**table;		/* name entry in table */
16732144Sminshall char	**(*next)();	/* routine to return next entry in table */
16832144Sminshall {
16932144Sminshall 	register char *p, *q;
17032144Sminshall 	register char **c, **found;
17132144Sminshall 	register int nmatches, longest;
17232144Sminshall 
17332144Sminshall 	if (name == 0) {
17432144Sminshall 	    return 0;
17532144Sminshall 	}
17632144Sminshall 	longest = 0;
17732144Sminshall 	nmatches = 0;
17832144Sminshall 	found = 0;
17932144Sminshall 	for (c = table; (p = *c) != 0; c = (*next)(c)) {
18032144Sminshall 		for (q = name;
18132144Sminshall 		    (*q == *p) || (isupper(*q) && tolower(*q) == *p); p++, q++)
18232144Sminshall 			if (*q == 0)		/* exact match? */
18332144Sminshall 				return (c);
18432144Sminshall 		if (!*q) {			/* the name was a prefix */
18532144Sminshall 			if (q - name > longest) {
18632144Sminshall 				longest = q - name;
18732144Sminshall 				nmatches = 1;
18832144Sminshall 				found = c;
18932144Sminshall 			} else if (q - name == longest)
19032144Sminshall 				nmatches++;
19132144Sminshall 		}
19232144Sminshall 	}
19332144Sminshall 	if (nmatches > 1)
19436180Sminshall 		return &ambiguous;
19532144Sminshall 	return (found);
19632144Sminshall }
19732144Sminshall 
19832144Sminshall /*
19932144Sminshall  * Make a character string into a number.
20032144Sminshall  *
20132144Sminshall  * Todo:  1.  Could take random integers (12, 0x12, 012, 0b1).
20232144Sminshall  */
20332144Sminshall 
20432144Sminshall static
20532144Sminshall special(s)
20632144Sminshall register char *s;
20732144Sminshall {
20832144Sminshall 	register char c;
20932144Sminshall 	char b;
21032144Sminshall 
21132144Sminshall 	switch (*s) {
21232144Sminshall 	case '^':
21332144Sminshall 		b = *++s;
21432144Sminshall 		if (b == '?') {
21532144Sminshall 		    c = b | 0x40;		/* DEL */
21632144Sminshall 		} else {
21732144Sminshall 		    c = b & 0x1f;
21832144Sminshall 		}
21932144Sminshall 		break;
22032144Sminshall 	default:
22132144Sminshall 		c = *s;
22232144Sminshall 		break;
22332144Sminshall 	}
22432144Sminshall 	return c;
22532144Sminshall }
22632144Sminshall 
22732144Sminshall /*
22832144Sminshall  * Construct a control character sequence
22932144Sminshall  * for a special character.
23032144Sminshall  */
23132144Sminshall static char *
23232144Sminshall control(c)
23340245Sborman 	register cc_t c;
23432144Sminshall {
23544361Sborman 	static char buf[5];
23632144Sminshall 
23732144Sminshall 	if (c == 0x7f)
23832144Sminshall 		return ("^?");
239*45233Sborman 	if (c == (cc_t)_POSIX_VDISABLE) {
24032144Sminshall 		return "off";
24132144Sminshall 	}
242*45233Sborman 	if ((unsigned int)c >= 0x80) {
24344361Sborman 		buf[0] = '\\';
24444361Sborman 		buf[1] = ((c>>6)&07) + '0';
24544361Sborman 		buf[2] = ((c>>3)&07) + '0';
24644361Sborman 		buf[3] = (c&07) + '0';
24744361Sborman 		buf[4] = 0;
248*45233Sborman 	} else if ((unsigned int)c >= 0x20) {
24932144Sminshall 		buf[0] = c;
25032144Sminshall 		buf[1] = 0;
25132144Sminshall 	} else {
25232144Sminshall 		buf[0] = '^';
25332144Sminshall 		buf[1] = '@'+c;
25432144Sminshall 		buf[2] = 0;
25532144Sminshall 	}
25632144Sminshall 	return (buf);
25732144Sminshall }
25832144Sminshall 
25932144Sminshall 
26032144Sminshall 
26132144Sminshall /*
26232144Sminshall  *	The following are data structures and routines for
26332144Sminshall  *	the "send" command.
26432144Sminshall  *
26532144Sminshall  */
26632144Sminshall 
26732144Sminshall struct sendlist {
26832144Sminshall     char	*name;		/* How user refers to it (case independent) */
26932144Sminshall     char	*help;		/* Help information (0 ==> no help) */
27032144Sminshall #if	defined(NOT43)
27138689Sborman     int		(*handler)();	/* Routine to perform (for special ops) */
27232144Sminshall #else	/* defined(NOT43) */
27338689Sborman     void	(*handler)();	/* Routine to perform (for special ops) */
27432144Sminshall #endif	/* defined(NOT43) */
27538689Sborman     int		what;		/* Character to be sent (<0 ==> special) */
27632144Sminshall };
27732144Sminshall 
27832144Sminshall #define	SENDQUESTION	-1
27932144Sminshall #define	SENDESCAPE	-3
28032144Sminshall 
28132144Sminshall static struct sendlist Sendlist[] = {
28238689Sborman     { "ao",	"Send Telnet Abort output",		0,	AO },
28338689Sborman     { "ayt",	"Send Telnet 'Are You There'",		0,	AYT },
28438689Sborman     { "brk",	"Send Telnet Break",			0,	BREAK },
28538689Sborman     { "ec",	"Send Telnet Erase Character",		0,	EC },
28638689Sborman     { "el",	"Send Telnet Erase Line",		0,	EL },
28738689Sborman     { "escape",	"Send current escape character",	0,	SENDESCAPE },
28838689Sborman     { "ga",	"Send Telnet 'Go Ahead' sequence",	0,	GA },
28938689Sborman     { "ip",	"Send Telnet Interrupt Process",	0,	IP },
29038689Sborman     { "nop",	"Send Telnet 'No operation'",		0,	NOP },
29138689Sborman     { "eor",	"Send Telnet 'End of Record'",		0,	EOR },
29238689Sborman     { "abort",	"Send Telnet 'Abort Process'",		0,	ABORT },
29338689Sborman     { "susp",	"Send Telnet 'Suspend Process'",	0,	SUSP },
29438689Sborman     { "eof",	"Send Telnet End of File Character",	0,	xEOF },
29538689Sborman     { "synch",	"Perform Telnet 'Synch operation'",	dosynch, SYNCH },
29638909Sborman     { "getstatus", "Send request for STATUS",		get_status, 0 },
29738689Sborman     { "?",	"Display send options",			0,	SENDQUESTION },
29832144Sminshall     { 0 }
29932144Sminshall };
30032144Sminshall 
30132144Sminshall static struct sendlist Sendlist2[] = {		/* some synonyms */
30238689Sborman     { "break",		0, 0, BREAK },
30332144Sminshall 
30438689Sborman     { "intp",		0, 0, IP },
30538689Sborman     { "interrupt",	0, 0, IP },
30638689Sborman     { "intr",		0, 0, IP },
30732144Sminshall 
30838689Sborman     { "help",		0, 0, SENDQUESTION },
30932144Sminshall 
31038689Sborman     { 0 }
31132144Sminshall };
31232144Sminshall 
31332144Sminshall static char **
31432144Sminshall getnextsend(name)
31532144Sminshall char *name;
31632144Sminshall {
31732144Sminshall     struct sendlist *c = (struct sendlist *) name;
31832144Sminshall 
31932144Sminshall     return (char **) (c+1);
32032144Sminshall }
32132144Sminshall 
32232144Sminshall static struct sendlist *
32332144Sminshall getsend(name)
32432144Sminshall char *name;
32532144Sminshall {
32632144Sminshall     struct sendlist *sl;
32732144Sminshall 
32832144Sminshall     if ((sl = (struct sendlist *)
32932144Sminshall 			genget(name, (char **) Sendlist, getnextsend)) != 0) {
33032144Sminshall 	return sl;
33132144Sminshall     } else {
33232144Sminshall 	return (struct sendlist *)
33332144Sminshall 				genget(name, (char **) Sendlist2, getnextsend);
33432144Sminshall     }
33532144Sminshall }
33632144Sminshall 
33732144Sminshall static
33832144Sminshall sendcmd(argc, argv)
33932144Sminshall int	argc;
34032144Sminshall char	**argv;
34132144Sminshall {
34232144Sminshall     int what;		/* what we are sending this time */
34332144Sminshall     int count;		/* how many bytes we are going to need to send */
34432144Sminshall     int i;
34532144Sminshall     int question = 0;	/* was at least one argument a question */
34632144Sminshall     struct sendlist *s;	/* pointer to current command */
34732144Sminshall 
34832144Sminshall     if (argc < 2) {
34932144Sminshall 	printf("need at least one argument for 'send' command\n");
35032144Sminshall 	printf("'send ?' for help\n");
35132144Sminshall 	return 0;
35232144Sminshall     }
35332144Sminshall     /*
35432144Sminshall      * First, validate all the send arguments.
35532144Sminshall      * In addition, we see how much space we are going to need, and
35632144Sminshall      * whether or not we will be doing a "SYNCH" operation (which
35732144Sminshall      * flushes the network queue).
35832144Sminshall      */
35932144Sminshall     count = 0;
36032144Sminshall     for (i = 1; i < argc; i++) {
36132144Sminshall 	s = getsend(argv[i]);
36232144Sminshall 	if (s == 0) {
36332144Sminshall 	    printf("Unknown send argument '%s'\n'send ?' for help.\n",
36432144Sminshall 			argv[i]);
36532144Sminshall 	    return 0;
36632144Sminshall 	} else if (Ambiguous(s)) {
36732144Sminshall 	    printf("Ambiguous send argument '%s'\n'send ?' for help.\n",
36832144Sminshall 			argv[i]);
36932144Sminshall 	    return 0;
37032144Sminshall 	}
37132144Sminshall 	switch (s->what) {
37232144Sminshall 	case SENDQUESTION:
37338689Sborman 	    question = 1;
37432144Sminshall 	    break;
37532144Sminshall 	case SENDESCAPE:
37632144Sminshall 	    count += 1;
37732144Sminshall 	    break;
37832144Sminshall 	case SYNCH:
37932144Sminshall 	    count += 2;
38032144Sminshall 	    break;
38132144Sminshall 	default:
38232144Sminshall 	    count += 2;
38332144Sminshall 	    break;
38432144Sminshall 	}
38532144Sminshall     }
38638689Sborman     if (!connected) {
38738689Sborman 	if (count)
38838689Sborman 	    printf("?Need to be connected first.\n");
38938689Sborman 	if (question) {
39038689Sborman 	    for (s = Sendlist; s->name; s++)
39138689Sborman 		if (s->help)
39238689Sborman 		    printf("%-15s %s\n", s->name, s->help);
39338689Sborman 	} else
39438689Sborman 	    printf("'send ?' for help\n");
39538689Sborman 	return !question;
39638689Sborman     }
39732144Sminshall     /* Now, do we have enough room? */
39832144Sminshall     if (NETROOM() < count) {
39932144Sminshall 	printf("There is not enough room in the buffer TO the network\n");
40032144Sminshall 	printf("to process your request.  Nothing will be done.\n");
40132144Sminshall 	printf("('send synch' will throw away most data in the network\n");
40232144Sminshall 	printf("buffer, if this might help.)\n");
40332144Sminshall 	return 0;
40432144Sminshall     }
40532144Sminshall     /* OK, they are all OK, now go through again and actually send */
40632144Sminshall     for (i = 1; i < argc; i++) {
40732144Sminshall 	if ((s = getsend(argv[i])) == 0) {
40832144Sminshall 	    fprintf(stderr, "Telnet 'send' error - argument disappeared!\n");
40944361Sborman 	    (void) quit();
41032144Sminshall 	    /*NOTREACHED*/
41132144Sminshall 	}
41238689Sborman 	if (s->handler) {
41338689Sborman 	    (*s->handler)(s);
41432144Sminshall 	} else {
41532144Sminshall 	    switch (what = s->what) {
41632144Sminshall 	    case SYNCH:
41732144Sminshall 		dosynch();
41832144Sminshall 		break;
41932144Sminshall 	    case SENDQUESTION:
42032144Sminshall 		for (s = Sendlist; s->name; s++) {
42138689Sborman 		    if (s->help)
42238689Sborman 			printf("%-15s %s\n", s->name, s->help);
42332144Sminshall 		}
42432144Sminshall 		question = 1;
42532144Sminshall 		break;
42632144Sminshall 	    case SENDESCAPE:
42732144Sminshall 		NETADD(escape);
42832144Sminshall 		break;
42932144Sminshall 	    default:
43032144Sminshall 		NET2ADD(IAC, what);
431*45233Sborman 		printoption("SENT", "IAC", what);
43232144Sminshall 		break;
43332144Sminshall 	    }
43432144Sminshall 	}
43532144Sminshall     }
43632144Sminshall     return !question;
43732144Sminshall }
43832144Sminshall 
43932144Sminshall /*
44032144Sminshall  * The following are the routines and data structures referred
44132144Sminshall  * to by the arguments to the "toggle" command.
44232144Sminshall  */
44332144Sminshall 
44432144Sminshall static
44532144Sminshall lclchars()
44632144Sminshall {
44732144Sminshall     donelclchars = 1;
44832144Sminshall     return 1;
44932144Sminshall }
45032144Sminshall 
45132144Sminshall static
45232144Sminshall togdebug()
45332144Sminshall {
45432144Sminshall #ifndef	NOT43
45532144Sminshall     if (net > 0 &&
45632144Sminshall 	(SetSockOpt(net, SOL_SOCKET, SO_DEBUG, debug)) < 0) {
45732144Sminshall 	    perror("setsockopt (SO_DEBUG)");
45832144Sminshall     }
45932144Sminshall #else	/* NOT43 */
46032144Sminshall     if (debug) {
46132144Sminshall 	if (net > 0 && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 0, 0) < 0)
46232144Sminshall 	    perror("setsockopt (SO_DEBUG)");
46332144Sminshall     } else
46432144Sminshall 	printf("Cannot turn off socket debugging\n");
46532144Sminshall #endif	/* NOT43 */
46632144Sminshall     return 1;
46732144Sminshall }
46832144Sminshall 
46932144Sminshall 
47032144Sminshall static int
47132144Sminshall togcrlf()
47232144Sminshall {
47332144Sminshall     if (crlf) {
47432144Sminshall 	printf("Will send carriage returns as telnet <CR><LF>.\n");
47532144Sminshall     } else {
47632144Sminshall 	printf("Will send carriage returns as telnet <CR><NUL>.\n");
47732144Sminshall     }
47832144Sminshall     return 1;
47932144Sminshall }
48032144Sminshall 
48138909Sborman int binmode;
48232144Sminshall 
48332144Sminshall static int
48438689Sborman togbinary(val)
48538689Sborman int val;
48632144Sminshall {
48732144Sminshall     donebinarytoggle = 1;
48832144Sminshall 
48938909Sborman     if (val >= 0) {
49038909Sborman 	binmode = val;
49138909Sborman     } else {
49238909Sborman 	if (my_want_state_is_will(TELOPT_BINARY) &&
49338909Sborman 				my_want_state_is_do(TELOPT_BINARY)) {
49438909Sborman 	    binmode = 1;
49538909Sborman 	} else if (my_want_state_is_wont(TELOPT_BINARY) &&
49638909Sborman 				my_want_state_is_dont(TELOPT_BINARY)) {
49738909Sborman 	    binmode = 0;
49838909Sborman 	}
49938909Sborman 	val = binmode ? 0 : 1;
50038909Sborman     }
50138909Sborman 
50238909Sborman     if (val == 1) {
50338909Sborman 	if (my_want_state_is_will(TELOPT_BINARY) &&
50438909Sborman 					my_want_state_is_do(TELOPT_BINARY)) {
50538689Sborman 	    printf("Already operating in binary mode with remote host.\n");
50638909Sborman 	} else {
50738909Sborman 	    printf("Negotiating binary mode with remote host.\n");
50838909Sborman 	    tel_enter_binary(3);
50938689Sborman 	}
51038909Sborman     } else {
51138909Sborman 	if (my_want_state_is_wont(TELOPT_BINARY) &&
51238909Sborman 					my_want_state_is_dont(TELOPT_BINARY)) {
51338689Sborman 	    printf("Already in network ascii mode with remote host.\n");
51438909Sborman 	} else {
51538909Sborman 	    printf("Negotiating network ascii mode with remote host.\n");
51638909Sborman 	    tel_leave_binary(3);
51738689Sborman 	}
51832144Sminshall     }
51932144Sminshall     return 1;
52032144Sminshall }
52132144Sminshall 
52238909Sborman static int
52338909Sborman togrbinary(val)
52438909Sborman int val;
52538909Sborman {
52638909Sborman     donebinarytoggle = 1;
52732144Sminshall 
52838909Sborman     if (val == -1)
52938909Sborman 	val = my_want_state_is_do(TELOPT_BINARY) ? 0 : 1;
53032144Sminshall 
53138909Sborman     if (val == 1) {
53238909Sborman 	if (my_want_state_is_do(TELOPT_BINARY)) {
53338909Sborman 	    printf("Already receiving in binary mode.\n");
53438909Sborman 	} else {
53538909Sborman 	    printf("Negotiating binary mode on input.\n");
53638909Sborman 	    tel_enter_binary(1);
53738909Sborman 	}
53838909Sborman     } else {
53938909Sborman 	if (my_want_state_is_dont(TELOPT_BINARY)) {
54038909Sborman 	    printf("Already receiving in network ascii mode.\n");
54138909Sborman 	} else {
54238909Sborman 	    printf("Negotiating network ascii mode on input.\n");
54338909Sborman 	    tel_leave_binary(1);
54438909Sborman 	}
54538909Sborman     }
54638909Sborman     return 1;
54738909Sborman }
54838909Sborman 
54938909Sborman static int
55038909Sborman togxbinary(val)
55138909Sborman int val;
55238909Sborman {
55338909Sborman     donebinarytoggle = 1;
55438909Sborman 
55538909Sborman     if (val == -1)
55638909Sborman 	val = my_want_state_is_will(TELOPT_BINARY) ? 0 : 1;
55738909Sborman 
55838909Sborman     if (val == 1) {
55938909Sborman 	if (my_want_state_is_will(TELOPT_BINARY)) {
56038909Sborman 	    printf("Already transmitting in binary mode.\n");
56138909Sborman 	} else {
56238909Sborman 	    printf("Negotiating binary mode on output.\n");
56338909Sborman 	    tel_enter_binary(2);
56438909Sborman 	}
56538909Sborman     } else {
56638909Sborman 	if (my_want_state_is_wont(TELOPT_BINARY)) {
56738909Sborman 	    printf("Already transmitting in network ascii mode.\n");
56838909Sborman 	} else {
56938909Sborman 	    printf("Negotiating network ascii mode on output.\n");
57038909Sborman 	    tel_leave_binary(2);
57138909Sborman 	}
57238909Sborman     }
57338909Sborman     return 1;
57438909Sborman }
57538909Sborman 
57638909Sborman 
57732144Sminshall extern int togglehelp();
57838689Sborman extern int slc_check();
57932144Sminshall 
58032144Sminshall struct togglelist {
58132144Sminshall     char	*name;		/* name of toggle */
58232144Sminshall     char	*help;		/* help message */
58332144Sminshall     int		(*handler)();	/* routine to do actual setting */
58432144Sminshall     int		*variable;
58532144Sminshall     char	*actionexplanation;
58632144Sminshall };
58732144Sminshall 
58832144Sminshall static struct togglelist Togglelist[] = {
58932144Sminshall     { "autoflush",
59038689Sborman 	"flushing of output when sending interrupt characters",
59132144Sminshall 	    0,
59238689Sborman 		&autoflush,
59338689Sborman 		    "flush output when sending interrupt characters" },
59432144Sminshall     { "autosynch",
59538689Sborman 	"automatic sending of interrupt characters in urgent mode",
59632144Sminshall 	    0,
59738689Sborman 		&autosynch,
59838689Sborman 		    "send interrupt characters in urgent mode" },
59932144Sminshall     { "binary",
60038689Sborman 	"sending and receiving of binary data",
60132144Sminshall 	    togbinary,
60238689Sborman 		0,
60338689Sborman 		    0 },
60438909Sborman     { "inbinary",
60538909Sborman 	"receiving of binary data",
60638909Sborman 	    togrbinary,
60738909Sborman 		0,
60838909Sborman 		    0 },
60938909Sborman     { "outbinary",
61038909Sborman 	"sending of binary data",
61138909Sborman 	    togxbinary,
61238909Sborman 		0,
61338909Sborman 		    0 },
61432144Sminshall     { "crlf",
61538689Sborman 	"sending carriage returns as telnet <CR><LF>",
61632144Sminshall 	    togcrlf,
61738689Sborman 		&crlf,
61838689Sborman 		    0 },
61932144Sminshall     { "crmod",
62038689Sborman 	"mapping of received carriage returns",
62132144Sminshall 	    0,
62238689Sborman 		&crmod,
62338689Sborman 		    "map carriage return on output" },
62432144Sminshall     { "localchars",
62538689Sborman 	"local recognition of certain control characters",
62632144Sminshall 	    lclchars,
62738689Sborman 		&localchars,
62838689Sborman 		    "recognize certain control characters" },
62943317Skfall #ifdef	KERBEROS
63043317Skfall     { "kerberos",
63143317Skfall 	"toggle use of Kerberos authentication",
63243317Skfall 	    0,
63343317Skfall 		&kerberized,
63443317Skfall 		    "use Kerberos authentication" },
63543317Skfall #endif
63638689Sborman     { " ", "", 0 },		/* empty line */
63738208Sminshall #if	defined(unix) && defined(TN3270)
63838920Sminshall     { "apitrace",
63938920Sminshall 	"(debugging) toggle tracing of API transactions",
64038920Sminshall 	    0,
64138920Sminshall 		&apitrace,
64238920Sminshall 		    "trace API transactions" },
64338208Sminshall     { "cursesdata",
64438208Sminshall 	"(debugging) toggle printing of hexadecimal curses data",
64538208Sminshall 	    0,
64638689Sborman 		&cursesdata,
64738689Sborman 		    "print hexadecimal representation of curses data" },
64838208Sminshall #endif	/* defined(unix) && defined(TN3270) */
64932144Sminshall     { "debug",
65038689Sborman 	"debugging",
65132144Sminshall 	    togdebug,
65238689Sborman 		&debug,
65338689Sborman 		    "turn on socket level debugging" },
65432144Sminshall     { "netdata",
65538689Sborman 	"printing of hexadecimal network data (debugging)",
65632144Sminshall 	    0,
65738689Sborman 		&netdata,
65838689Sborman 		    "print hexadecimal representation of network traffic" },
65938689Sborman     { "prettydump",
66038689Sborman 	"output of \"netdata\" to user readable format (debugging)",
66138689Sborman 	    0,
66238689Sborman 		&prettydump,
66338689Sborman 		    "print user readable output for \"netdata\"" },
66432144Sminshall     { "options",
66538689Sborman 	"viewing of options processing (debugging)",
66632144Sminshall 	    0,
66738689Sborman 		&showoptions,
66838689Sborman 		    "show option processing" },
66938208Sminshall #if	defined(unix)
67038208Sminshall     { "termdata",
67138208Sminshall 	"(debugging) toggle printing of hexadecimal terminal data",
67238208Sminshall 	    0,
67338689Sborman 		&termdata,
67438689Sborman 		    "print hexadecimal representation of terminal traffic" },
67538208Sminshall #endif	/* defined(unix) */
67632144Sminshall     { "?",
67738689Sborman 	0,
67838689Sborman 	    togglehelp },
67932144Sminshall     { "help",
68038689Sborman 	0,
68138689Sborman 	    togglehelp },
68232144Sminshall     { 0 }
68332144Sminshall };
68432144Sminshall 
68532144Sminshall static
68632144Sminshall togglehelp()
68732144Sminshall {
68832144Sminshall     struct togglelist *c;
68932144Sminshall 
69032144Sminshall     for (c = Togglelist; c->name; c++) {
69138689Sborman 	if (c->help) {
69238689Sborman 	    if (*c->help)
69338689Sborman 		printf("%-15s toggle %s\n", c->name, c->help);
69438689Sborman 	    else
69538689Sborman 		printf("\n");
69632144Sminshall 	}
69732144Sminshall     }
69838689Sborman     printf("\n");
69938689Sborman     printf("%-15s %s\n", "?", "display help information");
70032144Sminshall     return 0;
70132144Sminshall }
70232144Sminshall 
70338689Sborman static
70438689Sborman settogglehelp(set)
70538689Sborman int set;
70638689Sborman {
70738689Sborman     struct togglelist *c;
70838689Sborman 
70938689Sborman     for (c = Togglelist; c->name; c++) {
71038689Sborman 	if (c->help) {
71138689Sborman 	    if (*c->help)
71238689Sborman 		printf("%-15s %s %s\n", c->name, set ? "enable" : "disable",
71338689Sborman 						c->help);
71438689Sborman 	    else
71538689Sborman 		printf("\n");
71638689Sborman 	}
71738689Sborman     }
71838689Sborman }
71938689Sborman 
72032144Sminshall static char **
72132144Sminshall getnexttoggle(name)
72232144Sminshall char *name;
72332144Sminshall {
72432144Sminshall     struct togglelist *c = (struct togglelist *) name;
72532144Sminshall 
72632144Sminshall     return (char **) (c+1);
72732144Sminshall }
72832144Sminshall 
72932144Sminshall static struct togglelist *
73032144Sminshall gettoggle(name)
73132144Sminshall char *name;
73232144Sminshall {
73332144Sminshall     return (struct togglelist *)
73432144Sminshall 			genget(name, (char **) Togglelist, getnexttoggle);
73532144Sminshall }
73632144Sminshall 
73732144Sminshall static
73832144Sminshall toggle(argc, argv)
73932144Sminshall int	argc;
74032144Sminshall char	*argv[];
74132144Sminshall {
74232144Sminshall     int retval = 1;
74332144Sminshall     char *name;
74432144Sminshall     struct togglelist *c;
74532144Sminshall 
74632144Sminshall     if (argc < 2) {
74732144Sminshall 	fprintf(stderr,
74832144Sminshall 	    "Need an argument to 'toggle' command.  'toggle ?' for help.\n");
74932144Sminshall 	return 0;
75032144Sminshall     }
75132144Sminshall     argc--;
75232144Sminshall     argv++;
75332144Sminshall     while (argc--) {
75432144Sminshall 	name = *argv++;
75532144Sminshall 	c = gettoggle(name);
75632144Sminshall 	if (Ambiguous(c)) {
75732144Sminshall 	    fprintf(stderr, "'%s': ambiguous argument ('toggle ?' for help).\n",
75832144Sminshall 					name);
75932144Sminshall 	    return 0;
76032144Sminshall 	} else if (c == 0) {
76132144Sminshall 	    fprintf(stderr, "'%s': unknown argument ('toggle ?' for help).\n",
76232144Sminshall 					name);
76332144Sminshall 	    return 0;
76432144Sminshall 	} else {
76532144Sminshall 	    if (c->variable) {
76632144Sminshall 		*c->variable = !*c->variable;		/* invert it */
76732144Sminshall 		if (c->actionexplanation) {
76832144Sminshall 		    printf("%s %s.\n", *c->variable? "Will" : "Won't",
76932144Sminshall 							c->actionexplanation);
77032144Sminshall 		}
77132144Sminshall 	    }
77232144Sminshall 	    if (c->handler) {
77338689Sborman 		retval &= (*c->handler)(-1);
77432144Sminshall 	    }
77532144Sminshall 	}
77632144Sminshall     }
77732144Sminshall     return retval;
77832144Sminshall }
77932144Sminshall 
78032144Sminshall /*
78132144Sminshall  * The following perform the "set" command.
78232144Sminshall  */
78332144Sminshall 
78438689Sborman #ifdef	USE_TERMIO
78538689Sborman struct termio new_tc = { 0 };
78638689Sborman #endif
78738689Sborman 
78832144Sminshall struct setlist {
78932144Sminshall     char *name;				/* name */
79032144Sminshall     char *help;				/* help information */
79138689Sborman     void (*handler)();
79240245Sborman     cc_t *charp;			/* where it is located at */
79332144Sminshall };
79432144Sminshall 
79532144Sminshall static struct setlist Setlist[] = {
79644361Sborman #ifdef	KLUDGELINEMODE
79738689Sborman     { "echo", 	"character to toggle local echoing on/off", 0, &echoc },
79844361Sborman #endif
79938689Sborman     { "escape",	"character to escape back to telnet command mode", 0, &escape },
800*45233Sborman     { "tracefile", "file to write trace information to", SetNetTrace, (cc_t *)NetTraceFile},
80132144Sminshall     { " ", "" },
80238689Sborman     { " ", "The following need 'localchars' to be toggled true", 0, 0 },
803*45233Sborman     { "flushoutput", "character to cause an Abort Output", 0, termFlushCharp },
80438689Sborman     { "interrupt", "character to cause an Interrupt Process", 0, termIntCharp },
80538689Sborman     { "quit",	"character to cause an Abort process", 0, termQuitCharp },
80638689Sborman     { "eof",	"character to cause an EOF ", 0, termEofCharp },
80738689Sborman     { " ", "" },
80838689Sborman     { " ", "The following are for local editing in linemode", 0, 0 },
80938689Sborman     { "erase",	"character to use to erase a character", 0, termEraseCharp },
81038689Sborman     { "kill",	"character to use to erase a line", 0, termKillCharp },
81138689Sborman     { "lnext",	"character to use for literal next", 0, termLiteralNextCharp },
81244361Sborman     { "susp",	"character to cause a Suspend Process", 0, termSuspCharp },
81338689Sborman     { "reprint", "character to use for line reprint", 0, termRprntCharp },
81438689Sborman     { "worderase", "character to use to erase a word", 0, termWerasCharp },
81538689Sborman     { "start",	"character to use for XON", 0, termStartCharp },
81644361Sborman     { "stop",	"character to use for XOFF", 0, termStopCharp },
81744361Sborman     { "forw1",	"alternate end of line character", 0, termForw1Charp },
81844361Sborman     { "forw2",	"alternate end of line character", 0, termForw2Charp },
819*45233Sborman     { "ayt",	"alternate AYT character", 0, termAytCharp },
82032144Sminshall     { 0 }
82132144Sminshall };
82232144Sminshall 
823*45233Sborman #if	defined(CRAY) && !defined(__STDC__)
824*45233Sborman /* Work around compiler bug in pcc 4.1.5 */
82538689Sborman _setlist_init()
82638689Sborman {
82744361Sborman #ifndef	KLUDGELINEMODE
82844361Sborman #define	N 4
82944361Sborman #else
83044361Sborman #define	N 5
83144361Sborman #endif
83244361Sborman 	Setlist[N+0].charp = &termFlushChar;
83344361Sborman 	Setlist[N+1].charp = &termIntChar;
83444361Sborman 	Setlist[N+2].charp = &termQuitChar;
83544361Sborman 	Setlist[N+3].charp = &termEofChar;
83644361Sborman 	Setlist[N+6].charp = &termEraseChar;
83744361Sborman 	Setlist[N+7].charp = &termKillChar;
83844361Sborman 	Setlist[N+8].charp = &termLiteralNextChar;
83944361Sborman 	Setlist[N+9].charp = &termSuspChar;
84044361Sborman 	Setlist[N+10].charp = &termRprntChar;
84144361Sborman 	Setlist[N+11].charp = &termWerasChar;
84244361Sborman 	Setlist[N+12].charp = &termStartChar;
84344361Sborman 	Setlist[N+13].charp = &termStopChar;
84444361Sborman 	Setlist[N+14].charp = &termForw1Char;
84544361Sborman 	Setlist[N+15].charp = &termForw2Char;
846*45233Sborman 	Setlist[N+16].charp = &termAytChar;
84744361Sborman #undef	N
84838689Sborman }
849*45233Sborman #endif	/* defined(CRAY) && !defined(__STDC__) */
85038689Sborman 
85132144Sminshall static char **
85232144Sminshall getnextset(name)
85332144Sminshall char *name;
85432144Sminshall {
85532144Sminshall     struct setlist *c = (struct setlist *)name;
85632144Sminshall 
85732144Sminshall     return (char **) (c+1);
85832144Sminshall }
85932144Sminshall 
86032144Sminshall static struct setlist *
86132144Sminshall getset(name)
86232144Sminshall char *name;
86332144Sminshall {
86432144Sminshall     return (struct setlist *) genget(name, (char **) Setlist, getnextset);
86532144Sminshall }
86632144Sminshall 
86744361Sborman set_escape_char(s)
86844361Sborman char *s;
86944361Sborman {
870*45233Sborman 	escape = (s && *s) ? special(s) : _POSIX_VDISABLE;
87144361Sborman 	printf("escape character is '%s'.\n", control(escape));
87244361Sborman }
87344361Sborman 
87432144Sminshall static
87532144Sminshall setcmd(argc, argv)
87632144Sminshall int	argc;
87732144Sminshall char	*argv[];
87832144Sminshall {
87932144Sminshall     int value;
88032144Sminshall     struct setlist *ct;
88138689Sborman     struct togglelist *c;
88232144Sminshall 
88338689Sborman     if (argc < 2 || argc > 3) {
88438689Sborman 	printf("Format is 'set Name Value'\n'set ?' for help.\n");
88532144Sminshall 	return 0;
88632144Sminshall     }
88738689Sborman     if ((argc == 2) &&
88838689Sborman 		((!strcmp(argv[1], "?")) || (!strcmp(argv[1], "help")))) {
88938689Sborman 	for (ct = Setlist; ct->name; ct++)
89038689Sborman 	    printf("%-15s %s\n", ct->name, ct->help);
89138689Sborman 	printf("\n");
89238689Sborman 	settogglehelp(1);
89338689Sborman 	printf("%-15s %s\n", "?", "display help information");
89438689Sborman 	return 0;
89538689Sborman     }
89632144Sminshall 
89732144Sminshall     ct = getset(argv[1]);
89832144Sminshall     if (ct == 0) {
89938689Sborman 	c = gettoggle(argv[1]);
90038689Sborman 	if (c == 0) {
90138689Sborman 	    fprintf(stderr, "'%s': unknown argument ('set ?' for help).\n",
90232144Sminshall 			argv[1]);
90338689Sborman 	    return 0;
90438689Sborman 	} else if (Ambiguous(c)) {
90538689Sborman 	    fprintf(stderr, "'%s': ambiguous argument ('set ?' for help).\n",
90638689Sborman 			argv[1]);
90738689Sborman 	    return 0;
90838689Sborman 	}
90938689Sborman 	if (c->variable) {
91038689Sborman 	    if ((argc == 2) || (strcmp("on", argv[2]) == 0))
91138689Sborman 		*c->variable = 1;
91238689Sborman 	    else if (strcmp("off", argv[2]) == 0)
91338689Sborman 		*c->variable = 0;
91438689Sborman 	    else {
91538689Sborman 		printf("Format is 'set togglename [on|off]'\n'set ?' for help.\n");
91638689Sborman 		return 0;
91738689Sborman 	    }
91838689Sborman 	    if (c->actionexplanation) {
91938689Sborman 		printf("%s %s.\n", *c->variable? "Will" : "Won't",
92038689Sborman 							c->actionexplanation);
92138689Sborman 	    }
92238689Sborman 	}
92338689Sborman 	if (c->handler)
92438689Sborman 	    (*c->handler)(1);
92538689Sborman     } else if (argc != 3) {
92638689Sborman 	printf("Format is 'set Name Value'\n'set ?' for help.\n");
92732144Sminshall 	return 0;
92832144Sminshall     } else if (Ambiguous(ct)) {
92932144Sminshall 	fprintf(stderr, "'%s': ambiguous argument ('set ?' for help).\n",
93032144Sminshall 			argv[1]);
93132144Sminshall 	return 0;
93238689Sborman     } else if (ct->handler) {
93338689Sborman 	(*ct->handler)(argv[2]);
93444361Sborman 	printf("%s set to \"%s\".\n", ct->name, (char *)ct->charp);
93532144Sminshall     } else {
93632144Sminshall 	if (strcmp("off", argv[2])) {
93732144Sminshall 	    value = special(argv[2]);
93832144Sminshall 	} else {
939*45233Sborman 	    value = _POSIX_VDISABLE;
94032144Sminshall 	}
94140245Sborman 	*(ct->charp) = (cc_t)value;
94232144Sminshall 	printf("%s character is '%s'.\n", ct->name, control(*(ct->charp)));
94332144Sminshall     }
94438689Sborman     slc_check();
94532144Sminshall     return 1;
94632144Sminshall }
94738689Sborman 
94838689Sborman static
94938689Sborman unsetcmd(argc, argv)
95038689Sborman int	argc;
95138689Sborman char	*argv[];
95238689Sborman {
95338689Sborman     struct setlist *ct;
95438689Sborman     struct togglelist *c;
95538689Sborman     register char *name;
95638689Sborman 
95738689Sborman     if (argc < 2) {
95838689Sborman 	fprintf(stderr,
95938689Sborman 	    "Need an argument to 'unset' command.  'unset ?' for help.\n");
96038689Sborman 	return 0;
96138689Sborman     }
96238689Sborman     if ((!strcmp(argv[1], "?")) || (!strcmp(argv[1], "help"))) {
96338689Sborman 	for (ct = Setlist; ct->name; ct++)
96438689Sborman 	    printf("%-15s %s\n", ct->name, ct->help);
96538689Sborman 	printf("\n");
96638689Sborman 	settogglehelp(0);
96738689Sborman 	printf("%-15s %s\n", "?", "display help information");
96838689Sborman 	return 0;
96938689Sborman     }
97038689Sborman 
97138689Sborman     argc--;
97238689Sborman     argv++;
97338689Sborman     while (argc--) {
97438689Sborman 	name = *argv++;
97538689Sborman 	ct = getset(name);
97638689Sborman 	if (ct == 0) {
97738689Sborman 	    c = gettoggle(name);
97838689Sborman 	    if (c == 0) {
97938689Sborman 		fprintf(stderr, "'%s': unknown argument ('unset ?' for help).\n",
98038689Sborman 			name);
98138689Sborman 		return 0;
98238689Sborman 	    } else if (Ambiguous(c)) {
98338689Sborman 		fprintf(stderr, "'%s': ambiguous argument ('unset ?' for help).\n",
98438689Sborman 			name);
98538689Sborman 		return 0;
98638689Sborman 	    }
98738689Sborman 	    if (c->variable) {
98838689Sborman 		*c->variable = 0;
98938689Sborman 		if (c->actionexplanation) {
99038689Sborman 		    printf("%s %s.\n", *c->variable? "Will" : "Won't",
99138689Sborman 							c->actionexplanation);
99238689Sborman 		}
99338689Sborman 	    }
99438689Sborman 	    if (c->handler)
99538689Sborman 		(*c->handler)(0);
99638689Sborman 	} else if (Ambiguous(ct)) {
99738689Sborman 	    fprintf(stderr, "'%s': ambiguous argument ('unset ?' for help).\n",
99838689Sborman 			name);
99938689Sborman 	    return 0;
100038689Sborman 	} else if (ct->handler) {
100138689Sborman 	    (*ct->handler)(0);
100244361Sborman 	    printf("%s reset to \"%s\".\n", ct->name, (char *)ct->charp);
100338689Sborman 	} else {
1004*45233Sborman 	    *(ct->charp) = _POSIX_VDISABLE;
100538689Sborman 	    printf("%s character is '%s'.\n", ct->name, control(*(ct->charp)));
100638689Sborman 	}
100738689Sborman     }
100838689Sborman     return 1;
100938689Sborman }
101032144Sminshall 
101132144Sminshall /*
101232144Sminshall  * The following are the data structures and routines for the
101332144Sminshall  * 'mode' command.
101432144Sminshall  */
101538689Sborman #ifdef	KLUDGELINEMODE
101638689Sborman extern int kludgelinemode;
101744361Sborman 
101844361Sborman dokludgemode()
101944361Sborman {
102044361Sborman     kludgelinemode = 1;
102144361Sborman     send_wont(TELOPT_LINEMODE, 1);
102244361Sborman     send_dont(TELOPT_SGA, 1);
102344361Sborman     send_dont(TELOPT_ECHO, 1);
102444361Sborman }
102538689Sborman #endif
102632144Sminshall 
102732144Sminshall static
102832144Sminshall dolinemode()
102932144Sminshall {
103038689Sborman #ifdef	KLUDGELINEMODE
103138689Sborman     if (kludgelinemode)
103238689Sborman 	send_dont(TELOPT_SGA, 1);
103338689Sborman #endif
103438689Sborman     send_will(TELOPT_LINEMODE, 1);
103538689Sborman     send_dont(TELOPT_ECHO, 1);
103632144Sminshall     return 1;
103732144Sminshall }
103832144Sminshall 
103932144Sminshall static
104032144Sminshall docharmode()
104132144Sminshall {
104238689Sborman #ifdef	KLUDGELINEMODE
104338689Sborman     if (kludgelinemode)
104438689Sborman 	send_do(TELOPT_SGA, 1);
104538689Sborman     else
104638689Sborman #endif
104738689Sborman     send_wont(TELOPT_LINEMODE, 1);
104838689Sborman     send_do(TELOPT_ECHO, 1);
104938689Sborman     return 1;
105038689Sborman }
105138689Sborman 
105238689Sborman setmode(bit)
105338689Sborman {
105438689Sborman     return dolmmode(bit, 1);
105538689Sborman }
105638689Sborman 
105738689Sborman clearmode(bit)
105838689Sborman {
105938689Sborman     return dolmmode(bit, 0);
106038689Sborman }
106138689Sborman 
106238689Sborman dolmmode(bit, on)
106338689Sborman int bit, on;
106438689Sborman {
106538689Sborman     char c;
106638689Sborman     extern int linemode;
106738689Sborman 
106838689Sborman     if (my_want_state_is_wont(TELOPT_LINEMODE)) {
106938689Sborman 	printf("?Need to have LINEMODE option enabled first.\n");
107038689Sborman 	printf("'mode ?' for help.\n");
107138689Sborman 	return 0;
107232144Sminshall     }
107338689Sborman 
107438689Sborman     if (on)
107538689Sborman 	c = (linemode | bit);
107638689Sborman     else
107738689Sborman 	c = (linemode & ~bit);
107838689Sborman     lm_mode(&c, 1, 1);
107932144Sminshall     return 1;
108032144Sminshall }
108132144Sminshall 
108238689Sborman struct modelist {
108338689Sborman 	char	*name;		/* command name */
108438689Sborman 	char	*help;		/* help string */
108538689Sborman 	int	(*handler)();	/* routine which executes command */
108638689Sborman 	int	needconnect;	/* Do we need to be connected to execute? */
108738689Sborman 	int	arg1;
108838689Sborman };
108938689Sborman 
109038689Sborman extern int modehelp();
109138689Sborman 
109238689Sborman static struct modelist ModeList[] = {
109338689Sborman     { "character", "Disable LINEMODE option",	docharmode, 1 },
109439529Sborman #ifdef	KLUDGELINEMODE
109539529Sborman     { "",	"(or disable obsolete line-by-line mode)", 0 },
109638689Sborman #endif
109738689Sborman     { "line",	"Enable LINEMODE option",	dolinemode, 1 },
109839529Sborman #ifdef	KLUDGELINEMODE
109939529Sborman     { "",	"(or enable obsolete line-by-line mode)", 0 },
110038689Sborman #endif
110138689Sborman     { "", "", 0 },
110238689Sborman     { "",	"These require the LINEMODE option to be enabled", 0 },
110338689Sborman     { "isig",	"Enable signal trapping",	setmode, 1, MODE_TRAPSIG },
110438689Sborman     { "+isig",	0,				setmode, 1, MODE_TRAPSIG },
110538689Sborman     { "-isig",	"Disable signal trapping",	clearmode, 1, MODE_TRAPSIG },
110638689Sborman     { "edit",	"Enable character editing",	setmode, 1, MODE_EDIT },
110738689Sborman     { "+edit",	0,				setmode, 1, MODE_EDIT },
110838689Sborman     { "-edit",	"Disable character editing",	clearmode, 1, MODE_EDIT },
110944361Sborman     { "softtabs", "Enable tab expansion",	setmode, 1, MODE_SOFT_TAB },
111044361Sborman     { "+softtabs", 0,				setmode, 1, MODE_SOFT_TAB },
111144361Sborman     { "-softtabs", "Disable character editing",	clearmode, 1, MODE_SOFT_TAB },
111244361Sborman     { "litecho", "Enable literal character echo", setmode, 1, MODE_LIT_ECHO },
111344361Sborman     { "+litecho", 0,				setmode, 1, MODE_LIT_ECHO },
111444361Sborman     { "-litecho", "Disable literal character echo", clearmode, 1, MODE_LIT_ECHO },
111538689Sborman     { "help",	0,				modehelp, 0 },
111644361Sborman #ifdef	KLUDGELINEMODE
111744361Sborman     { "kludgeline", 0,				dokludgemode, 1 },
111844361Sborman #endif
111944361Sborman     { "", "", 0 },
112038689Sborman     { "?",	"Print help information",	modehelp, 0 },
112132144Sminshall     { 0 },
112232144Sminshall };
112332144Sminshall 
112432144Sminshall static char **
112532144Sminshall getnextmode(name)
112632144Sminshall char *name;
112732144Sminshall {
112838689Sborman     return (char **) (((struct modelist *)name)+1);
112932144Sminshall }
113032144Sminshall 
113138689Sborman static struct modelist *
113232144Sminshall getmodecmd(name)
113332144Sminshall char *name;
113432144Sminshall {
113538689Sborman     return (struct modelist *) genget(name, (char **) ModeList, getnextmode);
113632144Sminshall }
113732144Sminshall 
113838689Sborman modehelp()
113938689Sborman {
114038689Sborman     struct modelist *mt;
114138689Sborman 
114238689Sborman     printf("format is:  'mode Mode', where 'Mode' is one of:\n\n");
114338689Sborman     for (mt = ModeList; mt->name; mt++) {
114438689Sborman 	if (mt->help) {
114538689Sborman 	    if (*mt->help)
114638689Sborman 		printf("%-15s %s\n", mt->name, mt->help);
114738689Sborman 	    else
114838689Sborman 		printf("\n");
114938689Sborman 	}
115038689Sborman     }
115138689Sborman     return 0;
115238689Sborman }
115338689Sborman 
115432144Sminshall static
115532144Sminshall modecmd(argc, argv)
115632144Sminshall int	argc;
115732144Sminshall char	*argv[];
115832144Sminshall {
115938689Sborman     struct modelist *mt;
116032144Sminshall 
116138689Sborman     if (argc != 2) {
116238689Sborman 	printf("'mode' command requires an argument\n");
116338689Sborman 	printf("'mode ?' for help.\n");
116438689Sborman     } else if ((mt = getmodecmd(argv[1])) == 0) {
116532144Sminshall 	fprintf(stderr, "Unknown mode '%s' ('mode ?' for help).\n", argv[1]);
116632144Sminshall     } else if (Ambiguous(mt)) {
116732144Sminshall 	fprintf(stderr, "Ambiguous mode '%s' ('mode ?' for help).\n", argv[1]);
116838689Sborman     } else if (mt->needconnect && !connected) {
116938689Sborman 	printf("?Need to be connected first.\n");
117038689Sborman 	printf("'mode ?' for help.\n");
117138689Sborman     } else if (mt->handler) {
117238689Sborman 	return (*mt->handler)(mt->arg1);
117332144Sminshall     }
117438689Sborman     return 0;
117532144Sminshall }
117632144Sminshall 
117732144Sminshall /*
117832144Sminshall  * The following data structures and routines implement the
117932144Sminshall  * "display" command.
118032144Sminshall  */
118132144Sminshall 
118232144Sminshall static
118332144Sminshall display(argc, argv)
118432144Sminshall int	argc;
118532144Sminshall char	*argv[];
118632144Sminshall {
118732144Sminshall #define	dotog(tl)	if (tl->variable && tl->actionexplanation) { \
118832144Sminshall 			    if (*tl->variable) { \
118932144Sminshall 				printf("will"); \
119032144Sminshall 			    } else { \
119132144Sminshall 				printf("won't"); \
119232144Sminshall 			    } \
119332144Sminshall 			    printf(" %s.\n", tl->actionexplanation); \
119432144Sminshall 			}
119532144Sminshall 
119632144Sminshall #define	doset(sl)   if (sl->name && *sl->name != ' ') { \
119738689Sborman 			if (sl->handler == 0) \
119838689Sborman 			    printf("%-15s [%s]\n", sl->name, control(*sl->charp)); \
119938689Sborman 			else \
120044361Sborman 			    printf("%-15s \"%s\"\n", sl->name, (char *)sl->charp); \
120132144Sminshall 		    }
120232144Sminshall 
120332144Sminshall     struct togglelist *tl;
120432144Sminshall     struct setlist *sl;
120532144Sminshall 
120632144Sminshall     if (argc == 1) {
120732144Sminshall 	for (tl = Togglelist; tl->name; tl++) {
120832144Sminshall 	    dotog(tl);
120932144Sminshall 	}
121032144Sminshall 	printf("\n");
121132144Sminshall 	for (sl = Setlist; sl->name; sl++) {
121232144Sminshall 	    doset(sl);
121332144Sminshall 	}
121432144Sminshall     } else {
121532144Sminshall 	int i;
121632144Sminshall 
121732144Sminshall 	for (i = 1; i < argc; i++) {
121832144Sminshall 	    sl = getset(argv[i]);
121932144Sminshall 	    tl = gettoggle(argv[i]);
122032144Sminshall 	    if (Ambiguous(sl) || Ambiguous(tl)) {
122132144Sminshall 		printf("?Ambiguous argument '%s'.\n", argv[i]);
122232144Sminshall 		return 0;
122332144Sminshall 	    } else if (!sl && !tl) {
122432144Sminshall 		printf("?Unknown argument '%s'.\n", argv[i]);
122532144Sminshall 		return 0;
122632144Sminshall 	    } else {
122732144Sminshall 		if (tl) {
122832144Sminshall 		    dotog(tl);
122932144Sminshall 		}
123032144Sminshall 		if (sl) {
123132144Sminshall 		    doset(sl);
123232144Sminshall 		}
123332144Sminshall 	    }
123432144Sminshall 	}
123532144Sminshall     }
123638689Sborman /*@*/optionstatus();
123732144Sminshall     return 1;
123832144Sminshall #undef	doset
123932144Sminshall #undef	dotog
124032144Sminshall }
124132144Sminshall 
124232144Sminshall /*
124332144Sminshall  * The following are the data structures, and many of the routines,
124432144Sminshall  * relating to command processing.
124532144Sminshall  */
124632144Sminshall 
124732144Sminshall /*
124832144Sminshall  * Set the escape character.
124932144Sminshall  */
125032144Sminshall static
125132144Sminshall setescape(argc, argv)
125232144Sminshall 	int argc;
125332144Sminshall 	char *argv[];
125432144Sminshall {
125532144Sminshall 	register char *arg;
125632144Sminshall 	char buf[50];
125732144Sminshall 
125832144Sminshall 	printf(
125932144Sminshall 	    "Deprecated usage - please use 'set escape%s%s' in the future.\n",
126032144Sminshall 				(argc > 2)? " ":"", (argc > 2)? argv[1]: "");
126132144Sminshall 	if (argc > 2)
126232144Sminshall 		arg = argv[1];
126332144Sminshall 	else {
126432144Sminshall 		printf("new escape character: ");
126534849Sminshall 		(void) gets(buf);
126632144Sminshall 		arg = buf;
126732144Sminshall 	}
126832144Sminshall 	if (arg[0] != '\0')
126932144Sminshall 		escape = arg[0];
127032144Sminshall 	if (!In3270) {
127132144Sminshall 		printf("Escape character is '%s'.\n", control(escape));
127232144Sminshall 	}
127334849Sminshall 	(void) fflush(stdout);
127432144Sminshall 	return 1;
127532144Sminshall }
127632144Sminshall 
127732144Sminshall /*VARARGS*/
127832144Sminshall static
127932144Sminshall togcrmod()
128032144Sminshall {
128132144Sminshall     crmod = !crmod;
128232144Sminshall     printf("Deprecated usage - please use 'toggle crmod' in the future.\n");
128332144Sminshall     printf("%s map carriage return on output.\n", crmod ? "Will" : "Won't");
128434849Sminshall     (void) fflush(stdout);
128532144Sminshall     return 1;
128632144Sminshall }
128732144Sminshall 
128832144Sminshall /*VARARGS*/
128932144Sminshall suspend()
129032144Sminshall {
129138689Sborman #ifdef	SIGTSTP
129237219Sminshall     setcommandmode();
129337219Sminshall     {
129444361Sborman 	long oldrows, oldcols, newrows, newcols, err;
129537219Sminshall 
129644361Sborman 	err = TerminalWindowSize(&oldrows, &oldcols);
129734849Sminshall 	(void) kill(0, SIGTSTP);
129844361Sborman 	err += TerminalWindowSize(&newrows, &newcols);
129944361Sborman 	if (connected && !err &&
130044361Sborman 	    ((oldrows != newrows) || (oldcols != newcols))) {
130137219Sminshall 		sendnaws();
130237219Sminshall 	}
130337219Sminshall     }
130437219Sminshall     /* reget parameters in case they were changed */
130537219Sminshall     TerminalSaveState();
130638689Sborman     setconnmode(0);
130738689Sborman #else
130838689Sborman     printf("Suspend is not supported.  Try the '!' command instead\n");
130938689Sborman #endif
131037219Sminshall     return 1;
131132144Sminshall }
131232144Sminshall 
131338689Sborman #if	!defined(TN3270)
131444361Sborman /*ARGSUSED*/
131538689Sborman shell(argc, argv)
131638689Sborman int argc;
131738689Sborman char *argv[];
131838689Sborman {
131938689Sborman     extern char *rindex();
132038689Sborman 
132138689Sborman     setcommandmode();
132238689Sborman     switch(vfork()) {
132338689Sborman     case -1:
132438689Sborman 	perror("Fork failed\n");
132538689Sborman 	break;
132638689Sborman 
132738689Sborman     case 0:
132838689Sborman 	{
132938689Sborman 	    /*
133038689Sborman 	     * Fire up the shell in the child.
133138689Sborman 	     */
133238689Sborman 	    register char *shell, *shellname;
133338689Sborman 
133438689Sborman 	    shell = getenv("SHELL");
133538689Sborman 	    if (shell == NULL)
133638689Sborman 		shell = "/bin/sh";
133738689Sborman 	    if ((shellname = rindex(shell, '/')) == 0)
133838689Sborman 		shellname = shell;
133938689Sborman 	    else
134038689Sborman 		shellname++;
134138689Sborman 	    if (argc > 1)
134238689Sborman 		execl(shell, shellname, "-c", &saveline[1], 0);
134338689Sborman 	    else
134438689Sborman 		execl(shell, shellname, 0);
134538689Sborman 	    perror("Execl");
134638689Sborman 	    _exit(1);
134738689Sborman 	}
134838689Sborman     default:
134944361Sborman 	    (void)wait((int *)0);	/* Wait for the shell to complete */
135038689Sborman     }
135138689Sborman }
135238689Sborman #endif	/* !defined(TN3270) */
135338689Sborman 
135432144Sminshall /*VARARGS*/
135532144Sminshall static
135632144Sminshall bye(argc, argv)
135732144Sminshall int	argc;		/* Number of arguments */
135832144Sminshall char	*argv[];	/* arguments */
135932144Sminshall {
136032144Sminshall     if (connected) {
136134849Sminshall 	(void) shutdown(net, 2);
136232144Sminshall 	printf("Connection closed.\n");
136334849Sminshall 	(void) NetClose(net);
136432144Sminshall 	connected = 0;
136532144Sminshall 	/* reset options */
136632144Sminshall 	tninit();
136732144Sminshall #if	defined(TN3270)
136832144Sminshall 	SetIn3270();		/* Get out of 3270 mode */
136932144Sminshall #endif	/* defined(TN3270) */
137032144Sminshall     }
137132144Sminshall     if ((argc != 2) || (strcmp(argv[1], "fromquit") != 0)) {
137232144Sminshall 	longjmp(toplevel, 1);
137332144Sminshall 	/* NOTREACHED */
137432144Sminshall     }
137532144Sminshall     return 1;			/* Keep lint, etc., happy */
137632144Sminshall }
137732144Sminshall 
137832144Sminshall /*VARARGS*/
137932144Sminshall quit()
138032144Sminshall {
138132144Sminshall 	(void) call(bye, "bye", "fromquit", 0);
138232144Sminshall 	Exit(0);
138344361Sborman 	/*NOTREACHED*/
138432144Sminshall }
138538689Sborman 
138638689Sborman /*
138738689Sborman  * The SLC command.
138838689Sborman  */
138932144Sminshall 
139038689Sborman struct slclist {
139138689Sborman 	char	*name;
139238689Sborman 	char	*help;
139338689Sborman 	int	(*handler)();
139438689Sborman 	int	arg;
139538689Sborman };
139638689Sborman 
139738689Sborman extern int slc_help();
139838689Sborman extern int slc_mode_export(), slc_mode_import(), slcstate();
139938689Sborman 
140038689Sborman struct slclist SlcList[] = {
140138689Sborman     { "export",	"Use local special character definitions",
140238689Sborman 						slc_mode_export,	0 },
140338689Sborman     { "import",	"Use remote special character definitions",
140438689Sborman 						slc_mode_import,	1 },
140538689Sborman     { "check",	"Verify remote special character definitions",
140638689Sborman 						slc_mode_import,	0 },
140738689Sborman     { "help",	0,				slc_help,		0 },
140838689Sborman     { "?",	"Print help information",	slc_help,		0 },
140938689Sborman     { 0 },
141038689Sborman };
141138689Sborman 
141238689Sborman static
141338689Sborman slc_help()
141438689Sborman {
141538689Sborman     struct slclist *c;
141638689Sborman 
141738689Sborman     for (c = SlcList; c->name; c++) {
141838689Sborman 	if (c->help) {
141938689Sborman 	    if (*c->help)
142038689Sborman 		printf("%-15s %s\n", c->name, c->help);
142138689Sborman 	    else
142238689Sborman 		printf("\n");
142338689Sborman 	}
142438689Sborman     }
142538689Sborman }
142638689Sborman 
142738689Sborman static char **
142838689Sborman getnextslc(name)
142938689Sborman char *name;
143038689Sborman {
143138689Sborman     return (char **)(((struct slclist *)name)+1);
143238689Sborman }
143338689Sborman 
143438689Sborman static struct slclist *
143538689Sborman getslc(name)
143638689Sborman char *name;
143738689Sborman {
143838689Sborman     return (struct slclist *)genget(name, (char **) SlcList, getnextslc);
143938689Sborman }
144038689Sborman 
144138689Sborman static
144238689Sborman slccmd(argc, argv)
144338689Sborman int	argc;
144438689Sborman char	*argv[];
144538689Sborman {
144638689Sborman     struct slclist *c;
144738689Sborman 
144838689Sborman     if (argc != 2) {
144938689Sborman 	fprintf(stderr,
145038689Sborman 	    "Need an argument to 'slc' command.  'slc ?' for help.\n");
145138689Sborman 	return 0;
145238689Sborman     }
145338689Sborman     c = getslc(argv[1]);
145438689Sborman     if (c == 0) {
145538689Sborman         fprintf(stderr, "'%s': unknown argument ('slc ?' for help).\n",
145638689Sborman     				argv[1]);
145738689Sborman         return 0;
145838689Sborman     }
145938689Sborman     if (Ambiguous(c)) {
146038689Sborman         fprintf(stderr, "'%s': ambiguous argument ('slc ?' for help).\n",
146138689Sborman     				argv[1]);
146238689Sborman         return 0;
146338689Sborman     }
146438689Sborman     (*c->handler)(c->arg);
146538689Sborman     slcstate();
146638689Sborman     return 1;
146738689Sborman }
146844361Sborman 
146944361Sborman /*
147044361Sborman  * The ENVIRON command.
147144361Sborman  */
147238689Sborman 
147344361Sborman struct envlist {
147444361Sborman 	char	*name;
147544361Sborman 	char	*help;
147644361Sborman 	int	(*handler)();
147744361Sborman 	int	narg;
147844361Sborman };
147944361Sborman 
148044361Sborman extern struct env_lst *env_define();
148144361Sborman extern int env_undefine();
148244361Sborman extern int env_export(), env_unexport();
1483*45233Sborman extern int env_send(), env_list(), env_help();
148444361Sborman 
148544361Sborman struct envlist EnvList[] = {
148644361Sborman     { "define",	"Define an environment variable",
148744361Sborman 						(int (*)())env_define,	2 },
148844361Sborman     { "undefine", "Undefine an environment variable",
148944361Sborman 						env_undefine,	1 },
149044361Sborman     { "export",	"Mark an environment variable for automatic export",
149144361Sborman 						env_export,	1 },
149244361Sborman     { "unexport", "Dont mark an environment variable for automatic export",
149344361Sborman 						env_unexport,	1 },
1494*45233Sborman     { "send",	"Send an environment variable", env_send,	1 },
149544361Sborman     { "list",	"List the current environment variables",
149644361Sborman 						env_list,	0 },
149744361Sborman     { "help",	0,				env_help,		0 },
149844361Sborman     { "?",	"Print help information",	env_help,		0 },
149944361Sborman     { 0 },
150044361Sborman };
150144361Sborman 
150244361Sborman static
150344361Sborman env_help()
150444361Sborman {
150544361Sborman     struct envlist *c;
150644361Sborman 
150744361Sborman     for (c = EnvList; c->name; c++) {
150844361Sborman 	if (c->help) {
150944361Sborman 	    if (*c->help)
151044361Sborman 		printf("%-15s %s\n", c->name, c->help);
151144361Sborman 	    else
151244361Sborman 		printf("\n");
151344361Sborman 	}
151444361Sborman     }
151544361Sborman }
151644361Sborman 
151744361Sborman static char **
151844361Sborman getnextenv(name)
151944361Sborman char *name;
152044361Sborman {
152144361Sborman     return (char **)(((struct envlist *)name)+1);
152244361Sborman }
152344361Sborman 
152444361Sborman static struct envlist *
152544361Sborman getenvcmd(name)
152644361Sborman char *name;
152744361Sborman {
152844361Sborman     return (struct envlist *)genget(name, (char **) EnvList, getnextenv);
152944361Sborman }
153044361Sborman 
153144361Sborman env_cmd(argc, argv)
153244361Sborman int	argc;
153344361Sborman char	*argv[];
153444361Sborman {
153544361Sborman     struct envlist *c;
153644361Sborman 
153744361Sborman     if (argc < 2) {
153844361Sborman 	fprintf(stderr,
153944361Sborman 	    "Need an argument to 'environ' command.  'environ ?' for help.\n");
154044361Sborman 	return 0;
154144361Sborman     }
154244361Sborman     c = getenvcmd(argv[1]);
154344361Sborman     if (c == 0) {
154444361Sborman         fprintf(stderr, "'%s': unknown argument ('environ ?' for help).\n",
154544361Sborman     				argv[1]);
154644361Sborman         return 0;
154744361Sborman     }
154844361Sborman     if (Ambiguous(c)) {
154944361Sborman         fprintf(stderr, "'%s': ambiguous argument ('environ ?' for help).\n",
155044361Sborman     				argv[1]);
155144361Sborman         return 0;
155244361Sborman     }
155344361Sborman     if (c->narg + 2 != argc) {
155444361Sborman 	fprintf(stderr,
155544361Sborman 	    "Need %s%d argument%s to 'environ %s' command.  'environ ?' for help.\n",
155644361Sborman 		c->narg < argc + 2 ? "only " : "",
155744361Sborman 		c->narg, c->narg == 1 ? "" : "s", c->name);
155844361Sborman 	return 0;
155944361Sborman     }
156044361Sborman     (void)(*c->handler)(argv[2], argv[3]);
156144361Sborman     return 1;
156244361Sborman }
156344361Sborman 
156444361Sborman struct env_lst {
156544361Sborman 	struct env_lst *next;	/* pointer to next structure */
156644361Sborman 	struct env_lst *prev;	/* pointer to next structure */
156744361Sborman 	char *var;		/* pointer to variable name */
156844361Sborman 	char *value;		/* pointer to varialbe value */
156944361Sborman 	int export;		/* 1 -> export with default list of variables */
157044361Sborman };
157144361Sborman 
157244361Sborman struct env_lst envlisthead;
157344361Sborman 
157444361Sborman struct env_lst *
157544361Sborman env_find(var)
1576*45233Sborman char *var;
157744361Sborman {
157844361Sborman 	register struct env_lst *ep;
157944361Sborman 
158044361Sborman 	for (ep = envlisthead.next; ep; ep = ep->next) {
158144361Sborman 		if (strcmp(ep->var, var) == 0)
158244361Sborman 			return(ep);
158344361Sborman 	}
158444361Sborman 	return(NULL);
158544361Sborman }
158644361Sborman 
158744361Sborman env_init()
158844361Sborman {
158944361Sborman 	extern char **environ, *index();
159044361Sborman 	register char **epp, *cp;
159144361Sborman 	register struct env_lst *ep;
159244361Sborman 
159344361Sborman 	for (epp = environ; *epp; epp++) {
159444361Sborman 		if (cp = index(*epp, '=')) {
159544361Sborman 			*cp = '\0';
159644361Sborman 			ep = env_define(*epp, cp+1);
159744361Sborman 			ep->export = 0;
159844361Sborman 			*cp = '=';
159944361Sborman 		}
160044361Sborman 	}
160144361Sborman 	/*
160244361Sborman 	 * Special case for DISPLAY variable.  If it is ":0.0" or
160344361Sborman 	 * "unix:0.0", we have to get rid of "unix" and insert our
160444361Sborman 	 * hostname.
160544361Sborman 	 */
160644361Sborman 	if ((ep = env_find("DISPLAY")) &&
160744361Sborman 	    ((*ep->value == ':') || (strncmp(ep->value, "unix:", 5) == 0))) {
160844361Sborman 		char hbuf[256+1];
160944361Sborman 		char *cp2 = index(ep->value, ':');
161044361Sborman 
161144361Sborman 		gethostname(hbuf, 256);
161244361Sborman 		hbuf[256] = '\0';
161344361Sborman 		cp = (char *)malloc(strlen(hbuf) + strlen(cp2) + 1);
161444361Sborman 		sprintf(cp, "%s%s", hbuf, cp2);
161544361Sborman 		free(ep->value);
161644361Sborman 		ep->value = cp;
161744361Sborman 	}
161844361Sborman 	/*
161944361Sborman 	 * If USER is not defined, but LOGNAME is, then add
1620*45233Sborman 	 * USER with the value from LOGNAME.  By default, we
1621*45233Sborman 	 * don't export the USER variable.
162244361Sborman 	 */
1623*45233Sborman 	if ((env_find("USER") == NULL) && (ep = env_find("LOGNAME"))) {
162444361Sborman 		env_define("USER", ep->value);
1625*45233Sborman 		env_unexport("USER");
1626*45233Sborman 	}
162744361Sborman 	env_export("DISPLAY");
162844361Sborman 	env_export("PRINTER");
162944361Sborman }
163044361Sborman 
163144361Sborman struct env_lst *
163244361Sborman env_define(var, value)
163344361Sborman char *var, *value;
163444361Sborman {
163544361Sborman 	register struct env_lst *ep;
1636*45233Sborman 	extern char *strdup();
163744361Sborman 
163844361Sborman 	if (ep = env_find(var)) {
163944361Sborman 		if (ep->var)
164044361Sborman 			free(ep->var);
164144361Sborman 		if (ep->value)
164244361Sborman 			free(ep->value);
164344361Sborman 	} else {
164444361Sborman 		ep = (struct env_lst *)malloc(sizeof(struct env_lst));
164544361Sborman 		ep->next = envlisthead.next;
164644361Sborman 		envlisthead.next = ep;
164744361Sborman 		ep->prev = &envlisthead;
164844361Sborman 		if (ep->next)
164944361Sborman 			ep->next->prev = ep;
165044361Sborman 	}
165145009Skarels 	ep->export = 1;
1652*45233Sborman 	ep->var = strdup(var);
1653*45233Sborman 	ep->value = strdup(value);
165444361Sborman 	return(ep);
165544361Sborman }
165644361Sborman 
165744361Sborman env_undefine(var)
165844361Sborman char *var;
165944361Sborman {
166044361Sborman 	register struct env_lst *ep;
166144361Sborman 
166244361Sborman 	if (ep = env_find(var)) {
166344361Sborman 		ep->prev->next = ep->next;
1664*45233Sborman 		if (ep->next)
1665*45233Sborman 			ep->next->prev = ep->prev;
166644361Sborman 		if (ep->var)
166744361Sborman 			free(ep->var);
166844361Sborman 		if (ep->value)
166944361Sborman 			free(ep->value);
167044361Sborman 		free(ep);
167144361Sborman 	}
167244361Sborman }
167344361Sborman 
167444361Sborman env_export(var)
167544361Sborman char *var;
167644361Sborman {
167744361Sborman 	register struct env_lst *ep;
167844361Sborman 
167944361Sborman 	if (ep = env_find(var))
168044361Sborman 		ep->export = 1;
168144361Sborman }
168244361Sborman 
168344361Sborman env_unexport(var)
168444361Sborman char *var;
168544361Sborman {
168644361Sborman 	register struct env_lst *ep;
168744361Sborman 
168844361Sborman 	if (ep = env_find(var))
168944361Sborman 		ep->export = 0;
169044361Sborman }
169144361Sborman 
1692*45233Sborman env_send(var)
1693*45233Sborman char *var;
1694*45233Sborman {
1695*45233Sborman 	register struct env_lst *ep;
1696*45233Sborman 
1697*45233Sborman         if (my_state_is_wont(TELOPT_ENVIRON)) {
1698*45233Sborman 		fprintf(stderr,
1699*45233Sborman 		    "Cannot send '%s': Telnet ENVIRON option not enabled\n",
1700*45233Sborman 									var);
1701*45233Sborman 		return;
1702*45233Sborman 	}
1703*45233Sborman 	ep = env_find(var);
1704*45233Sborman 	if (ep == 0) {
1705*45233Sborman 		fprintf(stderr, "Cannot send '%s': variable not defined\n",
1706*45233Sborman 									var);
1707*45233Sborman 		return;
1708*45233Sborman 	}
1709*45233Sborman 	env_opt_start_info();
1710*45233Sborman 	env_opt_add(ep->var);
1711*45233Sborman 	env_opt_end(0);
1712*45233Sborman }
1713*45233Sborman 
171444361Sborman env_list()
171544361Sborman {
171644361Sborman 	register struct env_lst *ep;
171744361Sborman 
171844361Sborman 	for (ep = envlisthead.next; ep; ep = ep->next) {
171944361Sborman 		printf("%c %-20s %s\n", ep->export ? '*' : ' ',
172044361Sborman 					ep->var, ep->value);
172144361Sborman 	}
172244361Sborman }
172344361Sborman 
172444361Sborman char *
172544361Sborman env_default(init)
172644361Sborman {
172744361Sborman 	static struct env_lst *nep = NULL;
172844361Sborman 
172944361Sborman 	if (init) {
173044361Sborman 		nep = &envlisthead;
173144361Sborman 		return;
173244361Sborman 	}
173344361Sborman 	if (nep) {
173444361Sborman 		while (nep = nep->next) {
173544361Sborman 			if (nep->export)
173644361Sborman 				return(nep->var);
173744361Sborman 		}
173844361Sborman 	}
173944361Sborman 	return(NULL);
174044361Sborman }
174144361Sborman 
174244361Sborman char *
174344361Sborman env_getvalue(var)
174444361Sborman char *var;
174544361Sborman {
174644361Sborman 	register struct env_lst *ep;
174744361Sborman 
174844361Sborman 	if (ep = env_find(var))
174944361Sborman 		return(ep->value);
175044361Sborman 	return(NULL);
175144361Sborman }
175244361Sborman 
1753*45233Sborman #ifdef	NO_STRDUP
175444361Sborman char *
1755*45233Sborman strdup(s)
175644361Sborman register char *s;
175744361Sborman {
175844361Sborman 	register char *ret;
175944361Sborman 	if (ret = (char *)malloc(strlen(s)+1))
176044361Sborman 		strcpy(ret, s);
176144361Sborman 	return(ret);
176244361Sborman }
1763*45233Sborman #endif
176444361Sborman 
176536274Sminshall #if	defined(unix)
176644361Sborman #ifdef notdef
176732144Sminshall /*
176836274Sminshall  * Some information about our file descriptors.
176936274Sminshall  */
177036274Sminshall 
177136274Sminshall char *
177236274Sminshall decodeflags(mask)
177336274Sminshall int mask;
177436274Sminshall {
177536274Sminshall     static char buffer[100];
177636274Sminshall #define do(m,s) \
177736274Sminshall 	if (mask&(m)) { \
177836274Sminshall 	    strcat(buffer, (s)); \
177936274Sminshall 	}
178036274Sminshall 
178136274Sminshall     buffer[0] = 0;			/* Terminate it */
178236274Sminshall 
178336274Sminshall #ifdef FREAD
178436274Sminshall     do(FREAD, " FREAD");
178536274Sminshall #endif
178636274Sminshall #ifdef FWRITE
178736274Sminshall     do(FWRITE, " FWRITE");
178836274Sminshall #endif
178936274Sminshall #ifdef F_DUPFP
179036274Sminshall     do(F_DUPFD, " F_DUPFD");
179136274Sminshall #endif
179236274Sminshall #ifdef FNDELAY
179336274Sminshall     do(FNDELAY, " FNDELAY");
179436274Sminshall #endif
179536274Sminshall #ifdef FAPPEND
179636274Sminshall     do(FAPPEND, " FAPPEND");
179736274Sminshall #endif
179836274Sminshall #ifdef FMARK
179936274Sminshall     do(FMARK, " FMARK");
180036274Sminshall #endif
180136274Sminshall #ifdef FDEFER
180236274Sminshall     do(FDEFER, " FDEFER");
180336274Sminshall #endif
180436274Sminshall #ifdef FASYNC
180536274Sminshall     do(FASYNC, " FASYNC");
180636274Sminshall #endif
180736274Sminshall #ifdef FSHLOCK
180836274Sminshall     do(FSHLOCK, " FSHLOCK");
180936274Sminshall #endif
181036274Sminshall #ifdef FEXLOCK
181136274Sminshall     do(FEXLOCK, " FEXLOCK");
181236274Sminshall #endif
181336274Sminshall #ifdef FCREAT
181436274Sminshall     do(FCREAT, " FCREAT");
181536274Sminshall #endif
181636274Sminshall #ifdef FTRUNC
181736274Sminshall     do(FTRUNC, " FTRUNC");
181836274Sminshall #endif
181936274Sminshall #ifdef FEXCL
182036274Sminshall     do(FEXCL, " FEXCL");
182136274Sminshall #endif
182236274Sminshall 
182336274Sminshall     return buffer;
182436274Sminshall }
182536274Sminshall #undef do
182644361Sborman #endif	/* notdef */
182736274Sminshall 
182844361Sborman #if defined(TN3270)
182936274Sminshall static void
183036274Sminshall filestuff(fd)
183136274Sminshall int fd;
183236274Sminshall {
183336274Sminshall     int res;
183436274Sminshall 
183538689Sborman #ifdef	F_GETOWN
183638689Sborman     setconnmode(0);
183736274Sminshall     res = fcntl(fd, F_GETOWN, 0);
183836274Sminshall     setcommandmode();
183936274Sminshall 
184036274Sminshall     if (res == -1) {
184136274Sminshall 	perror("fcntl");
184236274Sminshall 	return;
184336274Sminshall     }
184436274Sminshall     printf("\tOwner is %d.\n", res);
184538689Sborman #endif
184636274Sminshall 
184738689Sborman     setconnmode(0);
184836274Sminshall     res = fcntl(fd, F_GETFL, 0);
184936274Sminshall     setcommandmode();
185036274Sminshall 
185136274Sminshall     if (res == -1) {
185236274Sminshall 	perror("fcntl");
185336274Sminshall 	return;
185436274Sminshall     }
185536274Sminshall     printf("\tFlags are 0x%x: %s\n", res, decodeflags(res));
185636274Sminshall }
185744361Sborman #endif /* defined(TN3270) */
185836274Sminshall 
185936274Sminshall 
186036274Sminshall #endif	/* defined(unix) */
186136274Sminshall 
186236274Sminshall /*
186332144Sminshall  * Print status about the connection.
186432144Sminshall  */
186534849Sminshall /*ARGSUSED*/
186632144Sminshall static
186732144Sminshall status(argc, argv)
186832144Sminshall int	argc;
186932144Sminshall char	*argv[];
187032144Sminshall {
187132144Sminshall     if (connected) {
187232144Sminshall 	printf("Connected to %s.\n", hostname);
187336242Sminshall 	if ((argc < 2) || strcmp(argv[1], "notmuch")) {
187438689Sborman 	    int mode = getconnmode();
187538689Sborman 
187638689Sborman 	    if (my_want_state_is_will(TELOPT_LINEMODE)) {
187738689Sborman 		printf("Operating with LINEMODE option\n");
187838689Sborman 		printf("%s line editing\n", (mode&MODE_EDIT) ? "Local" : "No");
187938689Sborman 		printf("%s catching of signals\n",
188038689Sborman 					(mode&MODE_TRAPSIG) ? "Local" : "No");
188138689Sborman 		slcstate();
188238689Sborman #ifdef	KLUDGELINEMODE
188339529Sborman 	    } else if (kludgelinemode && my_want_state_is_dont(TELOPT_SGA)) {
188438689Sborman 		printf("Operating in obsolete linemode\n");
188538689Sborman #endif
188638689Sborman 	    } else {
188738689Sborman 		printf("Operating in single character mode\n");
188838689Sborman 		if (localchars)
188938689Sborman 		    printf("Catching signals locally\n");
189032144Sminshall 	    }
189138689Sborman 	    printf("%s character echo\n", (mode&MODE_ECHO) ? "Local" : "Remote");
189238689Sborman 	    if (my_want_state_is_will(TELOPT_LFLOW))
189338689Sborman 		printf("%s flow control\n", (mode&MODE_FLOW) ? "Local" : "No");
189432144Sminshall 	}
189532144Sminshall     } else {
189632144Sminshall 	printf("No connection.\n");
189732144Sminshall     }
189832144Sminshall #   if !defined(TN3270)
189932144Sminshall     printf("Escape character is '%s'.\n", control(escape));
190034849Sminshall     (void) fflush(stdout);
190132144Sminshall #   else /* !defined(TN3270) */
190232144Sminshall     if ((!In3270) && ((argc < 2) || strcmp(argv[1], "notmuch"))) {
190332144Sminshall 	printf("Escape character is '%s'.\n", control(escape));
190432144Sminshall     }
190532144Sminshall #   if defined(unix)
190636242Sminshall     if ((argc >= 2) && !strcmp(argv[1], "everything")) {
190736242Sminshall 	printf("SIGIO received %d time%s.\n",
190836242Sminshall 				sigiocount, (sigiocount == 1)? "":"s");
190936274Sminshall 	if (In3270) {
191036274Sminshall 	    printf("Process ID %d, process group %d.\n",
191136274Sminshall 					    getpid(), getpgrp(getpid()));
191236274Sminshall 	    printf("Terminal input:\n");
191336274Sminshall 	    filestuff(tin);
191436274Sminshall 	    printf("Terminal output:\n");
191536274Sminshall 	    filestuff(tout);
191636274Sminshall 	    printf("Network socket:\n");
191736274Sminshall 	    filestuff(net);
191836274Sminshall 	}
191936242Sminshall     }
192032144Sminshall     if (In3270 && transcom) {
192132144Sminshall        printf("Transparent mode command is '%s'.\n", transcom);
192232144Sminshall     }
192332144Sminshall #   endif /* defined(unix) */
192434849Sminshall     (void) fflush(stdout);
192532144Sminshall     if (In3270) {
192632144Sminshall 	return 0;
192732144Sminshall     }
192832144Sminshall #   endif /* defined(TN3270) */
192932144Sminshall     return 1;
193032144Sminshall }
193132144Sminshall 
1932*45233Sborman #ifdef	SIGINFO
1933*45233Sborman /*
1934*45233Sborman  * Function that gets called when SIGINFO is received.
1935*45233Sborman  */
1936*45233Sborman ayt_status()
1937*45233Sborman {
1938*45233Sborman     (void) call(status, "status", "notmuch", 0);
1939*45233Sborman }
1940*45233Sborman #endif
194132144Sminshall 
194244361Sborman #if	defined(NEED_GETTOS)
194344361Sborman struct tosent {
194444361Sborman 	char	*t_name;	/* name */
194544361Sborman 	char	**t_aliases;	/* alias list */
194644361Sborman 	char	*t_proto;	/* protocol */
194744361Sborman 	int	t_tos;		/* Type Of Service bits */
194844361Sborman };
194944361Sborman 
195044361Sborman struct tosent *
195144361Sborman gettosbyname(name, proto)
195244361Sborman char *name, *proto;
195344361Sborman {
195444361Sborman 	static struct tosent te;
195544361Sborman 	static char *aliasp = 0;
195644361Sborman 
195744361Sborman 	te.t_name = name;
195844361Sborman 	te.t_aliases = &aliasp;
195944361Sborman 	te.t_proto = proto;
196044361Sborman 	te.t_tos = 020; /* Low Delay bit */
196144361Sborman 	return(&te);
196244361Sborman }
196344361Sborman #endif
196444361Sborman 
196545008Skarels extern	int autologin;
196645008Skarels 
196732144Sminshall int
196832144Sminshall tn(argc, argv)
196932144Sminshall 	int argc;
197032144Sminshall 	char *argv[];
197132144Sminshall {
197232144Sminshall     register struct hostent *host = 0;
197332144Sminshall     struct sockaddr_in sin;
197432144Sminshall     struct servent *sp = 0;
197532144Sminshall     static char	hnamebuf[32];
197638689Sborman     unsigned long temp, inet_addr();
197737219Sminshall     extern char *inet_ntoa();
197838689Sborman #if	defined(SRCRT) && defined(IPPROTO_IP)
197938689Sborman     char *srp = 0, *strrchr();
198038689Sborman     unsigned long sourceroute(), srlen;
198138689Sborman #endif
198244361Sborman #if defined(HAS_IP_TOS) || defined(NEED_GETTOS)
198340245Sborman     struct tosent *tp;
198444361Sborman #endif /* defined(HAS_IP_TOS) || defined(NEED_GETTOS) */
198544361Sborman     char *cmd, *hostp = 0, *portp = 0, *user = 0;
198632144Sminshall 
1987*45233Sborman     /* clear the socket address prior to use */
1988*45233Sborman     bzero((char *)&sin, sizeof(sin));
198932144Sminshall 
199032144Sminshall     if (connected) {
199132144Sminshall 	printf("?Already connected to %s\n", hostname);
199232144Sminshall 	return 0;
199332144Sminshall     }
199432144Sminshall     if (argc < 2) {
199532144Sminshall 	(void) strcpy(line, "Connect ");
199632144Sminshall 	printf("(to) ");
199734849Sminshall 	(void) gets(&line[strlen(line)]);
199832144Sminshall 	makeargv();
199932144Sminshall 	argc = margc;
200032144Sminshall 	argv = margv;
200132144Sminshall     }
200244361Sborman     cmd = *argv;
200344361Sborman     --argc; ++argv;
200444361Sborman     while (argc) {
200544361Sborman 	if (strcmp(*argv, "-l") == 0) {
200644361Sborman 	    --argc; ++argv;
200744361Sborman 	    if (argc == 0)
200844361Sborman 		goto usage;
200944361Sborman 	    user = *argv++;
201044361Sborman 	    --argc;
201144361Sborman 	    continue;
201244361Sborman 	}
2013*45233Sborman 	if (strcmp(*argv, "-a") == 0) {
2014*45233Sborman 	    --argc; ++argv;
2015*45233Sborman 	    autologin = 1;
2016*45233Sborman 	    continue;
2017*45233Sborman 	}
201844361Sborman 	if (hostp == 0) {
201944361Sborman 	    hostp = *argv++;
202044361Sborman 	    --argc;
202144361Sborman 	    continue;
202244361Sborman 	}
202344361Sborman 	if (portp == 0) {
202444361Sborman 	    portp = *argv++;
202544361Sborman 	    --argc;
202644361Sborman 	    continue;
202744361Sborman 	}
202844361Sborman     usage:
2029*45233Sborman 	printf("usage: %s [-l user] [-a] host-name [port]\n", cmd);
203032144Sminshall 	return 0;
203132144Sminshall     }
203238689Sborman #if	defined(SRCRT) && defined(IPPROTO_IP)
203344361Sborman     if (hostp[0] == '@' || hostp[0] == '!') {
203444361Sborman 	if ((hostname = strrchr(hostp, ':')) == NULL)
203544361Sborman 	    hostname = strrchr(hostp, '@');
203638689Sborman 	hostname++;
203738689Sborman 	srp = 0;
203844361Sborman 	temp = sourceroute(hostp, &srp, &srlen);
203938689Sborman 	if (temp == 0) {
204038689Sborman 	    herror(srp);
204138689Sborman 	    return 0;
204238689Sborman 	} else if (temp == -1) {
204344361Sborman 	    printf("Bad source route option: %s\n", hostp);
204438689Sborman 	    return 0;
204538689Sborman 	} else {
204638689Sborman 	    sin.sin_addr.s_addr = temp;
204738689Sborman 	    sin.sin_family = AF_INET;
204838689Sborman 	}
204932144Sminshall     } else {
205038689Sborman #endif
205144361Sborman 	temp = inet_addr(hostp);
205238689Sborman 	if (temp != (unsigned long) -1) {
205338689Sborman 	    sin.sin_addr.s_addr = temp;
205438689Sborman 	    sin.sin_family = AF_INET;
205544361Sborman 	    (void) strcpy(hnamebuf, hostp);
205638689Sborman 	    hostname = hnamebuf;
205738689Sborman 	} else {
205844361Sborman 	    host = gethostbyname(hostp);
205938689Sborman 	    if (host) {
206038689Sborman 		sin.sin_family = host->h_addrtype;
206132144Sminshall #if	defined(h_addr)		/* In 4.3, this is a #define */
206238689Sborman 		memcpy((caddr_t)&sin.sin_addr,
206332144Sminshall 				host->h_addr_list[0], host->h_length);
206432144Sminshall #else	/* defined(h_addr) */
206538689Sborman 		memcpy((caddr_t)&sin.sin_addr, host->h_addr, host->h_length);
206632144Sminshall #endif	/* defined(h_addr) */
206738689Sborman 		hostname = host->h_name;
206838689Sborman 	    } else {
206944361Sborman 		herror(hostp);
207038689Sborman 		return 0;
207138689Sborman 	    }
207232144Sminshall 	}
207338689Sborman #if	defined(SRCRT) && defined(IPPROTO_IP)
207432144Sminshall     }
207538689Sborman #endif
207644361Sborman     if (portp) {
207744361Sborman 	if (*portp == '-') {
207844361Sborman 	    portp++;
207938689Sborman 	    telnetport = 1;
208038689Sborman 	} else
208138689Sborman 	    telnetport = 0;
208244361Sborman 	sin.sin_port = atoi(portp);
208332144Sminshall 	if (sin.sin_port == 0) {
208444361Sborman 	    sp = getservbyname(portp, "tcp");
208532144Sminshall 	    if (sp)
208632144Sminshall 		sin.sin_port = sp->s_port;
208732144Sminshall 	    else {
208844361Sborman 		printf("%s: bad port number\n", portp);
208932144Sminshall 		return 0;
209032144Sminshall 	    }
209132144Sminshall 	} else {
209234849Sminshall #if	!defined(htons)
209334849Sminshall 	    u_short htons();
209434849Sminshall #endif	/* !defined(htons) */
209532144Sminshall 	    sin.sin_port = htons(sin.sin_port);
209632144Sminshall 	}
209732144Sminshall     } else {
209832144Sminshall 	if (sp == 0) {
209932144Sminshall 	    sp = getservbyname("telnet", "tcp");
210032144Sminshall 	    if (sp == 0) {
210134849Sminshall 		fprintf(stderr, "telnet: tcp/telnet: unknown service\n");
210232144Sminshall 		return 0;
210332144Sminshall 	    }
210432144Sminshall 	    sin.sin_port = sp->s_port;
210532144Sminshall 	}
210632144Sminshall 	telnetport = 1;
210732144Sminshall     }
210837219Sminshall     printf("Trying %s...\n", inet_ntoa(sin.sin_addr));
210932144Sminshall     do {
211032144Sminshall 	net = socket(AF_INET, SOCK_STREAM, 0);
211132144Sminshall 	if (net < 0) {
211232144Sminshall 	    perror("telnet: socket");
211332144Sminshall 	    return 0;
211432144Sminshall 	}
211538689Sborman #if	defined(SRCRT) && defined(IPPROTO_IP)
211638689Sborman 	if (srp && setsockopt(net, IPPROTO_IP, IP_OPTIONS, (char *)srp, srlen) < 0)
211738689Sborman 		perror("setsockopt (IP_OPTIONS)");
211838689Sborman #endif
211944361Sborman #if	defined(HAS_IP_TOS) || defined(NEED_GETTOS)
212044361Sborman 	if ((tp = gettosbyname("telnet", "tcp")) &&
212144361Sborman 	    (setsockopt(net, IPPROTO_IP, IP_TOS, &tp->t_tos, sizeof(int)) < 0))
212240245Sborman 		perror("telnet: setsockopt TOS (ignored)");
212344361Sborman #endif	/* defined(HAS_IP_TOS) || defined(NEED_GETTOS) */
212440245Sborman 
212532144Sminshall 	if (debug && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 1) < 0) {
212632144Sminshall 		perror("setsockopt (SO_DEBUG)");
212732144Sminshall 	}
212832144Sminshall 
212932144Sminshall 	if (connect(net, (struct sockaddr *)&sin, sizeof (sin)) < 0) {
213032144Sminshall #if	defined(h_addr)		/* In 4.3, this is a #define */
213132144Sminshall 	    if (host && host->h_addr_list[1]) {
213232144Sminshall 		int oerrno = errno;
213332144Sminshall 
213432144Sminshall 		fprintf(stderr, "telnet: connect to address %s: ",
213532144Sminshall 						inet_ntoa(sin.sin_addr));
213632144Sminshall 		errno = oerrno;
213732144Sminshall 		perror((char *)0);
213832144Sminshall 		host->h_addr_list++;
213932144Sminshall 		memcpy((caddr_t)&sin.sin_addr,
214032144Sminshall 			host->h_addr_list[0], host->h_length);
214132144Sminshall 		(void) NetClose(net);
214232144Sminshall 		continue;
214332144Sminshall 	    }
214432144Sminshall #endif	/* defined(h_addr) */
214532144Sminshall 	    perror("telnet: Unable to connect to remote host");
214632144Sminshall 	    return 0;
214737219Sminshall 	}
214832144Sminshall 	connected++;
214932144Sminshall     } while (connected == 0);
215044361Sborman     cmdrc(hostp, hostname);
215145008Skarels     if (autologin && user == NULL) {
215245008Skarels 	struct passwd *pw;
215345008Skarels 
2154*45233Sborman 	user = getenv("USER");
215545008Skarels 	if (user == NULL ||
2156*45233Sborman 	    (pw = getpwnam(user)) && pw->pw_uid != getuid()) {
2157*45233Sborman 		if (pw = getpwuid(getuid()))
215845008Skarels 			user = pw->pw_name;
215945008Skarels 		else
216045008Skarels 			user = NULL;
2161*45233Sborman 	}
216245008Skarels     }
216345008Skarels     if (user) {
216444361Sborman 	env_define("USER", user);
216545008Skarels 	env_export("USER");
216645008Skarels     }
216734849Sminshall     (void) call(status, "status", "notmuch", 0);
216832144Sminshall     if (setjmp(peerdied) == 0)
216932144Sminshall 	telnet();
217034849Sminshall     (void) NetClose(net);
217132381Sminshall     ExitString("Connection closed by foreign host.\n",1);
217232144Sminshall     /*NOTREACHED*/
217332144Sminshall }
217432144Sminshall 
217532144Sminshall 
217632144Sminshall #define HELPINDENT (sizeof ("connect"))
217732144Sminshall 
217832144Sminshall static char
217932144Sminshall 	openhelp[] =	"connect to a site",
218032144Sminshall 	closehelp[] =	"close current connection",
218132144Sminshall 	quithelp[] =	"exit telnet",
218232144Sminshall 	statushelp[] =	"print status information",
218332144Sminshall 	helphelp[] =	"print help information",
218432144Sminshall 	sendhelp[] =	"transmit special characters ('send ?' for more)",
218532144Sminshall 	sethelp[] = 	"set operating parameters ('set ?' for more)",
218638689Sborman 	unsethelp[] = 	"unset operating parameters ('unset ?' for more)",
218732144Sminshall 	togglestring[] ="toggle operating parameters ('toggle ?' for more)",
218838689Sborman 	slchelp[] =	"change state of special charaters ('slc ?' for more)",
218932144Sminshall 	displayhelp[] =	"display operating parameters",
219032144Sminshall #if	defined(TN3270) && defined(unix)
219132144Sminshall 	transcomhelp[] = "specify Unix command for transparent mode pipe",
219232144Sminshall #endif	/* defined(TN3270) && defined(unix) */
219332144Sminshall #if	defined(unix)
219432144Sminshall 	zhelp[] =	"suspend telnet",
219543317Skfall #endif	/* defined(unix) */
219632144Sminshall 	shellhelp[] =	"invoke a subshell",
219744361Sborman 	envhelp[] =	"change environment variables ('environ ?' for more)",
219844361Sborman 	modestring[] = "try to enter line or character mode ('mode ?' for more)";
219932144Sminshall 
220032144Sminshall extern int	help(), shell();
220132144Sminshall 
220232144Sminshall static Command cmdtab[] = {
220338689Sborman 	{ "close",	closehelp,	bye,		1 },
220438689Sborman 	{ "display",	displayhelp,	display,	0 },
220538689Sborman 	{ "mode",	modestring,	modecmd,	0 },
220638689Sborman 	{ "open",	openhelp,	tn,		0 },
220738689Sborman 	{ "quit",	quithelp,	quit,		0 },
220838689Sborman 	{ "send",	sendhelp,	sendcmd,	0 },
220938689Sborman 	{ "set",	sethelp,	setcmd,		0 },
221038689Sborman 	{ "unset",	unsethelp,	unsetcmd,	0 },
221138689Sborman 	{ "status",	statushelp,	status,		0 },
221238689Sborman 	{ "toggle",	togglestring,	toggle,		0 },
221338689Sborman 	{ "slc",	slchelp,	slccmd,		0 },
221432144Sminshall #if	defined(TN3270) && defined(unix)
221538689Sborman 	{ "transcom",	transcomhelp,	settranscom,	0 },
221632144Sminshall #endif	/* defined(TN3270) && defined(unix) */
221732144Sminshall #if	defined(unix)
221838689Sborman 	{ "z",		zhelp,		suspend,	0 },
221932144Sminshall #endif	/* defined(unix) */
222032144Sminshall #if	defined(TN3270)
222138689Sborman 	{ "!",		shellhelp,	shell,		1 },
222238689Sborman #else
222338689Sborman 	{ "!",		shellhelp,	shell,		0 },
222438689Sborman #endif
222544361Sborman 	{ "environ",	envhelp,	env_cmd,	0 },
222638689Sborman 	{ "?",		helphelp,	help,		0 },
222732144Sminshall 	0
222832144Sminshall };
222932144Sminshall 
223032144Sminshall static char	crmodhelp[] =	"deprecated command -- use 'toggle crmod' instead";
223132144Sminshall static char	escapehelp[] =	"deprecated command -- use 'set escape' instead";
223232144Sminshall 
223332144Sminshall static Command cmdtab2[] = {
223438689Sborman 	{ "help",	0,		help,		0 },
223538689Sborman 	{ "escape",	escapehelp,	setescape,	0 },
223638689Sborman 	{ "crmod",	crmodhelp,	togcrmod,	0 },
223732144Sminshall 	0
223832144Sminshall };
223932144Sminshall 
224035298Sminshall 
224132144Sminshall /*
224232144Sminshall  * Call routine with argc, argv set from args (terminated by 0).
224332144Sminshall  */
224435298Sminshall 
224535417Sminshall /*VARARGS1*/
224632144Sminshall static
224735298Sminshall call(va_alist)
224835298Sminshall va_dcl
224932144Sminshall {
225035298Sminshall     va_list ap;
225135298Sminshall     typedef int (*intrtn_t)();
225235298Sminshall     intrtn_t routine;
225335298Sminshall     char *args[100];
225435298Sminshall     int argno = 0;
225535298Sminshall 
225635298Sminshall     va_start(ap);
225735298Sminshall     routine = (va_arg(ap, intrtn_t));
225835495Sminshall     while ((args[argno++] = va_arg(ap, char *)) != 0) {
225935298Sminshall 	;
226035495Sminshall     }
226135298Sminshall     va_end(ap);
226235495Sminshall     return (*routine)(argno-1, args);
226332144Sminshall }
226432144Sminshall 
226535298Sminshall 
226632144Sminshall static char **
226732144Sminshall getnextcmd(name)
226832144Sminshall char *name;
226932144Sminshall {
227032144Sminshall     Command *c = (Command *) name;
227132144Sminshall 
227232144Sminshall     return (char **) (c+1);
227332144Sminshall }
227432144Sminshall 
227532144Sminshall static Command *
227632144Sminshall getcmd(name)
227732144Sminshall char *name;
227832144Sminshall {
227932144Sminshall     Command *cm;
228032144Sminshall 
228132144Sminshall     if ((cm = (Command *) genget(name, (char **) cmdtab, getnextcmd)) != 0) {
228232144Sminshall 	return cm;
228332144Sminshall     } else {
228432144Sminshall 	return (Command *) genget(name, (char **) cmdtab2, getnextcmd);
228532144Sminshall     }
228632144Sminshall }
228732144Sminshall 
228832144Sminshall void
228938689Sborman command(top, tbuf, cnt)
229032144Sminshall 	int top;
229138689Sborman 	char *tbuf;
229238689Sborman 	int cnt;
229332144Sminshall {
229432144Sminshall     register Command *c;
229532144Sminshall 
229632144Sminshall     setcommandmode();
229732144Sminshall     if (!top) {
229832144Sminshall 	putchar('\n');
229937219Sminshall #if	defined(unix)
230032144Sminshall     } else {
230144361Sborman 	(void) signal(SIGINT, SIG_DFL);
230244361Sborman 	(void) signal(SIGQUIT, SIG_DFL);
230332144Sminshall #endif	/* defined(unix) */
230432144Sminshall     }
230532144Sminshall     for (;;) {
230632144Sminshall 	printf("%s> ", prompt);
230738689Sborman 	if (tbuf) {
230838689Sborman 	    register char *cp;
230938689Sborman 	    cp = line;
231038689Sborman 	    while (cnt > 0 && (*cp++ = *tbuf++) != '\n')
231138689Sborman 		cnt--;
231238689Sborman 	    tbuf = 0;
231338689Sborman 	    if (cp == line || *--cp != '\n' || cp == line)
231438689Sborman 		goto getline;
231538689Sborman 	    *cp = '\0';
231638689Sborman 	    printf("%s\n", line);
231738689Sborman 	} else {
231838689Sborman 	getline:
231938689Sborman 	    if (gets(line) == NULL) {
232044361Sborman 		if (feof(stdin) || ferror(stdin)) {
232144361Sborman 		    (void) quit();
232244361Sborman 		    /*NOTREACHED*/
232344361Sborman 		}
232438689Sborman 		break;
232538689Sborman 	    }
232632144Sminshall 	}
232732144Sminshall 	if (line[0] == 0)
232832144Sminshall 	    break;
232932144Sminshall 	makeargv();
233037219Sminshall 	if (margv[0] == 0) {
233137219Sminshall 	    break;
233237219Sminshall 	}
233332144Sminshall 	c = getcmd(margv[0]);
233432144Sminshall 	if (Ambiguous(c)) {
233532144Sminshall 	    printf("?Ambiguous command\n");
233632144Sminshall 	    continue;
233732144Sminshall 	}
233832144Sminshall 	if (c == 0) {
233932144Sminshall 	    printf("?Invalid command\n");
234032144Sminshall 	    continue;
234132144Sminshall 	}
234232144Sminshall 	if (c->needconnect && !connected) {
234332144Sminshall 	    printf("?Need to be connected first.\n");
234432144Sminshall 	    continue;
234532144Sminshall 	}
234632144Sminshall 	if ((*c->handler)(margc, margv)) {
234732144Sminshall 	    break;
234832144Sminshall 	}
234932144Sminshall     }
235032144Sminshall     if (!top) {
235132144Sminshall 	if (!connected) {
235232144Sminshall 	    longjmp(toplevel, 1);
235332144Sminshall 	    /*NOTREACHED*/
235432144Sminshall 	}
235532144Sminshall #if	defined(TN3270)
235632144Sminshall 	if (shell_active == 0) {
235738689Sborman 	    setconnmode(0);
235832144Sminshall 	}
235932144Sminshall #else	/* defined(TN3270) */
236038689Sborman 	setconnmode(0);
236132144Sminshall #endif	/* defined(TN3270) */
236232144Sminshall     }
236332144Sminshall }
236432144Sminshall 
236532144Sminshall /*
236632144Sminshall  * Help command.
236732144Sminshall  */
236832144Sminshall static
236932144Sminshall help(argc, argv)
237032144Sminshall 	int argc;
237132144Sminshall 	char *argv[];
237232144Sminshall {
237332144Sminshall 	register Command *c;
237432144Sminshall 
237532144Sminshall 	if (argc == 1) {
237632144Sminshall 		printf("Commands may be abbreviated.  Commands are:\n\n");
237732144Sminshall 		for (c = cmdtab; c->name; c++)
237838689Sborman 			if (c->help) {
237932144Sminshall 				printf("%-*s\t%s\n", HELPINDENT, c->name,
238032144Sminshall 								    c->help);
238132144Sminshall 			}
238232144Sminshall 		return 0;
238332144Sminshall 	}
238432144Sminshall 	while (--argc > 0) {
238532144Sminshall 		register char *arg;
238632144Sminshall 		arg = *++argv;
238732144Sminshall 		c = getcmd(arg);
238832144Sminshall 		if (Ambiguous(c))
238932144Sminshall 			printf("?Ambiguous help command %s\n", arg);
239032144Sminshall 		else if (c == (Command *)0)
239132144Sminshall 			printf("?Invalid help command %s\n", arg);
239232144Sminshall 		else
239332144Sminshall 			printf("%s\n", c->help);
239432144Sminshall 	}
239532144Sminshall 	return 0;
239632144Sminshall }
239738689Sborman 
239838689Sborman static char *rcname = 0;
239938689Sborman static char rcbuf[128];
240038689Sborman 
240138689Sborman cmdrc(m1, m2)
240238689Sborman 	char *m1, *m2;
240338689Sborman {
240438689Sborman     register Command *c;
240538689Sborman     FILE *rcfile;
240638689Sborman     int gotmachine = 0;
240738689Sborman     int l1 = strlen(m1);
240838689Sborman     int l2 = strlen(m2);
240938689Sborman     char m1save[64];
241038689Sborman 
241138689Sborman     strcpy(m1save, m1);
241238689Sborman     m1 = m1save;
241338689Sborman 
241438689Sborman     if (rcname == 0) {
241538689Sborman 	rcname = getenv("HOME");
241638689Sborman 	if (rcname)
241738689Sborman 	    strcpy(rcbuf, rcname);
241838689Sborman 	else
241938689Sborman 	    rcbuf[0] = '\0';
242038689Sborman 	strcat(rcbuf, "/.telnetrc");
242138689Sborman 	rcname = rcbuf;
242238689Sborman     }
242338689Sborman 
242438689Sborman     if ((rcfile = fopen(rcname, "r")) == 0) {
242538689Sborman 	return;
242638689Sborman     }
242738689Sborman 
242838689Sborman     for (;;) {
242938689Sborman 	if (fgets(line, sizeof(line), rcfile) == NULL)
243038689Sborman 	    break;
243138689Sborman 	if (line[0] == 0)
243238689Sborman 	    break;
243338689Sborman 	if (line[0] == '#')
243438689Sborman 	    continue;
243538689Sborman 	if (gotmachine == 0) {
243638689Sborman 	    if (isspace(line[0]))
243738689Sborman 		continue;
243838689Sborman 	    if (strncasecmp(line, m1, l1) == 0)
243938689Sborman 		strncpy(line, &line[l1], sizeof(line) - l1);
244038689Sborman 	    else if (strncasecmp(line, m2, l2) == 0)
244138689Sborman 		strncpy(line, &line[l2], sizeof(line) - l2);
244238689Sborman 	    else
244338689Sborman 		continue;
244438689Sborman 	    gotmachine = 1;
244538689Sborman 	} else {
244638689Sborman 	    if (!isspace(line[0])) {
244738689Sborman 		gotmachine = 0;
244838689Sborman 		continue;
244938689Sborman 	    }
245038689Sborman 	}
245138689Sborman 	makeargv();
245238689Sborman 	if (margv[0] == 0)
245338689Sborman 	    continue;
245438689Sborman 	c = getcmd(margv[0]);
245538689Sborman 	if (Ambiguous(c)) {
245638689Sborman 	    printf("?Ambiguous command: %s\n", margv[0]);
245738689Sborman 	    continue;
245838689Sborman 	}
245938689Sborman 	if (c == 0) {
246038689Sborman 	    printf("?Invalid command: %s\n", margv[0]);
246138689Sborman 	    continue;
246238689Sborman 	}
246338689Sborman 	/*
246438689Sborman 	 * This should never happen...
246538689Sborman 	 */
246638689Sborman 	if (c->needconnect && !connected) {
246738689Sborman 	    printf("?Need to be connected first for %s.\n", margv[0]);
246838689Sborman 	    continue;
246938689Sborman 	}
247038689Sborman 	(*c->handler)(margc, margv);
247138689Sborman     }
247238689Sborman     fclose(rcfile);
247338689Sborman }
247438689Sborman 
247538689Sborman #if	defined(SRCRT) && defined(IPPROTO_IP)
247638689Sborman 
247738689Sborman /*
247838689Sborman  * Source route is handed in as
247938689Sborman  *	[!]@hop1@hop2...[@|:]dst
248038689Sborman  * If the leading ! is present, it is a
248138689Sborman  * strict source route, otherwise it is
248238689Sborman  * assmed to be a loose source route.
248338689Sborman  *
248438689Sborman  * We fill in the source route option as
248538689Sborman  *	hop1,hop2,hop3...dest
248638689Sborman  * and return a pointer to hop1, which will
248738689Sborman  * be the address to connect() to.
248838689Sborman  *
248938689Sborman  * Arguments:
249038689Sborman  *	arg:	pointer to route list to decipher
249138689Sborman  *
249238689Sborman  *	cpp: 	If *cpp is not equal to NULL, this is a
249338689Sborman  *		pointer to a pointer to a character array
249438689Sborman  *		that should be filled in with the option.
249538689Sborman  *
249638689Sborman  *	lenp:	pointer to an integer that contains the
249738689Sborman  *		length of *cpp if *cpp != NULL.
249838689Sborman  *
249938689Sborman  * Return values:
250038689Sborman  *
250138689Sborman  *	Returns the address of the host to connect to.  If the
250238689Sborman  *	return value is -1, there was a syntax error in the
250338689Sborman  *	option, either unknown characters, or too many hosts.
250438689Sborman  *	If the return value is 0, one of the hostnames in the
250538689Sborman  *	path is unknown, and *cpp is set to point to the bad
250638689Sborman  *	hostname.
250738689Sborman  *
250838689Sborman  *	*cpp:	If *cpp was equal to NULL, it will be filled
250938689Sborman  *		in with a pointer to our static area that has
251038689Sborman  *		the option filled in.  This will be 32bit aligned.
251138689Sborman  *
251238689Sborman  *	*lenp:	This will be filled in with how long the option
251338689Sborman  *		pointed to by *cpp is.
251438689Sborman  *
251538689Sborman  */
251638689Sborman unsigned long
251738689Sborman sourceroute(arg, cpp, lenp)
251838689Sborman char	*arg;
251938689Sborman char	**cpp;
252038689Sborman int	*lenp;
252138689Sborman {
252238689Sborman 	static char lsr[44];
252338689Sborman 	char *cp, *cp2, *lsrp, *lsrep, *index();
252438689Sborman 	register int tmp;
252538689Sborman 	struct in_addr sin_addr;
252638689Sborman 	register struct hostent *host = 0;
252738689Sborman 	register char c;
252838689Sborman 
252938689Sborman 	/*
253038689Sborman 	 * Verify the arguments, and make sure we have
253138689Sborman 	 * at least 7 bytes for the option.
253238689Sborman 	 */
253338689Sborman 	if (cpp == NULL || lenp == NULL)
253438689Sborman 		return((unsigned long)-1);
253538689Sborman 	if (*cpp != NULL && *lenp < 7)
253638689Sborman 		return((unsigned long)-1);
253738689Sborman 	/*
253838689Sborman 	 * Decide whether we have a buffer passed to us,
253938689Sborman 	 * or if we need to use our own static buffer.
254038689Sborman 	 */
254138689Sborman 	if (*cpp) {
254238689Sborman 		lsrp = *cpp;
254338689Sborman 		lsrep = lsrp + *lenp;
254438689Sborman 	} else {
254538689Sborman 		*cpp = lsrp = lsr;
254638689Sborman 		lsrep = lsrp + 44;
254738689Sborman 	}
254838689Sborman 
254938689Sborman 	cp = arg;
255038689Sborman 
255138689Sborman 	/*
255238689Sborman 	 * Next, decide whether we have a loose source
255338689Sborman 	 * route or a strict source route, and fill in
255438689Sborman 	 * the begining of the option.
255538689Sborman 	 */
255638689Sborman 	if (*cp == '!') {
255738689Sborman 		cp++;
255838689Sborman 		*lsrp++ = IPOPT_SSRR;
255938689Sborman 	} else
256038689Sborman 		*lsrp++ = IPOPT_LSRR;
256138689Sborman 
256238689Sborman 	if (*cp != '@')
256338689Sborman 		return((unsigned long)-1);
256438689Sborman 
256538689Sborman 	lsrp++;		/* skip over length, we'll fill it in later */
256638689Sborman 	*lsrp++ = 4;
256738689Sborman 
256838689Sborman 	cp++;
256938689Sborman 
257038689Sborman 	sin_addr.s_addr = 0;
257138689Sborman 
257238689Sborman 	for (c = 0;;) {
257338689Sborman 		if (c == ':')
257438689Sborman 			cp2 = 0;
257538689Sborman 		else for (cp2 = cp; c = *cp2; cp2++) {
257638689Sborman 			if (c == ',') {
257738689Sborman 				*cp2++ = '\0';
257838689Sborman 				if (*cp2 == '@')
257938689Sborman 					cp2++;
258038689Sborman 			} else if (c == '@') {
258138689Sborman 				*cp2++ = '\0';
258238689Sborman 			} else if (c == ':') {
258338689Sborman 				*cp2++ = '\0';
258438689Sborman 			} else
258538689Sborman 				continue;
258638689Sborman 			break;
258738689Sborman 		}
258838689Sborman 		if (!c)
258938689Sborman 			cp2 = 0;
259038689Sborman 
259138689Sborman 		if ((tmp = inet_addr(cp)) != -1) {
259238689Sborman 			sin_addr.s_addr = tmp;
259338689Sborman 		} else if (host = gethostbyname(cp)) {
259438689Sborman #if	defined(h_addr)
259538689Sborman 			memcpy((caddr_t)&sin_addr,
259638689Sborman 				host->h_addr_list[0], host->h_length);
259738689Sborman #else
259838689Sborman 			memcpy((caddr_t)&sin_addr, host->h_addr, host->h_length);
259938689Sborman #endif
260038689Sborman 		} else {
260138689Sborman 			*cpp = cp;
260238689Sborman 			return(0);
260338689Sborman 		}
260438689Sborman 		memcpy(lsrp, (char *)&sin_addr, 4);
260538689Sborman 		lsrp += 4;
260638689Sborman 		if (cp2)
260738689Sborman 			cp = cp2;
260838689Sborman 		else
260938689Sborman 			break;
261038689Sborman 		/*
261138689Sborman 		 * Check to make sure there is space for next address
261238689Sborman 		 */
261338689Sborman 		if (lsrp + 4 > lsrep)
261438689Sborman 			return((unsigned long)-1);
261538689Sborman 	}
261638689Sborman 	if ((*(*cpp+IPOPT_OLEN) = lsrp - *cpp) <= 7) {
261738689Sborman 		*cpp = 0;
261838689Sborman 		*lenp = 0;
261938689Sborman 		return((unsigned long)-1);
262038689Sborman 	}
262138689Sborman 	*lsrp++ = IPOPT_NOP; /* 32 bit word align it */
262238689Sborman 	*lenp = lsrp - *cpp;
262338689Sborman 	return(sin_addr.s_addr);
262438689Sborman }
262538689Sborman #endif
262638689Sborman 
262738909Sborman #if	defined(NOSTRNCASECMP)
262838689Sborman strncasecmp(p1, p2, len)
262938689Sborman register char *p1, *p2;
263038689Sborman int len;
263138689Sborman {
263238689Sborman     while (len--) {
263338689Sborman 	if (tolower(*p1) != tolower(*p2))
263438689Sborman 	   return(tolower(*p1) - tolower(*p2));
263538689Sborman 	if (*p1 == '\0')
263638689Sborman 	    return(0);
263738689Sborman 	p1++, p2++;
263838689Sborman     }
263938689Sborman     return(0);
264038689Sborman }
264138689Sborman #endif
2642