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