xref: /f-stack/tools/sysctl/sysctl.c (revision 7abd0fb2)
1*7abd0fb2Slogwang /*
2*7abd0fb2Slogwang  * Copyright (c) 1993
3*7abd0fb2Slogwang  *    The Regents of the University of California.  All rights reserved.
4*7abd0fb2Slogwang  *
5*7abd0fb2Slogwang  * Copyright (C) 2017 THL A29 Limited, a Tencent company.
6*7abd0fb2Slogwang  * All rights reserved.
7*7abd0fb2Slogwang  *
8*7abd0fb2Slogwang  * Redistribution and use in source and binary forms, with or without
9*7abd0fb2Slogwang  * modification, are permitted provided that the following conditions
10*7abd0fb2Slogwang  * are met:
11*7abd0fb2Slogwang  * 1. Redistributions of source code must retain the above copyright
12*7abd0fb2Slogwang  *    notice, this list of conditions and the following disclaimer.
13*7abd0fb2Slogwang  * 2. Redistributions in binary form must reproduce the above copyright
14*7abd0fb2Slogwang  *    notice, this list of conditions and the following disclaimer in the
15*7abd0fb2Slogwang  *    documentation and/or other materials provided with the distribution.
16*7abd0fb2Slogwang  * 4. Neither the name of the University nor the names of its contributors
17*7abd0fb2Slogwang  *    may be used to endorse or promote products derived from this software
18*7abd0fb2Slogwang  *    without specific prior written permission.
19*7abd0fb2Slogwang  *
20*7abd0fb2Slogwang  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21*7abd0fb2Slogwang  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22*7abd0fb2Slogwang  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23*7abd0fb2Slogwang  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24*7abd0fb2Slogwang  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25*7abd0fb2Slogwang  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26*7abd0fb2Slogwang  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27*7abd0fb2Slogwang  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28*7abd0fb2Slogwang  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29*7abd0fb2Slogwang  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30*7abd0fb2Slogwang  * SUCH DAMAGE.
31*7abd0fb2Slogwang  *
32*7abd0fb2Slogwang  *  Derived in part from FreeBSD's /sbin/sysctl/sysctl.c.
33*7abd0fb2Slogwang  */
34*7abd0fb2Slogwang 
35*7abd0fb2Slogwang #ifndef lint
36*7abd0fb2Slogwang static const char copyright[] =
37*7abd0fb2Slogwang "@(#) Copyright (c) 1993\n\
38*7abd0fb2Slogwang     The Regents of the University of California.  All rights reserved.\n";
39*7abd0fb2Slogwang #endif /* not lint */
40*7abd0fb2Slogwang 
41*7abd0fb2Slogwang #ifndef lint
42*7abd0fb2Slogwang #if 0
43*7abd0fb2Slogwang static char sccsid[] = "@(#)from: sysctl.c    8.1 (Berkeley) 6/6/93";
44*7abd0fb2Slogwang #endif
45*7abd0fb2Slogwang static const char rcsid[] = "$FreeBSD$";
46*7abd0fb2Slogwang #endif /* not lint */
47*7abd0fb2Slogwang 
48*7abd0fb2Slogwang #include <assert.h>
49*7abd0fb2Slogwang #include <ctype.h>
50*7abd0fb2Slogwang #include <err.h>
51*7abd0fb2Slogwang #include <errno.h>
52*7abd0fb2Slogwang #include <inttypes.h>
53*7abd0fb2Slogwang #include <locale.h>
54*7abd0fb2Slogwang #include <stdio.h>
55*7abd0fb2Slogwang #include <stdlib.h>
56*7abd0fb2Slogwang #include <stdint.h>
57*7abd0fb2Slogwang #include <string.h>
58*7abd0fb2Slogwang #include <sysexits.h>
59*7abd0fb2Slogwang #include <limits.h>
60*7abd0fb2Slogwang #include <unistd.h>
61*7abd0fb2Slogwang #include <time.h>
62*7abd0fb2Slogwang 
63*7abd0fb2Slogwang #include "ff_ipc.h"
64*7abd0fb2Slogwang 
65*7abd0fb2Slogwang /*
66*7abd0fb2Slogwang  * Definitions for sysctl call.  The sysctl call uses a hierarchical name
67*7abd0fb2Slogwang  * for objects that can be examined or modified.  The name is expressed as
68*7abd0fb2Slogwang  * a sequence of integers.  Like a file path name, the meaning of each
69*7abd0fb2Slogwang  * component depends on its place in the hierarchy.  The top-level and kern
70*7abd0fb2Slogwang  * identifiers are defined here, and other identifiers are defined in the
71*7abd0fb2Slogwang  * respective subsystem header files.
72*7abd0fb2Slogwang  */
73*7abd0fb2Slogwang 
74*7abd0fb2Slogwang #define CTL_MAXNAME       24    /* largest number of components supported */
75*7abd0fb2Slogwang 
76*7abd0fb2Slogwang #define CTLTYPE           0xf    /* mask for the type */
77*7abd0fb2Slogwang #define CTLTYPE_NODE      1    /* name is a node */
78*7abd0fb2Slogwang #define CTLTYPE_INT       2    /* name describes an integer */
79*7abd0fb2Slogwang #define CTLTYPE_STRING    3    /* name describes a string */
80*7abd0fb2Slogwang #define CTLTYPE_S64       4    /* name describes a signed 64-bit number */
81*7abd0fb2Slogwang #define CTLTYPE_OPAQUE    5    /* name describes a structure */
82*7abd0fb2Slogwang #define CTLTYPE_STRUCT    CTLTYPE_OPAQUE    /* name describes a structure */
83*7abd0fb2Slogwang #define CTLTYPE_UINT      6    /* name describes an unsigned integer */
84*7abd0fb2Slogwang #define CTLTYPE_LONG      7    /* name describes a long */
85*7abd0fb2Slogwang #define CTLTYPE_ULONG     8    /* name describes an unsigned long */
86*7abd0fb2Slogwang #define CTLTYPE_U64       9    /* name describes an unsigned 64-bit number */
87*7abd0fb2Slogwang #define CTLTYPE_U8        0xa  /* name describes an unsigned 8-bit number */
88*7abd0fb2Slogwang #define CTLTYPE_U16       0xb  /* name describes an unsigned 16-bit number */
89*7abd0fb2Slogwang #define CTLTYPE_S8        0xc  /* name describes a signed 8-bit number */
90*7abd0fb2Slogwang #define CTLTYPE_S16       0xd  /* name describes a signed 16-bit number */
91*7abd0fb2Slogwang #define CTLTYPE_S32       0xe  /* name describes a signed 32-bit number */
92*7abd0fb2Slogwang #define CTLTYPE_U32       0xf  /* name describes an unsigned 32-bit number */
93*7abd0fb2Slogwang 
94*7abd0fb2Slogwang #define CTLFLAG_RD        0x80000000    /* Allow reads of variable */
95*7abd0fb2Slogwang #define CTLFLAG_WR        0x40000000    /* Allow writes to the variable */
96*7abd0fb2Slogwang #define CTLFLAG_RW        (CTLFLAG_RD|CTLFLAG_WR)
97*7abd0fb2Slogwang #define CTLFLAG_ANYBODY   0x10000000    /* All users can set this var */
98*7abd0fb2Slogwang #define CTLFLAG_SECURE    0x08000000    /* Permit set only if securelevel<=0 */
99*7abd0fb2Slogwang #define CTLFLAG_PRISON    0x04000000    /* Prisoned roots can fiddle */
100*7abd0fb2Slogwang #define CTLFLAG_DYN       0x02000000    /* Dynamic oid - can be freed */
101*7abd0fb2Slogwang #define CTLFLAG_SKIP      0x01000000    /* Skip this sysctl when listing */
102*7abd0fb2Slogwang #define CTLMASK_SECURE    0x00F00000    /* Secure level */
103*7abd0fb2Slogwang #define CTLFLAG_TUN       0x00080000    /* Default value is loaded from getenv() */
104*7abd0fb2Slogwang #define CTLFLAG_RDTUN     (CTLFLAG_RD|CTLFLAG_TUN)
105*7abd0fb2Slogwang #define CTLFLAG_RWTUN     (CTLFLAG_RW|CTLFLAG_TUN)
106*7abd0fb2Slogwang #define CTLFLAG_MPSAFE    0x00040000    /* Handler is MP safe */
107*7abd0fb2Slogwang #define CTLFLAG_VNET      0x00020000    /* Prisons with vnet can fiddle */
108*7abd0fb2Slogwang #define CTLFLAG_DYING     0x00010000    /* Oid is being removed */
109*7abd0fb2Slogwang #define CTLFLAG_CAPRD     0x00008000    /* Can be read in capability mode */
110*7abd0fb2Slogwang #define CTLFLAG_CAPWR     0x00004000    /* Can be written in capability mode */
111*7abd0fb2Slogwang #define CTLFLAG_STATS     0x00002000    /* Statistics, not a tuneable */
112*7abd0fb2Slogwang #define CTLFLAG_NOFETCH   0x00001000    /* Don't fetch tunable from getenv() */
113*7abd0fb2Slogwang #define CTLFLAG_CAPRW    (CTLFLAG_CAPRD|CTLFLAG_CAPWR)
114*7abd0fb2Slogwang 
115*7abd0fb2Slogwang 
116*7abd0fb2Slogwang struct clockinfo {
117*7abd0fb2Slogwang     int hz;        /* clock frequency */
118*7abd0fb2Slogwang     int tick;      /* micro-seconds per hz tick */
119*7abd0fb2Slogwang     int spare;
120*7abd0fb2Slogwang     int stathz;    /* statistics clock frequency */
121*7abd0fb2Slogwang     int profhz;    /* profiling clock frequency */
122*7abd0fb2Slogwang };
123*7abd0fb2Slogwang 
124*7abd0fb2Slogwang struct loadavg {
125*7abd0fb2Slogwang     __uint32_t ldavg[3];
126*7abd0fb2Slogwang     long fscale;
127*7abd0fb2Slogwang };
128*7abd0fb2Slogwang 
129*7abd0fb2Slogwang /* Structure extended to include extended attribute field in ACPI 3.0. */
130*7abd0fb2Slogwang struct bios_smap_xattr {
131*7abd0fb2Slogwang     u_int64_t base;
132*7abd0fb2Slogwang     u_int64_t length;
133*7abd0fb2Slogwang     u_int32_t type;
134*7abd0fb2Slogwang     u_int32_t xattr;
135*7abd0fb2Slogwang } __packed;
136*7abd0fb2Slogwang 
137*7abd0fb2Slogwang /* systemwide totals computed every five seconds */
138*7abd0fb2Slogwang struct vmtotal {
139*7abd0fb2Slogwang     int16_t t_rq;        /* length of the run queue */
140*7abd0fb2Slogwang     int16_t t_dw;        /* jobs in ``disk wait'' (neg priority) */
141*7abd0fb2Slogwang     int16_t t_pw;        /* jobs in page wait */
142*7abd0fb2Slogwang     int16_t t_sl;        /* jobs sleeping in core */
143*7abd0fb2Slogwang     int16_t t_sw;        /* swapped out runnable/short block jobs */
144*7abd0fb2Slogwang     int32_t t_vm;        /* total virtual memory */
145*7abd0fb2Slogwang     int32_t t_avm;       /* active virtual memory */
146*7abd0fb2Slogwang     int32_t t_rm;        /* total real memory in use */
147*7abd0fb2Slogwang     int32_t t_arm;       /* active real memory */
148*7abd0fb2Slogwang     int32_t t_vmshr;     /* shared virtual memory */
149*7abd0fb2Slogwang     int32_t t_avmshr;    /* active shared virtual memory */
150*7abd0fb2Slogwang     int32_t t_rmshr;     /* shared real memory */
151*7abd0fb2Slogwang     int32_t t_armshr;    /* active shared real memory */
152*7abd0fb2Slogwang     int32_t t_free;      /* free memory pages */
153*7abd0fb2Slogwang };
154*7abd0fb2Slogwang 
155*7abd0fb2Slogwang struct efi_md {
156*7abd0fb2Slogwang     uint32_t md_type;
157*7abd0fb2Slogwang #define EFI_MD_TYPE_NULL    0
158*7abd0fb2Slogwang #define EFI_MD_TYPE_CODE    1   /* Loader text. */
159*7abd0fb2Slogwang #define EFI_MD_TYPE_DATA    2   /* Loader data. */
160*7abd0fb2Slogwang #define EFI_MD_TYPE_BS_CODE 3   /* Boot services text. */
161*7abd0fb2Slogwang #define EFI_MD_TYPE_BS_DATA 4   /* Boot services data. */
162*7abd0fb2Slogwang #define EFI_MD_TYPE_RT_CODE 5   /* Runtime services text. */
163*7abd0fb2Slogwang #define EFI_MD_TYPE_RT_DATA 6   /* Runtime services data. */
164*7abd0fb2Slogwang #define EFI_MD_TYPE_FREE    7   /* Unused/free memory. */
165*7abd0fb2Slogwang #define EFI_MD_TYPE_BAD     8   /* Bad memory */
166*7abd0fb2Slogwang #define EFI_MD_TYPE_RECLAIM 9   /* ACPI reclaimable memory. */
167*7abd0fb2Slogwang #define EFI_MD_TYPE_FIRMWARE    10  /* ACPI NV memory */
168*7abd0fb2Slogwang #define EFI_MD_TYPE_IOMEM   11  /* Memory-mapped I/O. */
169*7abd0fb2Slogwang #define EFI_MD_TYPE_IOPORT  12  /* I/O port space. */
170*7abd0fb2Slogwang #define EFI_MD_TYPE_PALCODE 13  /* PAL */
171*7abd0fb2Slogwang     uint32_t __pad;
172*7abd0fb2Slogwang     uint64_t md_phys;
173*7abd0fb2Slogwang     void *md_virt;
174*7abd0fb2Slogwang     uint64_t md_pages;
175*7abd0fb2Slogwang     uint64_t md_attr;
176*7abd0fb2Slogwang #define EFI_MD_ATTR_UC      0x0000000000000001UL
177*7abd0fb2Slogwang #define EFI_MD_ATTR_WC      0x0000000000000002UL
178*7abd0fb2Slogwang #define EFI_MD_ATTR_WT      0x0000000000000004UL
179*7abd0fb2Slogwang #define EFI_MD_ATTR_WB      0x0000000000000008UL
180*7abd0fb2Slogwang #define EFI_MD_ATTR_UCE     0x0000000000000010UL
181*7abd0fb2Slogwang #define EFI_MD_ATTR_WP      0x0000000000001000UL
182*7abd0fb2Slogwang #define EFI_MD_ATTR_RP      0x0000000000002000UL
183*7abd0fb2Slogwang #define EFI_MD_ATTR_XP      0x0000000000004000UL
184*7abd0fb2Slogwang #define EFI_MD_ATTR_RT      0x8000000000000000UL
185*7abd0fb2Slogwang };
186*7abd0fb2Slogwang 
187*7abd0fb2Slogwang struct efi_map_header {
188*7abd0fb2Slogwang     uint64_t memory_size;
189*7abd0fb2Slogwang     uint64_t descriptor_size;
190*7abd0fb2Slogwang     uint32_t descriptor_version;
191*7abd0fb2Slogwang };
192*7abd0fb2Slogwang 
193*7abd0fb2Slogwang static const char *conffile;
194*7abd0fb2Slogwang 
195*7abd0fb2Slogwang static int aflag, bflag, Bflag, dflag, eflag, hflag, iflag;
196*7abd0fb2Slogwang static int Nflag, nflag, oflag, qflag, tflag, Tflag, Wflag, xflag;
197*7abd0fb2Slogwang static uint16_t proc_id;
198*7abd0fb2Slogwang 
199*7abd0fb2Slogwang static int oidfmt(int *, int, char *, u_int *);
200*7abd0fb2Slogwang static int parsefile(const char *);
201*7abd0fb2Slogwang static int parse(const char *, int);
202*7abd0fb2Slogwang static int show_var(int *, int);
203*7abd0fb2Slogwang static int sysctl_all(int *oid, int len);
204*7abd0fb2Slogwang static int name2oid(const char *, int *);
205*7abd0fb2Slogwang 
206*7abd0fb2Slogwang static int strIKtoi(const char *, char **, const char *);
207*7abd0fb2Slogwang 
208*7abd0fb2Slogwang static int sysctl_ipc(int *name, unsigned namelen, void *old,
209*7abd0fb2Slogwang     size_t *oldlenp, const void *new, size_t newlen);
210*7abd0fb2Slogwang 
211*7abd0fb2Slogwang static int ctl_sign[CTLTYPE+1] = {
212*7abd0fb2Slogwang     [CTLTYPE_INT] = 1,
213*7abd0fb2Slogwang     [CTLTYPE_LONG] = 1,
214*7abd0fb2Slogwang     [CTLTYPE_S8] = 1,
215*7abd0fb2Slogwang     [CTLTYPE_S16] = 1,
216*7abd0fb2Slogwang     [CTLTYPE_S32] = 1,
217*7abd0fb2Slogwang     [CTLTYPE_S64] = 1,
218*7abd0fb2Slogwang };
219*7abd0fb2Slogwang 
220*7abd0fb2Slogwang static int ctl_size[CTLTYPE+1] = {
221*7abd0fb2Slogwang     [CTLTYPE_INT] = sizeof(int),
222*7abd0fb2Slogwang     [CTLTYPE_UINT] = sizeof(u_int),
223*7abd0fb2Slogwang     [CTLTYPE_LONG] = sizeof(long),
224*7abd0fb2Slogwang     [CTLTYPE_ULONG] = sizeof(u_long),
225*7abd0fb2Slogwang     [CTLTYPE_S8] = sizeof(int8_t),
226*7abd0fb2Slogwang     [CTLTYPE_S16] = sizeof(int16_t),
227*7abd0fb2Slogwang     [CTLTYPE_S32] = sizeof(int32_t),
228*7abd0fb2Slogwang     [CTLTYPE_S64] = sizeof(int64_t),
229*7abd0fb2Slogwang     [CTLTYPE_U8] = sizeof(uint8_t),
230*7abd0fb2Slogwang     [CTLTYPE_U16] = sizeof(uint16_t),
231*7abd0fb2Slogwang     [CTLTYPE_U32] = sizeof(uint32_t),
232*7abd0fb2Slogwang     [CTLTYPE_U64] = sizeof(uint64_t),
233*7abd0fb2Slogwang };
234*7abd0fb2Slogwang 
235*7abd0fb2Slogwang static const char *ctl_typename[CTLTYPE+1] = {
236*7abd0fb2Slogwang     [CTLTYPE_INT] = "integer",
237*7abd0fb2Slogwang     [CTLTYPE_UINT] = "unsigned integer",
238*7abd0fb2Slogwang     [CTLTYPE_LONG] = "long integer",
239*7abd0fb2Slogwang     [CTLTYPE_ULONG] = "unsigned long",
240*7abd0fb2Slogwang     [CTLTYPE_U8] = "uint8_t",
241*7abd0fb2Slogwang     [CTLTYPE_U16] = "uint16_t",
242*7abd0fb2Slogwang     [CTLTYPE_U32] = "uint16_t",
243*7abd0fb2Slogwang     [CTLTYPE_U64] = "uint64_t",
244*7abd0fb2Slogwang     [CTLTYPE_S8] = "int8_t",
245*7abd0fb2Slogwang     [CTLTYPE_S16] = "int16_t",
246*7abd0fb2Slogwang     [CTLTYPE_S32] = "int32_t",
247*7abd0fb2Slogwang     [CTLTYPE_S64] = "int64_t",
248*7abd0fb2Slogwang     [CTLTYPE_NODE] = "node",
249*7abd0fb2Slogwang     [CTLTYPE_STRING] = "string",
250*7abd0fb2Slogwang     [CTLTYPE_OPAQUE] = "opaque",
251*7abd0fb2Slogwang };
252*7abd0fb2Slogwang 
253*7abd0fb2Slogwang static void
254*7abd0fb2Slogwang usage(void)
255*7abd0fb2Slogwang {
256*7abd0fb2Slogwang     (void)fprintf(stderr, "%s\n%s\n",
257*7abd0fb2Slogwang         "usage: sysctl -p <f-stack proc_id> [-bdehiNnoqTtWx] [ -B <bufsize> ] [-f filename] name[=value] ...",
258*7abd0fb2Slogwang         "       sysctl -p <f-stack proc_id> [-bdehNnoqTtWx] [ -B <bufsize> ] -a");
259*7abd0fb2Slogwang     exit(1);
260*7abd0fb2Slogwang }
261*7abd0fb2Slogwang 
262*7abd0fb2Slogwang int
263*7abd0fb2Slogwang main(int argc, char **argv)
264*7abd0fb2Slogwang {
265*7abd0fb2Slogwang     int ch;
266*7abd0fb2Slogwang     int warncount = 0;
267*7abd0fb2Slogwang 
268*7abd0fb2Slogwang     setlocale(LC_NUMERIC, "");
269*7abd0fb2Slogwang     setbuf(stdout,0);
270*7abd0fb2Slogwang     setbuf(stderr,0);
271*7abd0fb2Slogwang 
272*7abd0fb2Slogwang     while ((ch = getopt(argc, argv, "AabB:def:hiNnoqtTwWxXp:")) != -1) {
273*7abd0fb2Slogwang         switch (ch) {
274*7abd0fb2Slogwang         case 'A':
275*7abd0fb2Slogwang             /* compatibility */
276*7abd0fb2Slogwang             aflag = oflag = 1;
277*7abd0fb2Slogwang             break;
278*7abd0fb2Slogwang         case 'a':
279*7abd0fb2Slogwang             aflag = 1;
280*7abd0fb2Slogwang             break;
281*7abd0fb2Slogwang         case 'b':
282*7abd0fb2Slogwang             bflag = 1;
283*7abd0fb2Slogwang             break;
284*7abd0fb2Slogwang         case 'B':
285*7abd0fb2Slogwang             Bflag = strtol(optarg, NULL, 0);
286*7abd0fb2Slogwang             break;
287*7abd0fb2Slogwang         case 'd':
288*7abd0fb2Slogwang             dflag = 1;
289*7abd0fb2Slogwang             break;
290*7abd0fb2Slogwang         case 'e':
291*7abd0fb2Slogwang             eflag = 1;
292*7abd0fb2Slogwang             break;
293*7abd0fb2Slogwang         case 'f':
294*7abd0fb2Slogwang             conffile = optarg;
295*7abd0fb2Slogwang             break;
296*7abd0fb2Slogwang         case 'h':
297*7abd0fb2Slogwang             hflag = 1;
298*7abd0fb2Slogwang             break;
299*7abd0fb2Slogwang         case 'i':
300*7abd0fb2Slogwang             iflag = 1;
301*7abd0fb2Slogwang             break;
302*7abd0fb2Slogwang         case 'N':
303*7abd0fb2Slogwang             Nflag = 1;
304*7abd0fb2Slogwang             break;
305*7abd0fb2Slogwang         case 'n':
306*7abd0fb2Slogwang             nflag = 1;
307*7abd0fb2Slogwang             break;
308*7abd0fb2Slogwang         case 'o':
309*7abd0fb2Slogwang             oflag = 1;
310*7abd0fb2Slogwang             break;
311*7abd0fb2Slogwang         case 'q':
312*7abd0fb2Slogwang             qflag = 1;
313*7abd0fb2Slogwang             break;
314*7abd0fb2Slogwang         case 't':
315*7abd0fb2Slogwang             tflag = 1;
316*7abd0fb2Slogwang             break;
317*7abd0fb2Slogwang         case 'T':
318*7abd0fb2Slogwang             Tflag = 1;
319*7abd0fb2Slogwang             break;
320*7abd0fb2Slogwang         case 'w':
321*7abd0fb2Slogwang             /* compatibility */
322*7abd0fb2Slogwang             /* ignored */
323*7abd0fb2Slogwang             break;
324*7abd0fb2Slogwang         case 'W':
325*7abd0fb2Slogwang             Wflag = 1;
326*7abd0fb2Slogwang             break;
327*7abd0fb2Slogwang         case 'X':
328*7abd0fb2Slogwang             /* compatibility */
329*7abd0fb2Slogwang             aflag = xflag = 1;
330*7abd0fb2Slogwang             break;
331*7abd0fb2Slogwang         case 'x':
332*7abd0fb2Slogwang             xflag = 1;
333*7abd0fb2Slogwang             break;
334*7abd0fb2Slogwang         case 'p':
335*7abd0fb2Slogwang             proc_id = atoi(optarg);
336*7abd0fb2Slogwang             break;
337*7abd0fb2Slogwang         default:
338*7abd0fb2Slogwang             usage();
339*7abd0fb2Slogwang         }
340*7abd0fb2Slogwang     }
341*7abd0fb2Slogwang     argc -= optind;
342*7abd0fb2Slogwang     argv += optind;
343*7abd0fb2Slogwang 
344*7abd0fb2Slogwang     if (Nflag && nflag)
345*7abd0fb2Slogwang         usage();
346*7abd0fb2Slogwang     if (aflag && argc == 0)
347*7abd0fb2Slogwang         exit(sysctl_all(0, 0));
348*7abd0fb2Slogwang     if (argc == 0 && conffile == NULL)
349*7abd0fb2Slogwang         usage();
350*7abd0fb2Slogwang 
351*7abd0fb2Slogwang     warncount = 0;
352*7abd0fb2Slogwang     if (conffile != NULL)
353*7abd0fb2Slogwang         warncount += parsefile(conffile);
354*7abd0fb2Slogwang 
355*7abd0fb2Slogwang     while (argc-- > 0)
356*7abd0fb2Slogwang         warncount += parse(*argv++, 0);
357*7abd0fb2Slogwang 
358*7abd0fb2Slogwang     return (warncount);
359*7abd0fb2Slogwang }
360*7abd0fb2Slogwang 
361*7abd0fb2Slogwang /*
362*7abd0fb2Slogwang  * Parse a name into a MIB entry.
363*7abd0fb2Slogwang  * Lookup and print out the MIB entry if it exists.
364*7abd0fb2Slogwang  * Set a new value if requested.
365*7abd0fb2Slogwang  */
366*7abd0fb2Slogwang static int
367*7abd0fb2Slogwang parse(const char *string, int lineno)
368*7abd0fb2Slogwang {
369*7abd0fb2Slogwang     int len, i, j;
370*7abd0fb2Slogwang     const void *newval;
371*7abd0fb2Slogwang     const char *newvalstr = NULL;
372*7abd0fb2Slogwang     int8_t i8val;
373*7abd0fb2Slogwang     uint8_t u8val;
374*7abd0fb2Slogwang     int16_t i16val;
375*7abd0fb2Slogwang     uint16_t u16val;
376*7abd0fb2Slogwang     int32_t i32val;
377*7abd0fb2Slogwang     uint32_t u32val;
378*7abd0fb2Slogwang     int intval;
379*7abd0fb2Slogwang     unsigned int uintval;
380*7abd0fb2Slogwang     long longval;
381*7abd0fb2Slogwang     unsigned long ulongval;
382*7abd0fb2Slogwang     size_t newsize = Bflag;
383*7abd0fb2Slogwang     int64_t i64val;
384*7abd0fb2Slogwang     uint64_t u64val;
385*7abd0fb2Slogwang     int mib[CTL_MAXNAME];
386*7abd0fb2Slogwang     char *cp, *bufp, buf[BUFSIZ], *endptr = NULL, fmt[BUFSIZ], line[BUFSIZ];
387*7abd0fb2Slogwang     u_int kind;
388*7abd0fb2Slogwang 
389*7abd0fb2Slogwang     if (lineno)
390*7abd0fb2Slogwang         snprintf(line, sizeof(line), " at line %d", lineno);
391*7abd0fb2Slogwang     else
392*7abd0fb2Slogwang         line[0] = '\0';
393*7abd0fb2Slogwang 
394*7abd0fb2Slogwang     cp = buf;
395*7abd0fb2Slogwang     if (snprintf(buf, BUFSIZ, "%s", string) >= BUFSIZ) {
396*7abd0fb2Slogwang         warnx("oid too long: '%s'%s", string, line);
397*7abd0fb2Slogwang         return (1);
398*7abd0fb2Slogwang     }
399*7abd0fb2Slogwang     bufp = strsep(&cp, "=:");
400*7abd0fb2Slogwang     if (cp != NULL) {
401*7abd0fb2Slogwang         /* Tflag just lists tunables, do not allow assignment */
402*7abd0fb2Slogwang         if (Tflag || Wflag) {
403*7abd0fb2Slogwang             warnx("Can't set variables when using -T or -W");
404*7abd0fb2Slogwang             usage();
405*7abd0fb2Slogwang         }
406*7abd0fb2Slogwang         while (isspace(*cp))
407*7abd0fb2Slogwang             cp++;
408*7abd0fb2Slogwang         /* Strip a pair of " or ' if any. */
409*7abd0fb2Slogwang         switch (*cp) {
410*7abd0fb2Slogwang         case '\"':
411*7abd0fb2Slogwang         case '\'':
412*7abd0fb2Slogwang             if (cp[strlen(cp) - 1] == *cp)
413*7abd0fb2Slogwang                 cp[strlen(cp) - 1] = '\0';
414*7abd0fb2Slogwang             cp++;
415*7abd0fb2Slogwang         }
416*7abd0fb2Slogwang         newvalstr = cp;
417*7abd0fb2Slogwang         newsize = strlen(cp);
418*7abd0fb2Slogwang     }
419*7abd0fb2Slogwang     /* Trim spaces */
420*7abd0fb2Slogwang     cp = bufp + strlen(bufp) - 1;
421*7abd0fb2Slogwang     while (cp >= bufp && isspace((int)*cp)) {
422*7abd0fb2Slogwang         *cp = '\0';
423*7abd0fb2Slogwang         cp--;
424*7abd0fb2Slogwang     }
425*7abd0fb2Slogwang     len = name2oid(bufp, mib);
426*7abd0fb2Slogwang 
427*7abd0fb2Slogwang     if (len < 0) {
428*7abd0fb2Slogwang         if (iflag)
429*7abd0fb2Slogwang             return (0);
430*7abd0fb2Slogwang         if (qflag)
431*7abd0fb2Slogwang             return (1);
432*7abd0fb2Slogwang         else {
433*7abd0fb2Slogwang             if (errno == ENOENT) {
434*7abd0fb2Slogwang                 warnx("unknown oid '%s'%s", bufp, line);
435*7abd0fb2Slogwang             } else {
436*7abd0fb2Slogwang                 warn("unknown oid '%s'%s", bufp, line);
437*7abd0fb2Slogwang             }
438*7abd0fb2Slogwang             return (1);
439*7abd0fb2Slogwang         }
440*7abd0fb2Slogwang     }
441*7abd0fb2Slogwang 
442*7abd0fb2Slogwang     if (oidfmt(mib, len, fmt, &kind)) {
443*7abd0fb2Slogwang         warn("couldn't find format of oid '%s'%s", bufp, line);
444*7abd0fb2Slogwang         if (iflag)
445*7abd0fb2Slogwang             return (1);
446*7abd0fb2Slogwang         else
447*7abd0fb2Slogwang             exit(1);
448*7abd0fb2Slogwang     }
449*7abd0fb2Slogwang 
450*7abd0fb2Slogwang     if (newvalstr == NULL || dflag) {
451*7abd0fb2Slogwang         if ((kind & CTLTYPE) == CTLTYPE_NODE) {
452*7abd0fb2Slogwang             if (dflag) {
453*7abd0fb2Slogwang                 i = show_var(mib, len);
454*7abd0fb2Slogwang                 if (!i && !bflag)
455*7abd0fb2Slogwang                     putchar('\n');
456*7abd0fb2Slogwang             }
457*7abd0fb2Slogwang             sysctl_all(mib, len);
458*7abd0fb2Slogwang         } else {
459*7abd0fb2Slogwang             i = show_var(mib, len);
460*7abd0fb2Slogwang             if (!i && !bflag)
461*7abd0fb2Slogwang                 putchar('\n');
462*7abd0fb2Slogwang         }
463*7abd0fb2Slogwang     } else {
464*7abd0fb2Slogwang         if ((kind & CTLTYPE) == CTLTYPE_NODE) {
465*7abd0fb2Slogwang             warnx("oid '%s' isn't a leaf node%s", bufp, line);
466*7abd0fb2Slogwang             return (1);
467*7abd0fb2Slogwang         }
468*7abd0fb2Slogwang 
469*7abd0fb2Slogwang         if (!(kind & CTLFLAG_WR)) {
470*7abd0fb2Slogwang             if (kind & CTLFLAG_TUN) {
471*7abd0fb2Slogwang                 warnx("oid '%s' is a read only tunable%s", bufp, line);
472*7abd0fb2Slogwang                 warnx("Tunable values are set in /boot/loader.conf");
473*7abd0fb2Slogwang             } else
474*7abd0fb2Slogwang                 warnx("oid '%s' is read only%s", bufp, line);
475*7abd0fb2Slogwang             return (1);
476*7abd0fb2Slogwang         }
477*7abd0fb2Slogwang 
478*7abd0fb2Slogwang         switch (kind & CTLTYPE) {
479*7abd0fb2Slogwang         case CTLTYPE_INT:
480*7abd0fb2Slogwang         case CTLTYPE_UINT:
481*7abd0fb2Slogwang         case CTLTYPE_LONG:
482*7abd0fb2Slogwang         case CTLTYPE_ULONG:
483*7abd0fb2Slogwang         case CTLTYPE_S8:
484*7abd0fb2Slogwang         case CTLTYPE_S16:
485*7abd0fb2Slogwang         case CTLTYPE_S32:
486*7abd0fb2Slogwang         case CTLTYPE_S64:
487*7abd0fb2Slogwang         case CTLTYPE_U8:
488*7abd0fb2Slogwang         case CTLTYPE_U16:
489*7abd0fb2Slogwang         case CTLTYPE_U32:
490*7abd0fb2Slogwang         case CTLTYPE_U64:
491*7abd0fb2Slogwang             if (strlen(newvalstr) == 0) {
492*7abd0fb2Slogwang                 warnx("empty numeric value");
493*7abd0fb2Slogwang                 return (1);
494*7abd0fb2Slogwang             }
495*7abd0fb2Slogwang             /* FALLTHROUGH */
496*7abd0fb2Slogwang         case CTLTYPE_STRING:
497*7abd0fb2Slogwang             break;
498*7abd0fb2Slogwang         default:
499*7abd0fb2Slogwang             warnx("oid '%s' is type %d,"
500*7abd0fb2Slogwang                 " cannot set that%s", bufp,
501*7abd0fb2Slogwang                 kind & CTLTYPE, line);
502*7abd0fb2Slogwang             return (1);
503*7abd0fb2Slogwang         }
504*7abd0fb2Slogwang 
505*7abd0fb2Slogwang         errno = 0;
506*7abd0fb2Slogwang 
507*7abd0fb2Slogwang         switch (kind & CTLTYPE) {
508*7abd0fb2Slogwang             case CTLTYPE_INT:
509*7abd0fb2Slogwang                 if (strncmp(fmt, "IK", 2) == 0)
510*7abd0fb2Slogwang                     intval = strIKtoi(newvalstr, &endptr, fmt);
511*7abd0fb2Slogwang                 else
512*7abd0fb2Slogwang                     intval = (int)strtol(newvalstr, &endptr,
513*7abd0fb2Slogwang                         0);
514*7abd0fb2Slogwang                 newval = &intval;
515*7abd0fb2Slogwang                 newsize = sizeof(intval);
516*7abd0fb2Slogwang                 break;
517*7abd0fb2Slogwang             case CTLTYPE_UINT:
518*7abd0fb2Slogwang                 uintval = (int) strtoul(newvalstr, &endptr, 0);
519*7abd0fb2Slogwang                 newval = &uintval;
520*7abd0fb2Slogwang                 newsize = sizeof(uintval);
521*7abd0fb2Slogwang                 break;
522*7abd0fb2Slogwang             case CTLTYPE_LONG:
523*7abd0fb2Slogwang                 longval = strtol(newvalstr, &endptr, 0);
524*7abd0fb2Slogwang                 newval = &longval;
525*7abd0fb2Slogwang                 newsize = sizeof(longval);
526*7abd0fb2Slogwang                 break;
527*7abd0fb2Slogwang             case CTLTYPE_ULONG:
528*7abd0fb2Slogwang                 ulongval = strtoul(newvalstr, &endptr, 0);
529*7abd0fb2Slogwang                 newval = &ulongval;
530*7abd0fb2Slogwang                 newsize = sizeof(ulongval);
531*7abd0fb2Slogwang                 break;
532*7abd0fb2Slogwang             case CTLTYPE_STRING:
533*7abd0fb2Slogwang                 newval = newvalstr;
534*7abd0fb2Slogwang                 break;
535*7abd0fb2Slogwang             case CTLTYPE_S8:
536*7abd0fb2Slogwang                 i8val = (int8_t)strtol(newvalstr, &endptr, 0);
537*7abd0fb2Slogwang                 newval = &i8val;
538*7abd0fb2Slogwang                 newsize = sizeof(i8val);
539*7abd0fb2Slogwang                 break;
540*7abd0fb2Slogwang             case CTLTYPE_S16:
541*7abd0fb2Slogwang                 i16val = (int16_t)strtol(newvalstr, &endptr,
542*7abd0fb2Slogwang                     0);
543*7abd0fb2Slogwang                 newval = &i16val;
544*7abd0fb2Slogwang                 newsize = sizeof(i16val);
545*7abd0fb2Slogwang                 break;
546*7abd0fb2Slogwang             case CTLTYPE_S32:
547*7abd0fb2Slogwang                 i32val = (int32_t)strtol(newvalstr, &endptr,
548*7abd0fb2Slogwang                     0);
549*7abd0fb2Slogwang                 newval = &i32val;
550*7abd0fb2Slogwang                 newsize = sizeof(i32val);
551*7abd0fb2Slogwang                 break;
552*7abd0fb2Slogwang             case CTLTYPE_S64:
553*7abd0fb2Slogwang                 i64val = strtoimax(newvalstr, &endptr, 0);
554*7abd0fb2Slogwang                 newval = &i64val;
555*7abd0fb2Slogwang                 newsize = sizeof(i64val);
556*7abd0fb2Slogwang                 break;
557*7abd0fb2Slogwang             case CTLTYPE_U8:
558*7abd0fb2Slogwang                 u8val = (uint8_t)strtoul(newvalstr, &endptr, 0);
559*7abd0fb2Slogwang                 newval = &u8val;
560*7abd0fb2Slogwang                 newsize = sizeof(u8val);
561*7abd0fb2Slogwang                 break;
562*7abd0fb2Slogwang             case CTLTYPE_U16:
563*7abd0fb2Slogwang                 u16val = (uint16_t)strtoul(newvalstr, &endptr,
564*7abd0fb2Slogwang                     0);
565*7abd0fb2Slogwang                 newval = &u16val;
566*7abd0fb2Slogwang                 newsize = sizeof(u16val);
567*7abd0fb2Slogwang                 break;
568*7abd0fb2Slogwang             case CTLTYPE_U32:
569*7abd0fb2Slogwang                 u32val = (uint32_t)strtoul(newvalstr, &endptr,
570*7abd0fb2Slogwang                     0);
571*7abd0fb2Slogwang                 newval = &u32val;
572*7abd0fb2Slogwang                 newsize = sizeof(u32val);
573*7abd0fb2Slogwang                 break;
574*7abd0fb2Slogwang             case CTLTYPE_U64:
575*7abd0fb2Slogwang                 u64val = strtoumax(newvalstr, &endptr, 0);
576*7abd0fb2Slogwang                 newval = &u64val;
577*7abd0fb2Slogwang                 newsize = sizeof(u64val);
578*7abd0fb2Slogwang                 break;
579*7abd0fb2Slogwang             default:
580*7abd0fb2Slogwang                 /* NOTREACHED */
581*7abd0fb2Slogwang                 abort();
582*7abd0fb2Slogwang         }
583*7abd0fb2Slogwang 
584*7abd0fb2Slogwang         if (errno != 0 || endptr == newvalstr ||
585*7abd0fb2Slogwang             (endptr != NULL && *endptr != '\0')) {
586*7abd0fb2Slogwang             warnx("invalid %s '%s'%s", ctl_typename[kind & CTLTYPE],
587*7abd0fb2Slogwang                 newvalstr, line);
588*7abd0fb2Slogwang             return (1);
589*7abd0fb2Slogwang         }
590*7abd0fb2Slogwang 
591*7abd0fb2Slogwang         i = show_var(mib, len);
592*7abd0fb2Slogwang         if (sysctl_ipc(mib, len, 0, 0, newval, newsize) == -1) {
593*7abd0fb2Slogwang             if (!i && !bflag)
594*7abd0fb2Slogwang                 putchar('\n');
595*7abd0fb2Slogwang             switch (errno) {
596*7abd0fb2Slogwang             case EOPNOTSUPP:
597*7abd0fb2Slogwang                 warnx("%s: value is not available%s",
598*7abd0fb2Slogwang                     string, line);
599*7abd0fb2Slogwang                 return (1);
600*7abd0fb2Slogwang             case ENOTDIR:
601*7abd0fb2Slogwang                 warnx("%s: specification is incomplete%s",
602*7abd0fb2Slogwang                     string, line);
603*7abd0fb2Slogwang                 return (1);
604*7abd0fb2Slogwang             case ENOMEM:
605*7abd0fb2Slogwang                 warnx("%s: type is unknown to this program%s",
606*7abd0fb2Slogwang                     string, line);
607*7abd0fb2Slogwang                 return (1);
608*7abd0fb2Slogwang             default:
609*7abd0fb2Slogwang                 warn("%s%s", string, line);
610*7abd0fb2Slogwang                 return (1);
611*7abd0fb2Slogwang             }
612*7abd0fb2Slogwang         }
613*7abd0fb2Slogwang         if (!bflag)
614*7abd0fb2Slogwang             printf(" -> ");
615*7abd0fb2Slogwang         i = nflag;
616*7abd0fb2Slogwang         nflag = 1;
617*7abd0fb2Slogwang         j = show_var(mib, len);
618*7abd0fb2Slogwang         if (!j && !bflag)
619*7abd0fb2Slogwang             putchar('\n');
620*7abd0fb2Slogwang         nflag = i;
621*7abd0fb2Slogwang     }
622*7abd0fb2Slogwang 
623*7abd0fb2Slogwang     return (0);
624*7abd0fb2Slogwang }
625*7abd0fb2Slogwang 
626*7abd0fb2Slogwang static int
627*7abd0fb2Slogwang parsefile(const char *filename)
628*7abd0fb2Slogwang {
629*7abd0fb2Slogwang     FILE *file;
630*7abd0fb2Slogwang     char line[BUFSIZ], *p, *pq, *pdq;
631*7abd0fb2Slogwang     int warncount = 0, lineno = 0;
632*7abd0fb2Slogwang 
633*7abd0fb2Slogwang     file = fopen(filename, "r");
634*7abd0fb2Slogwang     if (file == NULL)
635*7abd0fb2Slogwang         err(EX_NOINPUT, "%s", filename);
636*7abd0fb2Slogwang     while (fgets(line, sizeof(line), file) != NULL) {
637*7abd0fb2Slogwang         lineno++;
638*7abd0fb2Slogwang         p = line;
639*7abd0fb2Slogwang         pq = strchr(line, '\'');
640*7abd0fb2Slogwang         pdq = strchr(line, '\"');
641*7abd0fb2Slogwang         /* Replace the first # with \0. */
642*7abd0fb2Slogwang         while((p = strchr(p, '#')) != NULL) {
643*7abd0fb2Slogwang             if (pq != NULL && p > pq) {
644*7abd0fb2Slogwang                 if ((p = strchr(pq+1, '\'')) != NULL)
645*7abd0fb2Slogwang                     *(++p) = '\0';
646*7abd0fb2Slogwang                 break;
647*7abd0fb2Slogwang             } else if (pdq != NULL && p > pdq) {
648*7abd0fb2Slogwang                 if ((p = strchr(pdq+1, '\"')) != NULL)
649*7abd0fb2Slogwang                     *(++p) = '\0';
650*7abd0fb2Slogwang                 break;
651*7abd0fb2Slogwang             } else if (p == line || *(p-1) != '\\') {
652*7abd0fb2Slogwang                 *p = '\0';
653*7abd0fb2Slogwang                 break;
654*7abd0fb2Slogwang             }
655*7abd0fb2Slogwang             p++;
656*7abd0fb2Slogwang         }
657*7abd0fb2Slogwang         /* Trim spaces */
658*7abd0fb2Slogwang         p = line + strlen(line) - 1;
659*7abd0fb2Slogwang         while (p >= line && isspace((int)*p)) {
660*7abd0fb2Slogwang             *p = '\0';
661*7abd0fb2Slogwang             p--;
662*7abd0fb2Slogwang         }
663*7abd0fb2Slogwang         p = line;
664*7abd0fb2Slogwang         while (isspace((int)*p))
665*7abd0fb2Slogwang             p++;
666*7abd0fb2Slogwang         if (*p == '\0')
667*7abd0fb2Slogwang             continue;
668*7abd0fb2Slogwang         else
669*7abd0fb2Slogwang             warncount += parse(p, lineno);
670*7abd0fb2Slogwang     }
671*7abd0fb2Slogwang     fclose(file);
672*7abd0fb2Slogwang 
673*7abd0fb2Slogwang     return (warncount);
674*7abd0fb2Slogwang }
675*7abd0fb2Slogwang 
676*7abd0fb2Slogwang /* These functions will dump out various interesting structures. */
677*7abd0fb2Slogwang 
678*7abd0fb2Slogwang static int
679*7abd0fb2Slogwang S_clockinfo(size_t l2, void *p)
680*7abd0fb2Slogwang {
681*7abd0fb2Slogwang     struct clockinfo *ci = (struct clockinfo*)p;
682*7abd0fb2Slogwang 
683*7abd0fb2Slogwang     if (l2 != sizeof(*ci)) {
684*7abd0fb2Slogwang         warnx("S_clockinfo %zu != %zu", l2, sizeof(*ci));
685*7abd0fb2Slogwang         return (1);
686*7abd0fb2Slogwang     }
687*7abd0fb2Slogwang     printf(hflag ? "{ hz = %'d, tick = %'d, profhz = %'d, stathz = %'d }" :
688*7abd0fb2Slogwang         "{ hz = %d, tick = %d, profhz = %d, stathz = %d }",
689*7abd0fb2Slogwang         ci->hz, ci->tick, ci->profhz, ci->stathz);
690*7abd0fb2Slogwang     return (0);
691*7abd0fb2Slogwang }
692*7abd0fb2Slogwang 
693*7abd0fb2Slogwang static int
694*7abd0fb2Slogwang S_loadavg(size_t l2, void *p)
695*7abd0fb2Slogwang {
696*7abd0fb2Slogwang     struct loadavg *tv = (struct loadavg*)p;
697*7abd0fb2Slogwang 
698*7abd0fb2Slogwang     if (l2 != sizeof(*tv)) {
699*7abd0fb2Slogwang         warnx("S_loadavg %zu != %zu", l2, sizeof(*tv));
700*7abd0fb2Slogwang         return (1);
701*7abd0fb2Slogwang     }
702*7abd0fb2Slogwang     printf(hflag ? "{ %'.2f %'.2f %'.2f }" : "{ %.2f %.2f %.2f }",
703*7abd0fb2Slogwang         (double)tv->ldavg[0]/(double)tv->fscale,
704*7abd0fb2Slogwang         (double)tv->ldavg[1]/(double)tv->fscale,
705*7abd0fb2Slogwang         (double)tv->ldavg[2]/(double)tv->fscale);
706*7abd0fb2Slogwang     return (0);
707*7abd0fb2Slogwang }
708*7abd0fb2Slogwang 
709*7abd0fb2Slogwang static int
710*7abd0fb2Slogwang S_timeval(size_t l2, void *p)
711*7abd0fb2Slogwang {
712*7abd0fb2Slogwang     struct timeval *tv = (struct timeval*)p;
713*7abd0fb2Slogwang     time_t tv_sec;
714*7abd0fb2Slogwang     char *p1, *p2;
715*7abd0fb2Slogwang 
716*7abd0fb2Slogwang     if (l2 != sizeof(*tv)) {
717*7abd0fb2Slogwang         warnx("S_timeval %zu != %zu", l2, sizeof(*tv));
718*7abd0fb2Slogwang         return (1);
719*7abd0fb2Slogwang     }
720*7abd0fb2Slogwang     printf(hflag ? "{ sec = %'jd, usec = %'ld } " :
721*7abd0fb2Slogwang         "{ sec = %jd, usec = %ld } ",
722*7abd0fb2Slogwang         (intmax_t)tv->tv_sec, tv->tv_usec);
723*7abd0fb2Slogwang     tv_sec = tv->tv_sec;
724*7abd0fb2Slogwang     p1 = strdup(ctime(&tv_sec));
725*7abd0fb2Slogwang     for (p2=p1; *p2 ; p2++)
726*7abd0fb2Slogwang         if (*p2 == '\n')
727*7abd0fb2Slogwang             *p2 = '\0';
728*7abd0fb2Slogwang     fputs(p1, stdout);
729*7abd0fb2Slogwang     free(p1);
730*7abd0fb2Slogwang     return (0);
731*7abd0fb2Slogwang }
732*7abd0fb2Slogwang 
733*7abd0fb2Slogwang static int
734*7abd0fb2Slogwang S_vmtotal(size_t l2, void *p)
735*7abd0fb2Slogwang {
736*7abd0fb2Slogwang     struct vmtotal *v = (struct vmtotal *)p;
737*7abd0fb2Slogwang     int pageKilo = getpagesize() / 1024;
738*7abd0fb2Slogwang 
739*7abd0fb2Slogwang     if (l2 != sizeof(*v)) {
740*7abd0fb2Slogwang         warnx("S_vmtotal %zu != %zu", l2, sizeof(*v));
741*7abd0fb2Slogwang         return (1);
742*7abd0fb2Slogwang     }
743*7abd0fb2Slogwang 
744*7abd0fb2Slogwang     printf(
745*7abd0fb2Slogwang         "\nSystem wide totals computed every five seconds:"
746*7abd0fb2Slogwang         " (values in kilobytes)\n");
747*7abd0fb2Slogwang     printf("===============================================\n");
748*7abd0fb2Slogwang     printf(
749*7abd0fb2Slogwang         "Processes:\t\t(RUNQ: %hd Disk Wait: %hd Page Wait: "
750*7abd0fb2Slogwang         "%hd Sleep: %hd)\n",
751*7abd0fb2Slogwang         v->t_rq, v->t_dw, v->t_pw, v->t_sl);
752*7abd0fb2Slogwang     printf(
753*7abd0fb2Slogwang         "Virtual Memory:\t\t(Total: %jdK Active: %jdK)\n",
754*7abd0fb2Slogwang         (intmax_t)v->t_vm * pageKilo, (intmax_t)v->t_avm * pageKilo);
755*7abd0fb2Slogwang     printf("Real Memory:\t\t(Total: %jdK Active: %jdK)\n",
756*7abd0fb2Slogwang         (intmax_t)v->t_rm * pageKilo, (intmax_t)v->t_arm * pageKilo);
757*7abd0fb2Slogwang     printf("Shared Virtual Memory:\t(Total: %jdK Active: %jdK)\n",
758*7abd0fb2Slogwang         (intmax_t)v->t_vmshr * pageKilo, (intmax_t)v->t_avmshr * pageKilo);
759*7abd0fb2Slogwang     printf("Shared Real Memory:\t(Total: %jdK Active: %jdK)\n",
760*7abd0fb2Slogwang         (intmax_t)v->t_rmshr * pageKilo, (intmax_t)v->t_armshr * pageKilo);
761*7abd0fb2Slogwang     printf("Free Memory:\t%jdK", (intmax_t)v->t_free * pageKilo);
762*7abd0fb2Slogwang 
763*7abd0fb2Slogwang     return (0);
764*7abd0fb2Slogwang }
765*7abd0fb2Slogwang 
766*7abd0fb2Slogwang #ifdef __amd64__
767*7abd0fb2Slogwang #define efi_next_descriptor(ptr, size) \
768*7abd0fb2Slogwang     ((struct efi_md *)(((uint8_t *) ptr) + size))
769*7abd0fb2Slogwang 
770*7abd0fb2Slogwang static int
771*7abd0fb2Slogwang S_efi_map(size_t l2, void *p)
772*7abd0fb2Slogwang {
773*7abd0fb2Slogwang     struct efi_map_header *efihdr;
774*7abd0fb2Slogwang     struct efi_md *map;
775*7abd0fb2Slogwang     const char *type;
776*7abd0fb2Slogwang     size_t efisz;
777*7abd0fb2Slogwang     int ndesc, i;
778*7abd0fb2Slogwang 
779*7abd0fb2Slogwang     static const char *types[] = {
780*7abd0fb2Slogwang         "Reserved",
781*7abd0fb2Slogwang         "LoaderCode",
782*7abd0fb2Slogwang         "LoaderData",
783*7abd0fb2Slogwang         "BootServicesCode",
784*7abd0fb2Slogwang         "BootServicesData",
785*7abd0fb2Slogwang         "RuntimeServicesCode",
786*7abd0fb2Slogwang         "RuntimeServicesData",
787*7abd0fb2Slogwang         "ConventionalMemory",
788*7abd0fb2Slogwang         "UnusableMemory",
789*7abd0fb2Slogwang         "ACPIReclaimMemory",
790*7abd0fb2Slogwang         "ACPIMemoryNVS",
791*7abd0fb2Slogwang         "MemoryMappedIO",
792*7abd0fb2Slogwang         "MemoryMappedIOPortSpace",
793*7abd0fb2Slogwang         "PalCode"
794*7abd0fb2Slogwang     };
795*7abd0fb2Slogwang 
796*7abd0fb2Slogwang     /*
797*7abd0fb2Slogwang      * Memory map data provided by UEFI via the GetMemoryMap
798*7abd0fb2Slogwang      * Boot Services API.
799*7abd0fb2Slogwang      */
800*7abd0fb2Slogwang     if (l2 < sizeof(*efihdr)) {
801*7abd0fb2Slogwang         warnx("S_efi_map length less than header");
802*7abd0fb2Slogwang         return (1);
803*7abd0fb2Slogwang     }
804*7abd0fb2Slogwang     efihdr = p;
805*7abd0fb2Slogwang     efisz = (sizeof(struct efi_map_header) + 0xf) & ~0xf;
806*7abd0fb2Slogwang     map = (struct efi_md *)((uint8_t *)efihdr + efisz);
807*7abd0fb2Slogwang 
808*7abd0fb2Slogwang     if (efihdr->descriptor_size == 0)
809*7abd0fb2Slogwang         return (0);
810*7abd0fb2Slogwang     if (l2 != efisz + efihdr->memory_size) {
811*7abd0fb2Slogwang         warnx("S_efi_map length mismatch %zu vs %zu", l2, efisz +
812*7abd0fb2Slogwang             efihdr->memory_size);
813*7abd0fb2Slogwang         return (1);
814*7abd0fb2Slogwang     }
815*7abd0fb2Slogwang     ndesc = efihdr->memory_size / efihdr->descriptor_size;
816*7abd0fb2Slogwang 
817*7abd0fb2Slogwang     printf("\n%23s %12s %12s %8s %4s",
818*7abd0fb2Slogwang         "Type", "Physical", "Virtual", "#Pages", "Attr");
819*7abd0fb2Slogwang 
820*7abd0fb2Slogwang     for (i = 0; i < ndesc; i++,
821*7abd0fb2Slogwang         map = efi_next_descriptor(map, efihdr->descriptor_size)) {
822*7abd0fb2Slogwang         if (map->md_type <= EFI_MD_TYPE_PALCODE)
823*7abd0fb2Slogwang             type = types[map->md_type];
824*7abd0fb2Slogwang         else
825*7abd0fb2Slogwang             type = "<INVALID>";
826*7abd0fb2Slogwang         printf("\n%23s %012lx %12p %08lx ", type, map->md_phys,
827*7abd0fb2Slogwang             map->md_virt, map->md_pages);
828*7abd0fb2Slogwang         if (map->md_attr & EFI_MD_ATTR_UC)
829*7abd0fb2Slogwang             printf("UC ");
830*7abd0fb2Slogwang         if (map->md_attr & EFI_MD_ATTR_WC)
831*7abd0fb2Slogwang             printf("WC ");
832*7abd0fb2Slogwang         if (map->md_attr & EFI_MD_ATTR_WT)
833*7abd0fb2Slogwang             printf("WT ");
834*7abd0fb2Slogwang         if (map->md_attr & EFI_MD_ATTR_WB)
835*7abd0fb2Slogwang             printf("WB ");
836*7abd0fb2Slogwang         if (map->md_attr & EFI_MD_ATTR_UCE)
837*7abd0fb2Slogwang             printf("UCE ");
838*7abd0fb2Slogwang         if (map->md_attr & EFI_MD_ATTR_WP)
839*7abd0fb2Slogwang             printf("WP ");
840*7abd0fb2Slogwang         if (map->md_attr & EFI_MD_ATTR_RP)
841*7abd0fb2Slogwang             printf("RP ");
842*7abd0fb2Slogwang         if (map->md_attr & EFI_MD_ATTR_XP)
843*7abd0fb2Slogwang             printf("XP ");
844*7abd0fb2Slogwang         if (map->md_attr & EFI_MD_ATTR_RT)
845*7abd0fb2Slogwang             printf("RUNTIME");
846*7abd0fb2Slogwang     }
847*7abd0fb2Slogwang     return (0);
848*7abd0fb2Slogwang }
849*7abd0fb2Slogwang #endif
850*7abd0fb2Slogwang 
851*7abd0fb2Slogwang #if defined(__amd64__) || defined(__i386__)
852*7abd0fb2Slogwang static int
853*7abd0fb2Slogwang S_bios_smap_xattr(size_t l2, void *p)
854*7abd0fb2Slogwang {
855*7abd0fb2Slogwang     struct bios_smap_xattr *smap, *end;
856*7abd0fb2Slogwang 
857*7abd0fb2Slogwang     if (l2 % sizeof(*smap) != 0) {
858*7abd0fb2Slogwang         warnx("S_bios_smap_xattr %zu is not a multiple of %zu", l2,
859*7abd0fb2Slogwang             sizeof(*smap));
860*7abd0fb2Slogwang         return (1);
861*7abd0fb2Slogwang     }
862*7abd0fb2Slogwang 
863*7abd0fb2Slogwang     end = (struct bios_smap_xattr *)((char *)p + l2);
864*7abd0fb2Slogwang     for (smap = p; smap < end; smap++)
865*7abd0fb2Slogwang         printf("\nSMAP type=%02x, xattr=%02x, base=%016jx, len=%016jx",
866*7abd0fb2Slogwang             smap->type, smap->xattr, (uintmax_t)smap->base,
867*7abd0fb2Slogwang             (uintmax_t)smap->length);
868*7abd0fb2Slogwang     return (0);
869*7abd0fb2Slogwang }
870*7abd0fb2Slogwang #endif
871*7abd0fb2Slogwang 
872*7abd0fb2Slogwang static int
873*7abd0fb2Slogwang strIKtoi(const char *str, char **endptrp, const char *fmt)
874*7abd0fb2Slogwang {
875*7abd0fb2Slogwang     int kelv;
876*7abd0fb2Slogwang     float temp;
877*7abd0fb2Slogwang     size_t len;
878*7abd0fb2Slogwang     const char *p;
879*7abd0fb2Slogwang     int prec, i;
880*7abd0fb2Slogwang 
881*7abd0fb2Slogwang     assert(errno == 0);
882*7abd0fb2Slogwang 
883*7abd0fb2Slogwang     len = strlen(str);
884*7abd0fb2Slogwang     /* caller already checked this */
885*7abd0fb2Slogwang     assert(len > 0);
886*7abd0fb2Slogwang 
887*7abd0fb2Slogwang     /*
888*7abd0fb2Slogwang      * A format of "IK" is in deciKelvin. A format of "IK3" is in
889*7abd0fb2Slogwang      * milliKelvin. The single digit following IK is log10 of the
890*7abd0fb2Slogwang      * multiplying factor to convert Kelvin into the untis of this sysctl,
891*7abd0fb2Slogwang      * or the dividing factor to convert the sysctl value to Kelvin. Numbers
892*7abd0fb2Slogwang      * larger than 6 will run into precision issues with 32-bit integers.
893*7abd0fb2Slogwang      * Characters that aren't ASCII digits after the 'K' are ignored. No
894*7abd0fb2Slogwang      * localization is present because this is an interface from the kernel
895*7abd0fb2Slogwang      * to this program (eg not an end-user interface), so isdigit() isn't
896*7abd0fb2Slogwang      * used here.
897*7abd0fb2Slogwang      */
898*7abd0fb2Slogwang     if (fmt[2] != '\0' && fmt[2] >= '0' && fmt[2] <= '9')
899*7abd0fb2Slogwang         prec = fmt[2] - '0';
900*7abd0fb2Slogwang     else
901*7abd0fb2Slogwang         prec = 1;
902*7abd0fb2Slogwang     p = &str[len - 1];
903*7abd0fb2Slogwang     if (*p == 'C' || *p == 'F' || *p == 'K') {
904*7abd0fb2Slogwang         temp = strtof(str, endptrp);
905*7abd0fb2Slogwang         if (*endptrp != str && *endptrp == p && errno == 0) {
906*7abd0fb2Slogwang             if (*p == 'F')
907*7abd0fb2Slogwang                 temp = (temp - 32) * 5 / 9;
908*7abd0fb2Slogwang             *endptrp = NULL;
909*7abd0fb2Slogwang             if (*p != 'K')
910*7abd0fb2Slogwang                 temp += 273.15;
911*7abd0fb2Slogwang             for (i = 0; i < prec; i++)
912*7abd0fb2Slogwang                 temp *= 10.0;
913*7abd0fb2Slogwang             return ((int)(temp + 0.5));
914*7abd0fb2Slogwang         }
915*7abd0fb2Slogwang     } else {
916*7abd0fb2Slogwang         /* No unit specified -> treat it as a raw number */
917*7abd0fb2Slogwang         kelv = (int)strtol(str, endptrp, 10);
918*7abd0fb2Slogwang         if (*endptrp != str && *endptrp == p && errno == 0) {
919*7abd0fb2Slogwang             *endptrp = NULL;
920*7abd0fb2Slogwang             return (kelv);
921*7abd0fb2Slogwang         }
922*7abd0fb2Slogwang     }
923*7abd0fb2Slogwang 
924*7abd0fb2Slogwang     errno = ERANGE;
925*7abd0fb2Slogwang     return (0);
926*7abd0fb2Slogwang }
927*7abd0fb2Slogwang 
928*7abd0fb2Slogwang /*
929*7abd0fb2Slogwang  * These functions uses a presently undocumented interface to the kernel
930*7abd0fb2Slogwang  * to walk the tree and get the type so it can print the value.
931*7abd0fb2Slogwang  * This interface is under work and consideration, and should probably
932*7abd0fb2Slogwang  * be killed with a big axe by the first person who can find the time.
933*7abd0fb2Slogwang  * (be aware though, that the proper interface isn't as obvious as it
934*7abd0fb2Slogwang  * may seem, there are various conflicting requirements.
935*7abd0fb2Slogwang  */
936*7abd0fb2Slogwang 
937*7abd0fb2Slogwang static int
938*7abd0fb2Slogwang name2oid(const char *name, int *oidp)
939*7abd0fb2Slogwang {
940*7abd0fb2Slogwang     int oid[2];
941*7abd0fb2Slogwang     int i;
942*7abd0fb2Slogwang     size_t j;
943*7abd0fb2Slogwang 
944*7abd0fb2Slogwang     oid[0] = 0;
945*7abd0fb2Slogwang     oid[1] = 3;
946*7abd0fb2Slogwang 
947*7abd0fb2Slogwang     j = CTL_MAXNAME * sizeof(int);
948*7abd0fb2Slogwang     i = sysctl_ipc(oid, 2, oidp, &j, name, strlen(name));
949*7abd0fb2Slogwang     if (i < 0)
950*7abd0fb2Slogwang         return (i);
951*7abd0fb2Slogwang     j /= sizeof(int);
952*7abd0fb2Slogwang     return (j);
953*7abd0fb2Slogwang }
954*7abd0fb2Slogwang 
955*7abd0fb2Slogwang static int
956*7abd0fb2Slogwang oidfmt(int *oid, int len, char *fmt, u_int *kind)
957*7abd0fb2Slogwang {
958*7abd0fb2Slogwang     int qoid[CTL_MAXNAME+2];
959*7abd0fb2Slogwang     u_char buf[BUFSIZ];
960*7abd0fb2Slogwang     int i;
961*7abd0fb2Slogwang     size_t j;
962*7abd0fb2Slogwang 
963*7abd0fb2Slogwang     qoid[0] = 0;
964*7abd0fb2Slogwang     qoid[1] = 4;
965*7abd0fb2Slogwang     memcpy(qoid + 2, oid, len * sizeof(int));
966*7abd0fb2Slogwang 
967*7abd0fb2Slogwang     j = sizeof(buf);
968*7abd0fb2Slogwang     i = sysctl_ipc(qoid, len + 2, buf, &j, 0, 0);
969*7abd0fb2Slogwang     if (i)
970*7abd0fb2Slogwang         err(1, "sysctl fmt %d %zu %d", i, j, errno);
971*7abd0fb2Slogwang 
972*7abd0fb2Slogwang     if (kind)
973*7abd0fb2Slogwang         *kind = *(u_int *)buf;
974*7abd0fb2Slogwang 
975*7abd0fb2Slogwang     if (fmt)
976*7abd0fb2Slogwang         strcpy(fmt, (char *)(buf + sizeof(u_int)));
977*7abd0fb2Slogwang     return (0);
978*7abd0fb2Slogwang }
979*7abd0fb2Slogwang 
980*7abd0fb2Slogwang /*
981*7abd0fb2Slogwang  * This formats and outputs the value of one variable
982*7abd0fb2Slogwang  *
983*7abd0fb2Slogwang  * Returns zero if anything was actually output.
984*7abd0fb2Slogwang  * Returns one if didn't know what to do with this.
985*7abd0fb2Slogwang  * Return minus one if we had errors.
986*7abd0fb2Slogwang  */
987*7abd0fb2Slogwang static int
988*7abd0fb2Slogwang show_var(int *oid, int nlen)
989*7abd0fb2Slogwang {
990*7abd0fb2Slogwang     u_char buf[BUFSIZ], *val, *oval, *p;
991*7abd0fb2Slogwang     char name[BUFSIZ], fmt[BUFSIZ];
992*7abd0fb2Slogwang     const char *sep, *sep1, *prntype;
993*7abd0fb2Slogwang     int qoid[CTL_MAXNAME+2];
994*7abd0fb2Slogwang     uintmax_t umv;
995*7abd0fb2Slogwang     intmax_t mv;
996*7abd0fb2Slogwang     int i, hexlen, sign, ctltype;
997*7abd0fb2Slogwang     size_t intlen;
998*7abd0fb2Slogwang     size_t j, len;
999*7abd0fb2Slogwang     u_int kind;
1000*7abd0fb2Slogwang     float base;
1001*7abd0fb2Slogwang     int (*func)(size_t, void *);
1002*7abd0fb2Slogwang     int prec;
1003*7abd0fb2Slogwang 
1004*7abd0fb2Slogwang     /* Silence GCC. */
1005*7abd0fb2Slogwang     umv = mv = intlen = 0;
1006*7abd0fb2Slogwang 
1007*7abd0fb2Slogwang     bzero(buf, BUFSIZ);
1008*7abd0fb2Slogwang     bzero(fmt, BUFSIZ);
1009*7abd0fb2Slogwang     bzero(name, BUFSIZ);
1010*7abd0fb2Slogwang     qoid[0] = 0;
1011*7abd0fb2Slogwang     memcpy(qoid + 2, oid, nlen * sizeof(int));
1012*7abd0fb2Slogwang 
1013*7abd0fb2Slogwang     qoid[1] = 1;
1014*7abd0fb2Slogwang     j = sizeof(name);
1015*7abd0fb2Slogwang     i = sysctl_ipc(qoid, nlen + 2, name, &j, 0, 0);
1016*7abd0fb2Slogwang     if (i || !j)
1017*7abd0fb2Slogwang         err(1, "sysctl name %d %zu %d", i, j, errno);
1018*7abd0fb2Slogwang 
1019*7abd0fb2Slogwang     oidfmt(oid, nlen, fmt, &kind);
1020*7abd0fb2Slogwang     /* if Wflag then only list sysctls that are writeable and not stats. */
1021*7abd0fb2Slogwang     if (Wflag && ((kind & CTLFLAG_WR) == 0 || (kind & CTLFLAG_STATS) != 0))
1022*7abd0fb2Slogwang         return 1;
1023*7abd0fb2Slogwang 
1024*7abd0fb2Slogwang     /* if Tflag then only list sysctls that are tuneables. */
1025*7abd0fb2Slogwang     if (Tflag && (kind & CTLFLAG_TUN) == 0)
1026*7abd0fb2Slogwang         return 1;
1027*7abd0fb2Slogwang 
1028*7abd0fb2Slogwang     if (Nflag) {
1029*7abd0fb2Slogwang         printf("%s", name);
1030*7abd0fb2Slogwang         return (0);
1031*7abd0fb2Slogwang     }
1032*7abd0fb2Slogwang 
1033*7abd0fb2Slogwang     if (eflag)
1034*7abd0fb2Slogwang         sep = "=";
1035*7abd0fb2Slogwang     else
1036*7abd0fb2Slogwang         sep = ": ";
1037*7abd0fb2Slogwang 
1038*7abd0fb2Slogwang     ctltype = (kind & CTLTYPE);
1039*7abd0fb2Slogwang     if (tflag || dflag) {
1040*7abd0fb2Slogwang         if (!nflag)
1041*7abd0fb2Slogwang             printf("%s%s", name, sep);
1042*7abd0fb2Slogwang             if (ctl_typename[ctltype] != NULL)
1043*7abd0fb2Slogwang                 prntype = ctl_typename[ctltype];
1044*7abd0fb2Slogwang             else
1045*7abd0fb2Slogwang                 prntype = "unknown";
1046*7abd0fb2Slogwang         if (tflag && dflag)
1047*7abd0fb2Slogwang             printf("%s%s", prntype, sep);
1048*7abd0fb2Slogwang         else if (tflag) {
1049*7abd0fb2Slogwang             printf("%s", prntype);
1050*7abd0fb2Slogwang             return (0);
1051*7abd0fb2Slogwang         }
1052*7abd0fb2Slogwang         qoid[1] = 5;
1053*7abd0fb2Slogwang         j = sizeof(buf);
1054*7abd0fb2Slogwang         i = sysctl_ipc(qoid, nlen + 2, buf, &j, 0, 0);
1055*7abd0fb2Slogwang         printf("%s", buf);
1056*7abd0fb2Slogwang         return (0);
1057*7abd0fb2Slogwang     }
1058*7abd0fb2Slogwang     /* find an estimate of how much we need for this var */
1059*7abd0fb2Slogwang     if (Bflag)
1060*7abd0fb2Slogwang         j = Bflag;
1061*7abd0fb2Slogwang     else {
1062*7abd0fb2Slogwang         j = 0;
1063*7abd0fb2Slogwang         i = sysctl_ipc(oid, nlen, 0, &j, 0, 0);
1064*7abd0fb2Slogwang         j += j; /* we want to be sure :-) */
1065*7abd0fb2Slogwang     }
1066*7abd0fb2Slogwang 
1067*7abd0fb2Slogwang     val = oval = malloc(j + 1);
1068*7abd0fb2Slogwang     if (val == NULL) {
1069*7abd0fb2Slogwang         warnx("malloc failed");
1070*7abd0fb2Slogwang         return (1);
1071*7abd0fb2Slogwang     }
1072*7abd0fb2Slogwang     len = j;
1073*7abd0fb2Slogwang     i = sysctl_ipc(oid, nlen, val, &len, 0, 0);
1074*7abd0fb2Slogwang     if (i != 0 || (len == 0 && ctltype != CTLTYPE_STRING)) {
1075*7abd0fb2Slogwang         free(oval);
1076*7abd0fb2Slogwang         return (1);
1077*7abd0fb2Slogwang     }
1078*7abd0fb2Slogwang 
1079*7abd0fb2Slogwang     if (bflag) {
1080*7abd0fb2Slogwang         fwrite(val, 1, len, stdout);
1081*7abd0fb2Slogwang         free(oval);
1082*7abd0fb2Slogwang         return (0);
1083*7abd0fb2Slogwang     }
1084*7abd0fb2Slogwang     val[len] = '\0';
1085*7abd0fb2Slogwang     p = val;
1086*7abd0fb2Slogwang     sign = ctl_sign[ctltype];
1087*7abd0fb2Slogwang     intlen = ctl_size[ctltype];
1088*7abd0fb2Slogwang 
1089*7abd0fb2Slogwang     switch (ctltype) {
1090*7abd0fb2Slogwang     case CTLTYPE_STRING:
1091*7abd0fb2Slogwang         if (!nflag)
1092*7abd0fb2Slogwang             printf("%s%s", name, sep);
1093*7abd0fb2Slogwang         printf("%.*s", (int)len, p);
1094*7abd0fb2Slogwang         free(oval);
1095*7abd0fb2Slogwang         return (0);
1096*7abd0fb2Slogwang 
1097*7abd0fb2Slogwang     case CTLTYPE_INT:
1098*7abd0fb2Slogwang     case CTLTYPE_UINT:
1099*7abd0fb2Slogwang     case CTLTYPE_LONG:
1100*7abd0fb2Slogwang     case CTLTYPE_ULONG:
1101*7abd0fb2Slogwang     case CTLTYPE_S8:
1102*7abd0fb2Slogwang     case CTLTYPE_S16:
1103*7abd0fb2Slogwang     case CTLTYPE_S32:
1104*7abd0fb2Slogwang     case CTLTYPE_S64:
1105*7abd0fb2Slogwang     case CTLTYPE_U8:
1106*7abd0fb2Slogwang     case CTLTYPE_U16:
1107*7abd0fb2Slogwang     case CTLTYPE_U32:
1108*7abd0fb2Slogwang     case CTLTYPE_U64:
1109*7abd0fb2Slogwang         if (!nflag)
1110*7abd0fb2Slogwang             printf("%s%s", name, sep);
1111*7abd0fb2Slogwang         hexlen = 2 + (intlen * CHAR_BIT + 3) / 4;
1112*7abd0fb2Slogwang         sep1 = "";
1113*7abd0fb2Slogwang         while (len >= intlen) {
1114*7abd0fb2Slogwang             switch (kind & CTLTYPE) {
1115*7abd0fb2Slogwang             case CTLTYPE_INT:
1116*7abd0fb2Slogwang             case CTLTYPE_UINT:
1117*7abd0fb2Slogwang                 umv = *(u_int *)p;
1118*7abd0fb2Slogwang                 mv = *(int *)p;
1119*7abd0fb2Slogwang                 break;
1120*7abd0fb2Slogwang             case CTLTYPE_LONG:
1121*7abd0fb2Slogwang             case CTLTYPE_ULONG:
1122*7abd0fb2Slogwang                 umv = *(u_long *)p;
1123*7abd0fb2Slogwang                 mv = *(long *)p;
1124*7abd0fb2Slogwang                 break;
1125*7abd0fb2Slogwang             case CTLTYPE_S8:
1126*7abd0fb2Slogwang             case CTLTYPE_U8:
1127*7abd0fb2Slogwang                 umv = *(uint8_t *)p;
1128*7abd0fb2Slogwang                 mv = *(int8_t *)p;
1129*7abd0fb2Slogwang                 break;
1130*7abd0fb2Slogwang             case CTLTYPE_S16:
1131*7abd0fb2Slogwang             case CTLTYPE_U16:
1132*7abd0fb2Slogwang                 umv = *(uint16_t *)p;
1133*7abd0fb2Slogwang                 mv = *(int16_t *)p;
1134*7abd0fb2Slogwang                 break;
1135*7abd0fb2Slogwang             case CTLTYPE_S32:
1136*7abd0fb2Slogwang             case CTLTYPE_U32:
1137*7abd0fb2Slogwang                 umv = *(uint32_t *)p;
1138*7abd0fb2Slogwang                 mv = *(int32_t *)p;
1139*7abd0fb2Slogwang                 break;
1140*7abd0fb2Slogwang             case CTLTYPE_S64:
1141*7abd0fb2Slogwang             case CTLTYPE_U64:
1142*7abd0fb2Slogwang                 umv = *(uint64_t *)p;
1143*7abd0fb2Slogwang                 mv = *(int64_t *)p;
1144*7abd0fb2Slogwang                 break;
1145*7abd0fb2Slogwang             }
1146*7abd0fb2Slogwang             fputs(sep1, stdout);
1147*7abd0fb2Slogwang             if (xflag)
1148*7abd0fb2Slogwang                 printf("%#0*jx", hexlen, umv);
1149*7abd0fb2Slogwang             else if (!sign)
1150*7abd0fb2Slogwang                 printf(hflag ? "%'ju" : "%ju", umv);
1151*7abd0fb2Slogwang             else if (fmt[1] == 'K') {
1152*7abd0fb2Slogwang                 if (mv < 0)
1153*7abd0fb2Slogwang                     printf("%jd", mv);
1154*7abd0fb2Slogwang                 else {
1155*7abd0fb2Slogwang                     /*
1156*7abd0fb2Slogwang                      * See strIKtoi for details on fmt.
1157*7abd0fb2Slogwang                      */
1158*7abd0fb2Slogwang                     int i;
1159*7abd0fb2Slogwang                     prec = 1;
1160*7abd0fb2Slogwang                     if (fmt[2] != '\0')
1161*7abd0fb2Slogwang                         prec = fmt[2] - '0';
1162*7abd0fb2Slogwang                     base = 1.0;
1163*7abd0fb2Slogwang                     for (i = 0; i < prec; i++)
1164*7abd0fb2Slogwang                         base *= 10.0;
1165*7abd0fb2Slogwang                     printf("%.*fC", prec,
1166*7abd0fb2Slogwang                         (float)mv / base - 273.15);
1167*7abd0fb2Slogwang                 }
1168*7abd0fb2Slogwang             } else
1169*7abd0fb2Slogwang                 printf(hflag ? "%'jd" : "%jd", mv);
1170*7abd0fb2Slogwang             sep1 = " ";
1171*7abd0fb2Slogwang             len -= intlen;
1172*7abd0fb2Slogwang             p += intlen;
1173*7abd0fb2Slogwang         }
1174*7abd0fb2Slogwang         free(oval);
1175*7abd0fb2Slogwang         return (0);
1176*7abd0fb2Slogwang 
1177*7abd0fb2Slogwang     case CTLTYPE_OPAQUE:
1178*7abd0fb2Slogwang         i = 0;
1179*7abd0fb2Slogwang         if (strcmp(fmt, "S,clockinfo") == 0)
1180*7abd0fb2Slogwang             func = S_clockinfo;
1181*7abd0fb2Slogwang         else if (strcmp(fmt, "S,timeval") == 0)
1182*7abd0fb2Slogwang             func = S_timeval;
1183*7abd0fb2Slogwang         else if (strcmp(fmt, "S,loadavg") == 0)
1184*7abd0fb2Slogwang             func = S_loadavg;
1185*7abd0fb2Slogwang         else if (strcmp(fmt, "S,vmtotal") == 0)
1186*7abd0fb2Slogwang             func = S_vmtotal;
1187*7abd0fb2Slogwang #ifdef __amd64__
1188*7abd0fb2Slogwang         else if (strcmp(fmt, "S,efi_map_header") == 0)
1189*7abd0fb2Slogwang             func = S_efi_map;
1190*7abd0fb2Slogwang #endif
1191*7abd0fb2Slogwang #if defined(__amd64__) || defined(__i386__)
1192*7abd0fb2Slogwang         else if (strcmp(fmt, "S,bios_smap_xattr") == 0)
1193*7abd0fb2Slogwang             func = S_bios_smap_xattr;
1194*7abd0fb2Slogwang #endif
1195*7abd0fb2Slogwang         else
1196*7abd0fb2Slogwang             func = NULL;
1197*7abd0fb2Slogwang         if (func) {
1198*7abd0fb2Slogwang             if (!nflag)
1199*7abd0fb2Slogwang                 printf("%s%s", name, sep);
1200*7abd0fb2Slogwang             i = (*func)(len, p);
1201*7abd0fb2Slogwang             free(oval);
1202*7abd0fb2Slogwang             return (i);
1203*7abd0fb2Slogwang         }
1204*7abd0fb2Slogwang         /* FALLTHROUGH */
1205*7abd0fb2Slogwang     default:
1206*7abd0fb2Slogwang         if (!oflag && !xflag) {
1207*7abd0fb2Slogwang             free(oval);
1208*7abd0fb2Slogwang             return (1);
1209*7abd0fb2Slogwang         }
1210*7abd0fb2Slogwang         if (!nflag)
1211*7abd0fb2Slogwang             printf("%s%s", name, sep);
1212*7abd0fb2Slogwang         printf("Format:%s Length:%zu Dump:0x", fmt, len);
1213*7abd0fb2Slogwang         while (len-- && (xflag || p < val + 16))
1214*7abd0fb2Slogwang             printf("%02x", *p++);
1215*7abd0fb2Slogwang         if (!xflag && len > 16)
1216*7abd0fb2Slogwang             printf("...");
1217*7abd0fb2Slogwang         free(oval);
1218*7abd0fb2Slogwang         return (0);
1219*7abd0fb2Slogwang     }
1220*7abd0fb2Slogwang     free(oval);
1221*7abd0fb2Slogwang     return (1);
1222*7abd0fb2Slogwang }
1223*7abd0fb2Slogwang 
1224*7abd0fb2Slogwang static int
1225*7abd0fb2Slogwang sysctl_all(int *oid, int len)
1226*7abd0fb2Slogwang {
1227*7abd0fb2Slogwang     int name1[22], name2[22];
1228*7abd0fb2Slogwang     int i, j;
1229*7abd0fb2Slogwang     size_t l1, l2;
1230*7abd0fb2Slogwang 
1231*7abd0fb2Slogwang     name1[0] = 0;
1232*7abd0fb2Slogwang     name1[1] = 2;
1233*7abd0fb2Slogwang     l1 = 2;
1234*7abd0fb2Slogwang     if (len) {
1235*7abd0fb2Slogwang         memcpy(name1+2, oid, len * sizeof(int));
1236*7abd0fb2Slogwang         l1 += len;
1237*7abd0fb2Slogwang     } else {
1238*7abd0fb2Slogwang         name1[2] = 1;
1239*7abd0fb2Slogwang         l1++;
1240*7abd0fb2Slogwang     }
1241*7abd0fb2Slogwang     for (;;) {
1242*7abd0fb2Slogwang         l2 = sizeof(name2);
1243*7abd0fb2Slogwang         j = sysctl_ipc(name1, l1, name2, &l2, 0, 0);
1244*7abd0fb2Slogwang         if (j < 0) {
1245*7abd0fb2Slogwang             if (errno == ENOENT)
1246*7abd0fb2Slogwang                 return (0);
1247*7abd0fb2Slogwang             else
1248*7abd0fb2Slogwang                 err(1, "sysctl_ipc(getnext) %d %zu", j, l2);
1249*7abd0fb2Slogwang         }
1250*7abd0fb2Slogwang 
1251*7abd0fb2Slogwang         l2 /= sizeof(int);
1252*7abd0fb2Slogwang 
1253*7abd0fb2Slogwang         if (len < 0 || l2 < (unsigned int)len)
1254*7abd0fb2Slogwang             return (0);
1255*7abd0fb2Slogwang 
1256*7abd0fb2Slogwang         for (i = 0; i < len; i++)
1257*7abd0fb2Slogwang             if (name2[i] != oid[i])
1258*7abd0fb2Slogwang                 return (0);
1259*7abd0fb2Slogwang 
1260*7abd0fb2Slogwang         i = show_var(name2, l2);
1261*7abd0fb2Slogwang         if (!i && !bflag)
1262*7abd0fb2Slogwang             putchar('\n');
1263*7abd0fb2Slogwang 
1264*7abd0fb2Slogwang         memcpy(name1+2, name2, l2 * sizeof(int));
1265*7abd0fb2Slogwang         l1 = 2 + l2;
1266*7abd0fb2Slogwang     }
1267*7abd0fb2Slogwang }
1268*7abd0fb2Slogwang 
1269*7abd0fb2Slogwang static int
1270*7abd0fb2Slogwang sysctl_ipc(int *name, unsigned namelen, void *old,
1271*7abd0fb2Slogwang     size_t *oldlenp, const void *new, size_t newlen)
1272*7abd0fb2Slogwang {
1273*7abd0fb2Slogwang     struct ff_msg *msg, *retmsg = NULL;
1274*7abd0fb2Slogwang 
1275*7abd0fb2Slogwang     if (old != NULL && oldlenp == NULL) {
1276*7abd0fb2Slogwang         errno = EINVAL;
1277*7abd0fb2Slogwang         return -1;
1278*7abd0fb2Slogwang     }
1279*7abd0fb2Slogwang 
1280*7abd0fb2Slogwang     msg = ff_ipc_msg_alloc();
1281*7abd0fb2Slogwang     if (msg == NULL) {
1282*7abd0fb2Slogwang         errno = ENOMEM;
1283*7abd0fb2Slogwang         return -1;
1284*7abd0fb2Slogwang     }
1285*7abd0fb2Slogwang 
1286*7abd0fb2Slogwang     size_t oldlen = 0;
1287*7abd0fb2Slogwang     if (oldlenp) {
1288*7abd0fb2Slogwang         oldlen = *oldlenp;
1289*7abd0fb2Slogwang     }
1290*7abd0fb2Slogwang 
1291*7abd0fb2Slogwang     if (namelen + oldlen + newlen > msg->buf_len) {
1292*7abd0fb2Slogwang         errno = EINVAL;
1293*7abd0fb2Slogwang         ff_ipc_msg_free(msg);
1294*7abd0fb2Slogwang         return -1;
1295*7abd0fb2Slogwang     }
1296*7abd0fb2Slogwang 
1297*7abd0fb2Slogwang     char *buf_addr = msg->buf_addr;
1298*7abd0fb2Slogwang 
1299*7abd0fb2Slogwang     msg->msg_type = FF_SYSCTL;
1300*7abd0fb2Slogwang     msg->sysctl.name = (int *)buf_addr;
1301*7abd0fb2Slogwang     msg->sysctl.namelen = namelen;
1302*7abd0fb2Slogwang     memcpy(msg->sysctl.name, name, namelen*sizeof(int));
1303*7abd0fb2Slogwang 
1304*7abd0fb2Slogwang     buf_addr += namelen*sizeof(int);
1305*7abd0fb2Slogwang 
1306*7abd0fb2Slogwang     if (new != NULL && newlen != 0) {
1307*7abd0fb2Slogwang         msg->sysctl.new = buf_addr;
1308*7abd0fb2Slogwang         msg->sysctl.newlen = newlen;
1309*7abd0fb2Slogwang         memcpy(msg->sysctl.new, new, newlen);
1310*7abd0fb2Slogwang 
1311*7abd0fb2Slogwang         buf_addr += newlen;
1312*7abd0fb2Slogwang     } else {
1313*7abd0fb2Slogwang         msg->sysctl.new = NULL;
1314*7abd0fb2Slogwang         msg->sysctl.newlen = 0;
1315*7abd0fb2Slogwang     }
1316*7abd0fb2Slogwang 
1317*7abd0fb2Slogwang     if (oldlenp != NULL) {
1318*7abd0fb2Slogwang         msg->sysctl.oldlenp = (size_t *)buf_addr;
1319*7abd0fb2Slogwang         memcpy(msg->sysctl.oldlenp, oldlenp, sizeof(size_t));
1320*7abd0fb2Slogwang         buf_addr += sizeof(size_t);
1321*7abd0fb2Slogwang 
1322*7abd0fb2Slogwang         if (old != NULL) {
1323*7abd0fb2Slogwang             msg->sysctl.old = (void *)buf_addr;
1324*7abd0fb2Slogwang             memcpy(msg->sysctl.old, old, *oldlenp);
1325*7abd0fb2Slogwang             buf_addr += *oldlenp;
1326*7abd0fb2Slogwang         } else {
1327*7abd0fb2Slogwang             msg->sysctl.old = NULL;
1328*7abd0fb2Slogwang         }
1329*7abd0fb2Slogwang     } else {
1330*7abd0fb2Slogwang         msg->sysctl.oldlenp = NULL;
1331*7abd0fb2Slogwang         msg->sysctl.old = NULL;
1332*7abd0fb2Slogwang     }
1333*7abd0fb2Slogwang 
1334*7abd0fb2Slogwang     int ret = ff_ipc_send(msg, proc_id);
1335*7abd0fb2Slogwang     if (ret < 0) {
1336*7abd0fb2Slogwang         errno = EPIPE;
1337*7abd0fb2Slogwang         ff_ipc_msg_free(msg);
1338*7abd0fb2Slogwang         return -1;
1339*7abd0fb2Slogwang     }
1340*7abd0fb2Slogwang 
1341*7abd0fb2Slogwang     do {
1342*7abd0fb2Slogwang         if (retmsg != NULL) {
1343*7abd0fb2Slogwang             ff_ipc_msg_free(retmsg);
1344*7abd0fb2Slogwang         }
1345*7abd0fb2Slogwang         ret = ff_ipc_recv(&retmsg, proc_id);
1346*7abd0fb2Slogwang         if (ret < 0) {
1347*7abd0fb2Slogwang             errno = EPIPE;
1348*7abd0fb2Slogwang             ff_ipc_msg_free(msg);
1349*7abd0fb2Slogwang             return -1;
1350*7abd0fb2Slogwang         }
1351*7abd0fb2Slogwang     } while (msg != retmsg);
1352*7abd0fb2Slogwang 
1353*7abd0fb2Slogwang     if (retmsg->result == 0) {
1354*7abd0fb2Slogwang         ret = 0;
1355*7abd0fb2Slogwang         if (oldlenp && retmsg->sysctl.oldlenp) {
1356*7abd0fb2Slogwang             *oldlenp = *retmsg->sysctl.oldlenp;
1357*7abd0fb2Slogwang         }
1358*7abd0fb2Slogwang 
1359*7abd0fb2Slogwang         if (old && retmsg->sysctl.old && oldlenp) {
1360*7abd0fb2Slogwang             memcpy(old, retmsg->sysctl.old, *oldlenp);
1361*7abd0fb2Slogwang         }
1362*7abd0fb2Slogwang     } else {
1363*7abd0fb2Slogwang         ret = -1;
1364*7abd0fb2Slogwang         errno = retmsg->result;
1365*7abd0fb2Slogwang     }
1366*7abd0fb2Slogwang 
1367*7abd0fb2Slogwang     ff_ipc_msg_free(msg);
1368*7abd0fb2Slogwang 
1369*7abd0fb2Slogwang     return ret;
1370*7abd0fb2Slogwang }
1371