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