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: releng/10.3/sbin/sysctl/sysctl.c 289292 2015-10-14 06:31:49Z bapt $";
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
51272913Sjhb#ifdef __amd64__
52272913Sjhb#include <sys/efi.h>
53272913Sjhb#include <machine/metadata.h>
54272913Sjhb#endif
55272913Sjhb
56272913Sjhb#if defined(__amd64__) || defined(__i386__)
57272913Sjhb#include <machine/pc/bios.h>
58272913Sjhb#endif
59272913Sjhb
6030602Scharnier#include <ctype.h>
6130602Scharnier#include <err.h>
621553Srgrimes#include <errno.h>
63170287Sdwmalone#include <inttypes.h>
64122233Sdes#include <locale.h>
651553Srgrimes#include <stdio.h>
661553Srgrimes#include <stdlib.h>
671553Srgrimes#include <string.h>
68244198Sdelphij#include <sysexits.h>
6930602Scharnier#include <unistd.h>
701553Srgrimes
71244198Sdelphijstatic const char *conffile;
72244198Sdelphij
73203310Sgavinstatic int	aflag, bflag, dflag, eflag, hflag, iflag;
74244198Sdelphijstatic int	Nflag, nflag, oflag, qflag, Tflag, Wflag, xflag;
751553Srgrimes
7612946Sphkstatic int	oidfmt(int *, int, char *, u_int *);
77244198Sdelphijstatic int	parsefile(const char *);
78244198Sdelphijstatic int	parse(const char *, int);
7912946Sphkstatic int	show_var(int *, int);
80170512Sdwmalonestatic int	sysctl_all(int *oid, int len);
81275485Sdelphijstatic int	name2oid(const char *, int *);
821553Srgrimes
83198340Sedstatic int	set_IK(const char *, int *);
8488696Sphk
8512946Sphkstatic void
8612946Sphkusage(void)
8712946Sphk{
881553Srgrimes
8977330Sdes	(void)fprintf(stderr, "%s\n%s\n",
90244198Sdelphij	    "usage: sysctl [-bdehiNnoqTWx] [-f filename] name[=value] ...",
91244106Salfred	    "       sysctl [-bdehNnoqTWx] -a");
9212946Sphk	exit(1);
9312946Sphk}
941553Srgrimes
951553Srgrimesint
9612946Sphkmain(int argc, char **argv)
971553Srgrimes{
9812946Sphk	int ch;
99244198Sdelphij	int warncount = 0;
100122233Sdes
101122233Sdes	setlocale(LC_NUMERIC, "");
10212946Sphk	setbuf(stdout,0);
10312946Sphk	setbuf(stderr,0);
1041553Srgrimes
105244198Sdelphij	while ((ch = getopt(argc, argv, "Aabdef:hiNnoqTwWxX")) != -1) {
1061553Srgrimes		switch (ch) {
10771034Sdes		case 'A':
10877330Sdes			/* compatibility */
10977330Sdes			aflag = oflag = 1;
11071034Sdes			break;
11171034Sdes		case 'a':
11271034Sdes			aflag = 1;
11371034Sdes			break;
11471034Sdes		case 'b':
11571034Sdes			bflag = 1;
11671034Sdes			break;
11788006Sluigi		case 'd':
11888006Sluigi			dflag = 1;
11988006Sluigi			break;
12085747Stobez		case 'e':
12185747Stobez			eflag = 1;
12285747Stobez			break;
123244198Sdelphij		case 'f':
124244198Sdelphij			conffile = optarg;
125244198Sdelphij			break;
126122233Sdes		case 'h':
127122233Sdes			hflag = 1;
128122233Sdes			break;
129203310Sgavin		case 'i':
130203310Sgavin			iflag = 1;
131203310Sgavin			break;
13271034Sdes		case 'N':
13371034Sdes			Nflag = 1;
13471034Sdes			break;
13571034Sdes		case 'n':
13671034Sdes			nflag = 1;
13771034Sdes			break;
13877330Sdes		case 'o':
13977330Sdes			oflag = 1;
14077330Sdes			break;
141150167Srwatson		case 'q':
142150167Srwatson			qflag = 1;
143150167Srwatson			break;
144244106Salfred		case 'T':
145244106Salfred			Tflag = 1;
146244106Salfred			break;
14771034Sdes		case 'w':
14877330Sdes			/* compatibility */
14977330Sdes			/* ignored */
15071034Sdes			break;
151244106Salfred		case 'W':
152244106Salfred			Wflag = 1;
153244106Salfred			break;
15471034Sdes		case 'X':
15577330Sdes			/* compatibility */
15677330Sdes			aflag = xflag = 1;
15771034Sdes			break;
15877330Sdes		case 'x':
15977330Sdes			xflag = 1;
16077330Sdes			break;
16171034Sdes		default:
16271034Sdes			usage();
1631553Srgrimes		}
1641553Srgrimes	}
1651553Srgrimes	argc -= optind;
1661553Srgrimes	argv += optind;
1671553Srgrimes
16877330Sdes	if (Nflag && nflag)
16942456Sdes		usage();
17077330Sdes	if (aflag && argc == 0)
17177330Sdes		exit(sysctl_all(0, 0));
172244198Sdelphij	if (argc == 0 && conffile == NULL)
1731553Srgrimes		usage();
174179965Smtm
175179965Smtm	warncount = 0;
176244198Sdelphij	if (conffile != NULL)
177244198Sdelphij		warncount += parsefile(conffile);
178244198Sdelphij
1791553Srgrimes	while (argc-- > 0)
180244198Sdelphij		warncount += parse(*argv++, 0);
181244198Sdelphij
182244198Sdelphij	return (warncount);
1831553Srgrimes}
1841553Srgrimes
1851553Srgrimes/*
1861553Srgrimes * Parse a name into a MIB entry.
1871553Srgrimes * Lookup and print out the MIB entry if it exists.
1881553Srgrimes * Set a new value if requested.
1891553Srgrimes */
190244198Sdelphijstatic int
191244198Sdelphijparse(const char *string, int lineno)
1921553Srgrimes{
19312946Sphk	int len, i, j;
1941553Srgrimes	void *newval = 0;
19578434Spirzyk	int intval;
19678434Spirzyk	unsigned int uintval;
19778434Spirzyk	long longval;
19878434Spirzyk	unsigned long ulongval;
19978434Spirzyk	size_t newsize = 0;
200217616Smdf	int64_t i64val;
201217616Smdf	uint64_t u64val;
2021553Srgrimes	int mib[CTL_MAXNAME];
203244198Sdelphij	char *cp, *bufp, buf[BUFSIZ], *endptr, fmt[BUFSIZ], line[BUFSIZ];
20412946Sphk	u_int kind;
2051553Srgrimes
206244198Sdelphij	if (lineno)
207244198Sdelphij		snprintf(line, sizeof(line), " at line %d", lineno);
208244198Sdelphij	else
209244198Sdelphij		line[0] = '\0';
210244198Sdelphij
211244104Sdelphij	cp = buf;
212244198Sdelphij	if (snprintf(buf, BUFSIZ, "%s", string) >= BUFSIZ) {
213260193Strasz		warnx("oid too long: '%s'%s", string, line);
214244198Sdelphij		return (1);
215244198Sdelphij	}
216244198Sdelphij	bufp = strsep(&cp, "=:");
217244104Sdelphij	if (cp != NULL) {
218244106Salfred		/* Tflag just lists tunables, do not allow assignment */
219244106Salfred		if (Tflag || Wflag) {
220244106Salfred			warnx("Can't set variables when using -T or -W");
221244106Salfred			usage();
222244106Salfred		}
2231553Srgrimes		while (isspace(*cp))
2241553Srgrimes			cp++;
225244198Sdelphij		/* Strip a pair of " or ' if any. */
226244198Sdelphij		switch (*cp) {
227244198Sdelphij		case '\"':
228244198Sdelphij		case '\'':
229244198Sdelphij			if (cp[strlen(cp) - 1] == *cp)
230244198Sdelphij				cp[strlen(cp) - 1] = '\0';
231244198Sdelphij			cp++;
232244198Sdelphij		}
2331553Srgrimes		newval = cp;
2341553Srgrimes		newsize = strlen(cp);
2351553Srgrimes	}
236289291Sbapt	/* Trim spaces */
237289291Sbapt	cp = bufp + strlen(bufp) - 1;
238289291Sbapt	while (cp >= bufp && isspace((int)*cp)) {
239289291Sbapt		*cp = '\0';
240289291Sbapt		cp--;
241289291Sbapt	}
24212946Sphk	len = name2oid(bufp, mib);
2431553Srgrimes
244150167Srwatson	if (len < 0) {
245203310Sgavin		if (iflag)
246244198Sdelphij			return (0);
247150167Srwatson		if (qflag)
248244198Sdelphij			return (1);
249244198Sdelphij		else {
250289292Sbapt			if (errno == ENOENT) {
251289292Sbapt				warnx("unknown oid '%s'%s", bufp, line);
252289292Sbapt			} else {
253289292Sbapt				warn("unknown oid '%s'%s", bufp, line);
254289292Sbapt			}
255244198Sdelphij			return (1);
256244198Sdelphij		}
257244198Sdelphij	}
258244198Sdelphij
259244198Sdelphij	if (oidfmt(mib, len, fmt, &kind)) {
260244198Sdelphij		warn("couldn't find format of oid '%s'%s", bufp, line);
261244198Sdelphij		if (iflag)
262244198Sdelphij			return (1);
263244198Sdelphij		else
264150167Srwatson			exit(1);
265150167Srwatson	}
2661553Srgrimes
267228181Sjhb	if (newval == NULL || dflag) {
26812946Sphk		if ((kind & CTLTYPE) == CTLTYPE_NODE) {
269144998Smdodd			if (dflag) {
270144998Smdodd				i = show_var(mib, len);
271144998Smdodd				if (!i && !bflag)
272144998Smdodd					putchar('\n');
273144998Smdodd			}
27412946Sphk			sysctl_all(mib, len);
27512946Sphk		} else {
27612946Sphk			i = show_var(mib, len);
27712946Sphk			if (!i && !bflag)
27812946Sphk				putchar('\n');
2791553Srgrimes		}
28012946Sphk	} else {
281244198Sdelphij		if ((kind & CTLTYPE) == CTLTYPE_NODE) {
282260193Strasz			warnx("oid '%s' isn't a leaf node%s", bufp, line);
283244198Sdelphij			return (1);
284244198Sdelphij		}
2851553Srgrimes
286121849Ssilby		if (!(kind & CTLFLAG_WR)) {
287121306Ssilby			if (kind & CTLFLAG_TUN) {
288245361Sdelphij				warnx("oid '%s' is a read only tunable%s", bufp, line);
289244198Sdelphij				warnx("Tunable values are set in /boot/loader.conf");
290244198Sdelphij			} else
291244198Sdelphij				warnx("oid '%s' is read only%s", bufp, line);
292244198Sdelphij			return (1);
293121306Ssilby		}
294116383Srwatson
295116383Srwatson		if ((kind & CTLTYPE) == CTLTYPE_INT ||
296116383Srwatson		    (kind & CTLTYPE) == CTLTYPE_UINT ||
297116383Srwatson		    (kind & CTLTYPE) == CTLTYPE_LONG ||
298126472Sdd		    (kind & CTLTYPE) == CTLTYPE_ULONG ||
299217616Smdf		    (kind & CTLTYPE) == CTLTYPE_S64 ||
300217616Smdf		    (kind & CTLTYPE) == CTLTYPE_U64) {
301244198Sdelphij			if (strlen(newval) == 0) {
302244198Sdelphij				warnx("empty numeric value");
303244198Sdelphij				return (1);
304244198Sdelphij			}
305116383Srwatson		}
306122234Sdes
30712946Sphk		switch (kind & CTLTYPE) {
30812946Sphk			case CTLTYPE_INT:
309161951Sume				if (strcmp(fmt, "IK") == 0) {
310244198Sdelphij					if (!set_IK(newval, &intval)) {
311244198Sdelphij						warnx("invalid value '%s'%s",
312244198Sdelphij						    (char *)newval, line);
313244198Sdelphij						return (1);
314244198Sdelphij					}
315161951Sume 				} else {
316161951Sume					intval = (int)strtol(newval, &endptr,
317161951Sume					    0);
318244198Sdelphij					if (endptr == newval || *endptr != '\0') {
319244198Sdelphij						warnx("invalid integer '%s'%s",
320244198Sdelphij						    (char *)newval, line);
321244198Sdelphij						return (1);
322244198Sdelphij					}
323161951Sume				}
32412946Sphk				newval = &intval;
32577928Sdd				newsize = sizeof(intval);
3261553Srgrimes				break;
32778434Spirzyk			case CTLTYPE_UINT:
328116383Srwatson				uintval = (int) strtoul(newval, &endptr, 0);
329244198Sdelphij				if (endptr == newval || *endptr != '\0') {
330244198Sdelphij					warnx("invalid unsigned integer '%s'%s",
331244198Sdelphij					    (char *)newval, line);
332244198Sdelphij					return (1);
333244198Sdelphij				}
33478434Spirzyk				newval = &uintval;
335170512Sdwmalone				newsize = sizeof(uintval);
33612946Sphk				break;
33778434Spirzyk			case CTLTYPE_LONG:
338116383Srwatson				longval = strtol(newval, &endptr, 0);
339244198Sdelphij				if (endptr == newval || *endptr != '\0') {
340244198Sdelphij					warnx("invalid long integer '%s'%s",
341244198Sdelphij					    (char *)newval, line);
342244198Sdelphij					return (1);
343244198Sdelphij				}
34478434Spirzyk				newval = &longval;
345170512Sdwmalone				newsize = sizeof(longval);
34678434Spirzyk				break;
34778434Spirzyk			case CTLTYPE_ULONG:
348116383Srwatson				ulongval = strtoul(newval, &endptr, 0);
349244198Sdelphij				if (endptr == newval || *endptr != '\0') {
350244198Sdelphij					warnx("invalid unsigned long integer"
351244198Sdelphij					    " '%s'%s", (char *)newval, line);
352244198Sdelphij					return (1);
353244198Sdelphij				}
35478434Spirzyk				newval = &ulongval;
355170512Sdwmalone				newsize = sizeof(ulongval);
35678434Spirzyk				break;
35712946Sphk			case CTLTYPE_STRING:
35812946Sphk				break;
359217616Smdf			case CTLTYPE_S64:
360217616Smdf				i64val = strtoimax(newval, &endptr, 0);
361244198Sdelphij				if (endptr == newval || *endptr != '\0') {
362244198Sdelphij					warnx("invalid int64_t '%s'%s",
363244198Sdelphij					    (char *)newval, line);
364244198Sdelphij					return (1);
365244198Sdelphij				}
366217616Smdf				newval = &i64val;
367217616Smdf				newsize = sizeof(i64val);
36812946Sphk				break;
369217616Smdf			case CTLTYPE_U64:
370217616Smdf				u64val = strtoumax(newval, &endptr, 0);
371244198Sdelphij				if (endptr == newval || *endptr != '\0') {
372244198Sdelphij					warnx("invalid uint64_t '%s'%s",
373244198Sdelphij					    (char *)newval, line);
374244198Sdelphij					return (1);
375244198Sdelphij				}
376217616Smdf				newval = &u64val;
377217616Smdf				newsize = sizeof(u64val);
378217616Smdf				break;
37988696Sphk			case CTLTYPE_OPAQUE:
38088696Sphk				/* FALLTHROUGH */
38112946Sphk			default:
382244198Sdelphij				warnx("oid '%s' is type %d,"
383244198Sdelphij					" cannot set that%s", bufp,
384244198Sdelphij					kind & CTLTYPE, line);
385244198Sdelphij				return (1);
3861553Srgrimes		}
3871553Srgrimes
38812946Sphk		i = show_var(mib, len);
38912946Sphk		if (sysctl(mib, len, 0, 0, newval, newsize) == -1) {
39012946Sphk			if (!i && !bflag)
39112946Sphk				putchar('\n');
39212946Sphk			switch (errno) {
39312946Sphk			case EOPNOTSUPP:
394244198Sdelphij				warnx("%s: value is not available%s",
395244198Sdelphij					string, line);
396244198Sdelphij				return (1);
39712946Sphk			case ENOTDIR:
398244198Sdelphij				warnx("%s: specification is incomplete%s",
399244198Sdelphij					string, line);
400244198Sdelphij				return (1);
40112946Sphk			case ENOMEM:
402244198Sdelphij				warnx("%s: type is unknown to this program%s",
403244198Sdelphij					string, line);
404244198Sdelphij				return (1);
40512946Sphk			default:
406244198Sdelphij				warn("%s%s", string, line);
407244198Sdelphij				return (1);
40812946Sphk			}
40912946Sphk		}
41012946Sphk		if (!bflag)
41112946Sphk			printf(" -> ");
41212946Sphk		i = nflag;
41312946Sphk		nflag = 1;
41412946Sphk		j = show_var(mib, len);
41512946Sphk		if (!j && !bflag)
41612946Sphk			putchar('\n');
41712946Sphk		nflag = i;
41812946Sphk	}
419244198Sdelphij
420244198Sdelphij	return (0);
42112946Sphk}
4221553Srgrimes
423244198Sdelphijstatic int
424244198Sdelphijparsefile(const char *filename)
425244198Sdelphij{
426244198Sdelphij	FILE *file;
427244198Sdelphij	char line[BUFSIZ], *p, *pq, *pdq;
428244198Sdelphij	int warncount = 0, lineno = 0;
429244198Sdelphij
430244198Sdelphij	file = fopen(filename, "r");
431244198Sdelphij	if (file == NULL)
432244198Sdelphij		err(EX_NOINPUT, "%s", filename);
433244198Sdelphij	while (fgets(line, sizeof(line), file) != NULL) {
434244198Sdelphij		lineno++;
435244198Sdelphij		p = line;
436244198Sdelphij		pq = strchr(line, '\'');
437244198Sdelphij		pdq = strchr(line, '\"');
438244198Sdelphij		/* Replace the first # with \0. */
439244198Sdelphij		while((p = strchr(p, '#')) != NULL) {
440244198Sdelphij			if (pq != NULL && p > pq) {
441244198Sdelphij				if ((p = strchr(pq+1, '\'')) != NULL)
442244198Sdelphij					*(++p) = '\0';
443244198Sdelphij				break;
444244198Sdelphij			} else if (pdq != NULL && p > pdq) {
445244198Sdelphij				if ((p = strchr(pdq+1, '\"')) != NULL)
446244198Sdelphij					*(++p) = '\0';
447244198Sdelphij				break;
448244198Sdelphij			} else if (p == line || *(p-1) != '\\') {
449244198Sdelphij				*p = '\0';
450244198Sdelphij				break;
451244198Sdelphij			}
452244198Sdelphij			p++;
453244198Sdelphij		}
454244198Sdelphij		/* Trim spaces */
455244198Sdelphij		p = line + strlen(line) - 1;
456244198Sdelphij		while (p >= line && isspace((int)*p)) {
457244198Sdelphij			*p = '\0';
458244198Sdelphij			p--;
459244198Sdelphij		}
460244198Sdelphij		p = line;
461244198Sdelphij		while (isspace((int)*p))
462244198Sdelphij			p++;
463244198Sdelphij		if (*p == '\0')
464244198Sdelphij			continue;
465244198Sdelphij		else
466244198Sdelphij			warncount += parse(p, lineno);
467244198Sdelphij	}
468244198Sdelphij	fclose(file);
469244198Sdelphij
470244198Sdelphij	return (warncount);
471244198Sdelphij}
472244198Sdelphij
47312946Sphk/* These functions will dump out various interesting structures. */
4741553Srgrimes
47512946Sphkstatic int
476272913SjhbS_clockinfo(size_t l2, void *p)
47712946Sphk{
47812946Sphk	struct clockinfo *ci = (struct clockinfo*)p;
479170512Sdwmalone
48097232Salfred	if (l2 != sizeof(*ci)) {
481272913Sjhb		warnx("S_clockinfo %zu != %zu", l2, sizeof(*ci));
482170558Sbde		return (1);
48397232Salfred	}
484122233Sdes	printf(hflag ? "{ hz = %'d, tick = %'d, profhz = %'d, stathz = %'d }" :
485122233Sdes		"{ hz = %d, tick = %d, profhz = %d, stathz = %d }",
48694752Sphk		ci->hz, ci->tick, ci->profhz, ci->stathz);
48712946Sphk	return (0);
48812946Sphk}
4891553Srgrimes
49012946Sphkstatic int
491272913SjhbS_loadavg(size_t l2, void *p)
49212946Sphk{
49312946Sphk	struct loadavg *tv = (struct loadavg*)p;
4948857Srgrimes
49597232Salfred	if (l2 != sizeof(*tv)) {
496272913Sjhb		warnx("S_loadavg %zu != %zu", l2, sizeof(*tv));
497170558Sbde		return (1);
49897232Salfred	}
499122233Sdes	printf(hflag ? "{ %'.2f %'.2f %'.2f }" : "{ %.2f %.2f %.2f }",
50012946Sphk		(double)tv->ldavg[0]/(double)tv->fscale,
50112946Sphk		(double)tv->ldavg[1]/(double)tv->fscale,
50212946Sphk		(double)tv->ldavg[2]/(double)tv->fscale);
50312946Sphk	return (0);
50412946Sphk}
5051553Srgrimes
50612946Sphkstatic int
507272913SjhbS_timeval(size_t l2, void *p)
50812946Sphk{
50912946Sphk	struct timeval *tv = (struct timeval*)p;
51037266Sbde	time_t tv_sec;
51112946Sphk	char *p1, *p2;
5121553Srgrimes
51397232Salfred	if (l2 != sizeof(*tv)) {
514272913Sjhb		warnx("S_timeval %zu != %zu", l2, sizeof(*tv));
515170558Sbde		return (1);
51697232Salfred	}
517194684Sjhay	printf(hflag ? "{ sec = %'jd, usec = %'ld } " :
518194684Sjhay		"{ sec = %jd, usec = %ld } ",
519194684Sjhay		(intmax_t)tv->tv_sec, tv->tv_usec);
52037266Sbde	tv_sec = tv->tv_sec;
52137266Sbde	p1 = strdup(ctime(&tv_sec));
52212946Sphk	for (p2=p1; *p2 ; p2++)
52312946Sphk		if (*p2 == '\n')
52412946Sphk			*p2 = '\0';
52512946Sphk	fputs(p1, stdout);
526205118Sbrucec	free(p1);
52712946Sphk	return (0);
52812946Sphk}
5291553Srgrimes
53012946Sphkstatic int
531272913SjhbS_vmtotal(size_t l2, void *p)
532109097Sdillon{
533109097Sdillon	struct vmtotal *v = (struct vmtotal *)p;
534109113Sdillon	int pageKilo = getpagesize() / 1024;
535109097Sdillon
536109097Sdillon	if (l2 != sizeof(*v)) {
537272913Sjhb		warnx("S_vmtotal %zu != %zu", l2, sizeof(*v));
538170558Sbde		return (1);
539109097Sdillon	}
540109097Sdillon
541109113Sdillon	printf(
542109113Sdillon	    "\nSystem wide totals computed every five seconds:"
543109113Sdillon	    " (values in kilobytes)\n");
544109097Sdillon	printf("===============================================\n");
545109113Sdillon	printf(
546164718Sru	    "Processes:\t\t(RUNQ: %hd Disk Wait: %hd Page Wait: "
547164718Sru	    "%hd Sleep: %hd)\n",
548109113Sdillon	    v->t_rq, v->t_dw, v->t_pw, v->t_sl);
549109113Sdillon	printf(
550212726Szec	    "Virtual Memory:\t\t(Total: %dK Active: %dK)\n",
551164718Sru	    v->t_vm * pageKilo, v->t_avm * pageKilo);
552212726Szec	printf("Real Memory:\t\t(Total: %dK Active: %dK)\n",
553164718Sru	    v->t_rm * pageKilo, v->t_arm * pageKilo);
554164718Sru	printf("Shared Virtual Memory:\t(Total: %dK Active: %dK)\n",
555164718Sru	    v->t_vmshr * pageKilo, v->t_avmshr * pageKilo);
556164718Sru	printf("Shared Real Memory:\t(Total: %dK Active: %dK)\n",
557164718Sru	    v->t_rmshr * pageKilo, v->t_armshr * pageKilo);
558272913Sjhb	printf("Free Memory:\t%dK", v->t_free * pageKilo);
559122234Sdes
560109097Sdillon	return (0);
561109097Sdillon}
562109097Sdillon
563272913Sjhb#ifdef __amd64__
564272913Sjhb#define efi_next_descriptor(ptr, size) \
565272913Sjhb	((struct efi_md *)(((uint8_t *) ptr) + size))
566272913Sjhb
567109097Sdillonstatic int
568272913SjhbS_efi_map(size_t l2, void *p)
569272913Sjhb{
570272913Sjhb	struct efi_map_header *efihdr;
571272913Sjhb	struct efi_md *map;
572272913Sjhb	const char *type;
573272913Sjhb	size_t efisz;
574272913Sjhb	int ndesc, i;
575272913Sjhb
576272913Sjhb	static const char *types[] = {
577272913Sjhb		"Reserved",
578272913Sjhb		"LoaderCode",
579272913Sjhb		"LoaderData",
580272913Sjhb		"BootServicesCode",
581272913Sjhb		"BootServicesData",
582272913Sjhb		"RuntimeServicesCode",
583272913Sjhb		"RuntimeServicesData",
584272913Sjhb		"ConventionalMemory",
585272913Sjhb		"UnusableMemory",
586272913Sjhb		"ACPIReclaimMemory",
587272913Sjhb		"ACPIMemoryNVS",
588272913Sjhb		"MemoryMappedIO",
589272913Sjhb		"MemoryMappedIOPortSpace",
590272913Sjhb		"PalCode"
591272913Sjhb	};
592272913Sjhb
593272913Sjhb	/*
594272913Sjhb	 * Memory map data provided by UEFI via the GetMemoryMap
595272913Sjhb	 * Boot Services API.
596272913Sjhb	 */
597272913Sjhb	if (l2 < sizeof(*efihdr)) {
598272913Sjhb		warnx("S_efi_map length less than header");
599272913Sjhb		return (1);
600272913Sjhb	}
601272913Sjhb	efihdr = p;
602272913Sjhb	efisz = (sizeof(struct efi_map_header) + 0xf) & ~0xf;
603272913Sjhb	map = (struct efi_md *)((uint8_t *)efihdr + efisz);
604272913Sjhb
605272913Sjhb	if (efihdr->descriptor_size == 0)
606272913Sjhb		return (0);
607272913Sjhb	if (l2 != efisz + efihdr->memory_size) {
608272913Sjhb		warnx("S_efi_map length mismatch %zu vs %zu", l2, efisz +
609272913Sjhb		    efihdr->memory_size);
610272913Sjhb		return (1);
611272913Sjhb	}
612272913Sjhb	ndesc = efihdr->memory_size / efihdr->descriptor_size;
613272913Sjhb
614272913Sjhb	printf("\n%23s %12s %12s %8s %4s",
615272913Sjhb	    "Type", "Physical", "Virtual", "#Pages", "Attr");
616272913Sjhb
617272913Sjhb	for (i = 0; i < ndesc; i++,
618272913Sjhb	    map = efi_next_descriptor(map, efihdr->descriptor_size)) {
619272913Sjhb		if (map->md_type <= EFI_MD_TYPE_PALCODE)
620272913Sjhb			type = types[map->md_type];
621272913Sjhb		else
622272913Sjhb			type = "<INVALID>";
623272913Sjhb		printf("\n%23s %012lx %12p %08lx ", type, map->md_phys,
624272913Sjhb		    map->md_virt, map->md_pages);
625272913Sjhb		if (map->md_attr & EFI_MD_ATTR_UC)
626272913Sjhb			printf("UC ");
627272913Sjhb		if (map->md_attr & EFI_MD_ATTR_WC)
628272913Sjhb			printf("WC ");
629272913Sjhb		if (map->md_attr & EFI_MD_ATTR_WT)
630272913Sjhb			printf("WT ");
631272913Sjhb		if (map->md_attr & EFI_MD_ATTR_WB)
632272913Sjhb			printf("WB ");
633272913Sjhb		if (map->md_attr & EFI_MD_ATTR_UCE)
634272913Sjhb			printf("UCE ");
635272913Sjhb		if (map->md_attr & EFI_MD_ATTR_WP)
636272913Sjhb			printf("WP ");
637272913Sjhb		if (map->md_attr & EFI_MD_ATTR_RP)
638272913Sjhb			printf("RP ");
639272913Sjhb		if (map->md_attr & EFI_MD_ATTR_XP)
640272913Sjhb			printf("XP ");
641272913Sjhb		if (map->md_attr & EFI_MD_ATTR_RT)
642272913Sjhb			printf("RUNTIME");
643272913Sjhb	}
644272913Sjhb	return (0);
645272913Sjhb}
646272913Sjhb#endif
647272913Sjhb
648272913Sjhb#if defined(__amd64__) || defined(__i386__)
649272913Sjhbstatic int
650272913SjhbS_bios_smap_xattr(size_t l2, void *p)
651272913Sjhb{
652272913Sjhb	struct bios_smap_xattr *smap, *end;
653272913Sjhb
654272913Sjhb	if (l2 % sizeof(*smap) != 0) {
655272913Sjhb		warnx("S_bios_smap_xattr %zu is not a multiple of %zu", l2,
656272913Sjhb		    sizeof(*smap));
657272913Sjhb		return (1);
658272913Sjhb	}
659272913Sjhb
660272913Sjhb	end = (struct bios_smap_xattr *)((char *)p + l2);
661272913Sjhb	for (smap = p; smap < end; smap++)
662272913Sjhb		printf("\nSMAP type=%02x, xattr=%02x, base=%016jx, len=%016jx",
663272913Sjhb		    smap->type, smap->xattr, (uintmax_t)smap->base,
664272913Sjhb		    (uintmax_t)smap->length);
665272913Sjhb	return (0);
666272913Sjhb}
667272913Sjhb#endif
668272913Sjhb
669272913Sjhbstatic int
670198340Sedset_IK(const char *str, int *val)
671161951Sume{
672161951Sume	float temp;
673161951Sume	int len, kelv;
674198340Sed	const char *p;
675198340Sed	char *endptr;
676161951Sume
677161951Sume	if ((len = strlen(str)) == 0)
678161951Sume		return (0);
679161951Sume	p = &str[len - 1];
680161951Sume	if (*p == 'C' || *p == 'F') {
681161951Sume		temp = strtof(str, &endptr);
682198340Sed		if (endptr == str || endptr != p)
683161951Sume			return (0);
684161951Sume		if (*p == 'F')
685161951Sume			temp = (temp - 32) * 5 / 9;
686161951Sume		kelv = temp * 10 + 2732;
687161951Sume	} else {
688161951Sume		kelv = (int)strtol(str, &endptr, 10);
689161951Sume		if (endptr == str || *endptr != '\0')
690161951Sume			return (0);
691161951Sume	}
692161951Sume	*val = kelv;
693161951Sume	return (1);
694161951Sume}
695161951Sume
69612946Sphk/*
69712946Sphk * These functions uses a presently undocumented interface to the kernel
69812946Sphk * to walk the tree and get the type so it can print the value.
69912946Sphk * This interface is under work and consideration, and should probably
70012946Sphk * be killed with a big axe by the first person who can find the time.
70112946Sphk * (be aware though, that the proper interface isn't as obvious as it
70212946Sphk * may seem, there are various conflicting requirements.
70312946Sphk */
7041553Srgrimes
70512946Sphkstatic int
706275485Sdelphijname2oid(const char *name, int *oidp)
70712946Sphk{
70812946Sphk	int oid[2];
70938533Sdfr	int i;
71038533Sdfr	size_t j;
7111553Srgrimes
71212946Sphk	oid[0] = 0;
71312946Sphk	oid[1] = 3;
7141553Srgrimes
71577928Sdd	j = CTL_MAXNAME * sizeof(int);
71612946Sphk	i = sysctl(oid, 2, oidp, &j, name, strlen(name));
717122234Sdes	if (i < 0)
718170512Sdwmalone		return (i);
71977928Sdd	j /= sizeof(int);
72012946Sphk	return (j);
7211553Srgrimes}
7221553Srgrimes
72312946Sphkstatic int
72412946Sphkoidfmt(int *oid, int len, char *fmt, u_int *kind)
72512946Sphk{
72612946Sphk	int qoid[CTL_MAXNAME+2];
72712946Sphk	u_char buf[BUFSIZ];
72838533Sdfr	int i;
72938533Sdfr	size_t j;
7301553Srgrimes
73112946Sphk	qoid[0] = 0;
73212946Sphk	qoid[1] = 4;
73312946Sphk	memcpy(qoid + 2, oid, len * sizeof(int));
7341553Srgrimes
73577928Sdd	j = sizeof(buf);
73612946Sphk	i = sysctl(qoid, len + 2, buf, &j, 0, 0);
73712946Sphk	if (i)
738203917Suqs		err(1, "sysctl fmt %d %zu %d", i, j, errno);
7391553Srgrimes
74012946Sphk	if (kind)
74112946Sphk		*kind = *(u_int *)buf;
74212946Sphk
74312946Sphk	if (fmt)
74412946Sphk		strcpy(fmt, (char *)(buf + sizeof(u_int)));
745170512Sdwmalone	return (0);
7461553Srgrimes}
7471553Srgrimes
748217616Smdfstatic int ctl_sign[CTLTYPE+1] = {
749217616Smdf	[CTLTYPE_INT] = 1,
750217616Smdf	[CTLTYPE_LONG] = 1,
751217616Smdf	[CTLTYPE_S64] = 1,
752217616Smdf};
753217616Smdf
754217616Smdfstatic int ctl_size[CTLTYPE+1] = {
755217616Smdf	[CTLTYPE_INT] = sizeof(int),
756217616Smdf	[CTLTYPE_UINT] = sizeof(u_int),
757217616Smdf	[CTLTYPE_LONG] = sizeof(long),
758217616Smdf	[CTLTYPE_ULONG] = sizeof(u_long),
759217616Smdf	[CTLTYPE_S64] = sizeof(int64_t),
760217616Smdf	[CTLTYPE_U64] = sizeof(int64_t),
761217616Smdf};
762217616Smdf
7631553Srgrimes/*
76412946Sphk * This formats and outputs the value of one variable
76512946Sphk *
76612946Sphk * Returns zero if anything was actually output.
76712946Sphk * Returns one if didn't know what to do with this.
76812946Sphk * Return minus one if we had errors.
7691553Srgrimes */
77012946Sphkstatic int
77112946Sphkshow_var(int *oid, int nlen)
7721553Srgrimes{
773162073Sru	u_char buf[BUFSIZ], *val, *oval, *p;
774244133Salfred	char name[BUFSIZ], fmt[BUFSIZ];
775170513Sdwmalone	const char *sep, *sep1;
77612946Sphk	int qoid[CTL_MAXNAME+2];
777170512Sdwmalone	uintmax_t umv;
778170512Sdwmalone	intmax_t mv;
779217586Smdf	int i, hexlen, sign, ctltype;
780170287Sdwmalone	size_t intlen;
78138533Sdfr	size_t j, len;
78212946Sphk	u_int kind;
783272913Sjhb	int (*func)(size_t, void *);
7841553Srgrimes
785203917Suqs	/* Silence GCC. */
786203917Suqs	umv = mv = intlen = 0;
787203917Suqs
788144997Smdodd	bzero(buf, BUFSIZ);
789244133Salfred	bzero(fmt, BUFSIZ);
790144997Smdodd	bzero(name, BUFSIZ);
79142456Sdes	qoid[0] = 0;
79242456Sdes	memcpy(qoid + 2, oid, nlen * sizeof(int));
79342456Sdes
79442456Sdes	qoid[1] = 1;
79577928Sdd	j = sizeof(name);
79642456Sdes	i = sysctl(qoid, nlen + 2, name, &j, 0, 0);
79742456Sdes	if (i || !j)
798203917Suqs		err(1, "sysctl name %d %zu %d", i, j, errno);
79942456Sdes
800244133Salfred	oidfmt(oid, nlen, fmt, &kind);
801244133Salfred	/* if Wflag then only list sysctls that are writeable and not stats. */
802244133Salfred	if (Wflag && ((kind & CTLFLAG_WR) == 0 || (kind & CTLFLAG_STATS) != 0))
803244133Salfred		return 1;
804244133Salfred
805244133Salfred	/* if Tflag then only list sysctls that are tuneables. */
806244133Salfred	if (Tflag && (kind & CTLFLAG_TUN) == 0)
807244133Salfred		return 1;
808244133Salfred
80971034Sdes	if (Nflag) {
81071034Sdes		printf("%s", name);
81171034Sdes		return (0);
81271034Sdes	}
81371034Sdes
81485747Stobez	if (eflag)
81585747Stobez		sep = "=";
81685747Stobez	else
81785747Stobez		sep = ": ";
81885747Stobez
81988006Sluigi	if (dflag) {	/* just print description */
82088006Sluigi		qoid[1] = 5;
82188006Sluigi		j = sizeof(buf);
82288006Sluigi		i = sysctl(qoid, nlen + 2, buf, &j, 0, 0);
82388006Sluigi		if (!nflag)
82488006Sluigi			printf("%s%s", name, sep);
82588006Sluigi		printf("%s", buf);
82688006Sluigi		return (0);
82788006Sluigi	}
82812946Sphk	/* find an estimate of how much we need for this var */
82912946Sphk	j = 0;
83012946Sphk	i = sysctl(oid, nlen, 0, &j, 0, 0);
83112946Sphk	j += j; /* we want to be sure :-) */
83212946Sphk
833162073Sru	val = oval = malloc(j + 1);
834162073Sru	if (val == NULL) {
835162073Sru		warnx("malloc failed");
836170558Sbde		return (1);
837162073Sru	}
838268243Shselasky	ctltype = (kind & CTLTYPE);
83912946Sphk	len = j;
84012946Sphk	i = sysctl(oid, nlen, val, &len, 0, 0);
841268243Shselasky	if (i != 0 || (len == 0 && ctltype != CTLTYPE_STRING)) {
842162073Sru		free(oval);
84312946Sphk		return (1);
844162073Sru	}
84512946Sphk
84612946Sphk	if (bflag) {
84712946Sphk		fwrite(val, 1, len, stdout);
848162073Sru		free(oval);
84912946Sphk		return (0);
8501553Srgrimes	}
85196234Sache	val[len] = '\0';
85212946Sphk	p = val;
853217616Smdf	sign = ctl_sign[ctltype];
854217616Smdf	intlen = ctl_size[ctltype];
855217616Smdf
856217586Smdf	switch (ctltype) {
857217586Smdf	case CTLTYPE_STRING:
85812946Sphk		if (!nflag)
85985747Stobez			printf("%s%s", name, sep);
860203917Suqs		printf("%.*s", (int)len, p);
861162073Sru		free(oval);
86212946Sphk		return (0);
863122234Sdes
864217586Smdf	case CTLTYPE_INT:
865217586Smdf	case CTLTYPE_UINT:
866217586Smdf	case CTLTYPE_LONG:
867217586Smdf	case CTLTYPE_ULONG:
868217616Smdf	case CTLTYPE_S64:
869217616Smdf	case CTLTYPE_U64:
87012946Sphk		if (!nflag)
87185747Stobez			printf("%s%s", name, sep);
872170514Sdwmalone		hexlen = 2 + (intlen * CHAR_BIT + 3) / 4;
873170513Sdwmalone		sep1 = "";
874170287Sdwmalone		while (len >= intlen) {
875217586Smdf			switch (kind & CTLTYPE) {
876217586Smdf			case CTLTYPE_INT:
877217586Smdf			case CTLTYPE_UINT:
878170514Sdwmalone				umv = *(u_int *)p;
879170514Sdwmalone				mv = *(int *)p;
880170287Sdwmalone				break;
881217586Smdf			case CTLTYPE_LONG:
882217586Smdf			case CTLTYPE_ULONG:
883170514Sdwmalone				umv = *(u_long *)p;
884170514Sdwmalone				mv = *(long *)p;
885170287Sdwmalone				break;
886217616Smdf			case CTLTYPE_S64:
887217616Smdf			case CTLTYPE_U64:
888217616Smdf				umv = *(uint64_t *)p;
889217616Smdf				mv = *(int64_t *)p;
890170287Sdwmalone				break;
891170287Sdwmalone			}
892170513Sdwmalone			fputs(sep1, stdout);
893217586Smdf			if (xflag)
894217586Smdf				printf("%#0*jx", hexlen, umv);
895217586Smdf			else if (!sign)
896170512Sdwmalone				printf(hflag ? "%'ju" : "%ju", umv);
897170287Sdwmalone			else if (fmt[1] == 'K') {
898170514Sdwmalone				if (mv < 0)
899170512Sdwmalone					printf("%jd", mv);
900134541Speter				else
901170512Sdwmalone					printf("%.1fC", (mv - 2732.0) / 10);
902134541Speter			} else
903170513Sdwmalone				printf(hflag ? "%'jd" : "%jd", mv);
904170513Sdwmalone			sep1 = " ";
905170287Sdwmalone			len -= intlen;
906170287Sdwmalone			p += intlen;
90741019Sphk		}
908162073Sru		free(oval);
90912946Sphk		return (0);
91012946Sphk
911217586Smdf	case CTLTYPE_OPAQUE:
91212946Sphk		i = 0;
91377332Sdes		if (strcmp(fmt, "S,clockinfo") == 0)
91477332Sdes			func = S_clockinfo;
91577332Sdes		else if (strcmp(fmt, "S,timeval") == 0)
91677332Sdes			func = S_timeval;
91777332Sdes		else if (strcmp(fmt, "S,loadavg") == 0)
91877332Sdes			func = S_loadavg;
919109097Sdillon		else if (strcmp(fmt, "S,vmtotal") == 0)
920109097Sdillon			func = S_vmtotal;
921272913Sjhb#ifdef __amd64__
922272913Sjhb		else if (strcmp(fmt, "S,efi_map_header") == 0)
923272913Sjhb			func = S_efi_map;
924272913Sjhb#endif
925272913Sjhb#if defined(__amd64__) || defined(__i386__)
926272913Sjhb		else if (strcmp(fmt, "S,bios_smap_xattr") == 0)
927272913Sjhb			func = S_bios_smap_xattr;
928272913Sjhb#endif
92977332Sdes		else
93077332Sdes			func = NULL;
93112946Sphk		if (func) {
93212946Sphk			if (!nflag)
93385747Stobez				printf("%s%s", name, sep);
934163275Sharti			i = (*func)(len, p);
935162073Sru			free(oval);
936163275Sharti			return (i);
93712946Sphk		}
938102411Scharnier		/* FALLTHROUGH */
93912946Sphk	default:
940162073Sru		if (!oflag && !xflag) {
941162073Sru			free(oval);
94212946Sphk			return (1);
943162073Sru		}
94412946Sphk		if (!nflag)
94585747Stobez			printf("%s%s", name, sep);
946203917Suqs		printf("Format:%s Length:%zu Dump:0x", fmt, len);
94777332Sdes		while (len-- && (xflag || p < val + 16))
94812946Sphk			printf("%02x", *p++);
94977332Sdes		if (!xflag && len > 16)
95012946Sphk			printf("...");
951162073Sru		free(oval);
95212946Sphk		return (0);
9531553Srgrimes	}
954162073Sru	free(oval);
95512946Sphk	return (1);
9561553Srgrimes}
9571553Srgrimes
95812946Sphkstatic int
959170512Sdwmalonesysctl_all(int *oid, int len)
9601553Srgrimes{
96112946Sphk	int name1[22], name2[22];
96238533Sdfr	int i, j;
96338533Sdfr	size_t l1, l2;
9641553Srgrimes
96512946Sphk	name1[0] = 0;
96612946Sphk	name1[1] = 2;
96712946Sphk	l1 = 2;
96812946Sphk	if (len) {
96977928Sdd		memcpy(name1+2, oid, len * sizeof(int));
97012946Sphk		l1 += len;
97112946Sphk	} else {
97212946Sphk		name1[2] = 1;
97312946Sphk		l1++;
97412946Sphk	}
97577332Sdes	for (;;) {
97677928Sdd		l2 = sizeof(name2);
97712946Sphk		j = sysctl(name1, l1, name2, &l2, 0, 0);
97848956Sbillf		if (j < 0) {
97912946Sphk			if (errno == ENOENT)
980170512Sdwmalone				return (0);
98112946Sphk			else
982203917Suqs				err(1, "sysctl(getnext) %d %zu", j, l2);
98348956Sbillf		}
98412946Sphk
98577928Sdd		l2 /= sizeof(int);
98612946Sphk
987170513Sdwmalone		if (len < 0 || l2 < (unsigned int)len)
988170512Sdwmalone			return (0);
98912946Sphk
99012946Sphk		for (i = 0; i < len; i++)
99112946Sphk			if (name2[i] != oid[i])
992170512Sdwmalone				return (0);
99312946Sphk
99412946Sphk		i = show_var(name2, l2);
99512946Sphk		if (!i && !bflag)
99612946Sphk			putchar('\n');
99712946Sphk
99877928Sdd		memcpy(name1+2, name2, l2 * sizeof(int));
99912946Sphk		l1 = 2 + l2;
100012946Sphk	}
10011553Srgrimes}
1002