1/*
2 * Copyright (c) 1988, 1990, 1993
3 *	The Regents of the University of California.  All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 *    must display the following acknowledgement:
15 *	This product includes software developed by the University of
16 *	California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34static char *copyright[] = {
35    "@(#) Copyright (c) 1988, 1990, 1993\n"
36    "\tThe Regents of the University of California.  All rights reserved.\n",
37    (char*)copyright
38};
39
40#include "telnet_locl.h"
41RCSID("$Id$");
42
43#if KRB5
44#define FORWARD
45#endif
46
47/*
48 * Initialize variables.
49 */
50void
51tninit(void)
52{
53    init_terminal();
54
55    init_network();
56
57    init_telnet();
58
59    init_sys();
60}
61
62static void
63usage(int exit_code)
64{
65  fprintf(stderr, "Usage: %s %s%s%s%s\n", prompt,
66#ifdef	AUTHENTICATION
67	  "[-8] [-E] [-K] [-L] [-G] [-S tos] [-X atype] [-a] [-c] [-d] [-e char]",
68	  "\n\t[-k realm] [-l user] [-f/-F] [-n tracefile] ",
69#else
70	  "[-8] [-E] [-L] [-S tos] [-a] [-c] [-d] [-e char] [-l user]",
71	  "\n\t[-n tracefile]",
72#endif
73	  "[-r] ",
74#ifdef	ENCRYPTION
75	  "[-x] [host-name [port]]"
76#else
77	  "[host-name [port]]"
78#endif
79    );
80  exit(exit_code);
81}
82
83/*
84 * main.  Parse arguments, invoke the protocol or command parser.
85 */
86
87
88#ifdef	FORWARD
89int forward_option = 0; /* forward flags set from command line */
90#endif	/* FORWARD */
91void
92set_forward_options(void)
93{
94#ifdef FORWARD
95	switch(forward_option) {
96	case 'f':
97		kerberos5_set_forward(1);
98		kerberos5_set_forwardable(0);
99		break;
100	case 'F':
101		kerberos5_set_forward(1);
102		kerberos5_set_forwardable(1);
103		break;
104	case 'G':
105		kerberos5_set_forward(0);
106		kerberos5_set_forwardable(0);
107		break;
108	default:
109		break;
110	}
111#endif
112}
113
114#ifdef KRB5
115#define Authenticator asn1_Authenticator
116#include <krb5.h>
117static void
118krb5_init(void)
119{
120    krb5_context context;
121    krb5_error_code ret;
122    krb5_boolean ret_val;
123
124    ret = krb5_init_context(&context);
125    if (ret)
126	return;
127
128#if defined(AUTHENTICATION) && defined(FORWARD)
129    krb5_appdefault_boolean(context, NULL,
130			    NULL, "forward",
131			    0, &ret_val);
132    if (ret_val)
133	    kerberos5_set_forward(1);
134    krb5_appdefault_boolean(context, NULL,
135			    NULL, "forwardable",
136			    0, &ret_val);
137    if (ret_val)
138	    kerberos5_set_forwardable(1);
139#endif
140#ifdef  ENCRYPTION
141    krb5_appdefault_boolean(context, NULL,
142			    NULL, "encrypt",
143			    0, &ret_val);
144    if (ret_val) {
145          encrypt_auto(1);
146          decrypt_auto(1);
147	  wantencryption = 1;
148          EncryptVerbose(1);
149        }
150#endif
151
152    krb5_free_context(context);
153}
154#endif
155
156int
157main(int argc, char **argv)
158{
159	int ch;
160	char *user;
161
162	setprogname(argv[0]);
163
164#ifdef KRB5
165	krb5_init();
166#endif
167
168	tninit();		/* Clear out things */
169
170	TerminalSaveState();
171
172	if ((prompt = strrchr(argv[0], '/')))
173		++prompt;
174	else
175		prompt = argv[0];
176
177	user = NULL;
178
179	rlogin = (strncmp(prompt, "rlog", 4) == 0) ? '~' : _POSIX_VDISABLE;
180
181	/*
182	 * if AUTHENTICATION and ENCRYPTION is set autologin will be
183	 * se to true after the getopt switch; unless the -K option is
184	 * passed
185	 */
186	autologin = -1;
187
188	if (argc == 2 && strcmp(argv[1], "--version") == 0) {
189	    print_version(NULL);
190	    exit(0);
191	}
192	if (argc == 2 && strcmp(argv[1], "--help") == 0)
193	    usage(0);
194
195
196	while((ch = getopt(argc, argv,
197			   "78DEKLS:X:abcde:fFk:l:n:rxG")) != -1) {
198		switch(ch) {
199		case '8':
200			eight = 3;	/* binary output and input */
201			break;
202		case '7':
203			eight = 0;
204			break;
205		case 'b':
206		    binary = 3;
207		    break;
208		case 'D': {
209		    /* sometimes we don't want a mangled display */
210		    char *p;
211		    if((p = getenv("DISPLAY")))
212			env_define((unsigned char*)"DISPLAY", (unsigned char*)p);
213		    break;
214		}
215		case 'E':
216			rlogin = escape = _POSIX_VDISABLE;
217			break;
218		case 'K':
219#ifdef	AUTHENTICATION
220			autologin = 0;
221#endif
222			break;
223		case 'L':
224			eight |= 2;	/* binary output only */
225			break;
226		case 'S':
227		    {
228#ifdef	HAVE_PARSETOS
229			extern int tos;
230
231			if ((tos = parsetos(optarg, "tcp")) < 0)
232				fprintf(stderr, "%s%s%s%s\n",
233					prompt, ": Bad TOS argument '",
234					optarg,
235					"; will try to use default TOS");
236#else
237			fprintf(stderr,
238			   "%s: Warning: -S ignored, no parsetos() support.\n",
239								prompt);
240#endif
241		    }
242			break;
243		case 'X':
244#ifdef	AUTHENTICATION
245			auth_disable_name(optarg);
246#endif
247			break;
248		case 'a':
249			autologin = 1;
250			break;
251		case 'c':
252			skiprc = 1;
253			break;
254		case 'd':
255			debug = 1;
256			break;
257		case 'e':
258			set_escape_char(optarg);
259			break;
260		case 'f':
261		case 'F':
262		case 'G':
263#if defined(AUTHENTICATION) && defined(KRB5) && defined(FORWARD)
264			if (forward_option) {
265			    fprintf(stderr,
266				    "%s: Only one of -f, -F and -G allowed.\n",
267				    prompt);
268			    usage(1);
269			}
270			forward_option = ch;
271#else
272			fprintf(stderr,
273			 "%s: Warning: -%c ignored, no Kerberos V5 support.\n",
274				prompt, ch);
275#endif
276			break;
277		case 'k':
278		    fprintf(stderr,
279			    "%s: Warning: -k ignored, no Kerberos V4 support.\n",
280			    prompt);
281		    break;
282		case 'l':
283		  if(autologin == 0){
284		    fprintf(stderr, "%s: Warning: -K ignored\n", prompt);
285		    autologin = -1;
286		  }
287			user = optarg;
288			break;
289		case 'n':
290				SetNetTrace(optarg);
291			break;
292		case 'r':
293			rlogin = '~';
294			break;
295		case 'x':
296#ifdef	ENCRYPTION
297			encrypt_auto(1);
298			decrypt_auto(1);
299			wantencryption = 1;
300			EncryptVerbose(1);
301#else
302			fprintf(stderr,
303			    "%s: Warning: -x ignored, no ENCRYPT support.\n",
304								prompt);
305#endif
306			break;
307
308		case '?':
309		default:
310			usage(1);
311			/* NOTREACHED */
312		}
313	}
314
315	if (autologin == -1) {		/* esc@magic.fi; force  */
316#if defined(AUTHENTICATION)
317		autologin = 1;
318#endif
319#if defined(ENCRYPTION)
320		encrypt_auto(1);
321		decrypt_auto(1);
322		wantencryption = -1;
323#endif
324	}
325
326	if (autologin == -1)
327		autologin = (rlogin == _POSIX_VDISABLE) ? 0 : 1;
328
329	argc -= optind;
330	argv += optind;
331
332	if (argc) {
333		char *args[7], **argp = args;
334
335		if (argc > 2)
336			usage(1);
337		*argp++ = prompt;
338		if (user) {
339			*argp++ = "-l";
340			*argp++ = user;
341		}
342		*argp++ = argv[0];		/* host */
343		if (argc > 1)
344			*argp++ = argv[1];	/* port */
345		*argp = 0;
346
347		if (setjmp(toplevel) != 0)
348			Exit(0);
349		if (tn(argp - args, args) == 1)
350			return (0);
351		else
352			return (1);
353	}
354	setjmp(toplevel);
355	for (;;) {
356			command(1, 0, 0);
357	}
358}
359