xref: /freebsd/contrib/telnet/telnet/main.c (revision 3db1b221edab9bada79da4f825347ce1772f5ee8)
181cb6ddcSMark Murray /*
281cb6ddcSMark Murray  * Copyright (c) 1988, 1990, 1993
381cb6ddcSMark Murray  *	The Regents of the University of California.  All rights reserved.
481cb6ddcSMark Murray  *
581cb6ddcSMark Murray  * Redistribution and use in source and binary forms, with or without
681cb6ddcSMark Murray  * modification, are permitted provided that the following conditions
781cb6ddcSMark Murray  * are met:
881cb6ddcSMark Murray  * 1. Redistributions of source code must retain the above copyright
981cb6ddcSMark Murray  *    notice, this list of conditions and the following disclaimer.
1081cb6ddcSMark Murray  * 2. Redistributions in binary form must reproduce the above copyright
1181cb6ddcSMark Murray  *    notice, this list of conditions and the following disclaimer in the
1281cb6ddcSMark Murray  *    documentation and/or other materials provided with the distribution.
1383129c0bSEd Maste  * 3. Neither the name of the University nor the names of its contributors
1481cb6ddcSMark Murray  *    may be used to endorse or promote products derived from this software
1581cb6ddcSMark Murray  *    without specific prior written permission.
1681cb6ddcSMark Murray  *
1781cb6ddcSMark Murray  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
1881cb6ddcSMark Murray  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1981cb6ddcSMark Murray  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2081cb6ddcSMark Murray  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2181cb6ddcSMark Murray  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2281cb6ddcSMark Murray  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2381cb6ddcSMark Murray  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2481cb6ddcSMark Murray  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2581cb6ddcSMark Murray  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2681cb6ddcSMark Murray  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2781cb6ddcSMark Murray  * SUCH DAMAGE.
2881cb6ddcSMark Murray  */
2981cb6ddcSMark Murray 
3077b7cdf1SDavid E. O'Brien #if 0
3181cb6ddcSMark Murray #ifndef lint
3204c426ccSMark Murray static const char sccsid[] = "@(#)main.c	8.3 (Berkeley) 5/30/95";
338fa113e5SMark Murray #endif
3477b7cdf1SDavid E. O'Brien #endif
3577b7cdf1SDavid E. O'Brien #include <sys/cdefs.h>
3677b7cdf1SDavid E. O'Brien __FBSDID("$FreeBSD$");
3781cb6ddcSMark Murray 
38de93353dSMaxim Konovalov #include <sys/param.h>
394dd8b5abSYoshinobu Inoue #include <sys/socket.h>
4004c426ccSMark Murray #include <stdlib.h>
4121f083c0SMark Murray #include <string.h>
4221f083c0SMark Murray #include <unistd.h>
4381cb6ddcSMark Murray 
4481cb6ddcSMark Murray #include "ring.h"
4581cb6ddcSMark Murray #include "externs.h"
4681cb6ddcSMark Murray #include "defines.h"
4781cb6ddcSMark Murray 
488fa113e5SMark Murray #ifdef	AUTHENTICATION
4904c426ccSMark Murray #include <libtelnet/auth.h>
5004c426ccSMark Murray #endif
518fa113e5SMark Murray #ifdef	ENCRYPTION
5204c426ccSMark Murray #include <libtelnet/encrypt.h>
5304c426ccSMark Murray #endif
5404c426ccSMark Murray 
5581cb6ddcSMark Murray /* These values need to be the same as defined in libtelnet/kerberos5.c */
5681cb6ddcSMark Murray /* Either define them in both places, or put in some common header file. */
5781cb6ddcSMark Murray #define OPTS_FORWARD_CREDS	0x00000002
5881cb6ddcSMark Murray #define OPTS_FORWARDABLE_CREDS	0x00000001
5981cb6ddcSMark Murray 
604dd8b5abSYoshinobu Inoue #if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
614dd8b5abSYoshinobu Inoue char *ipsec_policy_in = NULL;
624dd8b5abSYoshinobu Inoue char *ipsec_policy_out = NULL;
634dd8b5abSYoshinobu Inoue #endif
644dd8b5abSYoshinobu Inoue 
65de93353dSMaxim Konovalov extern int tos;
66de93353dSMaxim Konovalov 
674dd8b5abSYoshinobu Inoue int family = AF_UNSPEC;
684dd8b5abSYoshinobu Inoue 
6981cb6ddcSMark Murray /*
7081cb6ddcSMark Murray  * Initialize variables.
7181cb6ddcSMark Murray  */
7281cb6ddcSMark Murray void
738fa113e5SMark Murray tninit(void)
7481cb6ddcSMark Murray {
7581cb6ddcSMark Murray     init_terminal();
7681cb6ddcSMark Murray 
7781cb6ddcSMark Murray     init_network();
7881cb6ddcSMark Murray 
7981cb6ddcSMark Murray     init_telnet();
8081cb6ddcSMark Murray 
8181cb6ddcSMark Murray     init_sys();
8281cb6ddcSMark Murray }
8381cb6ddcSMark Murray 
848fa113e5SMark Murray static void
858fa113e5SMark Murray usage(void)
8681cb6ddcSMark Murray {
8786953b02SMark Murray 	fprintf(stderr, "usage: %s %s%s%s%s\n",
8881cb6ddcSMark Murray 	    prompt,
8981cb6ddcSMark Murray #ifdef	AUTHENTICATION
90ad11def5SEnji Cooper 	    "[-4] [-6] [-8] [-B baudrate] [-E] [-K] [-L] [-N] [-S tos] [-X atype]",
91ad11def5SEnji Cooper 	    "\n\t[-c] [-d] [-e char] [-k realm] [-l user] [-f/-F] [-n tracefile] ",
9281cb6ddcSMark Murray #else
93ad11def5SEnji Cooper 	    "[-4] [-6] [-8] [-B baudrate] [-E] [-L] [-N] [-S tos] [-c] [-d]",
94a5493c1bSRuslan Ermilov 	    "\n\t[-e char] [-l user] [-n tracefile] ",
9581cb6ddcSMark Murray #endif
96a5493c1bSRuslan Ermilov 	    "[-r] [-s src_addr] [-u] ",
974dd8b5abSYoshinobu Inoue #if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
984dd8b5abSYoshinobu Inoue 	    "[-P policy] "
994dd8b5abSYoshinobu Inoue #endif
10081cb6ddcSMark Murray #ifdef	ENCRYPTION
10103679084SNick Sayer 	    "[-y] [host-name [port]]"
10281cb6ddcSMark Murray #else	/* ENCRYPTION */
10381cb6ddcSMark Murray 	    "[host-name [port]]"
10481cb6ddcSMark Murray #endif	/* ENCRYPTION */
10581cb6ddcSMark Murray 	);
10681cb6ddcSMark Murray 	exit(1);
10781cb6ddcSMark Murray }
10881cb6ddcSMark Murray 
10981cb6ddcSMark Murray /*
11081cb6ddcSMark Murray  * main.  Parse arguments, invoke the protocol or command parser.
11181cb6ddcSMark Murray  */
11281cb6ddcSMark Murray 
11304c426ccSMark Murray int
1148fa113e5SMark Murray main(int argc, char *argv[])
11581cb6ddcSMark Murray {
116de93353dSMaxim Konovalov 	u_long ultmp;
11781cb6ddcSMark Murray 	int ch;
118de93353dSMaxim Konovalov 	char *ep, *user;
11942cf8219SRuslan Ermilov 	char *src_addr = NULL;
12081cb6ddcSMark Murray #ifdef	FORWARD
12181cb6ddcSMark Murray 	extern int forward_flags;
12281cb6ddcSMark Murray #endif	/* FORWARD */
12381cb6ddcSMark Murray 
124*3db1b221SPoul-Henning Kamp 	setbuf(stdout, NULL);
125*3db1b221SPoul-Henning Kamp 	setbuf(stderr, NULL);
12681cb6ddcSMark Murray 	tninit();		/* Clear out things */
12781cb6ddcSMark Murray 
12881cb6ddcSMark Murray 	TerminalSaveState();
12981cb6ddcSMark Murray 
13004c426ccSMark Murray 	if ((prompt = strrchr(argv[0], '/')))
13181cb6ddcSMark Murray 		++prompt;
13281cb6ddcSMark Murray 	else
13381cb6ddcSMark Murray 		prompt = argv[0];
13481cb6ddcSMark Murray 
13581cb6ddcSMark Murray 	user = NULL;
13681cb6ddcSMark Murray 
13781cb6ddcSMark Murray 	rlogin = (strncmp(prompt, "rlog", 4) == 0) ? '~' : _POSIX_VDISABLE;
13821f083c0SMark Murray #ifdef AUTHENTICATION
13903679084SNick Sayer 	autologin = 1;
14021f083c0SMark Murray #else
14121f083c0SMark Murray 	autologin = -1;
14221f083c0SMark Murray #endif
14303679084SNick Sayer 
1448fa113e5SMark Murray #ifdef	ENCRYPTION
14503679084SNick Sayer 	encrypt_auto(1);
14603679084SNick Sayer 	decrypt_auto(1);
14703679084SNick Sayer #endif
14881cb6ddcSMark Murray 
1494dd8b5abSYoshinobu Inoue #if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
1504dd8b5abSYoshinobu Inoue #define IPSECOPT	"P:"
1514dd8b5abSYoshinobu Inoue #else
1524dd8b5abSYoshinobu Inoue #define IPSECOPT
1534dd8b5abSYoshinobu Inoue #endif
1544dd8b5abSYoshinobu Inoue 	while ((ch = getopt(argc, argv,
155ad11def5SEnji Cooper 			    "468B:EKLNS:X:acde:fFk:l:n:rs:uxy" IPSECOPT)) != -1)
1564dd8b5abSYoshinobu Inoue #undef IPSECOPT
1574dd8b5abSYoshinobu Inoue 	{
15881cb6ddcSMark Murray 		switch(ch) {
1594dd8b5abSYoshinobu Inoue 		case '4':
1604dd8b5abSYoshinobu Inoue 			family = AF_INET;
1614dd8b5abSYoshinobu Inoue 			break;
1624dd8b5abSYoshinobu Inoue #ifdef INET6
1634dd8b5abSYoshinobu Inoue 		case '6':
1644dd8b5abSYoshinobu Inoue 			family = AF_INET6;
1654dd8b5abSYoshinobu Inoue 			break;
1664dd8b5abSYoshinobu Inoue #endif
16781cb6ddcSMark Murray 		case '8':
16881cb6ddcSMark Murray 			eight = 3;	/* binary output and input */
16981cb6ddcSMark Murray 			break;
170ad11def5SEnji Cooper 		case 'B':
171ad11def5SEnji Cooper 			DoBaudRate(optarg);
172ad11def5SEnji Cooper 			break;
17381cb6ddcSMark Murray 		case 'E':
17481cb6ddcSMark Murray 			rlogin = escape = _POSIX_VDISABLE;
17581cb6ddcSMark Murray 			break;
17681cb6ddcSMark Murray 		case 'K':
17781cb6ddcSMark Murray #ifdef	AUTHENTICATION
17881cb6ddcSMark Murray 			autologin = 0;
17981cb6ddcSMark Murray #endif
18081cb6ddcSMark Murray 			break;
18181cb6ddcSMark Murray 		case 'L':
18281cb6ddcSMark Murray 			eight |= 2;	/* binary output only */
18381cb6ddcSMark Murray 			break;
18442cf8219SRuslan Ermilov 		case 'N':
18542cf8219SRuslan Ermilov 			doaddrlookup = 0;
18642cf8219SRuslan Ermilov 			break;
18781cb6ddcSMark Murray 		case 'S':
18881cb6ddcSMark Murray #ifdef	HAS_GETTOS
18981cb6ddcSMark Murray 
19081cb6ddcSMark Murray 			if ((tos = parsetos(optarg, "tcp")) < 0)
19181cb6ddcSMark Murray 				fprintf(stderr, "%s%s%s%s\n",
19281cb6ddcSMark Murray 					prompt, ": Bad TOS argument '",
19381cb6ddcSMark Murray 					optarg,
19481cb6ddcSMark Murray 					"; will try to use default TOS");
19581cb6ddcSMark Murray #else
196de93353dSMaxim Konovalov #define	MAXTOS	255
197de93353dSMaxim Konovalov 			ultmp = strtoul(optarg, &ep, 0);
198de93353dSMaxim Konovalov 			if (*ep || ep == optarg || ultmp > MAXTOS)
199de93353dSMaxim Konovalov 				fprintf(stderr, "%s%s%s%s\n",
200de93353dSMaxim Konovalov 					prompt, ": Bad TOS argument '",
201de93353dSMaxim Konovalov 					optarg,
202de93353dSMaxim Konovalov 					"; will try to use default TOS");
203de93353dSMaxim Konovalov 			else
204de93353dSMaxim Konovalov 				tos = ultmp;
20581cb6ddcSMark Murray #endif
20681cb6ddcSMark Murray 			break;
20781cb6ddcSMark Murray 		case 'X':
20881cb6ddcSMark Murray #ifdef	AUTHENTICATION
20981cb6ddcSMark Murray 			auth_disable_name(optarg);
21081cb6ddcSMark Murray #endif
21181cb6ddcSMark Murray 			break;
21281cb6ddcSMark Murray 		case 'a':
21321f083c0SMark Murray #ifdef	AUTHENTICATION
21403679084SNick Sayer 			/* It's the default now, so ignore */
21521f083c0SMark Murray #else
21621f083c0SMark Murray 			autologin = 1;
21721f083c0SMark Murray #endif
21881cb6ddcSMark Murray 			break;
21981cb6ddcSMark Murray 		case 'c':
22081cb6ddcSMark Murray 			skiprc = 1;
22181cb6ddcSMark Murray 			break;
22281cb6ddcSMark Murray 		case 'd':
223074e8e8eSMark Murray 			telnet_debug = 1;
22481cb6ddcSMark Murray 			break;
22581cb6ddcSMark Murray 		case 'e':
22681cb6ddcSMark Murray 			set_escape_char(optarg);
22781cb6ddcSMark Murray 			break;
22881cb6ddcSMark Murray 		case 'f':
2298fa113e5SMark Murray #ifdef	AUTHENTICATION
2308fa113e5SMark Murray #if defined(KRB5) && defined(FORWARD)
23181cb6ddcSMark Murray 			if (forward_flags & OPTS_FORWARD_CREDS) {
23281cb6ddcSMark Murray 			    fprintf(stderr,
23381cb6ddcSMark Murray 				    "%s: Only one of -f and -F allowed.\n",
23481cb6ddcSMark Murray 				    prompt);
23581cb6ddcSMark Murray 			    usage();
23681cb6ddcSMark Murray 			}
23781cb6ddcSMark Murray 			forward_flags |= OPTS_FORWARD_CREDS;
23881cb6ddcSMark Murray #else
23981cb6ddcSMark Murray 			fprintf(stderr,
24081cb6ddcSMark Murray 			 "%s: Warning: -f ignored, no Kerberos V5 support.\n",
24181cb6ddcSMark Murray 				prompt);
24281cb6ddcSMark Murray #endif
2438fa113e5SMark Murray #else
2448fa113e5SMark Murray 			fprintf(stderr,
2458fa113e5SMark Murray 			 "%s: Warning: -f ignored, no Kerberos V5 support.\n",
2468fa113e5SMark Murray 				prompt);
2478fa113e5SMark Murray #endif
24881cb6ddcSMark Murray 			break;
24981cb6ddcSMark Murray 		case 'F':
2508fa113e5SMark Murray #ifdef	AUTHENTICATION
2518fa113e5SMark Murray #if defined(KRB5) && defined(FORWARD)
25281cb6ddcSMark Murray 			if (forward_flags & OPTS_FORWARD_CREDS) {
25381cb6ddcSMark Murray 			    fprintf(stderr,
25481cb6ddcSMark Murray 				    "%s: Only one of -f and -F allowed.\n",
25581cb6ddcSMark Murray 				    prompt);
25681cb6ddcSMark Murray 			    usage();
25781cb6ddcSMark Murray 			}
25881cb6ddcSMark Murray 			forward_flags |= OPTS_FORWARD_CREDS;
25981cb6ddcSMark Murray 			forward_flags |= OPTS_FORWARDABLE_CREDS;
26081cb6ddcSMark Murray #else
26181cb6ddcSMark Murray 			fprintf(stderr,
26281cb6ddcSMark Murray 			 "%s: Warning: -F ignored, no Kerberos V5 support.\n",
26381cb6ddcSMark Murray 				prompt);
26481cb6ddcSMark Murray #endif
2658fa113e5SMark Murray #else
2668fa113e5SMark Murray 			fprintf(stderr,
2678fa113e5SMark Murray 			 "%s: Warning: -F ignored, no Kerberos V5 support.\n",
2688fa113e5SMark Murray 				prompt);
2698fa113e5SMark Murray #endif
27081cb6ddcSMark Murray 			break;
27181cb6ddcSMark Murray 		case 'k':
2728fa113e5SMark Murray #ifdef	AUTHENTICATION
2738fa113e5SMark Murray #if defined(KRB4)
27481cb6ddcSMark Murray 		    {
27581cb6ddcSMark Murray 			extern char *dest_realm, dst_realm_buf[], dst_realm_sz;
27681cb6ddcSMark Murray 			dest_realm = dst_realm_buf;
27781cb6ddcSMark Murray 			(void)strncpy(dest_realm, optarg, dst_realm_sz);
27881cb6ddcSMark Murray 		    }
27981cb6ddcSMark Murray #else
28081cb6ddcSMark Murray 			fprintf(stderr,
28181cb6ddcSMark Murray 			   "%s: Warning: -k ignored, no Kerberos V4 support.\n",
28281cb6ddcSMark Murray 								prompt);
28381cb6ddcSMark Murray #endif
2848fa113e5SMark Murray #else
2858fa113e5SMark Murray 			fprintf(stderr,
2868fa113e5SMark Murray 			   "%s: Warning: -k ignored, no Kerberos V4 support.\n",
2878fa113e5SMark Murray 								prompt);
2888fa113e5SMark Murray #endif
28981cb6ddcSMark Murray 			break;
29081cb6ddcSMark Murray 		case 'l':
29121f083c0SMark Murray #ifdef	AUTHENTICATION
29221f083c0SMark Murray 			/* This is the default now, so ignore it */
29321f083c0SMark Murray #else
29421f083c0SMark Murray 			autologin = 1;
29521f083c0SMark Murray #endif
29681cb6ddcSMark Murray 			user = optarg;
29781cb6ddcSMark Murray 			break;
29881cb6ddcSMark Murray 		case 'n':
29981cb6ddcSMark Murray 				SetNetTrace(optarg);
30081cb6ddcSMark Murray 			break;
30181cb6ddcSMark Murray 		case 'r':
30281cb6ddcSMark Murray 			rlogin = '~';
30381cb6ddcSMark Murray 			break;
30442cf8219SRuslan Ermilov 		case 's':
30542cf8219SRuslan Ermilov 			src_addr = optarg;
30642cf8219SRuslan Ermilov 			break;
307a5493c1bSRuslan Ermilov 		case 'u':
308a5493c1bSRuslan Ermilov 			family = AF_UNIX;
309a5493c1bSRuslan Ermilov 			break;
31081cb6ddcSMark Murray 		case 'x':
3118fa113e5SMark Murray #ifndef	ENCRYPTION
31221f083c0SMark Murray 			fprintf(stderr,
31321f083c0SMark Murray 			    "%s: Warning: -x ignored, no ENCRYPT support.\n",
31421f083c0SMark Murray 								prompt);
31521f083c0SMark Murray #endif	/* ENCRYPTION */
31603679084SNick Sayer 			break;
31703679084SNick Sayer 		case 'y':
31881cb6ddcSMark Murray #ifdef	ENCRYPTION
31903679084SNick Sayer 			encrypt_auto(0);
32003679084SNick Sayer 			decrypt_auto(0);
32121f083c0SMark Murray #else
32221f083c0SMark Murray 			fprintf(stderr,
32321f083c0SMark Murray 			    "%s: Warning: -y ignored, no ENCRYPT support.\n",
32421f083c0SMark Murray 								prompt);
32581cb6ddcSMark Murray #endif	/* ENCRYPTION */
32681cb6ddcSMark Murray 			break;
3274dd8b5abSYoshinobu Inoue #if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
3284dd8b5abSYoshinobu Inoue 		case 'P':
3294dd8b5abSYoshinobu Inoue 			if (!strncmp("in", optarg, 2))
3304dd8b5abSYoshinobu Inoue 				ipsec_policy_in = strdup(optarg);
3314dd8b5abSYoshinobu Inoue 			else if (!strncmp("out", optarg, 3))
3324dd8b5abSYoshinobu Inoue 				ipsec_policy_out = strdup(optarg);
3334dd8b5abSYoshinobu Inoue 			else
3344dd8b5abSYoshinobu Inoue 				usage();
3354dd8b5abSYoshinobu Inoue 			break;
3364dd8b5abSYoshinobu Inoue #endif
33781cb6ddcSMark Murray 		case '?':
33881cb6ddcSMark Murray 		default:
33981cb6ddcSMark Murray 			usage();
34081cb6ddcSMark Murray 			/* NOTREACHED */
34181cb6ddcSMark Murray 		}
34281cb6ddcSMark Murray 	}
34321f083c0SMark Murray 	if (autologin == -1)
34421f083c0SMark Murray 		autologin = (rlogin == _POSIX_VDISABLE) ? 0 : 1;
345bb330cd0SAssar Westerlund 
34681cb6ddcSMark Murray 	argc -= optind;
34781cb6ddcSMark Murray 	argv += optind;
34881cb6ddcSMark Murray 
34981cb6ddcSMark Murray 	if (argc) {
35042cf8219SRuslan Ermilov 		char *args[9], **argp = args;
35181cb6ddcSMark Murray 
35281cb6ddcSMark Murray 		if (argc > 2)
35381cb6ddcSMark Murray 			usage();
35481cb6ddcSMark Murray 		*argp++ = prompt;
35581cb6ddcSMark Murray 		if (user) {
3568fa113e5SMark Murray 			*argp++ = strdup("-l");
35781cb6ddcSMark Murray 			*argp++ = user;
35881cb6ddcSMark Murray 		}
35942cf8219SRuslan Ermilov 		if (src_addr) {
3608fa113e5SMark Murray 			*argp++ = strdup("-s");
36142cf8219SRuslan Ermilov 			*argp++ = src_addr;
36242cf8219SRuslan Ermilov 		}
36381cb6ddcSMark Murray 		*argp++ = argv[0];		/* host */
36481cb6ddcSMark Murray 		if (argc > 1)
36581cb6ddcSMark Murray 			*argp++ = argv[1];	/* port */
36681cb6ddcSMark Murray 		*argp = 0;
36781cb6ddcSMark Murray 
36881cb6ddcSMark Murray 		if (setjmp(toplevel) != 0)
36981cb6ddcSMark Murray 			Exit(0);
37081cb6ddcSMark Murray 		if (tn(argp - args, args) == 1)
37181cb6ddcSMark Murray 			return (0);
37281cb6ddcSMark Murray 		else
37381cb6ddcSMark Murray 			return (1);
37481cb6ddcSMark Murray 	}
37581cb6ddcSMark Murray 	(void)setjmp(toplevel);
37681cb6ddcSMark Murray 	for (;;) {
37781cb6ddcSMark Murray 			command(1, 0, 0);
37881cb6ddcSMark Murray 	}
37904c426ccSMark Murray 	return 0;
38081cb6ddcSMark Murray }
381