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