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