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$";
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 *);
65244669Sdelphijstatic 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",
77203717Sgavin	    "usage: sysctl [-bdehiNnoqx] name[=value] ...",
78152995Sru	    "       sysctl [-bdehNnoqx] -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
91203310Sgavin	while ((ch = getopt(argc, argv, "AabdehiNnoqwxX")) != -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;
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();
151179965Smtm
152179965Smtm	warncount = 0;
1531553Srgrimes	while (argc-- > 0)
15412946Sphk		parse(*argv++);
155179965Smtm	exit(warncount);
1561553Srgrimes}
1571553Srgrimes
1581553Srgrimes/*
1591553Srgrimes * Parse a name into a MIB entry.
1601553Srgrimes * Lookup and print out the MIB entry if it exists.
1611553Srgrimes * Set a new value if requested.
1621553Srgrimes */
16312946Sphkstatic void
164244669Sdelphijparse(const char *string)
1651553Srgrimes{
16612946Sphk	int len, i, j;
1671553Srgrimes	void *newval = 0;
16878434Spirzyk	int intval;
16978434Spirzyk	unsigned int uintval;
17078434Spirzyk	long longval;
17178434Spirzyk	unsigned long ulongval;
17278434Spirzyk	size_t newsize = 0;
173217616Smdf	int64_t i64val;
174217616Smdf	uint64_t u64val;
1751553Srgrimes	int mib[CTL_MAXNAME];
176116383Srwatson	char *cp, *bufp, buf[BUFSIZ], *endptr, fmt[BUFSIZ];
17712946Sphk	u_int kind;
1781553Srgrimes
179244669Sdelphij	cp = buf;
180140818Sssouhlal	if (snprintf(buf, BUFSIZ, "%s", string) >= BUFSIZ)
181140818Sssouhlal		errx(1, "oid too long: '%s'", string);
182244669Sdelphij	bufp = strsep(&cp, "=");
183244669Sdelphij	if (cp != NULL) {
1841553Srgrimes		while (isspace(*cp))
1851553Srgrimes			cp++;
1861553Srgrimes		newval = cp;
1871553Srgrimes		newsize = strlen(cp);
1881553Srgrimes	}
18912946Sphk	len = name2oid(bufp, mib);
1901553Srgrimes
191150167Srwatson	if (len < 0) {
192203310Sgavin		if (iflag)
193203310Sgavin			return;
194150167Srwatson		if (qflag)
195150167Srwatson			exit(1);
196150167Srwatson		else
197150167Srwatson			errx(1, "unknown oid '%s'", bufp);
198150167Srwatson	}
1991553Srgrimes
20088696Sphk	if (oidfmt(mib, len, fmt, &kind))
20130602Scharnier		err(1, "couldn't find format of oid '%s'", bufp);
2021553Srgrimes
203229615Sjhb	if (newval == NULL || dflag) {
20412946Sphk		if ((kind & CTLTYPE) == CTLTYPE_NODE) {
205144998Smdodd			if (dflag) {
206144998Smdodd				i = show_var(mib, len);
207144998Smdodd				if (!i && !bflag)
208144998Smdodd					putchar('\n');
209144998Smdodd			}
21012946Sphk			sysctl_all(mib, len);
21112946Sphk		} else {
21212946Sphk			i = show_var(mib, len);
21312946Sphk			if (!i && !bflag)
21412946Sphk				putchar('\n');
2151553Srgrimes		}
21612946Sphk	} else {
21712946Sphk		if ((kind & CTLTYPE) == CTLTYPE_NODE)
21812946Sphk			errx(1, "oid '%s' isn't a leaf node", bufp);
2191553Srgrimes
220121849Ssilby		if (!(kind & CTLFLAG_WR)) {
221121306Ssilby			if (kind & CTLFLAG_TUN) {
222121849Ssilby				warnx("oid '%s' is a read only tunable", bufp);
223121849Ssilby				errx(1, "Tunable values are set in /boot/loader.conf");
224121306Ssilby			} else {
225121306Ssilby				errx(1, "oid '%s' is read only", bufp);
226121849Ssilby			}
227121306Ssilby		}
228116383Srwatson
229116383Srwatson		if ((kind & CTLTYPE) == CTLTYPE_INT ||
230116383Srwatson		    (kind & CTLTYPE) == CTLTYPE_UINT ||
231116383Srwatson		    (kind & CTLTYPE) == CTLTYPE_LONG ||
232126472Sdd		    (kind & CTLTYPE) == CTLTYPE_ULONG ||
233217616Smdf		    (kind & CTLTYPE) == CTLTYPE_S64 ||
234217616Smdf		    (kind & CTLTYPE) == CTLTYPE_U64) {
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;
281217616Smdf			case CTLTYPE_S64:
282217616Smdf				i64val = strtoimax(newval, &endptr, 0);
283203917Suqs				if (endptr == newval || *endptr != '\0')
284217616Smdf					errx(1, "invalid int64_t '%s'",
285217616Smdf					    (char *)newval);
286217616Smdf				newval = &i64val;
287217616Smdf				newsize = sizeof(i64val);
28812946Sphk				break;
289217616Smdf			case CTLTYPE_U64:
290217616Smdf				u64val = strtoumax(newval, &endptr, 0);
291217616Smdf				if (endptr == newval || *endptr != '\0')
292217616Smdf					errx(1, "invalid uint64_t '%s'",
293217616Smdf					    (char *)newval);
294217616Smdf				newval = &u64val;
295217616Smdf				newsize = sizeof(u64val);
296217616Smdf				break;
29788696Sphk			case CTLTYPE_OPAQUE:
29888696Sphk				/* FALLTHROUGH */
29912946Sphk			default:
30012946Sphk				errx(1, "oid '%s' is type %d,"
30131214Sjdp					" cannot set that", bufp,
30231214Sjdp					kind & CTLTYPE);
3031553Srgrimes		}
3041553Srgrimes
30512946Sphk		i = show_var(mib, len);
30612946Sphk		if (sysctl(mib, len, 0, 0, newval, newsize) == -1) {
30712946Sphk			if (!i && !bflag)
30812946Sphk				putchar('\n');
30912946Sphk			switch (errno) {
31012946Sphk			case EOPNOTSUPP:
311122234Sdes				errx(1, "%s: value is not available",
31212946Sphk					string);
31312946Sphk			case ENOTDIR:
314122234Sdes				errx(1, "%s: specification is incomplete",
31512946Sphk					string);
31612946Sphk			case ENOMEM:
317122234Sdes				errx(1, "%s: type is unknown to this program",
31812946Sphk					string);
31912946Sphk			default:
32030602Scharnier				warn("%s", string);
321179965Smtm				warncount++;
32212946Sphk				return;
32312946Sphk			}
32412946Sphk		}
32512946Sphk		if (!bflag)
32612946Sphk			printf(" -> ");
32712946Sphk		i = nflag;
32812946Sphk		nflag = 1;
32912946Sphk		j = show_var(mib, len);
33012946Sphk		if (!j && !bflag)
33112946Sphk			putchar('\n');
33212946Sphk		nflag = i;
33312946Sphk	}
33412946Sphk}
3351553Srgrimes
33612946Sphk/* These functions will dump out various interesting structures. */
3371553Srgrimes
33812946Sphkstatic int
33912946SphkS_clockinfo(int l2, void *p)
34012946Sphk{
34112946Sphk	struct clockinfo *ci = (struct clockinfo*)p;
342170512Sdwmalone
34397232Salfred	if (l2 != sizeof(*ci)) {
344203917Suqs		warnx("S_clockinfo %d != %zu", l2, sizeof(*ci));
345170558Sbde		return (1);
34697232Salfred	}
347122233Sdes	printf(hflag ? "{ hz = %'d, tick = %'d, profhz = %'d, stathz = %'d }" :
348122233Sdes		"{ hz = %d, tick = %d, profhz = %d, stathz = %d }",
34994752Sphk		ci->hz, ci->tick, ci->profhz, ci->stathz);
35012946Sphk	return (0);
35112946Sphk}
3521553Srgrimes
35312946Sphkstatic int
35412946SphkS_loadavg(int l2, void *p)
35512946Sphk{
35612946Sphk	struct loadavg *tv = (struct loadavg*)p;
3578857Srgrimes
35897232Salfred	if (l2 != sizeof(*tv)) {
359203917Suqs		warnx("S_loadavg %d != %zu", l2, sizeof(*tv));
360170558Sbde		return (1);
36197232Salfred	}
362122233Sdes	printf(hflag ? "{ %'.2f %'.2f %'.2f }" : "{ %.2f %.2f %.2f }",
36312946Sphk		(double)tv->ldavg[0]/(double)tv->fscale,
36412946Sphk		(double)tv->ldavg[1]/(double)tv->fscale,
36512946Sphk		(double)tv->ldavg[2]/(double)tv->fscale);
36612946Sphk	return (0);
36712946Sphk}
3681553Srgrimes
36912946Sphkstatic int
37012946SphkS_timeval(int l2, void *p)
37112946Sphk{
37212946Sphk	struct timeval *tv = (struct timeval*)p;
37337266Sbde	time_t tv_sec;
37412946Sphk	char *p1, *p2;
3751553Srgrimes
37697232Salfred	if (l2 != sizeof(*tv)) {
377203917Suqs		warnx("S_timeval %d != %zu", l2, sizeof(*tv));
378170558Sbde		return (1);
37997232Salfred	}
380194684Sjhay	printf(hflag ? "{ sec = %'jd, usec = %'ld } " :
381194684Sjhay		"{ sec = %jd, usec = %ld } ",
382194684Sjhay		(intmax_t)tv->tv_sec, tv->tv_usec);
38337266Sbde	tv_sec = tv->tv_sec;
38437266Sbde	p1 = strdup(ctime(&tv_sec));
38512946Sphk	for (p2=p1; *p2 ; p2++)
38612946Sphk		if (*p2 == '\n')
38712946Sphk			*p2 = '\0';
38812946Sphk	fputs(p1, stdout);
389205118Sbrucec	free(p1);
39012946Sphk	return (0);
39112946Sphk}
3921553Srgrimes
39312946Sphkstatic int
394109097SdillonS_vmtotal(int l2, void *p)
395109097Sdillon{
396109097Sdillon	struct vmtotal *v = (struct vmtotal *)p;
397109113Sdillon	int pageKilo = getpagesize() / 1024;
398109097Sdillon
399109097Sdillon	if (l2 != sizeof(*v)) {
400203917Suqs		warnx("S_vmtotal %d != %zu", l2, sizeof(*v));
401170558Sbde		return (1);
402109097Sdillon	}
403109097Sdillon
404109113Sdillon	printf(
405109113Sdillon	    "\nSystem wide totals computed every five seconds:"
406109113Sdillon	    " (values in kilobytes)\n");
407109097Sdillon	printf("===============================================\n");
408109113Sdillon	printf(
409164718Sru	    "Processes:\t\t(RUNQ: %hd Disk Wait: %hd Page Wait: "
410164718Sru	    "%hd Sleep: %hd)\n",
411109113Sdillon	    v->t_rq, v->t_dw, v->t_pw, v->t_sl);
412109113Sdillon	printf(
413212726Szec	    "Virtual Memory:\t\t(Total: %dK Active: %dK)\n",
414164718Sru	    v->t_vm * pageKilo, v->t_avm * pageKilo);
415212726Szec	printf("Real Memory:\t\t(Total: %dK Active: %dK)\n",
416164718Sru	    v->t_rm * pageKilo, v->t_arm * pageKilo);
417164718Sru	printf("Shared Virtual Memory:\t(Total: %dK Active: %dK)\n",
418164718Sru	    v->t_vmshr * pageKilo, v->t_avmshr * pageKilo);
419164718Sru	printf("Shared Real Memory:\t(Total: %dK Active: %dK)\n",
420164718Sru	    v->t_rmshr * pageKilo, v->t_armshr * pageKilo);
421234260Seadler	printf("Free Memory:\t%dK\n", v->t_free * pageKilo);
422122234Sdes
423109097Sdillon	return (0);
424109097Sdillon}
425109097Sdillon
426109097Sdillonstatic int
427198340Sedset_IK(const char *str, int *val)
428161951Sume{
429161951Sume	float temp;
430161951Sume	int len, kelv;
431198340Sed	const char *p;
432198340Sed	char *endptr;
433161951Sume
434161951Sume	if ((len = strlen(str)) == 0)
435161951Sume		return (0);
436161951Sume	p = &str[len - 1];
437161951Sume	if (*p == 'C' || *p == 'F') {
438161951Sume		temp = strtof(str, &endptr);
439198340Sed		if (endptr == str || endptr != p)
440161951Sume			return (0);
441161951Sume		if (*p == 'F')
442161951Sume			temp = (temp - 32) * 5 / 9;
443161951Sume		kelv = temp * 10 + 2732;
444161951Sume	} else {
445161951Sume		kelv = (int)strtol(str, &endptr, 10);
446161951Sume		if (endptr == str || *endptr != '\0')
447161951Sume			return (0);
448161951Sume	}
449161951Sume	*val = kelv;
450161951Sume	return (1);
451161951Sume}
452161951Sume
45312946Sphk/*
45412946Sphk * These functions uses a presently undocumented interface to the kernel
45512946Sphk * to walk the tree and get the type so it can print the value.
45612946Sphk * This interface is under work and consideration, and should probably
45712946Sphk * be killed with a big axe by the first person who can find the time.
45812946Sphk * (be aware though, that the proper interface isn't as obvious as it
45912946Sphk * may seem, there are various conflicting requirements.
46012946Sphk */
4611553Srgrimes
46212946Sphkstatic int
46312946Sphkname2oid(char *name, int *oidp)
46412946Sphk{
46512946Sphk	int oid[2];
46638533Sdfr	int i;
46738533Sdfr	size_t j;
4681553Srgrimes
46912946Sphk	oid[0] = 0;
47012946Sphk	oid[1] = 3;
4711553Srgrimes
47277928Sdd	j = CTL_MAXNAME * sizeof(int);
47312946Sphk	i = sysctl(oid, 2, oidp, &j, name, strlen(name));
474122234Sdes	if (i < 0)
475170512Sdwmalone		return (i);
47677928Sdd	j /= sizeof(int);
47712946Sphk	return (j);
4781553Srgrimes}
4791553Srgrimes
48012946Sphkstatic int
48112946Sphkoidfmt(int *oid, int len, char *fmt, u_int *kind)
48212946Sphk{
48312946Sphk	int qoid[CTL_MAXNAME+2];
48412946Sphk	u_char buf[BUFSIZ];
48538533Sdfr	int i;
48638533Sdfr	size_t j;
4871553Srgrimes
48812946Sphk	qoid[0] = 0;
48912946Sphk	qoid[1] = 4;
49012946Sphk	memcpy(qoid + 2, oid, len * sizeof(int));
4911553Srgrimes
49277928Sdd	j = sizeof(buf);
49312946Sphk	i = sysctl(qoid, len + 2, buf, &j, 0, 0);
49412946Sphk	if (i)
495203917Suqs		err(1, "sysctl fmt %d %zu %d", i, j, errno);
4961553Srgrimes
49712946Sphk	if (kind)
49812946Sphk		*kind = *(u_int *)buf;
49912946Sphk
50012946Sphk	if (fmt)
50112946Sphk		strcpy(fmt, (char *)(buf + sizeof(u_int)));
502170512Sdwmalone	return (0);
5031553Srgrimes}
5041553Srgrimes
505217616Smdfstatic int ctl_sign[CTLTYPE+1] = {
506217616Smdf	[CTLTYPE_INT] = 1,
507217616Smdf	[CTLTYPE_LONG] = 1,
508217616Smdf	[CTLTYPE_S64] = 1,
509217616Smdf};
510217616Smdf
511217616Smdfstatic int ctl_size[CTLTYPE+1] = {
512217616Smdf	[CTLTYPE_INT] = sizeof(int),
513217616Smdf	[CTLTYPE_UINT] = sizeof(u_int),
514217616Smdf	[CTLTYPE_LONG] = sizeof(long),
515217616Smdf	[CTLTYPE_ULONG] = sizeof(u_long),
516217616Smdf	[CTLTYPE_S64] = sizeof(int64_t),
517217616Smdf	[CTLTYPE_U64] = sizeof(int64_t),
518217616Smdf};
519217616Smdf
5201553Srgrimes/*
52112946Sphk * This formats and outputs the value of one variable
52212946Sphk *
52312946Sphk * Returns zero if anything was actually output.
52412946Sphk * Returns one if didn't know what to do with this.
52512946Sphk * Return minus one if we had errors.
5261553Srgrimes */
52712946Sphkstatic int
52812946Sphkshow_var(int *oid, int nlen)
5291553Srgrimes{
530162073Sru	u_char buf[BUFSIZ], *val, *oval, *p;
531170513Sdwmalone	char name[BUFSIZ], *fmt;
532170513Sdwmalone	const char *sep, *sep1;
53312946Sphk	int qoid[CTL_MAXNAME+2];
534170512Sdwmalone	uintmax_t umv;
535170512Sdwmalone	intmax_t mv;
536217586Smdf	int i, hexlen, sign, ctltype;
537170287Sdwmalone	size_t intlen;
53838533Sdfr	size_t j, len;
53912946Sphk	u_int kind;
54077332Sdes	int (*func)(int, void *);
5411553Srgrimes
542203917Suqs	/* Silence GCC. */
543203917Suqs	umv = mv = intlen = 0;
544203917Suqs
545144997Smdodd	bzero(buf, BUFSIZ);
546144997Smdodd	bzero(name, BUFSIZ);
54742456Sdes	qoid[0] = 0;
54842456Sdes	memcpy(qoid + 2, oid, nlen * sizeof(int));
54942456Sdes
55042456Sdes	qoid[1] = 1;
55177928Sdd	j = sizeof(name);
55242456Sdes	i = sysctl(qoid, nlen + 2, name, &j, 0, 0);
55342456Sdes	if (i || !j)
554203917Suqs		err(1, "sysctl name %d %zu %d", i, j, errno);
55542456Sdes
55671034Sdes	if (Nflag) {
55771034Sdes		printf("%s", name);
55871034Sdes		return (0);
55971034Sdes	}
56071034Sdes
56185747Stobez	if (eflag)
56285747Stobez		sep = "=";
56385747Stobez	else
56485747Stobez		sep = ": ";
56585747Stobez
56688006Sluigi	if (dflag) {	/* just print description */
56788006Sluigi		qoid[1] = 5;
56888006Sluigi		j = sizeof(buf);
56988006Sluigi		i = sysctl(qoid, nlen + 2, buf, &j, 0, 0);
57088006Sluigi		if (!nflag)
57188006Sluigi			printf("%s%s", name, sep);
57288006Sluigi		printf("%s", buf);
57388006Sluigi		return (0);
57488006Sluigi	}
57512946Sphk	/* find an estimate of how much we need for this var */
57612946Sphk	j = 0;
57712946Sphk	i = sysctl(oid, nlen, 0, &j, 0, 0);
57812946Sphk	j += j; /* we want to be sure :-) */
57912946Sphk
580162073Sru	val = oval = malloc(j + 1);
581162073Sru	if (val == NULL) {
582162073Sru		warnx("malloc failed");
583170558Sbde		return (1);
584162073Sru	}
58512946Sphk	len = j;
58612946Sphk	i = sysctl(oid, nlen, val, &len, 0, 0);
587162073Sru	if (i || !len) {
588162073Sru		free(oval);
58912946Sphk		return (1);
590162073Sru	}
59112946Sphk
59212946Sphk	if (bflag) {
59312946Sphk		fwrite(val, 1, len, stdout);
594162073Sru		free(oval);
59512946Sphk		return (0);
5961553Srgrimes	}
59796234Sache	val[len] = '\0';
59888696Sphk	fmt = buf;
59988696Sphk	oidfmt(oid, nlen, fmt, &kind);
60012946Sphk	p = val;
601217586Smdf	ctltype = (kind & CTLTYPE);
602217616Smdf	sign = ctl_sign[ctltype];
603217616Smdf	intlen = ctl_size[ctltype];
604217616Smdf
605217586Smdf	switch (ctltype) {
606217586Smdf	case CTLTYPE_STRING:
60712946Sphk		if (!nflag)
60885747Stobez			printf("%s%s", name, sep);
609203917Suqs		printf("%.*s", (int)len, p);
610162073Sru		free(oval);
61112946Sphk		return (0);
612122234Sdes
613217586Smdf	case CTLTYPE_INT:
614217586Smdf	case CTLTYPE_UINT:
615217586Smdf	case CTLTYPE_LONG:
616217586Smdf	case CTLTYPE_ULONG:
617217616Smdf	case CTLTYPE_S64:
618217616Smdf	case CTLTYPE_U64:
61912946Sphk		if (!nflag)
62085747Stobez			printf("%s%s", name, sep);
621170514Sdwmalone		hexlen = 2 + (intlen * CHAR_BIT + 3) / 4;
622170513Sdwmalone		sep1 = "";
623170287Sdwmalone		while (len >= intlen) {
624217586Smdf			switch (kind & CTLTYPE) {
625217586Smdf			case CTLTYPE_INT:
626217586Smdf			case CTLTYPE_UINT:
627170514Sdwmalone				umv = *(u_int *)p;
628170514Sdwmalone				mv = *(int *)p;
629170287Sdwmalone				break;
630217586Smdf			case CTLTYPE_LONG:
631217586Smdf			case CTLTYPE_ULONG:
632170514Sdwmalone				umv = *(u_long *)p;
633170514Sdwmalone				mv = *(long *)p;
634170287Sdwmalone				break;
635217616Smdf			case CTLTYPE_S64:
636217616Smdf			case CTLTYPE_U64:
637217616Smdf				umv = *(uint64_t *)p;
638217616Smdf				mv = *(int64_t *)p;
639170287Sdwmalone				break;
640170287Sdwmalone			}
641170513Sdwmalone			fputs(sep1, stdout);
642217586Smdf			if (xflag)
643217586Smdf				printf("%#0*jx", hexlen, umv);
644217586Smdf			else if (!sign)
645170512Sdwmalone				printf(hflag ? "%'ju" : "%ju", umv);
646170287Sdwmalone			else if (fmt[1] == 'K') {
647170514Sdwmalone				if (mv < 0)
648170512Sdwmalone					printf("%jd", mv);
649134541Speter				else
650170512Sdwmalone					printf("%.1fC", (mv - 2732.0) / 10);
651134541Speter			} else
652170513Sdwmalone				printf(hflag ? "%'jd" : "%jd", mv);
653170513Sdwmalone			sep1 = " ";
654170287Sdwmalone			len -= intlen;
655170287Sdwmalone			p += intlen;
65641019Sphk		}
657162073Sru		free(oval);
65812946Sphk		return (0);
65912946Sphk
660217586Smdf	case CTLTYPE_OPAQUE:
66112946Sphk		i = 0;
66277332Sdes		if (strcmp(fmt, "S,clockinfo") == 0)
66377332Sdes			func = S_clockinfo;
66477332Sdes		else if (strcmp(fmt, "S,timeval") == 0)
66577332Sdes			func = S_timeval;
66677332Sdes		else if (strcmp(fmt, "S,loadavg") == 0)
66777332Sdes			func = S_loadavg;
668109097Sdillon		else if (strcmp(fmt, "S,vmtotal") == 0)
669109097Sdillon			func = S_vmtotal;
67077332Sdes		else
67177332Sdes			func = NULL;
67212946Sphk		if (func) {
67312946Sphk			if (!nflag)
67485747Stobez				printf("%s%s", name, sep);
675163275Sharti			i = (*func)(len, p);
676162073Sru			free(oval);
677163275Sharti			return (i);
67812946Sphk		}
679102411Scharnier		/* FALLTHROUGH */
68012946Sphk	default:
681162073Sru		if (!oflag && !xflag) {
682162073Sru			free(oval);
68312946Sphk			return (1);
684162073Sru		}
68512946Sphk		if (!nflag)
68685747Stobez			printf("%s%s", name, sep);
687203917Suqs		printf("Format:%s Length:%zu Dump:0x", fmt, len);
68877332Sdes		while (len-- && (xflag || p < val + 16))
68912946Sphk			printf("%02x", *p++);
69077332Sdes		if (!xflag && len > 16)
69112946Sphk			printf("...");
692162073Sru		free(oval);
69312946Sphk		return (0);
6941553Srgrimes	}
695162073Sru	free(oval);
69612946Sphk	return (1);
6971553Srgrimes}
6981553Srgrimes
69912946Sphkstatic int
700170512Sdwmalonesysctl_all(int *oid, int len)
7011553Srgrimes{
70212946Sphk	int name1[22], name2[22];
70338533Sdfr	int i, j;
70438533Sdfr	size_t l1, l2;
7051553Srgrimes
70612946Sphk	name1[0] = 0;
70712946Sphk	name1[1] = 2;
70812946Sphk	l1 = 2;
70912946Sphk	if (len) {
71077928Sdd		memcpy(name1+2, oid, len * sizeof(int));
71112946Sphk		l1 += len;
71212946Sphk	} else {
71312946Sphk		name1[2] = 1;
71412946Sphk		l1++;
71512946Sphk	}
71677332Sdes	for (;;) {
71777928Sdd		l2 = sizeof(name2);
71812946Sphk		j = sysctl(name1, l1, name2, &l2, 0, 0);
71948956Sbillf		if (j < 0) {
72012946Sphk			if (errno == ENOENT)
721170512Sdwmalone				return (0);
72212946Sphk			else
723203917Suqs				err(1, "sysctl(getnext) %d %zu", j, l2);
72448956Sbillf		}
72512946Sphk
72677928Sdd		l2 /= sizeof(int);
72712946Sphk
728170513Sdwmalone		if (len < 0 || l2 < (unsigned int)len)
729170512Sdwmalone			return (0);
73012946Sphk
73112946Sphk		for (i = 0; i < len; i++)
73212946Sphk			if (name2[i] != oid[i])
733170512Sdwmalone				return (0);
73412946Sphk
73512946Sphk		i = show_var(name2, l2);
73612946Sphk		if (!i && !bflag)
73712946Sphk			putchar('\n');
73812946Sphk
73977928Sdd		memcpy(name1+2, name2, l2 * sizeof(int));
74012946Sphk		l1 = 2 + l2;
74112946Sphk	}
7421553Srgrimes}
743