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