sysctl.c revision 1.110
1/*	$OpenBSD: sysctl.c,v 1.110 2004/02/24 21:45:01 tedu 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. Neither the name of the University nor the names of its contributors
17 *    may be used to endorse or promote products derived from this software
18 *    without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33#ifndef lint
34static const char copyright[] =
35"@(#) Copyright (c) 1993\n\
36	The Regents of the University of California.  All rights reserved.\n";
37#endif /* not lint */
38
39#ifndef lint
40#if 0
41static const char sccsid[] = "@(#)sysctl.c	8.5 (Berkeley) 5/9/95";
42#else
43static const char rcsid[] = "$OpenBSD: sysctl.c,v 1.110 2004/02/24 21:45:01 tedu Exp $";
44#endif
45#endif /* not lint */
46
47#include <sys/param.h>
48#include <sys/gmon.h>
49#include <sys/mount.h>
50#include <sys/stat.h>
51#include <sys/sem.h>
52#include <sys/shm.h>
53#include <sys/sysctl.h>
54#include <sys/socket.h>
55#include <sys/malloc.h>
56#include <sys/dkstat.h>
57#include <sys/uio.h>
58#include <sys/tty.h>
59#include <sys/namei.h>
60#include <sys/sensors.h>
61#include <machine/cpu.h>
62#include <net/route.h>
63
64#include <netinet/in.h>
65#include <netinet/in_systm.h>
66#include <netinet/ip.h>
67#include <netinet/in_pcb.h>
68#include <netinet/ip_icmp.h>
69#include <netinet/ip_ipip.h>
70#include <netinet/ip_ether.h>
71#include <netinet/ip_ah.h>
72#include <netinet/ip_esp.h>
73#include <netinet/icmp_var.h>
74#include <netinet/ip_var.h>
75#include <netinet/udp.h>
76#include <netinet/udp_var.h>
77#include <netinet/tcp.h>
78#include <netinet/tcp_timer.h>
79#include <netinet/tcp_var.h>
80#include <netinet/ip_gre.h>
81#include <netinet/ip_ipcomp.h>
82#include <netinet/ip_carp.h>
83
84#ifdef INET6
85#include <netinet/ip6.h>
86#include <netinet/icmp6.h>
87#include <netinet6/ip6_var.h>
88#include <netinet6/pim6_var.h>
89#endif
90
91#include <uvm/uvm_swap_encrypt.h>
92
93#include <ufs/ufs/quota.h>
94#include <ufs/ufs/inode.h>
95#include <ufs/ffs/fs.h>
96#include <ufs/ffs/ffs_extern.h>
97
98#include <nfs/rpcv2.h>
99#include <nfs/nfsproto.h>
100#include <nfs/nfs.h>
101
102#include <netipx/ipx.h>
103#include <netipx/ipx_var.h>
104#include <netipx/spx_var.h>
105#include <ddb/db_var.h>
106#include <dev/rndvar.h>
107
108#include <err.h>
109#include <errno.h>
110#include <stdio.h>
111#include <stdlib.h>
112#include <string.h>
113#include <ctype.h>
114
115#ifdef CPU_BIOS
116#include <machine/biosvar.h>
117#endif
118
119struct ctlname topname[] = CTL_NAMES;
120struct ctlname kernname[] = CTL_KERN_NAMES;
121struct ctlname vmname[] = CTL_VM_NAMES;
122struct ctlname fsname[] = CTL_FS_NAMES;
123struct ctlname netname[] = CTL_NET_NAMES;
124struct ctlname hwname[] = CTL_HW_NAMES;
125struct ctlname username[] = CTL_USER_NAMES;
126struct ctlname debugname[CTL_DEBUG_MAXID];
127struct ctlname kernmallocname[] = CTL_KERN_MALLOC_NAMES;
128struct ctlname forkstatname[] = CTL_KERN_FORKSTAT_NAMES;
129struct ctlname nchstatsname[] = CTL_KERN_NCHSTATS_NAMES;
130struct ctlname ttyname[] = CTL_KERN_TTY_NAMES;
131struct ctlname semname[] = CTL_KERN_SEMINFO_NAMES;
132struct ctlname shmname[] = CTL_KERN_SHMINFO_NAMES;
133struct ctlname watchdogname[] = CTL_KERN_WATCHDOG_NAMES;
134struct ctlname *vfsname;
135#ifdef CTL_MACHDEP_NAMES
136struct ctlname machdepname[] = CTL_MACHDEP_NAMES;
137#endif
138struct ctlname ddbname[] = CTL_DDB_NAMES;
139char names[BUFSIZ];
140int lastused;
141
142struct list {
143	struct	ctlname *list;
144	int	size;
145};
146struct list toplist = { topname, CTL_MAXID };
147struct list secondlevel[] = {
148	{ 0, 0 },			/* CTL_UNSPEC */
149	{ kernname, KERN_MAXID },	/* CTL_KERN */
150	{ vmname, VM_MAXID },		/* CTL_VM */
151	{ fsname, FS_MAXID },		/* CTL_FS */
152	{ netname, NET_MAXID },		/* CTL_NET */
153	{ 0, CTL_DEBUG_MAXID },		/* CTL_DEBUG */
154	{ hwname, HW_MAXID },		/* CTL_HW */
155#ifdef CTL_MACHDEP_NAMES
156	{ machdepname, CPU_MAXID },	/* CTL_MACHDEP */
157#else
158	{ 0, 0 },			/* CTL_MACHDEP */
159#endif
160	{ username, USER_MAXID },	/* CTL_USER_NAMES */
161	{ ddbname, DBCTL_MAXID },	/* CTL_DDB_NAMES */
162	{ 0, 0 },			/* CTL_VFS */
163};
164
165int	Aflag, aflag, nflag, qflag;
166
167/*
168 * Variables requiring special processing.
169 */
170#define	CLOCK		0x00000001
171#define	BOOTTIME	0x00000002
172#define	CHRDEV		0x00000004
173#define	BLKDEV		0x00000008
174#define	RNDSTATS	0x00000010
175#define	BADDYNAMIC	0x00000020
176#define	BIOSGEO		0x00000040
177#define	BIOSDEV		0x00000080
178#define	MAJ2DEV		0x00000100
179#define	UNSIGNED	0x00000200
180#define	KMEMBUCKETS	0x00000400
181#define	LONGARRAY	0x00000800
182#define	KMEMSTATS	0x00001000
183#define	SENSORS		0x00002000
184
185/* prototypes */
186void debuginit(void);
187void listall(char *, struct list *);
188void parse(char *, int);
189void parse_baddynamic(int *, size_t, char *, void **, size_t *, int, int);
190void usage(void);
191int findname(char *, char *, char **, struct list *);
192int sysctl_inet(char *, char **, int *, int, int *);
193#ifdef INET6
194int sysctl_inet6(char *, char **, int *, int, int *);
195#endif
196int sysctl_bpf(char *, char **, int *, int, int *);
197int sysctl_ipx(char *, char **, int *, int, int *);
198int sysctl_fs(char *, char **, int *, int, int *);
199static int sysctl_vfs(char *, char **, int[], int, int *);
200static int sysctl_vfsgen(char *, char **, int[], int, int *);
201int sysctl_bios(char *, char **, int *, int, int *);
202int sysctl_swpenc(char *, char **, int *, int, int *);
203int sysctl_forkstat(char *, char **, int *, int, int *);
204int sysctl_tty(char *, char **, int *, int, int *);
205int sysctl_nchstats(char *, char **, int *, int, int *);
206int sysctl_malloc(char *, char **, int *, int, int *);
207int sysctl_seminfo(char *, char **, int *, int, int *);
208int sysctl_shminfo(char *, char **, int *, int, int *);
209int sysctl_watchdog(char *, char **, int *, int, int *);
210int sysctl_sensors(char *, char **, int *, int, int *);
211int sysctl_emul(char *, char *, int);
212#ifdef CPU_CHIPSET
213int sysctl_chipset(char *, char **, int *, int, int *);
214#endif
215void vfsinit(void);
216
217char *equ = "=";
218
219int
220main(int argc, char *argv[])
221{
222	int ch, lvl1;
223
224	while ((ch = getopt(argc, argv, "Aanqw")) != -1) {
225		switch (ch) {
226
227		case 'A':
228			Aflag = 1;
229			break;
230
231		case 'a':
232			aflag = 1;
233			break;
234
235		case 'n':
236			nflag = 1;
237			break;
238
239		case 'q':
240			qflag = 1;
241			break;
242
243		case 'w':
244			/* flag no longer needed; var=value implies write */
245			break;
246
247		default:
248			usage();
249		}
250	}
251	argc -= optind;
252	argv += optind;
253
254	if (argc == 0 && (Aflag || aflag)) {
255		debuginit();
256		vfsinit();
257		for (lvl1 = 1; lvl1 < CTL_MAXID; lvl1++)
258			listall(topname[lvl1].ctl_name, &secondlevel[lvl1]);
259		return (0);
260	}
261	if (argc == 0)
262		usage();
263	for (; *argv != NULL; ++argv)
264		parse(*argv, 1);
265	return (0);
266}
267
268/*
269 * List all variables known to the system.
270 */
271void
272listall(char *prefix, struct list *lp)
273{
274	char *cp, name[BUFSIZ];
275	int lvl2, len;
276
277	if (lp->list == NULL)
278		return;
279	if ((len = strlcpy(name, prefix, sizeof(name))) >= sizeof(name))
280		warn("%s: name too long", prefix);
281	cp = name + len++;
282	*cp++ = '.';
283	for (lvl2 = 0; lvl2 < lp->size; lvl2++) {
284		if (lp->list[lvl2].ctl_name == NULL)
285			continue;
286		if (strlcpy(cp, lp->list[lvl2].ctl_name,
287		    sizeof(name) - len) >= sizeof(name) - len)
288			warn("%s: name too long", lp->list[lvl2].ctl_name);
289		parse(name, Aflag);
290	}
291}
292
293/*
294 * Parse a name into a MIB entry.
295 * Lookup and print out the MIB entry if it exists.
296 * Set a new value if requested.
297 */
298void
299parse(char *string, int flags)
300{
301	int indx, type, state, intval, len;
302	size_t size, newsize = 0;
303	int lal = 0, special = 0;
304	void *newval = 0;
305	int64_t quadval;
306	struct list *lp;
307	int mib[CTL_MAXNAME];
308	char *cp, *bufp, buf[BUFSIZ];
309
310	(void)strlcpy(buf, string, sizeof(buf));
311	bufp = buf;
312	if ((cp = strchr(string, '=')) != NULL) {
313		*strchr(buf, '=') = '\0';
314		*cp++ = '\0';
315		while (isspace(*cp))
316			cp++;
317		newval = cp;
318		newsize = strlen(cp);
319	}
320	if ((indx = findname(string, "top", &bufp, &toplist)) == -1)
321		return;
322	mib[0] = indx;
323	if (indx == CTL_VFS)
324		vfsinit();
325	if (indx == CTL_DEBUG)
326		debuginit();
327	lp = &secondlevel[indx];
328	if (lp->list == 0) {
329		warnx("%s: class is not implemented", topname[indx].ctl_name);
330		return;
331	}
332	if (bufp == NULL) {
333		listall(topname[indx].ctl_name, lp);
334		return;
335	}
336	if ((indx = findname(string, "second", &bufp, lp)) == -1)
337		return;
338	mib[1] = indx;
339	type = lp->list[indx].ctl_type;
340	len = 2;
341	switch (mib[0]) {
342
343	case CTL_KERN:
344		switch (mib[1]) {
345		case KERN_PROF:
346			mib[2] = GPROF_STATE;
347			size = sizeof(state);
348			if (sysctl(mib, 3, &state, &size, NULL, 0) == -1) {
349				if (flags == 0)
350					return;
351				if (!nflag)
352					(void)printf("%s: ", string);
353				(void)puts("kernel is not compiled for profiling");
354				return;
355			}
356			if (!nflag)
357				(void)printf("%s = %s\n", string,
358				    state == GMON_PROF_OFF ? "off" : "running");
359			return;
360		case KERN_FORKSTAT:
361			sysctl_forkstat(string, &bufp, mib, flags, &type);
362			return;
363		case KERN_TTY:
364			len = sysctl_tty(string, &bufp, mib, flags, &type);
365			if (len < 0)
366				return;
367			newsize = 0;
368			break;
369		case KERN_NCHSTATS:
370			sysctl_nchstats(string, &bufp, mib, flags, &type);
371			return;
372		case KERN_MALLOCSTATS:
373			len = sysctl_malloc(string, &bufp, mib, flags, &type);
374			if (len < 0)
375				return;
376			if (mib[2] == KERN_MALLOC_BUCKET)
377				special |= KMEMBUCKETS;
378			if (mib[2] == KERN_MALLOC_KMEMSTATS)
379				special |= KMEMSTATS;
380			newsize = 0;
381			break;
382		case KERN_MBSTAT:
383			if (flags == 0)
384				return;
385			warnx("use netstat to view %s", string);
386			return;
387		case KERN_MSGBUF:
388			if (flags == 0)
389				return;
390			warnx("use dmesg to view %s", string);
391			return;
392		case KERN_VNODE:
393		case KERN_FILE:
394			if (flags == 0)
395				return;
396			warnx("use pstat to view %s information", string);
397			return;
398		case KERN_PROC:
399		case KERN_PROC2:
400			if (flags == 0)
401				return;
402			warnx("use ps to view %s information", string);
403			return;
404		case KERN_CLOCKRATE:
405			special |= CLOCK;
406			break;
407		case KERN_BOOTTIME:
408			special |= BOOTTIME;
409			break;
410		case KERN_RND:
411			special |= RNDSTATS;
412			break;
413		case KERN_HOSTID:
414		case KERN_ARND:
415			special |= UNSIGNED;
416			break;
417		case KERN_CPTIME:
418			special |= LONGARRAY;
419			lal = CPUSTATES;
420			break;
421		case KERN_SEMINFO:
422			len = sysctl_seminfo(string, &bufp, mib, flags, &type);
423			if (len < 0)
424				return;
425			break;
426		case KERN_SHMINFO:
427			len = sysctl_shminfo(string, &bufp, mib, flags, &type);
428			if (len < 0)
429				return;
430			break;
431		case KERN_WATCHDOG:
432			len = sysctl_watchdog(string, &bufp, mib, flags,
433			    &type);
434			if (len < 0)
435				return;
436			break;
437		case KERN_EMUL:
438			sysctl_emul(string, newval, flags);
439			return;
440		}
441		break;
442
443	case CTL_HW:
444		switch (mib[1]) {
445		case HW_DISKSTATS:
446			/*
447			 * Only complain if someone asks explicitly for this,
448			 * otherwise "fail" silently.
449			 */
450			if (flags)
451				warnx("use vmstat to view %s information",
452				    string);
453			return;
454		case HW_SENSORS:
455			special |= SENSORS;
456			len = sysctl_sensors(string, &bufp, mib, flags, &type);
457			if (len < 0)
458				return;
459			break;
460		}
461		break;
462
463	case CTL_VM:
464		if (mib[1] == VM_LOADAVG) {
465			double loads[3];
466
467			getloadavg(loads, 3);
468			if (!nflag)
469				(void)printf("%s%s", string, equ);
470			(void)printf("%.2f %.2f %.2f\n", loads[0],
471			    loads[1], loads[2]);
472			return;
473		} else if (mib[1] == VM_PSSTRINGS) {
474			struct _ps_strings _ps;
475
476			size = sizeof(_ps);
477			if (sysctl(mib, 2, &_ps, &size, NULL, 0) == -1) {
478				if (flags == 0)
479					return;
480				if (!nflag)
481					(void)printf("%s: ", string);
482				(void)puts("can't find ps strings");
483				return;
484			}
485			if (!nflag)
486				(void)printf("%s%s", string, equ);
487			(void)printf("%p\n", _ps.val);
488			return;
489		} else if (mib[1] == VM_SWAPENCRYPT) {
490			len = sysctl_swpenc(string, &bufp, mib, flags, &type);
491			if (len < 0)
492				return;
493
494			break;
495		} else if (mib[1] == VM_NKMEMPAGES ||
496		    mib[1] == VM_ANONMIN ||
497		    mib[1] == VM_VTEXTMIN ||
498		    mib[1] == VM_VNODEMIN) {
499			break;
500		}
501		if (flags == 0)
502			return;
503		warnx("use vmstat or systat to view %s information", string);
504		return;
505
506		break;
507
508	case CTL_NET:
509		if (mib[1] == PF_INET) {
510			len = sysctl_inet(string, &bufp, mib, flags, &type);
511			if (len < 0)
512				return;
513
514			if ((mib[2] == IPPROTO_TCP &&
515			     mib[3] == TCPCTL_BADDYNAMIC) ||
516			    (mib[2] == IPPROTO_UDP &&
517			     mib[3] == UDPCTL_BADDYNAMIC)) {
518
519				special |= BADDYNAMIC;
520
521				if (newval != NULL)
522					parse_baddynamic(mib, len, string,
523					    &newval, &newsize, flags, nflag);
524			}
525			break;
526		}
527#ifdef INET6
528		if (mib[1] == PF_INET6) {
529			len = sysctl_inet6(string, &bufp, mib, flags, &type);
530			if (len < 0)
531				return;
532
533			break;
534		}
535#endif
536		if (mib[1] == PF_IPX) {
537			len = sysctl_ipx(string, &bufp, mib, flags, &type);
538			if (len >= 0)
539				break;
540			return;
541		}
542		if (mib[1] == PF_BPF) {
543			len = sysctl_bpf(string, &bufp, mib, flags, &type);
544			if (len < 0)
545				return;
546			break;
547		}
548		if (flags == 0)
549			return;
550		warnx("use netstat to view %s information", string);
551		return;
552
553	case CTL_DEBUG:
554		mib[2] = CTL_DEBUG_VALUE;
555		len = 3;
556		break;
557
558	case CTL_MACHDEP:
559#ifdef CPU_CONSDEV
560		if (mib[1] == CPU_CONSDEV)
561			special |= CHRDEV;
562#endif
563#ifdef CPU_BLK2CHR
564		if (mib[1] == CPU_BLK2CHR) {
565			if (bufp == NULL)
566				return;
567			mib[2] = makedev(atoi(bufp),0);
568			bufp = NULL;
569			len = 3;
570			special |= CHRDEV;
571			break;
572		}
573#endif
574#ifdef CPU_CHR2BLK
575		if (mib[1] == CPU_CHR2BLK) {
576			if (bufp == NULL)
577				return;
578			mib[2] = makedev(atoi(bufp),0);
579			bufp = NULL;
580			len = 3;
581			special |= BLKDEV;
582			break;
583		}
584#endif
585#ifdef CPU_BIOS
586		if (mib[1] == CPU_BIOS) {
587			len = sysctl_bios(string, &bufp, mib, flags, &type);
588			if (len < 0)
589				return;
590			if (mib[2] == BIOS_DEV)
591				special |= BIOSDEV;
592			if (mib[2] == BIOS_DISKINFO)
593				special |= BIOSGEO;
594			break;
595		}
596#endif
597#ifdef CPU_CHIPSET
598		if (mib[1] == CPU_CHIPSET) {
599			len = sysctl_chipset(string, &bufp, mib, flags, &type);
600			if (len < 0)
601				return;
602			break;
603		}
604#endif
605#ifdef CPU_LONGRUN
606		if (mib[1] == CPU_LONGRUN)
607			return;
608#endif
609
610		break;
611
612	case CTL_FS:
613		len = sysctl_fs(string, &bufp, mib, flags, &type);
614		if (len >= 0)
615			break;
616		return;
617
618	case CTL_VFS:
619		if (mib[1])
620			len = sysctl_vfs(string, &bufp, mib, flags, &type);
621		else
622			len = sysctl_vfsgen(string, &bufp, mib, flags, &type);
623		if (len >= 0) {
624			if (type == CTLTYPE_STRUCT) {
625				if (flags)
626					warnx("use nfsstat to view %s information",
627					    MOUNT_NFS);
628				return;
629			} else
630				break;
631		}
632		return;
633
634	case CTL_USER:
635	case CTL_DDB:
636		break;
637
638	default:
639		warnx("illegal top level value: %d", mib[0]);
640		return;
641
642	}
643	if (bufp) {
644		warnx("name %s in %s is unknown", bufp, string);
645		return;
646	}
647	if (newsize > 0) {
648		switch (type) {
649		case CTLTYPE_INT:
650			errno = 0;
651			if (special & UNSIGNED)
652				intval = strtoul(newval, &cp, 10);
653			else
654				intval = strtol(newval, &cp, 10);
655			if (*cp != '\0') {
656				warnx("%s: illegal value: %s", string,
657				    (char *)newval);
658				return;
659			}
660			if (errno == ERANGE) {
661				warnx("%s: value %s out of range", string,
662				    (char *)newval);
663				return;
664			}
665			newval = &intval;
666			newsize = sizeof(intval);
667			break;
668
669		case CTLTYPE_QUAD:
670			/* XXX - assumes sizeof(long long) == sizeof(quad_t) */
671			(void)sscanf(newval, "%lld", (long long *)&quadval);
672			newval = &quadval;
673			newsize = sizeof(quadval);
674			break;
675		}
676	}
677	size = BUFSIZ;
678	if (sysctl(mib, len, buf, &size, newval, newsize) == -1) {
679		if (flags == 0)
680			return;
681		switch (errno) {
682		case EOPNOTSUPP:
683			warnx("%s: value is not available", string);
684			return;
685		case ENOTDIR:
686			warnx("%s: specification is incomplete", string);
687			return;
688		case ENOMEM:
689			warnx("%s: type is unknown to this program", string);
690			return;
691		case ENXIO:
692			if (special & BIOSGEO)
693				return;
694		default:
695			warn("%s", string);
696			return;
697		}
698	}
699	if (special & KMEMBUCKETS) {
700		struct kmembuckets *kb = (struct kmembuckets *)buf;
701		if (!nflag)
702			(void)printf("%s%s", string, equ);
703		printf("(");
704		printf("calls = %llu ", (long long)kb->kb_calls);
705		printf("total_allocated = %llu ", (long long)kb->kb_total);
706		printf("total_free = %lld ", (long long)kb->kb_totalfree);
707		printf("elements = %lld ", (long long)kb->kb_elmpercl);
708		printf("high watermark = %lld ", (long long)kb->kb_highwat);
709		printf("could_free = %lld", (long long)kb->kb_couldfree);
710		printf(")\n");
711		return;
712	}
713	if (special & KMEMSTATS) {
714		struct kmemstats *km = (struct kmemstats *)buf;
715		int j, first = 1;
716
717		if (!nflag)
718			(void)printf("%s%s", string, equ);
719		(void)printf("(inuse = %ld, calls = %ld, memuse = %ldK, "
720		    "limblocks = %d, mapblocks = %d, maxused = %ldK, "
721		    "limit = %ldK, spare = %ld, sizes = (",
722		    km->ks_inuse, km->ks_calls,
723		    (km->ks_memuse + 1023) / 1024, km->ks_limblocks,
724		    km->ks_mapblocks, (km->ks_maxused + 1023) / 1024,
725		    (km->ks_limit + 1023) / 1024, km->ks_spare);
726		for (j = 1 << MINBUCKET; j < 1 << (MINBUCKET + 16); j <<= 1) {
727			if ((km->ks_size & j ) == 0)
728				continue;
729			if (first)
730				(void)printf("%d", j);
731			else
732				(void)printf(",%d", j);
733			first = 0;
734		}
735		if (first)
736			(void)printf("none");
737		(void)printf("))\n");
738		return;
739	}
740	if (special & CLOCK) {
741		struct clockinfo *clkp = (struct clockinfo *)buf;
742
743		if (!nflag)
744			(void)printf("%s%s", string, equ);
745		(void)printf(
746		    "tick = %d, tickadj = %d, hz = %d, profhz = %d, stathz = %d\n",
747		    clkp->tick, clkp->tickadj, clkp->hz, clkp->profhz, clkp->stathz);
748		return;
749	}
750	if (special & BOOTTIME) {
751		struct timeval *btp = (struct timeval *)buf;
752		time_t boottime;
753
754		if (!nflag) {
755			boottime = btp->tv_sec;
756			(void)printf("%s%s%s", string, equ, ctime(&boottime));
757		} else
758			(void)printf("%ld\n", btp->tv_sec);
759		return;
760	}
761	if (special & BLKDEV) {
762		dev_t dev = *(dev_t *)buf;
763
764		if (!nflag)
765			(void)printf("%s%s%s\n", string, equ,
766			    devname(dev, S_IFBLK));
767		else
768			(void)printf("0x%x\n", dev);
769		return;
770	}
771	if (special & CHRDEV) {
772		dev_t dev = *(dev_t *)buf;
773
774		if (!nflag)
775			(void)printf("%s%s%s\n", string, equ,
776			    devname(dev, S_IFCHR));
777		else
778			(void)printf("0x%x\n", dev);
779		return;
780	}
781#ifdef CPU_BIOS
782	if (special & BIOSGEO) {
783		bios_diskinfo_t *pdi = (bios_diskinfo_t *)buf;
784
785		if (!nflag)
786			(void)printf("%s%s", string, equ);
787		(void)printf("bootdev = 0x%x, "
788			     "cylinders = %u, heads = %u, sectors = %u\n",
789			     pdi->bsd_dev, pdi->bios_cylinders,
790			     pdi->bios_heads, pdi->bios_sectors);
791		return;
792	}
793	if (special & BIOSDEV) {
794		int dev = *(int*)buf;
795
796		if (!nflag)
797			(void)printf("%s%s", string, equ);
798		(void) printf("0x%02x\n", dev);
799		return;
800	}
801#endif
802	if (special & UNSIGNED) {
803		if (newsize == 0) {
804			if (!nflag)
805				(void)printf("%s%s", string, equ);
806			(void)printf("%u\n", *(u_int *)buf);
807		} else {
808			if (!qflag) {
809				if (!nflag)
810					(void)printf("%s: %u -> ", string,
811					    *(u_int *)buf);
812				(void)printf("%u\n", *(u_int *)newval);
813			}
814		}
815		return;
816	}
817	if (special & RNDSTATS) {
818		struct rndstats *rndstats = (struct rndstats *)buf;
819		int i;
820
821		if (!nflag)
822			(void)printf("%s%s", string, equ);
823		(void)printf(
824		"%llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu",
825		    (unsigned long long)rndstats->rnd_total,
826		    (unsigned long long)rndstats->rnd_used,
827		    (unsigned long long)rndstats->rnd_reads,
828		    (unsigned long long)rndstats->arc4_reads,
829		    (unsigned long long)rndstats->arc4_nstirs,
830		    (unsigned long long)rndstats->arc4_stirs,
831		    (unsigned long long)rndstats->rnd_pad[0],
832		    (unsigned long long)rndstats->rnd_pad[1],
833		    (unsigned long long)rndstats->rnd_pad[2],
834		    (unsigned long long)rndstats->rnd_pad[3],
835		    (unsigned long long)rndstats->rnd_pad[4],
836		    (unsigned long long)rndstats->rnd_waits,
837		    (unsigned long long)rndstats->rnd_enqs,
838		    (unsigned long long)rndstats->rnd_deqs,
839		    (unsigned long long)rndstats->rnd_drops,
840		    (unsigned long long)rndstats->rnd_drople);
841		for (i = 0; i < sizeof(rndstats->rnd_ed)/sizeof(rndstats->rnd_ed[0]);
842		    i++)
843			(void)printf(" %llu", (unsigned long long)rndstats->rnd_ed[i]);
844		for (i = 0; i < sizeof(rndstats->rnd_sc)/sizeof(rndstats->rnd_sc[0]);
845		    i++)
846			(void)printf(" %llu", (unsigned long long)rndstats->rnd_sc[i]);
847		for (i = 0; i < sizeof(rndstats->rnd_sb)/sizeof(rndstats->rnd_sb[0]);
848		    i++)
849			(void)printf(" %llu", (unsigned long long)rndstats->rnd_sb[i]);
850		printf("\n");
851		return;
852	}
853	if (special & BADDYNAMIC) {
854		in_port_t port, lastport;
855		u_int32_t *baddynamic = (u_int32_t *)buf;
856
857		if (!qflag) {
858			if (!nflag)
859				(void)printf("%s%s", string,
860				    newsize ? ": " : equ);
861			lastport = 0;
862			for (port = IPPORT_RESERVED/2; port < IPPORT_RESERVED;
863			    port++)
864				if (DP_ISSET(baddynamic, port)) {
865					(void)printf("%s%hd",
866					    lastport ? "," : "", port);
867					lastport = port;
868				}
869			if (newsize != 0) {
870				if (!nflag)
871					fputs(" -> ", stdout);
872				baddynamic = (u_int32_t *)newval;
873				lastport = 0;
874				for (port = IPPORT_RESERVED/2;
875				    port < IPPORT_RESERVED; port++)
876					if (DP_ISSET(baddynamic, port)) {
877						(void)printf("%s%hd",
878						    lastport ? "," : "", port);
879						lastport = port;
880					}
881			}
882			(void)putchar('\n');
883		}
884		return;
885	}
886	if (special & LONGARRAY) {
887		long *la = (long *)buf;
888		if (!nflag)
889			printf("%s%s", string, equ);
890		while (lal--)
891			printf("%ld%s", *la++, lal? ",":"");
892		putchar('\n');
893		return;
894	}
895	if (special & SENSORS) {
896		struct sensor *s = (struct sensor *)buf;
897
898		if (size > 0 && (s->flags & SENSOR_FINVALID) == 0) {
899			if (!nflag)
900				printf("%s%s", string, equ);
901			printf("%s, %s, ", s->device, s->desc);
902			switch (s->type) {
903			case SENSOR_TEMP:
904				printf("temp, %.2f degC / %.2f degF",
905				    (s->value - 273150000) / 1000000.0,
906				    (s->value - 273150000) / 1000000.0 * 9 / 5 +
907				    32);
908				break;
909			case SENSOR_FANRPM:
910				printf("fanrpm, %lld RPM", s->value);
911				break;
912			case SENSOR_VOLTS_DC:
913				printf("volts_dc, %.2f V",
914				    s->value / 1000000.0);
915				break;
916			default:
917				printf("unknown");
918			}
919			printf("\n");
920		}
921		return;
922	}
923
924	switch (type) {
925	case CTLTYPE_INT:
926		if (newsize == 0) {
927			if (!nflag)
928				(void)printf("%s%s", string, equ);
929			(void)printf("%d\n", *(int *)buf);
930		} else {
931			if (!qflag) {
932				if (!nflag)
933					(void)printf("%s: %d -> ", string,
934					    *(int *)buf);
935				(void)printf("%d\n", *(int *)newval);
936			}
937		}
938		return;
939
940	case CTLTYPE_STRING:
941		if (newval == NULL) {
942			if (!nflag)
943				(void)printf("%s%s", string, equ);
944			(void)puts(buf);
945		} else {
946			if (!qflag) {
947				if (!nflag)
948					(void)printf("%s: %s -> ", string, buf);
949				(void)puts((char *)newval);
950			}
951		}
952		return;
953
954	case CTLTYPE_QUAD:
955		if (newsize == 0) {
956			long long tmp = *(quad_t *)buf;
957
958			if (!nflag)
959				(void)printf("%s%s", string, equ);
960			(void)printf("%lld\n", tmp);
961		} else {
962			long long tmp = *(quad_t *)buf;
963
964			if (!qflag) {
965				if (!nflag)
966					(void)printf("%s: %lld -> ",
967					    string, tmp);
968				tmp = *(quad_t *)newval;
969				(void)printf("%qd\n", tmp);
970			}
971		}
972		return;
973
974	case CTLTYPE_STRUCT:
975		warnx("%s: unknown structure returned", string);
976		return;
977
978	default:
979	case CTLTYPE_NODE:
980		warnx("%s: unknown type returned", string);
981		return;
982	}
983}
984
985void
986parse_baddynamic(int mib[], size_t len, char *string, void **newvalp,
987    size_t *newsizep, int flags, int nflag)
988{
989	static u_int32_t newbaddynamic[DP_MAPSIZE];
990	in_port_t port;
991	size_t size;
992	char action, *cp;
993
994	if (strchr((char *)*newvalp, '+') || strchr((char *)*newvalp, '-')) {
995		size = sizeof(newbaddynamic);
996		if (sysctl(mib, len, newbaddynamic, &size, 0, 0) == -1) {
997			if (flags == 0)
998				return;
999			if (!nflag)
1000				(void)printf("%s: ", string);
1001			(void)puts("kernel does contain bad dynamic port tables");
1002			return;
1003		}
1004
1005		while (*newvalp && (cp = strsep((char **)newvalp, ", \t")) && *cp) {
1006			if (*cp != '+' && *cp != '-')
1007				errx(1, "cannot mix +/- with full list");
1008			action = *cp++;
1009			port = atoi(cp);
1010			if (port < IPPORT_RESERVED/2 || port >= IPPORT_RESERVED)
1011				errx(1, "invalid port, range is %d to %d",
1012				    IPPORT_RESERVED/2, IPPORT_RESERVED-1);
1013			if (action == '+')
1014				DP_SET(newbaddynamic, port);
1015			else
1016				DP_CLR(newbaddynamic, port);
1017		}
1018	} else {
1019		(void)memset((void *)newbaddynamic, 0, sizeof(newbaddynamic));
1020		while (*newvalp && (cp = strsep((char **)newvalp, ", \t")) && *cp) {
1021			port = atoi(cp);
1022			if (port < IPPORT_RESERVED/2 || port >= IPPORT_RESERVED)
1023				errx(1, "invalid port, range is %d to %d",
1024				    IPPORT_RESERVED/2, IPPORT_RESERVED-1);
1025			DP_SET(newbaddynamic, port);
1026		}
1027	}
1028
1029	*newvalp = (void *)newbaddynamic;
1030	*newsizep = sizeof(newbaddynamic);
1031}
1032
1033/*
1034 * Initialize the set of debugging names
1035 */
1036void
1037debuginit(void)
1038{
1039	int mib[3], loc, i;
1040	size_t size;
1041
1042	if (secondlevel[CTL_DEBUG].list != 0)
1043		return;
1044	secondlevel[CTL_DEBUG].list = debugname;
1045	mib[0] = CTL_DEBUG;
1046	mib[2] = CTL_DEBUG_NAME;
1047	for (loc = lastused, i = 0; i < CTL_DEBUG_MAXID; i++) {
1048		mib[1] = i;
1049		size = BUFSIZ - loc;
1050		if (sysctl(mib, 3, &names[loc], &size, NULL, 0) == -1)
1051			continue;
1052		debugname[i].ctl_name = &names[loc];
1053		debugname[i].ctl_type = CTLTYPE_INT;
1054		loc += size;
1055	}
1056	lastused = loc;
1057}
1058
1059struct ctlname vfsgennames[] = CTL_VFSGENCTL_NAMES;
1060struct ctlname ffsname[] = FFS_NAMES;
1061struct ctlname nfsname[] = FS_NFS_NAMES;
1062struct list *vfsvars;
1063int *vfs_typenums;
1064
1065/*
1066 * Initialize the set of filesystem names
1067 */
1068void
1069vfsinit(void)
1070{
1071	int mib[4], maxtypenum, cnt, loc, size;
1072	struct vfsconf vfc;
1073	size_t buflen;
1074
1075	if (secondlevel[CTL_VFS].list != 0)
1076		return;
1077	mib[0] = CTL_VFS;
1078	mib[1] = VFS_GENERIC;
1079	mib[2] = VFS_MAXTYPENUM;
1080	buflen = 4;
1081	if (sysctl(mib, 3, &maxtypenum, &buflen, (void *)0, (size_t)0) < 0)
1082		return;
1083	maxtypenum++;	/* + generic */
1084	if ((vfs_typenums = malloc(maxtypenum * sizeof(int))) == NULL)
1085		return;
1086	memset(vfs_typenums, 0, maxtypenum * sizeof(int));
1087	if ((vfsvars = malloc(maxtypenum * sizeof(*vfsvars))) == NULL) {
1088		free(vfs_typenums);
1089		return;
1090	}
1091	memset(vfsvars, 0, maxtypenum * sizeof(*vfsvars));
1092	if ((vfsname = malloc(maxtypenum * sizeof(*vfsname))) == NULL) {
1093		free(vfs_typenums);
1094		free(vfsvars);
1095		return;
1096	}
1097	memset(vfsname, 0, maxtypenum * sizeof(*vfsname));
1098	mib[2] = VFS_CONF;
1099	buflen = sizeof vfc;
1100	for (loc = lastused, cnt = 1; cnt < maxtypenum; cnt++) {
1101		mib[3] = cnt - 1;
1102		if (sysctl(mib, 4, &vfc, &buflen, (void *)0, (size_t)0) < 0) {
1103			if (errno == EOPNOTSUPP)
1104				continue;
1105			warn("vfsinit");
1106			free(vfsname);
1107			return;
1108		}
1109		if (!strcmp(vfc.vfc_name, MOUNT_FFS)) {
1110			vfsvars[cnt].list = ffsname;
1111			vfsvars[cnt].size = FFS_MAXID;
1112		}
1113		if (!strcmp(vfc.vfc_name, MOUNT_NFS)) {
1114			vfsvars[cnt].list = nfsname;
1115			vfsvars[cnt].size = NFS_MAXID;
1116		}
1117		vfs_typenums[cnt] = vfc.vfc_typenum;
1118		strlcat(&names[loc], vfc.vfc_name, sizeof names - loc);
1119		vfsname[cnt].ctl_name = &names[loc];
1120		vfsname[cnt].ctl_type = CTLTYPE_NODE;
1121		size = strlen(vfc.vfc_name) + 1;
1122		loc += size;
1123	}
1124	lastused = loc;
1125
1126	vfsname[0].ctl_name = "mounts";
1127	vfsname[0].ctl_type = CTLTYPE_NODE;
1128	vfsvars[0].list = vfsname + 1;
1129	vfsvars[0].size = maxtypenum - 1;
1130
1131	secondlevel[CTL_VFS].list = vfsname;
1132	secondlevel[CTL_VFS].size = maxtypenum;
1133	return;
1134}
1135
1136int
1137sysctl_vfsgen(char *string, char **bufpp, int mib[], int flags, int *typep)
1138{
1139	int indx;
1140	size_t size;
1141	struct vfsconf vfc;
1142
1143	if (*bufpp == NULL) {
1144		listall(string, vfsvars);
1145		return (-1);
1146	}
1147
1148	if ((indx = findname(string, "third", bufpp, vfsvars)) == -1)
1149		return (-1);
1150
1151	mib[1] = VFS_GENERIC;
1152	mib[2] = VFS_CONF;
1153	mib[3] = indx;
1154	size = sizeof vfc;
1155	if (sysctl(mib, 4, &vfc, &size, (void *)0, (size_t)0) < 0) {
1156		if (errno != EOPNOTSUPP)
1157			warn("vfs print");
1158		return -1;
1159	}
1160	if (flags == 0 && vfc.vfc_refcount == 0)
1161		return -1;
1162	if (!nflag)
1163		fprintf(stdout, "%s has %d mounted instance%s\n",
1164		    string, vfc.vfc_refcount,
1165		    vfc.vfc_refcount != 1 ? "s" : "");
1166	else
1167		fprintf(stdout, "%d\n", vfc.vfc_refcount);
1168
1169	return -1;
1170}
1171
1172int
1173sysctl_vfs(char *string, char **bufpp, int mib[], int flags, int *typep)
1174{
1175	struct list *lp = &vfsvars[mib[1]];
1176	int indx;
1177
1178	if (lp->list == NULL) {
1179		if (flags)
1180			warnx("No variables defined for file system %s", string);
1181		return (-1);
1182	}
1183	if (*bufpp == NULL) {
1184		listall(string, lp);
1185		return (-1);
1186	}
1187	if ((indx = findname(string, "third", bufpp, lp)) == -1)
1188		return (-1);
1189
1190	mib[1] = vfs_typenums[mib[1]];
1191	mib[2] = indx;
1192	*typep = lp->list[indx].ctl_type;
1193	return (3);
1194}
1195
1196struct ctlname posixname[] = CTL_FS_POSIX_NAMES;
1197struct list fslist = { posixname, FS_POSIX_MAXID };
1198
1199/*
1200 * handle file system requests
1201 */
1202int
1203sysctl_fs(char *string, char **bufpp, int mib[], int flags, int *typep)
1204{
1205	int indx;
1206
1207	if (*bufpp == NULL) {
1208		listall(string, &fslist);
1209		return (-1);
1210	}
1211	if ((indx = findname(string, "third", bufpp, &fslist)) == -1)
1212		return (-1);
1213	mib[2] = indx;
1214	*typep = fslist.list[indx].ctl_type;
1215	return (3);
1216}
1217
1218#ifdef CPU_BIOS
1219struct ctlname biosname[] = CTL_BIOS_NAMES;
1220struct list bioslist = { biosname, BIOS_MAXID };
1221
1222/*
1223 * handle BIOS requests
1224 */
1225int
1226sysctl_bios(char *string, char **bufpp, int mib[], int flags, int *typep)
1227{
1228	char *name;
1229	int indx;
1230
1231	if (*bufpp == NULL) {
1232		listall(string, &bioslist);
1233		return (-1);
1234	}
1235	if ((indx = findname(string, "third", bufpp, &bioslist)) == -1)
1236		return (-1);
1237	mib[2] = indx;
1238	if (indx == BIOS_DISKINFO) {
1239		if (*bufpp == NULL) {
1240			char name[BUFSIZ];
1241
1242			/* scan all the bios devices */
1243			for (indx = 0; indx < 256; indx++) {
1244				snprintf(name, sizeof(name), "%s.%u",
1245					 string, indx);
1246				parse(name, 1);
1247			}
1248			return (-1);
1249		}
1250		if ((name = strsep(bufpp, ".")) == NULL) {
1251			warnx("%s: incomplete specification", string);
1252			return (-1);
1253		}
1254		mib[3] = atoi(name);
1255		*typep = CTLTYPE_STRUCT;
1256		return (4);
1257	} else {
1258		*typep = bioslist.list[indx].ctl_type;
1259		return (3);
1260	}
1261}
1262#endif
1263
1264struct ctlname swpencname[] = CTL_SWPENC_NAMES;
1265struct list swpenclist = { swpencname, SWPENC_MAXID };
1266
1267/*
1268 * handle swap encrypt requests
1269 */
1270int
1271sysctl_swpenc(char *string, char **bufpp, int mib[], int flags, int *typep)
1272{
1273	int indx;
1274
1275	if (*bufpp == NULL) {
1276		listall(string, &swpenclist);
1277		return (-1);
1278	}
1279	if ((indx = findname(string, "third", bufpp, &swpenclist)) == -1)
1280		return (-1);
1281	mib[2] = indx;
1282	*typep = swpenclist.list[indx].ctl_type;
1283	return (3);
1284}
1285
1286struct ctlname inetname[] = CTL_IPPROTO_NAMES;
1287struct ctlname ipname[] = IPCTL_NAMES;
1288struct ctlname icmpname[] = ICMPCTL_NAMES;
1289struct ctlname ipipname[] = IPIPCTL_NAMES;
1290struct ctlname tcpname[] = TCPCTL_NAMES;
1291struct ctlname udpname[] = UDPCTL_NAMES;
1292struct ctlname espname[] = ESPCTL_NAMES;
1293struct ctlname ahname[] = AHCTL_NAMES;
1294struct ctlname etheripname[] = ETHERIPCTL_NAMES;
1295struct ctlname grename[] = GRECTL_NAMES;
1296struct ctlname mobileipname[] = MOBILEIPCTL_NAMES;
1297struct ctlname ipcompname[] = IPCOMPCTL_NAMES;
1298struct ctlname carpname[] = CARPCTL_NAMES;
1299struct ctlname bpfname[] = CTL_NET_BPF_NAMES;
1300struct list inetlist = { inetname, IPPROTO_MAXID };
1301struct list inetvars[] = {
1302	{ ipname, IPCTL_MAXID },	/* ip */
1303	{ icmpname, ICMPCTL_MAXID },	/* icmp */
1304	{ 0, 0 },			/* igmp */
1305	{ 0, 0 },			/* ggmp */
1306	{ ipipname, IPIPCTL_MAXID },	/* ipencap */
1307	{ 0, 0 },
1308	{ tcpname, TCPCTL_MAXID },	/* tcp */
1309	{ 0, 0 },
1310	{ 0, 0 },			/* egp */
1311	{ 0, 0 },
1312	{ 0, 0 },
1313	{ 0, 0 },
1314	{ 0, 0 },			/* pup */
1315	{ 0, 0 },
1316	{ 0, 0 },
1317	{ 0, 0 },
1318	{ 0, 0 },
1319	{ udpname, UDPCTL_MAXID },	/* udp */
1320	{ 0, 0 },
1321	{ 0, 0 },
1322	{ 0, 0 },
1323	{ 0, 0 },
1324	{ 0, 0 },
1325	{ 0, 0 },
1326	{ 0, 0 },
1327	{ 0, 0 },
1328	{ 0, 0 },
1329	{ 0, 0 },
1330	{ 0, 0 },
1331	{ 0, 0 },
1332	{ 0, 0 },
1333	{ 0, 0 },
1334	{ 0, 0 },
1335	{ 0, 0 },
1336	{ 0, 0 },
1337	{ 0, 0 },
1338	{ 0, 0 },
1339	{ 0, 0 },
1340	{ 0, 0 },
1341	{ 0, 0 },
1342	{ 0, 0 },
1343	{ 0, 0 },
1344	{ 0, 0 },
1345	{ 0, 0 },
1346	{ 0, 0 },
1347	{ 0, 0 },
1348	{ 0, 0 },
1349	{ grename, GRECTL_MAXID }, /* GRE */
1350	{ 0, 0 },
1351	{ 0, 0 },
1352	{ espname, ESPCTL_MAXID },	/* esp */
1353	{ ahname, AHCTL_MAXID },	/* ah */
1354	{ 0, 0 },
1355	{ 0, 0 },
1356	{ 0, 0 },
1357	{ mobileipname, MOBILEIPCTL_MAXID }, /* mobileip */
1358	{ 0, 0 },
1359	{ 0, 0 },
1360	{ 0, 0 },
1361	{ 0, 0 },
1362	{ 0, 0 },
1363	{ 0, 0 },
1364	{ 0, 0 },
1365	{ 0, 0 },
1366	{ 0, 0 },
1367	{ 0, 0 },
1368	{ 0, 0 },
1369	{ 0, 0 },
1370	{ 0, 0 },
1371	{ 0, 0 },
1372	{ 0, 0 },
1373	{ 0, 0 },
1374	{ 0, 0 },
1375	{ 0, 0 },
1376	{ 0, 0 },
1377	{ 0, 0 },
1378	{ 0, 0 },
1379	{ 0, 0 },
1380	{ 0, 0 },
1381	{ 0, 0 },
1382	{ 0, 0 },
1383	{ 0, 0 },
1384	{ 0, 0 },
1385	{ 0, 0 },
1386	{ 0, 0 },
1387	{ 0, 0 },
1388	{ 0, 0 },
1389	{ 0, 0 },
1390	{ 0, 0 },
1391	{ 0, 0 },
1392	{ 0, 0 },
1393	{ 0, 0 },
1394	{ 0, 0 },
1395	{ 0, 0 },
1396	{ 0, 0 },
1397	{ 0, 0 },
1398	{ 0, 0 },
1399	{ etheripname, ETHERIPCTL_MAXID },
1400	{ 0, 0 },
1401	{ 0, 0 },
1402	{ 0, 0 },
1403	{ 0, 0 },
1404	{ 0, 0 },
1405	{ 0, 0 },
1406	{ 0, 0 },
1407	{ 0, 0 },
1408	{ 0, 0 },
1409	{ 0, 0 },
1410	{ ipcompname, IPCOMPCTL_MAXID },
1411	{ 0, 0 },
1412	{ 0, 0 },
1413	{ 0, 0 },
1414	{ carpname, CARPCTL_MAXID },
1415};
1416struct list bpflist = { bpfname, NET_BPF_MAXID };
1417
1418struct list kernmalloclist = { kernmallocname, KERN_MALLOC_MAXID };
1419struct list forkstatlist = { forkstatname, KERN_FORKSTAT_MAXID };
1420struct list nchstatslist = { nchstatsname, KERN_NCHSTATS_MAXID };
1421struct list ttylist = { ttyname, KERN_TTY_MAXID };
1422struct list semlist = { semname, KERN_SEMINFO_MAXID };
1423struct list shmlist = { shmname, KERN_SHMINFO_MAXID };
1424struct list watchdoglist = { watchdogname, KERN_WATCHDOG_MAXID };
1425
1426/*
1427 * handle vfs namei cache statistics
1428 */
1429int
1430sysctl_nchstats(char *string, char **bufpp, int mib[], int flags, int *typep)
1431{
1432	static struct nchstats nch;
1433	int indx;
1434	size_t size;
1435	static int keepvalue = 0;
1436
1437	if (*bufpp == NULL) {
1438		bzero(&nch, sizeof(struct nchstats));
1439		listall(string, &nchstatslist);
1440		return (-1);
1441	}
1442	if ((indx = findname(string, "third", bufpp, &nchstatslist)) == -1)
1443		return (-1);
1444	mib[2] = indx;
1445	if (*bufpp != NULL) {
1446		warnx("fourth level name in %s is invalid", string);
1447		return (-1);
1448	}
1449	if (keepvalue == 0) {
1450		size = sizeof(struct nchstats);
1451		if (sysctl(mib, 2, &nch, &size, NULL, 0) < 0)
1452			return (-1);
1453		keepvalue = 1;
1454	}
1455	if (!nflag)
1456		(void)printf("%s%s", string, equ);
1457	switch (indx) {
1458	case KERN_NCHSTATS_GOODHITS:
1459		(void)printf("%ld\n", nch.ncs_goodhits);
1460		break;
1461	case KERN_NCHSTATS_NEGHITS:
1462		(void)printf("%ld\n", nch.ncs_neghits);
1463		break;
1464	case KERN_NCHSTATS_BADHITS:
1465		(void)printf("%ld\n", nch.ncs_badhits);
1466		break;
1467	case KERN_NCHSTATS_FALSEHITS:
1468		(void)printf("%ld\n", nch.ncs_falsehits);
1469		break;
1470	case KERN_NCHSTATS_MISS:
1471		(void)printf("%ld\n", nch.ncs_miss);
1472		break;
1473	case KERN_NCHSTATS_LONG:
1474		(void)printf("%ld\n", nch.ncs_long);
1475		break;
1476	case KERN_NCHSTATS_PASS2:
1477		(void)printf("%ld\n", nch.ncs_pass2);
1478		break;
1479	case KERN_NCHSTATS_2PASSES:
1480		(void)printf("%ld\n", nch.ncs_2passes);
1481		break;
1482	}
1483	return (-1);
1484}
1485
1486/*
1487 * handle tty statistics
1488 */
1489int
1490sysctl_tty(char *string, char **bufpp, int mib[], int flags, int *typep)
1491{
1492	int indx;
1493
1494	if (*bufpp == NULL) {
1495		listall(string, &ttylist);
1496		return (-1);
1497	}
1498	if ((indx = findname(string, "third", bufpp, &ttylist)) == -1)
1499		return (-1);
1500	mib[2] = indx;
1501
1502	if ((*typep = ttylist.list[indx].ctl_type) == CTLTYPE_STRUCT) {
1503		if (flags)
1504			warnx("use pstat -t to view %s information",
1505			    string);
1506		return (-1);
1507	}
1508	return (3);
1509}
1510
1511/*
1512 * handle fork statistics
1513 */
1514int
1515sysctl_forkstat(char *string, char **bufpp, int mib[], int flags, int *typep)
1516{
1517	static struct forkstat fks;
1518	static int keepvalue = 0;
1519	int indx;
1520	size_t size;
1521
1522	if (*bufpp == NULL) {
1523		bzero(&fks, sizeof(struct forkstat));
1524		listall(string, &forkstatlist);
1525		return (-1);
1526	}
1527	if ((indx = findname(string, "third", bufpp, &forkstatlist)) == -1)
1528		return (-1);
1529	if (*bufpp != NULL) {
1530		warnx("fourth level name in %s is invalid", string);
1531		return (-1);
1532	}
1533	if (keepvalue == 0) {
1534		size = sizeof(struct forkstat);
1535		if (sysctl(mib, 2, &fks, &size, NULL, 0) < 0)
1536			return (-1);
1537		keepvalue = 1;
1538	}
1539	if (!nflag)
1540		(void)printf("%s%s", string, equ);
1541	switch (indx)	{
1542	case KERN_FORKSTAT_FORK:
1543		(void)printf("%d\n", fks.cntfork);
1544		break;
1545	case KERN_FORKSTAT_VFORK:
1546		(void)printf("%d\n", fks.cntvfork);
1547		break;
1548	case KERN_FORKSTAT_RFORK:
1549		(void)printf("%d\n", fks.cntrfork);
1550		break;
1551	case KERN_FORKSTAT_KTHREAD:
1552		(void)printf("%d\n", fks.cntkthread);
1553		break;
1554	case KERN_FORKSTAT_SIZFORK:
1555		(void)printf("%d\n", fks.sizfork);
1556		break;
1557	case KERN_FORKSTAT_SIZVFORK:
1558		(void)printf("%d\n", fks.sizvfork);
1559		break;
1560	case KERN_FORKSTAT_SIZRFORK:
1561		(void)printf("%d\n", fks.sizrfork);
1562		break;
1563	case KERN_FORKSTAT_SIZKTHREAD:
1564		(void)printf("%d\n", fks.sizkthread);
1565		break;
1566	}
1567	return (-1);
1568}
1569
1570/*
1571 * handle malloc statistics
1572 */
1573int
1574sysctl_malloc(char *string, char **bufpp, int mib[], int flags, int *typep)
1575{
1576	int indx, stor, i;
1577	char *name, bufp[BUFSIZ], *buf, *ptr;
1578	struct list lp;
1579	size_t size;
1580
1581	if (*bufpp == NULL) {
1582		listall(string, &kernmalloclist);
1583		return (-1);
1584	}
1585	if ((indx = findname(string, "third", bufpp, &kernmalloclist)) == -1)
1586		return (-1);
1587	mib[2] = indx;
1588	if (mib[2] == KERN_MALLOC_BUCKET) {
1589		if ((name = strsep(bufpp, ".")) == NULL) {
1590			size = BUFSIZ;
1591			stor = mib[2];
1592			mib[2] = KERN_MALLOC_BUCKETS;
1593			buf = bufp;
1594			if (sysctl(mib, 3, buf, &size, NULL, 0) < 0)
1595				return (-1);
1596			mib[2] = stor;
1597			for (stor = 0, i = 0; i < size; i++)
1598				if (buf[i] == ',')
1599					stor++;
1600			lp.list = calloc(stor + 2, sizeof(struct ctlname));
1601			if (lp.list == NULL)
1602				return (-1);
1603			lp.size = stor + 2;
1604			for (i = 1;
1605			    (lp.list[i].ctl_name = strsep(&buf, ",")) != NULL;
1606			    i++) {
1607				lp.list[i].ctl_type = CTLTYPE_STRUCT;
1608			}
1609			lp.list[i].ctl_name = buf;
1610			lp.list[i].ctl_type = CTLTYPE_STRUCT;
1611			listall(string, &lp);
1612			free(lp.list);
1613			return (-1);
1614		}
1615		mib[3] = atoi(name);
1616		return (4);
1617	} else if (mib[2] == KERN_MALLOC_BUCKETS) {
1618		*typep = CTLTYPE_STRING;
1619		return (3);
1620	} else if (mib[2] == KERN_MALLOC_KMEMSTATS) {
1621		size = BUFSIZ;
1622		stor = mib[2];
1623		mib[2] = KERN_MALLOC_KMEMNAMES;
1624		buf = bufp;
1625		if (sysctl(mib, 3, buf, &size, NULL, 0) < 0)
1626			return (-1);
1627		mib[2] = stor;
1628		if ((name = strsep(bufpp, ".")) == NULL) {
1629			for (stor = 0, i = 0; i < size; i++)
1630				if (buf[i] == ',')
1631					stor++;
1632			lp.list = calloc(stor + 2, sizeof(struct ctlname));
1633			if (lp.list == NULL)
1634				return (-1);
1635			lp.size = stor + 2;
1636			for (i = 1;
1637			    (lp.list[i].ctl_name = strsep(&buf, ",")) != NULL; i++) {
1638				if (lp.list[i].ctl_name[0] == '\0') {
1639					i--;
1640					continue;
1641				}
1642				lp.list[i].ctl_type = CTLTYPE_STRUCT;
1643			}
1644			lp.list[i].ctl_name = buf;
1645			lp.list[i].ctl_type = CTLTYPE_STRUCT;
1646			listall(string, &lp);
1647			free(lp.list);
1648			return (-1);
1649		}
1650		ptr = strstr(buf, name);
1651 tryagain:
1652		if (ptr == NULL) {
1653		       warnx("fourth level name %s in %s is invalid", name,
1654			     string);
1655		       return (-1);
1656		}
1657		if ((*(ptr + strlen(name)) != ',') &&
1658		    (*(ptr + strlen(name)) != '\0')) {
1659			ptr = strstr(ptr + 1, name); /* retry */
1660			goto tryagain;
1661		}
1662		if ((ptr != buf) && (*(ptr - 1) != ',')) {
1663			ptr = strstr(ptr + 1, name); /* retry */
1664			goto tryagain;
1665		}
1666		for (i = 0, stor = 0; buf + i < ptr; i++)
1667			if (buf[i] == ',')
1668				stor++;
1669		mib[3] = stor;
1670		return (4);
1671	} else if (mib[2] == KERN_MALLOC_KMEMNAMES) {
1672		*typep = CTLTYPE_STRING;
1673		return (3);
1674	}
1675	return (-1);
1676}
1677
1678#ifdef CPU_CHIPSET
1679/*
1680 * handle machdep.chipset requests
1681 */
1682struct ctlname chipsetname[] = CTL_CHIPSET_NAMES;
1683struct list chipsetlist = { chipsetname, CPU_CHIPSET_MAXID };
1684
1685int
1686sysctl_chipset(char *string, char **bufpp, int mib[], int flags, int *typep)
1687{
1688	int indx, bwx;
1689	static void *q;
1690	size_t len;
1691	char *p;
1692
1693	if (*bufpp == NULL) {
1694		listall(string, &chipsetlist);
1695		return (-1);
1696	}
1697	if ((indx = findname(string, "third", bufpp, &chipsetlist)) == -1)
1698		return (-1);
1699	mib[2] = indx;
1700	if (!nflag)
1701		printf("%s%s", string, equ);
1702	switch(mib[2]) {
1703	case CPU_CHIPSET_MEM:
1704	case CPU_CHIPSET_DENSE:
1705	case CPU_CHIPSET_PORTS:
1706	case CPU_CHIPSET_HAE_MASK:
1707		len = sizeof(void *);
1708		if (sysctl(mib, 3, &q, &len, NULL, 0) < 0)
1709			return (-1);
1710		printf("%p\n", q);
1711		break;
1712	case CPU_CHIPSET_BWX:
1713		len = sizeof(int);
1714		if (sysctl(mib, 3, &bwx, &len, NULL, 0) < 0)
1715			return (-1);
1716		printf("%d\n", bwx);
1717		break;
1718	case CPU_CHIPSET_TYPE:
1719		if (sysctl(mib, 3, NULL, &len, NULL, 0) < 0)
1720			return (-1);
1721		p = malloc(len + 1);
1722		if (p == NULL)
1723			return (-1);
1724		if (sysctl(mib, 3, p, &len, NULL, 0) < 0)
1725			return (-1);
1726		p[len] = '\0';
1727		printf("%s\n", p);
1728		break;
1729	}
1730	return (-1);
1731}
1732#endif
1733/*
1734 * handle internet requests
1735 */
1736int
1737sysctl_inet(char *string, char **bufpp, int mib[], int flags, int *typep)
1738{
1739	struct list *lp;
1740	int indx;
1741
1742	if (*bufpp == NULL) {
1743		listall(string, &inetlist);
1744		return (-1);
1745	}
1746	if ((indx = findname(string, "third", bufpp, &inetlist)) == -1)
1747		return (-1);
1748	mib[2] = indx;
1749	if (indx < IPPROTO_MAXID && inetvars[indx].list != NULL)
1750		lp = &inetvars[indx];
1751	else if (!flags)
1752		return (-1);
1753	else {
1754		warnx("%s: no variables defined for this protocol", string);
1755		return (-1);
1756	}
1757	if (*bufpp == NULL) {
1758		listall(string, lp);
1759		return (-1);
1760	}
1761	if ((indx = findname(string, "fourth", bufpp, lp)) == -1)
1762		return (-1);
1763	mib[3] = indx;
1764	*typep = lp->list[indx].ctl_type;
1765	return (4);
1766}
1767
1768#ifdef INET6
1769struct ctlname inet6name[] = CTL_IPV6PROTO_NAMES;
1770struct ctlname ip6name[] = IPV6CTL_NAMES;
1771struct ctlname icmp6name[] = ICMPV6CTL_NAMES;
1772struct ctlname pim6name[] = PIM6CTL_NAMES;
1773struct list inet6list = { inet6name, IPV6PROTO_MAXID };
1774struct list inet6vars[] = {
1775/*0*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1776	{ 0, 0 },
1777	{ 0, 0 },
1778	{ 0, 0 },
1779	{ 0, 0 },
1780	{ 0, 0 },
1781/*10*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1782	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1783/*20*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1784	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1785/*30*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1786	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1787/*40*/	{ 0, 0 },
1788	{ ip6name, IPV6CTL_MAXID },	/* ipv6 */
1789	{ 0, 0 },
1790	{ 0, 0 },
1791	{ 0, 0 },
1792	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1793/*50*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1794	{ 0, 0 },
1795	{ 0, 0 },
1796	{ 0, 0 },
1797	{ icmp6name, ICMPV6CTL_MAXID },	/* icmp6 */
1798	{ 0, 0 },
1799/*60*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1800	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1801/*70*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1802	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1803/*80*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1804	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1805/*90*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1806	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1807/*100*/	{ 0, 0 },
1808	{ 0, 0 },
1809	{ 0, 0 },
1810	{ pim6name, PIM6CTL_MAXID },	/* pim6 */
1811};
1812
1813/*
1814 * handle internet6 requests
1815 */
1816int
1817sysctl_inet6(char *string, char **bufpp, int mib[], int flags, int *typep)
1818{
1819	struct list *lp;
1820	int indx;
1821
1822	if (*bufpp == NULL) {
1823		listall(string, &inet6list);
1824		return (-1);
1825	}
1826	if ((indx = findname(string, "third", bufpp, &inet6list)) == -1)
1827		return (-1);
1828	mib[2] = indx;
1829	if (indx < IPV6PROTO_MAXID && inet6vars[indx].list != NULL)
1830		lp = &inet6vars[indx];
1831	else if (!flags)
1832		return (-1);
1833	else {
1834		warnx("%s: no variables defined for this protocol", string);
1835		return (-1);
1836	}
1837	if (*bufpp == NULL) {
1838		listall(string, lp);
1839		return (-1);
1840	}
1841	if ((indx = findname(string, "fourth", bufpp, lp)) == -1)
1842		return (-1);
1843	mib[3] = indx;
1844	*typep = lp->list[indx].ctl_type;
1845	return (4);
1846}
1847#endif
1848
1849struct ctlname ipxname[] = CTL_IPXPROTO_NAMES;
1850struct ctlname ipxpname[] = IPXCTL_NAMES;
1851struct ctlname spxpname[] = SPXCTL_NAMES;
1852struct list ipxlist = { ipxname, IPXCTL_MAXID };
1853struct list ipxvars[] = {
1854	{ ipxpname, IPXCTL_MAXID },	/* ipx */
1855	{ 0, 0 },
1856	{ 0, 0 },
1857	{ 0, 0 },
1858	{ 0, 0 },
1859	{ spxpname, SPXCTL_MAXID },
1860};
1861
1862/*
1863 * Handle internet requests
1864 */
1865int
1866sysctl_ipx(char *string, char **bufpp, int mib[], int flags, int *typep)
1867{
1868	struct list *lp;
1869	int indx;
1870
1871	if (*bufpp == NULL) {
1872		listall(string, &ipxlist);
1873		return (-1);
1874	}
1875	if ((indx = findname(string, "third", bufpp, &ipxlist)) == -1)
1876		return (-1);
1877	mib[2] = indx;
1878	if (indx <= IPXPROTO_SPX && ipxvars[indx].list != NULL)
1879		lp = &ipxvars[indx];
1880	else if (!flags)
1881		return (-1);
1882	else {
1883		warnx("%s: no variables defined for this protocol", string);
1884		return (-1);
1885	}
1886	if (*bufpp == NULL) {
1887		listall(string, lp);
1888		return (-1);
1889	}
1890	if ((indx = findname(string, "fourth", bufpp, lp)) == -1)
1891		return (-1);
1892	mib[3] = indx;
1893	*typep = lp->list[indx].ctl_type;
1894	return (4);
1895}
1896
1897/* handle bpf requests */
1898int
1899sysctl_bpf(char *string, char **bufpp, int mib[], int flags, int *typep)
1900{
1901	int indx;
1902
1903	if (*bufpp == NULL) {
1904		listall(string, &bpflist);
1905		return (-1);
1906	}
1907	if ((indx = findname(string, "third", bufpp, &bpflist)) == -1)
1908		return (-1);
1909	mib[2] = indx;
1910	*typep = CTLTYPE_INT;
1911	return (3);
1912}
1913
1914/*
1915 * Handle SysV semaphore info requests
1916 */
1917int
1918sysctl_seminfo(string, bufpp, mib, flags, typep)
1919	char *string;
1920	char **bufpp;
1921	int mib[];
1922	int flags;
1923	int *typep;
1924{
1925	int indx;
1926
1927	if (*bufpp == NULL) {
1928		listall(string, &semlist);
1929		return (-1);
1930	}
1931	if ((indx = findname(string, "third", bufpp, &semlist)) == -1)
1932		return (-1);
1933	mib[2] = indx;
1934	*typep = CTLTYPE_INT;
1935	return (3);
1936}
1937
1938/*
1939 * Handle SysV shared memory info requests
1940 */
1941int
1942sysctl_shminfo(string, bufpp, mib, flags, typep)
1943	char *string;
1944	char **bufpp;
1945	int mib[];
1946	int flags;
1947	int *typep;
1948{
1949	int indx;
1950
1951	if (*bufpp == NULL) {
1952		listall(string, &shmlist);
1953		return (-1);
1954	}
1955	if ((indx = findname(string, "third", bufpp, &shmlist)) == -1)
1956		return (-1);
1957	mib[2] = indx;
1958	*typep = CTLTYPE_INT;
1959	return (3);
1960}
1961
1962/*
1963 * Handle watchdog support
1964 */
1965int
1966sysctl_watchdog(char *string, char **bufpp, int mib[], int flags,
1967    int *typep)
1968{
1969	int indx;
1970
1971	if (*bufpp == NULL) {
1972		listall(string, &watchdoglist);
1973		return (-1);
1974	}
1975	if ((indx = findname(string, "third", bufpp, &watchdoglist)) == -1)
1976		return (-1);
1977	mib[2] = indx;
1978	*typep = watchdoglist.list[indx].ctl_type;
1979	return (3);
1980}
1981
1982/*
1983 * Handle hardware monitoring sensors support
1984 */
1985int
1986sysctl_sensors(char *string, char **bufpp, int mib[], int flags, int *typep)
1987{
1988	char *name;
1989	int indx;
1990
1991	if (*bufpp == NULL) {
1992		char name[BUFSIZ];
1993
1994		/* scan all sensors */
1995		for (indx = 0; indx < 256; indx++) {
1996			snprintf(name, sizeof(name), "%s.%u", string, indx);
1997			parse(name, 0);
1998		}
1999		return (-1);
2000	}
2001	if ((name = strsep(bufpp, ".")) == NULL) {
2002		warnx("%s: incomplete specification", string);
2003		return (-1);
2004	}
2005	mib[2] = atoi(name);
2006	*typep = CTLTYPE_STRUCT;
2007	return (3);
2008}
2009
2010char	**emul_names;
2011int	emul_num, nemuls;
2012int	emul_init(void);
2013
2014int
2015sysctl_emul(char *string, char *newval, int flags)
2016{
2017	int mib[4], enabled, i, old, print, found = 0;
2018	char *head, *target;
2019	size_t len;
2020
2021	if (emul_init() == -1) {
2022		warnx("emul_init: out of memory");
2023		return (1);
2024	}
2025
2026	mib[0] = CTL_KERN;
2027	mib[1] = KERN_EMUL;
2028	mib[3] = KERN_EMUL_ENABLED;
2029	head = "kern.emul.";
2030
2031	if (aflag || strcmp(string, "kern.emul") == 0) {
2032		if (newval) {
2033			warnx("%s: specification is incomplete", string);
2034			return (1);
2035		}
2036		if (nflag)
2037			printf("%d\n", nemuls);
2038		else
2039			printf("%snemuls%s%d\n", head, equ, nemuls);
2040		for (i = 0; i < emul_num; i++) {
2041			if (emul_names[i] == NULL)
2042				continue;
2043			mib[2] = i + 1;
2044			len = sizeof(int);
2045			if (sysctl(mib, 4, &enabled, &len, NULL, 0) == -1) {
2046				warn("%s", string);
2047				continue;
2048			}
2049			if (nflag)
2050				printf("%d\n", enabled);
2051			else
2052				printf("%s%s%s%d\n", head, emul_names[i], equ,
2053				    enabled);
2054		}
2055		return (0);
2056	}
2057	/* User specified a third level name */
2058	target = strrchr(string, '.');
2059	target++;
2060	if (strcmp(string, "nemuls") == 0) {
2061		if (newval) {
2062			warnx("Operation not permitted");
2063			return (1);
2064		}
2065		if (nflag)
2066			printf("%d\n", nemuls);
2067		else
2068			printf("%snemuls = %d\n", head, nemuls);
2069		return (0);
2070	}
2071	for (i = 0; i < emul_num; i++) {
2072		print = 1;
2073		if (!emul_names[i]) {
2074			print = 0;
2075			if (strcmp(target, emul_names[i-1]))
2076				continue;
2077		} else if (strcmp(target, emul_names[i]))
2078			continue;
2079		found = 1;
2080		mib[2] = i + 1;
2081		len = sizeof(int);
2082		if (newval) {
2083			enabled = atoi(newval);
2084			if (sysctl(mib, 4, &old, &len, &enabled, len) == -1) {
2085				warn("%s", string);
2086				continue;
2087			}
2088			if (print) {
2089				if (nflag)
2090					printf("%d\n", enabled);
2091				else
2092					printf("%s%s: %d -> %d\n", head,
2093					    target, old, enabled);
2094			}
2095		} else {
2096			if (sysctl(mib, 4, &enabled, &len, NULL, 0) == -1) {
2097				warn("%s", string);
2098				continue;
2099			}
2100			if (print) {
2101				if (nflag)
2102					printf("%d\n", enabled);
2103				else
2104					printf("%s%s = %d\n", head, target,
2105					    enabled);
2106			}
2107		}
2108	}
2109	if (!found)
2110		warnx("third level name %s in kern.emul is invalid",
2111		    string);
2112	return (0);
2113
2114
2115}
2116
2117int
2118emul_init(void)
2119{
2120	static int done;
2121	char string[16];
2122	int mib[4], i;
2123	size_t len;
2124
2125	if (done)
2126		return (0);
2127	done = 1;
2128
2129	mib[0] = CTL_KERN;
2130	mib[1] = KERN_EMUL;
2131	mib[2] = KERN_EMUL_NUM;
2132	len = sizeof(int);
2133	if (sysctl(mib, 3, &emul_num, &len, NULL, 0) == -1)
2134		return (-1);
2135
2136	emul_names = calloc(emul_num, sizeof(char *));
2137	if (emul_names == NULL)
2138		return (-1);
2139
2140	nemuls = emul_num;
2141	for (i = 0; i < emul_num; i++) {
2142		mib[2] = i + 1;
2143		mib[3] = KERN_EMUL_NAME;
2144		len = sizeof(string);
2145		if (sysctl(mib, 4, string, &len, NULL, 0) == -1)
2146			break;
2147		if (i > 0 && emul_names[i - 1] &&
2148		    strcmp(string, emul_names[i - 1]) == 0) {
2149			nemuls--;
2150			continue;
2151		}
2152		emul_names[i] = strdup(string);
2153		if (emul_names[i] == NULL) {
2154			free(emul_names);
2155			return (-1);
2156		}
2157	}
2158	return (0);
2159}
2160
2161/*
2162 * Scan a list of names searching for a particular name.
2163 */
2164int
2165findname(char *string, char *level, char **bufp, struct list *namelist)
2166{
2167	char *name;
2168	int i;
2169
2170	if (namelist->list == 0 || (name = strsep(bufp, ".")) == NULL) {
2171		warnx("%s: incomplete specification", string);
2172		return (-1);
2173	}
2174	for (i = 0; i < namelist->size; i++)
2175		if (namelist->list[i].ctl_name != NULL &&
2176		    strcmp(name, namelist->list[i].ctl_name) == 0)
2177			break;
2178	if (i == namelist->size) {
2179		warnx("%s level name %s in %s is invalid", level, name, string);
2180		return (-1);
2181	}
2182	return (i);
2183}
2184
2185void
2186usage(void)
2187{
2188
2189	(void)fprintf(stderr, "usage:\t%s\n\t%s\n\t%s\n",
2190	    "sysctl [-n] variable ...", "sysctl [-nq] -w variable=value ...",
2191	    "sysctl -aA [-n]");
2192	exit(1);
2193}
2194