sysctl.c revision 244106
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 244106 2012-12-11 01:28:06Z alfred $";
421553Srgrimes#endif /* not lint */
431553Srgrimes
4491217Sbde#include <sys/param.h>
4591217Sbde#include <sys/time.h>
4691217Sbde#include <sys/resource.h>
471553Srgrimes#include <sys/stat.h>
481553Srgrimes#include <sys/sysctl.h>
49109097Sdillon#include <sys/vmmeter.h>
501553Srgrimes
5130602Scharnier#include <ctype.h>
5230602Scharnier#include <err.h>
531553Srgrimes#include <errno.h>
54170287Sdwmalone#include <inttypes.h>
55122233Sdes#include <locale.h>
561553Srgrimes#include <stdio.h>
571553Srgrimes#include <stdlib.h>
581553Srgrimes#include <string.h>
5930602Scharnier#include <unistd.h>
601553Srgrimes
61203310Sgavinstatic int	aflag, bflag, dflag, eflag, hflag, iflag;
62244106Salfredstatic int	Nflag, nflag, oflag, qflag, Tflag, Wflag, xflag, warncount;
631553Srgrimes
6412946Sphkstatic int	oidfmt(int *, int, char *, u_int *);
65244104Sdelphijstatic void	parse(const char *);
6612946Sphkstatic int	show_var(int *, int);
67170512Sdwmalonestatic int	sysctl_all(int *oid, int len);
6812946Sphkstatic int	name2oid(char *, int *);
691553Srgrimes
70198340Sedstatic int	set_IK(const char *, int *);
7188696Sphk
7212946Sphkstatic void
7312946Sphkusage(void)
7412946Sphk{
751553Srgrimes
7677330Sdes	(void)fprintf(stderr, "%s\n%s\n",
77244106Salfred	    "usage: sysctl [-bdehiNnoqTWx] name[=value] ...",
78244106Salfred	    "       sysctl [-bdehNnoqTWx] -a");
7912946Sphk	exit(1);
8012946Sphk}
811553Srgrimes
821553Srgrimesint
8312946Sphkmain(int argc, char **argv)
841553Srgrimes{
8512946Sphk	int ch;
86122233Sdes
87122233Sdes	setlocale(LC_NUMERIC, "");
8812946Sphk	setbuf(stdout,0);
8912946Sphk	setbuf(stderr,0);
901553Srgrimes
91244106Salfred	while ((ch = getopt(argc, argv, "AabdehiNnoqTwWxX")) != -1) {
921553Srgrimes		switch (ch) {
9371034Sdes		case 'A':
9477330Sdes			/* compatibility */
9577330Sdes			aflag = oflag = 1;
9671034Sdes			break;
9771034Sdes		case 'a':
9871034Sdes			aflag = 1;
9971034Sdes			break;
10071034Sdes		case 'b':
10171034Sdes			bflag = 1;
10271034Sdes			break;
10388006Sluigi		case 'd':
10488006Sluigi			dflag = 1;
10588006Sluigi			break;
10685747Stobez		case 'e':
10785747Stobez			eflag = 1;
10885747Stobez			break;
109122233Sdes		case 'h':
110122233Sdes			hflag = 1;
111122233Sdes			break;
112203310Sgavin		case 'i':
113203310Sgavin			iflag = 1;
114203310Sgavin			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;
127244106Salfred		case 'T':
128244106Salfred			Tflag = 1;
129244106Salfred			break;
13071034Sdes		case 'w':
13177330Sdes			/* compatibility */
13277330Sdes			/* ignored */
13371034Sdes			break;
134244106Salfred		case 'W':
135244106Salfred			Wflag = 1;
136244106Salfred			break;
13771034Sdes		case 'X':
13877330Sdes			/* compatibility */
13977330Sdes			aflag = xflag = 1;
14071034Sdes			break;
14177330Sdes		case 'x':
14277330Sdes			xflag = 1;
14377330Sdes			break;
14471034Sdes		default:
14571034Sdes			usage();
1461553Srgrimes		}
1471553Srgrimes	}
1481553Srgrimes	argc -= optind;
1491553Srgrimes	argv += optind;
1501553Srgrimes
15177330Sdes	if (Nflag && nflag)
15242456Sdes		usage();
15377330Sdes	if (aflag && argc == 0)
15477330Sdes		exit(sysctl_all(0, 0));
1551553Srgrimes	if (argc == 0)
1561553Srgrimes		usage();
157179965Smtm
158179965Smtm	warncount = 0;
1591553Srgrimes	while (argc-- > 0)
16012946Sphk		parse(*argv++);
161179965Smtm	exit(warncount);
1621553Srgrimes}
1631553Srgrimes
1641553Srgrimes/*
1651553Srgrimes * Parse a name into a MIB entry.
1661553Srgrimes * Lookup and print out the MIB entry if it exists.
1671553Srgrimes * Set a new value if requested.
1681553Srgrimes */
16912946Sphkstatic void
170244104Sdelphijparse(const char *string)
1711553Srgrimes{
17212946Sphk	int len, i, j;
1731553Srgrimes	void *newval = 0;
17478434Spirzyk	int intval;
17578434Spirzyk	unsigned int uintval;
17678434Spirzyk	long longval;
17778434Spirzyk	unsigned long ulongval;
17878434Spirzyk	size_t newsize = 0;
179217616Smdf	int64_t i64val;
180217616Smdf	uint64_t u64val;
1811553Srgrimes	int mib[CTL_MAXNAME];
182116383Srwatson	char *cp, *bufp, buf[BUFSIZ], *endptr, fmt[BUFSIZ];
18312946Sphk	u_int kind;
1841553Srgrimes
185244104Sdelphij	cp = buf;
186140818Sssouhlal	if (snprintf(buf, BUFSIZ, "%s", string) >= BUFSIZ)
187140818Sssouhlal		errx(1, "oid too long: '%s'", string);
188244104Sdelphij	bufp = strsep(&cp, "=");
189244104Sdelphij	if (cp != NULL) {
190244106Salfred		/* Tflag just lists tunables, do not allow assignment */
191244106Salfred		if (Tflag || Wflag) {
192244106Salfred			warnx("Can't set variables when using -T or -W");
193244106Salfred			usage();
194244106Salfred		}
1951553Srgrimes		while (isspace(*cp))
1961553Srgrimes			cp++;
1971553Srgrimes		newval = cp;
1981553Srgrimes		newsize = strlen(cp);
1991553Srgrimes	}
20012946Sphk	len = name2oid(bufp, mib);
2011553Srgrimes
202150167Srwatson	if (len < 0) {
203203310Sgavin		if (iflag)
204203310Sgavin			return;
205150167Srwatson		if (qflag)
206150167Srwatson			exit(1);
207150167Srwatson		else
208150167Srwatson			errx(1, "unknown oid '%s'", bufp);
209150167Srwatson	}
2101553Srgrimes
21188696Sphk	if (oidfmt(mib, len, fmt, &kind))
21230602Scharnier		err(1, "couldn't find format of oid '%s'", bufp);
2131553Srgrimes
214228181Sjhb	if (newval == NULL || dflag) {
21512946Sphk		if ((kind & CTLTYPE) == CTLTYPE_NODE) {
216144998Smdodd			if (dflag) {
217144998Smdodd				i = show_var(mib, len);
218144998Smdodd				if (!i && !bflag)
219144998Smdodd					putchar('\n');
220144998Smdodd			}
22112946Sphk			sysctl_all(mib, len);
22212946Sphk		} else {
22312946Sphk			i = show_var(mib, len);
22412946Sphk			if (!i && !bflag)
22512946Sphk				putchar('\n');
2261553Srgrimes		}
22712946Sphk	} else {
22812946Sphk		if ((kind & CTLTYPE) == CTLTYPE_NODE)
22912946Sphk			errx(1, "oid '%s' isn't a leaf node", bufp);
2301553Srgrimes
231121849Ssilby		if (!(kind & CTLFLAG_WR)) {
232121306Ssilby			if (kind & CTLFLAG_TUN) {
233121849Ssilby				warnx("oid '%s' is a read only tunable", bufp);
234121849Ssilby				errx(1, "Tunable values are set in /boot/loader.conf");
235121306Ssilby			} else {
236121306Ssilby				errx(1, "oid '%s' is read only", bufp);
237121849Ssilby			}
238121306Ssilby		}
239116383Srwatson
240116383Srwatson		if ((kind & CTLTYPE) == CTLTYPE_INT ||
241116383Srwatson		    (kind & CTLTYPE) == CTLTYPE_UINT ||
242116383Srwatson		    (kind & CTLTYPE) == CTLTYPE_LONG ||
243126472Sdd		    (kind & CTLTYPE) == CTLTYPE_ULONG ||
244217616Smdf		    (kind & CTLTYPE) == CTLTYPE_S64 ||
245217616Smdf		    (kind & CTLTYPE) == CTLTYPE_U64) {
246116383Srwatson			if (strlen(newval) == 0)
247116383Srwatson				errx(1, "empty numeric value");
248116383Srwatson		}
249122234Sdes
25012946Sphk		switch (kind & CTLTYPE) {
25112946Sphk			case CTLTYPE_INT:
252161951Sume				if (strcmp(fmt, "IK") == 0) {
253170512Sdwmalone					if (!set_IK(newval, &intval))
254161951Sume						errx(1, "invalid value '%s'",
255170513Sdwmalone						    (char *)newval);
256161951Sume 				} else {
257161951Sume					intval = (int)strtol(newval, &endptr,
258161951Sume					    0);
259161951Sume					if (endptr == newval || *endptr != '\0')
260161951Sume						errx(1, "invalid integer '%s'",
261170513Sdwmalone						    (char *)newval);
262161951Sume				}
26312946Sphk				newval = &intval;
26477928Sdd				newsize = sizeof(intval);
2651553Srgrimes				break;
26678434Spirzyk			case CTLTYPE_UINT:
267116383Srwatson				uintval = (int) strtoul(newval, &endptr, 0);
268116383Srwatson				if (endptr == newval || *endptr != '\0')
269116383Srwatson					errx(1, "invalid unsigned integer '%s'",
270170513Sdwmalone					    (char *)newval);
27178434Spirzyk				newval = &uintval;
272170512Sdwmalone				newsize = sizeof(uintval);
27312946Sphk				break;
27478434Spirzyk			case CTLTYPE_LONG:
275116383Srwatson				longval = strtol(newval, &endptr, 0);
276116383Srwatson				if (endptr == newval || *endptr != '\0')
277116383Srwatson					errx(1, "invalid long integer '%s'",
278170513Sdwmalone					    (char *)newval);
27978434Spirzyk				newval = &longval;
280170512Sdwmalone				newsize = sizeof(longval);
28178434Spirzyk				break;
28278434Spirzyk			case CTLTYPE_ULONG:
283116383Srwatson				ulongval = strtoul(newval, &endptr, 0);
284116383Srwatson				if (endptr == newval || *endptr != '\0')
285116383Srwatson					errx(1, "invalid unsigned long integer"
286170513Sdwmalone					    " '%s'", (char *)newval);
28778434Spirzyk				newval = &ulongval;
288170512Sdwmalone				newsize = sizeof(ulongval);
28978434Spirzyk				break;
29012946Sphk			case CTLTYPE_STRING:
29112946Sphk				break;
292217616Smdf			case CTLTYPE_S64:
293217616Smdf				i64val = strtoimax(newval, &endptr, 0);
294203917Suqs				if (endptr == newval || *endptr != '\0')
295217616Smdf					errx(1, "invalid int64_t '%s'",
296217616Smdf					    (char *)newval);
297217616Smdf				newval = &i64val;
298217616Smdf				newsize = sizeof(i64val);
29912946Sphk				break;
300217616Smdf			case CTLTYPE_U64:
301217616Smdf				u64val = strtoumax(newval, &endptr, 0);
302217616Smdf				if (endptr == newval || *endptr != '\0')
303217616Smdf					errx(1, "invalid uint64_t '%s'",
304217616Smdf					    (char *)newval);
305217616Smdf				newval = &u64val;
306217616Smdf				newsize = sizeof(u64val);
307217616Smdf				break;
30888696Sphk			case CTLTYPE_OPAQUE:
30988696Sphk				/* FALLTHROUGH */
31012946Sphk			default:
31112946Sphk				errx(1, "oid '%s' is type %d,"
31231214Sjdp					" cannot set that", bufp,
31331214Sjdp					kind & CTLTYPE);
3141553Srgrimes		}
3151553Srgrimes
31612946Sphk		i = show_var(mib, len);
31712946Sphk		if (sysctl(mib, len, 0, 0, newval, newsize) == -1) {
31812946Sphk			if (!i && !bflag)
31912946Sphk				putchar('\n');
32012946Sphk			switch (errno) {
32112946Sphk			case EOPNOTSUPP:
322122234Sdes				errx(1, "%s: value is not available",
32312946Sphk					string);
32412946Sphk			case ENOTDIR:
325122234Sdes				errx(1, "%s: specification is incomplete",
32612946Sphk					string);
32712946Sphk			case ENOMEM:
328122234Sdes				errx(1, "%s: type is unknown to this program",
32912946Sphk					string);
33012946Sphk			default:
33130602Scharnier				warn("%s", string);
332179965Smtm				warncount++;
33312946Sphk				return;
33412946Sphk			}
33512946Sphk		}
33612946Sphk		if (!bflag)
33712946Sphk			printf(" -> ");
33812946Sphk		i = nflag;
33912946Sphk		nflag = 1;
34012946Sphk		j = show_var(mib, len);
34112946Sphk		if (!j && !bflag)
34212946Sphk			putchar('\n');
34312946Sphk		nflag = i;
34412946Sphk	}
34512946Sphk}
3461553Srgrimes
34712946Sphk/* These functions will dump out various interesting structures. */
3481553Srgrimes
34912946Sphkstatic int
35012946SphkS_clockinfo(int l2, void *p)
35112946Sphk{
35212946Sphk	struct clockinfo *ci = (struct clockinfo*)p;
353170512Sdwmalone
35497232Salfred	if (l2 != sizeof(*ci)) {
355203917Suqs		warnx("S_clockinfo %d != %zu", l2, sizeof(*ci));
356170558Sbde		return (1);
35797232Salfred	}
358122233Sdes	printf(hflag ? "{ hz = %'d, tick = %'d, profhz = %'d, stathz = %'d }" :
359122233Sdes		"{ hz = %d, tick = %d, profhz = %d, stathz = %d }",
36094752Sphk		ci->hz, ci->tick, ci->profhz, ci->stathz);
36112946Sphk	return (0);
36212946Sphk}
3631553Srgrimes
36412946Sphkstatic int
36512946SphkS_loadavg(int l2, void *p)
36612946Sphk{
36712946Sphk	struct loadavg *tv = (struct loadavg*)p;
3688857Srgrimes
36997232Salfred	if (l2 != sizeof(*tv)) {
370203917Suqs		warnx("S_loadavg %d != %zu", l2, sizeof(*tv));
371170558Sbde		return (1);
37297232Salfred	}
373122233Sdes	printf(hflag ? "{ %'.2f %'.2f %'.2f }" : "{ %.2f %.2f %.2f }",
37412946Sphk		(double)tv->ldavg[0]/(double)tv->fscale,
37512946Sphk		(double)tv->ldavg[1]/(double)tv->fscale,
37612946Sphk		(double)tv->ldavg[2]/(double)tv->fscale);
37712946Sphk	return (0);
37812946Sphk}
3791553Srgrimes
38012946Sphkstatic int
38112946SphkS_timeval(int l2, void *p)
38212946Sphk{
38312946Sphk	struct timeval *tv = (struct timeval*)p;
38437266Sbde	time_t tv_sec;
38512946Sphk	char *p1, *p2;
3861553Srgrimes
38797232Salfred	if (l2 != sizeof(*tv)) {
388203917Suqs		warnx("S_timeval %d != %zu", l2, sizeof(*tv));
389170558Sbde		return (1);
39097232Salfred	}
391194684Sjhay	printf(hflag ? "{ sec = %'jd, usec = %'ld } " :
392194684Sjhay		"{ sec = %jd, usec = %ld } ",
393194684Sjhay		(intmax_t)tv->tv_sec, tv->tv_usec);
39437266Sbde	tv_sec = tv->tv_sec;
39537266Sbde	p1 = strdup(ctime(&tv_sec));
39612946Sphk	for (p2=p1; *p2 ; p2++)
39712946Sphk		if (*p2 == '\n')
39812946Sphk			*p2 = '\0';
39912946Sphk	fputs(p1, stdout);
400205118Sbrucec	free(p1);
40112946Sphk	return (0);
40212946Sphk}
4031553Srgrimes
40412946Sphkstatic int
405109097SdillonS_vmtotal(int l2, void *p)
406109097Sdillon{
407109097Sdillon	struct vmtotal *v = (struct vmtotal *)p;
408109113Sdillon	int pageKilo = getpagesize() / 1024;
409109097Sdillon
410109097Sdillon	if (l2 != sizeof(*v)) {
411203917Suqs		warnx("S_vmtotal %d != %zu", l2, sizeof(*v));
412170558Sbde		return (1);
413109097Sdillon	}
414109097Sdillon
415109113Sdillon	printf(
416109113Sdillon	    "\nSystem wide totals computed every five seconds:"
417109113Sdillon	    " (values in kilobytes)\n");
418109097Sdillon	printf("===============================================\n");
419109113Sdillon	printf(
420164718Sru	    "Processes:\t\t(RUNQ: %hd Disk Wait: %hd Page Wait: "
421164718Sru	    "%hd Sleep: %hd)\n",
422109113Sdillon	    v->t_rq, v->t_dw, v->t_pw, v->t_sl);
423109113Sdillon	printf(
424212726Szec	    "Virtual Memory:\t\t(Total: %dK Active: %dK)\n",
425164718Sru	    v->t_vm * pageKilo, v->t_avm * pageKilo);
426212726Szec	printf("Real Memory:\t\t(Total: %dK Active: %dK)\n",
427164718Sru	    v->t_rm * pageKilo, v->t_arm * pageKilo);
428164718Sru	printf("Shared Virtual Memory:\t(Total: %dK Active: %dK)\n",
429164718Sru	    v->t_vmshr * pageKilo, v->t_avmshr * pageKilo);
430164718Sru	printf("Shared Real Memory:\t(Total: %dK Active: %dK)\n",
431164718Sru	    v->t_rmshr * pageKilo, v->t_armshr * pageKilo);
432234134Seadler	printf("Free Memory:\t%dK\n", v->t_free * pageKilo);
433122234Sdes
434109097Sdillon	return (0);
435109097Sdillon}
436109097Sdillon
437109097Sdillonstatic int
438198340Sedset_IK(const char *str, int *val)
439161951Sume{
440161951Sume	float temp;
441161951Sume	int len, kelv;
442198340Sed	const char *p;
443198340Sed	char *endptr;
444161951Sume
445161951Sume	if ((len = strlen(str)) == 0)
446161951Sume		return (0);
447161951Sume	p = &str[len - 1];
448161951Sume	if (*p == 'C' || *p == 'F') {
449161951Sume		temp = strtof(str, &endptr);
450198340Sed		if (endptr == str || endptr != p)
451161951Sume			return (0);
452161951Sume		if (*p == 'F')
453161951Sume			temp = (temp - 32) * 5 / 9;
454161951Sume		kelv = temp * 10 + 2732;
455161951Sume	} else {
456161951Sume		kelv = (int)strtol(str, &endptr, 10);
457161951Sume		if (endptr == str || *endptr != '\0')
458161951Sume			return (0);
459161951Sume	}
460161951Sume	*val = kelv;
461161951Sume	return (1);
462161951Sume}
463161951Sume
46412946Sphk/*
46512946Sphk * These functions uses a presently undocumented interface to the kernel
46612946Sphk * to walk the tree and get the type so it can print the value.
46712946Sphk * This interface is under work and consideration, and should probably
46812946Sphk * be killed with a big axe by the first person who can find the time.
46912946Sphk * (be aware though, that the proper interface isn't as obvious as it
47012946Sphk * may seem, there are various conflicting requirements.
47112946Sphk */
4721553Srgrimes
47312946Sphkstatic int
47412946Sphkname2oid(char *name, int *oidp)
47512946Sphk{
47612946Sphk	int oid[2];
47738533Sdfr	int i;
47838533Sdfr	size_t j;
4791553Srgrimes
48012946Sphk	oid[0] = 0;
48112946Sphk	oid[1] = 3;
4821553Srgrimes
48377928Sdd	j = CTL_MAXNAME * sizeof(int);
48412946Sphk	i = sysctl(oid, 2, oidp, &j, name, strlen(name));
485122234Sdes	if (i < 0)
486170512Sdwmalone		return (i);
48777928Sdd	j /= sizeof(int);
48812946Sphk	return (j);
4891553Srgrimes}
4901553Srgrimes
49112946Sphkstatic int
49212946Sphkoidfmt(int *oid, int len, char *fmt, u_int *kind)
49312946Sphk{
49412946Sphk	int qoid[CTL_MAXNAME+2];
49512946Sphk	u_char buf[BUFSIZ];
49638533Sdfr	int i;
49738533Sdfr	size_t j;
4981553Srgrimes
49912946Sphk	qoid[0] = 0;
50012946Sphk	qoid[1] = 4;
50112946Sphk	memcpy(qoid + 2, oid, len * sizeof(int));
5021553Srgrimes
50377928Sdd	j = sizeof(buf);
50412946Sphk	i = sysctl(qoid, len + 2, buf, &j, 0, 0);
50512946Sphk	if (i)
506203917Suqs		err(1, "sysctl fmt %d %zu %d", i, j, errno);
5071553Srgrimes
50812946Sphk	if (kind)
50912946Sphk		*kind = *(u_int *)buf;
51012946Sphk
51112946Sphk	if (fmt)
51212946Sphk		strcpy(fmt, (char *)(buf + sizeof(u_int)));
513170512Sdwmalone	return (0);
5141553Srgrimes}
5151553Srgrimes
516217616Smdfstatic int ctl_sign[CTLTYPE+1] = {
517217616Smdf	[CTLTYPE_INT] = 1,
518217616Smdf	[CTLTYPE_LONG] = 1,
519217616Smdf	[CTLTYPE_S64] = 1,
520217616Smdf};
521217616Smdf
522217616Smdfstatic int ctl_size[CTLTYPE+1] = {
523217616Smdf	[CTLTYPE_INT] = sizeof(int),
524217616Smdf	[CTLTYPE_UINT] = sizeof(u_int),
525217616Smdf	[CTLTYPE_LONG] = sizeof(long),
526217616Smdf	[CTLTYPE_ULONG] = sizeof(u_long),
527217616Smdf	[CTLTYPE_S64] = sizeof(int64_t),
528217616Smdf	[CTLTYPE_U64] = sizeof(int64_t),
529217616Smdf};
530217616Smdf
5311553Srgrimes/*
53212946Sphk * This formats and outputs the value of one variable
53312946Sphk *
53412946Sphk * Returns zero if anything was actually output.
53512946Sphk * Returns one if didn't know what to do with this.
53612946Sphk * Return minus one if we had errors.
5371553Srgrimes */
53812946Sphkstatic int
53912946Sphkshow_var(int *oid, int nlen)
5401553Srgrimes{
541162073Sru	u_char buf[BUFSIZ], *val, *oval, *p;
542170513Sdwmalone	char name[BUFSIZ], *fmt;
543170513Sdwmalone	const char *sep, *sep1;
54412946Sphk	int qoid[CTL_MAXNAME+2];
545170512Sdwmalone	uintmax_t umv;
546170512Sdwmalone	intmax_t mv;
547217586Smdf	int i, hexlen, sign, ctltype;
548170287Sdwmalone	size_t intlen;
54938533Sdfr	size_t j, len;
55012946Sphk	u_int kind;
55177332Sdes	int (*func)(int, void *);
5521553Srgrimes
553203917Suqs	/* Silence GCC. */
554203917Suqs	umv = mv = intlen = 0;
555203917Suqs
556144997Smdodd	bzero(buf, BUFSIZ);
557144997Smdodd	bzero(name, BUFSIZ);
55842456Sdes	qoid[0] = 0;
55942456Sdes	memcpy(qoid + 2, oid, nlen * sizeof(int));
56042456Sdes
56142456Sdes	qoid[1] = 1;
56277928Sdd	j = sizeof(name);
56342456Sdes	i = sysctl(qoid, nlen + 2, name, &j, 0, 0);
56442456Sdes	if (i || !j)
565203917Suqs		err(1, "sysctl name %d %zu %d", i, j, errno);
56642456Sdes
56771034Sdes	if (Nflag) {
56871034Sdes		printf("%s", name);
56971034Sdes		return (0);
57071034Sdes	}
57171034Sdes
57285747Stobez	if (eflag)
57385747Stobez		sep = "=";
57485747Stobez	else
57585747Stobez		sep = ": ";
57685747Stobez
57788006Sluigi	if (dflag) {	/* just print description */
57888006Sluigi		qoid[1] = 5;
57988006Sluigi		j = sizeof(buf);
58088006Sluigi		i = sysctl(qoid, nlen + 2, buf, &j, 0, 0);
58188006Sluigi		if (!nflag)
58288006Sluigi			printf("%s%s", name, sep);
58388006Sluigi		printf("%s", buf);
58488006Sluigi		return (0);
58588006Sluigi	}
58612946Sphk	/* find an estimate of how much we need for this var */
58712946Sphk	j = 0;
58812946Sphk	i = sysctl(oid, nlen, 0, &j, 0, 0);
58912946Sphk	j += j; /* we want to be sure :-) */
59012946Sphk
591162073Sru	val = oval = malloc(j + 1);
592162073Sru	if (val == NULL) {
593162073Sru		warnx("malloc failed");
594170558Sbde		return (1);
595162073Sru	}
59612946Sphk	len = j;
59712946Sphk	i = sysctl(oid, nlen, val, &len, 0, 0);
598162073Sru	if (i || !len) {
599162073Sru		free(oval);
60012946Sphk		return (1);
601162073Sru	}
60212946Sphk
60312946Sphk	if (bflag) {
60412946Sphk		fwrite(val, 1, len, stdout);
605162073Sru		free(oval);
60612946Sphk		return (0);
6071553Srgrimes	}
60896234Sache	val[len] = '\0';
60988696Sphk	fmt = buf;
61088696Sphk	oidfmt(oid, nlen, fmt, &kind);
61112946Sphk	p = val;
612217586Smdf	ctltype = (kind & CTLTYPE);
613217616Smdf	sign = ctl_sign[ctltype];
614217616Smdf	intlen = ctl_size[ctltype];
615217616Smdf
616244106Salfred	/* if Wflag then only list sysctls that are writeable and not stats. */
617244106Salfred	if (Wflag && ((kind & CTLFLAG_WR) == 0 || (kind & CTLFLAG_STATS) != 0))
618244106Salfred		return 1;
619244106Salfred
620244106Salfred	/* if Tflag then only list sysctls that are tuneables. */
621244106Salfred	if (Tflag && (kind & CTLFLAG_TUN) == 0)
622244106Salfred		return 1;
623244106Salfred
624217586Smdf	switch (ctltype) {
625217586Smdf	case CTLTYPE_STRING:
62612946Sphk		if (!nflag)
62785747Stobez			printf("%s%s", name, sep);
628203917Suqs		printf("%.*s", (int)len, p);
629162073Sru		free(oval);
63012946Sphk		return (0);
631122234Sdes
632217586Smdf	case CTLTYPE_INT:
633217586Smdf	case CTLTYPE_UINT:
634217586Smdf	case CTLTYPE_LONG:
635217586Smdf	case CTLTYPE_ULONG:
636217616Smdf	case CTLTYPE_S64:
637217616Smdf	case CTLTYPE_U64:
63812946Sphk		if (!nflag)
63985747Stobez			printf("%s%s", name, sep);
640170514Sdwmalone		hexlen = 2 + (intlen * CHAR_BIT + 3) / 4;
641170513Sdwmalone		sep1 = "";
642170287Sdwmalone		while (len >= intlen) {
643217586Smdf			switch (kind & CTLTYPE) {
644217586Smdf			case CTLTYPE_INT:
645217586Smdf			case CTLTYPE_UINT:
646170514Sdwmalone				umv = *(u_int *)p;
647170514Sdwmalone				mv = *(int *)p;
648170287Sdwmalone				break;
649217586Smdf			case CTLTYPE_LONG:
650217586Smdf			case CTLTYPE_ULONG:
651170514Sdwmalone				umv = *(u_long *)p;
652170514Sdwmalone				mv = *(long *)p;
653170287Sdwmalone				break;
654217616Smdf			case CTLTYPE_S64:
655217616Smdf			case CTLTYPE_U64:
656217616Smdf				umv = *(uint64_t *)p;
657217616Smdf				mv = *(int64_t *)p;
658170287Sdwmalone				break;
659170287Sdwmalone			}
660170513Sdwmalone			fputs(sep1, stdout);
661217586Smdf			if (xflag)
662217586Smdf				printf("%#0*jx", hexlen, umv);
663217586Smdf			else if (!sign)
664170512Sdwmalone				printf(hflag ? "%'ju" : "%ju", umv);
665170287Sdwmalone			else if (fmt[1] == 'K') {
666170514Sdwmalone				if (mv < 0)
667170512Sdwmalone					printf("%jd", mv);
668134541Speter				else
669170512Sdwmalone					printf("%.1fC", (mv - 2732.0) / 10);
670134541Speter			} else
671170513Sdwmalone				printf(hflag ? "%'jd" : "%jd", mv);
672170513Sdwmalone			sep1 = " ";
673170287Sdwmalone			len -= intlen;
674170287Sdwmalone			p += intlen;
67541019Sphk		}
676162073Sru		free(oval);
67712946Sphk		return (0);
67812946Sphk
679217586Smdf	case CTLTYPE_OPAQUE:
68012946Sphk		i = 0;
68177332Sdes		if (strcmp(fmt, "S,clockinfo") == 0)
68277332Sdes			func = S_clockinfo;
68377332Sdes		else if (strcmp(fmt, "S,timeval") == 0)
68477332Sdes			func = S_timeval;
68577332Sdes		else if (strcmp(fmt, "S,loadavg") == 0)
68677332Sdes			func = S_loadavg;
687109097Sdillon		else if (strcmp(fmt, "S,vmtotal") == 0)
688109097Sdillon			func = S_vmtotal;
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);
706203917Suqs		printf("Format:%s Length:%zu 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
719170512Sdwmalonesysctl_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)
740170512Sdwmalone				return (0);
74112946Sphk			else
742203917Suqs				err(1, "sysctl(getnext) %d %zu", j, l2);
74348956Sbillf		}
74412946Sphk
74577928Sdd		l2 /= sizeof(int);
74612946Sphk
747170513Sdwmalone		if (len < 0 || l2 < (unsigned int)len)
748170512Sdwmalone			return (0);
74912946Sphk
75012946Sphk		for (i = 0; i < len; i++)
75112946Sphk			if (name2[i] != oid[i])
752170512Sdwmalone				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