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