sysctl.c revision 1.53
1/*	$OpenBSD: sysctl.c,v 1.53 2000/06/30 16:00:10 millert Exp $	*/
2/*	$NetBSD: sysctl.c,v 1.9 1995/09/30 07:12:50 thorpej Exp $	*/
3
4/*
5 * Copyright (c) 1993
6 *	The Regents of the University of California.  All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 *    must display the following acknowledgement:
18 *	This product includes software developed by the University of
19 *	California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 *    may be used to endorse or promote products derived from this software
22 *    without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 */
36
37#ifndef lint
38static char copyright[] =
39"@(#) Copyright (c) 1993\n\
40	The Regents of the University of California.  All rights reserved.\n";
41#endif /* not lint */
42
43#ifndef lint
44#if 0
45static char sccsid[] = "@(#)sysctl.c	8.5 (Berkeley) 5/9/95";
46#else
47static char *rcsid = "$OpenBSD: sysctl.c,v 1.53 2000/06/30 16:00:10 millert Exp $";
48#endif
49#endif /* not lint */
50
51#include <sys/param.h>
52#include <sys/gmon.h>
53#include <sys/mount.h>
54#include <sys/stat.h>
55#include <sys/sysctl.h>
56#include <sys/socket.h>
57#include <vm/vm_param.h>
58#include <machine/cpu.h>
59#include <net/route.h>
60
61#include <netinet/in.h>
62#include <netinet/in_systm.h>
63#include <netinet/ip.h>
64#include <netinet/in_pcb.h>
65#include <netinet/ip_icmp.h>
66#include <netinet/ip_ipip.h>
67#include <netinet/ip_ether.h>
68#include <netinet/ip_ah.h>
69#include <netinet/ip_esp.h>
70#include <netinet/icmp_var.h>
71#include <netinet/ip_var.h>
72#include <netinet/udp.h>
73#include <netinet/udp_var.h>
74#include <netinet/tcp.h>
75#include <netinet/tcp_timer.h>
76#include <netinet/tcp_var.h>
77#include <netinet/ip_gre.h>
78
79#ifdef INET6
80#include <netinet/ip6.h>
81#include <netinet/icmp6.h>
82#include <netinet6/ip6_var.h>
83#include <netinet6/pim6_var.h>
84#endif
85
86#ifdef UVM
87#include <uvm/uvm_swap_encrypt.h>
88#endif
89
90#include <ufs/ufs/quota.h>
91#include <ufs/ufs/inode.h>
92#include <ufs/ffs/fs.h>
93#include <ufs/ffs/ffs_extern.h>
94
95#include <nfs/rpcv2.h>
96#include <nfs/nfsproto.h>
97#include <nfs/nfs.h>
98
99#include <netipx/ipx.h>
100#include <netipx/ipx_var.h>
101#include <netipx/spx_var.h>
102#include <ddb/db_var.h>
103#include <dev/rndvar.h>
104
105#include <err.h>
106#include <errno.h>
107#include <stdio.h>
108#include <stdlib.h>
109#include <string.h>
110#include <ctype.h>
111
112#ifdef CPU_BIOS
113#include <machine/biosvar.h>
114#endif
115
116struct ctlname topname[] = CTL_NAMES;
117struct ctlname kernname[] = CTL_KERN_NAMES;
118struct ctlname vmname[] = CTL_VM_NAMES;
119struct ctlname fsname[] = CTL_FS_NAMES;
120struct ctlname netname[] = CTL_NET_NAMES;
121struct ctlname hwname[] = CTL_HW_NAMES;
122struct ctlname username[] = CTL_USER_NAMES;
123struct ctlname debugname[CTL_DEBUG_MAXID];
124struct ctlname *vfsname;
125#ifdef CTL_MACHDEP_NAMES
126struct ctlname machdepname[] = CTL_MACHDEP_NAMES;
127#endif
128struct ctlname ddbname[] = CTL_DDB_NAMES;
129char names[BUFSIZ];
130int lastused;
131
132struct list {
133	struct	ctlname *list;
134	int	size;
135};
136struct list toplist = { topname, CTL_MAXID };
137struct list secondlevel[] = {
138	{ 0, 0 },			/* CTL_UNSPEC */
139	{ kernname, KERN_MAXID },	/* CTL_KERN */
140	{ vmname, VM_MAXID },		/* CTL_VM */
141	{ fsname, FS_MAXID },		/* CTL_FS */
142	{ netname, NET_MAXID },		/* CTL_NET */
143	{ 0, CTL_DEBUG_MAXID },		/* CTL_DEBUG */
144	{ hwname, HW_MAXID },		/* CTL_HW */
145#ifdef CTL_MACHDEP_NAMES
146	{ machdepname, CPU_MAXID },	/* CTL_MACHDEP */
147#else
148	{ 0, 0 },			/* CTL_MACHDEP */
149#endif
150	{ username, USER_MAXID },	/* CTL_USER_NAMES */
151	{ ddbname, DBCTL_MAXID },	/* CTL_DDB_NAMES */
152	{ 0, 0 },			/* CTL_VFS */
153};
154
155int	Aflag, aflag, nflag, wflag;
156
157/*
158 * Variables requiring special processing.
159 */
160#define	CLOCK		0x00000001
161#define	BOOTTIME	0x00000002
162#define	CHRDEV		0x00000004
163#define	BLKDEV		0x00000008
164#define	RNDSTATS	0x00000010
165#define	BADDYNAMIC	0x00000020
166#define	BIOSGEO		0x00000040
167#define	BIOSDEV		0x00000080
168#define	MAJ2DEV		0x00000100
169#define	UNSIGNED	0x00000200
170
171/* prototypes */
172void debuginit __P((void));
173void listall __P((char *, struct list *));
174void parse __P((char *, int));
175void parse_baddynamic __P((int *, size_t, char *, void **, size_t *, int, int));
176void usage __P((void));
177int findname __P((char *, char *, char **, struct list *));
178int sysctl_inet __P((char *, char **, int *, int, int *));
179#ifdef INET6
180int sysctl_inet6 __P((char *, char **, int *, int, int *));
181#endif
182int sysctl_ipx __P((char *, char **, int *, int, int *));
183int sysctl_fs __P((char *, char **, int *, int, int *));
184static int sysctl_vfs __P((char *, char **, int[], int, int *));
185static int sysctl_vfsgen __P((char *, char **, int[], int, int *));
186int sysctl_bios __P((char *, char **, int *, int, int *));
187int sysctl_swpenc __P((char *, char **, int *, int, int *));
188void vfsinit __P((void));
189
190int
191main(argc, argv)
192	int argc;
193	char *argv[];
194{
195	int ch, lvl1;
196
197	while ((ch = getopt(argc, argv, "Aanw")) != -1) {
198		switch (ch) {
199
200		case 'A':
201			Aflag = 1;
202			break;
203
204		case 'a':
205			aflag = 1;
206			break;
207
208		case 'n':
209			nflag = 1;
210			break;
211
212		case 'w':
213			wflag = 1;
214			break;
215
216		default:
217			usage();
218		}
219	}
220	argc -= optind;
221	argv += optind;
222
223	if (argc == 0 && (Aflag || aflag)) {
224		debuginit();
225		vfsinit();
226		for (lvl1 = 1; lvl1 < CTL_MAXID; lvl1++)
227			listall(topname[lvl1].ctl_name, &secondlevel[lvl1]);
228		exit(0);
229	}
230	if (argc == 0)
231		usage();
232	for (; *argv != NULL; ++argv)
233		parse(*argv, 1);
234	exit(0);
235}
236
237/*
238 * List all variables known to the system.
239 */
240void
241listall(prefix, lp)
242	char *prefix;
243	struct list *lp;
244{
245	int lvl2;
246	char *cp, name[BUFSIZ];
247
248	if (lp->list == NULL)
249		return;
250	(void)strncpy(name, prefix, BUFSIZ-1);
251	name[BUFSIZ-1] = '\0';
252	cp = &name[strlen(name)];
253	*cp++ = '.';
254	for (lvl2 = 0; lvl2 < lp->size; lvl2++) {
255		if (lp->list[lvl2].ctl_name == NULL)
256			continue;
257		(void)strcpy(cp, lp->list[lvl2].ctl_name);
258		parse(name, Aflag);
259	}
260}
261
262/*
263 * Parse a name into a MIB entry.
264 * Lookup and print out the MIB entry if it exists.
265 * Set a new value if requested.
266 */
267void
268parse(string, flags)
269	char *string;
270	int flags;
271{
272	int indx, type, state, intval, len;
273	size_t size, newsize = 0;
274	int special = 0;
275	void *newval = 0;
276	quad_t quadval;
277	struct list *lp;
278	int mib[CTL_MAXNAME];
279	char *cp, *bufp, buf[BUFSIZ];
280
281	(void)strncpy(buf, string, sizeof(buf) - 1);
282	buf[sizeof(buf) - 1] = '\0';
283	bufp = buf;
284	if ((cp = strchr(string, '=')) != NULL) {
285		if (!wflag)
286			errx(2, "must specify -w to set variables");
287		*strchr(buf, '=') = '\0';
288		*cp++ = '\0';
289		while (isspace(*cp))
290			cp++;
291		newval = cp;
292		newsize = strlen(cp);
293	}
294	if ((indx = findname(string, "top", &bufp, &toplist)) == -1)
295		return;
296	mib[0] = indx;
297	if (indx == CTL_VFS)
298		vfsinit();
299	if (indx == CTL_DEBUG)
300		debuginit();
301	lp = &secondlevel[indx];
302	if (lp->list == 0) {
303		warnx("%s: class is not implemented", topname[indx].ctl_name);
304		return;
305	}
306	if (bufp == NULL) {
307		listall(topname[indx].ctl_name, lp);
308		return;
309	}
310	if ((indx = findname(string, "second", &bufp, lp)) == -1)
311		return;
312	mib[1] = indx;
313	type = lp->list[indx].ctl_type;
314	len = 2;
315	switch (mib[0]) {
316
317	case CTL_KERN:
318		switch (mib[1]) {
319		case KERN_PROF:
320			mib[2] = GPROF_STATE;
321			size = sizeof(state);
322			if (sysctl(mib, 3, &state, &size, NULL, 0) == -1) {
323				if (flags == 0)
324					return;
325				if (!nflag)
326					(void)printf("%s: ", string);
327				(void)puts("kernel is not compiled for profiling");
328				return;
329			}
330			if (!nflag)
331				(void)printf("%s = %s\n", string,
332				    state == GMON_PROF_OFF ? "off" : "running");
333			return;
334		case KERN_VNODE:
335		case KERN_FILE:
336			if (flags == 0)
337				return;
338			warnx("use pstat to view %s information", string);
339			return;
340		case KERN_PROC:
341			if (flags == 0)
342				return;
343			warnx("use ps to view %s information", string);
344			return;
345		case KERN_NTPTIME:
346			if (flags == 0)
347				return;
348			warnx("use xntpdc to view %s information", string);
349			return;
350		case KERN_CLOCKRATE:
351			special |= CLOCK;
352			break;
353		case KERN_BOOTTIME:
354			special |= BOOTTIME;
355			break;
356		case KERN_RND:
357			special |= RNDSTATS;
358			break;
359		case KERN_HOSTID:
360		case KERN_ARND:
361			special |= UNSIGNED;
362			break;
363		}
364		break;
365
366	case CTL_HW:
367		break;
368
369	case CTL_VM:
370		if (mib[1] == VM_LOADAVG) {
371			double loads[3];
372
373			getloadavg(loads, 3);
374			if (!nflag)
375				(void)printf("%s = ", string);
376			(void)printf("%.2f %.2f %.2f\n", loads[0],
377			    loads[1], loads[2]);
378			return;
379		} else if (mib[1] == VM_PSSTRINGS) {
380			struct _ps_strings _ps;
381
382			len = sizeof(_ps);
383			if (sysctl(mib, 2, &_ps, &len, NULL, 0) == -1) {
384				if (flags == 0)
385					return;
386				if (!nflag)
387					(void)printf("%s: ", string);
388				(void)puts("can't find ps strings");
389				return;
390			}
391			if (!nflag)
392				(void)printf("%s = ", string);
393			(void)printf("%p\n", _ps.val);
394			return;
395		}
396#ifdef UVM
397		else if (mib[1] == VM_SWAPENCRYPT) {
398			len = sysctl_swpenc(string, &bufp, mib, flags, &type);
399			if (len < 0)
400				return;
401
402			break;
403		}
404#endif
405		if (flags == 0)
406			return;
407		warnx("use vmstat or systat to view %s information", string);
408		return;
409
410		break;
411
412	case CTL_NET:
413		if (mib[1] == PF_INET) {
414			len = sysctl_inet(string, &bufp, mib, flags, &type);
415			if (len < 0)
416				return;
417
418			if ((mib[2] == IPPROTO_TCP &&
419			     mib[3] == TCPCTL_BADDYNAMIC) ||
420			    (mib[2] == IPPROTO_UDP &&
421			     mib[3] == UDPCTL_BADDYNAMIC)) {
422
423				special |= BADDYNAMIC;
424
425				if (newval != NULL)
426					parse_baddynamic(mib, len, string,
427					    &newval, &newsize, flags, nflag);
428			}
429			break;
430		}
431#ifdef INET6
432		if (mib[1] == PF_INET6) {
433			len = sysctl_inet6(string, &bufp, mib, flags, &type);
434			if (len < 0)
435				return;
436
437			break;
438		}
439#endif
440		if (mib[1] == PF_IPX) {
441			len = sysctl_ipx(string, &bufp, mib, flags, &type);
442			if (len >= 0)
443				break;
444			return;
445		}
446		if (flags == 0)
447			return;
448		warnx("use netstat to view %s information", string);
449		return;
450
451	case CTL_DEBUG:
452		mib[2] = CTL_DEBUG_VALUE;
453		len = 3;
454		break;
455
456	case CTL_MACHDEP:
457#ifdef CPU_CONSDEV
458		if (mib[1] == CPU_CONSDEV)
459			special |= CHRDEV;
460#endif
461#ifdef CPU_BLK2CHR
462		if (mib[1] == CPU_BLK2CHR) {
463			if (bufp == NULL)
464				return;
465			mib[2] = makedev(atoi(bufp),0);
466			bufp = NULL;
467			len = 3;
468			special |= CHRDEV;
469			break;
470		}
471#endif
472#ifdef CPU_CHR2BLK
473		if (mib[1] == CPU_CHR2BLK) {
474			if (bufp == NULL)
475				return;
476			mib[2] = makedev(atoi(bufp),0);
477			bufp = NULL;
478			len = 3;
479			special |= BLKDEV;
480			break;
481		}
482#endif
483#ifdef CPU_BIOS
484		if (mib[1] == CPU_BIOS) {
485			len = sysctl_bios(string, &bufp, mib, flags, &type);
486			if (len < 0)
487				return;
488			if (mib[2] == BIOS_DEV)
489				special |= BIOSDEV;
490			if (mib[2] == BIOS_DISKINFO)
491				special |= BIOSGEO;
492			break;
493		}
494#endif
495		break;
496
497	case CTL_FS:
498		len = sysctl_fs(string, &bufp, mib, flags, &type);
499		if (len >= 0)
500			break;
501		return;
502
503	case CTL_VFS:
504		if (mib[1])
505			len = sysctl_vfs(string, &bufp, mib, flags, &type);
506		else
507			len = sysctl_vfsgen(string, &bufp, mib, flags, &type);
508		if (len >= 0) {
509			if (type == CTLTYPE_STRUCT) {
510				if (flags)
511					warnx("use nfsstat to view %s information",
512					    MOUNT_NFS);
513				return;
514			} else
515				break;
516		}
517		return;
518
519	case CTL_USER:
520	case CTL_DDB:
521		break;
522
523	default:
524		warnx("illegal top level value: %d", mib[0]);
525		return;
526
527	}
528	if (bufp) {
529		warnx("name %s in %s is unknown", bufp, string);
530		return;
531	}
532	if (newsize > 0) {
533		switch (type) {
534		case CTLTYPE_INT:
535			errno = 0;
536			if (special & UNSIGNED)
537				intval = strtoul(newval, &cp, 10);
538			else
539				intval = strtol(newval, &cp, 10);
540			if (*cp != '\0') {
541				warnx("%s: illegal value: %s", string,
542				    (char *)newval);
543				return;
544			}
545			if (errno == ERANGE) {
546				warnx("%s: value %s out of range", string,
547				    (char *)newval);
548				return;
549			}
550			newval = &intval;
551			newsize = sizeof(intval);
552			break;
553
554		case CTLTYPE_QUAD:
555			(void)sscanf(newval, "%qd", &quadval);
556			newval = &quadval;
557			newsize = sizeof(quadval);
558			break;
559		}
560	}
561	size = BUFSIZ;
562	if (sysctl(mib, len, buf, &size, newsize ? newval : 0, newsize) == -1) {
563		if (flags == 0)
564			return;
565		switch (errno) {
566		case EOPNOTSUPP:
567			warnx("%s: value is not available", string);
568			return;
569		case ENOTDIR:
570			warnx("%s: specification is incomplete", string);
571			return;
572		case ENOMEM:
573			warnx("%s: type is unknown to this program", string);
574			return;
575		case ENXIO:
576			if (special & BIOSGEO)
577				return;
578		default:
579			warn("%s", string);
580			return;
581		}
582	}
583	if (special & CLOCK) {
584		struct clockinfo *clkp = (struct clockinfo *)buf;
585
586		if (!nflag)
587			(void)printf("%s = ", string);
588		(void)printf(
589		    "tick = %d, tickadj = %d, hz = %d, profhz = %d, stathz = %d\n",
590		    clkp->tick, clkp->tickadj, clkp->hz, clkp->profhz, clkp->stathz);
591		return;
592	}
593	if (special & BOOTTIME) {
594		struct timeval *btp = (struct timeval *)buf;
595		time_t boottime;
596
597		if (!nflag) {
598			boottime = btp->tv_sec;
599			(void)printf("%s = %s", string, ctime(&boottime));
600		} else
601			(void)printf("%ld\n", btp->tv_sec);
602		return;
603	}
604	if (special & BLKDEV) {
605		dev_t dev = *(dev_t *)buf;
606
607		if (!nflag)
608			(void)printf("%s = %s\n", string,
609			    devname(dev, S_IFBLK));
610		else
611			(void)printf("0x%x\n", dev);
612		return;
613	}
614	if (special & CHRDEV) {
615		dev_t dev = *(dev_t *)buf;
616
617		if (!nflag)
618			(void)printf("%s = %s\n", string,
619			    devname(dev, S_IFCHR));
620		else
621			(void)printf("0x%x\n", dev);
622		return;
623	}
624#ifdef CPU_BIOS
625	if (special & BIOSGEO) {
626		bios_diskinfo_t *pdi = (bios_diskinfo_t *)buf;
627
628		if (!nflag)
629			(void)printf("%s = ", string);
630		(void)printf("bootdev = 0x%x, "
631			     "cylinders = %u, heads = %u, sectors = %u\n",
632			     pdi->bsd_dev, pdi->bios_cylinders, pdi->bios_heads,
633			     pdi->bios_sectors);
634		return;
635	}
636	if (special & BIOSDEV) {
637		int dev = *(int*)buf;
638
639		if (!nflag)
640			(void)printf("%s = ", string);
641		(void) printf("0x%02x\n", dev);
642		return;
643	}
644#endif
645	if (special & UNSIGNED) {
646		if (newsize == 0) {
647			if (!nflag)
648				(void)printf("%s = ", string);
649			(void)printf("%u\n", *(u_int *)buf);
650		} else {
651			if (!nflag)
652				(void)printf("%s: %u -> ", string,
653				    *(u_int *)buf);
654			(void)printf("%u\n", *(u_int *)newval);
655		}
656		return;
657	}
658	if (special & RNDSTATS) {
659		struct rndstats *rndstats = (struct rndstats *)buf;
660		int i;
661
662		if (!nflag)
663			(void)printf("%s = ", string);
664		(void)printf(
665		"%qu %qu %qu %qu %qu %qu %qu %qu %qu %qu %qu %qu %qu %qu %qu %qu",
666		    rndstats->rnd_total,
667		    rndstats->rnd_used, rndstats->rnd_reads,
668		    rndstats->arc4_reads, rndstats->arc4_nstirs,
669		    rndstats->arc4_stirs,
670		    rndstats->rnd_pad[0],
671		    rndstats->rnd_pad[1],
672		    rndstats->rnd_pad[2],
673		    rndstats->rnd_pad[3],
674		    rndstats->rnd_pad[4],
675		    rndstats->rnd_waits,
676		    rndstats->rnd_enqs, rndstats->rnd_deqs,
677		    rndstats->rnd_drops, rndstats->rnd_drople);
678		for (i = 0; i < sizeof(rndstats->rnd_ed)/sizeof(rndstats->rnd_ed[0]); i++)
679			(void)printf(" %qu", rndstats->rnd_ed[i]);
680		for (i = 0; i < sizeof(rndstats->rnd_sc)/sizeof(rndstats->rnd_sc[0]); i++)
681			(void)printf(" %qu", rndstats->rnd_sc[i]);
682		for (i = 0; i < sizeof(rndstats->rnd_sb)/sizeof(rndstats->rnd_sb[0]); i++)
683			(void)printf(" %qu", rndstats->rnd_sb[i]);
684		printf("\n");
685		return;
686	}
687	if (special & BADDYNAMIC) {
688		in_port_t port, lastport;
689		u_int32_t *baddynamic = (u_int32_t *)buf;
690
691		if (!nflag)
692			(void)printf("%s%s", string, newsize ? ": " : " = ");
693		lastport = 0;
694		for (port = IPPORT_RESERVED/2; port < IPPORT_RESERVED; port++)
695			if (DP_ISSET(baddynamic, port)) {
696				(void)printf("%s%hd", lastport ? "," : "",
697				    port);
698				lastport = port;
699			}
700		if (newsize != 0) {
701			if (!nflag)
702				fputs(" -> ", stdout);
703			baddynamic = (u_int32_t *)newval;
704			lastport = 0;
705			for (port = IPPORT_RESERVED/2; port < IPPORT_RESERVED;
706			    port++)
707				if (DP_ISSET(baddynamic, port)) {
708					(void)printf("%s%hd",
709					    lastport ? "," : "", port);
710					lastport = port;
711				}
712		}
713		(void)putchar('\n');
714		return;
715	}
716	switch (type) {
717	case CTLTYPE_INT:
718		if (newsize == 0) {
719			if (!nflag)
720				(void)printf("%s = ", string);
721			(void)printf("%d\n", *(int *)buf);
722		} else {
723			if (!nflag)
724				(void)printf("%s: %d -> ", string,
725				    *(int *)buf);
726			(void)printf("%d\n", *(int *)newval);
727		}
728		return;
729
730	case CTLTYPE_STRING:
731		if (newsize == 0) {
732			if (!nflag)
733				(void)printf("%s = ", string);
734			(void)puts(buf);
735		} else {
736			if (!nflag)
737				(void)printf("%s: %s -> ", string, buf);
738			(void)puts((char *)newval);
739		}
740		return;
741
742	case CTLTYPE_QUAD:
743		if (newsize == 0) {
744			if (!nflag)
745				(void)printf("%s = ", string);
746			(void)printf("%qd\n", *(quad_t *)buf);
747		} else {
748			if (!nflag)
749				(void)printf("%s: %qd -> ", string,
750				    *(quad_t *)buf);
751			(void)printf("%qd\n", *(quad_t *)newval);
752		}
753		return;
754
755	case CTLTYPE_STRUCT:
756		warnx("%s: unknown structure returned", string);
757		return;
758
759	default:
760	case CTLTYPE_NODE:
761		warnx("%s: unknown type returned", string);
762		return;
763	}
764}
765
766void
767parse_baddynamic(mib, len, string, newvalp, newsizep, flags, nflag)
768	int mib[];
769	size_t len;
770	char *string;
771	void **newvalp;
772	size_t *newsizep;
773	int flags;
774	int nflag;
775{
776	static u_int32_t newbaddynamic[DP_MAPSIZE];
777	in_port_t port;
778	size_t size;
779	char action, *cp;
780
781	if (strchr((char *)*newvalp, '+') || strchr((char *)*newvalp, '-')) {
782		size = sizeof(newbaddynamic);
783		if (sysctl(mib, len, newbaddynamic, &size, 0, 0) == -1) {
784			if (flags == 0)
785				return;
786			if (!nflag)
787				(void)printf("%s: ", string);
788			(void)puts("kernel does contain bad dynamic port tables");
789			return;
790		}
791
792		while (*newvalp && (cp = strsep((char **)newvalp, ", \t")) && *cp) {
793			if (*cp != '+' && *cp != '-')
794				errx(1, "cannot mix +/- with full list");
795			action = *cp++;
796			port = atoi(cp);
797			if (port < IPPORT_RESERVED/2 || port >= IPPORT_RESERVED)
798				errx(1, "invalid port, range is %d to %d",
799				    IPPORT_RESERVED/2, IPPORT_RESERVED-1);
800			if (action == '+')
801				DP_SET(newbaddynamic, port);
802			else
803				DP_CLR(newbaddynamic, port);
804		}
805	} else {
806		(void)memset((void *)newbaddynamic, 0, sizeof(newbaddynamic));
807		while (*newvalp && (cp = strsep((char **)newvalp, ", \t")) && *cp) {
808			port = atoi(cp);
809			if (port < IPPORT_RESERVED/2 || port >= IPPORT_RESERVED)
810				errx(1, "invalid port, range is %d to %d",
811				    IPPORT_RESERVED/2, IPPORT_RESERVED-1);
812			DP_SET(newbaddynamic, port);
813		}
814	}
815
816	*newvalp = (void *)newbaddynamic;
817	*newsizep = sizeof(newbaddynamic);
818}
819
820/*
821 * Initialize the set of debugging names
822 */
823void
824debuginit()
825{
826	int mib[3], loc, i;
827	size_t size;
828
829	if (secondlevel[CTL_DEBUG].list != 0)
830		return;
831	secondlevel[CTL_DEBUG].list = debugname;
832	mib[0] = CTL_DEBUG;
833	mib[2] = CTL_DEBUG_NAME;
834	for (loc = lastused, i = 0; i < CTL_DEBUG_MAXID; i++) {
835		mib[1] = i;
836		size = BUFSIZ - loc;
837		if (sysctl(mib, 3, &names[loc], &size, NULL, 0) == -1)
838			continue;
839		debugname[i].ctl_name = &names[loc];
840		debugname[i].ctl_type = CTLTYPE_INT;
841		loc += size;
842	}
843	lastused = loc;
844}
845
846struct ctlname vfsgennames[] = CTL_VFSGENCTL_NAMES;
847struct ctlname ffsname[] = FFS_NAMES;
848struct ctlname nfsname[] = FS_NFS_NAMES;
849struct list *vfsvars;
850int *vfs_typenums;
851
852/*
853 * Initialize the set of filesystem names
854 */
855void
856vfsinit()
857{
858	int mib[4], maxtypenum, cnt, loc, size;
859	struct vfsconf vfc;
860	size_t buflen;
861
862	if (secondlevel[CTL_VFS].list != 0)
863		return;
864	mib[0] = CTL_VFS;
865	mib[1] = VFS_GENERIC;
866	mib[2] = VFS_MAXTYPENUM;
867	buflen = 4;
868	if (sysctl(mib, 3, &maxtypenum, &buflen, (void *)0, (size_t)0) < 0)
869		return;
870	maxtypenum++;	/* + generic */
871	if ((vfs_typenums = malloc(maxtypenum * sizeof(int))) == NULL)
872		return;
873	memset(vfs_typenums, 0, maxtypenum * sizeof(int));
874	if ((vfsvars = malloc(maxtypenum * sizeof(*vfsvars))) == NULL) {
875		free(vfs_typenums);
876		return;
877	}
878	memset(vfsvars, 0, maxtypenum * sizeof(*vfsvars));
879	if ((vfsname = malloc(maxtypenum * sizeof(*vfsname))) == NULL) {
880		free(vfs_typenums);
881		free(vfsvars);
882		return;
883	}
884	memset(vfsname, 0, maxtypenum * sizeof(*vfsname));
885	mib[2] = VFS_CONF;
886	buflen = sizeof vfc;
887	for (loc = lastused, cnt = 1; cnt < maxtypenum; cnt++) {
888		mib[3] = cnt - 1;
889		if (sysctl(mib, 4, &vfc, &buflen, (void *)0, (size_t)0) < 0) {
890			if (errno == EOPNOTSUPP)
891				continue;
892			warn("vfsinit");
893			free(vfsname);
894			return;
895		}
896		if (!strcmp(vfc.vfc_name, MOUNT_FFS)) {
897			vfsvars[cnt].list = ffsname;
898			vfsvars[cnt].size = FFS_MAXID;
899		}
900		if (!strcmp(vfc.vfc_name, MOUNT_NFS)) {
901			vfsvars[cnt].list = nfsname;
902			vfsvars[cnt].size = NFS_MAXID;
903		}
904		vfs_typenums[cnt] = vfc.vfc_typenum;
905		strcat(&names[loc], vfc.vfc_name);
906		vfsname[cnt].ctl_name = &names[loc];
907		vfsname[cnt].ctl_type = CTLTYPE_NODE;
908		size = strlen(vfc.vfc_name) + 1;
909		loc += size;
910	}
911	lastused = loc;
912
913	vfsname[0].ctl_name = "mounts";
914	vfsname[0].ctl_type = CTLTYPE_NODE;
915	vfsvars[0].list = vfsname + 1;
916	vfsvars[0].size = maxtypenum - 1;
917
918	secondlevel[CTL_VFS].list = vfsname;
919	secondlevel[CTL_VFS].size = maxtypenum;
920	return;
921}
922
923int
924sysctl_vfsgen(string, bufpp, mib, flags, typep)
925	char *string;
926	char **bufpp;
927	int mib[];
928	int flags;
929	int *typep;
930{
931	int indx;
932	size_t size;
933	struct vfsconf vfc;
934
935	if (*bufpp == NULL) {
936		listall(string, vfsvars);
937		return (-1);
938	}
939
940	if ((indx = findname(string, "third", bufpp, vfsvars)) == -1)
941		return (-1);
942
943	mib[1] = VFS_GENERIC;
944	mib[2] = VFS_CONF;
945	mib[3] = indx;
946	size = sizeof vfc;
947	if (sysctl(mib, 4, &vfc, &size, (void *)0, (size_t)0) < 0) {
948		if (errno != EOPNOTSUPP)
949			warn("vfs print");
950		return -1;
951	}
952	if (flags == 0 && vfc.vfc_refcount == 0)
953		return -1;
954	if (!nflag)
955		fprintf(stdout, "%s has %d mounted instance%s\n",
956		    string, vfc.vfc_refcount,
957		    vfc.vfc_refcount != 1 ? "s" : "");
958	else
959		fprintf(stdout, "%d\n", vfc.vfc_refcount);
960
961	return -1;
962}
963
964int
965sysctl_vfs(string, bufpp, mib, flags, typep)
966	char *string;
967	char **bufpp;
968	int mib[];
969	int flags;
970	int *typep;
971{
972	struct list *lp = &vfsvars[mib[1]];
973	int indx;
974
975	if (lp->list == NULL) {
976		if (flags)
977			warnx("No variables defined for file system %s", string);
978		return(-1);
979	}
980	if (*bufpp == NULL) {
981		listall(string, lp);
982		return (-1);
983	}
984	if ((indx = findname(string, "third", bufpp, lp)) == -1)
985		return (-1);
986
987	mib[1] = vfs_typenums[mib[1]];
988	mib[2] = indx;
989	*typep = lp->list[indx].ctl_type;
990	return (3);
991}
992
993struct ctlname posixname[] = CTL_FS_POSIX_NAMES;
994struct list fslist = { posixname, FS_POSIX_MAXID };
995
996/*
997 * handle file system requests
998 */
999int
1000sysctl_fs(string, bufpp, mib, flags, typep)
1001	char *string;
1002	char **bufpp;
1003	int mib[];
1004	int flags;
1005	int *typep;
1006{
1007	int indx;
1008
1009	if (*bufpp == NULL) {
1010		listall(string, &fslist);
1011		return(-1);
1012	}
1013	if ((indx = findname(string, "third", bufpp, &fslist)) == -1)
1014		return(-1);
1015	mib[2] = indx;
1016	*typep = fslist.list[indx].ctl_type;
1017	return(3);
1018}
1019
1020#ifdef CPU_BIOS
1021struct ctlname biosname[] = CTL_BIOS_NAMES;
1022struct list bioslist = { biosname, BIOS_MAXID };
1023
1024/*
1025 * handle BIOS requests
1026 */
1027int
1028sysctl_bios(string, bufpp, mib, flags, typep)
1029	char *string;
1030	char **bufpp;
1031	int mib[];
1032	int flags;
1033	int *typep;
1034{
1035	char *name;
1036	int indx;
1037
1038	if (*bufpp == NULL) {
1039		listall(string, &bioslist);
1040		return(-1);
1041	}
1042	if ((indx = findname(string, "third", bufpp, &bioslist)) == -1)
1043		return(-1);
1044	mib[2] = indx;
1045	if (indx == BIOS_DISKINFO) {
1046		if (*bufpp == NULL) {
1047			char name[BUFSIZ];
1048
1049			/* scan all the bios devices */
1050			for (indx = 0; indx < 256; indx++) {
1051				snprintf(name, sizeof(name), "%s.%u",
1052					 string, indx);
1053				parse(name, 1);
1054			}
1055			return(-1);
1056		}
1057		if ((name = strsep(bufpp, ".")) == NULL) {
1058			warnx("%s: incomplete specification", string);
1059			return(-1);
1060		}
1061		mib[3] = atoi(name);
1062		*typep = CTLTYPE_STRUCT;
1063		return 4;
1064	} else {
1065		*typep = bioslist.list[indx].ctl_type;
1066		return(3);
1067	}
1068}
1069#endif
1070
1071#ifdef UVM
1072struct ctlname swpencname[] = CTL_SWPENC_NAMES;
1073struct list swpenclist = { swpencname, SWPENC_MAXID };
1074
1075/*
1076 * handle swap encrypt requests
1077 */
1078int
1079sysctl_swpenc(string, bufpp, mib, flags, typep)
1080	char *string;
1081	char **bufpp;
1082	int mib[];
1083	int flags;
1084	int *typep;
1085{
1086	char *name;
1087	int indx;
1088
1089	if (*bufpp == NULL) {
1090		listall(string, &swpenclist);
1091		return(-1);
1092	}
1093	if ((indx = findname(string, "third", bufpp, &swpenclist)) == -1)
1094		return(-1);
1095	mib[2] = indx;
1096	*typep = swpenclist.list[indx].ctl_type;
1097	return(3);
1098}
1099#endif
1100
1101struct ctlname inetname[] = CTL_IPPROTO_NAMES;
1102struct ctlname ipname[] = IPCTL_NAMES;
1103struct ctlname icmpname[] = ICMPCTL_NAMES;
1104struct ctlname ipipname[] = IPIPCTL_NAMES;
1105struct ctlname tcpname[] = TCPCTL_NAMES;
1106struct ctlname udpname[] = UDPCTL_NAMES;
1107struct ctlname espname[] = ESPCTL_NAMES;
1108struct ctlname ahname[] = AHCTL_NAMES;
1109struct ctlname etheripname[] = ETHERIPCTL_NAMES;
1110struct ctlname grename[] = GRECTL_NAMES;
1111struct ctlname mobileipname[] = MOBILEIPCTL_NAMES;
1112struct list inetlist = { inetname, IPPROTO_MAXID };
1113struct list inetvars[] = {
1114	{ ipname, IPCTL_MAXID },	/* ip */
1115	{ icmpname, ICMPCTL_MAXID },	/* icmp */
1116	{ 0, 0 },			/* igmp */
1117	{ 0, 0 },			/* ggmp */
1118	{ ipipname, IPIPCTL_MAXID },	/* ipencap */
1119	{ 0, 0 },
1120	{ tcpname, TCPCTL_MAXID },	/* tcp */
1121	{ 0, 0 },
1122	{ 0, 0 },			/* egp */
1123	{ 0, 0 },
1124	{ 0, 0 },
1125	{ 0, 0 },
1126	{ 0, 0 },			/* pup */
1127	{ 0, 0 },
1128	{ 0, 0 },
1129	{ 0, 0 },
1130	{ 0, 0 },
1131	{ udpname, UDPCTL_MAXID },	/* udp */
1132	{ 0, 0 },
1133	{ 0, 0 },
1134	{ 0, 0 },
1135	{ 0, 0 },
1136	{ 0, 0 },
1137	{ 0, 0 },
1138	{ 0, 0 },
1139	{ 0, 0 },
1140	{ 0, 0 },
1141	{ 0, 0 },
1142	{ 0, 0 },
1143	{ 0, 0 },
1144	{ 0, 0 },
1145	{ 0, 0 },
1146	{ 0, 0 },
1147	{ 0, 0 },
1148	{ 0, 0 },
1149	{ 0, 0 },
1150	{ 0, 0 },
1151	{ 0, 0 },
1152	{ 0, 0 },
1153	{ 0, 0 },
1154	{ 0, 0 },
1155	{ 0, 0 },
1156	{ 0, 0 },
1157	{ 0, 0 },
1158	{ 0, 0 },
1159	{ 0, 0 },
1160	{ 0, 0 },
1161	{ grename, GRECTL_MAXID }, /* GRE */
1162	{ 0, 0 },
1163	{ 0, 0 },
1164	{ espname, ESPCTL_MAXID },	/* esp */
1165	{ ahname, AHCTL_MAXID },	/* ah */
1166	{ 0, 0 },
1167	{ 0, 0 },
1168	{ 0, 0 },
1169	{ mobileipname, MOBILEIPCTL_MAXID }, /* mobileip */
1170	{ 0, 0 },
1171	{ 0, 0 },
1172	{ 0, 0 },
1173	{ 0, 0 },
1174	{ 0, 0 },
1175	{ 0, 0 },
1176	{ 0, 0 },
1177	{ 0, 0 },
1178	{ 0, 0 },
1179	{ 0, 0 },
1180	{ 0, 0 },
1181	{ 0, 0 },
1182	{ 0, 0 },
1183	{ 0, 0 },
1184	{ 0, 0 },
1185	{ 0, 0 },
1186	{ 0, 0 },
1187	{ 0, 0 },
1188	{ 0, 0 },
1189	{ 0, 0 },
1190	{ 0, 0 },
1191	{ 0, 0 },
1192	{ 0, 0 },
1193	{ 0, 0 },
1194	{ 0, 0 },
1195	{ 0, 0 },
1196	{ 0, 0 },
1197	{ 0, 0 },
1198	{ 0, 0 },
1199	{ 0, 0 },
1200	{ 0, 0 },
1201	{ 0, 0 },
1202	{ 0, 0 },
1203	{ 0, 0 },
1204	{ 0, 0 },
1205	{ 0, 0 },
1206	{ 0, 0 },
1207	{ 0, 0 },
1208	{ 0, 0 },
1209	{ 0, 0 },
1210	{ 0, 0 },
1211	{ etheripname, ETHERIPCTL_MAXID },
1212};
1213
1214/*
1215 * handle internet requests
1216 */
1217int
1218sysctl_inet(string, bufpp, mib, flags, typep)
1219	char *string;
1220	char **bufpp;
1221	int mib[];
1222	int flags;
1223	int *typep;
1224{
1225	struct list *lp;
1226	int indx;
1227
1228	if (*bufpp == NULL) {
1229		listall(string, &inetlist);
1230		return(-1);
1231	}
1232	if ((indx = findname(string, "third", bufpp, &inetlist)) == -1)
1233		return(-1);
1234	mib[2] = indx;
1235	if (indx < IPPROTO_MAXID && inetvars[indx].list != NULL)
1236		lp = &inetvars[indx];
1237	else if (!flags)
1238		return(-1);
1239	else {
1240		warnx("%s: no variables defined for this protocol", string);
1241		return(-1);
1242	}
1243	if (*bufpp == NULL) {
1244		listall(string, lp);
1245		return(-1);
1246	}
1247	if ((indx = findname(string, "fourth", bufpp, lp)) == -1)
1248		return(-1);
1249	mib[3] = indx;
1250	*typep = lp->list[indx].ctl_type;
1251	return(4);
1252}
1253
1254#ifdef INET6
1255struct ctlname inet6name[] = CTL_IPV6PROTO_NAMES;
1256struct ctlname ip6name[] = IPV6CTL_NAMES;
1257struct ctlname icmp6name[] = ICMPV6CTL_NAMES;
1258struct ctlname pim6name[] = PIM6CTL_NAMES;
1259struct list inet6list = { inet6name, IPV6PROTO_MAXID };
1260struct list inet6vars[] = {
1261/*0*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1262	{ 0, 0 },
1263	{ 0, 0 },
1264	{ 0, 0 },
1265	{ 0, 0 },
1266	{ 0, 0 },
1267/*10*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1268	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1269/*20*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1270	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1271/*30*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1272	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1273/*40*/	{ 0, 0 },
1274	{ ip6name, IPV6CTL_MAXID },	/* ipv6 */
1275	{ 0, 0 },
1276	{ 0, 0 },
1277	{ 0, 0 },
1278	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1279/*50*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1280	{ 0, 0 },
1281	{ 0, 0 },
1282	{ 0, 0 },
1283	{ icmp6name, ICMPV6CTL_MAXID },	/* icmp6 */
1284	{ 0, 0 },
1285/*60*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1286	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1287/*70*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1288	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1289/*80*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1290	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1291/*90*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1292	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1293/*100*/	{ 0, 0 },
1294	{ 0, 0 },
1295	{ 0, 0 },
1296	{ pim6name, PIM6CTL_MAXID },	/* pim6 */
1297};
1298
1299/*
1300 * handle internet6 requests
1301 */
1302int
1303sysctl_inet6(string, bufpp, mib, flags, typep)
1304	char *string;
1305	char **bufpp;
1306	int mib[];
1307	int flags;
1308	int *typep;
1309{
1310	struct list *lp;
1311	int indx;
1312
1313	if (*bufpp == NULL) {
1314		listall(string, &inet6list);
1315		return(-1);
1316	}
1317	if ((indx = findname(string, "third", bufpp, &inet6list)) == -1)
1318		return(-1);
1319	mib[2] = indx;
1320	if (indx < IPV6PROTO_MAXID && inet6vars[indx].list != NULL)
1321		lp = &inet6vars[indx];
1322	else if (!flags)
1323		return(-1);
1324	else {
1325		warnx("%s: no variables defined for this protocol", string);
1326		return(-1);
1327	}
1328	if (*bufpp == NULL) {
1329		listall(string, lp);
1330		return(-1);
1331	}
1332	if ((indx = findname(string, "fourth", bufpp, lp)) == -1)
1333		return(-1);
1334	mib[3] = indx;
1335	*typep = lp->list[indx].ctl_type;
1336	return(4);
1337}
1338#endif
1339
1340struct ctlname ipxname[] = CTL_IPXPROTO_NAMES;
1341struct ctlname ipxpname[] = IPXCTL_NAMES;
1342struct ctlname spxpname[] = SPXCTL_NAMES;
1343struct list ipxlist = { ipxname, IPXCTL_MAXID };
1344struct list ipxvars[] = {
1345	{ ipxpname, IPXCTL_MAXID },	/* ipx */
1346	{ 0, 0 },
1347	{ 0, 0 },
1348	{ 0, 0 },
1349	{ 0, 0 },
1350	{ spxpname, SPXCTL_MAXID },
1351};
1352
1353/*
1354 * Handle internet requests
1355 */
1356int
1357sysctl_ipx(string, bufpp, mib, flags, typep)
1358	char *string;
1359	char **bufpp;
1360	int mib[];
1361	int flags;
1362	int *typep;
1363{
1364	struct list *lp;
1365	int indx;
1366
1367	if (*bufpp == NULL) {
1368		listall(string, &ipxlist);
1369		return(-1);
1370	}
1371	if ((indx = findname(string, "third", bufpp, &ipxlist)) == -1)
1372		return(-1);
1373	mib[2] = indx;
1374	if (indx <= IPXPROTO_SPX && ipxvars[indx].list != NULL)
1375		lp = &ipxvars[indx];
1376	else if (!flags)
1377		return(-1);
1378	else {
1379		warnx("%s: no variables defined for this protocol", string);
1380		return(-1);
1381	}
1382	if (*bufpp == NULL) {
1383		listall(string, lp);
1384		return(-1);
1385	}
1386	if ((indx = findname(string, "fourth", bufpp, lp)) == -1)
1387		return(-1);
1388	mib[3] = indx;
1389	*typep = lp->list[indx].ctl_type;
1390	return(4);
1391}
1392
1393/*
1394 * Scan a list of names searching for a particular name.
1395 */
1396int
1397findname(string, level, bufp, namelist)
1398	char *string;
1399	char *level;
1400	char **bufp;
1401	struct list *namelist;
1402{
1403	char *name;
1404	int i;
1405
1406	if (namelist->list == 0 || (name = strsep(bufp, ".")) == NULL) {
1407		warnx("%s: incomplete specification", string);
1408		return(-1);
1409	}
1410	for (i = 0; i < namelist->size; i++)
1411		if (namelist->list[i].ctl_name != NULL &&
1412		    strcmp(name, namelist->list[i].ctl_name) == 0)
1413			break;
1414	if (i == namelist->size) {
1415		warnx("%s level name %s in %s is invalid", level, name, string);
1416		return(-1);
1417	}
1418	return(i);
1419}
1420
1421void
1422usage()
1423{
1424
1425	(void)fprintf(stderr, "usage:\t%s\n\t%s\n\t%s\n\t%s\n",
1426	    "sysctl [-n] variable ...", "sysctl [-n] -w variable=value ...",
1427	    "sysctl [-n] -a", "sysctl [-n] -A");
1428	exit(1);
1429}
1430