sysctl.c revision 212726
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 212726 2010-09-16 10:53:01Z zec $";
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;
62203310Sgavinstatic int	Nflag, nflag, oflag, qflag, xflag, warncount;
631553Srgrimes
6412946Sphkstatic int	oidfmt(int *, int, char *, u_int *);
6512946Sphkstatic void	parse(char *);
6612946Sphkstatic int	show_var(int *, int);
67170512Sdwmalonestatic int	sysctl_all(int *oid, int len);
6812946Sphkstatic int	name2oid(char *, int *);
691553Srgrimes
70170512Sdwmalonestatic void	set_T_dev_t(char *, void **, size_t *);
71198340Sedstatic int	set_IK(const char *, int *);
7288696Sphk
7312946Sphkstatic void
7412946Sphkusage(void)
7512946Sphk{
761553Srgrimes
7777330Sdes	(void)fprintf(stderr, "%s\n%s\n",
78203717Sgavin	    "usage: sysctl [-bdehiNnoqx] name[=value] ...",
79152995Sru	    "       sysctl [-bdehNnoqx] -a");
8012946Sphk	exit(1);
8112946Sphk}
821553Srgrimes
831553Srgrimesint
8412946Sphkmain(int argc, char **argv)
851553Srgrimes{
8612946Sphk	int ch;
87122233Sdes
88122233Sdes	setlocale(LC_NUMERIC, "");
8912946Sphk	setbuf(stdout,0);
9012946Sphk	setbuf(stderr,0);
911553Srgrimes
92203310Sgavin	while ((ch = getopt(argc, argv, "AabdehiNnoqwxX")) != -1) {
931553Srgrimes		switch (ch) {
9471034Sdes		case 'A':
9577330Sdes			/* compatibility */
9677330Sdes			aflag = oflag = 1;
9771034Sdes			break;
9871034Sdes		case 'a':
9971034Sdes			aflag = 1;
10071034Sdes			break;
10171034Sdes		case 'b':
10271034Sdes			bflag = 1;
10371034Sdes			break;
10488006Sluigi		case 'd':
10588006Sluigi			dflag = 1;
10688006Sluigi			break;
10785747Stobez		case 'e':
10885747Stobez			eflag = 1;
10985747Stobez			break;
110122233Sdes		case 'h':
111122233Sdes			hflag = 1;
112122233Sdes			break;
113203310Sgavin		case 'i':
114203310Sgavin			iflag = 1;
115203310Sgavin			break;
11671034Sdes		case 'N':
11771034Sdes			Nflag = 1;
11871034Sdes			break;
11971034Sdes		case 'n':
12071034Sdes			nflag = 1;
12171034Sdes			break;
12277330Sdes		case 'o':
12377330Sdes			oflag = 1;
12477330Sdes			break;
125150167Srwatson		case 'q':
126150167Srwatson			qflag = 1;
127150167Srwatson			break;
12871034Sdes		case 'w':
12977330Sdes			/* compatibility */
13077330Sdes			/* ignored */
13171034Sdes			break;
13271034Sdes		case 'X':
13377330Sdes			/* compatibility */
13477330Sdes			aflag = xflag = 1;
13571034Sdes			break;
13677330Sdes		case 'x':
13777330Sdes			xflag = 1;
13877330Sdes			break;
13971034Sdes		default:
14071034Sdes			usage();
1411553Srgrimes		}
1421553Srgrimes	}
1431553Srgrimes	argc -= optind;
1441553Srgrimes	argv += optind;
1451553Srgrimes
14677330Sdes	if (Nflag && nflag)
14742456Sdes		usage();
14877330Sdes	if (aflag && argc == 0)
14977330Sdes		exit(sysctl_all(0, 0));
1501553Srgrimes	if (argc == 0)
1511553Srgrimes		usage();
152179965Smtm
153179965Smtm	warncount = 0;
1541553Srgrimes	while (argc-- > 0)
15512946Sphk		parse(*argv++);
156179965Smtm	exit(warncount);
1571553Srgrimes}
1581553Srgrimes
1591553Srgrimes/*
1601553Srgrimes * Parse a name into a MIB entry.
1611553Srgrimes * Lookup and print out the MIB entry if it exists.
1621553Srgrimes * Set a new value if requested.
1631553Srgrimes */
16412946Sphkstatic void
16512946Sphkparse(char *string)
1661553Srgrimes{
16712946Sphk	int len, i, j;
1681553Srgrimes	void *newval = 0;
16978434Spirzyk	int intval;
17078434Spirzyk	unsigned int uintval;
17178434Spirzyk	long longval;
17278434Spirzyk	unsigned long ulongval;
17378434Spirzyk	size_t newsize = 0;
1741553Srgrimes	quad_t quadval;
1751553Srgrimes	int mib[CTL_MAXNAME];
176116383Srwatson	char *cp, *bufp, buf[BUFSIZ], *endptr, fmt[BUFSIZ];
17712946Sphk	u_int kind;
1781553Srgrimes
1791553Srgrimes	bufp = buf;
180140818Sssouhlal	if (snprintf(buf, BUFSIZ, "%s", string) >= BUFSIZ)
181140818Sssouhlal		errx(1, "oid too long: '%s'", string);
1821553Srgrimes	if ((cp = strchr(string, '=')) != NULL) {
1831553Srgrimes		*strchr(buf, '=') = '\0';
1841553Srgrimes		*cp++ = '\0';
1851553Srgrimes		while (isspace(*cp))
1861553Srgrimes			cp++;
1871553Srgrimes		newval = cp;
1881553Srgrimes		newsize = strlen(cp);
1891553Srgrimes	}
19012946Sphk	len = name2oid(bufp, mib);
1911553Srgrimes
192150167Srwatson	if (len < 0) {
193203310Sgavin		if (iflag)
194203310Sgavin			return;
195150167Srwatson		if (qflag)
196150167Srwatson			exit(1);
197150167Srwatson		else
198150167Srwatson			errx(1, "unknown oid '%s'", bufp);
199150167Srwatson	}
2001553Srgrimes
20188696Sphk	if (oidfmt(mib, len, fmt, &kind))
20230602Scharnier		err(1, "couldn't find format of oid '%s'", bufp);
2031553Srgrimes
20477330Sdes	if (newval == NULL) {
20512946Sphk		if ((kind & CTLTYPE) == CTLTYPE_NODE) {
206144998Smdodd			if (dflag) {
207144998Smdodd				i = show_var(mib, len);
208144998Smdodd				if (!i && !bflag)
209144998Smdodd					putchar('\n');
210144998Smdodd			}
21112946Sphk			sysctl_all(mib, len);
21212946Sphk		} else {
21312946Sphk			i = show_var(mib, len);
21412946Sphk			if (!i && !bflag)
21512946Sphk				putchar('\n');
2161553Srgrimes		}
21712946Sphk	} else {
21812946Sphk		if ((kind & CTLTYPE) == CTLTYPE_NODE)
21912946Sphk			errx(1, "oid '%s' isn't a leaf node", bufp);
2201553Srgrimes
221121849Ssilby		if (!(kind & CTLFLAG_WR)) {
222121306Ssilby			if (kind & CTLFLAG_TUN) {
223121849Ssilby				warnx("oid '%s' is a read only tunable", bufp);
224121849Ssilby				errx(1, "Tunable values are set in /boot/loader.conf");
225121306Ssilby			} else {
226121306Ssilby				errx(1, "oid '%s' is read only", bufp);
227121849Ssilby			}
228121306Ssilby		}
229116383Srwatson
230116383Srwatson		if ((kind & CTLTYPE) == CTLTYPE_INT ||
231116383Srwatson		    (kind & CTLTYPE) == CTLTYPE_UINT ||
232116383Srwatson		    (kind & CTLTYPE) == CTLTYPE_LONG ||
233126472Sdd		    (kind & CTLTYPE) == CTLTYPE_ULONG ||
234126472Sdd		    (kind & CTLTYPE) == CTLTYPE_QUAD) {
235116383Srwatson			if (strlen(newval) == 0)
236116383Srwatson				errx(1, "empty numeric value");
237116383Srwatson		}
238122234Sdes
23912946Sphk		switch (kind & CTLTYPE) {
24012946Sphk			case CTLTYPE_INT:
241161951Sume				if (strcmp(fmt, "IK") == 0) {
242170512Sdwmalone					if (!set_IK(newval, &intval))
243161951Sume						errx(1, "invalid value '%s'",
244170513Sdwmalone						    (char *)newval);
245161951Sume 				} else {
246161951Sume					intval = (int)strtol(newval, &endptr,
247161951Sume					    0);
248161951Sume					if (endptr == newval || *endptr != '\0')
249161951Sume						errx(1, "invalid integer '%s'",
250170513Sdwmalone						    (char *)newval);
251161951Sume				}
25212946Sphk				newval = &intval;
25377928Sdd				newsize = sizeof(intval);
2541553Srgrimes				break;
25578434Spirzyk			case CTLTYPE_UINT:
256116383Srwatson				uintval = (int) strtoul(newval, &endptr, 0);
257116383Srwatson				if (endptr == newval || *endptr != '\0')
258116383Srwatson					errx(1, "invalid unsigned integer '%s'",
259170513Sdwmalone					    (char *)newval);
26078434Spirzyk				newval = &uintval;
261170512Sdwmalone				newsize = sizeof(uintval);
26212946Sphk				break;
26378434Spirzyk			case CTLTYPE_LONG:
264116383Srwatson				longval = strtol(newval, &endptr, 0);
265116383Srwatson				if (endptr == newval || *endptr != '\0')
266116383Srwatson					errx(1, "invalid long integer '%s'",
267170513Sdwmalone					    (char *)newval);
26878434Spirzyk				newval = &longval;
269170512Sdwmalone				newsize = sizeof(longval);
27078434Spirzyk				break;
27178434Spirzyk			case CTLTYPE_ULONG:
272116383Srwatson				ulongval = strtoul(newval, &endptr, 0);
273116383Srwatson				if (endptr == newval || *endptr != '\0')
274116383Srwatson					errx(1, "invalid unsigned long integer"
275170513Sdwmalone					    " '%s'", (char *)newval);
27678434Spirzyk				newval = &ulongval;
277170512Sdwmalone				newsize = sizeof(ulongval);
27878434Spirzyk				break;
27912946Sphk			case CTLTYPE_STRING:
28012946Sphk				break;
28112946Sphk			case CTLTYPE_QUAD:
282203917Suqs				quadval = strtoq(newval, &endptr, 0);
283203917Suqs				if (endptr == newval || *endptr != '\0')
284203917Suqs					errx(1, "invalid quad integer"
285203917Suqs					    " '%s'", (char *)newval);
28612946Sphk				newval = &quadval;
28777928Sdd				newsize = sizeof(quadval);
28812946Sphk				break;
28988696Sphk			case CTLTYPE_OPAQUE:
29088696Sphk				if (strcmp(fmt, "T,dev_t") == 0) {
291170512Sdwmalone					set_T_dev_t (newval, &newval, &newsize);
29288696Sphk					break;
29388696Sphk				}
29488696Sphk				/* FALLTHROUGH */
29512946Sphk			default:
29612946Sphk				errx(1, "oid '%s' is type %d,"
29731214Sjdp					" cannot set that", bufp,
29831214Sjdp					kind & CTLTYPE);
2991553Srgrimes		}
3001553Srgrimes
30112946Sphk		i = show_var(mib, len);
30212946Sphk		if (sysctl(mib, len, 0, 0, newval, newsize) == -1) {
30312946Sphk			if (!i && !bflag)
30412946Sphk				putchar('\n');
30512946Sphk			switch (errno) {
30612946Sphk			case EOPNOTSUPP:
307122234Sdes				errx(1, "%s: value is not available",
30812946Sphk					string);
30912946Sphk			case ENOTDIR:
310122234Sdes				errx(1, "%s: specification is incomplete",
31112946Sphk					string);
31212946Sphk			case ENOMEM:
313122234Sdes				errx(1, "%s: type is unknown to this program",
31412946Sphk					string);
31512946Sphk			default:
31630602Scharnier				warn("%s", string);
317179965Smtm				warncount++;
31812946Sphk				return;
31912946Sphk			}
32012946Sphk		}
32112946Sphk		if (!bflag)
32212946Sphk			printf(" -> ");
32312946Sphk		i = nflag;
32412946Sphk		nflag = 1;
32512946Sphk		j = show_var(mib, len);
32612946Sphk		if (!j && !bflag)
32712946Sphk			putchar('\n');
32812946Sphk		nflag = i;
32912946Sphk	}
33012946Sphk}
3311553Srgrimes
33212946Sphk/* These functions will dump out various interesting structures. */
3331553Srgrimes
33412946Sphkstatic int
33512946SphkS_clockinfo(int l2, void *p)
33612946Sphk{
33712946Sphk	struct clockinfo *ci = (struct clockinfo*)p;
338170512Sdwmalone
33997232Salfred	if (l2 != sizeof(*ci)) {
340203917Suqs		warnx("S_clockinfo %d != %zu", l2, sizeof(*ci));
341170558Sbde		return (1);
34297232Salfred	}
343122233Sdes	printf(hflag ? "{ hz = %'d, tick = %'d, profhz = %'d, stathz = %'d }" :
344122233Sdes		"{ hz = %d, tick = %d, profhz = %d, stathz = %d }",
34594752Sphk		ci->hz, ci->tick, ci->profhz, ci->stathz);
34612946Sphk	return (0);
34712946Sphk}
3481553Srgrimes
34912946Sphkstatic int
35012946SphkS_loadavg(int l2, void *p)
35112946Sphk{
35212946Sphk	struct loadavg *tv = (struct loadavg*)p;
3538857Srgrimes
35497232Salfred	if (l2 != sizeof(*tv)) {
355203917Suqs		warnx("S_loadavg %d != %zu", l2, sizeof(*tv));
356170558Sbde		return (1);
35797232Salfred	}
358122233Sdes	printf(hflag ? "{ %'.2f %'.2f %'.2f }" : "{ %.2f %.2f %.2f }",
35912946Sphk		(double)tv->ldavg[0]/(double)tv->fscale,
36012946Sphk		(double)tv->ldavg[1]/(double)tv->fscale,
36112946Sphk		(double)tv->ldavg[2]/(double)tv->fscale);
36212946Sphk	return (0);
36312946Sphk}
3641553Srgrimes
36512946Sphkstatic int
36612946SphkS_timeval(int l2, void *p)
36712946Sphk{
36812946Sphk	struct timeval *tv = (struct timeval*)p;
36937266Sbde	time_t tv_sec;
37012946Sphk	char *p1, *p2;
3711553Srgrimes
37297232Salfred	if (l2 != sizeof(*tv)) {
373203917Suqs		warnx("S_timeval %d != %zu", l2, sizeof(*tv));
374170558Sbde		return (1);
37597232Salfred	}
376194684Sjhay	printf(hflag ? "{ sec = %'jd, usec = %'ld } " :
377194684Sjhay		"{ sec = %jd, usec = %ld } ",
378194684Sjhay		(intmax_t)tv->tv_sec, tv->tv_usec);
37937266Sbde	tv_sec = tv->tv_sec;
38037266Sbde	p1 = strdup(ctime(&tv_sec));
38112946Sphk	for (p2=p1; *p2 ; p2++)
38212946Sphk		if (*p2 == '\n')
38312946Sphk			*p2 = '\0';
38412946Sphk	fputs(p1, stdout);
385205118Sbrucec	free(p1);
38612946Sphk	return (0);
38712946Sphk}
3881553Srgrimes
38912946Sphkstatic int
390109097SdillonS_vmtotal(int l2, void *p)
391109097Sdillon{
392109097Sdillon	struct vmtotal *v = (struct vmtotal *)p;
393109113Sdillon	int pageKilo = getpagesize() / 1024;
394109097Sdillon
395109097Sdillon	if (l2 != sizeof(*v)) {
396203917Suqs		warnx("S_vmtotal %d != %zu", l2, sizeof(*v));
397170558Sbde		return (1);
398109097Sdillon	}
399109097Sdillon
400109113Sdillon	printf(
401109113Sdillon	    "\nSystem wide totals computed every five seconds:"
402109113Sdillon	    " (values in kilobytes)\n");
403109097Sdillon	printf("===============================================\n");
404109113Sdillon	printf(
405164718Sru	    "Processes:\t\t(RUNQ: %hd Disk Wait: %hd Page Wait: "
406164718Sru	    "%hd Sleep: %hd)\n",
407109113Sdillon	    v->t_rq, v->t_dw, v->t_pw, v->t_sl);
408109113Sdillon	printf(
409212726Szec	    "Virtual Memory:\t\t(Total: %dK Active: %dK)\n",
410164718Sru	    v->t_vm * pageKilo, v->t_avm * pageKilo);
411212726Szec	printf("Real Memory:\t\t(Total: %dK Active: %dK)\n",
412164718Sru	    v->t_rm * pageKilo, v->t_arm * pageKilo);
413164718Sru	printf("Shared Virtual Memory:\t(Total: %dK Active: %dK)\n",
414164718Sru	    v->t_vmshr * pageKilo, v->t_avmshr * pageKilo);
415164718Sru	printf("Shared Real Memory:\t(Total: %dK Active: %dK)\n",
416164718Sru	    v->t_rmshr * pageKilo, v->t_armshr * pageKilo);
417164718Sru	printf("Free Memory Pages:\t%dK\n", v->t_free * pageKilo);
418122234Sdes
419109097Sdillon	return (0);
420109097Sdillon}
421109097Sdillon
422109097Sdillonstatic int
42312946SphkT_dev_t(int l2, void *p)
42412946Sphk{
42512946Sphk	dev_t *d = (dev_t *)p;
426170512Sdwmalone
42797232Salfred	if (l2 != sizeof(*d)) {
428203917Suqs		warnx("T_dev_T %d != %zu", l2, sizeof(*d));
429170558Sbde		return (1);
43097232Salfred	}
431198850Sed	printf("%s", devname(*d, S_IFCHR));
43212946Sphk	return (0);
43312946Sphk}
4341553Srgrimes
43588696Sphkstatic void
436170512Sdwmaloneset_T_dev_t(char *path, void **val, size_t *size)
43788696Sphk{
43888696Sphk	static struct stat statb;
43988696Sphk
44088696Sphk	if (strcmp(path, "none") && strcmp(path, "off")) {
44188696Sphk		int rc = stat (path, &statb);
44288696Sphk		if (rc) {
44388696Sphk			err(1, "cannot stat %s", path);
44488696Sphk		}
44588696Sphk
44688696Sphk		if (!S_ISCHR(statb.st_mode)) {
44788696Sphk			errx(1, "must specify a device special file.");
44888696Sphk		}
44988696Sphk	} else {
45088696Sphk		statb.st_rdev = NODEV;
45188696Sphk	}
452170512Sdwmalone	*val = (void *) &statb.st_rdev;
453170512Sdwmalone	*size = sizeof(statb.st_rdev);
45488696Sphk}
45588696Sphk
456161951Sumestatic int
457198340Sedset_IK(const char *str, int *val)
458161951Sume{
459161951Sume	float temp;
460161951Sume	int len, kelv;
461198340Sed	const char *p;
462198340Sed	char *endptr;
463161951Sume
464161951Sume	if ((len = strlen(str)) == 0)
465161951Sume		return (0);
466161951Sume	p = &str[len - 1];
467161951Sume	if (*p == 'C' || *p == 'F') {
468161951Sume		temp = strtof(str, &endptr);
469198340Sed		if (endptr == str || endptr != p)
470161951Sume			return (0);
471161951Sume		if (*p == 'F')
472161951Sume			temp = (temp - 32) * 5 / 9;
473161951Sume		kelv = temp * 10 + 2732;
474161951Sume	} else {
475161951Sume		kelv = (int)strtol(str, &endptr, 10);
476161951Sume		if (endptr == str || *endptr != '\0')
477161951Sume			return (0);
478161951Sume	}
479161951Sume	*val = kelv;
480161951Sume	return (1);
481161951Sume}
482161951Sume
48312946Sphk/*
48412946Sphk * These functions uses a presently undocumented interface to the kernel
48512946Sphk * to walk the tree and get the type so it can print the value.
48612946Sphk * This interface is under work and consideration, and should probably
48712946Sphk * be killed with a big axe by the first person who can find the time.
48812946Sphk * (be aware though, that the proper interface isn't as obvious as it
48912946Sphk * may seem, there are various conflicting requirements.
49012946Sphk */
4911553Srgrimes
49212946Sphkstatic int
49312946Sphkname2oid(char *name, int *oidp)
49412946Sphk{
49512946Sphk	int oid[2];
49638533Sdfr	int i;
49738533Sdfr	size_t j;
4981553Srgrimes
49912946Sphk	oid[0] = 0;
50012946Sphk	oid[1] = 3;
5011553Srgrimes
50277928Sdd	j = CTL_MAXNAME * sizeof(int);
50312946Sphk	i = sysctl(oid, 2, oidp, &j, name, strlen(name));
504122234Sdes	if (i < 0)
505170512Sdwmalone		return (i);
50677928Sdd	j /= sizeof(int);
50712946Sphk	return (j);
5081553Srgrimes}
5091553Srgrimes
51012946Sphkstatic int
51112946Sphkoidfmt(int *oid, int len, char *fmt, u_int *kind)
51212946Sphk{
51312946Sphk	int qoid[CTL_MAXNAME+2];
51412946Sphk	u_char buf[BUFSIZ];
51538533Sdfr	int i;
51638533Sdfr	size_t j;
5171553Srgrimes
51812946Sphk	qoid[0] = 0;
51912946Sphk	qoid[1] = 4;
52012946Sphk	memcpy(qoid + 2, oid, len * sizeof(int));
5211553Srgrimes
52277928Sdd	j = sizeof(buf);
52312946Sphk	i = sysctl(qoid, len + 2, buf, &j, 0, 0);
52412946Sphk	if (i)
525203917Suqs		err(1, "sysctl fmt %d %zu %d", i, j, errno);
5261553Srgrimes
52712946Sphk	if (kind)
52812946Sphk		*kind = *(u_int *)buf;
52912946Sphk
53012946Sphk	if (fmt)
53112946Sphk		strcpy(fmt, (char *)(buf + sizeof(u_int)));
532170512Sdwmalone	return (0);
5331553Srgrimes}
5341553Srgrimes
5351553Srgrimes/*
53612946Sphk * This formats and outputs the value of one variable
53712946Sphk *
53812946Sphk * Returns zero if anything was actually output.
53912946Sphk * Returns one if didn't know what to do with this.
54012946Sphk * Return minus one if we had errors.
5411553Srgrimes */
54212946Sphk
54312946Sphkstatic int
54412946Sphkshow_var(int *oid, int nlen)
5451553Srgrimes{
546162073Sru	u_char buf[BUFSIZ], *val, *oval, *p;
547170513Sdwmalone	char name[BUFSIZ], *fmt;
548170513Sdwmalone	const char *sep, *sep1;
54912946Sphk	int qoid[CTL_MAXNAME+2];
550170512Sdwmalone	uintmax_t umv;
551170512Sdwmalone	intmax_t mv;
552170514Sdwmalone	int i, hexlen;
553170287Sdwmalone	size_t intlen;
55438533Sdfr	size_t j, len;
55512946Sphk	u_int kind;
55677332Sdes	int (*func)(int, void *);
5571553Srgrimes
558203917Suqs	/* Silence GCC. */
559203917Suqs	umv = mv = intlen = 0;
560203917Suqs
561144997Smdodd	bzero(buf, BUFSIZ);
562144997Smdodd	bzero(name, BUFSIZ);
56342456Sdes	qoid[0] = 0;
56442456Sdes	memcpy(qoid + 2, oid, nlen * sizeof(int));
56542456Sdes
56642456Sdes	qoid[1] = 1;
56777928Sdd	j = sizeof(name);
56842456Sdes	i = sysctl(qoid, nlen + 2, name, &j, 0, 0);
56942456Sdes	if (i || !j)
570203917Suqs		err(1, "sysctl name %d %zu %d", i, j, errno);
57142456Sdes
57271034Sdes	if (Nflag) {
57371034Sdes		printf("%s", name);
57471034Sdes		return (0);
57571034Sdes	}
57671034Sdes
57785747Stobez	if (eflag)
57885747Stobez		sep = "=";
57985747Stobez	else
58085747Stobez		sep = ": ";
58185747Stobez
58288006Sluigi	if (dflag) {	/* just print description */
58388006Sluigi		qoid[1] = 5;
58488006Sluigi		j = sizeof(buf);
58588006Sluigi		i = sysctl(qoid, nlen + 2, buf, &j, 0, 0);
58688006Sluigi		if (!nflag)
58788006Sluigi			printf("%s%s", name, sep);
58888006Sluigi		printf("%s", buf);
58988006Sluigi		return (0);
59088006Sluigi	}
59112946Sphk	/* find an estimate of how much we need for this var */
59212946Sphk	j = 0;
59312946Sphk	i = sysctl(oid, nlen, 0, &j, 0, 0);
59412946Sphk	j += j; /* we want to be sure :-) */
59512946Sphk
596162073Sru	val = oval = malloc(j + 1);
597162073Sru	if (val == NULL) {
598162073Sru		warnx("malloc failed");
599170558Sbde		return (1);
600162073Sru	}
60112946Sphk	len = j;
60212946Sphk	i = sysctl(oid, nlen, val, &len, 0, 0);
603162073Sru	if (i || !len) {
604162073Sru		free(oval);
60512946Sphk		return (1);
606162073Sru	}
60712946Sphk
60812946Sphk	if (bflag) {
60912946Sphk		fwrite(val, 1, len, stdout);
610162073Sru		free(oval);
61112946Sphk		return (0);
6121553Srgrimes	}
61396234Sache	val[len] = '\0';
61488696Sphk	fmt = buf;
61588696Sphk	oidfmt(oid, nlen, fmt, &kind);
61612946Sphk	p = val;
61712946Sphk	switch (*fmt) {
61812946Sphk	case 'A':
61912946Sphk		if (!nflag)
62085747Stobez			printf("%s%s", name, sep);
621203917Suqs		printf("%.*s", (int)len, p);
622162073Sru		free(oval);
62312946Sphk		return (0);
624122234Sdes
62512946Sphk	case 'I':
626170287Sdwmalone	case 'L':
627170287Sdwmalone	case 'Q':
62812946Sphk		if (!nflag)
62985747Stobez			printf("%s%s", name, sep);
630170287Sdwmalone		switch (*fmt) {
631170514Sdwmalone		case 'I': intlen = sizeof(int); break;
632170514Sdwmalone		case 'L': intlen = sizeof(long); break;
633170514Sdwmalone		case 'Q': intlen = sizeof(quad_t); break;
634170287Sdwmalone		}
635170514Sdwmalone		hexlen = 2 + (intlen * CHAR_BIT + 3) / 4;
636170513Sdwmalone		sep1 = "";
637170287Sdwmalone		while (len >= intlen) {
638170287Sdwmalone			switch (*fmt) {
639170287Sdwmalone			case 'I':
640170514Sdwmalone				umv = *(u_int *)p;
641170514Sdwmalone				mv = *(int *)p;
642170287Sdwmalone				break;
643170287Sdwmalone			case 'L':
644170514Sdwmalone				umv = *(u_long *)p;
645170514Sdwmalone				mv = *(long *)p;
646170287Sdwmalone				break;
647170287Sdwmalone			case 'Q':
648170514Sdwmalone				umv = *(u_quad_t *)p;
649170514Sdwmalone				mv = *(quad_t *)p;
650170287Sdwmalone				break;
651170287Sdwmalone			}
652170513Sdwmalone			fputs(sep1, stdout);
653170287Sdwmalone			if (fmt[1] == 'U')
654170512Sdwmalone				printf(hflag ? "%'ju" : "%ju", umv);
655170287Sdwmalone			else if (fmt[1] == 'X')
656170514Sdwmalone				printf("%#0*jx", hexlen, umv);
657170287Sdwmalone			else if (fmt[1] == 'K') {
658170514Sdwmalone				if (mv < 0)
659170512Sdwmalone					printf("%jd", mv);
660134541Speter				else
661170512Sdwmalone					printf("%.1fC", (mv - 2732.0) / 10);
662134541Speter			} else
663170513Sdwmalone				printf(hflag ? "%'jd" : "%jd", mv);
664170513Sdwmalone			sep1 = " ";
665170287Sdwmalone			len -= intlen;
666170287Sdwmalone			p += intlen;
66741019Sphk		}
668162073Sru		free(oval);
66912946Sphk		return (0);
67012946Sphk
67138533Sdfr	case 'P':
67238533Sdfr		if (!nflag)
67385747Stobez			printf("%s%s", name, sep);
67438533Sdfr		printf("%p", *(void **)p);
675162073Sru		free(oval);
67638533Sdfr		return (0);
67738533Sdfr
67812946Sphk	case 'T':
67912946Sphk	case 'S':
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 if (strcmp(fmt, "T,dev_t") == 0)
69077332Sdes			func = T_dev_t;
69177332Sdes		else
69277332Sdes			func = NULL;
69312946Sphk		if (func) {
69412946Sphk			if (!nflag)
69585747Stobez				printf("%s%s", name, sep);
696163275Sharti			i = (*func)(len, p);
697162073Sru			free(oval);
698163275Sharti			return (i);
69912946Sphk		}
700102411Scharnier		/* FALLTHROUGH */
70112946Sphk	default:
702162073Sru		if (!oflag && !xflag) {
703162073Sru			free(oval);
70412946Sphk			return (1);
705162073Sru		}
70612946Sphk		if (!nflag)
70785747Stobez			printf("%s%s", name, sep);
708203917Suqs		printf("Format:%s Length:%zu Dump:0x", fmt, len);
70977332Sdes		while (len-- && (xflag || p < val + 16))
71012946Sphk			printf("%02x", *p++);
71177332Sdes		if (!xflag && len > 16)
71212946Sphk			printf("...");
713162073Sru		free(oval);
71412946Sphk		return (0);
7151553Srgrimes	}
716162073Sru	free(oval);
71712946Sphk	return (1);
7181553Srgrimes}
7191553Srgrimes
72012946Sphkstatic int
721170512Sdwmalonesysctl_all(int *oid, int len)
7221553Srgrimes{
72312946Sphk	int name1[22], name2[22];
72438533Sdfr	int i, j;
72538533Sdfr	size_t l1, l2;
7261553Srgrimes
72712946Sphk	name1[0] = 0;
72812946Sphk	name1[1] = 2;
72912946Sphk	l1 = 2;
73012946Sphk	if (len) {
73177928Sdd		memcpy(name1+2, oid, len * sizeof(int));
73212946Sphk		l1 += len;
73312946Sphk	} else {
73412946Sphk		name1[2] = 1;
73512946Sphk		l1++;
73612946Sphk	}
73777332Sdes	for (;;) {
73877928Sdd		l2 = sizeof(name2);
73912946Sphk		j = sysctl(name1, l1, name2, &l2, 0, 0);
74048956Sbillf		if (j < 0) {
74112946Sphk			if (errno == ENOENT)
742170512Sdwmalone				return (0);
74312946Sphk			else
744203917Suqs				err(1, "sysctl(getnext) %d %zu", j, l2);
74548956Sbillf		}
74612946Sphk
74777928Sdd		l2 /= sizeof(int);
74812946Sphk
749170513Sdwmalone		if (len < 0 || l2 < (unsigned int)len)
750170512Sdwmalone			return (0);
75112946Sphk
75212946Sphk		for (i = 0; i < len; i++)
75312946Sphk			if (name2[i] != oid[i])
754170512Sdwmalone				return (0);
75512946Sphk
75612946Sphk		i = show_var(name2, l2);
75712946Sphk		if (!i && !bflag)
75812946Sphk			putchar('\n');
75912946Sphk
76077928Sdd		memcpy(name1+2, name2, l2 * sizeof(int));
76112946Sphk		l1 = 2 + l2;
76212946Sphk	}
7631553Srgrimes}
764