xref: /freebsd/contrib/telnet/telnet/main.c (revision daf1cffce2e07931f27c6c6998652e90df6ba87e)
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  *	$FreeBSD$
34  */
35 
36 #ifndef lint
37 static const char copyright[] =
38 "@(#) Copyright (c) 1988, 1990, 1993\n\
39 	The Regents of the University of California.  All rights reserved.\n";
40 #endif /* not lint */
41 
42 #ifndef lint
43 static const char sccsid[] = "@(#)main.c	8.3 (Berkeley) 5/30/95";
44 #endif /* not lint */
45 
46 #include <sys/types.h>
47 #include <sys/socket.h>
48 #include <stdlib.h>
49 
50 #include "ring.h"
51 #include "externs.h"
52 #include "defines.h"
53 
54 #if	defined(AUTHENTICATION)
55 #include <libtelnet/auth.h>
56 #endif
57 #if	defined(ENCRYPTION)
58 #include <libtelnet/encrypt.h>
59 #endif
60 
61 /* These values need to be the same as defined in libtelnet/kerberos5.c */
62 /* Either define them in both places, or put in some common header file. */
63 #define OPTS_FORWARD_CREDS	0x00000002
64 #define OPTS_FORWARDABLE_CREDS	0x00000001
65 
66 #if 0
67 #define FORWARD
68 #endif
69 
70 void init_terminal(void);
71 void init_network(void);
72 void init_telnet(void);
73 void init_sys(void);
74 void init_3270(void);
75 
76 #if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
77 char *ipsec_policy_in = NULL;
78 char *ipsec_policy_out = NULL;
79 #endif
80 
81 int family = AF_UNSPEC;
82 
83 /*
84  * Initialize variables.
85  */
86     void
87 tninit()
88 {
89     init_terminal();
90 
91     init_network();
92 
93     init_telnet();
94 
95     init_sys();
96 
97 #if defined(TN3270)
98     init_3270();
99 #endif
100 }
101 
102 	void
103 usage()
104 {
105 	fprintf(stderr, "Usage: %s %s%s%s%s\n",
106 	    prompt,
107 #ifdef	AUTHENTICATION
108 	    "[-4] [-6] [-8] [-E] [-K] [-L] [-N] [-S tos] [-X atype] [-a] [-c] [-d]",
109 	    "\n\t[-e char] [-k realm] [-l user] [-f/-F] [-n tracefile] ",
110 #else
111 	    "[-4] [-6] [-8] [-E] [-L] [-N] [-S tos] [-a] [-c] [-d] [-e char] [-l user]",
112 	    "\n\t[-n tracefile] ",
113 #endif
114 #if defined(TN3270) && defined(unix)
115 # ifdef AUTHENTICATION
116 	    "[-noasynch] [-noasynctty]\n\t"
117 	    "[-noasyncnet] [-r] [-s src_addr] [-t transcom] ",
118 # else
119 	    "[-noasynch] [-noasynctty] [-noasyncnet] [-r]\n\t"
120 	    "[-s src_addr] [-t transcom]",
121 # endif
122 #else
123 	    "[-r] [-s src_addr] ",
124 #endif
125 #if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
126 	    "[-P policy]"
127 #endif
128 #ifdef	ENCRYPTION
129 	    "[-x] [host-name [port]]"
130 #else	/* ENCRYPTION */
131 	    "[host-name [port]]"
132 #endif	/* ENCRYPTION */
133 	);
134 	exit(1);
135 }
136 
137 /*
138  * main.  Parse arguments, invoke the protocol or command parser.
139  */
140 
141 	int
142 main(argc, argv)
143 	int argc;
144 	char *argv[];
145 {
146 	extern char *optarg;
147 	extern int optind;
148 	int ch;
149 	char *user, *strrchr();
150 	char *src_addr = NULL;
151 #ifdef	FORWARD
152 	extern int forward_flags;
153 #endif	/* FORWARD */
154 
155 	tninit();		/* Clear out things */
156 #if	defined(CRAY) && !defined(__STDC__)
157 	_setlist_init();	/* Work around compiler bug */
158 #endif
159 
160 	TerminalSaveState();
161 
162 	if ((prompt = strrchr(argv[0], '/')))
163 		++prompt;
164 	else
165 		prompt = argv[0];
166 
167 	user = NULL;
168 
169 	rlogin = (strncmp(prompt, "rlog", 4) == 0) ? '~' : _POSIX_VDISABLE;
170 	autologin = -1;
171 
172 #if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
173 #define IPSECOPT	"P:"
174 #else
175 #define IPSECOPT
176 #endif
177 	while ((ch = getopt(argc, argv,
178 			    "468EKLNS:X:acde:fFk:l:n:rs:t:x" IPSECOPT)) != -1)
179 #undef IPSECOPT
180 	{
181 		switch(ch) {
182 		case '4':
183 			family = AF_INET;
184 			break;
185 #ifdef INET6
186 		case '6':
187 			family = AF_INET6;
188 			break;
189 #endif
190 		case '8':
191 			eight = 3;	/* binary output and input */
192 			break;
193 		case 'E':
194 			rlogin = escape = _POSIX_VDISABLE;
195 			break;
196 		case 'K':
197 #ifdef	AUTHENTICATION
198 			autologin = 0;
199 #endif
200 			break;
201 		case 'L':
202 			eight |= 2;	/* binary output only */
203 			break;
204 		case 'N':
205 			doaddrlookup = 0;
206 			break;
207 		case 'S':
208 		    {
209 #ifdef	HAS_GETTOS
210 			extern int tos;
211 
212 			if ((tos = parsetos(optarg, "tcp")) < 0)
213 				fprintf(stderr, "%s%s%s%s\n",
214 					prompt, ": Bad TOS argument '",
215 					optarg,
216 					"; will try to use default TOS");
217 #else
218 			fprintf(stderr,
219 			   "%s: Warning: -S ignored, no parsetos() support.\n",
220 								prompt);
221 #endif
222 		    }
223 			break;
224 		case 'X':
225 #ifdef	AUTHENTICATION
226 			auth_disable_name(optarg);
227 #endif
228 			break;
229 		case 'a':
230 			autologin = 1;
231 			break;
232 		case 'c':
233 			skiprc = 1;
234 			break;
235 		case 'd':
236 			debug = 1;
237 			break;
238 		case 'e':
239 			set_escape_char(optarg);
240 			break;
241 		case 'f':
242 #if defined(AUTHENTICATION) && defined(KRB5) && defined(FORWARD)
243 			if (forward_flags & OPTS_FORWARD_CREDS) {
244 			    fprintf(stderr,
245 				    "%s: Only one of -f and -F allowed.\n",
246 				    prompt);
247 			    usage();
248 			}
249 			forward_flags |= OPTS_FORWARD_CREDS;
250 #else
251 			fprintf(stderr,
252 			 "%s: Warning: -f ignored, no Kerberos V5 support.\n",
253 				prompt);
254 #endif
255 			break;
256 		case 'F':
257 #if defined(AUTHENTICATION) && defined(KRB5) && defined(FORWARD)
258 			if (forward_flags & OPTS_FORWARD_CREDS) {
259 			    fprintf(stderr,
260 				    "%s: Only one of -f and -F allowed.\n",
261 				    prompt);
262 			    usage();
263 			}
264 			forward_flags |= OPTS_FORWARD_CREDS;
265 			forward_flags |= OPTS_FORWARDABLE_CREDS;
266 #else
267 			fprintf(stderr,
268 			 "%s: Warning: -F ignored, no Kerberos V5 support.\n",
269 				prompt);
270 #endif
271 			break;
272 		case 'k':
273 #if defined(AUTHENTICATION) && defined(KRB4)
274 		    {
275 			extern char *dest_realm, dst_realm_buf[], dst_realm_sz;
276 			dest_realm = dst_realm_buf;
277 			(void)strncpy(dest_realm, optarg, dst_realm_sz);
278 		    }
279 #else
280 			fprintf(stderr,
281 			   "%s: Warning: -k ignored, no Kerberos V4 support.\n",
282 								prompt);
283 #endif
284 			break;
285 		case 'l':
286 			autologin = 1;
287 			user = optarg;
288 			break;
289 		case 'n':
290 #if defined(TN3270) && defined(unix)
291 			/* distinguish between "-n oasynch" and "-noasynch" */
292 			if (argv[optind - 1][0] == '-' && argv[optind - 1][1]
293 			    == 'n' && argv[optind - 1][2] == 'o') {
294 				if (!strcmp(optarg, "oasynch")) {
295 					noasynchtty = 1;
296 					noasynchnet = 1;
297 				} else if (!strcmp(optarg, "oasynchtty"))
298 					noasynchtty = 1;
299 				else if (!strcmp(optarg, "oasynchnet"))
300 					noasynchnet = 1;
301 			} else
302 #endif	/* defined(TN3270) && defined(unix) */
303 				SetNetTrace(optarg);
304 			break;
305 		case 'r':
306 			rlogin = '~';
307 			break;
308 		case 's':
309 			src_addr = optarg;
310 			break;
311 		case 't':
312 #if defined(TN3270) && defined(unix)
313 			transcom = tline;
314 			(void)strcpy(transcom, optarg);
315 #else
316 			fprintf(stderr,
317 			   "%s: Warning: -t ignored, no TN3270 support.\n",
318 								prompt);
319 #endif
320 			break;
321 		case 'x':
322 #ifdef	ENCRYPTION
323 			encrypt_auto(1);
324 			decrypt_auto(1);
325 #else	/* ENCRYPTION */
326 			fprintf(stderr,
327 			    "%s: Warning: -x ignored, no ENCRYPT support.\n",
328 								prompt);
329 #endif	/* ENCRYPTION */
330 			break;
331 #if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
332 		case 'P':
333 			if (!strncmp("in", optarg, 2))
334 				ipsec_policy_in = strdup(optarg);
335 			else if (!strncmp("out", optarg, 3))
336 				ipsec_policy_out = strdup(optarg);
337 			else
338 				usage();
339 			break;
340 #endif
341 		case '?':
342 		default:
343 			usage();
344 			/* NOTREACHED */
345 		}
346 	}
347 	if (autologin == -1)
348 		autologin = (rlogin == _POSIX_VDISABLE) ? 0 : 1;
349 
350 	argc -= optind;
351 	argv += optind;
352 
353 	if (argc) {
354 		char *args[9], **argp = args;
355 
356 		if (argc > 2)
357 			usage();
358 		*argp++ = prompt;
359 		if (user) {
360 			*argp++ = "-l";
361 			*argp++ = user;
362 		}
363 		if (src_addr) {
364 			*argp++ = "-s";
365 			*argp++ = src_addr;
366 		}
367 		*argp++ = argv[0];		/* host */
368 		if (argc > 1)
369 			*argp++ = argv[1];	/* port */
370 		*argp = 0;
371 
372 		if (setjmp(toplevel) != 0)
373 			Exit(0);
374 		if (tn(argp - args, args) == 1)
375 			return (0);
376 		else
377 			return (1);
378 	}
379 	(void)setjmp(toplevel);
380 	for (;;) {
381 #ifdef TN3270
382 		if (shell_active)
383 			shell_continue();
384 		else
385 #endif
386 			command(1, 0, 0);
387 	}
388 	return 0;
389 }
390