xref: /openbsd-src/sbin/sysctl/sysctl.c (revision ac9b4aacc1da35008afea06a5d23c2f2dea9b93e)
1 /*	$OpenBSD: sysctl.c,v 1.183 2012/04/12 12:33:04 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 #include <sys/param.h>
34 #include <sys/gmon.h>
35 #include <sys/mount.h>
36 #include <sys/stat.h>
37 #include <sys/sem.h>
38 #include <sys/shm.h>
39 #include <sys/sysctl.h>
40 #include <sys/socket.h>
41 #include <sys/malloc.h>
42 #include <sys/dkstat.h>
43 #include <sys/uio.h>
44 #include <sys/tty.h>
45 #include <sys/namei.h>
46 #include <sys/sensors.h>
47 #include <machine/cpu.h>
48 #include <net/route.h>
49 #include <net/if.h>
50 
51 #include <netinet/in.h>
52 #include <netinet/in_systm.h>
53 #include <netinet/ip.h>
54 #include <netinet/in_pcb.h>
55 #include <netinet/ip_icmp.h>
56 #include <netinet/ip_ipip.h>
57 #include <netinet/ip_ether.h>
58 #include <netinet/ip_ah.h>
59 #include <netinet/ip_esp.h>
60 #include <netinet/icmp_var.h>
61 #include <netinet/igmp_var.h>
62 #include <netinet/ip_var.h>
63 #include <netinet/udp.h>
64 #include <netinet/udp_var.h>
65 #include <netinet/tcp.h>
66 #include <netinet/tcp_timer.h>
67 #include <netinet/tcp_var.h>
68 #include <netinet/ip_gre.h>
69 #include <netinet/ip_ipcomp.h>
70 #include <netinet/ip_carp.h>
71 #include <netinet/ip_divert.h>
72 
73 #include <net/pfvar.h>
74 #include <net/if_pfsync.h>
75 #include <net/pipex.h>
76 
77 #ifdef INET6
78 #include <netinet/ip6.h>
79 #include <netinet/icmp6.h>
80 #include <netinet6/ip6_var.h>
81 #include <netinet6/pim6_var.h>
82 #include <netinet6/ip6_divert.h>
83 #endif
84 
85 #include <netmpls/mpls.h>
86 
87 #include <uvm/uvm_swap_encrypt.h>
88 
89 #include <ufs/ufs/quota.h>
90 #include <ufs/ufs/inode.h>
91 #include <ufs/ffs/fs.h>
92 #include <ufs/ffs/ffs_extern.h>
93 
94 #include <nfs/rpcv2.h>
95 #include <nfs/nfsproto.h>
96 #include <nfs/nfs.h>
97 
98 #include <ddb/db_var.h>
99 #include <dev/rndvar.h>
100 
101 #include <err.h>
102 #include <errno.h>
103 #include <stdio.h>
104 #include <stdlib.h>
105 #include <string.h>
106 #include <ctype.h>
107 
108 #ifdef CPU_BIOS
109 #include <machine/biosvar.h>
110 #endif
111 
112 struct ctlname topname[] = CTL_NAMES;
113 struct ctlname kernname[] = CTL_KERN_NAMES;
114 struct ctlname vmname[] = CTL_VM_NAMES;
115 struct ctlname fsname[] = CTL_FS_NAMES;
116 struct ctlname netname[] = CTL_NET_NAMES;
117 struct ctlname hwname[] = CTL_HW_NAMES;
118 struct ctlname username[] = CTL_USER_NAMES;
119 struct ctlname debugname[CTL_DEBUG_MAXID];
120 struct ctlname kernmallocname[] = CTL_KERN_MALLOC_NAMES;
121 struct ctlname forkstatname[] = CTL_KERN_FORKSTAT_NAMES;
122 struct ctlname nchstatsname[] = CTL_KERN_NCHSTATS_NAMES;
123 struct ctlname ttysname[] = CTL_KERN_TTY_NAMES;
124 struct ctlname semname[] = CTL_KERN_SEMINFO_NAMES;
125 struct ctlname shmname[] = CTL_KERN_SHMINFO_NAMES;
126 struct ctlname watchdogname[] = CTL_KERN_WATCHDOG_NAMES;
127 struct ctlname tcname[] = CTL_KERN_TIMECOUNTER_NAMES;
128 struct ctlname *vfsname;
129 #ifdef CTL_MACHDEP_NAMES
130 struct ctlname machdepname[] = CTL_MACHDEP_NAMES;
131 #endif
132 struct ctlname ddbname[] = CTL_DDB_NAMES;
133 char names[BUFSIZ];
134 int lastused;
135 
136 /* Maximum size object to expect from sysctl(3) */
137 #define SYSCTL_BUFSIZ	8192
138 
139 struct list {
140 	struct	ctlname *list;
141 	int	size;
142 };
143 struct list toplist = { topname, CTL_MAXID };
144 struct list secondlevel[] = {
145 	{ 0, 0 },			/* CTL_UNSPEC */
146 	{ kernname, KERN_MAXID },	/* CTL_KERN */
147 	{ vmname, VM_MAXID },		/* CTL_VM */
148 	{ fsname, FS_MAXID },		/* CTL_FS */
149 	{ netname, NET_MAXID },		/* CTL_NET */
150 	{ 0, CTL_DEBUG_MAXID },		/* CTL_DEBUG */
151 	{ hwname, HW_MAXID },		/* CTL_HW */
152 #ifdef CTL_MACHDEP_NAMES
153 	{ machdepname, CPU_MAXID },	/* CTL_MACHDEP */
154 #else
155 	{ 0, 0 },			/* CTL_MACHDEP */
156 #endif
157 	{ username, USER_MAXID },	/* CTL_USER_NAMES */
158 	{ ddbname, DBCTL_MAXID },	/* CTL_DDB_NAMES */
159 	{ 0, 0 },			/* CTL_VFS */
160 };
161 
162 int	Aflag, aflag, nflag, qflag;
163 
164 /*
165  * Variables requiring special processing.
166  */
167 #define	CLOCK		0x00000001
168 #define	BOOTTIME	0x00000002
169 #define	CHRDEV		0x00000004
170 #define	BLKDEV		0x00000008
171 #define	RNDSTATS	0x00000010
172 #define	BADDYNAMIC	0x00000020
173 #define	BIOSGEO		0x00000040
174 #define	BIOSDEV		0x00000080
175 #define	MAJ2DEV		0x00000100
176 #define	UNSIGNED	0x00000200
177 #define	KMEMBUCKETS	0x00000400
178 #define	LONGARRAY	0x00000800
179 #define	KMEMSTATS	0x00001000
180 #define	SENSORS		0x00002000
181 
182 /* prototypes */
183 void debuginit(void);
184 void listall(char *, struct list *);
185 void parse(char *, int);
186 void parse_baddynamic(int *, size_t, char *, void **, size_t *, int, int);
187 void usage(void);
188 int findname(char *, char *, char **, struct list *);
189 int sysctl_inet(char *, char **, int *, int, int *);
190 #ifdef INET6
191 int sysctl_inet6(char *, char **, int *, int, int *);
192 #endif
193 int sysctl_bpf(char *, char **, int *, int, int *);
194 int sysctl_mpls(char *, char **, int *, int, int *);
195 int sysctl_pipex(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_tc(char *, char **, int *, int, int *);
209 int sysctl_sensors(char *, char **, int *, int, int *);
210 void print_sensordev(char *, int *, u_int, struct sensordev *);
211 void print_sensor(struct sensor *);
212 int sysctl_emul(char *, char *, int);
213 #ifdef CPU_CHIPSET
214 int sysctl_chipset(char *, char **, int *, int, int *);
215 #endif
216 void vfsinit(void);
217 
218 char *equ = "=";
219 
220 int
221 main(int argc, char *argv[])
222 {
223 	int ch, lvl1;
224 
225 	while ((ch = getopt(argc, argv, "Aanqw")) != -1) {
226 		switch (ch) {
227 
228 		case 'A':
229 			Aflag = 1;
230 			break;
231 
232 		case 'a':
233 			aflag = 1;
234 			break;
235 
236 		case 'n':
237 			nflag = 1;
238 			break;
239 
240 		case 'q':
241 			qflag = 1;
242 			break;
243 
244 		case 'w':
245 			/* flag no longer needed; var=value implies write */
246 			break;
247 
248 		default:
249 			usage();
250 		}
251 	}
252 	argc -= optind;
253 	argv += optind;
254 
255 	if (argc == 0 || (Aflag || aflag)) {
256 		debuginit();
257 		vfsinit();
258 		for (lvl1 = 1; lvl1 < CTL_MAXID; lvl1++)
259 			listall(topname[lvl1].ctl_name, &secondlevel[lvl1]);
260 		return (0);
261 	}
262 	for (; *argv != NULL; ++argv)
263 		parse(*argv, 1);
264 	return (0);
265 }
266 
267 /*
268  * List all variables known to the system.
269  */
270 void
271 listall(char *prefix, struct list *lp)
272 {
273 	char *cp, name[BUFSIZ];
274 	int lvl2, len;
275 
276 	if (lp->list == NULL)
277 		return;
278 	if ((len = strlcpy(name, prefix, sizeof(name))) >= sizeof(name))
279 		errx(1, "%s: name too long", prefix);
280 	cp = name + len++;
281 	*cp++ = '.';
282 	for (lvl2 = 0; lvl2 < lp->size; lvl2++) {
283 		if (lp->list[lvl2].ctl_name == NULL)
284 			continue;
285 		if (strlcpy(cp, lp->list[lvl2].ctl_name,
286 		    sizeof(name) - len) >= sizeof(name) - len)
287 			warn("%s: name too long", lp->list[lvl2].ctl_name);
288 		parse(name, Aflag);
289 	}
290 }
291 
292 /*
293  * Parse a name into a MIB entry.
294  * Lookup and print out the MIB entry if it exists.
295  * Set a new value if requested.
296  */
297 void
298 parse(char *string, int flags)
299 {
300 	int indx, type, state, intval, len;
301 	size_t size, newsize = 0;
302 	int lal = 0, special = 0;
303 	void *newval = NULL;
304 	int64_t quadval;
305 	struct list *lp;
306 	int mib[CTL_MAXNAME];
307 	char *cp, *bufp, buf[SYSCTL_BUFSIZ];
308 
309 	(void)strlcpy(buf, string, sizeof(buf));
310 	bufp = buf;
311 	if ((cp = strchr(string, '=')) != NULL) {
312 		*strchr(buf, '=') = '\0';
313 		*cp++ = '\0';
314 		while (isspace(*cp))
315 			cp++;
316 		newval = cp;
317 		newsize = strlen(cp);
318 	}
319 	if ((indx = findname(string, "top", &bufp, &toplist)) == -1)
320 		return;
321 	mib[0] = indx;
322 	if (indx == CTL_VFS)
323 		vfsinit();
324 	if (indx == CTL_DEBUG)
325 		debuginit();
326 	lp = &secondlevel[indx];
327 	if (lp->list == 0) {
328 		warnx("%s: class is not implemented", topname[indx].ctl_name);
329 		return;
330 	}
331 	if (bufp == NULL) {
332 		listall(topname[indx].ctl_name, lp);
333 		return;
334 	}
335 	if ((indx = findname(string, "second", &bufp, lp)) == -1)
336 		return;
337 	mib[1] = indx;
338 	type = lp->list[indx].ctl_type;
339 	len = 2;
340 	switch (mib[0]) {
341 
342 	case CTL_KERN:
343 		switch (mib[1]) {
344 		case KERN_PROF:
345 			mib[2] = GPROF_STATE;
346 			size = sizeof(state);
347 			if (sysctl(mib, 3, &state, &size, NULL, 0) == -1) {
348 				if (flags == 0)
349 					return;
350 				if (!nflag)
351 					(void)printf("%s: ", string);
352 				(void)puts("kernel is not compiled for profiling");
353 				return;
354 			}
355 			if (!nflag)
356 				(void)printf("%s = %s\n", string,
357 				    state == GMON_PROF_OFF ? "off" : "running");
358 			return;
359 		case KERN_FORKSTAT:
360 			sysctl_forkstat(string, &bufp, mib, flags, &type);
361 			return;
362 		case KERN_TTY:
363 			len = sysctl_tty(string, &bufp, mib, flags, &type);
364 			if (len < 0)
365 				return;
366 			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_TIMECOUNTER:
435 			len = sysctl_tc(string, &bufp, mib, flags,
436 			    &type);
437 			if (len < 0)
438 				return;
439 			break;
440 		case KERN_EMUL:
441 			sysctl_emul(string, newval, flags);
442 			return;
443 		case KERN_FILE2:
444 			if (flags == 0)
445 				return;
446 			warnx("use fstat to view %s information", string);
447 			return;
448 		case KERN_CONSDEV:
449 			special |= CHRDEV;
450 			break;
451 		case KERN_NETLIVELOCKS:
452 			special |= UNSIGNED;
453 			break;
454 		}
455 		break;
456 
457 	case CTL_HW:
458 		switch (mib[1]) {
459 		case HW_DISKSTATS:
460 			/*
461 			 * Only complain if someone asks explicitly for this,
462 			 * otherwise "fail" silently.
463 			 */
464 			if (flags)
465 				warnx("use vmstat to view %s information",
466 				    string);
467 			return;
468 		case HW_SENSORS:
469 			special |= SENSORS;
470 			len = sysctl_sensors(string, &bufp, mib, flags, &type);
471 			if (len < 0)
472 				return;
473 			break;
474 		case HW_PHYSMEM:
475 		case HW_USERMEM:
476 			/*
477 			 * Don't print these; we'll print the 64-bit
478 			 * variants instead.
479 			 */
480 			return;
481 		}
482 		break;
483 
484 	case CTL_VM:
485 		if (mib[1] == VM_LOADAVG) {
486 			double loads[3];
487 
488 			getloadavg(loads, 3);
489 			if (!nflag)
490 				(void)printf("%s%s", string, equ);
491 			(void)printf("%.2f %.2f %.2f\n", loads[0],
492 			    loads[1], loads[2]);
493 			return;
494 		} else if (mib[1] == VM_PSSTRINGS) {
495 			struct _ps_strings _ps;
496 
497 			size = sizeof(_ps);
498 			if (sysctl(mib, 2, &_ps, &size, NULL, 0) == -1) {
499 				if (flags == 0)
500 					return;
501 				if (!nflag)
502 					(void)printf("%s: ", string);
503 				(void)puts("can't find ps strings");
504 				return;
505 			}
506 			if (!nflag)
507 				(void)printf("%s%s", string, equ);
508 			(void)printf("%p\n", _ps.val);
509 			return;
510 		} else if (mib[1] == VM_SWAPENCRYPT) {
511 			len = sysctl_swpenc(string, &bufp, mib, flags, &type);
512 			if (len < 0)
513 				return;
514 
515 			break;
516 		} else if (mib[1] == VM_NKMEMPAGES ||
517 		    mib[1] == VM_ANONMIN ||
518 		    mib[1] == VM_VTEXTMIN ||
519 		    mib[1] == VM_VNODEMIN) {
520 			break;
521 		}
522 		if (flags == 0)
523 			return;
524 		warnx("use vmstat or systat to view %s information", string);
525 		return;
526 
527 		break;
528 
529 	case CTL_NET:
530 		if (mib[1] == PF_INET) {
531 			len = sysctl_inet(string, &bufp, mib, flags, &type);
532 			if (len < 0)
533 				return;
534 
535 			if ((mib[2] == IPPROTO_IP && mib[3] == IPCTL_MRTSTATS) ||
536 			    (mib[2] == IPPROTO_IP && mib[3] == IPCTL_STATS) ||
537 			    (mib[2] == IPPROTO_TCP && mib[3] == TCPCTL_STATS) ||
538 			    (mib[2] == IPPROTO_UDP && mib[3] == UDPCTL_STATS) ||
539 			    (mib[2] == IPPROTO_ESP && mib[3] == ESPCTL_STATS) ||
540 			    (mib[2] == IPPROTO_AH && mib[3] == AHCTL_STATS) ||
541 			    (mib[2] == IPPROTO_IGMP && mib[3] == IGMPCTL_STATS) ||
542 			    (mib[2] == IPPROTO_ETHERIP && mib[3] == ETHERIPCTL_STATS) ||
543 			    (mib[2] == IPPROTO_IPIP && mib[3] == IPIPCTL_STATS) ||
544 			    (mib[2] == IPPROTO_IPCOMP && mib[3] == IPCOMPCTL_STATS) ||
545 			    (mib[2] == IPPROTO_ICMP && mib[3] == ICMPCTL_STATS) ||
546 			    (mib[2] == IPPROTO_CARP && mib[3] == CARPCTL_STATS) ||
547 			    (mib[2] == IPPROTO_PFSYNC && mib[3] == PFSYNCCTL_STATS) ||
548 			    (mib[2] == IPPROTO_DIVERT && mib[3] == DIVERTCTL_STATS)) {
549 				if (flags == 0)
550 					return;
551 				warnx("use netstat to view %s information",
552 				    string);
553 				return;
554 			} else if ((mib[2] == IPPROTO_TCP &&
555 			    mib[3] == TCPCTL_BADDYNAMIC) ||
556 			    (mib[2] == IPPROTO_UDP &&
557 			    mib[3] == UDPCTL_BADDYNAMIC)) {
558 
559 				special |= BADDYNAMIC;
560 
561 				if (newval != NULL)
562 					parse_baddynamic(mib, len, string,
563 					    &newval, &newsize, flags, nflag);
564 			}
565 			break;
566 		}
567 #ifdef INET6
568 		if (mib[1] == PF_INET6) {
569 			len = sysctl_inet6(string, &bufp, mib, flags, &type);
570 			if (len < 0)
571 				return;
572 
573 			if ((mib[2] == IPPROTO_PIM && mib[3] == PIM6CTL_STATS) ||
574 			    (mib[2] == IPPROTO_DIVERT && mib[3] == DIVERT6CTL_STATS)) {
575 				if (flags == 0)
576 					return;
577 				warnx("use netstat to view %s information",
578 				    string);
579 				return;
580 			}
581 			break;
582 		}
583 #endif
584 		if (mib[1] == PF_BPF) {
585 			len = sysctl_bpf(string, &bufp, mib, flags, &type);
586 			if (len < 0)
587 				return;
588 			break;
589 		}
590 		if (mib[1] == PF_MPLS) {
591 			len = sysctl_mpls(string, &bufp, mib, flags, &type);
592 			if (len < 0)
593 				return;
594 			break;
595 		}
596 		if (mib[1] == PF_PIPEX) {
597 			len = sysctl_pipex(string, &bufp, mib, flags, &type);
598 			if (len < 0)
599 				return;
600 			break;
601 		}
602 		if (flags == 0)
603 			return;
604 		warnx("use netstat to view %s information", string);
605 		return;
606 
607 	case CTL_DEBUG:
608 		mib[2] = CTL_DEBUG_VALUE;
609 		len = 3;
610 		break;
611 
612 	case CTL_MACHDEP:
613 #ifdef CPU_CONSDEV
614 		if (mib[1] == CPU_CONSDEV)
615 			special |= CHRDEV;
616 #endif
617 #ifdef CPU_BLK2CHR
618 		if (mib[1] == CPU_BLK2CHR) {
619 			if (bufp == NULL)
620 				return;
621 			mib[2] = makedev(atoi(bufp),0);
622 			bufp = NULL;
623 			len = 3;
624 			special |= CHRDEV;
625 			break;
626 		}
627 #endif
628 #ifdef CPU_CHR2BLK
629 		if (mib[1] == CPU_CHR2BLK) {
630 			if (bufp == NULL)
631 				return;
632 			mib[2] = makedev(atoi(bufp),0);
633 			bufp = NULL;
634 			len = 3;
635 			special |= BLKDEV;
636 			break;
637 		}
638 #endif
639 #ifdef CPU_BIOS
640 		if (mib[1] == CPU_BIOS) {
641 			len = sysctl_bios(string, &bufp, mib, flags, &type);
642 			if (len < 0)
643 				return;
644 			if (mib[2] == BIOS_DEV)
645 				special |= BIOSDEV;
646 			if (mib[2] == BIOS_DISKINFO)
647 				special |= BIOSGEO;
648 			break;
649 		}
650 #endif
651 #ifdef CPU_CHIPSET
652 		if (mib[1] == CPU_CHIPSET) {
653 			len = sysctl_chipset(string, &bufp, mib, flags, &type);
654 			if (len < 0)
655 				return;
656 			break;
657 		}
658 #endif
659 		break;
660 
661 	case CTL_FS:
662 		len = sysctl_fs(string, &bufp, mib, flags, &type);
663 		if (len >= 0)
664 			break;
665 		return;
666 
667 	case CTL_VFS:
668 		if (mib[1])
669 			len = sysctl_vfs(string, &bufp, mib, flags, &type);
670 		else
671 			len = sysctl_vfsgen(string, &bufp, mib, flags, &type);
672 		if (len >= 0) {
673 			if (type == CTLTYPE_STRUCT) {
674 				if (flags)
675 					warnx("use nfsstat to view %s information",
676 					    MOUNT_NFS);
677 				return;
678 			} else
679 				break;
680 		}
681 		return;
682 
683 	case CTL_USER:
684 	case CTL_DDB:
685 		break;
686 
687 	default:
688 		warnx("illegal top level value: %d", mib[0]);
689 		return;
690 
691 	}
692 	if (bufp) {
693 		warnx("name %s in %s is unknown", bufp, string);
694 		return;
695 	}
696 	if (newsize > 0) {
697 		switch (type) {
698 		case CTLTYPE_INT:
699 			errno = 0;
700 			if (special & UNSIGNED)
701 				intval = strtoul(newval, &cp, 10);
702 			else
703 				intval = strtol(newval, &cp, 10);
704 			if (*cp != '\0') {
705 				warnx("%s: illegal value: %s", string,
706 				    (char *)newval);
707 				return;
708 			}
709 			if (errno == ERANGE) {
710 				warnx("%s: value %s out of range", string,
711 				    (char *)newval);
712 				return;
713 			}
714 			newval = &intval;
715 			newsize = sizeof(intval);
716 			break;
717 
718 		case CTLTYPE_QUAD:
719 			/* XXX - assumes sizeof(long long) == sizeof(quad_t) */
720 			(void)sscanf(newval, "%lld", (long long *)&quadval);
721 			newval = &quadval;
722 			newsize = sizeof(quadval);
723 			break;
724 		}
725 	}
726 	size = SYSCTL_BUFSIZ;
727 	if (sysctl(mib, len, buf, &size, newval, newsize) == -1) {
728 		if (flags == 0)
729 			return;
730 		switch (errno) {
731 		case EOPNOTSUPP:
732 			warnx("%s: value is not available", string);
733 			return;
734 		case ENOTDIR:
735 			warnx("%s: specification is incomplete", string);
736 			return;
737 		case ENOMEM:
738 			warnx("%s: type is unknown to this program", string);
739 			return;
740 		case ENXIO:
741 			if (special & BIOSGEO)
742 				return;
743 		default:
744 			warn("%s", string);
745 			return;
746 		}
747 	}
748 	if (special & KMEMBUCKETS) {
749 		struct kmembuckets *kb = (struct kmembuckets *)buf;
750 		if (!nflag)
751 			(void)printf("%s%s", string, equ);
752 		printf("(");
753 		printf("calls = %llu ", (long long)kb->kb_calls);
754 		printf("total_allocated = %llu ", (long long)kb->kb_total);
755 		printf("total_free = %lld ", (long long)kb->kb_totalfree);
756 		printf("elements = %lld ", (long long)kb->kb_elmpercl);
757 		printf("high watermark = %lld ", (long long)kb->kb_highwat);
758 		printf("could_free = %lld", (long long)kb->kb_couldfree);
759 		printf(")\n");
760 		return;
761 	}
762 	if (special & KMEMSTATS) {
763 		struct kmemstats *km = (struct kmemstats *)buf;
764 		int j, first = 1;
765 
766 		if (!nflag)
767 			(void)printf("%s%s", string, equ);
768 		(void)printf("(inuse = %ld, calls = %ld, memuse = %ldK, "
769 		    "limblocks = %d, mapblocks = %d, maxused = %ldK, "
770 		    "limit = %ldK, spare = %ld, sizes = (",
771 		    km->ks_inuse, km->ks_calls,
772 		    (km->ks_memuse + 1023) / 1024, km->ks_limblocks,
773 		    km->ks_mapblocks, (km->ks_maxused + 1023) / 1024,
774 		    (km->ks_limit + 1023) / 1024, km->ks_spare);
775 		for (j = 1 << MINBUCKET; j < 1 << (MINBUCKET + 16); j <<= 1) {
776 			if ((km->ks_size & j ) == 0)
777 				continue;
778 			if (first)
779 				(void)printf("%d", j);
780 			else
781 				(void)printf(",%d", j);
782 			first = 0;
783 		}
784 		if (first)
785 			(void)printf("none");
786 		(void)printf("))\n");
787 		return;
788 	}
789 	if (special & CLOCK) {
790 		struct clockinfo *clkp = (struct clockinfo *)buf;
791 
792 		if (!nflag)
793 			(void)printf("%s%s", string, equ);
794 		(void)printf(
795 		    "tick = %d, tickadj = %d, hz = %d, profhz = %d, stathz = %d\n",
796 		    clkp->tick, clkp->tickadj, clkp->hz, clkp->profhz, clkp->stathz);
797 		return;
798 	}
799 	if (special & BOOTTIME) {
800 		struct timeval *btp = (struct timeval *)buf;
801 		time_t boottime;
802 
803 		if (!nflag) {
804 			boottime = btp->tv_sec;
805 			(void)printf("%s%s%s", string, equ, ctime(&boottime));
806 		} else
807 			(void)printf("%ld\n", btp->tv_sec);
808 		return;
809 	}
810 	if (special & BLKDEV) {
811 		dev_t dev = *(dev_t *)buf;
812 
813 		if (!nflag)
814 			(void)printf("%s%s%s\n", string, equ,
815 			    devname(dev, S_IFBLK));
816 		else
817 			(void)printf("0x%x\n", dev);
818 		return;
819 	}
820 	if (special & CHRDEV) {
821 		dev_t dev = *(dev_t *)buf;
822 
823 		if (!nflag)
824 			(void)printf("%s%s%s\n", string, equ,
825 			    devname(dev, S_IFCHR));
826 		else
827 			(void)printf("0x%x\n", dev);
828 		return;
829 	}
830 #ifdef CPU_BIOS
831 	if (special & BIOSGEO) {
832 		bios_diskinfo_t *pdi = (bios_diskinfo_t *)buf;
833 
834 		if (!nflag)
835 			(void)printf("%s%s", string, equ);
836 		(void)printf("bootdev = 0x%x, "
837 		    "cylinders = %u, heads = %u, sectors = %u\n",
838 		    pdi->bsd_dev, pdi->bios_cylinders,
839 		    pdi->bios_heads, pdi->bios_sectors);
840 		return;
841 	}
842 	if (special & BIOSDEV) {
843 		int dev = *(int*)buf;
844 
845 		if (!nflag)
846 			(void)printf("%s%s", string, equ);
847 		(void) printf("0x%02x\n", dev);
848 		return;
849 	}
850 #endif
851 	if (special & UNSIGNED) {
852 		if (newsize == 0) {
853 			if (!nflag)
854 				(void)printf("%s%s", string, equ);
855 			(void)printf("%u\n", *(u_int *)buf);
856 		} else {
857 			if (!qflag) {
858 				if (!nflag)
859 					(void)printf("%s: %u -> ", string,
860 					    *(u_int *)buf);
861 				(void)printf("%u\n", *(u_int *)newval);
862 			}
863 		}
864 		return;
865 	}
866 	if (special & RNDSTATS) {
867 		struct rndstats *rndstats = (struct rndstats *)buf;
868 		int i;
869 
870 		if (!nflag)
871 			(void)printf("%s%s", string, equ);
872 		(void)printf(
873 		"%llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu",
874 		    (unsigned long long)rndstats->rnd_total,
875 		    (unsigned long long)rndstats->rnd_used,
876 		    (unsigned long long)rndstats->rnd_reads,
877 		    (unsigned long long)rndstats->arc4_reads,
878 		    (unsigned long long)rndstats->arc4_nstirs,
879 		    (unsigned long long)rndstats->arc4_stirs,
880 		    (unsigned long long)rndstats->rnd_pad[0],
881 		    (unsigned long long)rndstats->rnd_pad[1],
882 		    (unsigned long long)rndstats->rnd_pad[2],
883 		    (unsigned long long)rndstats->rnd_pad[3],
884 		    (unsigned long long)rndstats->rnd_pad[4],
885 		    (unsigned long long)rndstats->rnd_waits,
886 		    (unsigned long long)rndstats->rnd_enqs,
887 		    (unsigned long long)rndstats->rnd_deqs,
888 		    (unsigned long long)rndstats->rnd_drops,
889 		    (unsigned long long)rndstats->rnd_drople);
890 		for (i = 0; i < sizeof(rndstats->rnd_ed)/sizeof(rndstats->rnd_ed[0]);
891 		    i++)
892 			(void)printf(" %llu", (unsigned long long)rndstats->rnd_ed[i]);
893 		for (i = 0; i < sizeof(rndstats->rnd_sc)/sizeof(rndstats->rnd_sc[0]);
894 		    i++)
895 			(void)printf(" %llu", (unsigned long long)rndstats->rnd_sc[i]);
896 		for (i = 0; i < sizeof(rndstats->rnd_sb)/sizeof(rndstats->rnd_sb[0]);
897 		    i++)
898 			(void)printf(" %llu", (unsigned long long)rndstats->rnd_sb[i]);
899 		printf("\n");
900 		return;
901 	}
902 	if (special & BADDYNAMIC) {
903 		u_int port, lastport;
904 		u_int32_t *baddynamic = (u_int32_t *)buf;
905 
906 		if (!qflag) {
907 			if (!nflag)
908 				(void)printf("%s%s", string,
909 				    newsize ? ": " : equ);
910 			lastport = 0;
911 			for (port = 0; port < 65536; port++)
912 				if (DP_ISSET(baddynamic, port)) {
913 					(void)printf("%s%u",
914 					    lastport ? "," : "", port);
915 					lastport = port;
916 				}
917 			if (newsize != 0) {
918 				if (!nflag)
919 					fputs(" -> ", stdout);
920 				baddynamic = (u_int32_t *)newval;
921 				lastport = 0;
922 				for (port = 0; port < 65536; port++)
923 					if (DP_ISSET(baddynamic, port)) {
924 						(void)printf("%s%u",
925 						    lastport ? "," : "", port);
926 						lastport = port;
927 					}
928 			}
929 			(void)putchar('\n');
930 		}
931 		return;
932 	}
933 	if (special & LONGARRAY) {
934 		long *la = (long *)buf;
935 		if (!nflag)
936 			printf("%s%s", string, equ);
937 		while (lal--)
938 			printf("%ld%s", *la++, lal? ",":"");
939 		putchar('\n');
940 		return;
941 	}
942 	if (special & SENSORS) {
943 		struct sensor *s = (struct sensor *)buf;
944 
945 		if (size > 0 && (s->flags & SENSOR_FINVALID) == 0) {
946 			if (!nflag)
947 				printf("%s%s", string, equ);
948 			print_sensor(s);
949 			printf("\n");
950 		}
951 		return;
952 	}
953 	switch (type) {
954 	case CTLTYPE_INT:
955 		if (newsize == 0) {
956 			if (!nflag)
957 				(void)printf("%s%s", string, equ);
958 			(void)printf("%d\n", *(int *)buf);
959 		} else {
960 			if (!qflag) {
961 				if (!nflag)
962 					(void)printf("%s: %d -> ", string,
963 					    *(int *)buf);
964 				(void)printf("%d\n", *(int *)newval);
965 			}
966 		}
967 		return;
968 
969 	case CTLTYPE_STRING:
970 		if (newval == NULL) {
971 			if (!nflag)
972 				(void)printf("%s%s", string, equ);
973 			(void)puts(buf);
974 		} else {
975 			if (!qflag) {
976 				if (!nflag)
977 					(void)printf("%s: %s -> ", string, buf);
978 				(void)puts((char *)newval);
979 			}
980 		}
981 		return;
982 
983 	case CTLTYPE_QUAD:
984 		if (newsize == 0) {
985 			long long tmp = *(quad_t *)buf;
986 
987 			if (!nflag)
988 				(void)printf("%s%s", string, equ);
989 			(void)printf("%lld\n", tmp);
990 		} else {
991 			long long tmp = *(quad_t *)buf;
992 
993 			if (!qflag) {
994 				if (!nflag)
995 					(void)printf("%s: %lld -> ",
996 					    string, tmp);
997 				tmp = *(quad_t *)newval;
998 				(void)printf("%qd\n", tmp);
999 			}
1000 		}
1001 		return;
1002 
1003 	case CTLTYPE_STRUCT:
1004 		warnx("%s: unknown structure returned", string);
1005 		return;
1006 
1007 	default:
1008 	case CTLTYPE_NODE:
1009 		warnx("%s: unknown type returned", string);
1010 		return;
1011 	}
1012 }
1013 
1014 static void
1015 parse_ports(char *portspec, int *port, int *high_port)
1016 {
1017 	char *dash;
1018 	const char *errstr;
1019 
1020 	if ((dash = strchr(portspec, '-')) != NULL)
1021 		*dash++ = '\0';
1022 	*port = strtonum(portspec, 0, 65535, &errstr);
1023 	if (errstr != NULL)
1024 		errx(1, "port is %s: %s", errstr, portspec);
1025 	if (dash != NULL) {
1026 		*high_port = strtonum(dash, 0, 65535, &errstr);
1027 		if (errstr != NULL)
1028 			errx(1, "high port is %s: %s", errstr, dash);
1029 		if (*high_port < *port)
1030 			errx(1, "high port %d is lower than %d",
1031 			    *high_port, *port);
1032 	} else
1033 		*high_port = *port;
1034 }
1035 
1036 void
1037 parse_baddynamic(int mib[], size_t len, char *string, void **newvalp,
1038     size_t *newsizep, int flags, int nflag)
1039 {
1040 	static u_int32_t newbaddynamic[DP_MAPSIZE];
1041 	int port, high_port, baddynamic_loaded = 0, full_list_set = 0;
1042 	size_t size;
1043 	char action, *cp;
1044 
1045 	while (*newvalp && (cp = strsep((char **)newvalp, ", \t")) && *cp) {
1046 		if (*cp == '+' || *cp == '-') {
1047 			if (full_list_set)
1048 				errx(1, "cannot mix +/- with full list");
1049 			action = *cp++;
1050 			if (!baddynamic_loaded) {
1051 				size = sizeof(newbaddynamic);
1052 				if (sysctl(mib, len, newbaddynamic,
1053 				    &size, 0, 0) == -1) {
1054 					if (flags == 0)
1055 						return;
1056 					if (!nflag)
1057 						printf("%s: ", string);
1058 					puts("kernel does contain bad dynamic "
1059 					    "port tables");
1060 					return;
1061 				}
1062 				baddynamic_loaded = 1;
1063 			}
1064 			parse_ports(cp, &port, &high_port);
1065 			for (; port <= high_port; port++) {
1066 				if (action == '+')
1067 					DP_SET(newbaddynamic, port);
1068 				else
1069 					DP_CLR(newbaddynamic, port);
1070 			}
1071 		} else {
1072 			if (baddynamic_loaded)
1073 				errx(1, "cannot mix +/- with full list");
1074 			if (!full_list_set) {
1075 				bzero(newbaddynamic, sizeof(newbaddynamic));
1076 				full_list_set = 1;
1077 			}
1078 			parse_ports(cp, &port, &high_port);
1079 			for (; port <= high_port; port++)
1080 				DP_SET(newbaddynamic, port);
1081 		}
1082 	}
1083 	*newvalp = (void *)newbaddynamic;
1084 	*newsizep = sizeof(newbaddynamic);
1085 }
1086 
1087 /*
1088  * Initialize the set of debugging names
1089  */
1090 void
1091 debuginit(void)
1092 {
1093 	int mib[3], loc, i;
1094 	size_t size;
1095 
1096 	if (secondlevel[CTL_DEBUG].list != 0)
1097 		return;
1098 	secondlevel[CTL_DEBUG].list = debugname;
1099 	mib[0] = CTL_DEBUG;
1100 	mib[2] = CTL_DEBUG_NAME;
1101 	for (loc = lastused, i = 0; i < CTL_DEBUG_MAXID; i++) {
1102 		mib[1] = i;
1103 		size = BUFSIZ - loc;
1104 		if (sysctl(mib, 3, &names[loc], &size, NULL, 0) == -1)
1105 			continue;
1106 		debugname[i].ctl_name = &names[loc];
1107 		debugname[i].ctl_type = CTLTYPE_INT;
1108 		loc += size;
1109 	}
1110 	lastused = loc;
1111 }
1112 
1113 struct ctlname vfsgennames[] = CTL_VFSGENCTL_NAMES;
1114 struct ctlname ffsname[] = FFS_NAMES;
1115 struct ctlname nfsname[] = FS_NFS_NAMES;
1116 struct list *vfsvars;
1117 int *vfs_typenums;
1118 
1119 /*
1120  * Initialize the set of filesystem names
1121  */
1122 void
1123 vfsinit(void)
1124 {
1125 	int mib[4], maxtypenum, cnt, loc, size;
1126 	struct vfsconf vfc;
1127 	size_t buflen;
1128 
1129 	if (secondlevel[CTL_VFS].list != 0)
1130 		return;
1131 	mib[0] = CTL_VFS;
1132 	mib[1] = VFS_GENERIC;
1133 	mib[2] = VFS_MAXTYPENUM;
1134 	buflen = 4;
1135 	if (sysctl(mib, 3, &maxtypenum, &buflen, (void *)0, (size_t)0) < 0)
1136 		return;
1137 	maxtypenum++;	/* + generic */
1138 	if ((vfs_typenums = calloc(maxtypenum, sizeof(int))) == NULL)
1139 		return;
1140 	if ((vfsvars = calloc(maxtypenum, sizeof(*vfsvars))) == NULL) {
1141 		free(vfs_typenums);
1142 		return;
1143 	}
1144 	if ((vfsname = calloc(maxtypenum, sizeof(*vfsname))) == NULL) {
1145 		free(vfs_typenums);
1146 		free(vfsvars);
1147 		return;
1148 	}
1149 	mib[2] = VFS_CONF;
1150 	buflen = sizeof vfc;
1151 	for (loc = lastused, cnt = 1; cnt < maxtypenum; cnt++) {
1152 		mib[3] = cnt - 1;
1153 		if (sysctl(mib, 4, &vfc, &buflen, (void *)0, (size_t)0) < 0) {
1154 			if (errno == EOPNOTSUPP)
1155 				continue;
1156 			warn("vfsinit");
1157 			free(vfsname);
1158 			free(vfsvars);
1159 			free(vfs_typenums);
1160 			return;
1161 		}
1162 		if (!strcmp(vfc.vfc_name, MOUNT_FFS)) {
1163 			vfsvars[cnt].list = ffsname;
1164 			vfsvars[cnt].size = FFS_MAXID;
1165 		}
1166 		if (!strcmp(vfc.vfc_name, MOUNT_NFS)) {
1167 			vfsvars[cnt].list = nfsname;
1168 			vfsvars[cnt].size = NFS_MAXID;
1169 		}
1170 		vfs_typenums[cnt] = vfc.vfc_typenum;
1171 		strlcat(&names[loc], vfc.vfc_name, sizeof names - loc);
1172 		vfsname[cnt].ctl_name = &names[loc];
1173 		vfsname[cnt].ctl_type = CTLTYPE_NODE;
1174 		size = strlen(vfc.vfc_name) + 1;
1175 		loc += size;
1176 	}
1177 	lastused = loc;
1178 
1179 	vfsname[0].ctl_name = "mounts";
1180 	vfsname[0].ctl_type = CTLTYPE_NODE;
1181 	vfsvars[0].list = vfsname + 1;
1182 	vfsvars[0].size = maxtypenum - 1;
1183 
1184 	secondlevel[CTL_VFS].list = vfsname;
1185 	secondlevel[CTL_VFS].size = maxtypenum;
1186 	return;
1187 }
1188 
1189 int
1190 sysctl_vfsgen(char *string, char **bufpp, int mib[], int flags, int *typep)
1191 {
1192 	int indx;
1193 	size_t size;
1194 	struct vfsconf vfc;
1195 
1196 	if (*bufpp == NULL) {
1197 		listall(string, vfsvars);
1198 		return (-1);
1199 	}
1200 
1201 	if ((indx = findname(string, "third", bufpp, vfsvars)) == -1)
1202 		return (-1);
1203 
1204 	mib[1] = VFS_GENERIC;
1205 	mib[2] = VFS_CONF;
1206 	mib[3] = indx;
1207 	size = sizeof vfc;
1208 	if (sysctl(mib, 4, &vfc, &size, (void *)0, (size_t)0) < 0) {
1209 		if (errno != EOPNOTSUPP)
1210 			warn("vfs print");
1211 		return -1;
1212 	}
1213 	if (flags == 0 && vfc.vfc_refcount == 0)
1214 		return -1;
1215 	if (!nflag)
1216 		fprintf(stdout, "%s has %d mounted instance%s\n",
1217 		    string, vfc.vfc_refcount,
1218 		    vfc.vfc_refcount != 1 ? "s" : "");
1219 	else
1220 		fprintf(stdout, "%d\n", vfc.vfc_refcount);
1221 
1222 	return -1;
1223 }
1224 
1225 int
1226 sysctl_vfs(char *string, char **bufpp, int mib[], int flags, int *typep)
1227 {
1228 	struct list *lp = &vfsvars[mib[1]];
1229 	int indx;
1230 
1231 	if (lp->list == NULL) {
1232 		if (flags)
1233 			warnx("No variables defined for file system %s", string);
1234 		return (-1);
1235 	}
1236 	if (*bufpp == NULL) {
1237 		listall(string, lp);
1238 		return (-1);
1239 	}
1240 	if ((indx = findname(string, "third", bufpp, lp)) == -1)
1241 		return (-1);
1242 
1243 	mib[1] = vfs_typenums[mib[1]];
1244 	mib[2] = indx;
1245 	*typep = lp->list[indx].ctl_type;
1246 	return (3);
1247 }
1248 
1249 struct ctlname posixname[] = CTL_FS_POSIX_NAMES;
1250 struct list fslist = { posixname, FS_POSIX_MAXID };
1251 
1252 /*
1253  * handle file system requests
1254  */
1255 int
1256 sysctl_fs(char *string, char **bufpp, int mib[], int flags, int *typep)
1257 {
1258 	int indx;
1259 
1260 	if (*bufpp == NULL) {
1261 		listall(string, &fslist);
1262 		return (-1);
1263 	}
1264 	if ((indx = findname(string, "third", bufpp, &fslist)) == -1)
1265 		return (-1);
1266 	mib[2] = indx;
1267 	*typep = fslist.list[indx].ctl_type;
1268 	return (3);
1269 }
1270 
1271 #ifdef CPU_BIOS
1272 struct ctlname biosname[] = CTL_BIOS_NAMES;
1273 struct list bioslist = { biosname, BIOS_MAXID };
1274 
1275 /*
1276  * handle BIOS requests
1277  */
1278 int
1279 sysctl_bios(char *string, char **bufpp, int mib[], int flags, int *typep)
1280 {
1281 	char *name;
1282 	int indx;
1283 
1284 	if (*bufpp == NULL) {
1285 		listall(string, &bioslist);
1286 		return (-1);
1287 	}
1288 	if ((indx = findname(string, "third", bufpp, &bioslist)) == -1)
1289 		return (-1);
1290 	mib[2] = indx;
1291 	if (indx == BIOS_DISKINFO) {
1292 		if (*bufpp == NULL) {
1293 			char name[BUFSIZ];
1294 
1295 			/* scan all the bios devices */
1296 			for (indx = 0; indx < 256; indx++) {
1297 				snprintf(name, sizeof(name), "%s.%u",
1298 				    string, indx);
1299 				parse(name, 1);
1300 			}
1301 			return (-1);
1302 		}
1303 		if ((name = strsep(bufpp, ".")) == NULL) {
1304 			warnx("%s: incomplete specification", string);
1305 			return (-1);
1306 		}
1307 		mib[3] = atoi(name);
1308 		*typep = CTLTYPE_STRUCT;
1309 		return (4);
1310 	} else {
1311 		*typep = bioslist.list[indx].ctl_type;
1312 		return (3);
1313 	}
1314 }
1315 #endif
1316 
1317 struct ctlname swpencname[] = CTL_SWPENC_NAMES;
1318 struct list swpenclist = { swpencname, SWPENC_MAXID };
1319 
1320 /*
1321  * handle swap encrypt requests
1322  */
1323 int
1324 sysctl_swpenc(char *string, char **bufpp, int mib[], int flags, int *typep)
1325 {
1326 	int indx;
1327 
1328 	if (*bufpp == NULL) {
1329 		listall(string, &swpenclist);
1330 		return (-1);
1331 	}
1332 	if ((indx = findname(string, "third", bufpp, &swpenclist)) == -1)
1333 		return (-1);
1334 	mib[2] = indx;
1335 	*typep = swpenclist.list[indx].ctl_type;
1336 	return (3);
1337 }
1338 
1339 struct ctlname inetname[] = CTL_IPPROTO_NAMES;
1340 struct ctlname ipname[] = IPCTL_NAMES;
1341 struct ctlname icmpname[] = ICMPCTL_NAMES;
1342 struct ctlname igmpname[] = IGMPCTL_NAMES;
1343 struct ctlname ipipname[] = IPIPCTL_NAMES;
1344 struct ctlname tcpname[] = TCPCTL_NAMES;
1345 struct ctlname udpname[] = UDPCTL_NAMES;
1346 struct ctlname espname[] = ESPCTL_NAMES;
1347 struct ctlname ahname[] = AHCTL_NAMES;
1348 struct ctlname etheripname[] = ETHERIPCTL_NAMES;
1349 struct ctlname grename[] = GRECTL_NAMES;
1350 struct ctlname mobileipname[] = MOBILEIPCTL_NAMES;
1351 struct ctlname ipcompname[] = IPCOMPCTL_NAMES;
1352 struct ctlname carpname[] = CARPCTL_NAMES;
1353 struct ctlname pfsyncname[] = PFSYNCCTL_NAMES;
1354 struct ctlname divertname[] = DIVERTCTL_NAMES;
1355 struct ctlname bpfname[] = CTL_NET_BPF_NAMES;
1356 struct ctlname ifqname[] = CTL_IFQ_NAMES;
1357 struct ctlname pipexname[] = PIPEXCTL_NAMES;
1358 struct list inetlist = { inetname, IPPROTO_MAXID };
1359 struct list inetvars[] = {
1360 	{ ipname, IPCTL_MAXID },	/* ip */
1361 	{ icmpname, ICMPCTL_MAXID },	/* icmp */
1362 	{ igmpname, IGMPCTL_MAXID },	/* igmp */
1363 	{ 0, 0 },			/* ggmp */
1364 	{ ipipname, IPIPCTL_MAXID },	/* ipencap */
1365 	{ 0, 0 },
1366 	{ tcpname, TCPCTL_MAXID },	/* tcp */
1367 	{ 0, 0 },
1368 	{ 0, 0 },			/* egp */
1369 	{ 0, 0 },
1370 	{ 0, 0 },
1371 	{ 0, 0 },
1372 	{ 0, 0 },			/* pup */
1373 	{ 0, 0 },
1374 	{ 0, 0 },
1375 	{ 0, 0 },
1376 	{ 0, 0 },
1377 	{ udpname, UDPCTL_MAXID },	/* udp */
1378 	{ 0, 0 },
1379 	{ 0, 0 },
1380 	{ 0, 0 },
1381 	{ 0, 0 },
1382 	{ 0, 0 },
1383 	{ 0, 0 },
1384 	{ 0, 0 },
1385 	{ 0, 0 },
1386 	{ 0, 0 },
1387 	{ 0, 0 },
1388 	{ 0, 0 },
1389 	{ 0, 0 },
1390 	{ 0, 0 },
1391 	{ 0, 0 },
1392 	{ 0, 0 },
1393 	{ 0, 0 },
1394 	{ 0, 0 },
1395 	{ 0, 0 },
1396 	{ 0, 0 },
1397 	{ 0, 0 },
1398 	{ 0, 0 },
1399 	{ 0, 0 },
1400 	{ 0, 0 },
1401 	{ 0, 0 },
1402 	{ 0, 0 },
1403 	{ 0, 0 },
1404 	{ 0, 0 },
1405 	{ 0, 0 },
1406 	{ 0, 0 },
1407 	{ grename, GRECTL_MAXID },	/* gre */
1408 	{ 0, 0 },
1409 	{ 0, 0 },
1410 	{ espname, ESPCTL_MAXID },	/* esp */
1411 	{ ahname, AHCTL_MAXID },	/* ah */
1412 	{ 0, 0 },
1413 	{ 0, 0 },
1414 	{ 0, 0 },
1415 	{ mobileipname, MOBILEIPCTL_MAXID }, /* mobileip */
1416 	{ 0, 0 },
1417 	{ 0, 0 },
1418 	{ 0, 0 },
1419 	{ 0, 0 },
1420 	{ 0, 0 },
1421 	{ 0, 0 },
1422 	{ 0, 0 },
1423 	{ 0, 0 },
1424 	{ 0, 0 },
1425 	{ 0, 0 },
1426 	{ 0, 0 },
1427 	{ 0, 0 },
1428 	{ 0, 0 },
1429 	{ 0, 0 },
1430 	{ 0, 0 },
1431 	{ 0, 0 },
1432 	{ 0, 0 },
1433 	{ 0, 0 },
1434 	{ 0, 0 },
1435 	{ 0, 0 },
1436 	{ 0, 0 },
1437 	{ 0, 0 },
1438 	{ 0, 0 },
1439 	{ 0, 0 },
1440 	{ 0, 0 },
1441 	{ 0, 0 },
1442 	{ 0, 0 },
1443 	{ 0, 0 },
1444 	{ 0, 0 },
1445 	{ 0, 0 },
1446 	{ 0, 0 },
1447 	{ 0, 0 },
1448 	{ 0, 0 },
1449 	{ 0, 0 },
1450 	{ 0, 0 },
1451 	{ 0, 0 },
1452 	{ 0, 0 },
1453 	{ 0, 0 },
1454 	{ 0, 0 },
1455 	{ 0, 0 },
1456 	{ 0, 0 },
1457 	{ etheripname, ETHERIPCTL_MAXID },
1458 	{ 0, 0 },
1459 	{ 0, 0 },
1460 	{ 0, 0 },
1461 	{ 0, 0 },
1462 	{ 0, 0 },
1463 	{ 0, 0 },
1464 	{ 0, 0 },
1465 	{ 0, 0 },
1466 	{ 0, 0 },
1467 	{ 0, 0 },
1468 	{ ipcompname, IPCOMPCTL_MAXID },
1469 	{ 0, 0 },
1470 	{ 0, 0 },
1471 	{ 0, 0 },
1472 	{ carpname, CARPCTL_MAXID },
1473 	{ 0, 0 },
1474 	{ 0, 0 },
1475 	{ 0, 0 },
1476 	{ 0, 0 },
1477 	{ 0, 0 },
1478 	{ 0, 0 },
1479 	{ 0, 0 },
1480 	{ 0, 0 },
1481 	{ 0, 0 },
1482 	{ 0, 0 },
1483 	{ 0, 0 },
1484 	{ 0, 0 },
1485 	{ 0, 0 },
1486 	{ 0, 0 },
1487 	{ 0, 0 },
1488 	{ 0, 0 },
1489 	{ 0, 0 },
1490 	{ 0, 0 },
1491 	{ 0, 0 },
1492 	{ 0, 0 },
1493 	{ 0, 0 },
1494 	{ 0, 0 },
1495 	{ 0, 0 },
1496 	{ 0, 0 },
1497 	{ 0, 0 },
1498 	{ 0, 0 },
1499 	{ 0, 0 },
1500 	{ 0, 0 },
1501 	{ 0, 0 },
1502 	{ 0, 0 },
1503 	{ 0, 0 },
1504 	{ 0, 0 },
1505 	{ 0, 0 },
1506 	{ 0, 0 },
1507 	{ 0, 0 },
1508 	{ 0, 0 },
1509 	{ 0, 0 },
1510 	{ 0, 0 },
1511 	{ 0, 0 },
1512 	{ 0, 0 },
1513 	{ 0, 0 },
1514 	{ 0, 0 },
1515 	{ 0, 0 },
1516 	{ 0, 0 },
1517 	{ 0, 0 },
1518 	{ 0, 0 },
1519 	{ 0, 0 },
1520 	{ 0, 0 },
1521 	{ 0, 0 },
1522 	{ 0, 0 },
1523 	{ 0, 0 },
1524 	{ 0, 0 },
1525 	{ 0, 0 },
1526 	{ 0, 0 },
1527 	{ 0, 0 },
1528 	{ 0, 0 },
1529 	{ 0, 0 },
1530 	{ 0, 0 },
1531 	{ 0, 0 },
1532 	{ 0, 0 },
1533 	{ 0, 0 },
1534 	{ 0, 0 },
1535 	{ 0, 0 },
1536 	{ 0, 0 },
1537 	{ 0, 0 },
1538 	{ 0, 0 },
1539 	{ 0, 0 },
1540 	{ 0, 0 },
1541 	{ 0, 0 },
1542 	{ 0, 0 },
1543 	{ 0, 0 },
1544 	{ 0, 0 },
1545 	{ 0, 0 },
1546 	{ 0, 0 },
1547 	{ 0, 0 },
1548 	{ 0, 0 },
1549 	{ 0, 0 },
1550 	{ 0, 0 },
1551 	{ 0, 0 },
1552 	{ 0, 0 },
1553 	{ 0, 0 },
1554 	{ 0, 0 },
1555 	{ 0, 0 },
1556 	{ 0, 0 },
1557 	{ 0, 0 },
1558 	{ 0, 0 },
1559 	{ 0, 0 },
1560 	{ 0, 0 },
1561 	{ 0, 0 },
1562 	{ 0, 0 },
1563 	{ 0, 0 },
1564 	{ 0, 0 },
1565 	{ 0, 0 },
1566 	{ 0, 0 },
1567 	{ 0, 0 },
1568 	{ 0, 0 },
1569 	{ 0, 0 },
1570 	{ 0, 0 },
1571 	{ 0, 0 },
1572 	{ 0, 0 },
1573 	{ 0, 0 },
1574 	{ 0, 0 },
1575 	{ 0, 0 },
1576 	{ 0, 0 },
1577 	{ 0, 0 },
1578 	{ 0, 0 },
1579 	{ 0, 0 },
1580 	{ 0, 0 },
1581 	{ 0, 0 },
1582 	{ 0, 0 },
1583 	{ 0, 0 },
1584 	{ 0, 0 },
1585 	{ 0, 0 },
1586 	{ 0, 0 },
1587 	{ 0, 0 },
1588 	{ 0, 0 },
1589 	{ 0, 0 },
1590 	{ 0, 0 },
1591 	{ 0, 0 },
1592 	{ 0, 0 },
1593 	{ 0, 0 },
1594 	{ 0, 0 },
1595 	{ 0, 0 },
1596 	{ 0, 0 },
1597 	{ 0, 0 },
1598 	{ 0, 0 },
1599 	{ 0, 0 },
1600 	{ 0, 0 },
1601 	{ 0, 0 },
1602 	{ 0, 0 },
1603 	{ 0, 0 },
1604 	{ 0, 0 },
1605 	{ 0, 0 },
1606 	{ 0, 0 },
1607 	{ 0, 0 },
1608 	{ 0, 0 },
1609 	{ pfsyncname, PFSYNCCTL_MAXID },
1610 	{ 0, 0 },
1611 	{ 0, 0 },
1612 	{ 0, 0 },
1613 	{ 0, 0 },
1614 	{ 0, 0 },
1615 	{ 0, 0 },
1616 	{ 0, 0 },
1617 	{ 0, 0 },
1618 	{ divertname, DIVERTCTL_MAXID },
1619 };
1620 struct list bpflist = { bpfname, NET_BPF_MAXID };
1621 struct list ifqlist = { ifqname, IFQCTL_MAXID };
1622 struct list pipexlist = { pipexname, PIPEXCTL_MAXID };
1623 
1624 struct list kernmalloclist = { kernmallocname, KERN_MALLOC_MAXID };
1625 struct list forkstatlist = { forkstatname, KERN_FORKSTAT_MAXID };
1626 struct list nchstatslist = { nchstatsname, KERN_NCHSTATS_MAXID };
1627 struct list ttylist = { ttysname, KERN_TTY_MAXID };
1628 struct list semlist = { semname, KERN_SEMINFO_MAXID };
1629 struct list shmlist = { shmname, KERN_SHMINFO_MAXID };
1630 struct list watchdoglist = { watchdogname, KERN_WATCHDOG_MAXID };
1631 struct list tclist = { tcname, KERN_TIMECOUNTER_MAXID };
1632 
1633 /*
1634  * handle vfs namei cache statistics
1635  */
1636 int
1637 sysctl_nchstats(char *string, char **bufpp, int mib[], int flags, int *typep)
1638 {
1639 	static struct nchstats nch;
1640 	int indx;
1641 	size_t size;
1642 	static int keepvalue = 0;
1643 
1644 	if (*bufpp == NULL) {
1645 		bzero(&nch, sizeof(struct nchstats));
1646 		listall(string, &nchstatslist);
1647 		return (-1);
1648 	}
1649 	if ((indx = findname(string, "third", bufpp, &nchstatslist)) == -1)
1650 		return (-1);
1651 	mib[2] = indx;
1652 	if (*bufpp != NULL) {
1653 		warnx("fourth level name in %s is invalid", string);
1654 		return (-1);
1655 	}
1656 	if (keepvalue == 0) {
1657 		size = sizeof(struct nchstats);
1658 		if (sysctl(mib, 2, &nch, &size, NULL, 0) < 0)
1659 			return (-1);
1660 		keepvalue = 1;
1661 	}
1662 	if (!nflag)
1663 		(void)printf("%s%s", string, equ);
1664 	switch (indx) {
1665 	case KERN_NCHSTATS_GOODHITS:
1666 		(void)printf("%llu\n", nch.ncs_goodhits);
1667 		break;
1668 	case KERN_NCHSTATS_NEGHITS:
1669 		(void)printf("%llu\n", nch.ncs_neghits);
1670 		break;
1671 	case KERN_NCHSTATS_BADHITS:
1672 		(void)printf("%llu\n", nch.ncs_badhits);
1673 		break;
1674 	case KERN_NCHSTATS_FALSEHITS:
1675 		(void)printf("%llu\n", nch.ncs_falsehits);
1676 		break;
1677 	case KERN_NCHSTATS_MISS:
1678 		(void)printf("%llu\n", nch.ncs_miss);
1679 		break;
1680 	case KERN_NCHSTATS_LONG:
1681 		(void)printf("%llu\n", nch.ncs_long);
1682 		break;
1683 	case KERN_NCHSTATS_PASS2:
1684 		(void)printf("%llu\n", nch.ncs_pass2);
1685 		break;
1686 	case KERN_NCHSTATS_2PASSES:
1687 		(void)printf("%llu\n", nch.ncs_2passes);
1688 		break;
1689 	case KERN_NCHSTATS_REVHITS:
1690 		(void)printf("%llu\n", nch.ncs_revhits);
1691 		break;
1692 	case KERN_NCHSTATS_REVMISS:
1693 		(void)printf("%llu\n", nch.ncs_revmiss);
1694 		break;
1695 	case KERN_NCHSTATS_DOTHITS:
1696 		(void)printf("%llu\n", nch.ncs_dothits);
1697 		break;
1698 	case KERN_NCHSTATS_DOTDOTHITS:
1699 		(void)printf("%llu\n", nch.ncs_dotdothits);
1700 		break;
1701 	}
1702 	return (-1);
1703 }
1704 
1705 /*
1706  * handle tty statistics
1707  */
1708 int
1709 sysctl_tty(char *string, char **bufpp, int mib[], int flags, int *typep)
1710 {
1711 	int indx;
1712 
1713 	if (*bufpp == NULL) {
1714 		listall(string, &ttylist);
1715 		return (-1);
1716 	}
1717 	if ((indx = findname(string, "third", bufpp, &ttylist)) == -1)
1718 		return (-1);
1719 	mib[2] = indx;
1720 
1721 	if ((*typep = ttylist.list[indx].ctl_type) == CTLTYPE_STRUCT) {
1722 		if (flags)
1723 			warnx("use pstat -t to view %s information",
1724 			    string);
1725 		return (-1);
1726 	}
1727 	return (3);
1728 }
1729 
1730 /*
1731  * handle fork statistics
1732  */
1733 int
1734 sysctl_forkstat(char *string, char **bufpp, int mib[], int flags, int *typep)
1735 {
1736 	static struct forkstat fks;
1737 	static int keepvalue = 0;
1738 	int indx;
1739 	size_t size;
1740 
1741 	if (*bufpp == NULL) {
1742 		bzero(&fks, sizeof(struct forkstat));
1743 		listall(string, &forkstatlist);
1744 		return (-1);
1745 	}
1746 	if ((indx = findname(string, "third", bufpp, &forkstatlist)) == -1)
1747 		return (-1);
1748 	if (*bufpp != NULL) {
1749 		warnx("fourth level name in %s is invalid", string);
1750 		return (-1);
1751 	}
1752 	if (keepvalue == 0) {
1753 		size = sizeof(struct forkstat);
1754 		if (sysctl(mib, 2, &fks, &size, NULL, 0) < 0)
1755 			return (-1);
1756 		keepvalue = 1;
1757 	}
1758 	if (!nflag)
1759 		(void)printf("%s%s", string, equ);
1760 	switch (indx)	{
1761 	case KERN_FORKSTAT_FORK:
1762 		(void)printf("%d\n", fks.cntfork);
1763 		break;
1764 	case KERN_FORKSTAT_VFORK:
1765 		(void)printf("%d\n", fks.cntvfork);
1766 		break;
1767 	case KERN_FORKSTAT_TFORK:
1768 		(void)printf("%d\n", fks.cnttfork);
1769 		break;
1770 	case KERN_FORKSTAT_KTHREAD:
1771 		(void)printf("%d\n", fks.cntkthread);
1772 		break;
1773 	case KERN_FORKSTAT_SIZFORK:
1774 		(void)printf("%d\n", fks.sizfork);
1775 		break;
1776 	case KERN_FORKSTAT_SIZVFORK:
1777 		(void)printf("%d\n", fks.sizvfork);
1778 		break;
1779 	case KERN_FORKSTAT_SIZTFORK:
1780 		(void)printf("%d\n", fks.siztfork);
1781 		break;
1782 	case KERN_FORKSTAT_SIZKTHREAD:
1783 		(void)printf("%d\n", fks.sizkthread);
1784 		break;
1785 	}
1786 	return (-1);
1787 }
1788 
1789 /*
1790  * handle malloc statistics
1791  */
1792 int
1793 sysctl_malloc(char *string, char **bufpp, int mib[], int flags, int *typep)
1794 {
1795 	int indx, stor, i;
1796 	char *name, bufp[SYSCTL_BUFSIZ], *buf, *ptr;
1797 	struct list lp;
1798 	size_t size;
1799 
1800 	if (*bufpp == NULL) {
1801 		listall(string, &kernmalloclist);
1802 		return (-1);
1803 	}
1804 	if ((indx = findname(string, "third", bufpp, &kernmalloclist)) == -1)
1805 		return (-1);
1806 	mib[2] = indx;
1807 	if (mib[2] == KERN_MALLOC_BUCKET) {
1808 		if ((name = strsep(bufpp, ".")) == NULL) {
1809 			size = SYSCTL_BUFSIZ;
1810 			stor = mib[2];
1811 			mib[2] = KERN_MALLOC_BUCKETS;
1812 			buf = bufp;
1813 			if (sysctl(mib, 3, buf, &size, NULL, 0) < 0)
1814 				return (-1);
1815 			mib[2] = stor;
1816 			for (stor = 0, i = 0; i < size; i++)
1817 				if (buf[i] == ',')
1818 					stor++;
1819 			lp.list = calloc(stor + 2, sizeof(struct ctlname));
1820 			if (lp.list == NULL)
1821 				return (-1);
1822 			lp.size = stor + 2;
1823 			for (i = 1;
1824 			    (lp.list[i].ctl_name = strsep(&buf, ",")) != NULL;
1825 			    i++) {
1826 				lp.list[i].ctl_type = CTLTYPE_STRUCT;
1827 			}
1828 			lp.list[i].ctl_name = buf;
1829 			lp.list[i].ctl_type = CTLTYPE_STRUCT;
1830 			listall(string, &lp);
1831 			free(lp.list);
1832 			return (-1);
1833 		}
1834 		mib[3] = atoi(name);
1835 		return (4);
1836 	} else if (mib[2] == KERN_MALLOC_BUCKETS) {
1837 		*typep = CTLTYPE_STRING;
1838 		return (3);
1839 	} else if (mib[2] == KERN_MALLOC_KMEMSTATS) {
1840 		size = SYSCTL_BUFSIZ;
1841 		stor = mib[2];
1842 		mib[2] = KERN_MALLOC_KMEMNAMES;
1843 		buf = bufp;
1844 		if (sysctl(mib, 3, buf, &size, NULL, 0) < 0)
1845 			return (-1);
1846 		mib[2] = stor;
1847 		if ((name = strsep(bufpp, ".")) == NULL) {
1848 			for (stor = 0, i = 0; i < size; i++)
1849 				if (buf[i] == ',')
1850 					stor++;
1851 			lp.list = calloc(stor + 2, sizeof(struct ctlname));
1852 			if (lp.list == NULL)
1853 				return (-1);
1854 			lp.size = stor + 2;
1855 			for (i = 1;
1856 			    (lp.list[i].ctl_name = strsep(&buf, ",")) != NULL;
1857 			    i++) {
1858 				if (lp.list[i].ctl_name[0] == '\0') {
1859 					i--;
1860 					continue;
1861 				}
1862 				lp.list[i].ctl_type = CTLTYPE_STRUCT;
1863 			}
1864 			lp.list[i].ctl_name = buf;
1865 			lp.list[i].ctl_type = CTLTYPE_STRUCT;
1866 			listall(string, &lp);
1867 			free(lp.list);
1868 			return (-1);
1869 		}
1870 		ptr = strstr(buf, name);
1871  tryagain:
1872 		if (ptr == NULL) {
1873 			warnx("fourth level name %s in %s is invalid", name,
1874 			    string);
1875 			return (-1);
1876 		}
1877 		if ((*(ptr + strlen(name)) != ',') &&
1878 		    (*(ptr + strlen(name)) != '\0')) {
1879 			ptr = strstr(ptr + 1, name); /* retry */
1880 			goto tryagain;
1881 		}
1882 		if ((ptr != buf) && (*(ptr - 1) != ',')) {
1883 			ptr = strstr(ptr + 1, name); /* retry */
1884 			goto tryagain;
1885 		}
1886 		for (i = 0, stor = 0; buf + i < ptr; i++)
1887 			if (buf[i] == ',')
1888 				stor++;
1889 		mib[3] = stor;
1890 		return (4);
1891 	} else if (mib[2] == KERN_MALLOC_KMEMNAMES) {
1892 		*typep = CTLTYPE_STRING;
1893 		return (3);
1894 	}
1895 	return (-1);
1896 }
1897 
1898 #ifdef CPU_CHIPSET
1899 /*
1900  * handle machdep.chipset requests
1901  */
1902 struct ctlname chipsetname[] = CTL_CHIPSET_NAMES;
1903 struct list chipsetlist = { chipsetname, CPU_CHIPSET_MAXID };
1904 
1905 int
1906 sysctl_chipset(char *string, char **bufpp, int mib[], int flags, int *typep)
1907 {
1908 	int indx, bwx;
1909 	static void *q;
1910 	size_t len;
1911 	char *p;
1912 
1913 	if (*bufpp == NULL) {
1914 		listall(string, &chipsetlist);
1915 		return (-1);
1916 	}
1917 	if ((indx = findname(string, "third", bufpp, &chipsetlist)) == -1)
1918 		return (-1);
1919 	mib[2] = indx;
1920 	if (!nflag)
1921 		printf("%s%s", string, equ);
1922 	switch(mib[2]) {
1923 	case CPU_CHIPSET_MEM:
1924 	case CPU_CHIPSET_DENSE:
1925 	case CPU_CHIPSET_PORTS:
1926 	case CPU_CHIPSET_HAE_MASK:
1927 		len = sizeof(void *);
1928 		if (sysctl(mib, 3, &q, &len, NULL, 0) < 0)
1929 			goto done;
1930 		printf("%p", q);
1931 		break;
1932 	case CPU_CHIPSET_BWX:
1933 		len = sizeof(int);
1934 		if (sysctl(mib, 3, &bwx, &len, NULL, 0) < 0)
1935 			goto done;
1936 		printf("%d", bwx);
1937 		break;
1938 	case CPU_CHIPSET_TYPE:
1939 		if (sysctl(mib, 3, NULL, &len, NULL, 0) < 0)
1940 			goto done;
1941 		p = malloc(len + 1);
1942 		if (p == NULL)
1943 			goto done;
1944 		if (sysctl(mib, 3, p, &len, NULL, 0) < 0) {
1945 			free(p);
1946 			goto done;
1947 		}
1948 		p[len] = '\0';
1949 		printf("%s", p);
1950 		free(p);
1951 		break;
1952 	}
1953 done:
1954 	printf("\n");
1955 	return (-1);
1956 }
1957 #endif
1958 /*
1959  * handle internet requests
1960  */
1961 int
1962 sysctl_inet(char *string, char **bufpp, int mib[], int flags, int *typep)
1963 {
1964 	struct list *lp;
1965 	int indx;
1966 
1967 	if (*bufpp == NULL) {
1968 		listall(string, &inetlist);
1969 		return (-1);
1970 	}
1971 	if ((indx = findname(string, "third", bufpp, &inetlist)) == -1)
1972 		return (-1);
1973 	mib[2] = indx;
1974 	if (indx < IPPROTO_MAXID && inetvars[indx].list != NULL)
1975 		lp = &inetvars[indx];
1976 	else if (!flags)
1977 		return (-1);
1978 	else {
1979 		warnx("%s: no variables defined for this protocol", string);
1980 		return (-1);
1981 	}
1982 	if (*bufpp == NULL) {
1983 		listall(string, lp);
1984 		return (-1);
1985 	}
1986 	if ((indx = findname(string, "fourth", bufpp, lp)) == -1)
1987 		return (-1);
1988 	mib[3] = indx;
1989 	*typep = lp->list[indx].ctl_type;
1990 	if (*typep == CTLTYPE_NODE) {
1991 		int tindx;
1992 
1993 		if (*bufpp == NULL) {
1994 			listall(string, &ifqlist);
1995 			return(-1);
1996 		}
1997 		lp = &ifqlist;
1998 		if ((tindx = findname(string, "fifth", bufpp, lp)) == -1)
1999 			return (-1);
2000 		mib[4] = tindx;
2001 		*typep = lp->list[tindx].ctl_type;
2002 		return(5);
2003 	}
2004 	return (4);
2005 }
2006 
2007 #ifdef INET6
2008 struct ctlname inet6name[] = CTL_IPV6PROTO_NAMES;
2009 struct ctlname ip6name[] = IPV6CTL_NAMES;
2010 struct ctlname icmp6name[] = ICMPV6CTL_NAMES;
2011 struct ctlname pim6name[] = PIM6CTL_NAMES;
2012 struct ctlname divert6name[] = DIVERT6CTL_NAMES;
2013 struct list inet6list = { inet6name, IPV6PROTO_MAXID };
2014 struct list inet6vars[] = {
2015 /*0*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2016 	{ 0, 0 },
2017 	{ 0, 0 },
2018 	{ 0, 0 },
2019 	{ 0, 0 },
2020 	{ 0, 0 },
2021 /*10*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2022 	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2023 /*20*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2024 	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2025 /*30*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2026 	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2027 /*40*/	{ 0, 0 },
2028 	{ ip6name, IPV6CTL_MAXID },	/* ipv6 */
2029 	{ 0, 0 },
2030 	{ 0, 0 },
2031 	{ 0, 0 },
2032 	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2033 /*50*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2034 	{ 0, 0 },
2035 	{ 0, 0 },
2036 	{ 0, 0 },
2037 	{ icmp6name, ICMPV6CTL_MAXID },	/* icmp6 */
2038 	{ 0, 0 },
2039 /*60*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2040 	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2041 /*70*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2042 	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2043 /*80*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2044 	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2045 /*90*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2046 	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2047 /*100*/	{ 0, 0 },
2048 	{ 0, 0 },
2049 	{ 0, 0 },
2050 	{ pim6name, PIM6CTL_MAXID },	/* pim6 */
2051 	{ 0, 0 },
2052 	{ 0, 0 },
2053 	{ 0, 0 },
2054 	{ 0, 0 },
2055 	{ 0, 0 },
2056 	{ 0, 0 },
2057 /*110*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2058 	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2059 /*120*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2060 	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2061 /*130*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2062 	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2063 /*140*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2064 	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2065 /*150*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2066 	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2067 /*160*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2068 	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2069 /*170*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2070 	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2071 /*180*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2072 	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2073 /*190*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2074 	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2075 /*200*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2076 	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2077 /*210*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2078 	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2079 /*220*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2080 	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2081 /*230*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2082 	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2083 /*240*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2084 	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2085 /*250*/	{ 0, 0 },
2086 	{ 0, 0 },
2087 	{ 0, 0 },
2088 	{ 0, 0 },
2089 	{ 0, 0 },
2090 	{ 0, 0 },
2091 	{ 0, 0 },
2092 	{ 0, 0 },
2093 	{ divert6name, DIVERT6CTL_MAXID },
2094 };
2095 
2096 /*
2097  * handle internet6 requests
2098  */
2099 int
2100 sysctl_inet6(char *string, char **bufpp, int mib[], int flags, int *typep)
2101 {
2102 	struct list *lp;
2103 	int indx;
2104 
2105 	if (*bufpp == NULL) {
2106 		listall(string, &inet6list);
2107 		return (-1);
2108 	}
2109 	if ((indx = findname(string, "third", bufpp, &inet6list)) == -1)
2110 		return (-1);
2111 	mib[2] = indx;
2112 	if (indx < IPV6PROTO_MAXID && inet6vars[indx].list != NULL)
2113 		lp = &inet6vars[indx];
2114 	else if (!flags)
2115 		return (-1);
2116 	else {
2117 		warnx("%s: no variables defined for this protocol", string);
2118 		return (-1);
2119 	}
2120 	if (*bufpp == NULL) {
2121 		listall(string, lp);
2122 		return (-1);
2123 	}
2124 	if ((indx = findname(string, "fourth", bufpp, lp)) == -1)
2125 		return (-1);
2126 	mib[3] = indx;
2127 	*typep = lp->list[indx].ctl_type;
2128 	return (4);
2129 }
2130 #endif
2131 
2132 /* handle bpf requests */
2133 int
2134 sysctl_bpf(char *string, char **bufpp, int mib[], int flags, int *typep)
2135 {
2136 	int indx;
2137 
2138 	if (*bufpp == NULL) {
2139 		listall(string, &bpflist);
2140 		return (-1);
2141 	}
2142 	if ((indx = findname(string, "third", bufpp, &bpflist)) == -1)
2143 		return (-1);
2144 	mib[2] = indx;
2145 	*typep = CTLTYPE_INT;
2146 	return (3);
2147 }
2148 
2149 struct ctlname mplsname[] = MPLSCTL_NAMES;
2150 struct list mplslist = { mplsname, MPLSCTL_MAXID };
2151 
2152 /* handle MPLS requests */
2153 int
2154 sysctl_mpls(char *string, char **bufpp, int mib[], int flags, int *typep)
2155 {
2156 	struct list *lp;
2157 	int indx;
2158 
2159 	if (*bufpp == NULL) {
2160 		listall(string, &mplslist);
2161 		return (-1);
2162 	}
2163 	if ((indx = findname(string, "third", bufpp, &mplslist)) == -1)
2164 		return (-1);
2165 	mib[2] = indx;
2166 	*typep = mplslist.list[indx].ctl_type;
2167 	if (*typep == CTLTYPE_NODE) {
2168 		int tindx;
2169 
2170 		if (*bufpp == NULL) {
2171 			listall(string, &ifqlist);
2172 			return(-1);
2173 		}
2174 		lp = &ifqlist;
2175 		if ((tindx = findname(string, "fourth", bufpp, lp)) == -1)
2176 			return (-1);
2177 		mib[3] = tindx;
2178 		*typep = lp->list[tindx].ctl_type;
2179 		return(4);
2180 	}
2181 	return (3);
2182 }
2183 
2184 /* handle PIPEX requests */
2185 int
2186 sysctl_pipex(char *string, char **bufpp, int mib[], int flags, int *typep)
2187 {
2188 	int indx;
2189 
2190 	if (*bufpp == NULL) {
2191 		listall(string, &pipexlist);
2192 		return (-1);
2193 	}
2194 	if ((indx = findname(string, "third", bufpp, &pipexlist)) == -1)
2195 		return (-1);
2196 	mib[2] = indx;
2197 	*typep = pipexlist.list[indx].ctl_type;
2198 	return (3);
2199 }
2200 
2201 /*
2202  * Handle SysV semaphore info requests
2203  */
2204 int
2205 sysctl_seminfo(string, bufpp, mib, flags, typep)
2206 	char *string;
2207 	char **bufpp;
2208 	int mib[];
2209 	int flags;
2210 	int *typep;
2211 {
2212 	int indx;
2213 
2214 	if (*bufpp == NULL) {
2215 		listall(string, &semlist);
2216 		return (-1);
2217 	}
2218 	if ((indx = findname(string, "third", bufpp, &semlist)) == -1)
2219 		return (-1);
2220 	mib[2] = indx;
2221 	*typep = CTLTYPE_INT;
2222 	return (3);
2223 }
2224 
2225 /*
2226  * Handle SysV shared memory info requests
2227  */
2228 int
2229 sysctl_shminfo(string, bufpp, mib, flags, typep)
2230 	char *string;
2231 	char **bufpp;
2232 	int mib[];
2233 	int flags;
2234 	int *typep;
2235 {
2236 	int indx;
2237 
2238 	if (*bufpp == NULL) {
2239 		listall(string, &shmlist);
2240 		return (-1);
2241 	}
2242 	if ((indx = findname(string, "third", bufpp, &shmlist)) == -1)
2243 		return (-1);
2244 	mib[2] = indx;
2245 	*typep = CTLTYPE_INT;
2246 	return (3);
2247 }
2248 
2249 /*
2250  * Handle watchdog support
2251  */
2252 int
2253 sysctl_watchdog(char *string, char **bufpp, int mib[], int flags,
2254     int *typep)
2255 {
2256 	int indx;
2257 
2258 	if (*bufpp == NULL) {
2259 		listall(string, &watchdoglist);
2260 		return (-1);
2261 	}
2262 	if ((indx = findname(string, "third", bufpp, &watchdoglist)) == -1)
2263 		return (-1);
2264 	mib[2] = indx;
2265 	*typep = watchdoglist.list[indx].ctl_type;
2266 	return (3);
2267 }
2268 
2269 /*
2270  * Handle timecounter support
2271  */
2272 int
2273 sysctl_tc(char *string, char **bufpp, int mib[], int flags,
2274     int *typep)
2275 {
2276 	int indx;
2277 
2278 	if (*bufpp == NULL) {
2279 		listall(string, &tclist);
2280 		return (-1);
2281 	}
2282 	if ((indx = findname(string, "third", bufpp, &tclist)) == -1)
2283 		return (-1);
2284 	mib[2] = indx;
2285 	*typep = tclist.list[indx].ctl_type;
2286 	return (3);
2287 }
2288 
2289 /*
2290  * Handle hardware monitoring sensors support
2291  */
2292 int
2293 sysctl_sensors(char *string, char **bufpp, int mib[], int flags, int *typep)
2294 {
2295 	char *devname, *typename;
2296 	int dev, numt, i;
2297 	enum sensor_type type;
2298 	struct sensordev snsrdev;
2299 	size_t sdlen = sizeof(snsrdev);
2300 
2301 	if (*bufpp == NULL) {
2302 		char buf[SYSCTL_BUFSIZ];
2303 
2304 		/* scan all sensor devices */
2305 		for (dev = 0; ; dev++) {
2306 			mib[2] = dev;
2307 			if (sysctl(mib, 3, &snsrdev, &sdlen, NULL, 0) == -1) {
2308 				if (errno == ENXIO)
2309 					continue;
2310 				if (errno == ENOENT)
2311 					break;
2312 			}
2313 			snprintf(buf, sizeof(buf), "%s.%s",
2314 			    string, snsrdev.xname);
2315 			print_sensordev(buf, mib, 3, &snsrdev);
2316 		}
2317 		return (-1);
2318 	}
2319 
2320 	/*
2321 	 * If we get this far, it means that some arguments were
2322 	 * provided below hw.sensors tree.
2323 	 * The first branch of hw.sensors tree is the device name.
2324 	 */
2325 	if ((devname = strsep(bufpp, ".")) == NULL) {
2326 		warnx("%s: incomplete specification", string);
2327 		return (-1);
2328 	}
2329 	/* convert sensor device string to an integer */
2330 	for (dev = 0; ; dev++) {
2331 		mib[2] = dev;
2332 		if (sysctl(mib, 3, &snsrdev, &sdlen, NULL, 0) == -1) {
2333 			if (errno == ENXIO)
2334 				continue;
2335 			if (errno == ENOENT)
2336 				break;
2337 		}
2338 		if (strcmp(devname, snsrdev.xname) == 0)
2339 			break;
2340 	}
2341 	if (strcmp(devname, snsrdev.xname) != 0) {
2342 		warnx("%s: sensor device not found: %s", string, devname);
2343 		return (-1);
2344 	}
2345 	if (*bufpp == NULL) {
2346 		/* only device name was provided -- let's print all sensors
2347 		 * that are attached to the specified device
2348 		 */
2349 		print_sensordev(string, mib, 3, &snsrdev);
2350 		return (-1);
2351 	}
2352 
2353 	/*
2354 	 * At this point we have identified the sensor device,
2355 	 * now let's go further and identify sensor type.
2356 	 */
2357 	if ((typename = strsep(bufpp, ".")) == NULL) {
2358 		warnx("%s: incomplete specification", string);
2359 		return (-1);
2360 	}
2361 	numt = -1;
2362 	for (i = 0; typename[i] != '\0'; i++)
2363 		if (isdigit(typename[i])) {
2364 			numt = atoi(&typename[i]);
2365 			typename[i] = '\0';
2366 			break;
2367 		}
2368 	for (type = 0; type < SENSOR_MAX_TYPES; type++)
2369 		if (strcmp(typename, sensor_type_s[type]) == 0)
2370 			break;
2371 	if (type == SENSOR_MAX_TYPES) {
2372 		warnx("%s: sensor type not recognised: %s", string, typename);
2373 		return (-1);
2374 	}
2375 	mib[3] = type;
2376 
2377 	/*
2378 	 * If no integer was provided after sensor_type, let's
2379 	 * print all sensors of the specified type.
2380 	 */
2381 	if (numt == -1) {
2382 		print_sensordev(string, mib, 4, &snsrdev);
2383 		return (-1);
2384 	}
2385 
2386 	/*
2387 	 * At this point we know that we have received a direct request
2388 	 * via command-line for a specific sensor. Let's have the parse()
2389 	 * function deal with it further, and report any errors if such
2390 	 * sensor node does not exist.
2391 	 */
2392 	mib[4] = numt;
2393 	*typep = CTLTYPE_STRUCT;
2394 	return (5);
2395 }
2396 
2397 /*
2398  * Print sensors from the specified device.
2399  */
2400 
2401 void
2402 print_sensordev(char *string, int mib[], u_int mlen, struct sensordev *snsrdev)
2403 {
2404 	char buf[SYSCTL_BUFSIZ];
2405 	enum sensor_type type;
2406 
2407 	if (mlen == 3) {
2408 		for (type = 0; type < SENSOR_MAX_TYPES; type++) {
2409 			mib[3] = type;
2410 			snprintf(buf, sizeof(buf), "%s.%s",
2411 			    string, sensor_type_s[type]);
2412 			print_sensordev(buf, mib, mlen+1, snsrdev);
2413 		}
2414 		return;
2415 	}
2416 
2417 	if (mlen == 4) {
2418 		int numt;
2419 
2420 		type = mib[3];
2421 		for (numt = 0; numt < snsrdev->maxnumt[type]; numt++) {
2422 			mib[4] = numt;
2423 			snprintf(buf, sizeof(buf), "%s%u", string, numt);
2424 			print_sensordev(buf, mib, mlen+1, snsrdev);
2425 		}
2426 		return;
2427 	}
2428 
2429 	if (mlen == 5) {
2430 		struct sensor snsr;
2431 		size_t slen = sizeof(snsr);
2432 
2433 		/* this function is only printing sensors in bulk, so we
2434 		 * do not return any error messages if the requested sensor
2435 		 * is not found by sysctl(3)
2436 		 */
2437 		if (sysctl(mib, 5, &snsr, &slen, NULL, 0) == -1)
2438 			return;
2439 
2440 		if (slen > 0 && (snsr.flags & SENSOR_FINVALID) == 0) {
2441 			if (!nflag)
2442 				printf("%s%s", string, equ);
2443 			print_sensor(&snsr);
2444 			printf("\n");
2445 		}
2446 		return;
2447 	}
2448 }
2449 
2450 void
2451 print_sensor(struct sensor *s)
2452 {
2453 	const char *name;
2454 
2455 	if (s->flags & SENSOR_FUNKNOWN)
2456 		printf("unknown");
2457 	else {
2458 		switch (s->type) {
2459 		case SENSOR_TEMP:
2460 			printf("%.2f degC",
2461 			    (s->value - 273150000) / 1000000.0);
2462 			break;
2463 		case SENSOR_FANRPM:
2464 			printf("%lld RPM", s->value);
2465 			break;
2466 		case SENSOR_VOLTS_DC:
2467 			printf("%.2f VDC", s->value / 1000000.0);
2468 			break;
2469 		case SENSOR_VOLTS_AC:
2470 			printf("%.2f VAC", s->value / 1000000.0);
2471 			break;
2472 		case SENSOR_OHMS:
2473 			printf("%lld ohm", s->value);
2474 			break;
2475 		case SENSOR_WATTS:
2476 			printf("%.2f W", s->value / 1000000.0);
2477 			break;
2478 		case SENSOR_AMPS:
2479 			printf("%.2f A", s->value / 1000000.0);
2480 			break;
2481 		case SENSOR_WATTHOUR:
2482 			printf("%.2f Wh", s->value / 1000000.0);
2483 			break;
2484 		case SENSOR_AMPHOUR:
2485 			printf("%.2f Ah", s->value / 1000000.0);
2486 			break;
2487 		case SENSOR_INDICATOR:
2488 			printf("%s", s->value ? "On" : "Off");
2489 			break;
2490 		case SENSOR_INTEGER:
2491 			printf("%lld", s->value);
2492 			break;
2493 		case SENSOR_PERCENT:
2494 			printf("%.2f%%", s->value / 1000.0);
2495 			break;
2496 		case SENSOR_LUX:
2497 			printf("%.2f lx", s->value / 1000000.0);
2498 			break;
2499 		case SENSOR_DRIVE:
2500 			switch (s->value) {
2501 			case SENSOR_DRIVE_EMPTY:
2502 				name = "empty";
2503 				break;
2504 			case SENSOR_DRIVE_READY:
2505 				name = "ready";
2506 				break;
2507 			case SENSOR_DRIVE_POWERUP:
2508 				name = "powering up";
2509 				break;
2510 			case SENSOR_DRIVE_ONLINE:
2511 				name = "online";
2512 				break;
2513 			case SENSOR_DRIVE_IDLE:
2514 				name = "idle";
2515 				break;
2516 			case SENSOR_DRIVE_ACTIVE:
2517 				name = "active";
2518 				break;
2519 			case SENSOR_DRIVE_REBUILD:
2520 				name = "rebuilding";
2521 				break;
2522 			case SENSOR_DRIVE_POWERDOWN:
2523 				name = "powering down";
2524 				break;
2525 			case SENSOR_DRIVE_FAIL:
2526 				name = "failed";
2527 				break;
2528 			case SENSOR_DRIVE_PFAIL:
2529 				name = "degraded";
2530 				break;
2531 			default:
2532 				name = "unknown";
2533 				break;
2534 			}
2535 			printf(name);
2536 			break;
2537 		case SENSOR_TIMEDELTA:
2538 			printf("%.6f secs", s->value / 1000000000.0);
2539 			break;
2540 		case SENSOR_HUMIDITY:
2541 			printf("%.2f%%", s->value / 1000.0);
2542 			break;
2543 		case SENSOR_FREQ:
2544 			printf("%.2f Hz", s->value / 1000000.0);
2545 			break;
2546 		case SENSOR_ANGLE:
2547 			printf("%3.4f degrees", s->value / 1000000.0);
2548 			break;
2549 		default:
2550 			printf("unknown");
2551 		}
2552 	}
2553 
2554 	if (s->desc[0] != '\0')
2555 		printf(" (%s)", s->desc);
2556 
2557 	switch (s->status) {
2558 	case SENSOR_S_UNSPEC:
2559 		break;
2560 	case SENSOR_S_OK:
2561 		printf(", OK");
2562 		break;
2563 	case SENSOR_S_WARN:
2564 		printf(", WARNING");
2565 		break;
2566 	case SENSOR_S_CRIT:
2567 		printf(", CRITICAL");
2568 		break;
2569 	case SENSOR_S_UNKNOWN:
2570 		printf(", UNKNOWN");
2571 		break;
2572 	}
2573 
2574 	if (s->tv.tv_sec) {
2575 		time_t t = s->tv.tv_sec;
2576 		char ct[26];
2577 
2578 		ctime_r(&t, ct);
2579 		ct[19] = '\0';
2580 		printf(", %s.%03ld", ct, s->tv.tv_usec / 1000);
2581 	}
2582 }
2583 
2584 struct emulname {
2585 	char *name;
2586 	int index;
2587 } *emul_names;
2588 int	emul_num, nemuls;
2589 int	emul_init(void);
2590 
2591 int
2592 sysctl_emul(char *string, char *newval, int flags)
2593 {
2594 	int mib[4], enabled, i, old, print, found = 0;
2595 	char *head, *target;
2596 	size_t len;
2597 
2598 	if (emul_init() == -1) {
2599 		warnx("emul_init: out of memory");
2600 		return (1);
2601 	}
2602 
2603 	mib[0] = CTL_KERN;
2604 	mib[1] = KERN_EMUL;
2605 	mib[3] = KERN_EMUL_ENABLED;
2606 	head = "kern.emul.";
2607 
2608 	if (aflag || strcmp(string, "kern.emul") == 0) {
2609 		if (newval) {
2610 			warnx("%s: specification is incomplete", string);
2611 			return (1);
2612 		}
2613 		if (nflag)
2614 			printf("%d\n", nemuls);
2615 		else
2616 			printf("%snemuls%s%d\n", head, equ, nemuls);
2617 		for (i = 0; i < emul_num; i++) {
2618 			if (emul_names[i].name == NULL)
2619 				break;
2620 			if (i > 0 && strcmp(emul_names[i].name,
2621 			    emul_names[i-1].name) == 0)
2622 				continue;
2623 			mib[2] = emul_names[i].index;
2624 			len = sizeof(int);
2625 			if (sysctl(mib, 4, &enabled, &len, NULL, 0) == -1) {
2626 				warn("%s", string);
2627 				continue;
2628 			}
2629 			if (nflag)
2630 				printf("%d\n", enabled);
2631 			else
2632 				printf("%s%s%s%d\n", head, emul_names[i].name,
2633 				    equ, enabled);
2634 		}
2635 		return (0);
2636 	}
2637 	/* User specified a third level name */
2638 	target = strrchr(string, '.');
2639 	target++;
2640 	if (strcmp(target, "nemuls") == 0) {
2641 		if (newval) {
2642 			warnx("Operation not permitted");
2643 			return (1);
2644 		}
2645 		if (nflag)
2646 			printf("%d\n", nemuls);
2647 		else
2648 			printf("%snemuls = %d\n", head, nemuls);
2649 		return (0);
2650 	}
2651 	print = 1;
2652 	for (i = 0; i < emul_num; i++) {
2653 		if (!emul_names[i].name || (strcmp(target, emul_names[i].name)))
2654 			continue;
2655 		found = 1;
2656 		mib[2] = emul_names[i].index;
2657 		len = sizeof(int);
2658 		if (newval) {
2659 			enabled = atoi(newval);
2660 			if (sysctl(mib, 4, &old, &len, &enabled, len) == -1) {
2661 				warn("%s", string);
2662 				print = 0;
2663 				continue;
2664 			}
2665 			if (print) {
2666 				if (nflag)
2667 					printf("%d\n", enabled);
2668 				else
2669 					printf("%s%s: %d -> %d\n", head,
2670 					    target, old, enabled);
2671 			}
2672 		} else {
2673 			if (sysctl(mib, 4, &enabled, &len, NULL, 0) == -1) {
2674 				warn("%s", string);
2675 				continue;
2676 			}
2677 			if (print) {
2678 				if (nflag)
2679 					printf("%d\n", enabled);
2680 				else
2681 					printf("%s%s = %d\n", head, target,
2682 					    enabled);
2683 			}
2684 		}
2685 		print = 0;
2686 	}
2687 	if (!found)
2688 		warnx("third level name %s in kern.emul is invalid",
2689 		    string);
2690 	return (0);
2691 
2692 
2693 }
2694 
2695 int
2696 emulcmp(const void *m, const void *n)
2697 {
2698 	const struct emulname *a = m, *b = n;
2699 
2700 	if (!a || !a->name)
2701 		return 1;
2702 	if (!b || !b->name)
2703 		return -1;
2704 	return (strcmp(a->name, b->name));
2705 }
2706 
2707 int
2708 emul_init(void)
2709 {
2710 	static int done;
2711 	char string[16];
2712 	int mib[4], i;
2713 	size_t len;
2714 
2715 	if (done)
2716 		return (0);
2717 	done = 1;
2718 
2719 	mib[0] = CTL_KERN;
2720 	mib[1] = KERN_EMUL;
2721 	mib[2] = KERN_EMUL_NUM;
2722 	len = sizeof(int);
2723 	if (sysctl(mib, 3, &emul_num, &len, NULL, 0) == -1)
2724 		return (-1);
2725 
2726 	emul_names = calloc(emul_num, sizeof(*emul_names));
2727 	if (emul_names == NULL)
2728 		return (-1);
2729 
2730 	nemuls = emul_num;
2731 	for (i = 0; i < emul_num; i++) {
2732 		emul_names[i].index = mib[2] = i + 1;
2733 		mib[3] = KERN_EMUL_NAME;
2734 		len = sizeof(string);
2735 		if (sysctl(mib, 4, string, &len, NULL, 0) == -1)
2736 			continue;
2737 		if (strcmp(string, "native") == 0)
2738 			continue;
2739 		emul_names[i].name = strdup(string);
2740 		if (emul_names[i].name == NULL) {
2741 			free(emul_names);
2742 			return (-1);
2743 		}
2744 	}
2745 	qsort(emul_names, nemuls, sizeof(*emul_names), emulcmp);
2746 	for (i = 0; i < emul_num; i++) {
2747 		if (!emul_names[i].name || (i > 0 &&
2748 		    strcmp(emul_names[i].name, emul_names[i - 1].name) == 0))
2749 			nemuls--;
2750 	}
2751 	return (0);
2752 }
2753 
2754 /*
2755  * Scan a list of names searching for a particular name.
2756  */
2757 int
2758 findname(char *string, char *level, char **bufp, struct list *namelist)
2759 {
2760 	char *name;
2761 	int i;
2762 
2763 	if (namelist->list == 0 || (name = strsep(bufp, ".")) == NULL) {
2764 		warnx("%s: incomplete specification", string);
2765 		return (-1);
2766 	}
2767 	for (i = 0; i < namelist->size; i++)
2768 		if (namelist->list[i].ctl_name != NULL &&
2769 		    strcmp(name, namelist->list[i].ctl_name) == 0)
2770 			break;
2771 	if (i == namelist->size) {
2772 		warnx("%s level name %s in %s is invalid", level, name, string);
2773 		return (-1);
2774 	}
2775 	return (i);
2776 }
2777 
2778 void
2779 usage(void)
2780 {
2781 
2782 	(void)fprintf(stderr,
2783 	    "usage: sysctl [-Aan]\n"
2784 	    "       sysctl [-n] name ...\n"
2785 	    "       sysctl [-nq] name=value ...\n");
2786 	exit(1);
2787 }
2788