sysctl.c revision 121306
11553Srgrimes/*
21553Srgrimes * Copyright (c) 1993
31553Srgrimes *	The Regents of the University of California.  All rights reserved.
41553Srgrimes *
51553Srgrimes * Redistribution and use in source and binary forms, with or without
61553Srgrimes * modification, are permitted provided that the following conditions
71553Srgrimes * are met:
81553Srgrimes * 1. Redistributions of source code must retain the above copyright
91553Srgrimes *    notice, this list of conditions and the following disclaimer.
101553Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
111553Srgrimes *    notice, this list of conditions and the following disclaimer in the
121553Srgrimes *    documentation and/or other materials provided with the distribution.
131553Srgrimes * 3. All advertising materials mentioning features or use of this software
141553Srgrimes *    must display the following acknowledgement:
151553Srgrimes *	This product includes software developed by the University of
161553Srgrimes *	California, Berkeley and its contributors.
171553Srgrimes * 4. Neither the name of the University nor the names of its contributors
181553Srgrimes *    may be used to endorse or promote products derived from this software
191553Srgrimes *    without specific prior written permission.
201553Srgrimes *
211553Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
221553Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
231553Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
241553Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
251553Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
261553Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
271553Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
281553Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
291553Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
301553Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
311553Srgrimes * SUCH DAMAGE.
321553Srgrimes */
331553Srgrimes
341553Srgrimes#ifndef lint
3530602Scharnierstatic const char copyright[] =
361553Srgrimes"@(#) Copyright (c) 1993\n\
371553Srgrimes	The Regents of the University of California.  All rights reserved.\n";
381553Srgrimes#endif /* not lint */
391553Srgrimes
401553Srgrimes#ifndef lint
4130602Scharnier#if 0
4230602Scharnierstatic char sccsid[] = "@(#)from: sysctl.c	8.1 (Berkeley) 6/6/93";
4330602Scharnier#endif
446284Swollmanstatic const char rcsid[] =
4550476Speter  "$FreeBSD: head/sbin/sysctl/sysctl.c 121306 2003-10-21 16:49:30Z silby $";
461553Srgrimes#endif /* not lint */
471553Srgrimes
4892066Sluigi#ifdef __i386__
4992066Sluigi#include <sys/reboot.h>		/* used for bootdev parsing */
5092066Sluigi#endif
5191217Sbde#include <sys/param.h>
5291217Sbde#include <sys/time.h>
5391217Sbde#include <sys/resource.h>
541553Srgrimes#include <sys/stat.h>
551553Srgrimes#include <sys/sysctl.h>
56109097Sdillon#include <sys/vmmeter.h>
571553Srgrimes
5830602Scharnier#include <ctype.h>
5930602Scharnier#include <err.h>
601553Srgrimes#include <errno.h>
611553Srgrimes#include <stdio.h>
621553Srgrimes#include <stdlib.h>
631553Srgrimes#include <string.h>
6430602Scharnier#include <unistd.h>
651553Srgrimes
6688006Sluigistatic int	aflag, bflag, dflag, eflag, Nflag, nflag, oflag, xflag;
671553Srgrimes
6812946Sphkstatic int	oidfmt(int *, int, char *, u_int *);
6912946Sphkstatic void	parse(char *);
7012946Sphkstatic int	show_var(int *, int);
7112946Sphkstatic int	sysctl_all (int *oid, int len);
7212946Sphkstatic int	name2oid(char *, int *);
731553Srgrimes
7488696Sphkstatic void	set_T_dev_t (char *, void **, int *);
7588696Sphk
7612946Sphkstatic void
7712946Sphkusage(void)
7812946Sphk{
791553Srgrimes
8077330Sdes	(void)fprintf(stderr, "%s\n%s\n",
8188006Sluigi	    "usage: sysctl [-bdeNnox] variable[=value] ...",
8288006Sluigi	    "       sysctl [-bdeNnox] -a");
8312946Sphk	exit(1);
8412946Sphk}
851553Srgrimes
861553Srgrimesint
8712946Sphkmain(int argc, char **argv)
881553Srgrimes{
8912946Sphk	int ch;
9012946Sphk	setbuf(stdout,0);
9112946Sphk	setbuf(stderr,0);
921553Srgrimes
9388006Sluigi	while ((ch = getopt(argc, argv, "AabdeNnowxX")) != -1) {
941553Srgrimes		switch (ch) {
9571034Sdes		case 'A':
9677330Sdes			/* compatibility */
9777330Sdes			aflag = oflag = 1;
9871034Sdes			break;
9971034Sdes		case 'a':
10071034Sdes			aflag = 1;
10171034Sdes			break;
10271034Sdes		case 'b':
10371034Sdes			bflag = 1;
10471034Sdes			break;
10588006Sluigi		case 'd':
10688006Sluigi			dflag = 1;
10788006Sluigi			break;
10885747Stobez		case 'e':
10985747Stobez			eflag = 1;
11085747Stobez			break;
11171034Sdes		case 'N':
11271034Sdes			Nflag = 1;
11371034Sdes			break;
11471034Sdes		case 'n':
11571034Sdes			nflag = 1;
11671034Sdes			break;
11777330Sdes		case 'o':
11877330Sdes			oflag = 1;
11977330Sdes			break;
12071034Sdes		case 'w':
12177330Sdes			/* compatibility */
12277330Sdes			/* ignored */
12371034Sdes			break;
12471034Sdes		case 'X':
12577330Sdes			/* compatibility */
12677330Sdes			aflag = xflag = 1;
12771034Sdes			break;
12877330Sdes		case 'x':
12977330Sdes			xflag = 1;
13077330Sdes			break;
13171034Sdes		default:
13271034Sdes			usage();
1331553Srgrimes		}
1341553Srgrimes	}
1351553Srgrimes	argc -= optind;
1361553Srgrimes	argv += optind;
1371553Srgrimes
13877330Sdes	if (Nflag && nflag)
13942456Sdes		usage();
14077330Sdes	if (aflag && argc == 0)
14177330Sdes		exit(sysctl_all(0, 0));
1421553Srgrimes	if (argc == 0)
1431553Srgrimes		usage();
1441553Srgrimes	while (argc-- > 0)
14512946Sphk		parse(*argv++);
1461553Srgrimes	exit(0);
1471553Srgrimes}
1481553Srgrimes
1491553Srgrimes/*
1501553Srgrimes * Parse a name into a MIB entry.
1511553Srgrimes * Lookup and print out the MIB entry if it exists.
1521553Srgrimes * Set a new value if requested.
1531553Srgrimes */
15412946Sphkstatic void
15512946Sphkparse(char *string)
1561553Srgrimes{
15712946Sphk	int len, i, j;
1581553Srgrimes	void *newval = 0;
15978434Spirzyk	int intval;
16078434Spirzyk	unsigned int uintval;
16178434Spirzyk	long longval;
16278434Spirzyk	unsigned long ulongval;
16378434Spirzyk	size_t newsize = 0;
1641553Srgrimes	quad_t quadval;
1651553Srgrimes	int mib[CTL_MAXNAME];
166116383Srwatson	char *cp, *bufp, buf[BUFSIZ], *endptr, fmt[BUFSIZ];
16712946Sphk	u_int kind;
1681553Srgrimes
1691553Srgrimes	bufp = buf;
1701553Srgrimes	snprintf(buf, BUFSIZ, "%s", string);
1711553Srgrimes	if ((cp = strchr(string, '=')) != NULL) {
1721553Srgrimes		*strchr(buf, '=') = '\0';
1731553Srgrimes		*cp++ = '\0';
1741553Srgrimes		while (isspace(*cp))
1751553Srgrimes			cp++;
1761553Srgrimes		newval = cp;
1771553Srgrimes		newsize = strlen(cp);
1781553Srgrimes	}
17912946Sphk	len = name2oid(bufp, mib);
1801553Srgrimes
18112946Sphk	if (len < 0)
18230602Scharnier		errx(1, "unknown oid '%s'", bufp);
1831553Srgrimes
18488696Sphk	if (oidfmt(mib, len, fmt, &kind))
18530602Scharnier		err(1, "couldn't find format of oid '%s'", bufp);
1861553Srgrimes
18777330Sdes	if (newval == NULL) {
18812946Sphk		if ((kind & CTLTYPE) == CTLTYPE_NODE) {
18912946Sphk			sysctl_all(mib, len);
19012946Sphk		} else {
19112946Sphk			i = show_var(mib, len);
19212946Sphk			if (!i && !bflag)
19312946Sphk				putchar('\n');
1941553Srgrimes		}
19512946Sphk	} else {
19612946Sphk		if ((kind & CTLTYPE) == CTLTYPE_NODE)
19712946Sphk			errx(1, "oid '%s' isn't a leaf node", bufp);
1981553Srgrimes
19912946Sphk		if (!(kind&CTLFLAG_WR))
200121306Ssilby			if (kind & CTLFLAG_TUN) {
201121306Ssilby				fprintf(stderr, "Tunable values are set in /boot/loader.conf and require a reboot to take effect.\n");
202121306Ssilby				errx(1, "oid '%s' is a tunable.", bufp);
203121306Ssilby			} else {
204121306Ssilby				errx(1, "oid '%s' is read only", bufp);
205121306Ssilby		}
206116383Srwatson
207116383Srwatson		if ((kind & CTLTYPE) == CTLTYPE_INT ||
208116383Srwatson		    (kind & CTLTYPE) == CTLTYPE_UINT ||
209116383Srwatson		    (kind & CTLTYPE) == CTLTYPE_LONG ||
210116383Srwatson		    (kind & CTLTYPE) == CTLTYPE_ULONG) {
211116383Srwatson			if (strlen(newval) == 0)
212116383Srwatson				errx(1, "empty numeric value");
213116383Srwatson		}
21412946Sphk
21512946Sphk		switch (kind & CTLTYPE) {
21612946Sphk			case CTLTYPE_INT:
217116383Srwatson				intval = (int) strtol(newval, &endptr, 0);
218116383Srwatson				if (endptr == newval || *endptr != '\0')
219116383Srwatson					errx(1, "invalid integer '%s'",
220116383Srwatson					    newval);
22112946Sphk				newval = &intval;
22277928Sdd				newsize = sizeof(intval);
2231553Srgrimes				break;
22478434Spirzyk			case CTLTYPE_UINT:
225116383Srwatson				uintval = (int) strtoul(newval, &endptr, 0);
226116383Srwatson				if (endptr == newval || *endptr != '\0')
227116383Srwatson					errx(1, "invalid unsigned integer '%s'",
228116383Srwatson					    newval);
22978434Spirzyk				newval = &uintval;
23078434Spirzyk				newsize = sizeof uintval;
23112946Sphk				break;
23278434Spirzyk			case CTLTYPE_LONG:
233116383Srwatson				longval = strtol(newval, &endptr, 0);
234116383Srwatson				if (endptr == newval || *endptr != '\0')
235116383Srwatson					errx(1, "invalid long integer '%s'",
236116383Srwatson					    newval);
23778434Spirzyk				newval = &longval;
23878434Spirzyk				newsize = sizeof longval;
23978434Spirzyk				break;
24078434Spirzyk			case CTLTYPE_ULONG:
241116383Srwatson				ulongval = strtoul(newval, &endptr, 0);
242116383Srwatson				if (endptr == newval || *endptr != '\0')
243116383Srwatson					errx(1, "invalid unsigned long integer"
244116383Srwatson					    " '%s'", newval);
24578434Spirzyk				newval = &ulongval;
24678434Spirzyk				newsize = sizeof ulongval;
24778434Spirzyk				break;
24812946Sphk			case CTLTYPE_STRING:
24912946Sphk				break;
25012946Sphk			case CTLTYPE_QUAD:
25112946Sphk				sscanf(newval, "%qd", &quadval);
25212946Sphk				newval = &quadval;
25377928Sdd				newsize = sizeof(quadval);
25412946Sphk				break;
25588696Sphk			case CTLTYPE_OPAQUE:
25688696Sphk				if (strcmp(fmt, "T,dev_t") == 0) {
25788696Sphk					set_T_dev_t ((char*)newval, &newval, &newsize);
25888696Sphk					break;
25988696Sphk				}
26088696Sphk				/* FALLTHROUGH */
26112946Sphk			default:
26212946Sphk				errx(1, "oid '%s' is type %d,"
26331214Sjdp					" cannot set that", bufp,
26431214Sjdp					kind & CTLTYPE);
2651553Srgrimes		}
2661553Srgrimes
26712946Sphk		i = show_var(mib, len);
26812946Sphk		if (sysctl(mib, len, 0, 0, newval, newsize) == -1) {
26912946Sphk			if (!i && !bflag)
27012946Sphk				putchar('\n');
27112946Sphk			switch (errno) {
27212946Sphk			case EOPNOTSUPP:
27330602Scharnier				errx(1, "%s: value is not available",
27412946Sphk					string);
27512946Sphk			case ENOTDIR:
27630602Scharnier				errx(1, "%s: specification is incomplete",
27712946Sphk					string);
27812946Sphk			case ENOMEM:
27930602Scharnier				errx(1, "%s: type is unknown to this program",
28012946Sphk					string);
28112946Sphk			default:
28230602Scharnier				warn("%s", string);
28312946Sphk				return;
28412946Sphk			}
28512946Sphk		}
28612946Sphk		if (!bflag)
28712946Sphk			printf(" -> ");
28812946Sphk		i = nflag;
28912946Sphk		nflag = 1;
29012946Sphk		j = show_var(mib, len);
29112946Sphk		if (!j && !bflag)
29212946Sphk			putchar('\n');
29312946Sphk		nflag = i;
29412946Sphk	}
29512946Sphk}
2961553Srgrimes
29712946Sphk/* These functions will dump out various interesting structures. */
2981553Srgrimes
29912946Sphkstatic int
30012946SphkS_clockinfo(int l2, void *p)
30112946Sphk{
30212946Sphk	struct clockinfo *ci = (struct clockinfo*)p;
30397232Salfred	if (l2 != sizeof(*ci)) {
30497232Salfred		warnx("S_clockinfo %d != %d", l2, sizeof(*ci));
30597232Salfred		return (0);
30697232Salfred	}
30794752Sphk	printf("{ hz = %d, tick = %d, profhz = %d, stathz = %d }",
30894752Sphk		ci->hz, ci->tick, ci->profhz, ci->stathz);
30912946Sphk	return (0);
31012946Sphk}
3111553Srgrimes
31212946Sphkstatic int
31312946SphkS_loadavg(int l2, void *p)
31412946Sphk{
31512946Sphk	struct loadavg *tv = (struct loadavg*)p;
3168857Srgrimes
31797232Salfred	if (l2 != sizeof(*tv)) {
31897232Salfred		warnx("S_loadavg %d != %d", l2, sizeof(*tv));
31997232Salfred		return (0);
32097232Salfred	}
32112946Sphk	printf("{ %.2f %.2f %.2f }",
32212946Sphk		(double)tv->ldavg[0]/(double)tv->fscale,
32312946Sphk		(double)tv->ldavg[1]/(double)tv->fscale,
32412946Sphk		(double)tv->ldavg[2]/(double)tv->fscale);
32512946Sphk	return (0);
32612946Sphk}
3271553Srgrimes
32812946Sphkstatic int
32912946SphkS_timeval(int l2, void *p)
33012946Sphk{
33112946Sphk	struct timeval *tv = (struct timeval*)p;
33237266Sbde	time_t tv_sec;
33312946Sphk	char *p1, *p2;
3341553Srgrimes
33597232Salfred	if (l2 != sizeof(*tv)) {
33697232Salfred		warnx("S_timeval %d != %d", l2, sizeof(*tv));
33797232Salfred		return (0);
33897232Salfred	}
33912946Sphk	printf("{ sec = %ld, usec = %ld } ",
34012946Sphk		tv->tv_sec, tv->tv_usec);
34137266Sbde	tv_sec = tv->tv_sec;
34237266Sbde	p1 = strdup(ctime(&tv_sec));
34312946Sphk	for (p2=p1; *p2 ; p2++)
34412946Sphk		if (*p2 == '\n')
34512946Sphk			*p2 = '\0';
34612946Sphk	fputs(p1, stdout);
34712946Sphk	return (0);
34812946Sphk}
3491553Srgrimes
35012946Sphkstatic int
351109097SdillonS_vmtotal(int l2, void *p)
352109097Sdillon{
353109097Sdillon	struct vmtotal *v = (struct vmtotal *)p;
354109113Sdillon	int pageKilo = getpagesize() / 1024;
355109097Sdillon
356109097Sdillon	if (l2 != sizeof(*v)) {
357109097Sdillon		warnx("S_vmtotal %d != %d", l2, sizeof(*v));
358109097Sdillon		return (0);
359109097Sdillon	}
360109097Sdillon
361109113Sdillon	printf(
362109113Sdillon	    "\nSystem wide totals computed every five seconds:"
363109113Sdillon	    " (values in kilobytes)\n");
364109097Sdillon	printf("===============================================\n");
365109113Sdillon	printf(
366109113Sdillon	    "Processes:\t\t(RUNQ: %hu Disk Wait: %hu Page Wait: "
367109113Sdillon	    "%hu Sleep: %hu)\n",
368109113Sdillon	    v->t_rq, v->t_dw, v->t_pw, v->t_sl);
369109113Sdillon	printf(
370109113Sdillon	    "Virtual Memory:\t\t(Total: %luK, Active %lldK)\n",
371109113Sdillon	    (unsigned long)v->t_vm / 1024,
372109113Sdillon	    (long long)v->t_avm * pageKilo);
373109113Sdillon	printf("Real Memory:\t\t(Total: %lldK Active %lldK)\n",
374109113Sdillon	    (long long)v->t_rm * pageKilo, (long long)v->t_arm * pageKilo);
375109113Sdillon	printf("Shared Virtual Memory:\t(Total: %lldK Active: %lldK)\n",
376109113Sdillon	    (long long)v->t_vmshr * pageKilo,
377109113Sdillon	    (long long)v->t_avmshr * pageKilo);
378109113Sdillon	printf("Shared Real Memory:\t(Total: %lldK Active: %lldK)\n",
379109113Sdillon	    (long long)v->t_rmshr * pageKilo,
380109113Sdillon	    (long long)v->t_armshr * pageKilo);
381109113Sdillon	printf("Free Memory Pages:\t%ldK\n", (long long)v->t_free * pageKilo);
382109097Sdillon
383109097Sdillon	return (0);
384109097Sdillon}
385109097Sdillon
386109097Sdillonstatic int
38712946SphkT_dev_t(int l2, void *p)
38812946Sphk{
38912946Sphk	dev_t *d = (dev_t *)p;
39097232Salfred	if (l2 != sizeof(*d)) {
39197232Salfred		warnx("T_dev_T %d != %d", l2, sizeof(*d));
39297232Salfred		return (0);
39397232Salfred	}
39461514Sphk	if ((int)(*d) != -1) {
39561514Sphk		if (minor(*d) > 255 || minor(*d) < 0)
39661514Sphk			printf("{ major = %d, minor = 0x%x }",
39761514Sphk				major(*d), minor(*d));
39861514Sphk		else
39961514Sphk			printf("{ major = %d, minor = %d }",
40061514Sphk				major(*d), minor(*d));
40161514Sphk	}
40212946Sphk	return (0);
40312946Sphk}
4041553Srgrimes
40588696Sphkstatic void
40688696Sphkset_T_dev_t (char *path, void **val, int *size)
40788696Sphk{
40888696Sphk	static struct stat statb;
40988696Sphk
41088696Sphk	if (strcmp(path, "none") && strcmp(path, "off")) {
41188696Sphk		int rc = stat (path, &statb);
41288696Sphk		if (rc) {
41388696Sphk			err(1, "cannot stat %s", path);
41488696Sphk		}
41588696Sphk
41688696Sphk		if (!S_ISCHR(statb.st_mode)) {
41788696Sphk			errx(1, "must specify a device special file.");
41888696Sphk		}
41988696Sphk	} else {
42088696Sphk		statb.st_rdev = NODEV;
42188696Sphk	}
42288696Sphk	*val = (char*) &statb.st_rdev;
42388696Sphk	*size = sizeof statb.st_rdev;
42488696Sphk}
42588696Sphk
42612946Sphk/*
42712946Sphk * These functions uses a presently undocumented interface to the kernel
42812946Sphk * to walk the tree and get the type so it can print the value.
42912946Sphk * This interface is under work and consideration, and should probably
43012946Sphk * be killed with a big axe by the first person who can find the time.
43112946Sphk * (be aware though, that the proper interface isn't as obvious as it
43212946Sphk * may seem, there are various conflicting requirements.
43312946Sphk */
4341553Srgrimes
43512946Sphkstatic int
43612946Sphkname2oid(char *name, int *oidp)
43712946Sphk{
43812946Sphk	int oid[2];
43938533Sdfr	int i;
44038533Sdfr	size_t j;
4411553Srgrimes
44212946Sphk	oid[0] = 0;
44312946Sphk	oid[1] = 3;
4441553Srgrimes
44577928Sdd	j = CTL_MAXNAME * sizeof(int);
44612946Sphk	i = sysctl(oid, 2, oidp, &j, name, strlen(name));
44712946Sphk	if (i < 0)
44812946Sphk		return i;
44977928Sdd	j /= sizeof(int);
45012946Sphk	return (j);
4511553Srgrimes}
4521553Srgrimes
45312946Sphkstatic int
45412946Sphkoidfmt(int *oid, int len, char *fmt, u_int *kind)
45512946Sphk{
45612946Sphk	int qoid[CTL_MAXNAME+2];
45712946Sphk	u_char buf[BUFSIZ];
45838533Sdfr	int i;
45938533Sdfr	size_t j;
4601553Srgrimes
46112946Sphk	qoid[0] = 0;
46212946Sphk	qoid[1] = 4;
46312946Sphk	memcpy(qoid + 2, oid, len * sizeof(int));
4641553Srgrimes
46577928Sdd	j = sizeof(buf);
46612946Sphk	i = sysctl(qoid, len + 2, buf, &j, 0, 0);
46712946Sphk	if (i)
46830602Scharnier		err(1, "sysctl fmt %d %d %d", i, j, errno);
4691553Srgrimes
47012946Sphk	if (kind)
47112946Sphk		*kind = *(u_int *)buf;
47212946Sphk
47312946Sphk	if (fmt)
47412946Sphk		strcpy(fmt, (char *)(buf + sizeof(u_int)));
47512946Sphk	return 0;
4761553Srgrimes}
4771553Srgrimes
4781553Srgrimes/*
47912946Sphk * This formats and outputs the value of one variable
48012946Sphk *
48112946Sphk * Returns zero if anything was actually output.
48212946Sphk * Returns one if didn't know what to do with this.
48312946Sphk * Return minus one if we had errors.
4841553Srgrimes */
48512946Sphk
48612946Sphkstatic int
48712946Sphkshow_var(int *oid, int nlen)
4881553Srgrimes{
48912946Sphk	u_char buf[BUFSIZ], *val, *p;
49085747Stobez	char name[BUFSIZ], *fmt, *sep;
49112946Sphk	int qoid[CTL_MAXNAME+2];
49238533Sdfr	int i;
49338533Sdfr	size_t j, len;
49412946Sphk	u_int kind;
49577332Sdes	int (*func)(int, void *);
4961553Srgrimes
49742456Sdes	qoid[0] = 0;
49842456Sdes	memcpy(qoid + 2, oid, nlen * sizeof(int));
49942456Sdes
50042456Sdes	qoid[1] = 1;
50177928Sdd	j = sizeof(name);
50242456Sdes	i = sysctl(qoid, nlen + 2, name, &j, 0, 0);
50342456Sdes	if (i || !j)
50442456Sdes		err(1, "sysctl name %d %d %d", i, j, errno);
50542456Sdes
50671034Sdes	if (Nflag) {
50771034Sdes		printf("%s", name);
50871034Sdes		return (0);
50971034Sdes	}
51071034Sdes
51185747Stobez	if (eflag)
51285747Stobez		sep = "=";
51385747Stobez	else
51485747Stobez		sep = ": ";
51585747Stobez
51688006Sluigi	if (dflag) {	/* just print description */
51788006Sluigi		qoid[1] = 5;
51888006Sluigi		j = sizeof(buf);
51988006Sluigi		i = sysctl(qoid, nlen + 2, buf, &j, 0, 0);
52088006Sluigi		if (!nflag)
52188006Sluigi			printf("%s%s", name, sep);
52288006Sluigi		printf("%s", buf);
52388006Sluigi		return (0);
52488006Sluigi	}
52512946Sphk	/* find an estimate of how much we need for this var */
52612946Sphk	j = 0;
52712946Sphk	i = sysctl(oid, nlen, 0, &j, 0, 0);
52812946Sphk	j += j; /* we want to be sure :-) */
52912946Sphk
530109671Speter	val = alloca(j + 1);
53112946Sphk	len = j;
53212946Sphk	i = sysctl(oid, nlen, val, &len, 0, 0);
53312946Sphk	if (i || !len)
53412946Sphk		return (1);
53512946Sphk
53612946Sphk	if (bflag) {
53712946Sphk		fwrite(val, 1, len, stdout);
53812946Sphk		return (0);
5391553Srgrimes	}
54096234Sache	val[len] = '\0';
54188696Sphk	fmt = buf;
54288696Sphk	oidfmt(oid, nlen, fmt, &kind);
54312946Sphk	p = val;
54412946Sphk	switch (*fmt) {
54512946Sphk	case 'A':
54612946Sphk		if (!nflag)
54785747Stobez			printf("%s%s", name, sep);
548106829Speter		printf("%.*s", len, p);
54912946Sphk		return (0);
55012946Sphk
55112946Sphk	case 'I':
55212946Sphk		if (!nflag)
55385747Stobez			printf("%s%s", name, sep);
55462622Sjhb		fmt++;
55541019Sphk		val = "";
55641019Sphk		while (len >= sizeof(int)) {
55762622Sjhb			if(*fmt == 'U')
55862622Sjhb				printf("%s%u", val, *(unsigned int *)p);
55962622Sjhb			else
56062622Sjhb				printf("%s%d", val, *(int *)p);
56141019Sphk			val = " ";
56277332Sdes			len -= sizeof(int);
56377332Sdes			p += sizeof(int);
56441019Sphk		}
56512946Sphk		return (0);
56612946Sphk
56738533Sdfr	case 'L':
56838533Sdfr		if (!nflag)
56985747Stobez			printf("%s%s", name, sep);
57062622Sjhb		fmt++;
57162975Sphk		val = "";
57262975Sphk		while (len >= sizeof(long)) {
57362975Sphk			if(*fmt == 'U')
57462975Sphk				printf("%s%lu", val, *(unsigned long *)p);
57562975Sphk			else
57662975Sphk				printf("%s%ld", val, *(long *)p);
57762975Sphk			val = " ";
57877332Sdes			len -= sizeof(long);
57977332Sdes			p += sizeof(long);
58062975Sphk		}
58138533Sdfr		return (0);
58238533Sdfr
58338533Sdfr	case 'P':
58438533Sdfr		if (!nflag)
58585747Stobez			printf("%s%s", name, sep);
58638533Sdfr		printf("%p", *(void **)p);
58738533Sdfr		return (0);
58838533Sdfr
58912946Sphk	case 'T':
59012946Sphk	case 'S':
59112946Sphk		i = 0;
59277332Sdes		if (strcmp(fmt, "S,clockinfo") == 0)
59377332Sdes			func = S_clockinfo;
59477332Sdes		else if (strcmp(fmt, "S,timeval") == 0)
59577332Sdes			func = S_timeval;
59677332Sdes		else if (strcmp(fmt, "S,loadavg") == 0)
59777332Sdes			func = S_loadavg;
598109097Sdillon		else if (strcmp(fmt, "S,vmtotal") == 0)
599109097Sdillon			func = S_vmtotal;
60077332Sdes		else if (strcmp(fmt, "T,dev_t") == 0)
60177332Sdes			func = T_dev_t;
60277332Sdes		else
60377332Sdes			func = NULL;
60412946Sphk		if (func) {
60512946Sphk			if (!nflag)
60685747Stobez				printf("%s%s", name, sep);
60712946Sphk			return ((*func)(len, p));
60812946Sphk		}
609102411Scharnier		/* FALLTHROUGH */
61012946Sphk	default:
61177330Sdes		if (!oflag && !xflag)
61212946Sphk			return (1);
61312946Sphk		if (!nflag)
61485747Stobez			printf("%s%s", name, sep);
61512946Sphk		printf("Format:%s Length:%d Dump:0x", fmt, len);
61677332Sdes		while (len-- && (xflag || p < val + 16))
61712946Sphk			printf("%02x", *p++);
61877332Sdes		if (!xflag && len > 16)
61912946Sphk			printf("...");
62012946Sphk		return (0);
6211553Srgrimes	}
62212946Sphk	return (1);
6231553Srgrimes}
6241553Srgrimes
62512946Sphkstatic int
62612946Sphksysctl_all (int *oid, int len)
6271553Srgrimes{
62812946Sphk	int name1[22], name2[22];
62938533Sdfr	int i, j;
63038533Sdfr	size_t l1, l2;
6311553Srgrimes
63212946Sphk	name1[0] = 0;
63312946Sphk	name1[1] = 2;
63412946Sphk	l1 = 2;
63512946Sphk	if (len) {
63677928Sdd		memcpy(name1+2, oid, len * sizeof(int));
63712946Sphk		l1 += len;
63812946Sphk	} else {
63912946Sphk		name1[2] = 1;
64012946Sphk		l1++;
64112946Sphk	}
64277332Sdes	for (;;) {
64377928Sdd		l2 = sizeof(name2);
64412946Sphk		j = sysctl(name1, l1, name2, &l2, 0, 0);
64548956Sbillf		if (j < 0) {
64612946Sphk			if (errno == ENOENT)
64712946Sphk				return 0;
64812946Sphk			else
64930602Scharnier				err(1, "sysctl(getnext) %d %d", j, l2);
65048956Sbillf		}
65112946Sphk
65277928Sdd		l2 /= sizeof(int);
65312946Sphk
65412946Sphk		if (l2 < len)
65512946Sphk			return 0;
65612946Sphk
65712946Sphk		for (i = 0; i < len; i++)
65812946Sphk			if (name2[i] != oid[i])
65912946Sphk				return 0;
66012946Sphk
66112946Sphk		i = show_var(name2, l2);
66212946Sphk		if (!i && !bflag)
66312946Sphk			putchar('\n');
66412946Sphk
66577928Sdd		memcpy(name1+2, name2, l2 * sizeof(int));
66612946Sphk		l1 = 2 + l2;
66712946Sphk	}
6681553Srgrimes}
669