commands.c revision 47973
129088Smarkm/*
229088Smarkm * Copyright (c) 1988, 1990, 1993
329088Smarkm *	The Regents of the University of California.  All rights reserved.
429088Smarkm *
529088Smarkm * Redistribution and use in source and binary forms, with or without
629088Smarkm * modification, are permitted provided that the following conditions
729088Smarkm * are met:
829088Smarkm * 1. Redistributions of source code must retain the above copyright
929088Smarkm *    notice, this list of conditions and the following disclaimer.
1029088Smarkm * 2. Redistributions in binary form must reproduce the above copyright
1129088Smarkm *    notice, this list of conditions and the following disclaimer in the
1229088Smarkm *    documentation and/or other materials provided with the distribution.
1329088Smarkm * 3. All advertising materials mentioning features or use of this software
1429088Smarkm *    must display the following acknowledgement:
1529088Smarkm *	This product includes software developed by the University of
1629088Smarkm *	California, Berkeley and its contributors.
1729088Smarkm * 4. Neither the name of the University nor the names of its contributors
1829088Smarkm *    may be used to endorse or promote products derived from this software
1929088Smarkm *    without specific prior written permission.
2029088Smarkm *
2129088Smarkm * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2229088Smarkm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2329088Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2429088Smarkm * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2529088Smarkm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2629088Smarkm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2729088Smarkm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2829088Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2929088Smarkm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3029088Smarkm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3129088Smarkm * SUCH DAMAGE.
3229088Smarkm */
3329088Smarkm
3429088Smarkm#ifndef lint
3529181Smarkmstatic const char sccsid[] = "@(#)commands.c	8.4 (Berkeley) 5/30/95";
3629088Smarkm#endif /* not lint */
3729088Smarkm
3829088Smarkm#if	defined(unix)
3929088Smarkm#include <sys/param.h>
4029088Smarkm#if	defined(CRAY) || defined(sysV88)
4129088Smarkm#include <sys/types.h>
4229088Smarkm#endif
4329088Smarkm#include <sys/file.h>
4429088Smarkm#else
4529088Smarkm#include <sys/types.h>
4629088Smarkm#endif	/* defined(unix) */
4729088Smarkm#include <sys/socket.h>
4829088Smarkm#include <netinet/in.h>
4929088Smarkm#ifdef	CRAY
5029088Smarkm#include <fcntl.h>
5129088Smarkm#endif	/* CRAY */
5229088Smarkm
5329088Smarkm#include <signal.h>
5429088Smarkm#include <netdb.h>
5529088Smarkm#include <ctype.h>
5629088Smarkm#include <pwd.h>
5729088Smarkm#include <varargs.h>
5829088Smarkm#include <errno.h>
5929181Smarkm#include <unistd.h>
6029181Smarkm#include <stdlib.h>
6129088Smarkm
6229088Smarkm#include <arpa/telnet.h>
6329088Smarkm
6429088Smarkm#include "general.h"
6529088Smarkm
6629088Smarkm#include "ring.h"
6729088Smarkm
6829088Smarkm#include "externs.h"
6929088Smarkm#include "defines.h"
7029088Smarkm#include "types.h"
7129088Smarkm
7229181Smarkm#if	defined(AUTHENTICATION)
7329181Smarkm#include <libtelnet/auth.h>
7429181Smarkm#endif
7529181Smarkm#if	defined(ENCRYPTION)
7629181Smarkm#include <libtelnet/encrypt.h>
7729181Smarkm#endif
7829181Smarkm
7929088Smarkm#if !defined(CRAY) && !defined(sysV88)
8029088Smarkm#include <netinet/in_systm.h>
8129088Smarkm# if (defined(vax) || defined(tahoe) || defined(hp300)) && !defined(ultrix)
8229088Smarkm# include <machine/endian.h>
8329088Smarkm# endif /* vax */
8429088Smarkm#endif /* !defined(CRAY) && !defined(sysV88) */
8529088Smarkm#include <netinet/ip.h>
8629088Smarkm
8729088Smarkm
8829088Smarkm#ifndef	MAXHOSTNAMELEN
8929088Smarkm#define	MAXHOSTNAMELEN 64
9029088Smarkm#endif	MAXHOSTNAMELEN
9129088Smarkm
9229088Smarkm#if	defined(IPPROTO_IP) && defined(IP_TOS)
9329088Smarkmint tos = -1;
9429088Smarkm#endif	/* defined(IPPROTO_IP) && defined(IP_TOS) */
9529088Smarkm
9629088Smarkmchar	*hostname;
9729088Smarkmstatic char _hostname[MAXHOSTNAMELEN];
9829088Smarkm
9929088Smarkmextern char *getenv();
10029088Smarkm
10129088Smarkmextern int isprefix();
10229088Smarkmextern char **genget();
10329088Smarkmextern int Ambiguous();
10429088Smarkm
10529181Smarkmstatic int help(int argc, char *argv[]);
10629181Smarkmstatic int call();
10729181Smarkmstatic void cmdrc(char *m1, char *m2);
10829088Smarkm
10929181Smarkmint quit(void);
11029181Smarkm
11129088Smarkmtypedef struct {
11229088Smarkm	char	*name;		/* command name */
11329088Smarkm	char	*help;		/* help string (NULL for no help) */
11429088Smarkm	int	(*handler)();	/* routine which executes command */
11529088Smarkm	int	needconnect;	/* Do we need to be connected to execute? */
11629088Smarkm} Command;
11729088Smarkm
11829088Smarkmstatic char line[256];
11929088Smarkmstatic char saveline[256];
12029088Smarkmstatic int margc;
12129088Smarkmstatic char *margv[20];
12229088Smarkm
12329181Smarkm#if	defined(SKEY)
12429181Smarkm#include <sys/wait.h>
12529181Smarkm#define PATH_SKEY	"/usr/bin/key"
12629181Smarkm    int
12729181Smarkmskey_calc(argc, argv)
12829181Smarkm	int argc;
12929181Smarkm	char **argv;
13029181Smarkm{
13129181Smarkm	int status;
13229181Smarkm
13329181Smarkm	if(argc != 3) {
13429181Smarkm		printf("%s sequence challenge\n", argv[0]);
13529181Smarkm		return;
13629181Smarkm	}
13729181Smarkm
13829181Smarkm	switch(fork()) {
13929181Smarkm	case 0:
14029181Smarkm		execv(PATH_SKEY, argv);
14129181Smarkm		exit (1);
14229181Smarkm	case -1:
14329181Smarkm		perror("fork");
14429181Smarkm		break;
14529181Smarkm	default:
14629181Smarkm		(void) wait(&status);
14729181Smarkm		if (WIFEXITED(status))
14829181Smarkm			return (WEXITSTATUS(status));
14929181Smarkm		return (0);
15029181Smarkm	}
15129181Smarkm}
15229181Smarkm#endif
15329181Smarkm
15429088Smarkm    static void
15529088Smarkmmakeargv()
15629088Smarkm{
15729088Smarkm    register char *cp, *cp2, c;
15829088Smarkm    register char **argp = margv;
15929088Smarkm
16029088Smarkm    margc = 0;
16129088Smarkm    cp = line;
16229088Smarkm    if (*cp == '!') {		/* Special case shell escape */
16329088Smarkm	strcpy(saveline, line);	/* save for shell command */
16429088Smarkm	*argp++ = "!";		/* No room in string to get this */
16529088Smarkm	margc++;
16629088Smarkm	cp++;
16729088Smarkm    }
16829181Smarkm    while ((c = *cp)) {
16929088Smarkm	register int inquote = 0;
17029088Smarkm	while (isspace(c))
17129088Smarkm	    c = *++cp;
17229088Smarkm	if (c == '\0')
17329088Smarkm	    break;
17429088Smarkm	*argp++ = cp;
17529088Smarkm	margc += 1;
17629088Smarkm	for (cp2 = cp; c != '\0'; c = *++cp) {
17729088Smarkm	    if (inquote) {
17829088Smarkm		if (c == inquote) {
17929088Smarkm		    inquote = 0;
18029088Smarkm		    continue;
18129088Smarkm		}
18229088Smarkm	    } else {
18329088Smarkm		if (c == '\\') {
18429088Smarkm		    if ((c = *++cp) == '\0')
18529088Smarkm			break;
18629088Smarkm		} else if (c == '"') {
18729088Smarkm		    inquote = '"';
18829088Smarkm		    continue;
18929088Smarkm		} else if (c == '\'') {
19029088Smarkm		    inquote = '\'';
19129088Smarkm		    continue;
19229088Smarkm		} else if (isspace(c))
19329088Smarkm		    break;
19429088Smarkm	    }
19529088Smarkm	    *cp2++ = c;
19629088Smarkm	}
19729088Smarkm	*cp2 = '\0';
19829088Smarkm	if (c == '\0')
19929088Smarkm	    break;
20029088Smarkm	cp++;
20129088Smarkm    }
20229088Smarkm    *argp++ = 0;
20329088Smarkm}
20429088Smarkm
20529088Smarkm/*
20629088Smarkm * Make a character string into a number.
20729088Smarkm *
20829088Smarkm * Todo:  1.  Could take random integers (12, 0x12, 012, 0b1).
20929088Smarkm */
21029088Smarkm
21129181Smarkm	static int
21229088Smarkmspecial(s)
21329088Smarkm	register char *s;
21429088Smarkm{
21529088Smarkm	register char c;
21629088Smarkm	char b;
21729088Smarkm
21829088Smarkm	switch (*s) {
21929088Smarkm	case '^':
22029088Smarkm		b = *++s;
22129088Smarkm		if (b == '?') {
22229088Smarkm		    c = b | 0x40;		/* DEL */
22329088Smarkm		} else {
22429088Smarkm		    c = b & 0x1f;
22529088Smarkm		}
22629088Smarkm		break;
22729088Smarkm	default:
22829088Smarkm		c = *s;
22929088Smarkm		break;
23029088Smarkm	}
23129088Smarkm	return c;
23229088Smarkm}
23329088Smarkm
23429088Smarkm/*
23529088Smarkm * Construct a control character sequence
23629088Smarkm * for a special character.
23729088Smarkm */
23829088Smarkm	static char *
23929088Smarkmcontrol(c)
24029088Smarkm	register cc_t c;
24129088Smarkm{
24229088Smarkm	static char buf[5];
24329088Smarkm	/*
24429088Smarkm	 * The only way I could get the Sun 3.5 compiler
24529088Smarkm	 * to shut up about
24629088Smarkm	 *	if ((unsigned int)c >= 0x80)
24729088Smarkm	 * was to assign "c" to an unsigned int variable...
24829088Smarkm	 * Arggg....
24929088Smarkm	 */
25029088Smarkm	register unsigned int uic = (unsigned int)c;
25129088Smarkm
25229088Smarkm	if (uic == 0x7f)
25329088Smarkm		return ("^?");
25429088Smarkm	if (c == (cc_t)_POSIX_VDISABLE) {
25529088Smarkm		return "off";
25629088Smarkm	}
25729088Smarkm	if (uic >= 0x80) {
25829088Smarkm		buf[0] = '\\';
25929088Smarkm		buf[1] = ((c>>6)&07) + '0';
26029088Smarkm		buf[2] = ((c>>3)&07) + '0';
26129088Smarkm		buf[3] = (c&07) + '0';
26229088Smarkm		buf[4] = 0;
26329088Smarkm	} else if (uic >= 0x20) {
26429088Smarkm		buf[0] = c;
26529088Smarkm		buf[1] = 0;
26629088Smarkm	} else {
26729088Smarkm		buf[0] = '^';
26829088Smarkm		buf[1] = '@'+c;
26929088Smarkm		buf[2] = 0;
27029088Smarkm	}
27129088Smarkm	return (buf);
27229088Smarkm}
27329088Smarkm
27429088Smarkm
27529088Smarkm
27629088Smarkm/*
27729088Smarkm *	The following are data structures and routines for
27829088Smarkm *	the "send" command.
27929088Smarkm *
28029088Smarkm */
28129088Smarkm
28229088Smarkmstruct sendlist {
28329088Smarkm    char	*name;		/* How user refers to it (case independent) */
28429088Smarkm    char	*help;		/* Help information (0 ==> no help) */
28529088Smarkm    int		needconnect;	/* Need to be connected */
28629088Smarkm    int		narg;		/* Number of arguments */
28729088Smarkm    int		(*handler)();	/* Routine to perform (for special ops) */
28829088Smarkm    int		nbyte;		/* Number of bytes to send this command */
28929088Smarkm    int		what;		/* Character to be sent (<0 ==> special) */
29029088Smarkm};
29129088Smarkm
29229088Smarkm
29329088Smarkmstatic int
29429088Smarkm	send_esc P((void)),
29529088Smarkm	send_help P((void)),
29629088Smarkm	send_docmd P((char *)),
29729088Smarkm	send_dontcmd P((char *)),
29829088Smarkm	send_willcmd P((char *)),
29929088Smarkm	send_wontcmd P((char *));
30029088Smarkm
30129088Smarkmstatic struct sendlist Sendlist[] = {
30229088Smarkm    { "ao",	"Send Telnet Abort output",		1, 0, 0, 2, AO },
30329088Smarkm    { "ayt",	"Send Telnet 'Are You There'",		1, 0, 0, 2, AYT },
30429088Smarkm    { "brk",	"Send Telnet Break",			1, 0, 0, 2, BREAK },
30529088Smarkm    { "break",	0,					1, 0, 0, 2, BREAK },
30629088Smarkm    { "ec",	"Send Telnet Erase Character",		1, 0, 0, 2, EC },
30729088Smarkm    { "el",	"Send Telnet Erase Line",		1, 0, 0, 2, EL },
30829088Smarkm    { "escape",	"Send current escape character",	1, 0, send_esc, 1, 0 },
30929088Smarkm    { "ga",	"Send Telnet 'Go Ahead' sequence",	1, 0, 0, 2, GA },
31029088Smarkm    { "ip",	"Send Telnet Interrupt Process",	1, 0, 0, 2, IP },
31129088Smarkm    { "intp",	0,					1, 0, 0, 2, IP },
31229088Smarkm    { "interrupt", 0,					1, 0, 0, 2, IP },
31329088Smarkm    { "intr",	0,					1, 0, 0, 2, IP },
31429088Smarkm    { "nop",	"Send Telnet 'No operation'",		1, 0, 0, 2, NOP },
31529088Smarkm    { "eor",	"Send Telnet 'End of Record'",		1, 0, 0, 2, EOR },
31629088Smarkm    { "abort",	"Send Telnet 'Abort Process'",		1, 0, 0, 2, ABORT },
31729088Smarkm    { "susp",	"Send Telnet 'Suspend Process'",	1, 0, 0, 2, SUSP },
31829088Smarkm    { "eof",	"Send Telnet End of File Character",	1, 0, 0, 2, xEOF },
31929088Smarkm    { "synch",	"Perform Telnet 'Synch operation'",	1, 0, dosynch, 2, 0 },
32029088Smarkm    { "getstatus", "Send request for STATUS",		1, 0, get_status, 6, 0 },
32129088Smarkm    { "?",	"Display send options",			0, 0, send_help, 0, 0 },
32229088Smarkm    { "help",	0,					0, 0, send_help, 0, 0 },
32329088Smarkm    { "do",	0,					0, 1, send_docmd, 3, 0 },
32429088Smarkm    { "dont",	0,					0, 1, send_dontcmd, 3, 0 },
32529088Smarkm    { "will",	0,					0, 1, send_willcmd, 3, 0 },
32629088Smarkm    { "wont",	0,					0, 1, send_wontcmd, 3, 0 },
32729088Smarkm    { 0 }
32829088Smarkm};
32929088Smarkm
33029088Smarkm#define	GETSEND(name) ((struct sendlist *) genget(name, (char **) Sendlist, \
33129088Smarkm				sizeof(struct sendlist)))
33229088Smarkm
33329088Smarkm    static int
33429088Smarkmsendcmd(argc, argv)
33529088Smarkm    int  argc;
33629088Smarkm    char **argv;
33729088Smarkm{
33829088Smarkm    int count;		/* how many bytes we are going to need to send */
33929088Smarkm    int i;
34029088Smarkm    struct sendlist *s;	/* pointer to current command */
34129088Smarkm    int success = 0;
34229088Smarkm    int needconnect = 0;
34329088Smarkm
34429088Smarkm    if (argc < 2) {
34529088Smarkm	printf("need at least one argument for 'send' command\n");
34629088Smarkm	printf("'send ?' for help\n");
34729088Smarkm	return 0;
34829088Smarkm    }
34929088Smarkm    /*
35029088Smarkm     * First, validate all the send arguments.
35129088Smarkm     * In addition, we see how much space we are going to need, and
35229088Smarkm     * whether or not we will be doing a "SYNCH" operation (which
35329088Smarkm     * flushes the network queue).
35429088Smarkm     */
35529088Smarkm    count = 0;
35629088Smarkm    for (i = 1; i < argc; i++) {
35729088Smarkm	s = GETSEND(argv[i]);
35829088Smarkm	if (s == 0) {
35929088Smarkm	    printf("Unknown send argument '%s'\n'send ?' for help.\n",
36029088Smarkm			argv[i]);
36129088Smarkm	    return 0;
36229088Smarkm	} else if (Ambiguous(s)) {
36329088Smarkm	    printf("Ambiguous send argument '%s'\n'send ?' for help.\n",
36429088Smarkm			argv[i]);
36529088Smarkm	    return 0;
36629088Smarkm	}
36729088Smarkm	if (i + s->narg >= argc) {
36829088Smarkm	    fprintf(stderr,
36929088Smarkm	    "Need %d argument%s to 'send %s' command.  'send %s ?' for help.\n",
37029088Smarkm		s->narg, s->narg == 1 ? "" : "s", s->name, s->name);
37129088Smarkm	    return 0;
37229088Smarkm	}
37329088Smarkm	count += s->nbyte;
37429088Smarkm	if (s->handler == send_help) {
37529088Smarkm	    send_help();
37629088Smarkm	    return 0;
37729088Smarkm	}
37829088Smarkm
37929088Smarkm	i += s->narg;
38029088Smarkm	needconnect += s->needconnect;
38129088Smarkm    }
38229088Smarkm    if (!connected && needconnect) {
38329088Smarkm	printf("?Need to be connected first.\n");
38429088Smarkm	printf("'send ?' for help\n");
38529088Smarkm	return 0;
38629088Smarkm    }
38729088Smarkm    /* Now, do we have enough room? */
38829088Smarkm    if (NETROOM() < count) {
38929088Smarkm	printf("There is not enough room in the buffer TO the network\n");
39029088Smarkm	printf("to process your request.  Nothing will be done.\n");
39129088Smarkm	printf("('send synch' will throw away most data in the network\n");
39229088Smarkm	printf("buffer, if this might help.)\n");
39329088Smarkm	return 0;
39429088Smarkm    }
39529088Smarkm    /* OK, they are all OK, now go through again and actually send */
39629088Smarkm    count = 0;
39729088Smarkm    for (i = 1; i < argc; i++) {
39829088Smarkm	if ((s = GETSEND(argv[i])) == 0) {
39929088Smarkm	    fprintf(stderr, "Telnet 'send' error - argument disappeared!\n");
40029088Smarkm	    (void) quit();
40129088Smarkm	    /*NOTREACHED*/
40229088Smarkm	}
40329088Smarkm	if (s->handler) {
40429088Smarkm	    count++;
40529088Smarkm	    success += (*s->handler)((s->narg > 0) ? argv[i+1] : 0,
40629088Smarkm				  (s->narg > 1) ? argv[i+2] : 0);
40729088Smarkm	    i += s->narg;
40829088Smarkm	} else {
40929088Smarkm	    NET2ADD(IAC, s->what);
41029088Smarkm	    printoption("SENT", IAC, s->what);
41129088Smarkm	}
41229088Smarkm    }
41329088Smarkm    return (count == success);
41429088Smarkm}
41529088Smarkm
41629088Smarkm    static int
41729088Smarkmsend_esc()
41829088Smarkm{
41929088Smarkm    NETADD(escape);
42029088Smarkm    return 1;
42129088Smarkm}
42229088Smarkm
42329088Smarkm    static int
42429088Smarkmsend_docmd(name)
42529088Smarkm    char *name;
42629088Smarkm{
42729088Smarkm    return(send_tncmd(send_do, "do", name));
42829088Smarkm}
42929088Smarkm
43029088Smarkm    static int
43129088Smarkmsend_dontcmd(name)
43229088Smarkm    char *name;
43329088Smarkm{
43429088Smarkm    return(send_tncmd(send_dont, "dont", name));
43529088Smarkm}
43629088Smarkm    static int
43729088Smarkmsend_willcmd(name)
43829088Smarkm    char *name;
43929088Smarkm{
44029088Smarkm    return(send_tncmd(send_will, "will", name));
44129088Smarkm}
44229088Smarkm    static int
44329088Smarkmsend_wontcmd(name)
44429088Smarkm    char *name;
44529088Smarkm{
44629088Smarkm    return(send_tncmd(send_wont, "wont", name));
44729088Smarkm}
44829088Smarkm
44929088Smarkm    int
45029088Smarkmsend_tncmd(func, cmd, name)
45129088Smarkm    void	(*func)();
45229088Smarkm    char	*cmd, *name;
45329088Smarkm{
45429088Smarkm    char **cpp;
45529088Smarkm    extern char *telopts[];
45629088Smarkm    register int val = 0;
45729088Smarkm
45829088Smarkm    if (isprefix(name, "help") || isprefix(name, "?")) {
45929088Smarkm	register int col, len;
46029088Smarkm
46129088Smarkm	printf("Usage: send %s <value|option>\n", cmd);
46229088Smarkm	printf("\"value\" must be from 0 to 255\n");
46329088Smarkm	printf("Valid options are:\n\t");
46429088Smarkm
46529088Smarkm	col = 8;
46629088Smarkm	for (cpp = telopts; *cpp; cpp++) {
46729088Smarkm	    len = strlen(*cpp) + 3;
46829088Smarkm	    if (col + len > 65) {
46929088Smarkm		printf("\n\t");
47029088Smarkm		col = 8;
47129088Smarkm	    }
47229088Smarkm	    printf(" \"%s\"", *cpp);
47329088Smarkm	    col += len;
47429088Smarkm	}
47529088Smarkm	printf("\n");
47629088Smarkm	return 0;
47729088Smarkm    }
47829088Smarkm    cpp = (char **)genget(name, telopts, sizeof(char *));
47929088Smarkm    if (Ambiguous(cpp)) {
48029088Smarkm	fprintf(stderr,"'%s': ambiguous argument ('send %s ?' for help).\n",
48129088Smarkm					name, cmd);
48229088Smarkm	return 0;
48329088Smarkm    }
48429088Smarkm    if (cpp) {
48529088Smarkm	val = cpp - telopts;
48629088Smarkm    } else {
48729088Smarkm	register char *cp = name;
48829088Smarkm
48929088Smarkm	while (*cp >= '0' && *cp <= '9') {
49029088Smarkm	    val *= 10;
49129088Smarkm	    val += *cp - '0';
49229088Smarkm	    cp++;
49329088Smarkm	}
49429088Smarkm	if (*cp != 0) {
49529088Smarkm	    fprintf(stderr, "'%s': unknown argument ('send %s ?' for help).\n",
49629088Smarkm					name, cmd);
49729088Smarkm	    return 0;
49829088Smarkm	} else if (val < 0 || val > 255) {
49929088Smarkm	    fprintf(stderr, "'%s': bad value ('send %s ?' for help).\n",
50029088Smarkm					name, cmd);
50129088Smarkm	    return 0;
50229088Smarkm	}
50329088Smarkm    }
50429088Smarkm    if (!connected) {
50529088Smarkm	printf("?Need to be connected first.\n");
50629088Smarkm	return 0;
50729088Smarkm    }
50829088Smarkm    (*func)(val, 1);
50929088Smarkm    return 1;
51029088Smarkm}
51129088Smarkm
51229088Smarkm    static int
51329088Smarkmsend_help()
51429088Smarkm{
51529088Smarkm    struct sendlist *s;	/* pointer to current command */
51629088Smarkm    for (s = Sendlist; s->name; s++) {
51729088Smarkm	if (s->help)
51829088Smarkm	    printf("%-15s %s\n", s->name, s->help);
51929088Smarkm    }
52029088Smarkm    return(0);
52129088Smarkm}
52229088Smarkm
52329088Smarkm/*
52429088Smarkm * The following are the routines and data structures referred
52529088Smarkm * to by the arguments to the "toggle" command.
52629088Smarkm */
52729088Smarkm
52829088Smarkm    static int
52929088Smarkmlclchars()
53029088Smarkm{
53129088Smarkm    donelclchars = 1;
53229088Smarkm    return 1;
53329088Smarkm}
53429088Smarkm
53529088Smarkm    static int
53629088Smarkmtogdebug()
53729088Smarkm{
53829088Smarkm#ifndef	NOT43
53929088Smarkm    if (net > 0 &&
54029088Smarkm	(SetSockOpt(net, SOL_SOCKET, SO_DEBUG, debug)) < 0) {
54129088Smarkm	    perror("setsockopt (SO_DEBUG)");
54229088Smarkm    }
54329088Smarkm#else	/* NOT43 */
54429088Smarkm    if (debug) {
54529181Smarkm	if (net > 0 && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 1) < 0)
54629088Smarkm	    perror("setsockopt (SO_DEBUG)");
54729088Smarkm    } else
54829088Smarkm	printf("Cannot turn off socket debugging\n");
54929088Smarkm#endif	/* NOT43 */
55029088Smarkm    return 1;
55129088Smarkm}
55229088Smarkm
55329088Smarkm
55429088Smarkm    static int
55529088Smarkmtogcrlf()
55629088Smarkm{
55729088Smarkm    if (crlf) {
55829088Smarkm	printf("Will send carriage returns as telnet <CR><LF>.\n");
55929088Smarkm    } else {
56029088Smarkm	printf("Will send carriage returns as telnet <CR><NUL>.\n");
56129088Smarkm    }
56229088Smarkm    return 1;
56329088Smarkm}
56429088Smarkm
56529088Smarkmint binmode;
56629088Smarkm
56729088Smarkm    static int
56829088Smarkmtogbinary(val)
56929088Smarkm    int val;
57029088Smarkm{
57129088Smarkm    donebinarytoggle = 1;
57229088Smarkm
57329088Smarkm    if (val >= 0) {
57429088Smarkm	binmode = val;
57529088Smarkm    } else {
57629088Smarkm	if (my_want_state_is_will(TELOPT_BINARY) &&
57729088Smarkm				my_want_state_is_do(TELOPT_BINARY)) {
57829088Smarkm	    binmode = 1;
57929088Smarkm	} else if (my_want_state_is_wont(TELOPT_BINARY) &&
58029088Smarkm				my_want_state_is_dont(TELOPT_BINARY)) {
58129088Smarkm	    binmode = 0;
58229088Smarkm	}
58329088Smarkm	val = binmode ? 0 : 1;
58429088Smarkm    }
58529088Smarkm
58629088Smarkm    if (val == 1) {
58729088Smarkm	if (my_want_state_is_will(TELOPT_BINARY) &&
58829088Smarkm					my_want_state_is_do(TELOPT_BINARY)) {
58929088Smarkm	    printf("Already operating in binary mode with remote host.\n");
59029088Smarkm	} else {
59129088Smarkm	    printf("Negotiating binary mode with remote host.\n");
59229088Smarkm	    tel_enter_binary(3);
59329088Smarkm	}
59429088Smarkm    } else {
59529088Smarkm	if (my_want_state_is_wont(TELOPT_BINARY) &&
59629088Smarkm					my_want_state_is_dont(TELOPT_BINARY)) {
59729088Smarkm	    printf("Already in network ascii mode with remote host.\n");
59829088Smarkm	} else {
59929088Smarkm	    printf("Negotiating network ascii mode with remote host.\n");
60029088Smarkm	    tel_leave_binary(3);
60129088Smarkm	}
60229088Smarkm    }
60329088Smarkm    return 1;
60429088Smarkm}
60529088Smarkm
60629088Smarkm    static int
60729088Smarkmtogrbinary(val)
60829088Smarkm    int val;
60929088Smarkm{
61029088Smarkm    donebinarytoggle = 1;
61129088Smarkm
61229088Smarkm    if (val == -1)
61329088Smarkm	val = my_want_state_is_do(TELOPT_BINARY) ? 0 : 1;
61429088Smarkm
61529088Smarkm    if (val == 1) {
61629088Smarkm	if (my_want_state_is_do(TELOPT_BINARY)) {
61729088Smarkm	    printf("Already receiving in binary mode.\n");
61829088Smarkm	} else {
61929088Smarkm	    printf("Negotiating binary mode on input.\n");
62029088Smarkm	    tel_enter_binary(1);
62129088Smarkm	}
62229088Smarkm    } else {
62329088Smarkm	if (my_want_state_is_dont(TELOPT_BINARY)) {
62429088Smarkm	    printf("Already receiving in network ascii mode.\n");
62529088Smarkm	} else {
62629088Smarkm	    printf("Negotiating network ascii mode on input.\n");
62729088Smarkm	    tel_leave_binary(1);
62829088Smarkm	}
62929088Smarkm    }
63029088Smarkm    return 1;
63129088Smarkm}
63229088Smarkm
63329088Smarkm    static int
63429088Smarkmtogxbinary(val)
63529088Smarkm    int val;
63629088Smarkm{
63729088Smarkm    donebinarytoggle = 1;
63829088Smarkm
63929088Smarkm    if (val == -1)
64029088Smarkm	val = my_want_state_is_will(TELOPT_BINARY) ? 0 : 1;
64129088Smarkm
64229088Smarkm    if (val == 1) {
64329088Smarkm	if (my_want_state_is_will(TELOPT_BINARY)) {
64429088Smarkm	    printf("Already transmitting in binary mode.\n");
64529088Smarkm	} else {
64629088Smarkm	    printf("Negotiating binary mode on output.\n");
64729088Smarkm	    tel_enter_binary(2);
64829088Smarkm	}
64929088Smarkm    } else {
65029088Smarkm	if (my_want_state_is_wont(TELOPT_BINARY)) {
65129088Smarkm	    printf("Already transmitting in network ascii mode.\n");
65229088Smarkm	} else {
65329088Smarkm	    printf("Negotiating network ascii mode on output.\n");
65429088Smarkm	    tel_leave_binary(2);
65529088Smarkm	}
65629088Smarkm    }
65729088Smarkm    return 1;
65829088Smarkm}
65929088Smarkm
66029088Smarkm
66129088Smarkmstatic int togglehelp P((void));
66229088Smarkm#if	defined(AUTHENTICATION)
66329088Smarkmextern int auth_togdebug P((int));
66429088Smarkm#endif
66529088Smarkm#ifdef	ENCRYPTION
66629088Smarkmextern int EncryptAutoEnc P((int));
66729088Smarkmextern int EncryptAutoDec P((int));
66829088Smarkmextern int EncryptDebug P((int));
66929088Smarkmextern int EncryptVerbose P((int));
67029088Smarkm#endif	/* ENCRYPTION */
67129088Smarkm
67229088Smarkmstruct togglelist {
67329088Smarkm    char	*name;		/* name of toggle */
67429088Smarkm    char	*help;		/* help message */
67529088Smarkm    int		(*handler)();	/* routine to do actual setting */
67629088Smarkm    int		*variable;
67729088Smarkm    char	*actionexplanation;
67829088Smarkm};
67929088Smarkm
68029088Smarkmstatic struct togglelist Togglelist[] = {
68129088Smarkm    { "autoflush",
68229088Smarkm	"flushing of output when sending interrupt characters",
68329088Smarkm	    0,
68429088Smarkm		&autoflush,
68529088Smarkm		    "flush output when sending interrupt characters" },
68629088Smarkm    { "autosynch",
68729088Smarkm	"automatic sending of interrupt characters in urgent mode",
68829088Smarkm	    0,
68929088Smarkm		&autosynch,
69029088Smarkm		    "send interrupt characters in urgent mode" },
69129088Smarkm#if	defined(AUTHENTICATION)
69229088Smarkm    { "autologin",
69329088Smarkm	"automatic sending of login and/or authentication info",
69429088Smarkm	    0,
69529088Smarkm		&autologin,
69629088Smarkm		    "send login name and/or authentication information" },
69729088Smarkm    { "authdebug",
69829088Smarkm	"Toggle authentication debugging",
69929088Smarkm	    auth_togdebug,
70029088Smarkm		0,
70129088Smarkm		     "print authentication debugging information" },
70229088Smarkm#endif
70329088Smarkm#ifdef	ENCRYPTION
70429088Smarkm    { "autoencrypt",
70529088Smarkm	"automatic encryption of data stream",
70629088Smarkm	    EncryptAutoEnc,
70729088Smarkm		0,
70829088Smarkm		    "automatically encrypt output" },
70929088Smarkm    { "autodecrypt",
71029088Smarkm	"automatic decryption of data stream",
71129088Smarkm	    EncryptAutoDec,
71229088Smarkm		0,
71329088Smarkm		    "automatically decrypt input" },
71429088Smarkm    { "verbose_encrypt",
71529088Smarkm	"Toggle verbose encryption output",
71629088Smarkm	    EncryptVerbose,
71729088Smarkm		0,
71829088Smarkm		    "print verbose encryption output" },
71929088Smarkm    { "encdebug",
72029088Smarkm	"Toggle encryption debugging",
72129088Smarkm	    EncryptDebug,
72229088Smarkm		0,
72329088Smarkm		    "print encryption debugging information" },
72429088Smarkm#endif	/* ENCRYPTION */
72529088Smarkm    { "skiprc",
72629088Smarkm	"don't read ~/.telnetrc file",
72729088Smarkm	    0,
72829088Smarkm		&skiprc,
72929088Smarkm		    "skip reading of ~/.telnetrc file" },
73029088Smarkm    { "binary",
73129088Smarkm	"sending and receiving of binary data",
73229088Smarkm	    togbinary,
73329088Smarkm		0,
73429088Smarkm		    0 },
73529088Smarkm    { "inbinary",
73629088Smarkm	"receiving of binary data",
73729088Smarkm	    togrbinary,
73829088Smarkm		0,
73929088Smarkm		    0 },
74029088Smarkm    { "outbinary",
74129088Smarkm	"sending of binary data",
74229088Smarkm	    togxbinary,
74329088Smarkm		0,
74429088Smarkm		    0 },
74529088Smarkm    { "crlf",
74629088Smarkm	"sending carriage returns as telnet <CR><LF>",
74729088Smarkm	    togcrlf,
74829088Smarkm		&crlf,
74929088Smarkm		    0 },
75029088Smarkm    { "crmod",
75129088Smarkm	"mapping of received carriage returns",
75229088Smarkm	    0,
75329088Smarkm		&crmod,
75429088Smarkm		    "map carriage return on output" },
75529088Smarkm    { "localchars",
75629088Smarkm	"local recognition of certain control characters",
75729088Smarkm	    lclchars,
75829088Smarkm		&localchars,
75929088Smarkm		    "recognize certain control characters" },
76029088Smarkm    { " ", "", 0 },		/* empty line */
76129088Smarkm#if	defined(unix) && defined(TN3270)
76229088Smarkm    { "apitrace",
76329088Smarkm	"(debugging) toggle tracing of API transactions",
76429088Smarkm	    0,
76529088Smarkm		&apitrace,
76629088Smarkm		    "trace API transactions" },
76729088Smarkm    { "cursesdata",
76829088Smarkm	"(debugging) toggle printing of hexadecimal curses data",
76929088Smarkm	    0,
77029088Smarkm		&cursesdata,
77129088Smarkm		    "print hexadecimal representation of curses data" },
77229088Smarkm#endif	/* defined(unix) && defined(TN3270) */
77329088Smarkm    { "debug",
77429088Smarkm	"debugging",
77529088Smarkm	    togdebug,
77629088Smarkm		&debug,
77729088Smarkm		    "turn on socket level debugging" },
77829088Smarkm    { "netdata",
77929088Smarkm	"printing of hexadecimal network data (debugging)",
78029088Smarkm	    0,
78129088Smarkm		&netdata,
78229088Smarkm		    "print hexadecimal representation of network traffic" },
78329088Smarkm    { "prettydump",
78429088Smarkm	"output of \"netdata\" to user readable format (debugging)",
78529088Smarkm	    0,
78629088Smarkm		&prettydump,
78729088Smarkm		    "print user readable output for \"netdata\"" },
78829088Smarkm    { "options",
78929088Smarkm	"viewing of options processing (debugging)",
79029088Smarkm	    0,
79129088Smarkm		&showoptions,
79229088Smarkm		    "show option processing" },
79329088Smarkm#if	defined(unix)
79429088Smarkm    { "termdata",
79529088Smarkm	"(debugging) toggle printing of hexadecimal terminal data",
79629088Smarkm	    0,
79729088Smarkm		&termdata,
79829088Smarkm		    "print hexadecimal representation of terminal traffic" },
79929088Smarkm#endif	/* defined(unix) */
80029088Smarkm    { "?",
80129088Smarkm	0,
80229088Smarkm	    togglehelp },
80329088Smarkm    { "help",
80429088Smarkm	0,
80529088Smarkm	    togglehelp },
80629088Smarkm    { 0 }
80729088Smarkm};
80829088Smarkm
80929088Smarkm    static int
81029088Smarkmtogglehelp()
81129088Smarkm{
81229088Smarkm    struct togglelist *c;
81329088Smarkm
81429088Smarkm    for (c = Togglelist; c->name; c++) {
81529088Smarkm	if (c->help) {
81629088Smarkm	    if (*c->help)
81729088Smarkm		printf("%-15s toggle %s\n", c->name, c->help);
81829088Smarkm	    else
81929088Smarkm		printf("\n");
82029088Smarkm	}
82129088Smarkm    }
82229088Smarkm    printf("\n");
82329088Smarkm    printf("%-15s %s\n", "?", "display help information");
82429088Smarkm    return 0;
82529088Smarkm}
82629088Smarkm
82729088Smarkm    static void
82829088Smarkmsettogglehelp(set)
82929088Smarkm    int set;
83029088Smarkm{
83129088Smarkm    struct togglelist *c;
83229088Smarkm
83329088Smarkm    for (c = Togglelist; c->name; c++) {
83429088Smarkm	if (c->help) {
83529088Smarkm	    if (*c->help)
83629088Smarkm		printf("%-15s %s %s\n", c->name, set ? "enable" : "disable",
83729088Smarkm						c->help);
83829088Smarkm	    else
83929088Smarkm		printf("\n");
84029088Smarkm	}
84129088Smarkm    }
84229088Smarkm}
84329088Smarkm
84429088Smarkm#define	GETTOGGLE(name) (struct togglelist *) \
84529088Smarkm		genget(name, (char **) Togglelist, sizeof(struct togglelist))
84629088Smarkm
84729088Smarkm    static int
84829088Smarkmtoggle(argc, argv)
84929088Smarkm    int  argc;
85029088Smarkm    char *argv[];
85129088Smarkm{
85229088Smarkm    int retval = 1;
85329088Smarkm    char *name;
85429088Smarkm    struct togglelist *c;
85529088Smarkm
85629088Smarkm    if (argc < 2) {
85729088Smarkm	fprintf(stderr,
85829088Smarkm	    "Need an argument to 'toggle' command.  'toggle ?' for help.\n");
85929088Smarkm	return 0;
86029088Smarkm    }
86129088Smarkm    argc--;
86229088Smarkm    argv++;
86329088Smarkm    while (argc--) {
86429088Smarkm	name = *argv++;
86529088Smarkm	c = GETTOGGLE(name);
86629088Smarkm	if (Ambiguous(c)) {
86729088Smarkm	    fprintf(stderr, "'%s': ambiguous argument ('toggle ?' for help).\n",
86829088Smarkm					name);
86929088Smarkm	    return 0;
87029088Smarkm	} else if (c == 0) {
87129088Smarkm	    fprintf(stderr, "'%s': unknown argument ('toggle ?' for help).\n",
87229088Smarkm					name);
87329088Smarkm	    return 0;
87429088Smarkm	} else {
87529088Smarkm	    if (c->variable) {
87629088Smarkm		*c->variable = !*c->variable;		/* invert it */
87729088Smarkm		if (c->actionexplanation) {
87829088Smarkm		    printf("%s %s.\n", *c->variable? "Will" : "Won't",
87929088Smarkm							c->actionexplanation);
88029088Smarkm		}
88129088Smarkm	    }
88229088Smarkm	    if (c->handler) {
88329088Smarkm		retval &= (*c->handler)(-1);
88429088Smarkm	    }
88529088Smarkm	}
88629088Smarkm    }
88729088Smarkm    return retval;
88829088Smarkm}
88929088Smarkm
89029088Smarkm/*
89129088Smarkm * The following perform the "set" command.
89229088Smarkm */
89329088Smarkm
89429088Smarkm#ifdef	USE_TERMIO
89529088Smarkmstruct termio new_tc = { 0 };
89629088Smarkm#endif
89729088Smarkm
89829088Smarkmstruct setlist {
89929088Smarkm    char *name;				/* name */
90029088Smarkm    char *help;				/* help information */
90129088Smarkm    void (*handler)();
90229088Smarkm    cc_t *charp;			/* where it is located at */
90329088Smarkm};
90429088Smarkm
90529088Smarkmstatic struct setlist Setlist[] = {
90629088Smarkm#ifdef	KLUDGELINEMODE
90729088Smarkm    { "echo", 	"character to toggle local echoing on/off", 0, &echoc },
90829088Smarkm#endif
90929088Smarkm    { "escape",	"character to escape back to telnet command mode", 0, &escape },
91029088Smarkm    { "rlogin", "rlogin escape character", 0, &rlogin },
91129088Smarkm    { "tracefile", "file to write trace information to", SetNetTrace, (cc_t *)NetTraceFile},
91229088Smarkm    { " ", "" },
91329088Smarkm    { " ", "The following need 'localchars' to be toggled true", 0, 0 },
91429088Smarkm    { "flushoutput", "character to cause an Abort Output", 0, termFlushCharp },
91529088Smarkm    { "interrupt", "character to cause an Interrupt Process", 0, termIntCharp },
91629088Smarkm    { "quit",	"character to cause an Abort process", 0, termQuitCharp },
91729088Smarkm    { "eof",	"character to cause an EOF ", 0, termEofCharp },
91829088Smarkm    { " ", "" },
91929088Smarkm    { " ", "The following are for local editing in linemode", 0, 0 },
92029088Smarkm    { "erase",	"character to use to erase a character", 0, termEraseCharp },
92129088Smarkm    { "kill",	"character to use to erase a line", 0, termKillCharp },
92229088Smarkm    { "lnext",	"character to use for literal next", 0, termLiteralNextCharp },
92329088Smarkm    { "susp",	"character to cause a Suspend Process", 0, termSuspCharp },
92429088Smarkm    { "reprint", "character to use for line reprint", 0, termRprntCharp },
92529088Smarkm    { "worderase", "character to use to erase a word", 0, termWerasCharp },
92629088Smarkm    { "start",	"character to use for XON", 0, termStartCharp },
92729088Smarkm    { "stop",	"character to use for XOFF", 0, termStopCharp },
92829088Smarkm    { "forw1",	"alternate end of line character", 0, termForw1Charp },
92929088Smarkm    { "forw2",	"alternate end of line character", 0, termForw2Charp },
93029088Smarkm    { "ayt",	"alternate AYT character", 0, termAytCharp },
93129088Smarkm    { 0 }
93229088Smarkm};
93329088Smarkm
93429088Smarkm#if	defined(CRAY) && !defined(__STDC__)
93529088Smarkm/* Work around compiler bug in pcc 4.1.5 */
93629088Smarkm    void
93729088Smarkm_setlist_init()
93829088Smarkm{
93929088Smarkm#ifndef	KLUDGELINEMODE
94029088Smarkm#define	N 5
94129088Smarkm#else
94229088Smarkm#define	N 6
94329088Smarkm#endif
94429088Smarkm	Setlist[N+0].charp = &termFlushChar;
94529088Smarkm	Setlist[N+1].charp = &termIntChar;
94629088Smarkm	Setlist[N+2].charp = &termQuitChar;
94729088Smarkm	Setlist[N+3].charp = &termEofChar;
94829088Smarkm	Setlist[N+6].charp = &termEraseChar;
94929088Smarkm	Setlist[N+7].charp = &termKillChar;
95029088Smarkm	Setlist[N+8].charp = &termLiteralNextChar;
95129088Smarkm	Setlist[N+9].charp = &termSuspChar;
95229088Smarkm	Setlist[N+10].charp = &termRprntChar;
95329088Smarkm	Setlist[N+11].charp = &termWerasChar;
95429088Smarkm	Setlist[N+12].charp = &termStartChar;
95529088Smarkm	Setlist[N+13].charp = &termStopChar;
95629088Smarkm	Setlist[N+14].charp = &termForw1Char;
95729088Smarkm	Setlist[N+15].charp = &termForw2Char;
95829088Smarkm	Setlist[N+16].charp = &termAytChar;
95929088Smarkm#undef	N
96029088Smarkm}
96129088Smarkm#endif	/* defined(CRAY) && !defined(__STDC__) */
96229088Smarkm
96329088Smarkm    static struct setlist *
96429088Smarkmgetset(name)
96529088Smarkm    char *name;
96629088Smarkm{
96729088Smarkm    return (struct setlist *)
96829088Smarkm		genget(name, (char **) Setlist, sizeof(struct setlist));
96929088Smarkm}
97029088Smarkm
97129088Smarkm    void
97229088Smarkmset_escape_char(s)
97329088Smarkm    char *s;
97429088Smarkm{
97529088Smarkm	if (rlogin != _POSIX_VDISABLE) {
97629088Smarkm		rlogin = (s && *s) ? special(s) : _POSIX_VDISABLE;
97729088Smarkm		printf("Telnet rlogin escape character is '%s'.\n",
97829088Smarkm					control(rlogin));
97929088Smarkm	} else {
98029088Smarkm		escape = (s && *s) ? special(s) : _POSIX_VDISABLE;
98129088Smarkm		printf("Telnet escape character is '%s'.\n", control(escape));
98229088Smarkm	}
98329088Smarkm}
98429088Smarkm
98529088Smarkm    static int
98629088Smarkmsetcmd(argc, argv)
98729088Smarkm    int  argc;
98829088Smarkm    char *argv[];
98929088Smarkm{
99029088Smarkm    int value;
99129088Smarkm    struct setlist *ct;
99229088Smarkm    struct togglelist *c;
99329088Smarkm
99429088Smarkm    if (argc < 2 || argc > 3) {
99529088Smarkm	printf("Format is 'set Name Value'\n'set ?' for help.\n");
99629088Smarkm	return 0;
99729088Smarkm    }
99829088Smarkm    if ((argc == 2) && (isprefix(argv[1], "?") || isprefix(argv[1], "help"))) {
99929088Smarkm	for (ct = Setlist; ct->name; ct++)
100029088Smarkm	    printf("%-15s %s\n", ct->name, ct->help);
100129088Smarkm	printf("\n");
100229088Smarkm	settogglehelp(1);
100329088Smarkm	printf("%-15s %s\n", "?", "display help information");
100429088Smarkm	return 0;
100529088Smarkm    }
100629088Smarkm
100729088Smarkm    ct = getset(argv[1]);
100829088Smarkm    if (ct == 0) {
100929088Smarkm	c = GETTOGGLE(argv[1]);
101029088Smarkm	if (c == 0) {
101129088Smarkm	    fprintf(stderr, "'%s': unknown argument ('set ?' for help).\n",
101229088Smarkm			argv[1]);
101329088Smarkm	    return 0;
101429088Smarkm	} else if (Ambiguous(c)) {
101529088Smarkm	    fprintf(stderr, "'%s': ambiguous argument ('set ?' for help).\n",
101629088Smarkm			argv[1]);
101729088Smarkm	    return 0;
101829088Smarkm	}
101929088Smarkm	if (c->variable) {
102029088Smarkm	    if ((argc == 2) || (strcmp("on", argv[2]) == 0))
102129088Smarkm		*c->variable = 1;
102229088Smarkm	    else if (strcmp("off", argv[2]) == 0)
102329088Smarkm		*c->variable = 0;
102429088Smarkm	    else {
102529088Smarkm		printf("Format is 'set togglename [on|off]'\n'set ?' for help.\n");
102629088Smarkm		return 0;
102729088Smarkm	    }
102829088Smarkm	    if (c->actionexplanation) {
102929088Smarkm		printf("%s %s.\n", *c->variable? "Will" : "Won't",
103029088Smarkm							c->actionexplanation);
103129088Smarkm	    }
103229088Smarkm	}
103329088Smarkm	if (c->handler)
103429088Smarkm	    (*c->handler)(1);
103529088Smarkm    } else if (argc != 3) {
103629088Smarkm	printf("Format is 'set Name Value'\n'set ?' for help.\n");
103729088Smarkm	return 0;
103829088Smarkm    } else if (Ambiguous(ct)) {
103929088Smarkm	fprintf(stderr, "'%s': ambiguous argument ('set ?' for help).\n",
104029088Smarkm			argv[1]);
104129088Smarkm	return 0;
104229088Smarkm    } else if (ct->handler) {
104329088Smarkm	(*ct->handler)(argv[2]);
104429088Smarkm	printf("%s set to \"%s\".\n", ct->name, (char *)ct->charp);
104529088Smarkm    } else {
104629088Smarkm	if (strcmp("off", argv[2])) {
104729088Smarkm	    value = special(argv[2]);
104829088Smarkm	} else {
104929088Smarkm	    value = _POSIX_VDISABLE;
105029088Smarkm	}
105129088Smarkm	*(ct->charp) = (cc_t)value;
105229088Smarkm	printf("%s character is '%s'.\n", ct->name, control(*(ct->charp)));
105329088Smarkm    }
105429088Smarkm    slc_check();
105529088Smarkm    return 1;
105629088Smarkm}
105729088Smarkm
105829088Smarkm    static int
105929088Smarkmunsetcmd(argc, argv)
106029088Smarkm    int  argc;
106129088Smarkm    char *argv[];
106229088Smarkm{
106329088Smarkm    struct setlist *ct;
106429088Smarkm    struct togglelist *c;
106529088Smarkm    register char *name;
106629088Smarkm
106729088Smarkm    if (argc < 2) {
106829088Smarkm	fprintf(stderr,
106929088Smarkm	    "Need an argument to 'unset' command.  'unset ?' for help.\n");
107029088Smarkm	return 0;
107129088Smarkm    }
107229088Smarkm    if (isprefix(argv[1], "?") || isprefix(argv[1], "help")) {
107329088Smarkm	for (ct = Setlist; ct->name; ct++)
107429088Smarkm	    printf("%-15s %s\n", ct->name, ct->help);
107529088Smarkm	printf("\n");
107629088Smarkm	settogglehelp(0);
107729088Smarkm	printf("%-15s %s\n", "?", "display help information");
107829088Smarkm	return 0;
107929088Smarkm    }
108029088Smarkm
108129088Smarkm    argc--;
108229088Smarkm    argv++;
108329088Smarkm    while (argc--) {
108429088Smarkm	name = *argv++;
108529088Smarkm	ct = getset(name);
108629088Smarkm	if (ct == 0) {
108729088Smarkm	    c = GETTOGGLE(name);
108829088Smarkm	    if (c == 0) {
108929088Smarkm		fprintf(stderr, "'%s': unknown argument ('unset ?' for help).\n",
109029088Smarkm			name);
109129088Smarkm		return 0;
109229088Smarkm	    } else if (Ambiguous(c)) {
109329088Smarkm		fprintf(stderr, "'%s': ambiguous argument ('unset ?' for help).\n",
109429088Smarkm			name);
109529088Smarkm		return 0;
109629088Smarkm	    }
109729088Smarkm	    if (c->variable) {
109829088Smarkm		*c->variable = 0;
109929088Smarkm		if (c->actionexplanation) {
110029088Smarkm		    printf("%s %s.\n", *c->variable? "Will" : "Won't",
110129088Smarkm							c->actionexplanation);
110229088Smarkm		}
110329088Smarkm	    }
110429088Smarkm	    if (c->handler)
110529088Smarkm		(*c->handler)(0);
110629088Smarkm	} else if (Ambiguous(ct)) {
110729088Smarkm	    fprintf(stderr, "'%s': ambiguous argument ('unset ?' for help).\n",
110829088Smarkm			name);
110929088Smarkm	    return 0;
111029088Smarkm	} else if (ct->handler) {
111129088Smarkm	    (*ct->handler)(0);
111229088Smarkm	    printf("%s reset to \"%s\".\n", ct->name, (char *)ct->charp);
111329088Smarkm	} else {
111429088Smarkm	    *(ct->charp) = _POSIX_VDISABLE;
111529088Smarkm	    printf("%s character is '%s'.\n", ct->name, control(*(ct->charp)));
111629088Smarkm	}
111729088Smarkm    }
111829088Smarkm    return 1;
111929088Smarkm}
112029088Smarkm
112129088Smarkm/*
112229088Smarkm * The following are the data structures and routines for the
112329088Smarkm * 'mode' command.
112429088Smarkm */
112529088Smarkm#ifdef	KLUDGELINEMODE
112629088Smarkmextern int kludgelinemode;
112729088Smarkm
112847973Sru    static int
112929088Smarkmdokludgemode()
113029088Smarkm{
113129088Smarkm    kludgelinemode = 1;
113229088Smarkm    send_wont(TELOPT_LINEMODE, 1);
113329088Smarkm    send_dont(TELOPT_SGA, 1);
113429088Smarkm    send_dont(TELOPT_ECHO, 1);
113529088Smarkm}
113629088Smarkm#endif
113729088Smarkm
113829088Smarkm    static int
113929088Smarkmdolinemode()
114029088Smarkm{
114129088Smarkm#ifdef	KLUDGELINEMODE
114229088Smarkm    if (kludgelinemode)
114329088Smarkm	send_dont(TELOPT_SGA, 1);
114429088Smarkm#endif
114529088Smarkm    send_will(TELOPT_LINEMODE, 1);
114629088Smarkm    send_dont(TELOPT_ECHO, 1);
114729088Smarkm    return 1;
114829088Smarkm}
114929088Smarkm
115029088Smarkm    static int
115129088Smarkmdocharmode()
115229088Smarkm{
115329088Smarkm#ifdef	KLUDGELINEMODE
115429088Smarkm    if (kludgelinemode)
115529088Smarkm	send_do(TELOPT_SGA, 1);
115629088Smarkm    else
115729088Smarkm#endif
115829088Smarkm    send_wont(TELOPT_LINEMODE, 1);
115929088Smarkm    send_do(TELOPT_ECHO, 1);
116029088Smarkm    return 1;
116129088Smarkm}
116229088Smarkm
116329088Smarkm    static int
116429088Smarkmdolmmode(bit, on)
116529088Smarkm    int bit, on;
116629088Smarkm{
116729088Smarkm    unsigned char c;
116829088Smarkm    extern int linemode;
116929088Smarkm
117029088Smarkm    if (my_want_state_is_wont(TELOPT_LINEMODE)) {
117129088Smarkm	printf("?Need to have LINEMODE option enabled first.\n");
117229088Smarkm	printf("'mode ?' for help.\n");
117329088Smarkm	return 0;
117429088Smarkm    }
117529088Smarkm
117629088Smarkm    if (on)
117729088Smarkm	c = (linemode | bit);
117829088Smarkm    else
117929088Smarkm	c = (linemode & ~bit);
118029088Smarkm    lm_mode(&c, 1, 1);
118129088Smarkm    return 1;
118229088Smarkm}
118329088Smarkm
118429088Smarkm    int
118529181Smarkmsetmod(bit)
118629088Smarkm{
118729088Smarkm    return dolmmode(bit, 1);
118829088Smarkm}
118929088Smarkm
119029088Smarkm    int
119129088Smarkmclearmode(bit)
119229088Smarkm{
119329088Smarkm    return dolmmode(bit, 0);
119429088Smarkm}
119529088Smarkm
119629088Smarkmstruct modelist {
119729088Smarkm	char	*name;		/* command name */
119829088Smarkm	char	*help;		/* help string */
119929088Smarkm	int	(*handler)();	/* routine which executes command */
120029088Smarkm	int	needconnect;	/* Do we need to be connected to execute? */
120129088Smarkm	int	arg1;
120229088Smarkm};
120329088Smarkm
120429088Smarkmextern int modehelp();
120529088Smarkm
120629088Smarkmstatic struct modelist ModeList[] = {
120729088Smarkm    { "character", "Disable LINEMODE option",	docharmode, 1 },
120829088Smarkm#ifdef	KLUDGELINEMODE
120929088Smarkm    { "",	"(or disable obsolete line-by-line mode)", 0 },
121029088Smarkm#endif
121129088Smarkm    { "line",	"Enable LINEMODE option",	dolinemode, 1 },
121229088Smarkm#ifdef	KLUDGELINEMODE
121329088Smarkm    { "",	"(or enable obsolete line-by-line mode)", 0 },
121429088Smarkm#endif
121529088Smarkm    { "", "", 0 },
121629088Smarkm    { "",	"These require the LINEMODE option to be enabled", 0 },
121729181Smarkm    { "isig",	"Enable signal trapping",	setmod, 1, MODE_TRAPSIG },
121829181Smarkm    { "+isig",	0,				setmod, 1, MODE_TRAPSIG },
121929088Smarkm    { "-isig",	"Disable signal trapping",	clearmode, 1, MODE_TRAPSIG },
122029181Smarkm    { "edit",	"Enable character editing",	setmod, 1, MODE_EDIT },
122129181Smarkm    { "+edit",	0,				setmod, 1, MODE_EDIT },
122229088Smarkm    { "-edit",	"Disable character editing",	clearmode, 1, MODE_EDIT },
122329181Smarkm    { "softtabs", "Enable tab expansion",	setmod, 1, MODE_SOFT_TAB },
122429181Smarkm    { "+softtabs", 0,				setmod, 1, MODE_SOFT_TAB },
122529088Smarkm    { "-softtabs", "Disable character editing",	clearmode, 1, MODE_SOFT_TAB },
122629181Smarkm    { "litecho", "Enable literal character echo", setmod, 1, MODE_LIT_ECHO },
122729181Smarkm    { "+litecho", 0,				setmod, 1, MODE_LIT_ECHO },
122829088Smarkm    { "-litecho", "Disable literal character echo", clearmode, 1, MODE_LIT_ECHO },
122929088Smarkm    { "help",	0,				modehelp, 0 },
123029088Smarkm#ifdef	KLUDGELINEMODE
123129088Smarkm    { "kludgeline", 0,				dokludgemode, 1 },
123229088Smarkm#endif
123329088Smarkm    { "", "", 0 },
123429088Smarkm    { "?",	"Print help information",	modehelp, 0 },
123529088Smarkm    { 0 },
123629088Smarkm};
123729088Smarkm
123829088Smarkm
123929088Smarkm    int
124029088Smarkmmodehelp()
124129088Smarkm{
124229088Smarkm    struct modelist *mt;
124329088Smarkm
124429088Smarkm    printf("format is:  'mode Mode', where 'Mode' is one of:\n\n");
124529088Smarkm    for (mt = ModeList; mt->name; mt++) {
124629088Smarkm	if (mt->help) {
124729088Smarkm	    if (*mt->help)
124829088Smarkm		printf("%-15s %s\n", mt->name, mt->help);
124929088Smarkm	    else
125029088Smarkm		printf("\n");
125129088Smarkm	}
125229088Smarkm    }
125329088Smarkm    return 0;
125429088Smarkm}
125529088Smarkm
125629088Smarkm#define	GETMODECMD(name) (struct modelist *) \
125729088Smarkm		genget(name, (char **) ModeList, sizeof(struct modelist))
125829088Smarkm
125929088Smarkm    static int
126029088Smarkmmodecmd(argc, argv)
126129088Smarkm    int  argc;
126229088Smarkm    char *argv[];
126329088Smarkm{
126429088Smarkm    struct modelist *mt;
126529088Smarkm
126629088Smarkm    if (argc != 2) {
126729088Smarkm	printf("'mode' command requires an argument\n");
126829088Smarkm	printf("'mode ?' for help.\n");
126929088Smarkm    } else if ((mt = GETMODECMD(argv[1])) == 0) {
127029088Smarkm	fprintf(stderr, "Unknown mode '%s' ('mode ?' for help).\n", argv[1]);
127129088Smarkm    } else if (Ambiguous(mt)) {
127229088Smarkm	fprintf(stderr, "Ambiguous mode '%s' ('mode ?' for help).\n", argv[1]);
127329088Smarkm    } else if (mt->needconnect && !connected) {
127429088Smarkm	printf("?Need to be connected first.\n");
127529088Smarkm	printf("'mode ?' for help.\n");
127629088Smarkm    } else if (mt->handler) {
127729088Smarkm	return (*mt->handler)(mt->arg1);
127829088Smarkm    }
127929088Smarkm    return 0;
128029088Smarkm}
128129088Smarkm
128229088Smarkm/*
128329088Smarkm * The following data structures and routines implement the
128429088Smarkm * "display" command.
128529088Smarkm */
128629088Smarkm
128729088Smarkm    static int
128829088Smarkmdisplay(argc, argv)
128929088Smarkm    int  argc;
129029088Smarkm    char *argv[];
129129088Smarkm{
129229088Smarkm    struct togglelist *tl;
129329088Smarkm    struct setlist *sl;
129429088Smarkm
129529088Smarkm#define	dotog(tl)	if (tl->variable && tl->actionexplanation) { \
129629088Smarkm			    if (*tl->variable) { \
129729088Smarkm				printf("will"); \
129829088Smarkm			    } else { \
129929088Smarkm				printf("won't"); \
130029088Smarkm			    } \
130129088Smarkm			    printf(" %s.\n", tl->actionexplanation); \
130229088Smarkm			}
130329088Smarkm
130429088Smarkm#define	doset(sl)   if (sl->name && *sl->name != ' ') { \
130529088Smarkm			if (sl->handler == 0) \
130629088Smarkm			    printf("%-15s [%s]\n", sl->name, control(*sl->charp)); \
130729088Smarkm			else \
130829088Smarkm			    printf("%-15s \"%s\"\n", sl->name, (char *)sl->charp); \
130929088Smarkm		    }
131029088Smarkm
131129088Smarkm    if (argc == 1) {
131229088Smarkm	for (tl = Togglelist; tl->name; tl++) {
131329088Smarkm	    dotog(tl);
131429088Smarkm	}
131529088Smarkm	printf("\n");
131629088Smarkm	for (sl = Setlist; sl->name; sl++) {
131729088Smarkm	    doset(sl);
131829088Smarkm	}
131929088Smarkm    } else {
132029088Smarkm	int i;
132129088Smarkm
132229088Smarkm	for (i = 1; i < argc; i++) {
132329088Smarkm	    sl = getset(argv[i]);
132429088Smarkm	    tl = GETTOGGLE(argv[i]);
132529088Smarkm	    if (Ambiguous(sl) || Ambiguous(tl)) {
132629088Smarkm		printf("?Ambiguous argument '%s'.\n", argv[i]);
132729088Smarkm		return 0;
132829088Smarkm	    } else if (!sl && !tl) {
132929088Smarkm		printf("?Unknown argument '%s'.\n", argv[i]);
133029088Smarkm		return 0;
133129088Smarkm	    } else {
133229088Smarkm		if (tl) {
133329088Smarkm		    dotog(tl);
133429088Smarkm		}
133529088Smarkm		if (sl) {
133629088Smarkm		    doset(sl);
133729088Smarkm		}
133829088Smarkm	    }
133929088Smarkm	}
134029088Smarkm    }
134129088Smarkm/*@*/optionstatus();
134229088Smarkm#ifdef	ENCRYPTION
134329088Smarkm    EncryptStatus();
134429088Smarkm#endif	/* ENCRYPTION */
134529088Smarkm    return 1;
134629088Smarkm#undef	doset
134729088Smarkm#undef	dotog
134829088Smarkm}
134929088Smarkm
135029088Smarkm/*
135129088Smarkm * The following are the data structures, and many of the routines,
135229088Smarkm * relating to command processing.
135329088Smarkm */
135429088Smarkm
135529088Smarkm/*
135629088Smarkm * Set the escape character.
135729088Smarkm */
135829088Smarkm	static int
135929088Smarkmsetescape(argc, argv)
136029088Smarkm	int argc;
136129088Smarkm	char *argv[];
136229088Smarkm{
136329088Smarkm	register char *arg;
136429088Smarkm	char buf[50];
136529088Smarkm
136629088Smarkm	printf(
136729088Smarkm	    "Deprecated usage - please use 'set escape%s%s' in the future.\n",
136829088Smarkm				(argc > 2)? " ":"", (argc > 2)? argv[1]: "");
136929088Smarkm	if (argc > 2)
137029088Smarkm		arg = argv[1];
137129088Smarkm	else {
137229088Smarkm		printf("new escape character: ");
137329088Smarkm		(void) fgets(buf, sizeof(buf), stdin);
137429088Smarkm		arg = buf;
137529088Smarkm	}
137629088Smarkm	if (arg[0] != '\0')
137729088Smarkm		escape = arg[0];
137829088Smarkm	if (!In3270) {
137929088Smarkm		printf("Escape character is '%s'.\n", control(escape));
138029088Smarkm	}
138129088Smarkm	(void) fflush(stdout);
138229088Smarkm	return 1;
138329088Smarkm}
138429088Smarkm
138529088Smarkm    /*VARARGS*/
138629088Smarkm    static int
138729088Smarkmtogcrmod()
138829088Smarkm{
138929088Smarkm    crmod = !crmod;
139029088Smarkm    printf("Deprecated usage - please use 'toggle crmod' in the future.\n");
139129088Smarkm    printf("%s map carriage return on output.\n", crmod ? "Will" : "Won't");
139229088Smarkm    (void) fflush(stdout);
139329088Smarkm    return 1;
139429088Smarkm}
139529088Smarkm
139629088Smarkm    /*VARARGS*/
139729088Smarkm    int
139829088Smarkmsuspend()
139929088Smarkm{
140029088Smarkm#ifdef	SIGTSTP
140129088Smarkm    setcommandmode();
140229088Smarkm    {
140329088Smarkm	long oldrows, oldcols, newrows, newcols, err;
140429088Smarkm
140529088Smarkm	err = (TerminalWindowSize(&oldrows, &oldcols) == 0) ? 1 : 0;
140629088Smarkm	(void) kill(0, SIGTSTP);
140729088Smarkm	/*
140829088Smarkm	 * If we didn't get the window size before the SUSPEND, but we
140929088Smarkm	 * can get them now (?), then send the NAWS to make sure that
141029088Smarkm	 * we are set up for the right window size.
141129088Smarkm	 */
141229088Smarkm	if (TerminalWindowSize(&newrows, &newcols) && connected &&
141329088Smarkm	    (err || ((oldrows != newrows) || (oldcols != newcols)))) {
141429088Smarkm		sendnaws();
141529088Smarkm	}
141629088Smarkm    }
141729088Smarkm    /* reget parameters in case they were changed */
141829088Smarkm    TerminalSaveState();
141929088Smarkm    setconnmode(0);
142029088Smarkm#else
142129088Smarkm    printf("Suspend is not supported.  Try the '!' command instead\n");
142229088Smarkm#endif
142329088Smarkm    return 1;
142429088Smarkm}
142529088Smarkm
142629088Smarkm#if	!defined(TN3270)
142729088Smarkm    /*ARGSUSED*/
142829088Smarkm    int
142929088Smarkmshell(argc, argv)
143029088Smarkm    int argc;
143129088Smarkm    char *argv[];
143229088Smarkm{
143329088Smarkm    long oldrows, oldcols, newrows, newcols, err;
143429088Smarkm
143529088Smarkm    setcommandmode();
143629088Smarkm
143729088Smarkm    err = (TerminalWindowSize(&oldrows, &oldcols) == 0) ? 1 : 0;
143829088Smarkm    switch(vfork()) {
143929088Smarkm    case -1:
144029088Smarkm	perror("Fork failed\n");
144129088Smarkm	break;
144229088Smarkm
144329088Smarkm    case 0:
144429088Smarkm	{
144529088Smarkm	    /*
144629088Smarkm	     * Fire up the shell in the child.
144729088Smarkm	     */
144829088Smarkm	    register char *shellp, *shellname;
144929088Smarkm	    extern char *strrchr();
145029088Smarkm
145129088Smarkm	    shellp = getenv("SHELL");
145229088Smarkm	    if (shellp == NULL)
145329088Smarkm		shellp = "/bin/sh";
145429088Smarkm	    if ((shellname = strrchr(shellp, '/')) == 0)
145529088Smarkm		shellname = shellp;
145629088Smarkm	    else
145729088Smarkm		shellname++;
145829088Smarkm	    if (argc > 1)
145929088Smarkm		execl(shellp, shellname, "-c", &saveline[1], 0);
146029088Smarkm	    else
146129088Smarkm		execl(shellp, shellname, 0);
146229088Smarkm	    perror("Execl");
146329088Smarkm	    _exit(1);
146429088Smarkm	}
146529088Smarkm    default:
146629088Smarkm	    (void)wait((int *)0);	/* Wait for the shell to complete */
146729088Smarkm
146829088Smarkm	    if (TerminalWindowSize(&newrows, &newcols) && connected &&
146929088Smarkm		(err || ((oldrows != newrows) || (oldcols != newcols)))) {
147029088Smarkm		    sendnaws();
147129088Smarkm	    }
147229088Smarkm	    break;
147329088Smarkm    }
147429088Smarkm    return 1;
147529088Smarkm}
147629088Smarkm#else	/* !defined(TN3270) */
147729088Smarkmextern int shell();
147829088Smarkm#endif	/* !defined(TN3270) */
147929088Smarkm
148029088Smarkm    /*VARARGS*/
148129181Smarkm    static int
148229088Smarkmbye(argc, argv)
148329088Smarkm    int  argc;		/* Number of arguments */
148429088Smarkm    char *argv[];	/* arguments */
148529088Smarkm{
148629088Smarkm    extern int resettermname;
148729088Smarkm
148829088Smarkm    if (connected) {
148929088Smarkm	(void) shutdown(net, 2);
149029088Smarkm	printf("Connection closed.\n");
149129088Smarkm	(void) NetClose(net);
149229088Smarkm	connected = 0;
149329088Smarkm	resettermname = 1;
149429088Smarkm#if	defined(AUTHENTICATION) || defined(ENCRYPTION)
149529088Smarkm	auth_encrypt_connect(connected);
149629088Smarkm#endif	/* defined(AUTHENTICATION) || defined(ENCRYPTION) */
149729088Smarkm	/* reset options */
149829088Smarkm	tninit();
149929088Smarkm#if	defined(TN3270)
150029088Smarkm	SetIn3270();		/* Get out of 3270 mode */
150129088Smarkm#endif	/* defined(TN3270) */
150229088Smarkm    }
150329088Smarkm    if ((argc != 2) || (strcmp(argv[1], "fromquit") != 0)) {
150429088Smarkm	longjmp(toplevel, 1);
150529088Smarkm	/* NOTREACHED */
150629088Smarkm    }
150729088Smarkm    return 1;			/* Keep lint, etc., happy */
150829088Smarkm}
150929088Smarkm
151029088Smarkm/*VARARGS*/
151129181Smarkm	int
151229088Smarkmquit()
151329088Smarkm{
151429088Smarkm	(void) call(bye, "bye", "fromquit", 0);
151529088Smarkm	Exit(0);
151629088Smarkm	/*NOTREACHED*/
151729088Smarkm}
151829088Smarkm
151929088Smarkm/*VARARGS*/
152029088Smarkm	int
152129088Smarkmlogout()
152229088Smarkm{
152329088Smarkm	send_do(TELOPT_LOGOUT, 1);
152429088Smarkm	(void) netflush();
152529088Smarkm	return 1;
152629088Smarkm}
152729088Smarkm
152829088Smarkm
152929088Smarkm/*
153029088Smarkm * The SLC command.
153129088Smarkm */
153229088Smarkm
153329088Smarkmstruct slclist {
153429088Smarkm	char	*name;
153529088Smarkm	char	*help;
153629088Smarkm	void	(*handler)();
153729088Smarkm	int	arg;
153829088Smarkm};
153929088Smarkm
154029088Smarkmstatic void slc_help();
154129088Smarkm
154229088Smarkmstruct slclist SlcList[] = {
154329088Smarkm    { "export",	"Use local special character definitions",
154429088Smarkm						slc_mode_export,	0 },
154529088Smarkm    { "import",	"Use remote special character definitions",
154629088Smarkm						slc_mode_import,	1 },
154729088Smarkm    { "check",	"Verify remote special character definitions",
154829088Smarkm						slc_mode_import,	0 },
154929088Smarkm    { "help",	0,				slc_help,		0 },
155029088Smarkm    { "?",	"Print help information",	slc_help,		0 },
155129088Smarkm    { 0 },
155229088Smarkm};
155329088Smarkm
155429088Smarkm    static void
155529088Smarkmslc_help()
155629088Smarkm{
155729088Smarkm    struct slclist *c;
155829088Smarkm
155929088Smarkm    for (c = SlcList; c->name; c++) {
156029088Smarkm	if (c->help) {
156129088Smarkm	    if (*c->help)
156229088Smarkm		printf("%-15s %s\n", c->name, c->help);
156329088Smarkm	    else
156429088Smarkm		printf("\n");
156529088Smarkm	}
156629088Smarkm    }
156729088Smarkm}
156829088Smarkm
156929088Smarkm    static struct slclist *
157029088Smarkmgetslc(name)
157129088Smarkm    char *name;
157229088Smarkm{
157329088Smarkm    return (struct slclist *)
157429088Smarkm		genget(name, (char **) SlcList, sizeof(struct slclist));
157529088Smarkm}
157629088Smarkm
157729181Smarkm    static int
157829088Smarkmslccmd(argc, argv)
157929088Smarkm    int  argc;
158029088Smarkm    char *argv[];
158129088Smarkm{
158229088Smarkm    struct slclist *c;
158329088Smarkm
158429088Smarkm    if (argc != 2) {
158529088Smarkm	fprintf(stderr,
158629088Smarkm	    "Need an argument to 'slc' command.  'slc ?' for help.\n");
158729088Smarkm	return 0;
158829088Smarkm    }
158929088Smarkm    c = getslc(argv[1]);
159029088Smarkm    if (c == 0) {
159129088Smarkm	fprintf(stderr, "'%s': unknown argument ('slc ?' for help).\n",
159229088Smarkm    				argv[1]);
159329088Smarkm	return 0;
159429088Smarkm    }
159529088Smarkm    if (Ambiguous(c)) {
159629088Smarkm	fprintf(stderr, "'%s': ambiguous argument ('slc ?' for help).\n",
159729088Smarkm    				argv[1]);
159829088Smarkm	return 0;
159929088Smarkm    }
160029088Smarkm    (*c->handler)(c->arg);
160129088Smarkm    slcstate();
160229088Smarkm    return 1;
160329088Smarkm}
160429088Smarkm
160529088Smarkm/*
160629088Smarkm * The ENVIRON command.
160729088Smarkm */
160829088Smarkm
160929088Smarkmstruct envlist {
161029088Smarkm	char	*name;
161129088Smarkm	char	*help;
161229088Smarkm	void	(*handler)();
161329088Smarkm	int	narg;
161429088Smarkm};
161529088Smarkm
161629088Smarkmextern struct env_lst *
161729088Smarkm	env_define P((unsigned char *, unsigned char *));
161829088Smarkmextern void
161929088Smarkm	env_undefine P((unsigned char *)),
162029088Smarkm	env_export P((unsigned char *)),
162129088Smarkm	env_unexport P((unsigned char *)),
162229088Smarkm	env_send P((unsigned char *)),
162329088Smarkm#if defined(OLD_ENVIRON) && defined(ENV_HACK)
162429088Smarkm	env_varval P((unsigned char *)),
162529088Smarkm#endif
162629088Smarkm	env_list P((void));
162729088Smarkmstatic void
162829088Smarkm	env_help P((void));
162929088Smarkm
163029088Smarkmstruct envlist EnvList[] = {
163129088Smarkm    { "define",	"Define an environment variable",
163229088Smarkm						(void (*)())env_define,	2 },
163329088Smarkm    { "undefine", "Undefine an environment variable",
163429088Smarkm						env_undefine,	1 },
163529088Smarkm    { "export",	"Mark an environment variable for automatic export",
163629088Smarkm						env_export,	1 },
163729088Smarkm    { "unexport", "Don't mark an environment variable for automatic export",
163829088Smarkm						env_unexport,	1 },
163929088Smarkm    { "send",	"Send an environment variable", env_send,	1 },
164029088Smarkm    { "list",	"List the current environment variables",
164129088Smarkm						env_list,	0 },
164229088Smarkm#if defined(OLD_ENVIRON) && defined(ENV_HACK)
164329088Smarkm    { "varval", "Reverse VAR and VALUE (auto, right, wrong, status)",
164429088Smarkm						env_varval,    1 },
164529088Smarkm#endif
164629088Smarkm    { "help",	0,				env_help,		0 },
164729088Smarkm    { "?",	"Print help information",	env_help,		0 },
164829088Smarkm    { 0 },
164929088Smarkm};
165029088Smarkm
165129088Smarkm    static void
165229088Smarkmenv_help()
165329088Smarkm{
165429088Smarkm    struct envlist *c;
165529088Smarkm
165629088Smarkm    for (c = EnvList; c->name; c++) {
165729088Smarkm	if (c->help) {
165829088Smarkm	    if (*c->help)
165929088Smarkm		printf("%-15s %s\n", c->name, c->help);
166029088Smarkm	    else
166129088Smarkm		printf("\n");
166229088Smarkm	}
166329088Smarkm    }
166429088Smarkm}
166529088Smarkm
166629088Smarkm    static struct envlist *
166729088Smarkmgetenvcmd(name)
166829088Smarkm    char *name;
166929088Smarkm{
167029088Smarkm    return (struct envlist *)
167129088Smarkm		genget(name, (char **) EnvList, sizeof(struct envlist));
167229088Smarkm}
167329088Smarkm
167429181Smarkm	int
167529088Smarkmenv_cmd(argc, argv)
167629088Smarkm    int  argc;
167729088Smarkm    char *argv[];
167829088Smarkm{
167929088Smarkm    struct envlist *c;
168029088Smarkm
168129088Smarkm    if (argc < 2) {
168229088Smarkm	fprintf(stderr,
168329088Smarkm	    "Need an argument to 'environ' command.  'environ ?' for help.\n");
168429088Smarkm	return 0;
168529088Smarkm    }
168629088Smarkm    c = getenvcmd(argv[1]);
168729088Smarkm    if (c == 0) {
168829088Smarkm	fprintf(stderr, "'%s': unknown argument ('environ ?' for help).\n",
168929088Smarkm    				argv[1]);
169029088Smarkm	return 0;
169129088Smarkm    }
169229088Smarkm    if (Ambiguous(c)) {
169329088Smarkm	fprintf(stderr, "'%s': ambiguous argument ('environ ?' for help).\n",
169429088Smarkm    				argv[1]);
169529088Smarkm	return 0;
169629088Smarkm    }
169729088Smarkm    if (c->narg + 2 != argc) {
169829088Smarkm	fprintf(stderr,
169929088Smarkm	    "Need %s%d argument%s to 'environ %s' command.  'environ ?' for help.\n",
170029088Smarkm		c->narg < argc + 2 ? "only " : "",
170129088Smarkm		c->narg, c->narg == 1 ? "" : "s", c->name);
170229088Smarkm	return 0;
170329088Smarkm    }
170429088Smarkm    (*c->handler)(argv[2], argv[3]);
170529088Smarkm    return 1;
170629088Smarkm}
170729088Smarkm
170829088Smarkmstruct env_lst {
170929088Smarkm	struct env_lst *next;	/* pointer to next structure */
171029088Smarkm	struct env_lst *prev;	/* pointer to previous structure */
171129088Smarkm	unsigned char *var;	/* pointer to variable name */
171229088Smarkm	unsigned char *value;	/* pointer to variable value */
171329088Smarkm	int export;		/* 1 -> export with default list of variables */
171429088Smarkm	int welldefined;	/* A well defined variable */
171529088Smarkm};
171629088Smarkm
171729088Smarkmstruct env_lst envlisthead;
171829088Smarkm
171929088Smarkm	struct env_lst *
172029088Smarkmenv_find(var)
172129088Smarkm	unsigned char *var;
172229088Smarkm{
172329088Smarkm	register struct env_lst *ep;
172429088Smarkm
172529088Smarkm	for (ep = envlisthead.next; ep; ep = ep->next) {
172629088Smarkm		if (strcmp((char *)ep->var, (char *)var) == 0)
172729088Smarkm			return(ep);
172829088Smarkm	}
172929088Smarkm	return(NULL);
173029088Smarkm}
173129088Smarkm
173229088Smarkm	void
173329088Smarkmenv_init()
173429088Smarkm{
173529088Smarkm	extern char **environ;
173629088Smarkm	register char **epp, *cp;
173729088Smarkm	register struct env_lst *ep;
173829088Smarkm	extern char *strchr();
173929088Smarkm
174029088Smarkm	for (epp = environ; *epp; epp++) {
174129181Smarkm		if ((cp = strchr(*epp, '='))) {
174229088Smarkm			*cp = '\0';
174329088Smarkm			ep = env_define((unsigned char *)*epp,
174429088Smarkm					(unsigned char *)cp+1);
174529088Smarkm			ep->export = 0;
174629088Smarkm			*cp = '=';
174729088Smarkm		}
174829088Smarkm	}
174929088Smarkm	/*
175029088Smarkm	 * Special case for DISPLAY variable.  If it is ":0.0" or
175129088Smarkm	 * "unix:0.0", we have to get rid of "unix" and insert our
175229088Smarkm	 * hostname.
175329088Smarkm	 */
175429088Smarkm	if ((ep = env_find("DISPLAY"))
175529088Smarkm	    && ((*ep->value == ':')
175629088Smarkm		|| (strncmp((char *)ep->value, "unix:", 5) == 0))) {
175729088Smarkm		char hbuf[256+1];
175829088Smarkm		char *cp2 = strchr((char *)ep->value, ':');
175929088Smarkm
176029088Smarkm		gethostname(hbuf, 256);
176129088Smarkm		hbuf[256] = '\0';
176229088Smarkm		cp = (char *)malloc(strlen(hbuf) + strlen(cp2) + 1);
176329088Smarkm		sprintf((char *)cp, "%s%s", hbuf, cp2);
176429088Smarkm		free(ep->value);
176529088Smarkm		ep->value = (unsigned char *)cp;
176629088Smarkm	}
176729088Smarkm	/*
176829088Smarkm	 * If USER is not defined, but LOGNAME is, then add
176929088Smarkm	 * USER with the value from LOGNAME.  By default, we
177029088Smarkm	 * don't export the USER variable.
177129088Smarkm	 */
177229088Smarkm	if ((env_find("USER") == NULL) && (ep = env_find("LOGNAME"))) {
177329088Smarkm		env_define((unsigned char *)"USER", ep->value);
177429088Smarkm		env_unexport((unsigned char *)"USER");
177529088Smarkm	}
177629088Smarkm	env_export((unsigned char *)"DISPLAY");
177729088Smarkm	env_export((unsigned char *)"PRINTER");
177829088Smarkm}
177929088Smarkm
178029088Smarkm	struct env_lst *
178129088Smarkmenv_define(var, value)
178229088Smarkm	unsigned char *var, *value;
178329088Smarkm{
178429088Smarkm	register struct env_lst *ep;
178529088Smarkm
178629181Smarkm	if ((ep = env_find(var))) {
178729088Smarkm		if (ep->var)
178829088Smarkm			free(ep->var);
178929088Smarkm		if (ep->value)
179029088Smarkm			free(ep->value);
179129088Smarkm	} else {
179229088Smarkm		ep = (struct env_lst *)malloc(sizeof(struct env_lst));
179329088Smarkm		ep->next = envlisthead.next;
179429088Smarkm		envlisthead.next = ep;
179529088Smarkm		ep->prev = &envlisthead;
179629088Smarkm		if (ep->next)
179729088Smarkm			ep->next->prev = ep;
179829088Smarkm	}
179929088Smarkm	ep->welldefined = opt_welldefined(var);
180029088Smarkm	ep->export = 1;
180129088Smarkm	ep->var = (unsigned char *)strdup((char *)var);
180229088Smarkm	ep->value = (unsigned char *)strdup((char *)value);
180329088Smarkm	return(ep);
180429088Smarkm}
180529088Smarkm
180629088Smarkm	void
180729088Smarkmenv_undefine(var)
180829088Smarkm	unsigned char *var;
180929088Smarkm{
181029088Smarkm	register struct env_lst *ep;
181129088Smarkm
181229181Smarkm	if ((ep = env_find(var))) {
181329088Smarkm		ep->prev->next = ep->next;
181429088Smarkm		if (ep->next)
181529088Smarkm			ep->next->prev = ep->prev;
181629088Smarkm		if (ep->var)
181729088Smarkm			free(ep->var);
181829088Smarkm		if (ep->value)
181929088Smarkm			free(ep->value);
182029088Smarkm		free(ep);
182129088Smarkm	}
182229088Smarkm}
182329088Smarkm
182429088Smarkm	void
182529088Smarkmenv_export(var)
182629088Smarkm	unsigned char *var;
182729088Smarkm{
182829088Smarkm	register struct env_lst *ep;
182929088Smarkm
183029181Smarkm	if ((ep = env_find(var)))
183129088Smarkm		ep->export = 1;
183229088Smarkm}
183329088Smarkm
183429088Smarkm	void
183529088Smarkmenv_unexport(var)
183629088Smarkm	unsigned char *var;
183729088Smarkm{
183829088Smarkm	register struct env_lst *ep;
183929088Smarkm
184029181Smarkm	if ((ep = env_find(var)))
184129088Smarkm		ep->export = 0;
184229088Smarkm}
184329088Smarkm
184429088Smarkm	void
184529088Smarkmenv_send(var)
184629088Smarkm	unsigned char *var;
184729088Smarkm{
184829088Smarkm	register struct env_lst *ep;
184929088Smarkm
185029088Smarkm	if (my_state_is_wont(TELOPT_NEW_ENVIRON)
185129088Smarkm#ifdef	OLD_ENVIRON
185229088Smarkm	    && my_state_is_wont(TELOPT_OLD_ENVIRON)
185329088Smarkm#endif
185429088Smarkm		) {
185529088Smarkm		fprintf(stderr,
185629088Smarkm		    "Cannot send '%s': Telnet ENVIRON option not enabled\n",
185729088Smarkm									var);
185829088Smarkm		return;
185929088Smarkm	}
186029088Smarkm	ep = env_find(var);
186129088Smarkm	if (ep == 0) {
186229088Smarkm		fprintf(stderr, "Cannot send '%s': variable not defined\n",
186329088Smarkm									var);
186429088Smarkm		return;
186529088Smarkm	}
186629088Smarkm	env_opt_start_info();
186729088Smarkm	env_opt_add(ep->var);
186829088Smarkm	env_opt_end(0);
186929088Smarkm}
187029088Smarkm
187129088Smarkm	void
187229088Smarkmenv_list()
187329088Smarkm{
187429088Smarkm	register struct env_lst *ep;
187529088Smarkm
187629088Smarkm	for (ep = envlisthead.next; ep; ep = ep->next) {
187729088Smarkm		printf("%c %-20s %s\n", ep->export ? '*' : ' ',
187829088Smarkm					ep->var, ep->value);
187929088Smarkm	}
188029088Smarkm}
188129088Smarkm
188229088Smarkm	unsigned char *
188329088Smarkmenv_default(init, welldefined)
188429088Smarkm	int init;
188529088Smarkm{
188629088Smarkm	static struct env_lst *nep = NULL;
188729088Smarkm
188829088Smarkm	if (init) {
188929088Smarkm		nep = &envlisthead;
189029181Smarkm		return(NULL);
189129088Smarkm	}
189229088Smarkm	if (nep) {
189329181Smarkm		while ((nep = nep->next)) {
189429088Smarkm			if (nep->export && (nep->welldefined == welldefined))
189529088Smarkm				return(nep->var);
189629088Smarkm		}
189729088Smarkm	}
189829088Smarkm	return(NULL);
189929088Smarkm}
190029088Smarkm
190129088Smarkm	unsigned char *
190229088Smarkmenv_getvalue(var)
190329088Smarkm	unsigned char *var;
190429088Smarkm{
190529088Smarkm	register struct env_lst *ep;
190629088Smarkm
190729181Smarkm	if ((ep = env_find(var)))
190829088Smarkm		return(ep->value);
190929088Smarkm	return(NULL);
191029088Smarkm}
191129088Smarkm
191229088Smarkm#if defined(OLD_ENVIRON) && defined(ENV_HACK)
191329088Smarkm	void
191429088Smarkmenv_varval(what)
191529088Smarkm	unsigned char *what;
191629088Smarkm{
191729088Smarkm	extern int old_env_var, old_env_value, env_auto;
191829088Smarkm	int len = strlen((char *)what);
191929088Smarkm
192029088Smarkm	if (len == 0)
192129088Smarkm		goto unknown;
192229088Smarkm
192329088Smarkm	if (strncasecmp((char *)what, "status", len) == 0) {
192429088Smarkm		if (env_auto)
192529088Smarkm			printf("%s%s", "VAR and VALUE are/will be ",
192629088Smarkm					"determined automatically\n");
192729088Smarkm		if (old_env_var == OLD_ENV_VAR)
192829088Smarkm			printf("VAR and VALUE set to correct definitions\n");
192929088Smarkm		else
193029088Smarkm			printf("VAR and VALUE definitions are reversed\n");
193129088Smarkm	} else if (strncasecmp((char *)what, "auto", len) == 0) {
193229088Smarkm		env_auto = 1;
193329088Smarkm		old_env_var = OLD_ENV_VALUE;
193429088Smarkm		old_env_value = OLD_ENV_VAR;
193529088Smarkm	} else if (strncasecmp((char *)what, "right", len) == 0) {
193629088Smarkm		env_auto = 0;
193729088Smarkm		old_env_var = OLD_ENV_VAR;
193829088Smarkm		old_env_value = OLD_ENV_VALUE;
193929088Smarkm	} else if (strncasecmp((char *)what, "wrong", len) == 0) {
194029088Smarkm		env_auto = 0;
194129088Smarkm		old_env_var = OLD_ENV_VALUE;
194229088Smarkm		old_env_value = OLD_ENV_VAR;
194329088Smarkm	} else {
194429088Smarkmunknown:
194529088Smarkm		printf("Unknown \"varval\" command. (\"auto\", \"right\", \"wrong\", \"status\")\n");
194629088Smarkm	}
194729088Smarkm}
194829088Smarkm#endif
194929088Smarkm
195029088Smarkm#if	defined(AUTHENTICATION)
195129088Smarkm/*
195229088Smarkm * The AUTHENTICATE command.
195329088Smarkm */
195429088Smarkm
195529088Smarkmstruct authlist {
195629088Smarkm	char	*name;
195729088Smarkm	char	*help;
195829088Smarkm	int	(*handler)();
195929088Smarkm	int	narg;
196029088Smarkm};
196129088Smarkm
196229088Smarkmextern int
196329088Smarkm	auth_enable P((char *)),
196429088Smarkm	auth_disable P((char *)),
196529088Smarkm	auth_status P((void));
196629088Smarkmstatic int
196729088Smarkm	auth_help P((void));
196829088Smarkm
196929088Smarkmstruct authlist AuthList[] = {
197029088Smarkm    { "status",	"Display current status of authentication information",
197129088Smarkm						auth_status,	0 },
197229088Smarkm    { "disable", "Disable an authentication type ('auth disable ?' for more)",
197329088Smarkm						auth_disable,	1 },
197429088Smarkm    { "enable", "Enable an authentication type ('auth enable ?' for more)",
197529088Smarkm						auth_enable,	1 },
197629088Smarkm    { "help",	0,				auth_help,		0 },
197729088Smarkm    { "?",	"Print help information",	auth_help,		0 },
197829088Smarkm    { 0 },
197929088Smarkm};
198029088Smarkm
198129088Smarkm    static int
198229088Smarkmauth_help()
198329088Smarkm{
198429088Smarkm    struct authlist *c;
198529088Smarkm
198629088Smarkm    for (c = AuthList; c->name; c++) {
198729088Smarkm	if (c->help) {
198829088Smarkm	    if (*c->help)
198929088Smarkm		printf("%-15s %s\n", c->name, c->help);
199029088Smarkm	    else
199129088Smarkm		printf("\n");
199229088Smarkm	}
199329088Smarkm    }
199429088Smarkm    return 0;
199529088Smarkm}
199629088Smarkm
199729181Smarkm	int
199829088Smarkmauth_cmd(argc, argv)
199929088Smarkm    int  argc;
200029088Smarkm    char *argv[];
200129088Smarkm{
200229088Smarkm    struct authlist *c;
200329088Smarkm
200429088Smarkm    if (argc < 2) {
200529088Smarkm	fprintf(stderr,
200629088Smarkm	    "Need an argument to 'auth' command.  'auth ?' for help.\n");
200729088Smarkm	return 0;
200829088Smarkm    }
200929088Smarkm
201029088Smarkm    c = (struct authlist *)
201129088Smarkm		genget(argv[1], (char **) AuthList, sizeof(struct authlist));
201229088Smarkm    if (c == 0) {
201329088Smarkm	fprintf(stderr, "'%s': unknown argument ('auth ?' for help).\n",
201429088Smarkm    				argv[1]);
201529088Smarkm	return 0;
201629088Smarkm    }
201729088Smarkm    if (Ambiguous(c)) {
201829088Smarkm	fprintf(stderr, "'%s': ambiguous argument ('auth ?' for help).\n",
201929088Smarkm    				argv[1]);
202029088Smarkm	return 0;
202129088Smarkm    }
202229088Smarkm    if (c->narg + 2 != argc) {
202329088Smarkm	fprintf(stderr,
202429088Smarkm	    "Need %s%d argument%s to 'auth %s' command.  'auth ?' for help.\n",
202529088Smarkm		c->narg < argc + 2 ? "only " : "",
202629088Smarkm		c->narg, c->narg == 1 ? "" : "s", c->name);
202729088Smarkm	return 0;
202829088Smarkm    }
202929088Smarkm    return((*c->handler)(argv[2], argv[3]));
203029088Smarkm}
203129088Smarkm#endif
203229088Smarkm
203329088Smarkm#ifdef	ENCRYPTION
203429088Smarkm/*
203529088Smarkm * The ENCRYPT command.
203629088Smarkm */
203729088Smarkm
203829088Smarkmstruct encryptlist {
203929088Smarkm	char	*name;
204029088Smarkm	char	*help;
204129088Smarkm	int	(*handler)();
204229088Smarkm	int	needconnect;
204329088Smarkm	int	minarg;
204429088Smarkm	int	maxarg;
204529088Smarkm};
204629088Smarkm
204729088Smarkmextern int
204829088Smarkm	EncryptEnable P((char *, char *)),
204929088Smarkm	EncryptDisable P((char *, char *)),
205029088Smarkm	EncryptType P((char *, char *)),
205129088Smarkm	EncryptStart P((char *)),
205229088Smarkm	EncryptStartInput P((void)),
205329088Smarkm	EncryptStartOutput P((void)),
205429088Smarkm	EncryptStop P((char *)),
205529088Smarkm	EncryptStopInput P((void)),
205629088Smarkm	EncryptStopOutput P((void)),
205729088Smarkm	EncryptStatus P((void));
205829088Smarkmstatic int
205929088Smarkm	EncryptHelp P((void));
206029088Smarkm
206129088Smarkmstruct encryptlist EncryptList[] = {
206229088Smarkm    { "enable", "Enable encryption. ('encrypt enable ?' for more)",
206329088Smarkm						EncryptEnable, 1, 1, 2 },
206429088Smarkm    { "disable", "Disable encryption. ('encrypt enable ?' for more)",
206529088Smarkm						EncryptDisable, 0, 1, 2 },
206629088Smarkm    { "type", "Set encryption type. ('encrypt type ?' for more)",
206729088Smarkm						EncryptType, 0, 1, 1 },
206829088Smarkm    { "start", "Start encryption. ('encrypt start ?' for more)",
206929088Smarkm						EncryptStart, 1, 0, 1 },
207029088Smarkm    { "stop", "Stop encryption. ('encrypt stop ?' for more)",
207129088Smarkm						EncryptStop, 1, 0, 1 },
207229088Smarkm    { "input", "Start encrypting the input stream",
207329088Smarkm						EncryptStartInput, 1, 0, 0 },
207429088Smarkm    { "-input", "Stop encrypting the input stream",
207529088Smarkm						EncryptStopInput, 1, 0, 0 },
207629088Smarkm    { "output", "Start encrypting the output stream",
207729088Smarkm						EncryptStartOutput, 1, 0, 0 },
207829088Smarkm    { "-output", "Stop encrypting the output stream",
207929088Smarkm						EncryptStopOutput, 1, 0, 0 },
208029088Smarkm
208129088Smarkm    { "status",	"Display current status of authentication information",
208229088Smarkm						EncryptStatus,	0, 0, 0 },
208329088Smarkm    { "help",	0,				EncryptHelp,	0, 0, 0 },
208429088Smarkm    { "?",	"Print help information",	EncryptHelp,	0, 0, 0 },
208529088Smarkm    { 0 },
208629088Smarkm};
208729088Smarkm
208829088Smarkm    static int
208929088SmarkmEncryptHelp()
209029088Smarkm{
209129088Smarkm    struct encryptlist *c;
209229088Smarkm
209329088Smarkm    for (c = EncryptList; c->name; c++) {
209429088Smarkm	if (c->help) {
209529088Smarkm	    if (*c->help)
209629088Smarkm		printf("%-15s %s\n", c->name, c->help);
209729088Smarkm	    else
209829088Smarkm		printf("\n");
209929088Smarkm	}
210029088Smarkm    }
210129088Smarkm    return 0;
210229088Smarkm}
210329088Smarkm
210429181Smarkm	int
210529088Smarkmencrypt_cmd(argc, argv)
210629088Smarkm    int  argc;
210729088Smarkm    char *argv[];
210829088Smarkm{
210929088Smarkm    struct encryptlist *c;
211029088Smarkm
211129088Smarkm    if (argc < 2) {
211229088Smarkm	fprintf(stderr,
211329088Smarkm	    "Need an argument to 'encrypt' command.  'encrypt ?' for help.\n");
211429088Smarkm	return 0;
211529088Smarkm    }
211629088Smarkm
211729088Smarkm    c = (struct encryptlist *)
211829088Smarkm		genget(argv[1], (char **) EncryptList, sizeof(struct encryptlist));
211929088Smarkm    if (c == 0) {
212029088Smarkm	fprintf(stderr, "'%s': unknown argument ('encrypt ?' for help).\n",
212129088Smarkm    				argv[1]);
212229088Smarkm	return 0;
212329088Smarkm    }
212429088Smarkm    if (Ambiguous(c)) {
212529088Smarkm	fprintf(stderr, "'%s': ambiguous argument ('encrypt ?' for help).\n",
212629088Smarkm    				argv[1]);
212729088Smarkm	return 0;
212829088Smarkm    }
212929088Smarkm    argc -= 2;
213029088Smarkm    if (argc < c->minarg || argc > c->maxarg) {
213129088Smarkm	if (c->minarg == c->maxarg) {
213229088Smarkm	    fprintf(stderr, "Need %s%d argument%s ",
213329088Smarkm		c->minarg < argc ? "only " : "", c->minarg,
213429088Smarkm		c->minarg == 1 ? "" : "s");
213529088Smarkm	} else {
213629088Smarkm	    fprintf(stderr, "Need %s%d-%d arguments ",
213729088Smarkm		c->maxarg < argc ? "only " : "", c->minarg, c->maxarg);
213829088Smarkm	}
213929088Smarkm	fprintf(stderr, "to 'encrypt %s' command.  'encrypt ?' for help.\n",
214029088Smarkm		c->name);
214129088Smarkm	return 0;
214229088Smarkm    }
214329088Smarkm    if (c->needconnect && !connected) {
214429088Smarkm	if (!(argc && (isprefix(argv[2], "help") || isprefix(argv[2], "?")))) {
214529088Smarkm	    printf("?Need to be connected first.\n");
214629088Smarkm	    return 0;
214729088Smarkm	}
214829088Smarkm    }
214929088Smarkm    return ((*c->handler)(argc > 0 ? argv[2] : 0,
215029088Smarkm			argc > 1 ? argv[3] : 0,
215129088Smarkm			argc > 2 ? argv[4] : 0));
215229088Smarkm}
215329088Smarkm#endif	/* ENCRYPTION */
215429088Smarkm
215529088Smarkm#if	defined(unix) && defined(TN3270)
215629088Smarkm    static void
215729088Smarkmfilestuff(fd)
215829088Smarkm    int fd;
215929088Smarkm{
216029088Smarkm    int res;
216129088Smarkm
216229088Smarkm#ifdef	F_GETOWN
216329088Smarkm    setconnmode(0);
216429088Smarkm    res = fcntl(fd, F_GETOWN, 0);
216529088Smarkm    setcommandmode();
216629088Smarkm
216729088Smarkm    if (res == -1) {
216829088Smarkm	perror("fcntl");
216929088Smarkm	return;
217029088Smarkm    }
217129088Smarkm    printf("\tOwner is %d.\n", res);
217229088Smarkm#endif
217329088Smarkm
217429088Smarkm    setconnmode(0);
217529088Smarkm    res = fcntl(fd, F_GETFL, 0);
217629088Smarkm    setcommandmode();
217729088Smarkm
217829088Smarkm    if (res == -1) {
217929088Smarkm	perror("fcntl");
218029088Smarkm	return;
218129088Smarkm    }
218229088Smarkm#ifdef notdef
218329088Smarkm    printf("\tFlags are 0x%x: %s\n", res, decodeflags(res));
218429088Smarkm#endif
218529088Smarkm}
218629088Smarkm#endif /* defined(unix) && defined(TN3270) */
218729088Smarkm
218829088Smarkm/*
218929088Smarkm * Print status about the connection.
219029088Smarkm */
219129088Smarkm    /*ARGSUSED*/
219229181Smarkm    static int
219329088Smarkmstatus(argc, argv)
219429088Smarkm    int	 argc;
219529088Smarkm    char *argv[];
219629088Smarkm{
219729088Smarkm    if (connected) {
219829088Smarkm	printf("Connected to %s.\n", hostname);
219929088Smarkm	if ((argc < 2) || strcmp(argv[1], "notmuch")) {
220029088Smarkm	    int mode = getconnmode();
220129088Smarkm
220229088Smarkm	    if (my_want_state_is_will(TELOPT_LINEMODE)) {
220329088Smarkm		printf("Operating with LINEMODE option\n");
220429088Smarkm		printf("%s line editing\n", (mode&MODE_EDIT) ? "Local" : "No");
220529088Smarkm		printf("%s catching of signals\n",
220629088Smarkm					(mode&MODE_TRAPSIG) ? "Local" : "No");
220729088Smarkm		slcstate();
220829088Smarkm#ifdef	KLUDGELINEMODE
220929088Smarkm	    } else if (kludgelinemode && my_want_state_is_dont(TELOPT_SGA)) {
221029088Smarkm		printf("Operating in obsolete linemode\n");
221129088Smarkm#endif
221229088Smarkm	    } else {
221329088Smarkm		printf("Operating in single character mode\n");
221429088Smarkm		if (localchars)
221529088Smarkm		    printf("Catching signals locally\n");
221629088Smarkm	    }
221729088Smarkm	    printf("%s character echo\n", (mode&MODE_ECHO) ? "Local" : "Remote");
221829088Smarkm	    if (my_want_state_is_will(TELOPT_LFLOW))
221929088Smarkm		printf("%s flow control\n", (mode&MODE_FLOW) ? "Local" : "No");
222029088Smarkm#ifdef	ENCRYPTION
222129088Smarkm	    encrypt_display();
222229088Smarkm#endif	/* ENCRYPTION */
222329088Smarkm	}
222429088Smarkm    } else {
222529088Smarkm	printf("No connection.\n");
222629088Smarkm    }
222729088Smarkm#   if !defined(TN3270)
222829088Smarkm    printf("Escape character is '%s'.\n", control(escape));
222929088Smarkm    (void) fflush(stdout);
223029088Smarkm#   else /* !defined(TN3270) */
223129088Smarkm    if ((!In3270) && ((argc < 2) || strcmp(argv[1], "notmuch"))) {
223229088Smarkm	printf("Escape character is '%s'.\n", control(escape));
223329088Smarkm    }
223429088Smarkm#   if defined(unix)
223529088Smarkm    if ((argc >= 2) && !strcmp(argv[1], "everything")) {
223629088Smarkm	printf("SIGIO received %d time%s.\n",
223729088Smarkm				sigiocount, (sigiocount == 1)? "":"s");
223829088Smarkm	if (In3270) {
223929088Smarkm	    printf("Process ID %d, process group %d.\n",
224029088Smarkm					    getpid(), getpgrp(getpid()));
224129088Smarkm	    printf("Terminal input:\n");
224229088Smarkm	    filestuff(tin);
224329088Smarkm	    printf("Terminal output:\n");
224429088Smarkm	    filestuff(tout);
224529088Smarkm	    printf("Network socket:\n");
224629088Smarkm	    filestuff(net);
224729088Smarkm	}
224829088Smarkm    }
224929088Smarkm    if (In3270 && transcom) {
225029088Smarkm       printf("Transparent mode command is '%s'.\n", transcom);
225129088Smarkm    }
225229088Smarkm#   endif /* defined(unix) */
225329088Smarkm    (void) fflush(stdout);
225429088Smarkm    if (In3270) {
225529088Smarkm	return 0;
225629088Smarkm    }
225729088Smarkm#   endif /* defined(TN3270) */
225829088Smarkm    return 1;
225929088Smarkm}
226029088Smarkm
226129088Smarkm#ifdef	SIGINFO
226229088Smarkm/*
226329088Smarkm * Function that gets called when SIGINFO is received.
226429088Smarkm */
226529181Smarkm	void
226629088Smarkmayt_status()
226729088Smarkm{
226829088Smarkm    (void) call(status, "status", "notmuch", 0);
226929088Smarkm}
227029088Smarkm#endif
227129088Smarkm
227229088Smarkmunsigned long inet_addr();
227329088Smarkm
227429088Smarkm    int
227529088Smarkmtn(argc, argv)
227629088Smarkm    int argc;
227729088Smarkm    char *argv[];
227829088Smarkm{
227929088Smarkm    register struct hostent *host = 0;
228047973Sru    struct sockaddr_in sin, src_sin;
228129088Smarkm    struct servent *sp = 0;
228229088Smarkm    unsigned long temp;
228329088Smarkm    extern char *inet_ntoa();
228429088Smarkm#if	defined(IP_OPTIONS) && defined(IPPROTO_IP)
228529088Smarkm    char *srp = 0, *strrchr();
228629088Smarkm    unsigned long sourceroute(), srlen;
228729088Smarkm#endif
228829088Smarkm    char *cmd, *hostp = 0, *portp = 0, *user = 0;
228947973Sru    char *src_addr = NULL;
229029088Smarkm
229129088Smarkm    /* clear the socket address prior to use */
229229088Smarkm    memset((char *)&sin, 0, sizeof(sin));
229329088Smarkm
229429088Smarkm    if (connected) {
229529088Smarkm	printf("?Already connected to %s\n", hostname);
229629088Smarkm	setuid(getuid());
229729088Smarkm	return 0;
229829088Smarkm    }
229929088Smarkm    if (argc < 2) {
230029088Smarkm	(void) strcpy(line, "open ");
230129088Smarkm	printf("(to) ");
230229088Smarkm	(void) fgets(&line[strlen(line)], sizeof(line) - strlen(line), stdin);
230329088Smarkm	makeargv();
230429088Smarkm	argc = margc;
230529088Smarkm	argv = margv;
230629088Smarkm    }
230729088Smarkm    cmd = *argv;
230829088Smarkm    --argc; ++argv;
230929088Smarkm    while (argc) {
231029088Smarkm	if (strcmp(*argv, "help") == 0 || isprefix(*argv, "?"))
231129088Smarkm	    goto usage;
231229088Smarkm	if (strcmp(*argv, "-l") == 0) {
231329088Smarkm	    --argc; ++argv;
231429088Smarkm	    if (argc == 0)
231529088Smarkm		goto usage;
231629088Smarkm	    user = *argv++;
231729088Smarkm	    --argc;
231829088Smarkm	    continue;
231929088Smarkm	}
232029088Smarkm	if (strcmp(*argv, "-a") == 0) {
232129088Smarkm	    --argc; ++argv;
232229088Smarkm	    autologin = 1;
232329088Smarkm	    continue;
232429088Smarkm	}
232547973Sru	if (strcmp(*argv, "-s") == 0) {
232647973Sru	    --argc; ++argv;
232747973Sru	    if (argc == 0)
232847973Sru		goto usage;
232947973Sru	    src_addr = *argv++;
233047973Sru	    --argc;
233147973Sru	    continue;
233247973Sru	}
233329088Smarkm	if (hostp == 0) {
233429088Smarkm	    hostp = *argv++;
233529088Smarkm	    --argc;
233629088Smarkm	    continue;
233729088Smarkm	}
233829088Smarkm	if (portp == 0) {
233929088Smarkm	    portp = *argv++;
234029088Smarkm	    --argc;
234129088Smarkm	    continue;
234229088Smarkm	}
234329088Smarkm    usage:
234447973Sru	printf("usage: %s [-l user] [-a] [-s src_addr] host-name [port]\n", cmd);
234529088Smarkm	setuid(getuid());
234629088Smarkm	return 0;
234729088Smarkm    }
234829088Smarkm    if (hostp == 0)
234929088Smarkm	goto usage;
235029088Smarkm
235147973Sru    if (src_addr != NULL) {
235247973Sru	bzero((char *)&src_sin, sizeof(src_sin));
235347973Sru	src_sin.sin_family = AF_INET;
235447973Sru	if (!inet_aton(src_addr, &src_sin.sin_addr)) {
235547973Sru	    host = gethostbyname2(src_addr, AF_INET);
235647973Sru	    if (host == NULL) {
235747973Sru		herror(src_addr);
235847973Sru		return 0;
235947973Sru	    }
236047973Sru	    if (host->h_length != sizeof(src_sin.sin_addr)) {
236147973Sru		fprintf(stderr, "telnet: gethostbyname2: invalid address\n");
236247973Sru		return 0;
236347973Sru	    }
236447973Sru	    memcpy((void *)&src_sin.sin_addr, (void *)host->h_addr_list[0],
236547973Sru			sizeof(src_sin.sin_addr));
236647973Sru	}
236747973Sru    }
236847973Sru
236929088Smarkm#if	defined(IP_OPTIONS) && defined(IPPROTO_IP)
237029088Smarkm    if (hostp[0] == '@' || hostp[0] == '!') {
237129088Smarkm	if ((hostname = strrchr(hostp, ':')) == NULL)
237229088Smarkm	    hostname = strrchr(hostp, '@');
237329088Smarkm	hostname++;
237429088Smarkm	srp = 0;
237529088Smarkm	temp = sourceroute(hostp, &srp, &srlen);
237629088Smarkm	if (temp == 0) {
237729088Smarkm	    herror(srp);
237829088Smarkm	    setuid(getuid());
237929088Smarkm	    return 0;
238029088Smarkm	} else if (temp == -1) {
238129088Smarkm	    printf("Bad source route option: %s\n", hostp);
238229088Smarkm	    setuid(getuid());
238329088Smarkm	    return 0;
238429088Smarkm	} else {
238529088Smarkm	    sin.sin_addr.s_addr = temp;
238629088Smarkm	    sin.sin_family = AF_INET;
238729088Smarkm	}
238829088Smarkm    } else {
238929088Smarkm#endif
239029088Smarkm	temp = inet_addr(hostp);
239129181Smarkm 	if (temp != INADDR_NONE) {
239229088Smarkm	    sin.sin_addr.s_addr = temp;
239329088Smarkm	    sin.sin_family = AF_INET;
239447973Sru	    if (doaddrlookup)
239547973Sru		host = gethostbyaddr((char *)&temp, sizeof(temp), AF_INET);
239629181Smarkm 	    if (host)
239729181Smarkm 	        (void) strncpy(_hostname, host->h_name, sizeof(_hostname));
239829181Smarkm 	    else
239929181Smarkm 		(void) strncpy(_hostname, hostp, sizeof(_hostname));
240029181Smarkm 	    _hostname[sizeof(_hostname)-1] = '\0';
240129088Smarkm	    hostname = _hostname;
240229088Smarkm	} else {
240329088Smarkm	    host = gethostbyname(hostp);
240429088Smarkm	    if (host) {
240529088Smarkm		sin.sin_family = host->h_addrtype;
240629088Smarkm#if	defined(h_addr)		/* In 4.3, this is a #define */
240729088Smarkm		memmove((caddr_t)&sin.sin_addr,
240829088Smarkm				host->h_addr_list[0], host->h_length);
240929088Smarkm#else	/* defined(h_addr) */
241029088Smarkm		memmove((caddr_t)&sin.sin_addr, host->h_addr, host->h_length);
241129088Smarkm#endif	/* defined(h_addr) */
241229088Smarkm		strncpy(_hostname, host->h_name, sizeof(_hostname));
241329088Smarkm		_hostname[sizeof(_hostname)-1] = '\0';
241429088Smarkm		hostname = _hostname;
241529088Smarkm	    } else {
241629088Smarkm		herror(hostp);
241729088Smarkm		setuid(getuid());
241829088Smarkm		return 0;
241929088Smarkm	    }
242029088Smarkm	}
242129088Smarkm#if	defined(IP_OPTIONS) && defined(IPPROTO_IP)
242229088Smarkm    }
242329088Smarkm#endif
242429088Smarkm    if (portp) {
242529088Smarkm	if (*portp == '-') {
242629088Smarkm	    portp++;
242729088Smarkm	    telnetport = 1;
242829088Smarkm	} else
242929088Smarkm	    telnetport = 0;
243029088Smarkm	sin.sin_port = atoi(portp);
243129088Smarkm	if (sin.sin_port == 0) {
243229088Smarkm	    sp = getservbyname(portp, "tcp");
243329088Smarkm	    if (sp)
243429088Smarkm		sin.sin_port = sp->s_port;
243529088Smarkm	    else {
243629088Smarkm		printf("%s: bad port number\n", portp);
243729088Smarkm		setuid(getuid());
243829088Smarkm		return 0;
243929088Smarkm	    }
244029088Smarkm	} else {
244129088Smarkm#if	!defined(htons)
244229088Smarkm	    u_short htons P((unsigned short));
244329088Smarkm#endif	/* !defined(htons) */
244429088Smarkm	    sin.sin_port = htons(sin.sin_port);
244529088Smarkm	}
244629088Smarkm    } else {
244729088Smarkm	if (sp == 0) {
244829088Smarkm	    sp = getservbyname("telnet", "tcp");
244929088Smarkm	    if (sp == 0) {
245029088Smarkm		fprintf(stderr, "telnet: tcp/telnet: unknown service\n");
245129088Smarkm		setuid(getuid());
245229088Smarkm		return 0;
245329088Smarkm	    }
245429088Smarkm	    sin.sin_port = sp->s_port;
245529088Smarkm	}
245629088Smarkm	telnetport = 1;
245729088Smarkm    }
245829088Smarkm    printf("Trying %s...\n", inet_ntoa(sin.sin_addr));
245929088Smarkm    do {
246029088Smarkm	net = socket(AF_INET, SOCK_STREAM, 0);
246129088Smarkm	setuid(getuid());
246229088Smarkm	if (net < 0) {
246329088Smarkm	    perror("telnet: socket");
246429088Smarkm	    return 0;
246529088Smarkm	}
246629088Smarkm#if	defined(IP_OPTIONS) && defined(IPPROTO_IP)
246729088Smarkm	if (srp && setsockopt(net, IPPROTO_IP, IP_OPTIONS, (char *)srp, srlen) < 0)
246829088Smarkm		perror("setsockopt (IP_OPTIONS)");
246929088Smarkm#endif
247029088Smarkm#if	defined(IPPROTO_IP) && defined(IP_TOS)
247129088Smarkm	{
247229088Smarkm# if	defined(HAS_GETTOS)
247329088Smarkm	    struct tosent *tp;
247429088Smarkm	    if (tos < 0 && (tp = gettosbyname("telnet", "tcp")))
247529088Smarkm		tos = tp->t_tos;
247629088Smarkm# endif
247729088Smarkm	    if (tos < 0)
247829088Smarkm		tos = 020;	/* Low Delay bit */
247929088Smarkm	    if (tos
248029088Smarkm		&& (setsockopt(net, IPPROTO_IP, IP_TOS,
248129088Smarkm		    (char *)&tos, sizeof(int)) < 0)
248229088Smarkm		&& (errno != ENOPROTOOPT))
248329088Smarkm		    perror("telnet: setsockopt (IP_TOS) (ignored)");
248429088Smarkm	}
248529088Smarkm#endif	/* defined(IPPROTO_IP) && defined(IP_TOS) */
248629088Smarkm
248729088Smarkm	if (debug && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 1) < 0) {
248829088Smarkm		perror("setsockopt (SO_DEBUG)");
248929088Smarkm	}
249029088Smarkm
249147973Sru	if (src_addr != NULL) {
249247973Sru	    if (bind(net, (struct sockaddr *)&src_sin, sizeof(src_sin)) == -1) {
249347973Sru		perror("bind");
249447973Sru		return 0;
249547973Sru	    }
249647973Sru	}
249747973Sru
249829088Smarkm	if (connect(net, (struct sockaddr *)&sin, sizeof (sin)) < 0) {
249929088Smarkm#if	defined(h_addr)		/* In 4.3, this is a #define */
250029088Smarkm	    if (host && host->h_addr_list[1]) {
250129088Smarkm		int oerrno = errno;
250229088Smarkm
250329088Smarkm		fprintf(stderr, "telnet: connect to address %s: ",
250429088Smarkm						inet_ntoa(sin.sin_addr));
250529088Smarkm		errno = oerrno;
250629088Smarkm		perror((char *)0);
250729088Smarkm		host->h_addr_list++;
250829088Smarkm		memmove((caddr_t)&sin.sin_addr,
250929088Smarkm			host->h_addr_list[0], host->h_length);
251029088Smarkm		(void) NetClose(net);
251129088Smarkm		continue;
251229088Smarkm	    }
251329088Smarkm#endif	/* defined(h_addr) */
251429088Smarkm	    perror("telnet: Unable to connect to remote host");
251529088Smarkm	    return 0;
251629088Smarkm	}
251729088Smarkm	connected++;
251829088Smarkm#if	defined(AUTHENTICATION) || defined(ENCRYPTION)
251929088Smarkm	auth_encrypt_connect(connected);
252029088Smarkm#endif	/* defined(AUTHENTICATION) || defined(ENCRYPTION) */
252129088Smarkm    } while (connected == 0);
252229088Smarkm    cmdrc(hostp, hostname);
252329088Smarkm    if (autologin && user == NULL) {
252429088Smarkm	struct passwd *pw;
252529088Smarkm
252629088Smarkm	user = getenv("USER");
252729088Smarkm	if (user == NULL ||
252829181Smarkm	    ((pw = getpwnam(user)) && pw->pw_uid != getuid())) {
252929181Smarkm		if ((pw = getpwuid(getuid())))
253029088Smarkm			user = pw->pw_name;
253129088Smarkm		else
253229088Smarkm			user = NULL;
253329088Smarkm	}
253429088Smarkm    }
253529088Smarkm    if (user) {
253629088Smarkm	env_define((unsigned char *)"USER", (unsigned char *)user);
253729088Smarkm	env_export((unsigned char *)"USER");
253829088Smarkm    }
253929088Smarkm    (void) call(status, "status", "notmuch", 0);
254029088Smarkm    if (setjmp(peerdied) == 0)
254129088Smarkm	telnet(user);
254229088Smarkm    (void) NetClose(net);
254329088Smarkm    ExitString("Connection closed by foreign host.\n",1);
254429088Smarkm    /*NOTREACHED*/
254529088Smarkm}
254629088Smarkm
254729088Smarkm#define HELPINDENT (sizeof ("connect"))
254829088Smarkm
254929088Smarkmstatic char
255029088Smarkm	openhelp[] =	"connect to a site",
255129088Smarkm	closehelp[] =	"close current connection",
255229088Smarkm	logouthelp[] =	"forcibly logout remote user and close the connection",
255329088Smarkm	quithelp[] =	"exit telnet",
255429088Smarkm	statushelp[] =	"print status information",
255529088Smarkm	helphelp[] =	"print help information",
255629088Smarkm	sendhelp[] =	"transmit special characters ('send ?' for more)",
255729088Smarkm	sethelp[] = 	"set operating parameters ('set ?' for more)",
255829088Smarkm	unsethelp[] = 	"unset operating parameters ('unset ?' for more)",
255929088Smarkm	togglestring[] ="toggle operating parameters ('toggle ?' for more)",
256029088Smarkm	slchelp[] =	"change state of special charaters ('slc ?' for more)",
256129088Smarkm	displayhelp[] =	"display operating parameters",
256229088Smarkm#if	defined(TN3270) && defined(unix)
256329088Smarkm	transcomhelp[] = "specify Unix command for transparent mode pipe",
256429088Smarkm#endif	/* defined(TN3270) && defined(unix) */
256529088Smarkm#if	defined(AUTHENTICATION)
256629088Smarkm	authhelp[] =	"turn on (off) authentication ('auth ?' for more)",
256729088Smarkm#endif
256829088Smarkm#ifdef	ENCRYPTION
256929088Smarkm	encrypthelp[] =	"turn on (off) encryption ('encrypt ?' for more)",
257029088Smarkm#endif	/* ENCRYPTION */
257129088Smarkm#if	defined(unix)
257229088Smarkm	zhelp[] =	"suspend telnet",
257329088Smarkm#endif	/* defined(unix) */
257429181Smarkm#if	defined(SKEY)
257529181Smarkm	skeyhelp[] =    "compute response to s/key challenge",
257629181Smarkm#endif
257729088Smarkm	shellhelp[] =	"invoke a subshell",
257829088Smarkm	envhelp[] =	"change environment variables ('environ ?' for more)",
257929088Smarkm	modestring[] = "try to enter line or character mode ('mode ?' for more)";
258029088Smarkm
258129088Smarkmstatic Command cmdtab[] = {
258229088Smarkm	{ "close",	closehelp,	bye,		1 },
258329088Smarkm	{ "logout",	logouthelp,	logout,		1 },
258429088Smarkm	{ "display",	displayhelp,	display,	0 },
258529088Smarkm	{ "mode",	modestring,	modecmd,	0 },
258629088Smarkm	{ "open",	openhelp,	tn,		0 },
258729088Smarkm	{ "quit",	quithelp,	quit,		0 },
258829088Smarkm	{ "send",	sendhelp,	sendcmd,	0 },
258929088Smarkm	{ "set",	sethelp,	setcmd,		0 },
259029088Smarkm	{ "unset",	unsethelp,	unsetcmd,	0 },
259129088Smarkm	{ "status",	statushelp,	status,		0 },
259229088Smarkm	{ "toggle",	togglestring,	toggle,		0 },
259329088Smarkm	{ "slc",	slchelp,	slccmd,		0 },
259429088Smarkm#if	defined(TN3270) && defined(unix)
259529088Smarkm	{ "transcom",	transcomhelp,	settranscom,	0 },
259629088Smarkm#endif	/* defined(TN3270) && defined(unix) */
259729088Smarkm#if	defined(AUTHENTICATION)
259829088Smarkm	{ "auth",	authhelp,	auth_cmd,	0 },
259929088Smarkm#endif
260029088Smarkm#ifdef	ENCRYPTION
260129088Smarkm	{ "encrypt",	encrypthelp,	encrypt_cmd,	0 },
260229088Smarkm#endif	/* ENCRYPTION */
260329088Smarkm#if	defined(unix)
260429088Smarkm	{ "z",		zhelp,		suspend,	0 },
260529088Smarkm#endif	/* defined(unix) */
260629088Smarkm#if	defined(TN3270)
260729088Smarkm	{ "!",		shellhelp,	shell,		1 },
260829088Smarkm#else
260929088Smarkm	{ "!",		shellhelp,	shell,		0 },
261029088Smarkm#endif
261129088Smarkm	{ "environ",	envhelp,	env_cmd,	0 },
261229088Smarkm	{ "?",		helphelp,	help,		0 },
261329181Smarkm#if	defined(SKEY)
261429181Smarkm	{ "skey",       skeyhelp,       skey_calc,      0 },
261529181Smarkm#endif
261629181Smarkm	{ 0, 0, 0, 0 }
261729088Smarkm};
261829088Smarkm
261929088Smarkmstatic char	crmodhelp[] =	"deprecated command -- use 'toggle crmod' instead";
262029088Smarkmstatic char	escapehelp[] =	"deprecated command -- use 'set escape' instead";
262129088Smarkm
262229088Smarkmstatic Command cmdtab2[] = {
262329088Smarkm	{ "help",	0,		help,		0 },
262429088Smarkm	{ "escape",	escapehelp,	setescape,	0 },
262529088Smarkm	{ "crmod",	crmodhelp,	togcrmod,	0 },
262629181Smarkm	{ 0, 0, 0, 0 }
262729088Smarkm};
262829088Smarkm
262929088Smarkm
263029088Smarkm/*
263129088Smarkm * Call routine with argc, argv set from args (terminated by 0).
263229088Smarkm */
263329088Smarkm
263429088Smarkm    /*VARARGS1*/
263529181Smarkm    static int
263629088Smarkmcall(va_alist)
263729088Smarkm    va_dcl
263829088Smarkm{
263929088Smarkm    va_list ap;
264029088Smarkm    typedef int (*intrtn_t)();
264129088Smarkm    intrtn_t routine;
264229088Smarkm    char *args[100];
264329088Smarkm    int argno = 0;
264429088Smarkm
264529088Smarkm    va_start(ap);
264629088Smarkm    routine = (va_arg(ap, intrtn_t));
264729088Smarkm    while ((args[argno++] = va_arg(ap, char *)) != 0) {
264829088Smarkm	;
264929088Smarkm    }
265029088Smarkm    va_end(ap);
265129088Smarkm    return (*routine)(argno-1, args);
265229088Smarkm}
265329088Smarkm
265429088Smarkm
265529088Smarkm    static Command *
265629088Smarkmgetcmd(name)
265729088Smarkm    char *name;
265829088Smarkm{
265929088Smarkm    Command *cm;
266029088Smarkm
266129181Smarkm    if ((cm = (Command *) genget(name, (char **) cmdtab, sizeof(Command))))
266229088Smarkm	return cm;
266329088Smarkm    return (Command *) genget(name, (char **) cmdtab2, sizeof(Command));
266429088Smarkm}
266529088Smarkm
266629088Smarkm    void
266729088Smarkmcommand(top, tbuf, cnt)
266829088Smarkm    int top;
266929088Smarkm    char *tbuf;
267029088Smarkm    int cnt;
267129088Smarkm{
267229088Smarkm    register Command *c;
267329088Smarkm
267429088Smarkm    setcommandmode();
267529088Smarkm    if (!top) {
267629088Smarkm	putchar('\n');
267729088Smarkm#if	defined(unix)
267829088Smarkm    } else {
267929088Smarkm	(void) signal(SIGINT, SIG_DFL);
268029088Smarkm	(void) signal(SIGQUIT, SIG_DFL);
268129088Smarkm#endif	/* defined(unix) */
268229088Smarkm    }
268329088Smarkm    for (;;) {
268429088Smarkm	if (rlogin == _POSIX_VDISABLE)
268529088Smarkm		printf("%s> ", prompt);
268629088Smarkm	if (tbuf) {
268729088Smarkm	    register char *cp;
268829088Smarkm	    cp = line;
268929088Smarkm	    while (cnt > 0 && (*cp++ = *tbuf++) != '\n')
269029088Smarkm		cnt--;
269129088Smarkm	    tbuf = 0;
269229088Smarkm	    if (cp == line || *--cp != '\n' || cp == line)
269329088Smarkm		goto getline;
269429088Smarkm	    *cp = '\0';
269529088Smarkm	    if (rlogin == _POSIX_VDISABLE)
269629088Smarkm		printf("%s\n", line);
269729088Smarkm	} else {
269829088Smarkm	getline:
269929088Smarkm	    if (rlogin != _POSIX_VDISABLE)
270029088Smarkm		printf("%s> ", prompt);
270129088Smarkm	    if (fgets(line, sizeof(line), stdin) == NULL) {
270229088Smarkm		if (feof(stdin) || ferror(stdin)) {
270329088Smarkm		    (void) quit();
270429088Smarkm		    /*NOTREACHED*/
270529088Smarkm		}
270629088Smarkm		break;
270729088Smarkm	    }
270829088Smarkm	}
270929088Smarkm	if (line[0] == 0)
271029088Smarkm	    break;
271129088Smarkm	makeargv();
271229088Smarkm	if (margv[0] == 0) {
271329088Smarkm	    break;
271429088Smarkm	}
271529088Smarkm	c = getcmd(margv[0]);
271629088Smarkm	if (Ambiguous(c)) {
271729088Smarkm	    printf("?Ambiguous command\n");
271829088Smarkm	    continue;
271929088Smarkm	}
272029088Smarkm	if (c == 0) {
272129088Smarkm	    printf("?Invalid command\n");
272229088Smarkm	    continue;
272329088Smarkm	}
272429088Smarkm	if (c->needconnect && !connected) {
272529088Smarkm	    printf("?Need to be connected first.\n");
272629088Smarkm	    continue;
272729088Smarkm	}
272829088Smarkm	if ((*c->handler)(margc, margv)) {
272929088Smarkm	    break;
273029088Smarkm	}
273129088Smarkm    }
273229088Smarkm    if (!top) {
273329088Smarkm	if (!connected) {
273429088Smarkm	    longjmp(toplevel, 1);
273529088Smarkm	    /*NOTREACHED*/
273629088Smarkm	}
273729088Smarkm#if	defined(TN3270)
273829088Smarkm	if (shell_active == 0) {
273929088Smarkm	    setconnmode(0);
274029088Smarkm	}
274129088Smarkm#else	/* defined(TN3270) */
274229088Smarkm	setconnmode(0);
274329088Smarkm#endif	/* defined(TN3270) */
274429088Smarkm    }
274529088Smarkm}
274629088Smarkm
274729088Smarkm/*
274829088Smarkm * Help command.
274929088Smarkm */
275029181Smarkm	static int
275129088Smarkmhelp(argc, argv)
275229088Smarkm	int argc;
275329088Smarkm	char *argv[];
275429088Smarkm{
275529088Smarkm	register Command *c;
275629088Smarkm
275729088Smarkm	if (argc == 1) {
275829088Smarkm		printf("Commands may be abbreviated.  Commands are:\n\n");
275929088Smarkm		for (c = cmdtab; c->name; c++)
276029088Smarkm			if (c->help) {
276129088Smarkm				printf("%-*s\t%s\n", HELPINDENT, c->name,
276229088Smarkm								    c->help);
276329088Smarkm			}
276429088Smarkm	}
276529181Smarkm	else while (--argc > 0) {
276629088Smarkm		register char *arg;
276729088Smarkm		arg = *++argv;
276829088Smarkm		c = getcmd(arg);
276929088Smarkm		if (Ambiguous(c))
277029088Smarkm			printf("?Ambiguous help command %s\n", arg);
277129088Smarkm		else if (c == (Command *)0)
277229088Smarkm			printf("?Invalid help command %s\n", arg);
277329088Smarkm		else
277429088Smarkm			printf("%s\n", c->help);
277529088Smarkm	}
277629181Smarkm	return(0);
277729088Smarkm}
277829088Smarkm
277929088Smarkmstatic char *rcname = 0;
278029088Smarkmstatic char rcbuf[128];
278129088Smarkm
278229181Smarkm	void
278329088Smarkmcmdrc(m1, m2)
278429088Smarkm	char *m1, *m2;
278529088Smarkm{
278629088Smarkm    register Command *c;
278729088Smarkm    FILE *rcfile;
278829088Smarkm    int gotmachine = 0;
278929088Smarkm    int l1 = strlen(m1);
279029088Smarkm    int l2 = strlen(m2);
279129088Smarkm    char m1save[64];
279229088Smarkm
279329088Smarkm    if (skiprc)
279429088Smarkm	return;
279529088Smarkm
279629088Smarkm    strcpy(m1save, m1);
279729088Smarkm    m1 = m1save;
279829088Smarkm
279929088Smarkm    if (rcname == 0) {
280029088Smarkm	rcname = getenv("HOME");
280129181Smarkm	if (rcname && (strlen(rcname) + 10) < sizeof(rcbuf))
280229088Smarkm	    strcpy(rcbuf, rcname);
280329088Smarkm	else
280429088Smarkm	    rcbuf[0] = '\0';
280529088Smarkm	strcat(rcbuf, "/.telnetrc");
280629088Smarkm	rcname = rcbuf;
280729088Smarkm    }
280829088Smarkm
280929088Smarkm    if ((rcfile = fopen(rcname, "r")) == 0) {
281029088Smarkm	return;
281129088Smarkm    }
281229088Smarkm
281329088Smarkm    for (;;) {
281429088Smarkm	if (fgets(line, sizeof(line), rcfile) == NULL)
281529088Smarkm	    break;
281629088Smarkm	if (line[0] == 0)
281729088Smarkm	    break;
281829088Smarkm	if (line[0] == '#')
281929088Smarkm	    continue;
282029088Smarkm	if (gotmachine) {
282129088Smarkm	    if (!isspace(line[0]))
282229088Smarkm		gotmachine = 0;
282329088Smarkm	}
282429088Smarkm	if (gotmachine == 0) {
282529088Smarkm	    if (isspace(line[0]))
282629088Smarkm		continue;
282729088Smarkm	    if (strncasecmp(line, m1, l1) == 0)
282829088Smarkm		strncpy(line, &line[l1], sizeof(line) - l1);
282929088Smarkm	    else if (strncasecmp(line, m2, l2) == 0)
283029088Smarkm		strncpy(line, &line[l2], sizeof(line) - l2);
283129088Smarkm	    else if (strncasecmp(line, "DEFAULT", 7) == 0)
283229088Smarkm		strncpy(line, &line[7], sizeof(line) - 7);
283329088Smarkm	    else
283429088Smarkm		continue;
283529088Smarkm	    if (line[0] != ' ' && line[0] != '\t' && line[0] != '\n')
283629088Smarkm		continue;
283729088Smarkm	    gotmachine = 1;
283829088Smarkm	}
283929088Smarkm	makeargv();
284029088Smarkm	if (margv[0] == 0)
284129088Smarkm	    continue;
284229088Smarkm	c = getcmd(margv[0]);
284329088Smarkm	if (Ambiguous(c)) {
284429088Smarkm	    printf("?Ambiguous command: %s\n", margv[0]);
284529088Smarkm	    continue;
284629088Smarkm	}
284729088Smarkm	if (c == 0) {
284829088Smarkm	    printf("?Invalid command: %s\n", margv[0]);
284929088Smarkm	    continue;
285029088Smarkm	}
285129088Smarkm	/*
285229088Smarkm	 * This should never happen...
285329088Smarkm	 */
285429088Smarkm	if (c->needconnect && !connected) {
285529088Smarkm	    printf("?Need to be connected first for %s.\n", margv[0]);
285629088Smarkm	    continue;
285729088Smarkm	}
285829088Smarkm	(*c->handler)(margc, margv);
285929088Smarkm    }
286029088Smarkm    fclose(rcfile);
286129088Smarkm}
286229088Smarkm
286329088Smarkm#if	defined(IP_OPTIONS) && defined(IPPROTO_IP)
286429088Smarkm
286529088Smarkm/*
286629088Smarkm * Source route is handed in as
286729088Smarkm *	[!]@hop1@hop2...[@|:]dst
286829088Smarkm * If the leading ! is present, it is a
286929088Smarkm * strict source route, otherwise it is
287029088Smarkm * assmed to be a loose source route.
287129088Smarkm *
287229088Smarkm * We fill in the source route option as
287329088Smarkm *	hop1,hop2,hop3...dest
287429088Smarkm * and return a pointer to hop1, which will
287529088Smarkm * be the address to connect() to.
287629088Smarkm *
287729088Smarkm * Arguments:
287829088Smarkm *	arg:	pointer to route list to decipher
287929088Smarkm *
288029088Smarkm *	cpp: 	If *cpp is not equal to NULL, this is a
288129088Smarkm *		pointer to a pointer to a character array
288229088Smarkm *		that should be filled in with the option.
288329088Smarkm *
288429088Smarkm *	lenp:	pointer to an integer that contains the
288529088Smarkm *		length of *cpp if *cpp != NULL.
288629088Smarkm *
288729088Smarkm * Return values:
288829088Smarkm *
288929088Smarkm *	Returns the address of the host to connect to.  If the
289029088Smarkm *	return value is -1, there was a syntax error in the
289129088Smarkm *	option, either unknown characters, or too many hosts.
289229088Smarkm *	If the return value is 0, one of the hostnames in the
289329088Smarkm *	path is unknown, and *cpp is set to point to the bad
289429088Smarkm *	hostname.
289529088Smarkm *
289629088Smarkm *	*cpp:	If *cpp was equal to NULL, it will be filled
289729088Smarkm *		in with a pointer to our static area that has
289829088Smarkm *		the option filled in.  This will be 32bit aligned.
289929088Smarkm *
290029088Smarkm *	*lenp:	This will be filled in with how long the option
290129088Smarkm *		pointed to by *cpp is.
290229088Smarkm *
290329088Smarkm */
290429088Smarkm	unsigned long
290529088Smarkmsourceroute(arg, cpp, lenp)
290629088Smarkm	char	*arg;
290729088Smarkm	char	**cpp;
290829088Smarkm	int	*lenp;
290929088Smarkm{
291029088Smarkm	static char lsr[44];
291129088Smarkm#ifdef	sysV88
291229088Smarkm	static IOPTN ipopt;
291329088Smarkm#endif
291429088Smarkm	char *cp, *cp2, *lsrp, *lsrep;
291529088Smarkm	register int tmp;
291629088Smarkm	struct in_addr sin_addr;
291729088Smarkm	register struct hostent *host = 0;
291829088Smarkm	register char c;
291929088Smarkm
292029088Smarkm	/*
292129088Smarkm	 * Verify the arguments, and make sure we have
292229088Smarkm	 * at least 7 bytes for the option.
292329088Smarkm	 */
292429088Smarkm	if (cpp == NULL || lenp == NULL)
292529088Smarkm		return((unsigned long)-1);
292629088Smarkm	if (*cpp != NULL && *lenp < 7)
292729088Smarkm		return((unsigned long)-1);
292829088Smarkm	/*
292929088Smarkm	 * Decide whether we have a buffer passed to us,
293029088Smarkm	 * or if we need to use our own static buffer.
293129088Smarkm	 */
293229088Smarkm	if (*cpp) {
293329088Smarkm		lsrp = *cpp;
293429088Smarkm		lsrep = lsrp + *lenp;
293529088Smarkm	} else {
293629088Smarkm		*cpp = lsrp = lsr;
293729088Smarkm		lsrep = lsrp + 44;
293829088Smarkm	}
293929088Smarkm
294029088Smarkm	cp = arg;
294129088Smarkm
294229088Smarkm	/*
294329088Smarkm	 * Next, decide whether we have a loose source
294429088Smarkm	 * route or a strict source route, and fill in
294529088Smarkm	 * the begining of the option.
294629088Smarkm	 */
294729088Smarkm#ifndef	sysV88
294829088Smarkm	if (*cp == '!') {
294929088Smarkm		cp++;
295029088Smarkm		*lsrp++ = IPOPT_SSRR;
295129088Smarkm	} else
295229088Smarkm		*lsrp++ = IPOPT_LSRR;
295329088Smarkm#else
295429088Smarkm	if (*cp == '!') {
295529088Smarkm		cp++;
295629088Smarkm		ipopt.io_type = IPOPT_SSRR;
295729088Smarkm	} else
295829088Smarkm		ipopt.io_type = IPOPT_LSRR;
295929088Smarkm#endif
296029088Smarkm
296129088Smarkm	if (*cp != '@')
296229088Smarkm		return((unsigned long)-1);
296329088Smarkm
296429088Smarkm#ifndef	sysV88
296529088Smarkm	lsrp++;		/* skip over length, we'll fill it in later */
296629088Smarkm	*lsrp++ = 4;
296729088Smarkm#endif
296829088Smarkm
296929088Smarkm	cp++;
297029088Smarkm
297129088Smarkm	sin_addr.s_addr = 0;
297229088Smarkm
297329088Smarkm	for (c = 0;;) {
297429088Smarkm		if (c == ':')
297529088Smarkm			cp2 = 0;
297629181Smarkm		else for (cp2 = cp; (c = *cp2); cp2++) {
297729088Smarkm			if (c == ',') {
297829088Smarkm				*cp2++ = '\0';
297929088Smarkm				if (*cp2 == '@')
298029088Smarkm					cp2++;
298129088Smarkm			} else if (c == '@') {
298229088Smarkm				*cp2++ = '\0';
298329088Smarkm			} else if (c == ':') {
298429088Smarkm				*cp2++ = '\0';
298529088Smarkm			} else
298629088Smarkm				continue;
298729088Smarkm			break;
298829088Smarkm		}
298929088Smarkm		if (!c)
299029088Smarkm			cp2 = 0;
299129088Smarkm
299229088Smarkm		if ((tmp = inet_addr(cp)) != -1) {
299329088Smarkm			sin_addr.s_addr = tmp;
299429181Smarkm		} else if ((host = gethostbyname(cp))) {
299529088Smarkm#if	defined(h_addr)
299629088Smarkm			memmove((caddr_t)&sin_addr,
299729088Smarkm				host->h_addr_list[0], host->h_length);
299829088Smarkm#else
299929088Smarkm			memmove((caddr_t)&sin_addr, host->h_addr, host->h_length);
300029088Smarkm#endif
300129088Smarkm		} else {
300229088Smarkm			*cpp = cp;
300329088Smarkm			return(0);
300429088Smarkm		}
300529088Smarkm		memmove(lsrp, (char *)&sin_addr, 4);
300629088Smarkm		lsrp += 4;
300729088Smarkm		if (cp2)
300829088Smarkm			cp = cp2;
300929088Smarkm		else
301029088Smarkm			break;
301129088Smarkm		/*
301229088Smarkm		 * Check to make sure there is space for next address
301329088Smarkm		 */
301429088Smarkm		if (lsrp + 4 > lsrep)
301529088Smarkm			return((unsigned long)-1);
301629088Smarkm	}
301729088Smarkm#ifndef	sysV88
301829088Smarkm	if ((*(*cpp+IPOPT_OLEN) = lsrp - *cpp) <= 7) {
301929088Smarkm		*cpp = 0;
302029088Smarkm		*lenp = 0;
302129088Smarkm		return((unsigned long)-1);
302229088Smarkm	}
302329088Smarkm	*lsrp++ = IPOPT_NOP; /* 32 bit word align it */
302429088Smarkm	*lenp = lsrp - *cpp;
302529088Smarkm#else
302629088Smarkm	ipopt.io_len = lsrp - *cpp;
302729088Smarkm	if (ipopt.io_len <= 5) {		/* Is 3 better ? */
302829088Smarkm		*cpp = 0;
302929088Smarkm		*lenp = 0;
303029088Smarkm		return((unsigned long)-1);
303129088Smarkm	}
303229088Smarkm	*lenp = sizeof(ipopt);
303329088Smarkm	*cpp = (char *) &ipopt;
303429088Smarkm#endif
303529088Smarkm	return(sin_addr.s_addr);
303629088Smarkm}
303729088Smarkm#endif
3038