sysctl.c revision 164718
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 * 4. Neither the name of the University nor the names of its contributors
141553Srgrimes *    may be used to endorse or promote products derived from this software
151553Srgrimes *    without specific prior written permission.
161553Srgrimes *
171553Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
181553Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
191553Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
201553Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
211553Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
221553Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
231553Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
241553Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
251553Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
261553Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
271553Srgrimes * SUCH DAMAGE.
281553Srgrimes */
291553Srgrimes
301553Srgrimes#ifndef lint
3130602Scharnierstatic const char copyright[] =
321553Srgrimes"@(#) Copyright (c) 1993\n\
331553Srgrimes	The Regents of the University of California.  All rights reserved.\n";
341553Srgrimes#endif /* not lint */
351553Srgrimes
361553Srgrimes#ifndef lint
3730602Scharnier#if 0
3830602Scharnierstatic char sccsid[] = "@(#)from: sysctl.c	8.1 (Berkeley) 6/6/93";
3930602Scharnier#endif
406284Swollmanstatic const char rcsid[] =
4150476Speter  "$FreeBSD: head/sbin/sysctl/sysctl.c 164718 2006-11-28 12:46:02Z ru $";
421553Srgrimes#endif /* not lint */
431553Srgrimes
4492066Sluigi#ifdef __i386__
4592066Sluigi#include <sys/reboot.h>		/* used for bootdev parsing */
4692066Sluigi#endif
4791217Sbde#include <sys/param.h>
4891217Sbde#include <sys/time.h>
4991217Sbde#include <sys/resource.h>
501553Srgrimes#include <sys/stat.h>
511553Srgrimes#include <sys/sysctl.h>
52109097Sdillon#include <sys/vmmeter.h>
531553Srgrimes
5430602Scharnier#include <ctype.h>
5530602Scharnier#include <err.h>
561553Srgrimes#include <errno.h>
57122233Sdes#include <locale.h>
581553Srgrimes#include <stdio.h>
591553Srgrimes#include <stdlib.h>
601553Srgrimes#include <string.h>
6130602Scharnier#include <unistd.h>
621553Srgrimes
63150167Srwatsonstatic int	aflag, bflag, dflag, eflag, hflag, Nflag, nflag, oflag;
64150167Srwatsonstatic int	qflag, xflag;
651553Srgrimes
6612946Sphkstatic int	oidfmt(int *, int, char *, u_int *);
6712946Sphkstatic void	parse(char *);
6812946Sphkstatic int	show_var(int *, int);
6912946Sphkstatic int	sysctl_all (int *oid, int len);
7012946Sphkstatic int	name2oid(char *, int *);
711553Srgrimes
72121542Speterstatic void	set_T_dev_t (char *, void **, size_t *);
73161951Sumestatic int	set_IK(char *, int *);
7488696Sphk
7512946Sphkstatic void
7612946Sphkusage(void)
7712946Sphk{
781553Srgrimes
7977330Sdes	(void)fprintf(stderr, "%s\n%s\n",
80152995Sru	    "usage: sysctl [-bdehNnoqx] name[=value] ...",
81152995Sru	    "       sysctl [-bdehNnoqx] -a");
8212946Sphk	exit(1);
8312946Sphk}
841553Srgrimes
851553Srgrimesint
8612946Sphkmain(int argc, char **argv)
871553Srgrimes{
8812946Sphk	int ch;
89122233Sdes
90122233Sdes	setlocale(LC_NUMERIC, "");
9112946Sphk	setbuf(stdout,0);
9212946Sphk	setbuf(stderr,0);
931553Srgrimes
94150167Srwatson	while ((ch = getopt(argc, argv, "AabdehNnoqwxX")) != -1) {
951553Srgrimes		switch (ch) {
9671034Sdes		case 'A':
9777330Sdes			/* compatibility */
9877330Sdes			aflag = oflag = 1;
9971034Sdes			break;
10071034Sdes		case 'a':
10171034Sdes			aflag = 1;
10271034Sdes			break;
10371034Sdes		case 'b':
10471034Sdes			bflag = 1;
10571034Sdes			break;
10688006Sluigi		case 'd':
10788006Sluigi			dflag = 1;
10888006Sluigi			break;
10985747Stobez		case 'e':
11085747Stobez			eflag = 1;
11185747Stobez			break;
112122233Sdes		case 'h':
113122233Sdes			hflag = 1;
114122233Sdes			break;
11571034Sdes		case 'N':
11671034Sdes			Nflag = 1;
11771034Sdes			break;
11871034Sdes		case 'n':
11971034Sdes			nflag = 1;
12071034Sdes			break;
12177330Sdes		case 'o':
12277330Sdes			oflag = 1;
12377330Sdes			break;
124150167Srwatson		case 'q':
125150167Srwatson			qflag = 1;
126150167Srwatson			break;
12771034Sdes		case 'w':
12877330Sdes			/* compatibility */
12977330Sdes			/* ignored */
13071034Sdes			break;
13171034Sdes		case 'X':
13277330Sdes			/* compatibility */
13377330Sdes			aflag = xflag = 1;
13471034Sdes			break;
13577330Sdes		case 'x':
13677330Sdes			xflag = 1;
13777330Sdes			break;
13871034Sdes		default:
13971034Sdes			usage();
1401553Srgrimes		}
1411553Srgrimes	}
1421553Srgrimes	argc -= optind;
1431553Srgrimes	argv += optind;
1441553Srgrimes
14577330Sdes	if (Nflag && nflag)
14642456Sdes		usage();
14777330Sdes	if (aflag && argc == 0)
14877330Sdes		exit(sysctl_all(0, 0));
1491553Srgrimes	if (argc == 0)
1501553Srgrimes		usage();
1511553Srgrimes	while (argc-- > 0)
15212946Sphk		parse(*argv++);
1531553Srgrimes	exit(0);
1541553Srgrimes}
1551553Srgrimes
1561553Srgrimes/*
1571553Srgrimes * Parse a name into a MIB entry.
1581553Srgrimes * Lookup and print out the MIB entry if it exists.
1591553Srgrimes * Set a new value if requested.
1601553Srgrimes */
16112946Sphkstatic void
16212946Sphkparse(char *string)
1631553Srgrimes{
16412946Sphk	int len, i, j;
1651553Srgrimes	void *newval = 0;
16678434Spirzyk	int intval;
16778434Spirzyk	unsigned int uintval;
16878434Spirzyk	long longval;
16978434Spirzyk	unsigned long ulongval;
17078434Spirzyk	size_t newsize = 0;
1711553Srgrimes	quad_t quadval;
1721553Srgrimes	int mib[CTL_MAXNAME];
173116383Srwatson	char *cp, *bufp, buf[BUFSIZ], *endptr, fmt[BUFSIZ];
17412946Sphk	u_int kind;
1751553Srgrimes
1761553Srgrimes	bufp = buf;
177140818Sssouhlal	if (snprintf(buf, BUFSIZ, "%s", string) >= BUFSIZ)
178140818Sssouhlal		errx(1, "oid too long: '%s'", string);
1791553Srgrimes	if ((cp = strchr(string, '=')) != NULL) {
1801553Srgrimes		*strchr(buf, '=') = '\0';
1811553Srgrimes		*cp++ = '\0';
1821553Srgrimes		while (isspace(*cp))
1831553Srgrimes			cp++;
1841553Srgrimes		newval = cp;
1851553Srgrimes		newsize = strlen(cp);
1861553Srgrimes	}
18712946Sphk	len = name2oid(bufp, mib);
1881553Srgrimes
189150167Srwatson	if (len < 0) {
190150167Srwatson		if (qflag)
191150167Srwatson			exit(1);
192150167Srwatson		else
193150167Srwatson			errx(1, "unknown oid '%s'", bufp);
194150167Srwatson	}
1951553Srgrimes
19688696Sphk	if (oidfmt(mib, len, fmt, &kind))
19730602Scharnier		err(1, "couldn't find format of oid '%s'", bufp);
1981553Srgrimes
19977330Sdes	if (newval == NULL) {
20012946Sphk		if ((kind & CTLTYPE) == CTLTYPE_NODE) {
201144998Smdodd			if (dflag) {
202144998Smdodd				i = show_var(mib, len);
203144998Smdodd				if (!i && !bflag)
204144998Smdodd					putchar('\n');
205144998Smdodd			}
20612946Sphk			sysctl_all(mib, len);
20712946Sphk		} else {
20812946Sphk			i = show_var(mib, len);
20912946Sphk			if (!i && !bflag)
21012946Sphk				putchar('\n');
2111553Srgrimes		}
21212946Sphk	} else {
21312946Sphk		if ((kind & CTLTYPE) == CTLTYPE_NODE)
21412946Sphk			errx(1, "oid '%s' isn't a leaf node", bufp);
2151553Srgrimes
216121849Ssilby		if (!(kind & CTLFLAG_WR)) {
217121306Ssilby			if (kind & CTLFLAG_TUN) {
218121849Ssilby				warnx("oid '%s' is a read only tunable", bufp);
219121849Ssilby				errx(1, "Tunable values are set in /boot/loader.conf");
220121306Ssilby			} else {
221121306Ssilby				errx(1, "oid '%s' is read only", bufp);
222121849Ssilby			}
223121306Ssilby		}
224116383Srwatson
225116383Srwatson		if ((kind & CTLTYPE) == CTLTYPE_INT ||
226116383Srwatson		    (kind & CTLTYPE) == CTLTYPE_UINT ||
227116383Srwatson		    (kind & CTLTYPE) == CTLTYPE_LONG ||
228126472Sdd		    (kind & CTLTYPE) == CTLTYPE_ULONG ||
229126472Sdd		    (kind & CTLTYPE) == CTLTYPE_QUAD) {
230116383Srwatson			if (strlen(newval) == 0)
231116383Srwatson				errx(1, "empty numeric value");
232116383Srwatson		}
233122234Sdes
23412946Sphk		switch (kind & CTLTYPE) {
23512946Sphk			case CTLTYPE_INT:
236161951Sume				if (strcmp(fmt, "IK") == 0) {
237161951Sume					if (!set_IK((char*)newval, &intval))
238161951Sume						errx(1, "invalid value '%s'",
239161951Sume						    newval);
240161951Sume 				} else {
241161951Sume					intval = (int)strtol(newval, &endptr,
242161951Sume					    0);
243161951Sume					if (endptr == newval || *endptr != '\0')
244161951Sume						errx(1, "invalid integer '%s'",
245161951Sume						    newval);
246161951Sume				}
24712946Sphk				newval = &intval;
24877928Sdd				newsize = sizeof(intval);
2491553Srgrimes				break;
25078434Spirzyk			case CTLTYPE_UINT:
251116383Srwatson				uintval = (int) strtoul(newval, &endptr, 0);
252116383Srwatson				if (endptr == newval || *endptr != '\0')
253116383Srwatson					errx(1, "invalid unsigned integer '%s'",
254116383Srwatson					    newval);
25578434Spirzyk				newval = &uintval;
25678434Spirzyk				newsize = sizeof uintval;
25712946Sphk				break;
25878434Spirzyk			case CTLTYPE_LONG:
259116383Srwatson				longval = strtol(newval, &endptr, 0);
260116383Srwatson				if (endptr == newval || *endptr != '\0')
261116383Srwatson					errx(1, "invalid long integer '%s'",
262116383Srwatson					    newval);
26378434Spirzyk				newval = &longval;
26478434Spirzyk				newsize = sizeof longval;
26578434Spirzyk				break;
26678434Spirzyk			case CTLTYPE_ULONG:
267116383Srwatson				ulongval = strtoul(newval, &endptr, 0);
268116383Srwatson				if (endptr == newval || *endptr != '\0')
269116383Srwatson					errx(1, "invalid unsigned long integer"
270116383Srwatson					    " '%s'", newval);
27178434Spirzyk				newval = &ulongval;
27278434Spirzyk				newsize = sizeof ulongval;
27378434Spirzyk				break;
27412946Sphk			case CTLTYPE_STRING:
27512946Sphk				break;
27612946Sphk			case CTLTYPE_QUAD:
27712946Sphk				sscanf(newval, "%qd", &quadval);
27812946Sphk				newval = &quadval;
27977928Sdd				newsize = sizeof(quadval);
28012946Sphk				break;
28188696Sphk			case CTLTYPE_OPAQUE:
28288696Sphk				if (strcmp(fmt, "T,dev_t") == 0) {
28388696Sphk					set_T_dev_t ((char*)newval, &newval, &newsize);
28488696Sphk					break;
28588696Sphk				}
28688696Sphk				/* FALLTHROUGH */
28712946Sphk			default:
28812946Sphk				errx(1, "oid '%s' is type %d,"
28931214Sjdp					" cannot set that", bufp,
29031214Sjdp					kind & CTLTYPE);
2911553Srgrimes		}
2921553Srgrimes
29312946Sphk		i = show_var(mib, len);
29412946Sphk		if (sysctl(mib, len, 0, 0, newval, newsize) == -1) {
29512946Sphk			if (!i && !bflag)
29612946Sphk				putchar('\n');
29712946Sphk			switch (errno) {
29812946Sphk			case EOPNOTSUPP:
299122234Sdes				errx(1, "%s: value is not available",
30012946Sphk					string);
30112946Sphk			case ENOTDIR:
302122234Sdes				errx(1, "%s: specification is incomplete",
30312946Sphk					string);
30412946Sphk			case ENOMEM:
305122234Sdes				errx(1, "%s: type is unknown to this program",
30612946Sphk					string);
30712946Sphk			default:
30830602Scharnier				warn("%s", string);
30912946Sphk				return;
31012946Sphk			}
31112946Sphk		}
31212946Sphk		if (!bflag)
31312946Sphk			printf(" -> ");
31412946Sphk		i = nflag;
31512946Sphk		nflag = 1;
31612946Sphk		j = show_var(mib, len);
31712946Sphk		if (!j && !bflag)
31812946Sphk			putchar('\n');
31912946Sphk		nflag = i;
32012946Sphk	}
32112946Sphk}
3221553Srgrimes
32312946Sphk/* These functions will dump out various interesting structures. */
3241553Srgrimes
32512946Sphkstatic int
32612946SphkS_clockinfo(int l2, void *p)
32712946Sphk{
32812946Sphk	struct clockinfo *ci = (struct clockinfo*)p;
32997232Salfred	if (l2 != sizeof(*ci)) {
33097232Salfred		warnx("S_clockinfo %d != %d", l2, sizeof(*ci));
33197232Salfred		return (0);
33297232Salfred	}
333122233Sdes	printf(hflag ? "{ hz = %'d, tick = %'d, profhz = %'d, stathz = %'d }" :
334122233Sdes		"{ hz = %d, tick = %d, profhz = %d, stathz = %d }",
33594752Sphk		ci->hz, ci->tick, ci->profhz, ci->stathz);
33612946Sphk	return (0);
33712946Sphk}
3381553Srgrimes
33912946Sphkstatic int
34012946SphkS_loadavg(int l2, void *p)
34112946Sphk{
34212946Sphk	struct loadavg *tv = (struct loadavg*)p;
3438857Srgrimes
34497232Salfred	if (l2 != sizeof(*tv)) {
34597232Salfred		warnx("S_loadavg %d != %d", l2, sizeof(*tv));
34697232Salfred		return (0);
34797232Salfred	}
348122233Sdes	printf(hflag ? "{ %'.2f %'.2f %'.2f }" : "{ %.2f %.2f %.2f }",
34912946Sphk		(double)tv->ldavg[0]/(double)tv->fscale,
35012946Sphk		(double)tv->ldavg[1]/(double)tv->fscale,
35112946Sphk		(double)tv->ldavg[2]/(double)tv->fscale);
35212946Sphk	return (0);
35312946Sphk}
3541553Srgrimes
35512946Sphkstatic int
35612946SphkS_timeval(int l2, void *p)
35712946Sphk{
35812946Sphk	struct timeval *tv = (struct timeval*)p;
35937266Sbde	time_t tv_sec;
36012946Sphk	char *p1, *p2;
3611553Srgrimes
36297232Salfred	if (l2 != sizeof(*tv)) {
36397232Salfred		warnx("S_timeval %d != %d", l2, sizeof(*tv));
36497232Salfred		return (0);
36597232Salfred	}
366122233Sdes	printf(hflag ? "{ sec = %'ld, usec = %'ld } " :
367122233Sdes		"{ sec = %ld, usec = %ld } ",
36812946Sphk		tv->tv_sec, tv->tv_usec);
36937266Sbde	tv_sec = tv->tv_sec;
37037266Sbde	p1 = strdup(ctime(&tv_sec));
37112946Sphk	for (p2=p1; *p2 ; p2++)
37212946Sphk		if (*p2 == '\n')
37312946Sphk			*p2 = '\0';
37412946Sphk	fputs(p1, stdout);
37512946Sphk	return (0);
37612946Sphk}
3771553Srgrimes
37812946Sphkstatic int
379109097SdillonS_vmtotal(int l2, void *p)
380109097Sdillon{
381109097Sdillon	struct vmtotal *v = (struct vmtotal *)p;
382109113Sdillon	int pageKilo = getpagesize() / 1024;
383109097Sdillon
384109097Sdillon	if (l2 != sizeof(*v)) {
385109097Sdillon		warnx("S_vmtotal %d != %d", l2, sizeof(*v));
386109097Sdillon		return (0);
387109097Sdillon	}
388109097Sdillon
389109113Sdillon	printf(
390109113Sdillon	    "\nSystem wide totals computed every five seconds:"
391109113Sdillon	    " (values in kilobytes)\n");
392109097Sdillon	printf("===============================================\n");
393109113Sdillon	printf(
394164718Sru	    "Processes:\t\t(RUNQ: %hd Disk Wait: %hd Page Wait: "
395164718Sru	    "%hd Sleep: %hd)\n",
396109113Sdillon	    v->t_rq, v->t_dw, v->t_pw, v->t_sl);
397109113Sdillon	printf(
398164718Sru	    "Virtual Memory:\t\t(Total: %dK, Active %dK)\n",
399164718Sru	    v->t_vm * pageKilo, v->t_avm * pageKilo);
400164718Sru	printf("Real Memory:\t\t(Total: %dK Active %dK)\n",
401164718Sru	    v->t_rm * pageKilo, v->t_arm * pageKilo);
402164718Sru	printf("Shared Virtual Memory:\t(Total: %dK Active: %dK)\n",
403164718Sru	    v->t_vmshr * pageKilo, v->t_avmshr * pageKilo);
404164718Sru	printf("Shared Real Memory:\t(Total: %dK Active: %dK)\n",
405164718Sru	    v->t_rmshr * pageKilo, v->t_armshr * pageKilo);
406164718Sru	printf("Free Memory Pages:\t%dK\n", v->t_free * pageKilo);
407122234Sdes
408109097Sdillon	return (0);
409109097Sdillon}
410109097Sdillon
411109097Sdillonstatic int
41212946SphkT_dev_t(int l2, void *p)
41312946Sphk{
41412946Sphk	dev_t *d = (dev_t *)p;
41597232Salfred	if (l2 != sizeof(*d)) {
41697232Salfred		warnx("T_dev_T %d != %d", l2, sizeof(*d));
41797232Salfred		return (0);
41897232Salfred	}
41961514Sphk	if ((int)(*d) != -1) {
42061514Sphk		if (minor(*d) > 255 || minor(*d) < 0)
42161514Sphk			printf("{ major = %d, minor = 0x%x }",
42261514Sphk				major(*d), minor(*d));
42361514Sphk		else
42461514Sphk			printf("{ major = %d, minor = %d }",
42561514Sphk				major(*d), minor(*d));
42661514Sphk	}
42712946Sphk	return (0);
42812946Sphk}
4291553Srgrimes
43088696Sphkstatic void
431121542Speterset_T_dev_t (char *path, void **val, size_t *size)
43288696Sphk{
43388696Sphk	static struct stat statb;
43488696Sphk
43588696Sphk	if (strcmp(path, "none") && strcmp(path, "off")) {
43688696Sphk		int rc = stat (path, &statb);
43788696Sphk		if (rc) {
43888696Sphk			err(1, "cannot stat %s", path);
43988696Sphk		}
44088696Sphk
44188696Sphk		if (!S_ISCHR(statb.st_mode)) {
44288696Sphk			errx(1, "must specify a device special file.");
44388696Sphk		}
44488696Sphk	} else {
44588696Sphk		statb.st_rdev = NODEV;
44688696Sphk	}
44788696Sphk	*val = (char*) &statb.st_rdev;
44888696Sphk	*size = sizeof statb.st_rdev;
44988696Sphk}
45088696Sphk
451161951Sumestatic int
452161951Sumeset_IK(char *str, int *val)
453161951Sume{
454161951Sume	float temp;
455161951Sume	int len, kelv;
456161951Sume	char *p, *endptr;
457161951Sume
458161951Sume	if ((len = strlen(str)) == 0)
459161951Sume		return (0);
460161951Sume	p = &str[len - 1];
461161951Sume	if (*p == 'C' || *p == 'F') {
462161951Sume		*p = '\0';
463161951Sume		temp = strtof(str, &endptr);
464161951Sume		if (endptr == str || *endptr != '\0')
465161951Sume			return (0);
466161951Sume		if (*p == 'F')
467161951Sume			temp = (temp - 32) * 5 / 9;
468161951Sume		kelv = temp * 10 + 2732;
469161951Sume	} else {
470161951Sume		kelv = (int)strtol(str, &endptr, 10);
471161951Sume		if (endptr == str || *endptr != '\0')
472161951Sume			return (0);
473161951Sume	}
474161951Sume	*val = kelv;
475161951Sume	return (1);
476161951Sume}
477161951Sume
47812946Sphk/*
47912946Sphk * These functions uses a presently undocumented interface to the kernel
48012946Sphk * to walk the tree and get the type so it can print the value.
48112946Sphk * This interface is under work and consideration, and should probably
48212946Sphk * be killed with a big axe by the first person who can find the time.
48312946Sphk * (be aware though, that the proper interface isn't as obvious as it
48412946Sphk * may seem, there are various conflicting requirements.
48512946Sphk */
4861553Srgrimes
48712946Sphkstatic int
48812946Sphkname2oid(char *name, int *oidp)
48912946Sphk{
49012946Sphk	int oid[2];
49138533Sdfr	int i;
49238533Sdfr	size_t j;
4931553Srgrimes
49412946Sphk	oid[0] = 0;
49512946Sphk	oid[1] = 3;
4961553Srgrimes
49777928Sdd	j = CTL_MAXNAME * sizeof(int);
49812946Sphk	i = sysctl(oid, 2, oidp, &j, name, strlen(name));
499122234Sdes	if (i < 0)
50012946Sphk		return i;
50177928Sdd	j /= sizeof(int);
50212946Sphk	return (j);
5031553Srgrimes}
5041553Srgrimes
50512946Sphkstatic int
50612946Sphkoidfmt(int *oid, int len, char *fmt, u_int *kind)
50712946Sphk{
50812946Sphk	int qoid[CTL_MAXNAME+2];
50912946Sphk	u_char buf[BUFSIZ];
51038533Sdfr	int i;
51138533Sdfr	size_t j;
5121553Srgrimes
51312946Sphk	qoid[0] = 0;
51412946Sphk	qoid[1] = 4;
51512946Sphk	memcpy(qoid + 2, oid, len * sizeof(int));
5161553Srgrimes
51777928Sdd	j = sizeof(buf);
51812946Sphk	i = sysctl(qoid, len + 2, buf, &j, 0, 0);
51912946Sphk	if (i)
52030602Scharnier		err(1, "sysctl fmt %d %d %d", i, j, errno);
5211553Srgrimes
52212946Sphk	if (kind)
52312946Sphk		*kind = *(u_int *)buf;
52412946Sphk
52512946Sphk	if (fmt)
52612946Sphk		strcpy(fmt, (char *)(buf + sizeof(u_int)));
52712946Sphk	return 0;
5281553Srgrimes}
5291553Srgrimes
5301553Srgrimes/*
53112946Sphk * This formats and outputs the value of one variable
53212946Sphk *
53312946Sphk * Returns zero if anything was actually output.
53412946Sphk * Returns one if didn't know what to do with this.
53512946Sphk * Return minus one if we had errors.
5361553Srgrimes */
53712946Sphk
53812946Sphkstatic int
53912946Sphkshow_var(int *oid, int nlen)
5401553Srgrimes{
541162073Sru	u_char buf[BUFSIZ], *val, *oval, *p;
54285747Stobez	char name[BUFSIZ], *fmt, *sep;
54312946Sphk	int qoid[CTL_MAXNAME+2];
54438533Sdfr	int i;
54538533Sdfr	size_t j, len;
54612946Sphk	u_int kind;
54777332Sdes	int (*func)(int, void *);
5481553Srgrimes
549144997Smdodd	bzero(buf, BUFSIZ);
550144997Smdodd	bzero(name, BUFSIZ);
55142456Sdes	qoid[0] = 0;
55242456Sdes	memcpy(qoid + 2, oid, nlen * sizeof(int));
55342456Sdes
55442456Sdes	qoid[1] = 1;
55577928Sdd	j = sizeof(name);
55642456Sdes	i = sysctl(qoid, nlen + 2, name, &j, 0, 0);
55742456Sdes	if (i || !j)
55842456Sdes		err(1, "sysctl name %d %d %d", i, j, errno);
55942456Sdes
56071034Sdes	if (Nflag) {
56171034Sdes		printf("%s", name);
56271034Sdes		return (0);
56371034Sdes	}
56471034Sdes
56585747Stobez	if (eflag)
56685747Stobez		sep = "=";
56785747Stobez	else
56885747Stobez		sep = ": ";
56985747Stobez
57088006Sluigi	if (dflag) {	/* just print description */
57188006Sluigi		qoid[1] = 5;
57288006Sluigi		j = sizeof(buf);
57388006Sluigi		i = sysctl(qoid, nlen + 2, buf, &j, 0, 0);
57488006Sluigi		if (!nflag)
57588006Sluigi			printf("%s%s", name, sep);
57688006Sluigi		printf("%s", buf);
57788006Sluigi		return (0);
57888006Sluigi	}
57912946Sphk	/* find an estimate of how much we need for this var */
58012946Sphk	j = 0;
58112946Sphk	i = sysctl(oid, nlen, 0, &j, 0, 0);
58212946Sphk	j += j; /* we want to be sure :-) */
58312946Sphk
584162073Sru	val = oval = malloc(j + 1);
585162073Sru	if (val == NULL) {
586162073Sru		warnx("malloc failed");
587162073Sru		return (-1);
588162073Sru	}
58912946Sphk	len = j;
59012946Sphk	i = sysctl(oid, nlen, val, &len, 0, 0);
591162073Sru	if (i || !len) {
592162073Sru		free(oval);
59312946Sphk		return (1);
594162073Sru	}
59512946Sphk
59612946Sphk	if (bflag) {
59712946Sphk		fwrite(val, 1, len, stdout);
598162073Sru		free(oval);
59912946Sphk		return (0);
6001553Srgrimes	}
60196234Sache	val[len] = '\0';
60288696Sphk	fmt = buf;
60388696Sphk	oidfmt(oid, nlen, fmt, &kind);
60412946Sphk	p = val;
60512946Sphk	switch (*fmt) {
60612946Sphk	case 'A':
60712946Sphk		if (!nflag)
60885747Stobez			printf("%s%s", name, sep);
609106829Speter		printf("%.*s", len, p);
610162073Sru		free(oval);
61112946Sphk		return (0);
612122234Sdes
61312946Sphk	case 'I':
61412946Sphk		if (!nflag)
61585747Stobez			printf("%s%s", name, sep);
61662622Sjhb		fmt++;
61741019Sphk		val = "";
61841019Sphk		while (len >= sizeof(int)) {
619122233Sdes			fputs(val, stdout);
620160963Snjl			if (*fmt == 'U')
621161256Sobrien				printf(hflag ? "%'u" : "%u",
622161256Sobrien				    *(unsigned int *)p);
623161256Sobrien			else if (*fmt == 'X')
624161256Sobrien				printf(hflag ? "%'#010x" : "%#010x",
625161256Sobrien				    *(unsigned int *)p);
626134541Speter			else if (*fmt == 'K') {
627161313Sru				if (*(int *)p < 0)
628161313Sru					printf("%d", *(int *)p);
629134541Speter				else
630160963Snjl					printf("%.1fC",
631161313Sru					    (*(int *)p - 2732.0) / 10);
632134541Speter			} else
633122233Sdes				printf(hflag ? "%'d" : "%d", *(int *)p);
63441019Sphk			val = " ";
63577332Sdes			len -= sizeof(int);
63677332Sdes			p += sizeof(int);
63741019Sphk		}
638162073Sru		free(oval);
63912946Sphk		return (0);
64012946Sphk
64138533Sdfr	case 'L':
64238533Sdfr		if (!nflag)
64385747Stobez			printf("%s%s", name, sep);
64462622Sjhb		fmt++;
64562975Sphk		val = "";
64662975Sphk		while (len >= sizeof(long)) {
647122233Sdes			fputs(val, stdout);
648160963Snjl			if (*fmt == 'U')
649161256Sobrien				printf(hflag ? "%'lu" : "%lu",
650161256Sobrien				    *(unsigned long *)p);
651161256Sobrien			else if (*fmt == 'X')
652161256Sobrien				printf(hflag ? "%'#018lx" : "%#018lx",
653161256Sobrien				    *(unsigned long *)p);
654134541Speter			else if (*fmt == 'K') {
655134541Speter				if (*(long *)p < 0)
656134541Speter					printf("%ld", *(long *)p);
657134541Speter				else
658160963Snjl					printf("%.1fC",
659160963Snjl					    (*(long *)p - 2732.0) / 10);
660134541Speter			} else
661122233Sdes				printf(hflag ? "%'ld" : "%ld", *(long *)p);
66262975Sphk			val = " ";
66377332Sdes			len -= sizeof(long);
66477332Sdes			p += sizeof(long);
66562975Sphk		}
666162073Sru		free(oval);
66738533Sdfr		return (0);
66838533Sdfr
66938533Sdfr	case 'P':
67038533Sdfr		if (!nflag)
67185747Stobez			printf("%s%s", name, sep);
67238533Sdfr		printf("%p", *(void **)p);
673162073Sru		free(oval);
67438533Sdfr		return (0);
67538533Sdfr
67612946Sphk	case 'T':
67712946Sphk	case 'S':
67812946Sphk		i = 0;
67977332Sdes		if (strcmp(fmt, "S,clockinfo") == 0)
68077332Sdes			func = S_clockinfo;
68177332Sdes		else if (strcmp(fmt, "S,timeval") == 0)
68277332Sdes			func = S_timeval;
68377332Sdes		else if (strcmp(fmt, "S,loadavg") == 0)
68477332Sdes			func = S_loadavg;
685109097Sdillon		else if (strcmp(fmt, "S,vmtotal") == 0)
686109097Sdillon			func = S_vmtotal;
68777332Sdes		else if (strcmp(fmt, "T,dev_t") == 0)
68877332Sdes			func = T_dev_t;
68977332Sdes		else
69077332Sdes			func = NULL;
69112946Sphk		if (func) {
69212946Sphk			if (!nflag)
69385747Stobez				printf("%s%s", name, sep);
694163275Sharti			i = (*func)(len, p);
695162073Sru			free(oval);
696163275Sharti			return (i);
69712946Sphk		}
698102411Scharnier		/* FALLTHROUGH */
69912946Sphk	default:
700162073Sru		if (!oflag && !xflag) {
701162073Sru			free(oval);
70212946Sphk			return (1);
703162073Sru		}
70412946Sphk		if (!nflag)
70585747Stobez			printf("%s%s", name, sep);
70612946Sphk		printf("Format:%s Length:%d Dump:0x", fmt, len);
70777332Sdes		while (len-- && (xflag || p < val + 16))
70812946Sphk			printf("%02x", *p++);
70977332Sdes		if (!xflag && len > 16)
71012946Sphk			printf("...");
711162073Sru		free(oval);
71212946Sphk		return (0);
7131553Srgrimes	}
714162073Sru	free(oval);
71512946Sphk	return (1);
7161553Srgrimes}
7171553Srgrimes
71812946Sphkstatic int
71912946Sphksysctl_all (int *oid, int len)
7201553Srgrimes{
72112946Sphk	int name1[22], name2[22];
72238533Sdfr	int i, j;
72338533Sdfr	size_t l1, l2;
7241553Srgrimes
72512946Sphk	name1[0] = 0;
72612946Sphk	name1[1] = 2;
72712946Sphk	l1 = 2;
72812946Sphk	if (len) {
72977928Sdd		memcpy(name1+2, oid, len * sizeof(int));
73012946Sphk		l1 += len;
73112946Sphk	} else {
73212946Sphk		name1[2] = 1;
73312946Sphk		l1++;
73412946Sphk	}
73577332Sdes	for (;;) {
73677928Sdd		l2 = sizeof(name2);
73712946Sphk		j = sysctl(name1, l1, name2, &l2, 0, 0);
73848956Sbillf		if (j < 0) {
73912946Sphk			if (errno == ENOENT)
74012946Sphk				return 0;
74112946Sphk			else
74230602Scharnier				err(1, "sysctl(getnext) %d %d", j, l2);
74348956Sbillf		}
74412946Sphk
74577928Sdd		l2 /= sizeof(int);
74612946Sphk
74712946Sphk		if (l2 < len)
74812946Sphk			return 0;
74912946Sphk
75012946Sphk		for (i = 0; i < len; i++)
75112946Sphk			if (name2[i] != oid[i])
75212946Sphk				return 0;
75312946Sphk
75412946Sphk		i = show_var(name2, l2);
75512946Sphk		if (!i && !bflag)
75612946Sphk			putchar('\n');
75712946Sphk
75877928Sdd		memcpy(name1+2, name2, l2 * sizeof(int));
75912946Sphk		l1 = 2 + l2;
76012946Sphk	}
7611553Srgrimes}
762