xref: /minix3/sbin/sysctl/sysctl.c (revision b4f34f94bee271f15440c5c33aecbd4cd2e40676)
1*b4f34f94SDavid van Moolenbroek /*	$NetBSD: sysctl.c,v 1.156 2015/08/17 06:42:46 knakahara Exp $ */
2*b4f34f94SDavid van Moolenbroek 
3*b4f34f94SDavid van Moolenbroek /*-
4*b4f34f94SDavid van Moolenbroek  * Copyright (c) 2003 The NetBSD Foundation, Inc.
5*b4f34f94SDavid van Moolenbroek  *	All rights reserved.
6*b4f34f94SDavid van Moolenbroek  *
7*b4f34f94SDavid van Moolenbroek  * This code is derived from software contributed to The NetBSD Foundation
8*b4f34f94SDavid van Moolenbroek  * by Andrew Brown.
9*b4f34f94SDavid van Moolenbroek  *
10*b4f34f94SDavid van Moolenbroek  * Redistribution and use in source and binary forms, with or without
11*b4f34f94SDavid van Moolenbroek  * modification, are permitted provided that the following conditions
12*b4f34f94SDavid van Moolenbroek  * are met:
13*b4f34f94SDavid van Moolenbroek  * 1. Redistributions of source code must retain the above copyright
14*b4f34f94SDavid van Moolenbroek  *    notice, this list of conditions and the following disclaimer.
15*b4f34f94SDavid van Moolenbroek  * 2. Redistributions in binary form must reproduce the above copyright
16*b4f34f94SDavid van Moolenbroek  *    notice, this list of conditions and the following disclaimer in the
17*b4f34f94SDavid van Moolenbroek  *    documentation and/or other materials provided with the distribution.
18*b4f34f94SDavid van Moolenbroek  *
19*b4f34f94SDavid van Moolenbroek  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20*b4f34f94SDavid van Moolenbroek  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21*b4f34f94SDavid van Moolenbroek  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22*b4f34f94SDavid van Moolenbroek  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23*b4f34f94SDavid van Moolenbroek  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24*b4f34f94SDavid van Moolenbroek  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25*b4f34f94SDavid van Moolenbroek  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26*b4f34f94SDavid van Moolenbroek  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27*b4f34f94SDavid van Moolenbroek  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28*b4f34f94SDavid van Moolenbroek  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29*b4f34f94SDavid van Moolenbroek  * POSSIBILITY OF SUCH DAMAGE.
30*b4f34f94SDavid van Moolenbroek  */
31*b4f34f94SDavid van Moolenbroek 
32*b4f34f94SDavid van Moolenbroek /*
33*b4f34f94SDavid van Moolenbroek  * Copyright (c) 1993
34*b4f34f94SDavid van Moolenbroek  *	The Regents of the University of California.  All rights reserved.
35*b4f34f94SDavid van Moolenbroek  *
36*b4f34f94SDavid van Moolenbroek  * Redistribution and use in source and binary forms, with or without
37*b4f34f94SDavid van Moolenbroek  * modification, are permitted provided that the following conditions
38*b4f34f94SDavid van Moolenbroek  * are met:
39*b4f34f94SDavid van Moolenbroek  * 1. Redistributions of source code must retain the above copyright
40*b4f34f94SDavid van Moolenbroek  *    notice, this list of conditions and the following disclaimer.
41*b4f34f94SDavid van Moolenbroek  * 2. Redistributions in binary form must reproduce the above copyright
42*b4f34f94SDavid van Moolenbroek  *    notice, this list of conditions and the following disclaimer in the
43*b4f34f94SDavid van Moolenbroek  *    documentation and/or other materials provided with the distribution.
44*b4f34f94SDavid van Moolenbroek  * 3. Neither the name of the University nor the names of its contributors
45*b4f34f94SDavid van Moolenbroek  *    may be used to endorse or promote products derived from this software
46*b4f34f94SDavid van Moolenbroek  *    without specific prior written permission.
47*b4f34f94SDavid van Moolenbroek  *
48*b4f34f94SDavid van Moolenbroek  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
49*b4f34f94SDavid van Moolenbroek  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50*b4f34f94SDavid van Moolenbroek  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51*b4f34f94SDavid van Moolenbroek  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
52*b4f34f94SDavid van Moolenbroek  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53*b4f34f94SDavid van Moolenbroek  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54*b4f34f94SDavid van Moolenbroek  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55*b4f34f94SDavid van Moolenbroek  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56*b4f34f94SDavid van Moolenbroek  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57*b4f34f94SDavid van Moolenbroek  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58*b4f34f94SDavid van Moolenbroek  * SUCH DAMAGE.
59*b4f34f94SDavid van Moolenbroek  */
60*b4f34f94SDavid van Moolenbroek 
61*b4f34f94SDavid van Moolenbroek #include <sys/cdefs.h>
62*b4f34f94SDavid van Moolenbroek #ifndef lint
63*b4f34f94SDavid van Moolenbroek __COPYRIGHT("@(#) Copyright (c) 1993\
64*b4f34f94SDavid van Moolenbroek  The Regents of the University of California.  All rights reserved.");
65*b4f34f94SDavid van Moolenbroek #endif /* not lint */
66*b4f34f94SDavid van Moolenbroek 
67*b4f34f94SDavid van Moolenbroek #ifndef lint
68*b4f34f94SDavid van Moolenbroek #if 0
69*b4f34f94SDavid van Moolenbroek static char sccsid[] = "@(#)sysctl.c	8.1 (Berkeley) 6/6/93";
70*b4f34f94SDavid van Moolenbroek #else
71*b4f34f94SDavid van Moolenbroek __RCSID("$NetBSD: sysctl.c,v 1.156 2015/08/17 06:42:46 knakahara Exp $");
72*b4f34f94SDavid van Moolenbroek #endif
73*b4f34f94SDavid van Moolenbroek #endif /* not lint */
74*b4f34f94SDavid van Moolenbroek 
75*b4f34f94SDavid van Moolenbroek #include <sys/types.h>
76*b4f34f94SDavid van Moolenbroek #include <sys/param.h>
77*b4f34f94SDavid van Moolenbroek #include <sys/sysctl.h>
78*b4f34f94SDavid van Moolenbroek #include <sys/mount.h>
79*b4f34f94SDavid van Moolenbroek #include <sys/resource.h>
80*b4f34f94SDavid van Moolenbroek #include <sys/stat.h>
81*b4f34f94SDavid van Moolenbroek #include <sys/sched.h>
82*b4f34f94SDavid van Moolenbroek #include <sys/socket.h>
83*b4f34f94SDavid van Moolenbroek #include <sys/bitops.h>
84*b4f34f94SDavid van Moolenbroek #include <netinet/in.h>
85*b4f34f94SDavid van Moolenbroek #include <netinet/ip_var.h>
86*b4f34f94SDavid van Moolenbroek #include <netinet/tcp.h>
87*b4f34f94SDavid van Moolenbroek #ifndef __minix
88*b4f34f94SDavid van Moolenbroek #include <netinet/tcp_timer.h>
89*b4f34f94SDavid van Moolenbroek #include <netinet/tcp_var.h>
90*b4f34f94SDavid van Moolenbroek #include <netinet/icmp6.h>
91*b4f34f94SDavid van Moolenbroek #include <nfs/rpcv2.h>
92*b4f34f94SDavid van Moolenbroek #include <nfs/nfsproto.h>
93*b4f34f94SDavid van Moolenbroek #include <nfs/nfs.h>
94*b4f34f94SDavid van Moolenbroek #endif /* !__minix */
95*b4f34f94SDavid van Moolenbroek #include <machine/cpu.h>
96*b4f34f94SDavid van Moolenbroek 
97*b4f34f94SDavid van Moolenbroek #include <assert.h>
98*b4f34f94SDavid van Moolenbroek #include <ctype.h>
99*b4f34f94SDavid van Moolenbroek #include <err.h>
100*b4f34f94SDavid van Moolenbroek #include <errno.h>
101*b4f34f94SDavid van Moolenbroek #include <inttypes.h>
102*b4f34f94SDavid van Moolenbroek #include <regex.h>
103*b4f34f94SDavid van Moolenbroek #include <stdarg.h>
104*b4f34f94SDavid van Moolenbroek #include <stdio.h>
105*b4f34f94SDavid van Moolenbroek #include <stdlib.h>
106*b4f34f94SDavid van Moolenbroek #include <string.h>
107*b4f34f94SDavid van Moolenbroek #include <time.h>
108*b4f34f94SDavid van Moolenbroek #include <unistd.h>
109*b4f34f94SDavid van Moolenbroek 
110*b4f34f94SDavid van Moolenbroek #include "prog_ops.h"
111*b4f34f94SDavid van Moolenbroek 
112*b4f34f94SDavid van Moolenbroek /*
113*b4f34f94SDavid van Moolenbroek  * this needs to be able to do the printing and the setting
114*b4f34f94SDavid van Moolenbroek  */
115*b4f34f94SDavid van Moolenbroek #define HANDLER_PROTO const char *, const char *, char *, \
116*b4f34f94SDavid van Moolenbroek 	int *, u_int, const struct sysctlnode *, \
117*b4f34f94SDavid van Moolenbroek 	u_int, void *
118*b4f34f94SDavid van Moolenbroek #define HANDLER_ARGS const char *sname, const char *dname, char *value, \
119*b4f34f94SDavid van Moolenbroek 	int *name, u_int namelen, const struct sysctlnode *pnode, \
120*b4f34f94SDavid van Moolenbroek 	u_int type, void *v
121*b4f34f94SDavid van Moolenbroek #define DISPLAY_VALUE	0
122*b4f34f94SDavid van Moolenbroek #define DISPLAY_OLD	1
123*b4f34f94SDavid van Moolenbroek #define DISPLAY_NEW	2
124*b4f34f94SDavid van Moolenbroek 
125*b4f34f94SDavid van Moolenbroek /*
126*b4f34f94SDavid van Moolenbroek  * generic routines
127*b4f34f94SDavid van Moolenbroek  */
128*b4f34f94SDavid van Moolenbroek static const struct handlespec *findhandler(const char *, regex_t *, size_t *);
129*b4f34f94SDavid van Moolenbroek static void canonicalize(const char *, char *);
130*b4f34f94SDavid van Moolenbroek static void purge_tree(struct sysctlnode *);
131*b4f34f94SDavid van Moolenbroek static void print_tree(int *, u_int, struct sysctlnode *, u_int, int, regex_t *,
132*b4f34f94SDavid van Moolenbroek     size_t *);
133*b4f34f94SDavid van Moolenbroek static void write_number(int *, u_int, struct sysctlnode *, char *);
134*b4f34f94SDavid van Moolenbroek static void write_string(int *, u_int, struct sysctlnode *, char *);
135*b4f34f94SDavid van Moolenbroek static void display_number(const struct sysctlnode *, const char *,
136*b4f34f94SDavid van Moolenbroek 			   const void *, size_t, int);
137*b4f34f94SDavid van Moolenbroek static void display_string(const struct sysctlnode *, const char *,
138*b4f34f94SDavid van Moolenbroek 			   const void *, size_t, int);
139*b4f34f94SDavid van Moolenbroek static void display_struct(const struct sysctlnode *, const char *,
140*b4f34f94SDavid van Moolenbroek 			   const void *, size_t, int);
141*b4f34f94SDavid van Moolenbroek static void hex_dump(const unsigned char *, size_t);
142*b4f34f94SDavid van Moolenbroek __dead static void usage(void);
143*b4f34f94SDavid van Moolenbroek static void parse(char *, regex_t *, size_t *);
144*b4f34f94SDavid van Moolenbroek static void parse_create(char *);
145*b4f34f94SDavid van Moolenbroek static void parse_destroy(char *);
146*b4f34f94SDavid van Moolenbroek static void parse_describe(char *);
147*b4f34f94SDavid van Moolenbroek static void getdesc1(int *, u_int, struct sysctlnode *);
148*b4f34f94SDavid van Moolenbroek static void getdesc(int *, u_int, struct sysctlnode *);
149*b4f34f94SDavid van Moolenbroek static void trim_whitespace(char *, int);
150*b4f34f94SDavid van Moolenbroek static void sysctlerror(int);
151*b4f34f94SDavid van Moolenbroek static void sysctlparseerror(u_int, const char *);
152*b4f34f94SDavid van Moolenbroek static void sysctlperror(const char *, ...) __printflike(1, 2);
153*b4f34f94SDavid van Moolenbroek #define EXIT(n) do { \
154*b4f34f94SDavid van Moolenbroek 	if (fn == NULL) exit(n); else return; } while (/*CONSTCOND*/0)
155*b4f34f94SDavid van Moolenbroek 
156*b4f34f94SDavid van Moolenbroek /*
157*b4f34f94SDavid van Moolenbroek  * "borrowed" from libc:sysctlgetmibinfo.c
158*b4f34f94SDavid van Moolenbroek  */
159*b4f34f94SDavid van Moolenbroek int __learn_tree(int *, u_int, struct sysctlnode *);
160*b4f34f94SDavid van Moolenbroek 
161*b4f34f94SDavid van Moolenbroek /*
162*b4f34f94SDavid van Moolenbroek  * "handlers"
163*b4f34f94SDavid van Moolenbroek  */
164*b4f34f94SDavid van Moolenbroek static void printother(HANDLER_PROTO);
165*b4f34f94SDavid van Moolenbroek static void kern_clockrate(HANDLER_PROTO);
166*b4f34f94SDavid van Moolenbroek static void kern_boottime(HANDLER_PROTO);
167*b4f34f94SDavid van Moolenbroek static void kern_consdev(HANDLER_PROTO);
168*b4f34f94SDavid van Moolenbroek static void kern_cp_time(HANDLER_PROTO);
169*b4f34f94SDavid van Moolenbroek static void kern_cp_id(HANDLER_PROTO);
170*b4f34f94SDavid van Moolenbroek static void kern_drivers(HANDLER_PROTO);
171*b4f34f94SDavid van Moolenbroek static void vm_loadavg(HANDLER_PROTO);
172*b4f34f94SDavid van Moolenbroek static void proc_limit(HANDLER_PROTO);
173*b4f34f94SDavid van Moolenbroek #ifdef CPU_DISKINFO
174*b4f34f94SDavid van Moolenbroek static void machdep_diskinfo(HANDLER_PROTO);
175*b4f34f94SDavid van Moolenbroek #endif /* CPU_DISKINFO */
176*b4f34f94SDavid van Moolenbroek static void mode_bits(HANDLER_PROTO);
177*b4f34f94SDavid van Moolenbroek static void reserve(HANDLER_PROTO);
178*b4f34f94SDavid van Moolenbroek 
179*b4f34f94SDavid van Moolenbroek static const struct handlespec {
180*b4f34f94SDavid van Moolenbroek 	const char *ps_re;
181*b4f34f94SDavid van Moolenbroek 	void (*ps_p)(HANDLER_PROTO);
182*b4f34f94SDavid van Moolenbroek 	void (*ps_w)(HANDLER_PROTO);
183*b4f34f94SDavid van Moolenbroek 	const void *ps_d;
184*b4f34f94SDavid van Moolenbroek } handlers[] = {
185*b4f34f94SDavid van Moolenbroek 	{ "/kern/clockrate",			kern_clockrate, NULL, NULL },
186*b4f34f94SDavid van Moolenbroek 	{ "/kern/evcnt",			printother, NULL, "vmstat -e" },
187*b4f34f94SDavid van Moolenbroek 	{ "/kern/vnode",			printother, NULL, "pstat" },
188*b4f34f94SDavid van Moolenbroek 	{ "/kern/proc(2|_args)?",		printother, NULL, "ps" },
189*b4f34f94SDavid van Moolenbroek 	{ "/kern/file2?",			printother, NULL, "pstat" },
190*b4f34f94SDavid van Moolenbroek 	{ "/kern/ntptime",			printother, NULL,
191*b4f34f94SDavid van Moolenbroek 						"ntpdc -c kerninfo" },
192*b4f34f94SDavid van Moolenbroek 	{ "/kern/msgbuf",			printother, NULL, "dmesg" },
193*b4f34f94SDavid van Moolenbroek 	{ "/kern/boottime",			kern_boottime, NULL, NULL },
194*b4f34f94SDavid van Moolenbroek 	{ "/kern/consdev",			kern_consdev, NULL, NULL },
195*b4f34f94SDavid van Moolenbroek 	{ "/kern/cp_time(/[0-9]+)?",		kern_cp_time, NULL, NULL },
196*b4f34f94SDavid van Moolenbroek 	{ "/kern/sysvipc_info",			printother, NULL, "ipcs" },
197*b4f34f94SDavid van Moolenbroek 	{ "/kern/cp_id(/[0-9]+)?",		kern_cp_id, NULL, NULL },
198*b4f34f94SDavid van Moolenbroek 
199*b4f34f94SDavid van Moolenbroek 	{ "/kern/coredump/setid/mode",		mode_bits, mode_bits, NULL },
200*b4f34f94SDavid van Moolenbroek 	{ "/kern/drivers",			kern_drivers, NULL, NULL },
201*b4f34f94SDavid van Moolenbroek 
202*b4f34f94SDavid van Moolenbroek 	{ "/kern/intr/list",			printother, NULL, "intrctl" },
203*b4f34f94SDavid van Moolenbroek 	{ "/kern/intr/affinity",		printother, NULL, "intrctl" },
204*b4f34f94SDavid van Moolenbroek 	{ "/kern/intr/intr",			printother, NULL, "intrctl" },
205*b4f34f94SDavid van Moolenbroek 	{ "/kern/intr/nointr",			printother, NULL, "intrctl" },
206*b4f34f94SDavid van Moolenbroek 
207*b4f34f94SDavid van Moolenbroek 	{ "/vm/vmmeter",			printother, NULL,
208*b4f34f94SDavid van Moolenbroek 						"vmstat' or 'systat" },
209*b4f34f94SDavid van Moolenbroek 	{ "/vm/loadavg",			vm_loadavg, NULL, NULL },
210*b4f34f94SDavid van Moolenbroek 	{ "/vm/uvmexp2?",			printother, NULL,
211*b4f34f94SDavid van Moolenbroek 						"vmstat' or 'systat" },
212*b4f34f94SDavid van Moolenbroek 
213*b4f34f94SDavid van Moolenbroek 	{ "/vfs/nfs/nfsstats",			printother, NULL, "nfsstat" },
214*b4f34f94SDavid van Moolenbroek 
215*b4f34f94SDavid van Moolenbroek 	{ "/net/inet6?/tcp6?/ident",		printother, NULL, "identd" },
216*b4f34f94SDavid van Moolenbroek 	{ "/net/inet6/icmp6/nd6_[dp]rlist",	printother, NULL, "ndp" },
217*b4f34f94SDavid van Moolenbroek 	{ "/net/key/dumps[ap]",			printother, NULL, "setkey" },
218*b4f34f94SDavid van Moolenbroek 	{ "/net/[^/]+/[^/]+/pcblist",		printother, NULL,
219*b4f34f94SDavid van Moolenbroek 						"netstat' or 'sockstat" },
220*b4f34f94SDavid van Moolenbroek 	{ "/net/(inet|inet6)/[^/]+/stats",	printother, NULL, "netstat"},
221*b4f34f94SDavid van Moolenbroek 	{ "/net/bpf/(stats|peers)",		printother, NULL, "netstat"},
222*b4f34f94SDavid van Moolenbroek 
223*b4f34f94SDavid van Moolenbroek 	{ "/net/inet.*/tcp.*/deb.*",		printother, NULL, "trpt" },
224*b4f34f94SDavid van Moolenbroek 
225*b4f34f94SDavid van Moolenbroek 	{ "/net/inet.*/ip.*/anonportalgo/reserve", reserve, reserve, NULL },
226*b4f34f94SDavid van Moolenbroek 
227*b4f34f94SDavid van Moolenbroek 	{ "/net/ns/spp/deb.*",			printother, NULL, "trsp" },
228*b4f34f94SDavid van Moolenbroek 
229*b4f34f94SDavid van Moolenbroek 	{ "/hw/diskstats",			printother, NULL, "iostat" },
230*b4f34f94SDavid van Moolenbroek 
231*b4f34f94SDavid van Moolenbroek #ifdef CPU_CONSDEV
232*b4f34f94SDavid van Moolenbroek 	{ "/machdep/consdev",			kern_consdev, NULL, NULL },
233*b4f34f94SDavid van Moolenbroek #endif /* CPU_CONSDEV */
234*b4f34f94SDavid van Moolenbroek #ifdef CPU_DISKINFO
235*b4f34f94SDavid van Moolenbroek 	{ "/machdep/diskinfo",			machdep_diskinfo, NULL, NULL },
236*b4f34f94SDavid van Moolenbroek #endif /* CPU_CONSDEV */
237*b4f34f94SDavid van Moolenbroek 
238*b4f34f94SDavid van Moolenbroek 	{ "/proc/[^/]+/rlimit/[^/]+/[^/]+",	proc_limit, proc_limit, NULL },
239*b4f34f94SDavid van Moolenbroek 
240*b4f34f94SDavid van Moolenbroek 	/*
241*b4f34f94SDavid van Moolenbroek 	 * these will only be called when the given node has no children
242*b4f34f94SDavid van Moolenbroek 	 */
243*b4f34f94SDavid van Moolenbroek 	{ "/net/[^/]+",				printother, NULL, NULL },
244*b4f34f94SDavid van Moolenbroek 	{ "/debug",				printother, NULL, NULL },
245*b4f34f94SDavid van Moolenbroek 	{ "/ddb",				printother, NULL, NULL },
246*b4f34f94SDavid van Moolenbroek 	{ "/vendor",				printother, NULL, NULL },
247*b4f34f94SDavid van Moolenbroek 
248*b4f34f94SDavid van Moolenbroek 	{ NULL,					NULL, NULL, NULL },
249*b4f34f94SDavid van Moolenbroek };
250*b4f34f94SDavid van Moolenbroek 
251*b4f34f94SDavid van Moolenbroek struct sysctlnode my_root = {
252*b4f34f94SDavid van Moolenbroek 	.sysctl_flags = SYSCTL_VERSION|CTLFLAG_ROOT|CTLTYPE_NODE,
253*b4f34f94SDavid van Moolenbroek 	.sysctl_size = sizeof(struct sysctlnode),
254*b4f34f94SDavid van Moolenbroek 	.sysctl_num = 0,
255*b4f34f94SDavid van Moolenbroek 	.sysctl_name = "(prog_root)",
256*b4f34f94SDavid van Moolenbroek };
257*b4f34f94SDavid van Moolenbroek 
258*b4f34f94SDavid van Moolenbroek int	Aflag, aflag, dflag, Mflag, nflag, qflag, rflag, wflag, xflag;
259*b4f34f94SDavid van Moolenbroek size_t	nr;
260*b4f34f94SDavid van Moolenbroek char	*fn;
261*b4f34f94SDavid van Moolenbroek int	req, stale, errs;
262*b4f34f94SDavid van Moolenbroek FILE	*warnfp = stderr;
263*b4f34f94SDavid van Moolenbroek 
264*b4f34f94SDavid van Moolenbroek #define MAXPORTS	0x10000
265*b4f34f94SDavid van Moolenbroek 
266*b4f34f94SDavid van Moolenbroek /*
267*b4f34f94SDavid van Moolenbroek  * vah-riables n stuff
268*b4f34f94SDavid van Moolenbroek  */
269*b4f34f94SDavid van Moolenbroek char gsname[SYSCTL_NAMELEN * CTL_MAXNAME + CTL_MAXNAME],
270*b4f34f94SDavid van Moolenbroek 	canonname[SYSCTL_NAMELEN * CTL_MAXNAME + CTL_MAXNAME],
271*b4f34f94SDavid van Moolenbroek 	gdname[10 * CTL_MAXNAME + CTL_MAXNAME];
272*b4f34f94SDavid van Moolenbroek char sep[] = ".";
273*b4f34f94SDavid van Moolenbroek const char *eq = " = ";
274*b4f34f94SDavid van Moolenbroek const char *lname[] = {
275*b4f34f94SDavid van Moolenbroek 	"top", "second", "third", "fourth", "fifth", "sixth",
276*b4f34f94SDavid van Moolenbroek 	"seventh", "eighth", "ninth", "tenth", "eleventh", "twelfth"
277*b4f34f94SDavid van Moolenbroek };
278*b4f34f94SDavid van Moolenbroek 
279*b4f34f94SDavid van Moolenbroek /*
280*b4f34f94SDavid van Moolenbroek  * you've heard of main, haven't you?
281*b4f34f94SDavid van Moolenbroek  */
282*b4f34f94SDavid van Moolenbroek int
main(int argc,char * argv[])283*b4f34f94SDavid van Moolenbroek main(int argc, char *argv[])
284*b4f34f94SDavid van Moolenbroek {
285*b4f34f94SDavid van Moolenbroek 	int name[CTL_MAXNAME];
286*b4f34f94SDavid van Moolenbroek 	int ch;
287*b4f34f94SDavid van Moolenbroek 	size_t lastcompiled = 0;
288*b4f34f94SDavid van Moolenbroek 	regex_t *re;
289*b4f34f94SDavid van Moolenbroek 
290*b4f34f94SDavid van Moolenbroek 	setprogname(argv[0]);
291*b4f34f94SDavid van Moolenbroek 	while ((ch = getopt(argc, argv, "Aabdef:Mnqrwx")) != -1) {
292*b4f34f94SDavid van Moolenbroek 		switch (ch) {
293*b4f34f94SDavid van Moolenbroek 		case 'A':
294*b4f34f94SDavid van Moolenbroek 			Aflag++;
295*b4f34f94SDavid van Moolenbroek 			break;
296*b4f34f94SDavid van Moolenbroek 		case 'a':
297*b4f34f94SDavid van Moolenbroek 			aflag++;
298*b4f34f94SDavid van Moolenbroek 			break;
299*b4f34f94SDavid van Moolenbroek 		case 'd':
300*b4f34f94SDavid van Moolenbroek 			dflag++;
301*b4f34f94SDavid van Moolenbroek 			break;
302*b4f34f94SDavid van Moolenbroek 		case 'e':
303*b4f34f94SDavid van Moolenbroek 			eq = "=";
304*b4f34f94SDavid van Moolenbroek 			break;
305*b4f34f94SDavid van Moolenbroek 		case 'f':
306*b4f34f94SDavid van Moolenbroek 			fn = optarg;
307*b4f34f94SDavid van Moolenbroek 			wflag++;
308*b4f34f94SDavid van Moolenbroek 			break;
309*b4f34f94SDavid van Moolenbroek 		case 'M':
310*b4f34f94SDavid van Moolenbroek 			Mflag++;
311*b4f34f94SDavid van Moolenbroek 			break;
312*b4f34f94SDavid van Moolenbroek 		case 'n':
313*b4f34f94SDavid van Moolenbroek 			nflag++;
314*b4f34f94SDavid van Moolenbroek 			break;
315*b4f34f94SDavid van Moolenbroek 		case 'q':
316*b4f34f94SDavid van Moolenbroek 			qflag++;
317*b4f34f94SDavid van Moolenbroek 			break;
318*b4f34f94SDavid van Moolenbroek 		case 'b':	/* FreeBSD compat */
319*b4f34f94SDavid van Moolenbroek 		case 'r':
320*b4f34f94SDavid van Moolenbroek 			rflag++;
321*b4f34f94SDavid van Moolenbroek 			break;
322*b4f34f94SDavid van Moolenbroek 		case 'w':
323*b4f34f94SDavid van Moolenbroek 			wflag++;
324*b4f34f94SDavid van Moolenbroek 			break;
325*b4f34f94SDavid van Moolenbroek 		case 'x':
326*b4f34f94SDavid van Moolenbroek 			xflag++;
327*b4f34f94SDavid van Moolenbroek 			break;
328*b4f34f94SDavid van Moolenbroek 		default:
329*b4f34f94SDavid van Moolenbroek 			usage();
330*b4f34f94SDavid van Moolenbroek 		}
331*b4f34f94SDavid van Moolenbroek 	}
332*b4f34f94SDavid van Moolenbroek 
333*b4f34f94SDavid van Moolenbroek 	argc -= optind;
334*b4f34f94SDavid van Moolenbroek 	argv += optind;
335*b4f34f94SDavid van Moolenbroek 
336*b4f34f94SDavid van Moolenbroek 	if (xflag && rflag)
337*b4f34f94SDavid van Moolenbroek 		usage();
338*b4f34f94SDavid van Moolenbroek 	/* if ((xflag || rflag) && wflag)
339*b4f34f94SDavid van Moolenbroek 		usage(); */
340*b4f34f94SDavid van Moolenbroek 	/* if (aflag && (Mflag || qflag))
341*b4f34f94SDavid van Moolenbroek 		usage(); */
342*b4f34f94SDavid van Moolenbroek 	if ((aflag || Aflag) && qflag)
343*b4f34f94SDavid van Moolenbroek 		usage();
344*b4f34f94SDavid van Moolenbroek 	if ((Aflag || Mflag || dflag) && argc == 0 && fn == NULL)
345*b4f34f94SDavid van Moolenbroek 		aflag = 1;
346*b4f34f94SDavid van Moolenbroek 
347*b4f34f94SDavid van Moolenbroek 	if (prog_init && prog_init() == -1)
348*b4f34f94SDavid van Moolenbroek 		err(EXIT_FAILURE, "prog init failed");
349*b4f34f94SDavid van Moolenbroek 
350*b4f34f94SDavid van Moolenbroek 	if (Aflag)
351*b4f34f94SDavid van Moolenbroek 		warnfp = stdout;
352*b4f34f94SDavid van Moolenbroek 	stale = req = 0;
353*b4f34f94SDavid van Moolenbroek 
354*b4f34f94SDavid van Moolenbroek 	if ((re = malloc(sizeof(*re) * __arraycount(handlers))) == NULL)
355*b4f34f94SDavid van Moolenbroek 		err(EXIT_FAILURE, "malloc regex");
356*b4f34f94SDavid van Moolenbroek 
357*b4f34f94SDavid van Moolenbroek 	if (aflag) {
358*b4f34f94SDavid van Moolenbroek 		print_tree(&name[0], 0, NULL, CTLTYPE_NODE, 1,
359*b4f34f94SDavid van Moolenbroek 		    re, &lastcompiled);
360*b4f34f94SDavid van Moolenbroek 		/* if (argc == 0) */
361*b4f34f94SDavid van Moolenbroek 		return (0);
362*b4f34f94SDavid van Moolenbroek 	}
363*b4f34f94SDavid van Moolenbroek 
364*b4f34f94SDavid van Moolenbroek 	if (fn) {
365*b4f34f94SDavid van Moolenbroek 		FILE *fp;
366*b4f34f94SDavid van Moolenbroek 		char *l;
367*b4f34f94SDavid van Moolenbroek 
368*b4f34f94SDavid van Moolenbroek 		fp = fopen(fn, "r");
369*b4f34f94SDavid van Moolenbroek 		if (fp == NULL) {
370*b4f34f94SDavid van Moolenbroek 			err(EXIT_FAILURE, "%s", fn);
371*b4f34f94SDavid van Moolenbroek 		} else {
372*b4f34f94SDavid van Moolenbroek 			nr = 0;
373*b4f34f94SDavid van Moolenbroek 			while ((l = fparseln(fp, NULL, &nr, NULL, 0)) != NULL)
374*b4f34f94SDavid van Moolenbroek 			{
375*b4f34f94SDavid van Moolenbroek 				if (*l) {
376*b4f34f94SDavid van Moolenbroek 					parse(l, re, &lastcompiled);
377*b4f34f94SDavid van Moolenbroek 					free(l);
378*b4f34f94SDavid van Moolenbroek 				}
379*b4f34f94SDavid van Moolenbroek 			}
380*b4f34f94SDavid van Moolenbroek 			fclose(fp);
381*b4f34f94SDavid van Moolenbroek 		}
382*b4f34f94SDavid van Moolenbroek 		return errs ? 1 : 0;
383*b4f34f94SDavid van Moolenbroek 	}
384*b4f34f94SDavid van Moolenbroek 
385*b4f34f94SDavid van Moolenbroek 	if (argc == 0)
386*b4f34f94SDavid van Moolenbroek 		usage();
387*b4f34f94SDavid van Moolenbroek 
388*b4f34f94SDavid van Moolenbroek 	while (argc-- > 0)
389*b4f34f94SDavid van Moolenbroek 		parse(*argv++, re, &lastcompiled);
390*b4f34f94SDavid van Moolenbroek 
391*b4f34f94SDavid van Moolenbroek 	return errs ? EXIT_FAILURE : EXIT_SUCCESS;
392*b4f34f94SDavid van Moolenbroek }
393*b4f34f94SDavid van Moolenbroek 
394*b4f34f94SDavid van Moolenbroek /*
395*b4f34f94SDavid van Moolenbroek  * ********************************************************************
396*b4f34f94SDavid van Moolenbroek  * how to find someone special to handle the reading (or maybe even
397*b4f34f94SDavid van Moolenbroek  * writing) of a particular node
398*b4f34f94SDavid van Moolenbroek  * ********************************************************************
399*b4f34f94SDavid van Moolenbroek  */
400*b4f34f94SDavid van Moolenbroek static const struct handlespec *
findhandler(const char * s,regex_t * re,size_t * lastcompiled)401*b4f34f94SDavid van Moolenbroek findhandler(const char *s, regex_t *re, size_t *lastcompiled)
402*b4f34f94SDavid van Moolenbroek {
403*b4f34f94SDavid van Moolenbroek 	const struct handlespec *p;
404*b4f34f94SDavid van Moolenbroek 	size_t i, l;
405*b4f34f94SDavid van Moolenbroek 	int j;
406*b4f34f94SDavid van Moolenbroek 	char eb[64];
407*b4f34f94SDavid van Moolenbroek 	regmatch_t match;
408*b4f34f94SDavid van Moolenbroek 
409*b4f34f94SDavid van Moolenbroek 	p = &handlers[0];
410*b4f34f94SDavid van Moolenbroek 	l = strlen(s);
411*b4f34f94SDavid van Moolenbroek 	for (i = 0; p[i].ps_re != NULL; i++) {
412*b4f34f94SDavid van Moolenbroek 		if (i >= *lastcompiled) {
413*b4f34f94SDavid van Moolenbroek 			j = regcomp(&re[i], p[i].ps_re, REG_EXTENDED);
414*b4f34f94SDavid van Moolenbroek 			if (j != 0) {
415*b4f34f94SDavid van Moolenbroek 				regerror(j, &re[i], eb, sizeof(eb));
416*b4f34f94SDavid van Moolenbroek 				errx(EXIT_FAILURE, "regcomp: %s: %s", p[i].ps_re, eb);
417*b4f34f94SDavid van Moolenbroek 			}
418*b4f34f94SDavid van Moolenbroek 			*lastcompiled = i + 1;
419*b4f34f94SDavid van Moolenbroek 		}
420*b4f34f94SDavid van Moolenbroek 		j = regexec(&re[i], s, 1, &match, 0);
421*b4f34f94SDavid van Moolenbroek 		if (j == 0) {
422*b4f34f94SDavid van Moolenbroek 			if (match.rm_so == 0 && match.rm_eo == (int)l)
423*b4f34f94SDavid van Moolenbroek 				return &p[i];
424*b4f34f94SDavid van Moolenbroek 		}
425*b4f34f94SDavid van Moolenbroek 		else if (j != REG_NOMATCH) {
426*b4f34f94SDavid van Moolenbroek 			regerror(j, &re[i], eb, sizeof(eb));
427*b4f34f94SDavid van Moolenbroek 			errx(EXIT_FAILURE, "regexec: %s: %s", p[i].ps_re, eb);
428*b4f34f94SDavid van Moolenbroek 		}
429*b4f34f94SDavid van Moolenbroek 	}
430*b4f34f94SDavid van Moolenbroek 
431*b4f34f94SDavid van Moolenbroek 	return NULL;
432*b4f34f94SDavid van Moolenbroek }
433*b4f34f94SDavid van Moolenbroek 
434*b4f34f94SDavid van Moolenbroek /*
435*b4f34f94SDavid van Moolenbroek  * after sysctlgetmibinfo is done with the name, we convert all
436*b4f34f94SDavid van Moolenbroek  * separators to / and stuff one at the front if it was missing
437*b4f34f94SDavid van Moolenbroek  */
438*b4f34f94SDavid van Moolenbroek static void
canonicalize(const char * i,char * o)439*b4f34f94SDavid van Moolenbroek canonicalize(const char *i, char *o)
440*b4f34f94SDavid van Moolenbroek {
441*b4f34f94SDavid van Moolenbroek 	const char *t;
442*b4f34f94SDavid van Moolenbroek 	char p[SYSCTL_NAMELEN + 1];
443*b4f34f94SDavid van Moolenbroek 	int l;
444*b4f34f94SDavid van Moolenbroek 
445*b4f34f94SDavid van Moolenbroek 	if (i[0] != *sep) {
446*b4f34f94SDavid van Moolenbroek 		o[0] = '/';
447*b4f34f94SDavid van Moolenbroek 		o[1] = '\0';
448*b4f34f94SDavid van Moolenbroek 	}
449*b4f34f94SDavid van Moolenbroek 	else
450*b4f34f94SDavid van Moolenbroek 		o[0] = '\0';
451*b4f34f94SDavid van Moolenbroek 
452*b4f34f94SDavid van Moolenbroek 	t = i;
453*b4f34f94SDavid van Moolenbroek 	do {
454*b4f34f94SDavid van Moolenbroek 		i = t;
455*b4f34f94SDavid van Moolenbroek 		t = strchr(i, sep[0]);
456*b4f34f94SDavid van Moolenbroek 		if (t == NULL)
457*b4f34f94SDavid van Moolenbroek 			strcat(o, i);
458*b4f34f94SDavid van Moolenbroek 		else {
459*b4f34f94SDavid van Moolenbroek 			l = t - i;
460*b4f34f94SDavid van Moolenbroek 			t++;
461*b4f34f94SDavid van Moolenbroek 			memcpy(p, i, l);
462*b4f34f94SDavid van Moolenbroek 			p[l] = '\0';
463*b4f34f94SDavid van Moolenbroek 			strcat(o, p);
464*b4f34f94SDavid van Moolenbroek 			strcat(o, "/");
465*b4f34f94SDavid van Moolenbroek 		}
466*b4f34f94SDavid van Moolenbroek 	} while (t != NULL);
467*b4f34f94SDavid van Moolenbroek }
468*b4f34f94SDavid van Moolenbroek 
469*b4f34f94SDavid van Moolenbroek /*
470*b4f34f94SDavid van Moolenbroek  * ********************************************************************
471*b4f34f94SDavid van Moolenbroek  * convert this special number to a special string so we can print the
472*b4f34f94SDavid van Moolenbroek  * mib
473*b4f34f94SDavid van Moolenbroek  * ********************************************************************
474*b4f34f94SDavid van Moolenbroek  */
475*b4f34f94SDavid van Moolenbroek static const char *
sf(u_int f)476*b4f34f94SDavid van Moolenbroek sf(u_int f)
477*b4f34f94SDavid van Moolenbroek {
478*b4f34f94SDavid van Moolenbroek 	static char s[256];
479*b4f34f94SDavid van Moolenbroek 	const char *c;
480*b4f34f94SDavid van Moolenbroek 
481*b4f34f94SDavid van Moolenbroek 	s[0] = '\0';
482*b4f34f94SDavid van Moolenbroek 	c = "";
483*b4f34f94SDavid van Moolenbroek 
484*b4f34f94SDavid van Moolenbroek #define print_flag(_f, _s, _c, _q, _x) \
485*b4f34f94SDavid van Moolenbroek 	if (((_f) & (__CONCAT(CTLFLAG_,_x))) == (__CONCAT(CTLFLAG_,_q))) { \
486*b4f34f94SDavid van Moolenbroek 		strlcat((_s), (_c), sizeof(_s)); \
487*b4f34f94SDavid van Moolenbroek 		strlcat((_s), __STRING(_q), sizeof(_s)); \
488*b4f34f94SDavid van Moolenbroek 		(_c) = ","; \
489*b4f34f94SDavid van Moolenbroek 		(_f) &= ~(__CONCAT(CTLFLAG_,_x)); \
490*b4f34f94SDavid van Moolenbroek 	}
491*b4f34f94SDavid van Moolenbroek 	print_flag(f, s, c, READONLY,  READWRITE);
492*b4f34f94SDavid van Moolenbroek 	print_flag(f, s, c, READWRITE, READWRITE);
493*b4f34f94SDavid van Moolenbroek 	print_flag(f, s, c, ANYWRITE,  ANYWRITE);
494*b4f34f94SDavid van Moolenbroek 	print_flag(f, s, c, PRIVATE,   PRIVATE);
495*b4f34f94SDavid van Moolenbroek 	print_flag(f, s, c, PERMANENT, PERMANENT);
496*b4f34f94SDavid van Moolenbroek 	print_flag(f, s, c, OWNDATA,   OWNDATA);
497*b4f34f94SDavid van Moolenbroek 	print_flag(f, s, c, IMMEDIATE, IMMEDIATE);
498*b4f34f94SDavid van Moolenbroek 	print_flag(f, s, c, HEX,       HEX);
499*b4f34f94SDavid van Moolenbroek 	print_flag(f, s, c, ROOT,      ROOT);
500*b4f34f94SDavid van Moolenbroek 	print_flag(f, s, c, ANYNUMBER, ANYNUMBER);
501*b4f34f94SDavid van Moolenbroek 	print_flag(f, s, c, HIDDEN,    HIDDEN);
502*b4f34f94SDavid van Moolenbroek 	print_flag(f, s, c, ALIAS,     ALIAS);
503*b4f34f94SDavid van Moolenbroek #undef print_flag
504*b4f34f94SDavid van Moolenbroek 
505*b4f34f94SDavid van Moolenbroek 	if (f) {
506*b4f34f94SDavid van Moolenbroek 		char foo[9];
507*b4f34f94SDavid van Moolenbroek 		snprintf(foo, sizeof(foo), "%x", f);
508*b4f34f94SDavid van Moolenbroek 		strlcat(s, c, sizeof(s));
509*b4f34f94SDavid van Moolenbroek 		strlcat(s, foo, sizeof(s));
510*b4f34f94SDavid van Moolenbroek 	}
511*b4f34f94SDavid van Moolenbroek 
512*b4f34f94SDavid van Moolenbroek 	return (s);
513*b4f34f94SDavid van Moolenbroek }
514*b4f34f94SDavid van Moolenbroek 
515*b4f34f94SDavid van Moolenbroek static const char *
st(u_int t)516*b4f34f94SDavid van Moolenbroek st(u_int t)
517*b4f34f94SDavid van Moolenbroek {
518*b4f34f94SDavid van Moolenbroek 
519*b4f34f94SDavid van Moolenbroek 	switch (t) {
520*b4f34f94SDavid van Moolenbroek 	case CTLTYPE_NODE:
521*b4f34f94SDavid van Moolenbroek 		return "NODE";
522*b4f34f94SDavid van Moolenbroek 	case CTLTYPE_INT:
523*b4f34f94SDavid van Moolenbroek 		return "INT";
524*b4f34f94SDavid van Moolenbroek 	case CTLTYPE_STRING:
525*b4f34f94SDavid van Moolenbroek 		return "STRING";
526*b4f34f94SDavid van Moolenbroek 	case CTLTYPE_QUAD:
527*b4f34f94SDavid van Moolenbroek                 return "QUAD";
528*b4f34f94SDavid van Moolenbroek 	case CTLTYPE_STRUCT:
529*b4f34f94SDavid van Moolenbroek 		return "STRUCT";
530*b4f34f94SDavid van Moolenbroek 	case CTLTYPE_BOOL:
531*b4f34f94SDavid van Moolenbroek 		return "BOOL";
532*b4f34f94SDavid van Moolenbroek 	}
533*b4f34f94SDavid van Moolenbroek 
534*b4f34f94SDavid van Moolenbroek 	return "???";
535*b4f34f94SDavid van Moolenbroek }
536*b4f34f94SDavid van Moolenbroek 
537*b4f34f94SDavid van Moolenbroek /*
538*b4f34f94SDavid van Moolenbroek  * ********************************************************************
539*b4f34f94SDavid van Moolenbroek  * recursively eliminate all data belonging to the given node
540*b4f34f94SDavid van Moolenbroek  * ********************************************************************
541*b4f34f94SDavid van Moolenbroek  */
542*b4f34f94SDavid van Moolenbroek static void
purge_tree(struct sysctlnode * rnode)543*b4f34f94SDavid van Moolenbroek purge_tree(struct sysctlnode *rnode)
544*b4f34f94SDavid van Moolenbroek {
545*b4f34f94SDavid van Moolenbroek 	struct sysctlnode *node;
546*b4f34f94SDavid van Moolenbroek 
547*b4f34f94SDavid van Moolenbroek 	if (rnode == NULL ||
548*b4f34f94SDavid van Moolenbroek 	    SYSCTL_TYPE(rnode->sysctl_flags) != CTLTYPE_NODE ||
549*b4f34f94SDavid van Moolenbroek 	    rnode->sysctl_child == NULL)
550*b4f34f94SDavid van Moolenbroek 		return;
551*b4f34f94SDavid van Moolenbroek 
552*b4f34f94SDavid van Moolenbroek 	for (node = rnode->sysctl_child;
553*b4f34f94SDavid van Moolenbroek 	     node < &rnode->sysctl_child[rnode->sysctl_clen];
554*b4f34f94SDavid van Moolenbroek 	     node++)
555*b4f34f94SDavid van Moolenbroek 		purge_tree(node);
556*b4f34f94SDavid van Moolenbroek 	free(rnode->sysctl_child);
557*b4f34f94SDavid van Moolenbroek 	rnode->sysctl_csize = 0;
558*b4f34f94SDavid van Moolenbroek 	rnode->sysctl_clen = 0;
559*b4f34f94SDavid van Moolenbroek 	rnode->sysctl_child = NULL;
560*b4f34f94SDavid van Moolenbroek 
561*b4f34f94SDavid van Moolenbroek 	if (rnode->sysctl_desc == (const char*)-1)
562*b4f34f94SDavid van Moolenbroek 		rnode->sysctl_desc = NULL;
563*b4f34f94SDavid van Moolenbroek 	if (rnode->sysctl_desc != NULL)
564*b4f34f94SDavid van Moolenbroek 		free(__UNCONST(rnode->sysctl_desc));
565*b4f34f94SDavid van Moolenbroek 	rnode->sysctl_desc = NULL;
566*b4f34f94SDavid van Moolenbroek }
567*b4f34f94SDavid van Moolenbroek 
568*b4f34f94SDavid van Moolenbroek static void __attribute__((__format__(__printf__, 3, 4)))
appendprintf(char ** bp,size_t * lbp,const char * fmt,...)569*b4f34f94SDavid van Moolenbroek appendprintf(char **bp, size_t *lbp, const char *fmt, ...)
570*b4f34f94SDavid van Moolenbroek {
571*b4f34f94SDavid van Moolenbroek 	int r;
572*b4f34f94SDavid van Moolenbroek 	va_list ap;
573*b4f34f94SDavid van Moolenbroek 
574*b4f34f94SDavid van Moolenbroek 	va_start(ap, fmt);
575*b4f34f94SDavid van Moolenbroek 	r = vsnprintf(*bp, *lbp, fmt, ap);
576*b4f34f94SDavid van Moolenbroek 	va_end(ap);
577*b4f34f94SDavid van Moolenbroek 	if (r < 0 || (size_t)r > *lbp)
578*b4f34f94SDavid van Moolenbroek 		r = *lbp;
579*b4f34f94SDavid van Moolenbroek 	*bp += r;
580*b4f34f94SDavid van Moolenbroek 	*lbp -= r;
581*b4f34f94SDavid van Moolenbroek }
582*b4f34f94SDavid van Moolenbroek 
583*b4f34f94SDavid van Moolenbroek /*
584*b4f34f94SDavid van Moolenbroek  * ********************************************************************
585*b4f34f94SDavid van Moolenbroek  * print this node and any others underneath it
586*b4f34f94SDavid van Moolenbroek  * ********************************************************************
587*b4f34f94SDavid van Moolenbroek  */
588*b4f34f94SDavid van Moolenbroek static void
print_tree(int * name,u_int namelen,struct sysctlnode * pnode,u_int type,int add,regex_t * re,size_t * lastcompiled)589*b4f34f94SDavid van Moolenbroek print_tree(int *name, u_int namelen, struct sysctlnode *pnode, u_int type,
590*b4f34f94SDavid van Moolenbroek    int add, regex_t *re, size_t *lastcompiled)
591*b4f34f94SDavid van Moolenbroek {
592*b4f34f94SDavid van Moolenbroek 	struct sysctlnode *node;
593*b4f34f94SDavid van Moolenbroek 	int rc;
594*b4f34f94SDavid van Moolenbroek 	size_t ni, sz, ldp, lsp;
595*b4f34f94SDavid van Moolenbroek 	char *sp, *dp, *tsp, *tdp;
596*b4f34f94SDavid van Moolenbroek 	const struct handlespec *p;
597*b4f34f94SDavid van Moolenbroek 
598*b4f34f94SDavid van Moolenbroek 	sp = tsp = &gsname[strlen(gsname)];
599*b4f34f94SDavid van Moolenbroek 	dp = tdp = &gdname[strlen(gdname)];
600*b4f34f94SDavid van Moolenbroek 	ldp = sizeof(gdname) - (dp - gdname);
601*b4f34f94SDavid van Moolenbroek 	lsp = sizeof(gsname) - (sp - gsname);
602*b4f34f94SDavid van Moolenbroek 
603*b4f34f94SDavid van Moolenbroek 	if (sp != &gsname[0] && dp == &gdname[0]) {
604*b4f34f94SDavid van Moolenbroek 		/*
605*b4f34f94SDavid van Moolenbroek 		 * aw...shucks.  now we must play catch up
606*b4f34f94SDavid van Moolenbroek 		 */
607*b4f34f94SDavid van Moolenbroek 		for (ni = 0; ni < namelen; ni++)
608*b4f34f94SDavid van Moolenbroek 			appendprintf(&tdp, &ldp, "%s%d", ni > 0 ? "." : "",
609*b4f34f94SDavid van Moolenbroek 			    name[ni]);
610*b4f34f94SDavid van Moolenbroek 	}
611*b4f34f94SDavid van Moolenbroek 
612*b4f34f94SDavid van Moolenbroek 	if (pnode == NULL)
613*b4f34f94SDavid van Moolenbroek 		pnode = &my_root;
614*b4f34f94SDavid van Moolenbroek 	else if (add) {
615*b4f34f94SDavid van Moolenbroek 		appendprintf(&tsp, &lsp, "%s%s", namelen > 1 ? sep : "",
616*b4f34f94SDavid van Moolenbroek 			pnode->sysctl_name);
617*b4f34f94SDavid van Moolenbroek 		appendprintf(&tdp, &ldp, "%s%d", namelen > 1 ? "." : "",
618*b4f34f94SDavid van Moolenbroek 			pnode->sysctl_num);
619*b4f34f94SDavid van Moolenbroek 	}
620*b4f34f94SDavid van Moolenbroek 
621*b4f34f94SDavid van Moolenbroek 	if (Mflag && pnode != &my_root) {
622*b4f34f94SDavid van Moolenbroek 		if (nflag)
623*b4f34f94SDavid van Moolenbroek 			printf("%s: ", gdname);
624*b4f34f94SDavid van Moolenbroek 		else
625*b4f34f94SDavid van Moolenbroek 			printf("%s (%s): ", gsname, gdname);
626*b4f34f94SDavid van Moolenbroek 		printf("CTLTYPE_%s", st(type));
627*b4f34f94SDavid van Moolenbroek 		if (type == CTLTYPE_NODE) {
628*b4f34f94SDavid van Moolenbroek 			if (SYSCTL_FLAGS(pnode->sysctl_flags) & CTLFLAG_ALIAS)
629*b4f34f94SDavid van Moolenbroek 				printf(", alias %d",
630*b4f34f94SDavid van Moolenbroek 				       pnode->sysctl_alias);
631*b4f34f94SDavid van Moolenbroek 			else
632*b4f34f94SDavid van Moolenbroek 				printf(", children %d/%d",
633*b4f34f94SDavid van Moolenbroek 				       pnode->sysctl_clen,
634*b4f34f94SDavid van Moolenbroek 				       pnode->sysctl_csize);
635*b4f34f94SDavid van Moolenbroek 		}
636*b4f34f94SDavid van Moolenbroek 		printf(", size %zu", pnode->sysctl_size);
637*b4f34f94SDavid van Moolenbroek 		printf(", flags 0x%x<%s>",
638*b4f34f94SDavid van Moolenbroek 		       SYSCTL_FLAGS(pnode->sysctl_flags),
639*b4f34f94SDavid van Moolenbroek 		       sf(SYSCTL_FLAGS(pnode->sysctl_flags)));
640*b4f34f94SDavid van Moolenbroek 		if (pnode->sysctl_func)
641*b4f34f94SDavid van Moolenbroek 			printf(", func=%p", pnode->sysctl_func);
642*b4f34f94SDavid van Moolenbroek 		printf(", ver=%d", pnode->sysctl_ver);
643*b4f34f94SDavid van Moolenbroek 		printf("\n");
644*b4f34f94SDavid van Moolenbroek 		if (type != CTLTYPE_NODE) {
645*b4f34f94SDavid van Moolenbroek 			*sp = *dp = '\0';
646*b4f34f94SDavid van Moolenbroek 			return;
647*b4f34f94SDavid van Moolenbroek 		}
648*b4f34f94SDavid van Moolenbroek 	}
649*b4f34f94SDavid van Moolenbroek 
650*b4f34f94SDavid van Moolenbroek 	if (dflag && pnode != &my_root) {
651*b4f34f94SDavid van Moolenbroek 		if (Aflag || type != CTLTYPE_NODE) {
652*b4f34f94SDavid van Moolenbroek 			if (pnode->sysctl_desc == NULL)
653*b4f34f94SDavid van Moolenbroek 				getdesc1(name, namelen, pnode);
654*b4f34f94SDavid van Moolenbroek 			if (Aflag || !add ||
655*b4f34f94SDavid van Moolenbroek 			    (pnode->sysctl_desc != NULL &&
656*b4f34f94SDavid van Moolenbroek 			     pnode->sysctl_desc != (const char*)-1)) {
657*b4f34f94SDavid van Moolenbroek 				if (!nflag)
658*b4f34f94SDavid van Moolenbroek 					printf("%s: ", gsname);
659*b4f34f94SDavid van Moolenbroek 				if (pnode->sysctl_desc == NULL ||
660*b4f34f94SDavid van Moolenbroek 				    pnode->sysctl_desc == (const char*)-1)
661*b4f34f94SDavid van Moolenbroek 					printf("(no description)\n");
662*b4f34f94SDavid van Moolenbroek 				else
663*b4f34f94SDavid van Moolenbroek 					printf("%s\n", pnode->sysctl_desc);
664*b4f34f94SDavid van Moolenbroek 			}
665*b4f34f94SDavid van Moolenbroek 		}
666*b4f34f94SDavid van Moolenbroek 
667*b4f34f94SDavid van Moolenbroek 		if (type != CTLTYPE_NODE) {
668*b4f34f94SDavid van Moolenbroek 			*sp = *dp = '\0';
669*b4f34f94SDavid van Moolenbroek 			return;
670*b4f34f94SDavid van Moolenbroek 		}
671*b4f34f94SDavid van Moolenbroek 	}
672*b4f34f94SDavid van Moolenbroek 
673*b4f34f94SDavid van Moolenbroek 	/*
674*b4f34f94SDavid van Moolenbroek 	 * if this is an alias and we added our name, that means we
675*b4f34f94SDavid van Moolenbroek 	 * got here by recursing down into the tree, so skip it.  The
676*b4f34f94SDavid van Moolenbroek 	 * only way to print an aliased node is with either -M or by
677*b4f34f94SDavid van Moolenbroek 	 * name specifically.
678*b4f34f94SDavid van Moolenbroek 	 */
679*b4f34f94SDavid van Moolenbroek 	if (SYSCTL_FLAGS(pnode->sysctl_flags) & CTLFLAG_ALIAS && add) {
680*b4f34f94SDavid van Moolenbroek 		*sp = *dp = '\0';
681*b4f34f94SDavid van Moolenbroek 		return;
682*b4f34f94SDavid van Moolenbroek 	}
683*b4f34f94SDavid van Moolenbroek 
684*b4f34f94SDavid van Moolenbroek 	canonicalize(gsname, canonname);
685*b4f34f94SDavid van Moolenbroek 	p = findhandler(canonname, re, lastcompiled);
686*b4f34f94SDavid van Moolenbroek 	if (type != CTLTYPE_NODE && p != NULL) {
687*b4f34f94SDavid van Moolenbroek 		if (p->ps_p == NULL) {
688*b4f34f94SDavid van Moolenbroek 			sysctlperror("Cannot print `%s': %s\n", gsname,
689*b4f34f94SDavid van Moolenbroek 			    strerror(EOPNOTSUPP));
690*b4f34f94SDavid van Moolenbroek 			exit(EXIT_FAILURE);
691*b4f34f94SDavid van Moolenbroek 		}
692*b4f34f94SDavid van Moolenbroek 		(*p->ps_p)(gsname, gdname, NULL, name, namelen, pnode, type,
693*b4f34f94SDavid van Moolenbroek 			   __UNCONST(p->ps_d));
694*b4f34f94SDavid van Moolenbroek 		*sp = *dp = '\0';
695*b4f34f94SDavid van Moolenbroek 		return;
696*b4f34f94SDavid van Moolenbroek 	}
697*b4f34f94SDavid van Moolenbroek 
698*b4f34f94SDavid van Moolenbroek 	if (type != CTLTYPE_NODE && pnode->sysctl_size == 0) {
699*b4f34f94SDavid van Moolenbroek 		rc = prog_sysctl(&name[0], namelen, NULL, &sz, NULL, 0);
700*b4f34f94SDavid van Moolenbroek 		if (rc == -1) {
701*b4f34f94SDavid van Moolenbroek 			sysctlerror(1);
702*b4f34f94SDavid van Moolenbroek 			*sp = *dp = '\0';
703*b4f34f94SDavid van Moolenbroek 			return;
704*b4f34f94SDavid van Moolenbroek 		}
705*b4f34f94SDavid van Moolenbroek 		if (sz == 0) {
706*b4f34f94SDavid van Moolenbroek 			if ((Aflag || req) && !Mflag)
707*b4f34f94SDavid van Moolenbroek 				printf("%s: node contains no data\n", gsname);
708*b4f34f94SDavid van Moolenbroek 			*sp = *dp = '\0';
709*b4f34f94SDavid van Moolenbroek 			return;
710*b4f34f94SDavid van Moolenbroek 		}
711*b4f34f94SDavid van Moolenbroek 	}
712*b4f34f94SDavid van Moolenbroek 	else
713*b4f34f94SDavid van Moolenbroek 		sz = pnode->sysctl_size;
714*b4f34f94SDavid van Moolenbroek 
715*b4f34f94SDavid van Moolenbroek 	switch (type) {
716*b4f34f94SDavid van Moolenbroek 	case CTLTYPE_NODE: {
717*b4f34f94SDavid van Moolenbroek 		__learn_tree(name, namelen, pnode);
718*b4f34f94SDavid van Moolenbroek 		node = pnode->sysctl_child;
719*b4f34f94SDavid van Moolenbroek 		if (node == NULL) {
720*b4f34f94SDavid van Moolenbroek 			if (dflag)
721*b4f34f94SDavid van Moolenbroek 				/* do nothing */;
722*b4f34f94SDavid van Moolenbroek 			else if (p != NULL)
723*b4f34f94SDavid van Moolenbroek 				(*p->ps_p)(gsname, gdname, NULL, name, namelen,
724*b4f34f94SDavid van Moolenbroek 					   pnode, type, __UNCONST(p->ps_d));
725*b4f34f94SDavid van Moolenbroek 			else if ((Aflag || req) && !Mflag)
726*b4f34f94SDavid van Moolenbroek 				printf("%s: no children\n", gsname);
727*b4f34f94SDavid van Moolenbroek 		}
728*b4f34f94SDavid van Moolenbroek 		else {
729*b4f34f94SDavid van Moolenbroek 			if (dflag)
730*b4f34f94SDavid van Moolenbroek 				/*
731*b4f34f94SDavid van Moolenbroek 				 * get all descriptions for next level
732*b4f34f94SDavid van Moolenbroek 				 * in one chunk
733*b4f34f94SDavid van Moolenbroek 				 */
734*b4f34f94SDavid van Moolenbroek 				getdesc(name, namelen, pnode);
735*b4f34f94SDavid van Moolenbroek 			req = 0;
736*b4f34f94SDavid van Moolenbroek 			for (ni = 0; ni < pnode->sysctl_clen; ni++) {
737*b4f34f94SDavid van Moolenbroek 				name[namelen] = node[ni].sysctl_num;
738*b4f34f94SDavid van Moolenbroek 				if ((node[ni].sysctl_flags & CTLFLAG_HIDDEN) &&
739*b4f34f94SDavid van Moolenbroek 				    !(Aflag || req))
740*b4f34f94SDavid van Moolenbroek 					continue;
741*b4f34f94SDavid van Moolenbroek 				print_tree(name, namelen + 1, &node[ni],
742*b4f34f94SDavid van Moolenbroek 					   SYSCTL_TYPE(node[ni].sysctl_flags),
743*b4f34f94SDavid van Moolenbroek 					   1, re, lastcompiled);
744*b4f34f94SDavid van Moolenbroek 			}
745*b4f34f94SDavid van Moolenbroek 		}
746*b4f34f94SDavid van Moolenbroek 		break;
747*b4f34f94SDavid van Moolenbroek 	}
748*b4f34f94SDavid van Moolenbroek 	case CTLTYPE_INT: {
749*b4f34f94SDavid van Moolenbroek 		int i;
750*b4f34f94SDavid van Moolenbroek 		rc = prog_sysctl(name, namelen, &i, &sz, NULL, 0);
751*b4f34f94SDavid van Moolenbroek 		if (rc == -1) {
752*b4f34f94SDavid van Moolenbroek 			sysctlerror(1);
753*b4f34f94SDavid van Moolenbroek 			break;
754*b4f34f94SDavid van Moolenbroek 		}
755*b4f34f94SDavid van Moolenbroek 		display_number(pnode, gsname, &i, sizeof(i), DISPLAY_VALUE);
756*b4f34f94SDavid van Moolenbroek 		break;
757*b4f34f94SDavid van Moolenbroek 	}
758*b4f34f94SDavid van Moolenbroek 	case CTLTYPE_BOOL: {
759*b4f34f94SDavid van Moolenbroek 		bool b;
760*b4f34f94SDavid van Moolenbroek 		rc = prog_sysctl(name, namelen, &b, &sz, NULL, 0);
761*b4f34f94SDavid van Moolenbroek 		if (rc == -1) {
762*b4f34f94SDavid van Moolenbroek 			sysctlerror(1);
763*b4f34f94SDavid van Moolenbroek 			break;
764*b4f34f94SDavid van Moolenbroek 		}
765*b4f34f94SDavid van Moolenbroek 		display_number(pnode, gsname, &b, sizeof(b), DISPLAY_VALUE);
766*b4f34f94SDavid van Moolenbroek 		break;
767*b4f34f94SDavid van Moolenbroek 	}
768*b4f34f94SDavid van Moolenbroek 	case CTLTYPE_STRING: {
769*b4f34f94SDavid van Moolenbroek 		unsigned char buf[1024], *tbuf;
770*b4f34f94SDavid van Moolenbroek 		tbuf = buf;
771*b4f34f94SDavid van Moolenbroek 		sz = sizeof(buf);
772*b4f34f94SDavid van Moolenbroek 		rc = prog_sysctl(&name[0], namelen, tbuf, &sz, NULL, 0);
773*b4f34f94SDavid van Moolenbroek 		if (rc == -1 && errno == ENOMEM) {
774*b4f34f94SDavid van Moolenbroek 			tbuf = malloc(sz);
775*b4f34f94SDavid van Moolenbroek 			if (tbuf == NULL) {
776*b4f34f94SDavid van Moolenbroek 				sysctlerror(1);
777*b4f34f94SDavid van Moolenbroek 				break;
778*b4f34f94SDavid van Moolenbroek 			}
779*b4f34f94SDavid van Moolenbroek 			rc = prog_sysctl(&name[0], namelen, tbuf, &sz, NULL, 0);
780*b4f34f94SDavid van Moolenbroek 		}
781*b4f34f94SDavid van Moolenbroek 		if (rc == -1)
782*b4f34f94SDavid van Moolenbroek 			sysctlerror(1);
783*b4f34f94SDavid van Moolenbroek 		else
784*b4f34f94SDavid van Moolenbroek 			display_string(pnode, gsname, tbuf, sz, DISPLAY_VALUE);
785*b4f34f94SDavid van Moolenbroek 		if (tbuf != buf)
786*b4f34f94SDavid van Moolenbroek 			free(tbuf);
787*b4f34f94SDavid van Moolenbroek 		break;
788*b4f34f94SDavid van Moolenbroek 	}
789*b4f34f94SDavid van Moolenbroek 	case CTLTYPE_QUAD: {
790*b4f34f94SDavid van Moolenbroek 		u_quad_t q;
791*b4f34f94SDavid van Moolenbroek 		sz = sizeof(q);
792*b4f34f94SDavid van Moolenbroek 		rc = prog_sysctl(&name[0], namelen, &q, &sz, NULL, 0);
793*b4f34f94SDavid van Moolenbroek 		if (rc == -1) {
794*b4f34f94SDavid van Moolenbroek 			sysctlerror(1);
795*b4f34f94SDavid van Moolenbroek 			break;
796*b4f34f94SDavid van Moolenbroek 		}
797*b4f34f94SDavid van Moolenbroek 		display_number(pnode, gsname, &q, sizeof(q), DISPLAY_VALUE);
798*b4f34f94SDavid van Moolenbroek 		break;
799*b4f34f94SDavid van Moolenbroek 	}
800*b4f34f94SDavid van Moolenbroek 	case CTLTYPE_STRUCT: {
801*b4f34f94SDavid van Moolenbroek 		/*
802*b4f34f94SDavid van Moolenbroek 		 * we shouldn't actually get here, but if we
803*b4f34f94SDavid van Moolenbroek 		 * do, would it be nice to have *something* to
804*b4f34f94SDavid van Moolenbroek 		 * do other than completely ignore the
805*b4f34f94SDavid van Moolenbroek 		 * request.
806*b4f34f94SDavid van Moolenbroek 		 */
807*b4f34f94SDavid van Moolenbroek 		unsigned char *d;
808*b4f34f94SDavid van Moolenbroek 		if ((d = malloc(sz)) == NULL) {
809*b4f34f94SDavid van Moolenbroek 			fprintf(warnfp, "%s: !malloc failed!\n", gsname);
810*b4f34f94SDavid van Moolenbroek 			break;
811*b4f34f94SDavid van Moolenbroek 		}
812*b4f34f94SDavid van Moolenbroek 		rc = prog_sysctl(&name[0], namelen, d, &sz, NULL, 0);
813*b4f34f94SDavid van Moolenbroek 		if (rc == -1) {
814*b4f34f94SDavid van Moolenbroek 			sysctlerror(1);
815*b4f34f94SDavid van Moolenbroek 			break;
816*b4f34f94SDavid van Moolenbroek 		}
817*b4f34f94SDavid van Moolenbroek 		display_struct(pnode, gsname, d, sz, DISPLAY_VALUE);
818*b4f34f94SDavid van Moolenbroek 		free(d);
819*b4f34f94SDavid van Moolenbroek 		break;
820*b4f34f94SDavid van Moolenbroek 	}
821*b4f34f94SDavid van Moolenbroek 	default:
822*b4f34f94SDavid van Moolenbroek 		/* should i print an error here? */
823*b4f34f94SDavid van Moolenbroek 		break;
824*b4f34f94SDavid van Moolenbroek 	}
825*b4f34f94SDavid van Moolenbroek 
826*b4f34f94SDavid van Moolenbroek 	*sp = *dp = '\0';
827*b4f34f94SDavid van Moolenbroek }
828*b4f34f94SDavid van Moolenbroek 
829*b4f34f94SDavid van Moolenbroek /*
830*b4f34f94SDavid van Moolenbroek  * ********************************************************************
831*b4f34f94SDavid van Moolenbroek  * parse a request, possibly determining that it's a create or destroy
832*b4f34f94SDavid van Moolenbroek  * request
833*b4f34f94SDavid van Moolenbroek  * ********************************************************************
834*b4f34f94SDavid van Moolenbroek  */
835*b4f34f94SDavid van Moolenbroek static void
parse(char * l,regex_t * re,size_t * lastcompiled)836*b4f34f94SDavid van Moolenbroek parse(char *l, regex_t *re, size_t *lastcompiled)
837*b4f34f94SDavid van Moolenbroek {
838*b4f34f94SDavid van Moolenbroek 	struct sysctlnode *node;
839*b4f34f94SDavid van Moolenbroek 	const struct handlespec *w;
840*b4f34f94SDavid van Moolenbroek 	int name[CTL_MAXNAME], dodesc = 0;
841*b4f34f94SDavid van Moolenbroek 	u_int namelen, type;
842*b4f34f94SDavid van Moolenbroek 	char *key, *value, *dot;
843*b4f34f94SDavid van Moolenbroek 	size_t sz;
844*b4f34f94SDavid van Moolenbroek 	bool optional = false;
845*b4f34f94SDavid van Moolenbroek 
846*b4f34f94SDavid van Moolenbroek 	req = 1;
847*b4f34f94SDavid van Moolenbroek 	key = l;
848*b4f34f94SDavid van Moolenbroek 
849*b4f34f94SDavid van Moolenbroek 	if ((value = strchr(l, '=')) != NULL) {
850*b4f34f94SDavid van Moolenbroek 		if (value > l && value[-1] == '?') {
851*b4f34f94SDavid van Moolenbroek 			value[-1] = '\0';
852*b4f34f94SDavid van Moolenbroek 			optional = true;
853*b4f34f94SDavid van Moolenbroek 		}
854*b4f34f94SDavid van Moolenbroek 		*value++ = '\0';
855*b4f34f94SDavid van Moolenbroek 	}
856*b4f34f94SDavid van Moolenbroek 
857*b4f34f94SDavid van Moolenbroek 	if ((dot = strpbrk(key, "./")) == NULL)
858*b4f34f94SDavid van Moolenbroek 		sep[0] = '.';
859*b4f34f94SDavid van Moolenbroek 	else
860*b4f34f94SDavid van Moolenbroek 		sep[0] = dot[0];
861*b4f34f94SDavid van Moolenbroek 	sep[1] = '\0';
862*b4f34f94SDavid van Moolenbroek 
863*b4f34f94SDavid van Moolenbroek 	while (key[0] == sep[0] && key[1] == sep[0]) {
864*b4f34f94SDavid van Moolenbroek 		if (value != NULL)
865*b4f34f94SDavid van Moolenbroek 			value[-1] = '=';
866*b4f34f94SDavid van Moolenbroek 		if (strncmp(key + 2, "create", 6) == 0 &&
867*b4f34f94SDavid van Moolenbroek 		    (key[8] == '=' || key[8] == sep[0]))
868*b4f34f94SDavid van Moolenbroek 			parse_create(key + 8 + (key[8] == '=' ? 1 : 0));
869*b4f34f94SDavid van Moolenbroek 		else if (strncmp(key + 2, "destroy", 7) == 0 &&
870*b4f34f94SDavid van Moolenbroek 			 (key[9] == '=' || key[9] == sep[0]))
871*b4f34f94SDavid van Moolenbroek 			parse_destroy(key + 9 + (key[9] == '=' ? 1 : 0));
872*b4f34f94SDavid van Moolenbroek 		else if (strncmp(key + 2, "describe", 8) == 0 &&
873*b4f34f94SDavid van Moolenbroek 			 (key[10] == '=' || key[10] == sep[0])) {
874*b4f34f94SDavid van Moolenbroek 			key += 10 + (key[10] == '=');
875*b4f34f94SDavid van Moolenbroek 			if ((value = strchr(key, '=')) != NULL)
876*b4f34f94SDavid van Moolenbroek 				parse_describe(key);
877*b4f34f94SDavid van Moolenbroek 			else {
878*b4f34f94SDavid van Moolenbroek 				if (!dflag)
879*b4f34f94SDavid van Moolenbroek 					dodesc = 1;
880*b4f34f94SDavid van Moolenbroek 				break;
881*b4f34f94SDavid van Moolenbroek 			}
882*b4f34f94SDavid van Moolenbroek 		}
883*b4f34f94SDavid van Moolenbroek 		else
884*b4f34f94SDavid van Moolenbroek 			sysctlperror("unable to parse '%s'\n", key);
885*b4f34f94SDavid van Moolenbroek 		return;
886*b4f34f94SDavid van Moolenbroek 	}
887*b4f34f94SDavid van Moolenbroek 
888*b4f34f94SDavid van Moolenbroek 	if (stale) {
889*b4f34f94SDavid van Moolenbroek 		purge_tree(&my_root);
890*b4f34f94SDavid van Moolenbroek 		stale = 0;
891*b4f34f94SDavid van Moolenbroek 	}
892*b4f34f94SDavid van Moolenbroek 	node = &my_root;
893*b4f34f94SDavid van Moolenbroek 	namelen = CTL_MAXNAME;
894*b4f34f94SDavid van Moolenbroek 	sz = sizeof(gsname);
895*b4f34f94SDavid van Moolenbroek 
896*b4f34f94SDavid van Moolenbroek 	if (sysctlgetmibinfo(key, &name[0], &namelen, gsname, &sz, &node,
897*b4f34f94SDavid van Moolenbroek 			     SYSCTL_VERSION) == -1) {
898*b4f34f94SDavid van Moolenbroek 		if (optional)
899*b4f34f94SDavid van Moolenbroek 			return;
900*b4f34f94SDavid van Moolenbroek 		sysctlparseerror(namelen, l);
901*b4f34f94SDavid van Moolenbroek 		EXIT(EXIT_FAILURE);
902*b4f34f94SDavid van Moolenbroek 	}
903*b4f34f94SDavid van Moolenbroek 
904*b4f34f94SDavid van Moolenbroek 	type = SYSCTL_TYPE(node->sysctl_flags);
905*b4f34f94SDavid van Moolenbroek 
906*b4f34f94SDavid van Moolenbroek 	if (value == NULL) {
907*b4f34f94SDavid van Moolenbroek 		if (dodesc)
908*b4f34f94SDavid van Moolenbroek 			dflag = 1;
909*b4f34f94SDavid van Moolenbroek 		print_tree(&name[0], namelen, node, type, 0, re, lastcompiled);
910*b4f34f94SDavid van Moolenbroek 		if (dodesc)
911*b4f34f94SDavid van Moolenbroek 			dflag = 0;
912*b4f34f94SDavid van Moolenbroek 		gsname[0] = '\0';
913*b4f34f94SDavid van Moolenbroek 		return;
914*b4f34f94SDavid van Moolenbroek 	}
915*b4f34f94SDavid van Moolenbroek 
916*b4f34f94SDavid van Moolenbroek 	if (fn)
917*b4f34f94SDavid van Moolenbroek 		trim_whitespace(value, 1);
918*b4f34f94SDavid van Moolenbroek 
919*b4f34f94SDavid van Moolenbroek 	if (!wflag) {
920*b4f34f94SDavid van Moolenbroek 		sysctlperror("Must specify -w to set variables\n");
921*b4f34f94SDavid van Moolenbroek 		exit(EXIT_FAILURE);
922*b4f34f94SDavid van Moolenbroek 	}
923*b4f34f94SDavid van Moolenbroek 
924*b4f34f94SDavid van Moolenbroek 	canonicalize(gsname, canonname);
925*b4f34f94SDavid van Moolenbroek 	if (type != CTLTYPE_NODE && (w = findhandler(canonname, re,
926*b4f34f94SDavid van Moolenbroek 	    lastcompiled)) != NULL) {
927*b4f34f94SDavid van Moolenbroek 		if (w->ps_w == NULL) {
928*b4f34f94SDavid van Moolenbroek 			sysctlperror("Cannot write `%s': %s\n", gsname,
929*b4f34f94SDavid van Moolenbroek 			    strerror(EOPNOTSUPP));
930*b4f34f94SDavid van Moolenbroek 			exit(EXIT_FAILURE);
931*b4f34f94SDavid van Moolenbroek 		}
932*b4f34f94SDavid van Moolenbroek 		(*w->ps_w)(gsname, gdname, value, name, namelen, node, type,
933*b4f34f94SDavid van Moolenbroek 			   __UNCONST(w->ps_d));
934*b4f34f94SDavid van Moolenbroek 		gsname[0] = '\0';
935*b4f34f94SDavid van Moolenbroek 		return;
936*b4f34f94SDavid van Moolenbroek 	}
937*b4f34f94SDavid van Moolenbroek 
938*b4f34f94SDavid van Moolenbroek 	switch (type) {
939*b4f34f94SDavid van Moolenbroek 	case CTLTYPE_NODE:
940*b4f34f94SDavid van Moolenbroek 		/*
941*b4f34f94SDavid van Moolenbroek 		 * XXX old behavior is to print.  should we error instead?
942*b4f34f94SDavid van Moolenbroek 		 */
943*b4f34f94SDavid van Moolenbroek 		print_tree(&name[0], namelen, node, CTLTYPE_NODE, 1, re,
944*b4f34f94SDavid van Moolenbroek 		    lastcompiled);
945*b4f34f94SDavid van Moolenbroek 		break;
946*b4f34f94SDavid van Moolenbroek 	case CTLTYPE_INT:
947*b4f34f94SDavid van Moolenbroek 	case CTLTYPE_BOOL:
948*b4f34f94SDavid van Moolenbroek 	case CTLTYPE_QUAD:
949*b4f34f94SDavid van Moolenbroek 		write_number(&name[0], namelen, node, value);
950*b4f34f94SDavid van Moolenbroek 		break;
951*b4f34f94SDavid van Moolenbroek 	case CTLTYPE_STRING:
952*b4f34f94SDavid van Moolenbroek 		write_string(&name[0], namelen, node, value);
953*b4f34f94SDavid van Moolenbroek 		break;
954*b4f34f94SDavid van Moolenbroek 	case CTLTYPE_STRUCT:
955*b4f34f94SDavid van Moolenbroek 		/*
956*b4f34f94SDavid van Moolenbroek 		 * XXX old behavior is to print.  should we error instead?
957*b4f34f94SDavid van Moolenbroek 		 */
958*b4f34f94SDavid van Moolenbroek 		/* fprintf(warnfp, "you can't write to %s\n", gsname); */
959*b4f34f94SDavid van Moolenbroek 		print_tree(&name[0], namelen, node, type, 0, re, lastcompiled);
960*b4f34f94SDavid van Moolenbroek 		break;
961*b4f34f94SDavid van Moolenbroek 	}
962*b4f34f94SDavid van Moolenbroek }
963*b4f34f94SDavid van Moolenbroek 
964*b4f34f94SDavid van Moolenbroek /*
965*b4f34f94SDavid van Moolenbroek 
966*b4f34f94SDavid van Moolenbroek   //create=foo.bar.whatever...,
967*b4f34f94SDavid van Moolenbroek   [type=(int|quad|string|struct|node),]
968*b4f34f94SDavid van Moolenbroek   [size=###,]
969*b4f34f94SDavid van Moolenbroek   [n=###,]
970*b4f34f94SDavid van Moolenbroek   [flags=(iohxparw12),]
971*b4f34f94SDavid van Moolenbroek   [addr=0x####,|symbol=...|value=...]
972*b4f34f94SDavid van Moolenbroek 
973*b4f34f94SDavid van Moolenbroek   size is optional for some types.  type must be set before anything
974*b4f34f94SDavid van Moolenbroek   else.  nodes can have [rwhp], but nothing else applies.  if no
975*b4f34f94SDavid van Moolenbroek   size or type is given, node is asserted.  writeable is the default,
976*b4f34f94SDavid van Moolenbroek   with [rw] being read-only and unconditionally writeable
977*b4f34f94SDavid van Moolenbroek   respectively.  if you specify addr, it is assumed to be the name of
978*b4f34f94SDavid van Moolenbroek   a kernel symbol, if value, CTLFLAG_OWNDATA will be asserted for
979*b4f34f94SDavid van Moolenbroek   strings, CTLFLAG_IMMEDIATE for ints and u_quad_ts.  you cannot
980*b4f34f94SDavid van Moolenbroek   specify both value and addr.
981*b4f34f94SDavid van Moolenbroek 
982*b4f34f94SDavid van Moolenbroek */
983*b4f34f94SDavid van Moolenbroek 
984*b4f34f94SDavid van Moolenbroek static void
parse_create(char * l)985*b4f34f94SDavid van Moolenbroek parse_create(char *l)
986*b4f34f94SDavid van Moolenbroek {
987*b4f34f94SDavid van Moolenbroek 	struct sysctlnode node;
988*b4f34f94SDavid van Moolenbroek 	size_t sz;
989*b4f34f94SDavid van Moolenbroek 	char *nname, *key, *value, *data, *addr, *c, *t;
990*b4f34f94SDavid van Moolenbroek 	int name[CTL_MAXNAME], i, rc, method, flags, rw;
991*b4f34f94SDavid van Moolenbroek 	u_int namelen, type;
992*b4f34f94SDavid van Moolenbroek 	u_quad_t uq;
993*b4f34f94SDavid van Moolenbroek 	quad_t q;
994*b4f34f94SDavid van Moolenbroek 	bool b;
995*b4f34f94SDavid van Moolenbroek 
996*b4f34f94SDavid van Moolenbroek 	if (!wflag) {
997*b4f34f94SDavid van Moolenbroek 		sysctlperror("Must specify -w to create nodes\n");
998*b4f34f94SDavid van Moolenbroek 		exit(EXIT_FAILURE);
999*b4f34f94SDavid van Moolenbroek 	}
1000*b4f34f94SDavid van Moolenbroek 
1001*b4f34f94SDavid van Moolenbroek 	/*
1002*b4f34f94SDavid van Moolenbroek 	 * these are the pieces that make up the description of a new
1003*b4f34f94SDavid van Moolenbroek 	 * node
1004*b4f34f94SDavid van Moolenbroek 	 */
1005*b4f34f94SDavid van Moolenbroek 	memset(&node, 0, sizeof(node));
1006*b4f34f94SDavid van Moolenbroek 	node.sysctl_num = CTL_CREATE;  /* any number is fine */
1007*b4f34f94SDavid van Moolenbroek 	flags = 0;
1008*b4f34f94SDavid van Moolenbroek 	rw = -1;
1009*b4f34f94SDavid van Moolenbroek 	type = 0;
1010*b4f34f94SDavid van Moolenbroek 	sz = 0;
1011*b4f34f94SDavid van Moolenbroek 	data = addr = NULL;
1012*b4f34f94SDavid van Moolenbroek 	memset(name, 0, sizeof(name));
1013*b4f34f94SDavid van Moolenbroek 	namelen = 0;
1014*b4f34f94SDavid van Moolenbroek 	method = 0;
1015*b4f34f94SDavid van Moolenbroek 
1016*b4f34f94SDavid van Moolenbroek 	/*
1017*b4f34f94SDavid van Moolenbroek 	 * misc stuff used when constructing
1018*b4f34f94SDavid van Moolenbroek 	 */
1019*b4f34f94SDavid van Moolenbroek 	i = 0;
1020*b4f34f94SDavid van Moolenbroek 	b = false;
1021*b4f34f94SDavid van Moolenbroek 	uq = 0;
1022*b4f34f94SDavid van Moolenbroek 	key = NULL;
1023*b4f34f94SDavid van Moolenbroek 	value = NULL;
1024*b4f34f94SDavid van Moolenbroek 
1025*b4f34f94SDavid van Moolenbroek 	/*
1026*b4f34f94SDavid van Moolenbroek 	 * the name of the thing we're trying to create is first, so
1027*b4f34f94SDavid van Moolenbroek 	 * pick it off.
1028*b4f34f94SDavid van Moolenbroek 	 */
1029*b4f34f94SDavid van Moolenbroek 	nname = l;
1030*b4f34f94SDavid van Moolenbroek 	if ((c = strchr(nname, ',')) != NULL)
1031*b4f34f94SDavid van Moolenbroek 		*c++ = '\0';
1032*b4f34f94SDavid van Moolenbroek 
1033*b4f34f94SDavid van Moolenbroek 	while (c != NULL) {
1034*b4f34f94SDavid van Moolenbroek 
1035*b4f34f94SDavid van Moolenbroek 		/*
1036*b4f34f94SDavid van Moolenbroek 		 * pull off the next "key=value" pair
1037*b4f34f94SDavid van Moolenbroek 		 */
1038*b4f34f94SDavid van Moolenbroek 		key = c;
1039*b4f34f94SDavid van Moolenbroek 		if ((t = strchr(key, '=')) != NULL) {
1040*b4f34f94SDavid van Moolenbroek 			*t++ = '\0';
1041*b4f34f94SDavid van Moolenbroek 			value = t;
1042*b4f34f94SDavid van Moolenbroek 		}
1043*b4f34f94SDavid van Moolenbroek 		else
1044*b4f34f94SDavid van Moolenbroek 			value = NULL;
1045*b4f34f94SDavid van Moolenbroek 
1046*b4f34f94SDavid van Moolenbroek 		/*
1047*b4f34f94SDavid van Moolenbroek 		 * if the "key" is "value", then that eats the rest of
1048*b4f34f94SDavid van Moolenbroek 		 * the string, so we're done, otherwise bite it off at
1049*b4f34f94SDavid van Moolenbroek 		 * the next comma.
1050*b4f34f94SDavid van Moolenbroek 		 */
1051*b4f34f94SDavid van Moolenbroek 		if (strcmp(key, "value") == 0) {
1052*b4f34f94SDavid van Moolenbroek 			c = NULL;
1053*b4f34f94SDavid van Moolenbroek 			data = value;
1054*b4f34f94SDavid van Moolenbroek 			break;
1055*b4f34f94SDavid van Moolenbroek 		}
1056*b4f34f94SDavid van Moolenbroek 		else if (value) {
1057*b4f34f94SDavid van Moolenbroek 			if ((c = strchr(value, ',')) != NULL)
1058*b4f34f94SDavid van Moolenbroek 				*c++ = '\0';
1059*b4f34f94SDavid van Moolenbroek 		}
1060*b4f34f94SDavid van Moolenbroek 
1061*b4f34f94SDavid van Moolenbroek 		/*
1062*b4f34f94SDavid van Moolenbroek 		 * note that we (mostly) let the invoker of prog_sysctl(8)
1063*b4f34f94SDavid van Moolenbroek 		 * play rampant here and depend on the kernel to tell
1064*b4f34f94SDavid van Moolenbroek 		 * them that they were wrong.  well...within reason.
1065*b4f34f94SDavid van Moolenbroek 		 * we later check the various parameters against each
1066*b4f34f94SDavid van Moolenbroek 		 * other to make sure it makes some sort of sense.
1067*b4f34f94SDavid van Moolenbroek 		 */
1068*b4f34f94SDavid van Moolenbroek 		if (strcmp(key, "addr") == 0) {
1069*b4f34f94SDavid van Moolenbroek 			/*
1070*b4f34f94SDavid van Moolenbroek 			 * we can't check these two.  only the kernel
1071*b4f34f94SDavid van Moolenbroek 			 * can tell us when it fails to find the name
1072*b4f34f94SDavid van Moolenbroek 			 * (or if the address is invalid).
1073*b4f34f94SDavid van Moolenbroek 			 */
1074*b4f34f94SDavid van Moolenbroek 			if (method != 0) {
1075*b4f34f94SDavid van Moolenbroek 				sysctlperror(
1076*b4f34f94SDavid van Moolenbroek 				    "%s: already have %s for new node\n",
1077*b4f34f94SDavid van Moolenbroek 				    nname,
1078*b4f34f94SDavid van Moolenbroek 				    method == CTL_CREATE ? "addr" : "symbol");
1079*b4f34f94SDavid van Moolenbroek 				EXIT(EXIT_FAILURE);
1080*b4f34f94SDavid van Moolenbroek 			}
1081*b4f34f94SDavid van Moolenbroek 			if (value == NULL) {
1082*b4f34f94SDavid van Moolenbroek 				sysctlperror("%s: missing value\n", nname);
1083*b4f34f94SDavid van Moolenbroek 				EXIT(EXIT_FAILURE);
1084*b4f34f94SDavid van Moolenbroek 			}
1085*b4f34f94SDavid van Moolenbroek 			errno = 0;
1086*b4f34f94SDavid van Moolenbroek 			addr = (void*)strtoul(value, &t, 0);
1087*b4f34f94SDavid van Moolenbroek 			if (t == value || *t != '\0' || errno != 0) {
1088*b4f34f94SDavid van Moolenbroek 				sysctlperror(
1089*b4f34f94SDavid van Moolenbroek 				    "%s: '%s' is not a valid address\n",
1090*b4f34f94SDavid van Moolenbroek 				    nname, value);
1091*b4f34f94SDavid van Moolenbroek 				EXIT(EXIT_FAILURE);
1092*b4f34f94SDavid van Moolenbroek 			}
1093*b4f34f94SDavid van Moolenbroek 			method = CTL_CREATE;
1094*b4f34f94SDavid van Moolenbroek 		}
1095*b4f34f94SDavid van Moolenbroek 		else if (strcmp(key, "symbol") == 0) {
1096*b4f34f94SDavid van Moolenbroek 			if (method != 0) {
1097*b4f34f94SDavid van Moolenbroek 				sysctlperror(
1098*b4f34f94SDavid van Moolenbroek 				    "%s: already have %s for new node\n",
1099*b4f34f94SDavid van Moolenbroek 				    nname,
1100*b4f34f94SDavid van Moolenbroek 				    method == CTL_CREATE ? "addr" : "symbol");
1101*b4f34f94SDavid van Moolenbroek 				EXIT(EXIT_FAILURE);
1102*b4f34f94SDavid van Moolenbroek 			}
1103*b4f34f94SDavid van Moolenbroek 			addr = value;
1104*b4f34f94SDavid van Moolenbroek 			method = CTL_CREATESYM;
1105*b4f34f94SDavid van Moolenbroek 		}
1106*b4f34f94SDavid van Moolenbroek 		else if (strcmp(key, "type") == 0) {
1107*b4f34f94SDavid van Moolenbroek 			if (value == NULL) {
1108*b4f34f94SDavid van Moolenbroek 				sysctlperror("%s: missing value\n", nname);
1109*b4f34f94SDavid van Moolenbroek 				EXIT(EXIT_FAILURE);
1110*b4f34f94SDavid van Moolenbroek 			}
1111*b4f34f94SDavid van Moolenbroek 			if (strcmp(value, "node") == 0)
1112*b4f34f94SDavid van Moolenbroek 				type = CTLTYPE_NODE;
1113*b4f34f94SDavid van Moolenbroek 			else if (strcmp(value, "int") == 0) {
1114*b4f34f94SDavid van Moolenbroek 				sz = sizeof(int);
1115*b4f34f94SDavid van Moolenbroek 				type = CTLTYPE_INT;
1116*b4f34f94SDavid van Moolenbroek 			}
1117*b4f34f94SDavid van Moolenbroek 			else if (strcmp(value, "bool") == 0) {
1118*b4f34f94SDavid van Moolenbroek 				sz = sizeof(bool);
1119*b4f34f94SDavid van Moolenbroek 				type = CTLTYPE_BOOL;
1120*b4f34f94SDavid van Moolenbroek 			}
1121*b4f34f94SDavid van Moolenbroek 			else if (strcmp(value, "string") == 0)
1122*b4f34f94SDavid van Moolenbroek 				type = CTLTYPE_STRING;
1123*b4f34f94SDavid van Moolenbroek 			else if (strcmp(value, "quad") == 0) {
1124*b4f34f94SDavid van Moolenbroek 				sz = sizeof(u_quad_t);
1125*b4f34f94SDavid van Moolenbroek 				type = CTLTYPE_QUAD;
1126*b4f34f94SDavid van Moolenbroek 			}
1127*b4f34f94SDavid van Moolenbroek 			else if (strcmp(value, "struct") == 0)
1128*b4f34f94SDavid van Moolenbroek 				type = CTLTYPE_STRUCT;
1129*b4f34f94SDavid van Moolenbroek 			else {
1130*b4f34f94SDavid van Moolenbroek 				sysctlperror(
1131*b4f34f94SDavid van Moolenbroek 					"%s: '%s' is not a valid type\n",
1132*b4f34f94SDavid van Moolenbroek 					nname, value);
1133*b4f34f94SDavid van Moolenbroek 				EXIT(EXIT_FAILURE);
1134*b4f34f94SDavid van Moolenbroek 			}
1135*b4f34f94SDavid van Moolenbroek 		}
1136*b4f34f94SDavid van Moolenbroek 		else if (strcmp(key, "size") == 0) {
1137*b4f34f94SDavid van Moolenbroek 			if (value == NULL) {
1138*b4f34f94SDavid van Moolenbroek 				sysctlperror("%s: missing value\n", nname);
1139*b4f34f94SDavid van Moolenbroek 				EXIT(EXIT_FAILURE);
1140*b4f34f94SDavid van Moolenbroek 			}
1141*b4f34f94SDavid van Moolenbroek 			errno = 0;
1142*b4f34f94SDavid van Moolenbroek 			/*
1143*b4f34f94SDavid van Moolenbroek 			 * yes, i know size_t is not an unsigned long,
1144*b4f34f94SDavid van Moolenbroek 			 * but we can all agree that it ought to be,
1145*b4f34f94SDavid van Moolenbroek 			 * right?
1146*b4f34f94SDavid van Moolenbroek 			 */
1147*b4f34f94SDavid van Moolenbroek 			sz = strtoul(value, &t, 0);
1148*b4f34f94SDavid van Moolenbroek 			if (t == value || *t != '\0' || errno != 0) {
1149*b4f34f94SDavid van Moolenbroek 				sysctlperror(
1150*b4f34f94SDavid van Moolenbroek 					"%s: '%s' is not a valid size\n",
1151*b4f34f94SDavid van Moolenbroek 					nname, value);
1152*b4f34f94SDavid van Moolenbroek 				EXIT(EXIT_FAILURE);
1153*b4f34f94SDavid van Moolenbroek 			}
1154*b4f34f94SDavid van Moolenbroek 		}
1155*b4f34f94SDavid van Moolenbroek 		else if (strcmp(key, "n") == 0) {
1156*b4f34f94SDavid van Moolenbroek 			if (value == NULL) {
1157*b4f34f94SDavid van Moolenbroek 				sysctlperror("%s: missing value\n", nname);
1158*b4f34f94SDavid van Moolenbroek 				EXIT(EXIT_FAILURE);
1159*b4f34f94SDavid van Moolenbroek 			}
1160*b4f34f94SDavid van Moolenbroek 			errno = 0;
1161*b4f34f94SDavid van Moolenbroek 			q = strtoll(value, &t, 0);
1162*b4f34f94SDavid van Moolenbroek 			if (t == value || *t != '\0' || errno != 0 ||
1163*b4f34f94SDavid van Moolenbroek 			    q < INT_MIN || q > UINT_MAX) {
1164*b4f34f94SDavid van Moolenbroek 				sysctlperror(
1165*b4f34f94SDavid van Moolenbroek 				    "%s: '%s' is not a valid mib number\n",
1166*b4f34f94SDavid van Moolenbroek 				    nname, value);
1167*b4f34f94SDavid van Moolenbroek 				EXIT(EXIT_FAILURE);
1168*b4f34f94SDavid van Moolenbroek 			}
1169*b4f34f94SDavid van Moolenbroek 			node.sysctl_num = (int)q;
1170*b4f34f94SDavid van Moolenbroek 		}
1171*b4f34f94SDavid van Moolenbroek 		else if (strcmp(key, "flags") == 0) {
1172*b4f34f94SDavid van Moolenbroek 			if (value == NULL) {
1173*b4f34f94SDavid van Moolenbroek 				sysctlperror("%s: missing value\n", nname);
1174*b4f34f94SDavid van Moolenbroek 				EXIT(EXIT_FAILURE);
1175*b4f34f94SDavid van Moolenbroek 			}
1176*b4f34f94SDavid van Moolenbroek 			t = value;
1177*b4f34f94SDavid van Moolenbroek 			while (*t != '\0') {
1178*b4f34f94SDavid van Moolenbroek 				switch (*t) {
1179*b4f34f94SDavid van Moolenbroek 				case 'a':
1180*b4f34f94SDavid van Moolenbroek 					flags |= CTLFLAG_ANYWRITE;
1181*b4f34f94SDavid van Moolenbroek 					break;
1182*b4f34f94SDavid van Moolenbroek 				case 'h':
1183*b4f34f94SDavid van Moolenbroek 					flags |= CTLFLAG_HIDDEN;
1184*b4f34f94SDavid van Moolenbroek 					break;
1185*b4f34f94SDavid van Moolenbroek 				case 'i':
1186*b4f34f94SDavid van Moolenbroek 					flags |= CTLFLAG_IMMEDIATE;
1187*b4f34f94SDavid van Moolenbroek 					break;
1188*b4f34f94SDavid van Moolenbroek 				case 'o':
1189*b4f34f94SDavid van Moolenbroek 					flags |= CTLFLAG_OWNDATA;
1190*b4f34f94SDavid van Moolenbroek 					break;
1191*b4f34f94SDavid van Moolenbroek 				case 'p':
1192*b4f34f94SDavid van Moolenbroek 					flags |= CTLFLAG_PRIVATE;
1193*b4f34f94SDavid van Moolenbroek 					break;
1194*b4f34f94SDavid van Moolenbroek 				case 'u':
1195*b4f34f94SDavid van Moolenbroek 					flags |= CTLFLAG_UNSIGNED;
1196*b4f34f94SDavid van Moolenbroek 					break;
1197*b4f34f94SDavid van Moolenbroek 				case 'x':
1198*b4f34f94SDavid van Moolenbroek 					flags |= CTLFLAG_HEX;
1199*b4f34f94SDavid van Moolenbroek 					break;
1200*b4f34f94SDavid van Moolenbroek 
1201*b4f34f94SDavid van Moolenbroek 				case 'r':
1202*b4f34f94SDavid van Moolenbroek 					rw = CTLFLAG_READONLY;
1203*b4f34f94SDavid van Moolenbroek 					break;
1204*b4f34f94SDavid van Moolenbroek 				case 'w':
1205*b4f34f94SDavid van Moolenbroek 					rw = CTLFLAG_READWRITE;
1206*b4f34f94SDavid van Moolenbroek 					break;
1207*b4f34f94SDavid van Moolenbroek 				default:
1208*b4f34f94SDavid van Moolenbroek 					sysctlperror(
1209*b4f34f94SDavid van Moolenbroek 					   "%s: '%c' is not a valid flag\n",
1210*b4f34f94SDavid van Moolenbroek 					    nname, *t);
1211*b4f34f94SDavid van Moolenbroek 					EXIT(EXIT_FAILURE);
1212*b4f34f94SDavid van Moolenbroek 				}
1213*b4f34f94SDavid van Moolenbroek 				t++;
1214*b4f34f94SDavid van Moolenbroek 			}
1215*b4f34f94SDavid van Moolenbroek 		}
1216*b4f34f94SDavid van Moolenbroek 		else {
1217*b4f34f94SDavid van Moolenbroek 			sysctlperror("%s: unrecognized keyword '%s'\n",
1218*b4f34f94SDavid van Moolenbroek 				     nname, key);
1219*b4f34f94SDavid van Moolenbroek 			EXIT(EXIT_FAILURE);
1220*b4f34f94SDavid van Moolenbroek 		}
1221*b4f34f94SDavid van Moolenbroek 	}
1222*b4f34f94SDavid van Moolenbroek 
1223*b4f34f94SDavid van Moolenbroek 	/*
1224*b4f34f94SDavid van Moolenbroek 	 * now that we've finished parsing the given string, fill in
1225*b4f34f94SDavid van Moolenbroek 	 * anything they didn't specify
1226*b4f34f94SDavid van Moolenbroek 	 */
1227*b4f34f94SDavid van Moolenbroek 	if (type == 0)
1228*b4f34f94SDavid van Moolenbroek 		type = CTLTYPE_NODE;
1229*b4f34f94SDavid van Moolenbroek 
1230*b4f34f94SDavid van Moolenbroek 	/*
1231*b4f34f94SDavid van Moolenbroek 	 * the "data" can be interpreted various ways depending on the
1232*b4f34f94SDavid van Moolenbroek 	 * type of node we're creating, as can the size
1233*b4f34f94SDavid van Moolenbroek 	 */
1234*b4f34f94SDavid van Moolenbroek 	if (data != NULL) {
1235*b4f34f94SDavid van Moolenbroek 		if (addr != NULL) {
1236*b4f34f94SDavid van Moolenbroek 			sysctlperror(
1237*b4f34f94SDavid van Moolenbroek 				"%s: cannot specify both value and "
1238*b4f34f94SDavid van Moolenbroek 				"address\n", nname);
1239*b4f34f94SDavid van Moolenbroek 			EXIT(EXIT_FAILURE);
1240*b4f34f94SDavid van Moolenbroek 		}
1241*b4f34f94SDavid van Moolenbroek 
1242*b4f34f94SDavid van Moolenbroek 		switch (type) {
1243*b4f34f94SDavid van Moolenbroek 		case CTLTYPE_INT:
1244*b4f34f94SDavid van Moolenbroek 			errno = 0;
1245*b4f34f94SDavid van Moolenbroek 			q = strtoll(data, &t, 0);
1246*b4f34f94SDavid van Moolenbroek 			if (t == data || *t != '\0' || errno != 0 ||
1247*b4f34f94SDavid van Moolenbroek 				q < INT_MIN || q > UINT_MAX) {
1248*b4f34f94SDavid van Moolenbroek 				sysctlperror(
1249*b4f34f94SDavid van Moolenbroek 				    "%s: '%s' is not a valid integer\n",
1250*b4f34f94SDavid van Moolenbroek 				    nname, value);
1251*b4f34f94SDavid van Moolenbroek 				EXIT(EXIT_FAILURE);
1252*b4f34f94SDavid van Moolenbroek 			}
1253*b4f34f94SDavid van Moolenbroek 			i = (int)q;
1254*b4f34f94SDavid van Moolenbroek 			if (!(flags & CTLFLAG_OWNDATA)) {
1255*b4f34f94SDavid van Moolenbroek 				flags |= CTLFLAG_IMMEDIATE;
1256*b4f34f94SDavid van Moolenbroek 				node.sysctl_idata = i;
1257*b4f34f94SDavid van Moolenbroek 			}
1258*b4f34f94SDavid van Moolenbroek 			else
1259*b4f34f94SDavid van Moolenbroek 				node.sysctl_data = &i;
1260*b4f34f94SDavid van Moolenbroek 			if (sz == 0)
1261*b4f34f94SDavid van Moolenbroek 				sz = sizeof(int);
1262*b4f34f94SDavid van Moolenbroek 			break;
1263*b4f34f94SDavid van Moolenbroek 		case CTLTYPE_BOOL:
1264*b4f34f94SDavid van Moolenbroek 			errno = 0;
1265*b4f34f94SDavid van Moolenbroek 			q = strtoll(data, &t, 0);
1266*b4f34f94SDavid van Moolenbroek 			if (t == data || *t != '\0' || errno != 0 ||
1267*b4f34f94SDavid van Moolenbroek 				(q != 0 && q != 1)) {
1268*b4f34f94SDavid van Moolenbroek 				sysctlperror(
1269*b4f34f94SDavid van Moolenbroek 				    "%s: '%s' is not a valid bool\n",
1270*b4f34f94SDavid van Moolenbroek 				    nname, value);
1271*b4f34f94SDavid van Moolenbroek 				EXIT(EXIT_FAILURE);
1272*b4f34f94SDavid van Moolenbroek 			}
1273*b4f34f94SDavid van Moolenbroek 			b = q == 1;
1274*b4f34f94SDavid van Moolenbroek 			if (!(flags & CTLFLAG_OWNDATA)) {
1275*b4f34f94SDavid van Moolenbroek 				flags |= CTLFLAG_IMMEDIATE;
1276*b4f34f94SDavid van Moolenbroek 				node.sysctl_idata = b;
1277*b4f34f94SDavid van Moolenbroek 			}
1278*b4f34f94SDavid van Moolenbroek 			else
1279*b4f34f94SDavid van Moolenbroek 				node.sysctl_data = &b;
1280*b4f34f94SDavid van Moolenbroek 			if (sz == 0)
1281*b4f34f94SDavid van Moolenbroek 				sz = sizeof(bool);
1282*b4f34f94SDavid van Moolenbroek 			break;
1283*b4f34f94SDavid van Moolenbroek 		case CTLTYPE_STRING:
1284*b4f34f94SDavid van Moolenbroek 			flags |= CTLFLAG_OWNDATA;
1285*b4f34f94SDavid van Moolenbroek 			node.sysctl_data = data;
1286*b4f34f94SDavid van Moolenbroek 			if (sz == 0)
1287*b4f34f94SDavid van Moolenbroek 				sz = strlen(data) + 1;
1288*b4f34f94SDavid van Moolenbroek 			else if (sz < strlen(data) + 1) {
1289*b4f34f94SDavid van Moolenbroek 				sysctlperror("%s: ignoring size=%zu for "
1290*b4f34f94SDavid van Moolenbroek 					"string node, too small for given "
1291*b4f34f94SDavid van Moolenbroek 					"value\n", nname, sz);
1292*b4f34f94SDavid van Moolenbroek 				sz = strlen(data) + 1;
1293*b4f34f94SDavid van Moolenbroek 			}
1294*b4f34f94SDavid van Moolenbroek 			break;
1295*b4f34f94SDavid van Moolenbroek 		case CTLTYPE_QUAD:
1296*b4f34f94SDavid van Moolenbroek 			errno = 0;
1297*b4f34f94SDavid van Moolenbroek 			uq = strtouq(data, &t, 0);
1298*b4f34f94SDavid van Moolenbroek 			if (t == data || *t != '\0' || errno != 0) {
1299*b4f34f94SDavid van Moolenbroek 				sysctlperror(
1300*b4f34f94SDavid van Moolenbroek 					"%s: '%s' is not a valid quad\n",
1301*b4f34f94SDavid van Moolenbroek 					nname, value);
1302*b4f34f94SDavid van Moolenbroek 				EXIT(EXIT_FAILURE);
1303*b4f34f94SDavid van Moolenbroek 			}
1304*b4f34f94SDavid van Moolenbroek 			if (!(flags & CTLFLAG_OWNDATA)) {
1305*b4f34f94SDavid van Moolenbroek 				flags |= CTLFLAG_IMMEDIATE;
1306*b4f34f94SDavid van Moolenbroek 				node.sysctl_qdata = uq;
1307*b4f34f94SDavid van Moolenbroek 			}
1308*b4f34f94SDavid van Moolenbroek 			else
1309*b4f34f94SDavid van Moolenbroek 				node.sysctl_data = &uq;
1310*b4f34f94SDavid van Moolenbroek 			if (sz == 0)
1311*b4f34f94SDavid van Moolenbroek 				sz = sizeof(u_quad_t);
1312*b4f34f94SDavid van Moolenbroek 			break;
1313*b4f34f94SDavid van Moolenbroek 		case CTLTYPE_STRUCT:
1314*b4f34f94SDavid van Moolenbroek 			sysctlperror("%s: struct not initializable\n",
1315*b4f34f94SDavid van Moolenbroek 				     nname);
1316*b4f34f94SDavid van Moolenbroek 			EXIT(EXIT_FAILURE);
1317*b4f34f94SDavid van Moolenbroek 		}
1318*b4f34f94SDavid van Moolenbroek 
1319*b4f34f94SDavid van Moolenbroek 		/*
1320*b4f34f94SDavid van Moolenbroek 		 * these methods have all provided local starting
1321*b4f34f94SDavid van Moolenbroek 		 * values that the kernel must copy in
1322*b4f34f94SDavid van Moolenbroek 		 */
1323*b4f34f94SDavid van Moolenbroek 	}
1324*b4f34f94SDavid van Moolenbroek 
1325*b4f34f94SDavid van Moolenbroek 	/*
1326*b4f34f94SDavid van Moolenbroek 	 * hmm...no data, but we have an address of data.  that's
1327*b4f34f94SDavid van Moolenbroek 	 * fine.
1328*b4f34f94SDavid van Moolenbroek 	 */
1329*b4f34f94SDavid van Moolenbroek 	else if (addr != 0)
1330*b4f34f94SDavid van Moolenbroek 		node.sysctl_data = (void*)addr;
1331*b4f34f94SDavid van Moolenbroek 
1332*b4f34f94SDavid van Moolenbroek 	/*
1333*b4f34f94SDavid van Moolenbroek 	 * no data and no address?  well...okay.  we might be able to
1334*b4f34f94SDavid van Moolenbroek 	 * manage that.
1335*b4f34f94SDavid van Moolenbroek 	 */
1336*b4f34f94SDavid van Moolenbroek 	else if (type != CTLTYPE_NODE) {
1337*b4f34f94SDavid van Moolenbroek 		if (sz == 0) {
1338*b4f34f94SDavid van Moolenbroek 			sysctlperror(
1339*b4f34f94SDavid van Moolenbroek 			    "%s: need a size or a starting value\n",
1340*b4f34f94SDavid van Moolenbroek 			    nname);
1341*b4f34f94SDavid van Moolenbroek                         EXIT(EXIT_FAILURE);
1342*b4f34f94SDavid van Moolenbroek                 }
1343*b4f34f94SDavid van Moolenbroek 		if (!(flags & CTLFLAG_IMMEDIATE))
1344*b4f34f94SDavid van Moolenbroek 			flags |= CTLFLAG_OWNDATA;
1345*b4f34f94SDavid van Moolenbroek 	}
1346*b4f34f94SDavid van Moolenbroek 
1347*b4f34f94SDavid van Moolenbroek 	/*
1348*b4f34f94SDavid van Moolenbroek 	 * now we do a few sanity checks on the description we've
1349*b4f34f94SDavid van Moolenbroek 	 * assembled
1350*b4f34f94SDavid van Moolenbroek 	 */
1351*b4f34f94SDavid van Moolenbroek 	if ((flags & CTLFLAG_IMMEDIATE) &&
1352*b4f34f94SDavid van Moolenbroek 	    (type == CTLTYPE_STRING || type == CTLTYPE_STRUCT)) {
1353*b4f34f94SDavid van Moolenbroek 		sysctlperror("%s: cannot make an immediate %s\n",
1354*b4f34f94SDavid van Moolenbroek 			     nname,
1355*b4f34f94SDavid van Moolenbroek 			     (type == CTLTYPE_STRING) ? "string" : "struct");
1356*b4f34f94SDavid van Moolenbroek 		EXIT(EXIT_FAILURE);
1357*b4f34f94SDavid van Moolenbroek 	}
1358*b4f34f94SDavid van Moolenbroek 	if (type == CTLTYPE_NODE && node.sysctl_data != NULL) {
1359*b4f34f94SDavid van Moolenbroek 		sysctlperror("%s: nodes do not have data\n", nname);
1360*b4f34f94SDavid van Moolenbroek 		EXIT(EXIT_FAILURE);
1361*b4f34f94SDavid van Moolenbroek 	}
1362*b4f34f94SDavid van Moolenbroek 
1363*b4f34f94SDavid van Moolenbroek 	/*
1364*b4f34f94SDavid van Moolenbroek 	 * some types must have a particular size
1365*b4f34f94SDavid van Moolenbroek 	 */
1366*b4f34f94SDavid van Moolenbroek 	if (sz != 0) {
1367*b4f34f94SDavid van Moolenbroek 		if ((type == CTLTYPE_INT && sz != sizeof(int)) ||
1368*b4f34f94SDavid van Moolenbroek 		    (type == CTLTYPE_BOOL && sz != sizeof(bool)) ||
1369*b4f34f94SDavid van Moolenbroek 		    (type == CTLTYPE_QUAD && sz != sizeof(u_quad_t)) ||
1370*b4f34f94SDavid van Moolenbroek 		    (type == CTLTYPE_NODE && sz != 0)) {
1371*b4f34f94SDavid van Moolenbroek 			sysctlperror("%s: wrong size for type\n", nname);
1372*b4f34f94SDavid van Moolenbroek 			EXIT(EXIT_FAILURE);
1373*b4f34f94SDavid van Moolenbroek 		}
1374*b4f34f94SDavid van Moolenbroek 	}
1375*b4f34f94SDavid van Moolenbroek 	else if (type == CTLTYPE_STRUCT) {
1376*b4f34f94SDavid van Moolenbroek 		sysctlperror("%s: struct must have size\n", nname);
1377*b4f34f94SDavid van Moolenbroek 		EXIT(EXIT_FAILURE);
1378*b4f34f94SDavid van Moolenbroek 	}
1379*b4f34f94SDavid van Moolenbroek 
1380*b4f34f94SDavid van Moolenbroek 	/*
1381*b4f34f94SDavid van Moolenbroek 	 * now...if no one said anything yet, we default nodes or
1382*b4f34f94SDavid van Moolenbroek 	 * any type that owns data being writeable, and everything
1383*b4f34f94SDavid van Moolenbroek 	 * else being readonly.
1384*b4f34f94SDavid van Moolenbroek 	 */
1385*b4f34f94SDavid van Moolenbroek 	if (rw == -1) {
1386*b4f34f94SDavid van Moolenbroek 		if (type == CTLTYPE_NODE ||
1387*b4f34f94SDavid van Moolenbroek 		    (flags & (CTLFLAG_OWNDATA|CTLFLAG_IMMEDIATE)))
1388*b4f34f94SDavid van Moolenbroek 			rw = CTLFLAG_READWRITE;
1389*b4f34f94SDavid van Moolenbroek 		else
1390*b4f34f94SDavid van Moolenbroek 			rw = CTLFLAG_READONLY;
1391*b4f34f94SDavid van Moolenbroek 	}
1392*b4f34f94SDavid van Moolenbroek 
1393*b4f34f94SDavid van Moolenbroek 	/*
1394*b4f34f94SDavid van Moolenbroek 	 * if a kernel address was specified, that can't be made
1395*b4f34f94SDavid van Moolenbroek 	 * writeable by us.
1396*b4f34f94SDavid van Moolenbroek 	if (rw != CTLFLAG_READONLY && addr) {
1397*b4f34f94SDavid van Moolenbroek 		sysctlperror("%s: kernel data can only be readable\n", nname);
1398*b4f34f94SDavid van Moolenbroek 		EXIT(EXIT_FAILURE);
1399*b4f34f94SDavid van Moolenbroek 	}
1400*b4f34f94SDavid van Moolenbroek 	 */
1401*b4f34f94SDavid van Moolenbroek 
1402*b4f34f94SDavid van Moolenbroek 	/*
1403*b4f34f94SDavid van Moolenbroek 	 * what separator were they using in the full name of the new
1404*b4f34f94SDavid van Moolenbroek 	 * node?
1405*b4f34f94SDavid van Moolenbroek 	 */
1406*b4f34f94SDavid van Moolenbroek 	if ((t = strpbrk(nname, "./")) == NULL)
1407*b4f34f94SDavid van Moolenbroek 		sep[0] = '.';
1408*b4f34f94SDavid van Moolenbroek 	else
1409*b4f34f94SDavid van Moolenbroek 		sep[0] = t[0];
1410*b4f34f94SDavid van Moolenbroek 	sep[1] = '\0';
1411*b4f34f94SDavid van Moolenbroek 
1412*b4f34f94SDavid van Moolenbroek 	/*
1413*b4f34f94SDavid van Moolenbroek 	 * put it all together, now.  t'ain't much, is it?
1414*b4f34f94SDavid van Moolenbroek 	 */
1415*b4f34f94SDavid van Moolenbroek 	node.sysctl_flags = SYSCTL_VERSION|flags|rw|type;
1416*b4f34f94SDavid van Moolenbroek 	node.sysctl_size = sz;
1417*b4f34f94SDavid van Moolenbroek 	t = strrchr(nname, sep[0]);
1418*b4f34f94SDavid van Moolenbroek 	if (t != NULL)
1419*b4f34f94SDavid van Moolenbroek 		strlcpy(node.sysctl_name, t + 1, sizeof(node.sysctl_name));
1420*b4f34f94SDavid van Moolenbroek 	else
1421*b4f34f94SDavid van Moolenbroek 		strlcpy(node.sysctl_name, nname, sizeof(node.sysctl_name));
1422*b4f34f94SDavid van Moolenbroek 	if (t == nname)
1423*b4f34f94SDavid van Moolenbroek 		t = NULL;
1424*b4f34f94SDavid van Moolenbroek 
1425*b4f34f94SDavid van Moolenbroek 	/*
1426*b4f34f94SDavid van Moolenbroek 	 * if this is a new top-level node, then we don't need to find
1427*b4f34f94SDavid van Moolenbroek 	 * the mib for its parent
1428*b4f34f94SDavid van Moolenbroek 	 */
1429*b4f34f94SDavid van Moolenbroek 	if (t == NULL) {
1430*b4f34f94SDavid van Moolenbroek 		namelen = 0;
1431*b4f34f94SDavid van Moolenbroek 		gsname[0] = '\0';
1432*b4f34f94SDavid van Moolenbroek 	}
1433*b4f34f94SDavid van Moolenbroek 
1434*b4f34f94SDavid van Moolenbroek 	/*
1435*b4f34f94SDavid van Moolenbroek 	 * on the other hand, if it's not a top-level node...
1436*b4f34f94SDavid van Moolenbroek 	 */
1437*b4f34f94SDavid van Moolenbroek 	else {
1438*b4f34f94SDavid van Moolenbroek 		namelen = sizeof(name) / sizeof(name[0]);
1439*b4f34f94SDavid van Moolenbroek 		sz = sizeof(gsname);
1440*b4f34f94SDavid van Moolenbroek 		*t = '\0';
1441*b4f34f94SDavid van Moolenbroek 		rc = sysctlgetmibinfo(nname, &name[0], &namelen,
1442*b4f34f94SDavid van Moolenbroek 				      gsname, &sz, NULL, SYSCTL_VERSION);
1443*b4f34f94SDavid van Moolenbroek 		*t = sep[0];
1444*b4f34f94SDavid van Moolenbroek 		if (rc == -1) {
1445*b4f34f94SDavid van Moolenbroek 			sysctlparseerror(namelen, nname);
1446*b4f34f94SDavid van Moolenbroek 			EXIT(EXIT_FAILURE);
1447*b4f34f94SDavid van Moolenbroek 		}
1448*b4f34f94SDavid van Moolenbroek 	}
1449*b4f34f94SDavid van Moolenbroek 
1450*b4f34f94SDavid van Moolenbroek 	/*
1451*b4f34f94SDavid van Moolenbroek 	 * yes, a new node is being created
1452*b4f34f94SDavid van Moolenbroek 	 */
1453*b4f34f94SDavid van Moolenbroek 	if (method != 0)
1454*b4f34f94SDavid van Moolenbroek 		name[namelen++] = method;
1455*b4f34f94SDavid van Moolenbroek 	else
1456*b4f34f94SDavid van Moolenbroek 		name[namelen++] = CTL_CREATE;
1457*b4f34f94SDavid van Moolenbroek 
1458*b4f34f94SDavid van Moolenbroek 	sz = sizeof(node);
1459*b4f34f94SDavid van Moolenbroek 	rc = prog_sysctl(&name[0], namelen, &node, &sz, &node, sizeof(node));
1460*b4f34f94SDavid van Moolenbroek 
1461*b4f34f94SDavid van Moolenbroek 	if (rc == -1) {
1462*b4f34f94SDavid van Moolenbroek 		sysctlperror("%s: CTL_CREATE failed: %s\n",
1463*b4f34f94SDavid van Moolenbroek 			     nname, strerror(errno));
1464*b4f34f94SDavid van Moolenbroek 		EXIT(EXIT_FAILURE);
1465*b4f34f94SDavid van Moolenbroek 	}
1466*b4f34f94SDavid van Moolenbroek 	else {
1467*b4f34f94SDavid van Moolenbroek 		if (!qflag && !nflag)
1468*b4f34f94SDavid van Moolenbroek 			printf("%s(%s): (created)\n", nname, st(type));
1469*b4f34f94SDavid van Moolenbroek 		stale = 1;
1470*b4f34f94SDavid van Moolenbroek 	}
1471*b4f34f94SDavid van Moolenbroek }
1472*b4f34f94SDavid van Moolenbroek 
1473*b4f34f94SDavid van Moolenbroek static void
parse_destroy(char * l)1474*b4f34f94SDavid van Moolenbroek parse_destroy(char *l)
1475*b4f34f94SDavid van Moolenbroek {
1476*b4f34f94SDavid van Moolenbroek 	struct sysctlnode node;
1477*b4f34f94SDavid van Moolenbroek 	size_t sz;
1478*b4f34f94SDavid van Moolenbroek 	int name[CTL_MAXNAME], rc;
1479*b4f34f94SDavid van Moolenbroek 	u_int namelen;
1480*b4f34f94SDavid van Moolenbroek 
1481*b4f34f94SDavid van Moolenbroek 	if (!wflag) {
1482*b4f34f94SDavid van Moolenbroek 		sysctlperror("Must specify -w to destroy nodes\n");
1483*b4f34f94SDavid van Moolenbroek 		exit(EXIT_FAILURE);
1484*b4f34f94SDavid van Moolenbroek 	}
1485*b4f34f94SDavid van Moolenbroek 
1486*b4f34f94SDavid van Moolenbroek 	memset(name, 0, sizeof(name));
1487*b4f34f94SDavid van Moolenbroek 	namelen = sizeof(name) / sizeof(name[0]);
1488*b4f34f94SDavid van Moolenbroek 	sz = sizeof(gsname);
1489*b4f34f94SDavid van Moolenbroek 	rc = sysctlgetmibinfo(l, &name[0], &namelen, gsname, &sz, NULL,
1490*b4f34f94SDavid van Moolenbroek 			      SYSCTL_VERSION);
1491*b4f34f94SDavid van Moolenbroek 	if (rc == -1) {
1492*b4f34f94SDavid van Moolenbroek 		sysctlparseerror(namelen, l);
1493*b4f34f94SDavid van Moolenbroek 		EXIT(EXIT_FAILURE);
1494*b4f34f94SDavid van Moolenbroek 	}
1495*b4f34f94SDavid van Moolenbroek 
1496*b4f34f94SDavid van Moolenbroek 	memset(&node, 0, sizeof(node));
1497*b4f34f94SDavid van Moolenbroek 	node.sysctl_flags = SYSCTL_VERSION;
1498*b4f34f94SDavid van Moolenbroek 	node.sysctl_num = name[namelen - 1];
1499*b4f34f94SDavid van Moolenbroek 	name[namelen - 1] = CTL_DESTROY;
1500*b4f34f94SDavid van Moolenbroek 
1501*b4f34f94SDavid van Moolenbroek 	sz = sizeof(node);
1502*b4f34f94SDavid van Moolenbroek 	rc = prog_sysctl(&name[0], namelen, &node, &sz, &node, sizeof(node));
1503*b4f34f94SDavid van Moolenbroek 
1504*b4f34f94SDavid van Moolenbroek 	if (rc == -1) {
1505*b4f34f94SDavid van Moolenbroek 		sysctlperror("%s: CTL_DESTROY failed: %s\n",
1506*b4f34f94SDavid van Moolenbroek 			     l, strerror(errno));
1507*b4f34f94SDavid van Moolenbroek 		EXIT(EXIT_FAILURE);
1508*b4f34f94SDavid van Moolenbroek 	}
1509*b4f34f94SDavid van Moolenbroek 	else {
1510*b4f34f94SDavid van Moolenbroek 		if (!qflag && !nflag)
1511*b4f34f94SDavid van Moolenbroek 			printf("%s(%s): (destroyed)\n", gsname,
1512*b4f34f94SDavid van Moolenbroek 			       st(SYSCTL_TYPE(node.sysctl_flags)));
1513*b4f34f94SDavid van Moolenbroek 		stale = 1;
1514*b4f34f94SDavid van Moolenbroek 	}
1515*b4f34f94SDavid van Moolenbroek }
1516*b4f34f94SDavid van Moolenbroek 
1517*b4f34f94SDavid van Moolenbroek static void
parse_describe(char * l)1518*b4f34f94SDavid van Moolenbroek parse_describe(char *l)
1519*b4f34f94SDavid van Moolenbroek {
1520*b4f34f94SDavid van Moolenbroek 	struct sysctlnode newdesc;
1521*b4f34f94SDavid van Moolenbroek 	char buf[1024], *value;
1522*b4f34f94SDavid van Moolenbroek 	struct sysctldesc *d = (void*)&buf[0];
1523*b4f34f94SDavid van Moolenbroek 	int name[CTL_MAXNAME], rc;
1524*b4f34f94SDavid van Moolenbroek 	u_int namelen;
1525*b4f34f94SDavid van Moolenbroek 	size_t sz;
1526*b4f34f94SDavid van Moolenbroek 
1527*b4f34f94SDavid van Moolenbroek 	if (!wflag) {
1528*b4f34f94SDavid van Moolenbroek 		sysctlperror("Must specify -w to set descriptions\n");
1529*b4f34f94SDavid van Moolenbroek 		exit(EXIT_FAILURE);
1530*b4f34f94SDavid van Moolenbroek 	}
1531*b4f34f94SDavid van Moolenbroek 
1532*b4f34f94SDavid van Moolenbroek 	value = strchr(l, '=');
1533*b4f34f94SDavid van Moolenbroek 	*value++ = '\0';
1534*b4f34f94SDavid van Moolenbroek 
1535*b4f34f94SDavid van Moolenbroek 	memset(name, 0, sizeof(name));
1536*b4f34f94SDavid van Moolenbroek 	namelen = sizeof(name) / sizeof(name[0]);
1537*b4f34f94SDavid van Moolenbroek 	sz = sizeof(gsname);
1538*b4f34f94SDavid van Moolenbroek 	rc = sysctlgetmibinfo(l, &name[0], &namelen, gsname, &sz, NULL,
1539*b4f34f94SDavid van Moolenbroek 			      SYSCTL_VERSION);
1540*b4f34f94SDavid van Moolenbroek 	if (rc == -1) {
1541*b4f34f94SDavid van Moolenbroek 		sysctlparseerror(namelen, l);
1542*b4f34f94SDavid van Moolenbroek 		EXIT(EXIT_FAILURE);
1543*b4f34f94SDavid van Moolenbroek 	}
1544*b4f34f94SDavid van Moolenbroek 
1545*b4f34f94SDavid van Moolenbroek 	sz = sizeof(buf);
1546*b4f34f94SDavid van Moolenbroek 	memset(&newdesc, 0, sizeof(newdesc));
1547*b4f34f94SDavid van Moolenbroek 	newdesc.sysctl_flags = SYSCTL_VERSION|CTLFLAG_OWNDESC;
1548*b4f34f94SDavid van Moolenbroek 	newdesc.sysctl_num = name[namelen - 1];
1549*b4f34f94SDavid van Moolenbroek 	newdesc.sysctl_desc = value;
1550*b4f34f94SDavid van Moolenbroek 	name[namelen - 1] = CTL_DESCRIBE;
1551*b4f34f94SDavid van Moolenbroek 	rc = prog_sysctl(name, namelen, d, &sz, &newdesc, sizeof(newdesc));
1552*b4f34f94SDavid van Moolenbroek 	if (rc == -1)
1553*b4f34f94SDavid van Moolenbroek 		sysctlperror("%s: CTL_DESCRIBE failed: %s\n",
1554*b4f34f94SDavid van Moolenbroek 			     gsname, strerror(errno));
1555*b4f34f94SDavid van Moolenbroek 	else if (d->descr_len == 1)
1556*b4f34f94SDavid van Moolenbroek 		sysctlperror("%s: description not set\n", gsname);
1557*b4f34f94SDavid van Moolenbroek 	else if (!qflag && !nflag)
1558*b4f34f94SDavid van Moolenbroek 		printf("%s: %s\n", gsname, d->descr_str);
1559*b4f34f94SDavid van Moolenbroek }
1560*b4f34f94SDavid van Moolenbroek 
1561*b4f34f94SDavid van Moolenbroek /*
1562*b4f34f94SDavid van Moolenbroek  * ********************************************************************
1563*b4f34f94SDavid van Moolenbroek  * when things go wrong...
1564*b4f34f94SDavid van Moolenbroek  * ********************************************************************
1565*b4f34f94SDavid van Moolenbroek  */
1566*b4f34f94SDavid van Moolenbroek static void
usage(void)1567*b4f34f94SDavid van Moolenbroek usage(void)
1568*b4f34f94SDavid van Moolenbroek {
1569*b4f34f94SDavid van Moolenbroek 	const char *progname = getprogname();
1570*b4f34f94SDavid van Moolenbroek 
1571*b4f34f94SDavid van Moolenbroek 	(void)fprintf(stderr,
1572*b4f34f94SDavid van Moolenbroek 		      "usage:\t%s %s\n"
1573*b4f34f94SDavid van Moolenbroek 		      "\t%s %s\n"
1574*b4f34f94SDavid van Moolenbroek 		      "\t%s %s\n"
1575*b4f34f94SDavid van Moolenbroek 		      "\t%s %s\n"
1576*b4f34f94SDavid van Moolenbroek 		      "\t%s %s\n"
1577*b4f34f94SDavid van Moolenbroek 		      "\t%s %s\n",
1578*b4f34f94SDavid van Moolenbroek 		      progname, "[-dneq] [-x[x]|-r] variable ...",
1579*b4f34f94SDavid van Moolenbroek 		      progname, "[-ne] [-q] -w variable=value ...",
1580*b4f34f94SDavid van Moolenbroek 		      progname, "[-dne] -a",
1581*b4f34f94SDavid van Moolenbroek 		      progname, "[-dne] -A",
1582*b4f34f94SDavid van Moolenbroek 		      progname, "[-ne] -M",
1583*b4f34f94SDavid van Moolenbroek 		      progname, "[-dne] [-q] -f file");
1584*b4f34f94SDavid van Moolenbroek 	exit(EXIT_FAILURE);
1585*b4f34f94SDavid van Moolenbroek }
1586*b4f34f94SDavid van Moolenbroek 
1587*b4f34f94SDavid van Moolenbroek static void
getdesc1(int * name,u_int namelen,struct sysctlnode * pnode)1588*b4f34f94SDavid van Moolenbroek getdesc1(int *name, u_int namelen, struct sysctlnode *pnode)
1589*b4f34f94SDavid van Moolenbroek {
1590*b4f34f94SDavid van Moolenbroek 	struct sysctlnode node;
1591*b4f34f94SDavid van Moolenbroek 	char buf[1024], *desc;
1592*b4f34f94SDavid van Moolenbroek 	struct sysctldesc *d = (void*)buf;
1593*b4f34f94SDavid van Moolenbroek 	size_t sz = sizeof(buf);
1594*b4f34f94SDavid van Moolenbroek 	int rc;
1595*b4f34f94SDavid van Moolenbroek 
1596*b4f34f94SDavid van Moolenbroek 	memset(&node, 0, sizeof(node));
1597*b4f34f94SDavid van Moolenbroek 	node.sysctl_flags = SYSCTL_VERSION;
1598*b4f34f94SDavid van Moolenbroek 	node.sysctl_num = name[namelen - 1];
1599*b4f34f94SDavid van Moolenbroek 	name[namelen - 1] = CTL_DESCRIBE;
1600*b4f34f94SDavid van Moolenbroek 	rc = prog_sysctl(name, namelen, d, &sz, &node, sizeof(node));
1601*b4f34f94SDavid van Moolenbroek 
1602*b4f34f94SDavid van Moolenbroek 	if (rc == -1 ||
1603*b4f34f94SDavid van Moolenbroek 	    d->descr_len == 1 ||
1604*b4f34f94SDavid van Moolenbroek 	    d->descr_num != pnode->sysctl_num ||
1605*b4f34f94SDavid van Moolenbroek 	    d->descr_ver != pnode->sysctl_ver)
1606*b4f34f94SDavid van Moolenbroek 		desc = (char *)-1;
1607*b4f34f94SDavid van Moolenbroek 	else
1608*b4f34f94SDavid van Moolenbroek 		desc = malloc(d->descr_len);
1609*b4f34f94SDavid van Moolenbroek 
1610*b4f34f94SDavid van Moolenbroek 	if (desc == NULL)
1611*b4f34f94SDavid van Moolenbroek 		desc = (char *)-1;
1612*b4f34f94SDavid van Moolenbroek 	if (desc != (char *)-1)
1613*b4f34f94SDavid van Moolenbroek 		memcpy(desc, &d->descr_str[0], d->descr_len);
1614*b4f34f94SDavid van Moolenbroek 	name[namelen - 1] = node.sysctl_num;
1615*b4f34f94SDavid van Moolenbroek 	if (pnode->sysctl_desc != NULL &&
1616*b4f34f94SDavid van Moolenbroek 	    pnode->sysctl_desc != (const char *)-1)
1617*b4f34f94SDavid van Moolenbroek 		free(__UNCONST(pnode->sysctl_desc));
1618*b4f34f94SDavid van Moolenbroek 	pnode->sysctl_desc = desc;
1619*b4f34f94SDavid van Moolenbroek }
1620*b4f34f94SDavid van Moolenbroek 
1621*b4f34f94SDavid van Moolenbroek static void
getdesc(int * name,u_int namelen,struct sysctlnode * pnode)1622*b4f34f94SDavid van Moolenbroek getdesc(int *name, u_int namelen, struct sysctlnode *pnode)
1623*b4f34f94SDavid van Moolenbroek {
1624*b4f34f94SDavid van Moolenbroek 	struct sysctlnode *node = pnode->sysctl_child;
1625*b4f34f94SDavid van Moolenbroek 	struct sysctldesc *d, *p, *plim;
1626*b4f34f94SDavid van Moolenbroek 	char *desc;
1627*b4f34f94SDavid van Moolenbroek 	size_t i, sz, child_cnt;
1628*b4f34f94SDavid van Moolenbroek 	int rc;
1629*b4f34f94SDavid van Moolenbroek 
1630*b4f34f94SDavid van Moolenbroek 	sz = 128 * pnode->sysctl_clen;
1631*b4f34f94SDavid van Moolenbroek 	name[namelen] = CTL_DESCRIBE;
1632*b4f34f94SDavid van Moolenbroek 
1633*b4f34f94SDavid van Moolenbroek 	/*
1634*b4f34f94SDavid van Moolenbroek 	 * attempt *twice* to get the description chunk.  if two tries
1635*b4f34f94SDavid van Moolenbroek 	 * doesn't work, give up.
1636*b4f34f94SDavid van Moolenbroek 	 */
1637*b4f34f94SDavid van Moolenbroek 	i = 0;
1638*b4f34f94SDavid van Moolenbroek 	do {
1639*b4f34f94SDavid van Moolenbroek 		d = malloc(sz);
1640*b4f34f94SDavid van Moolenbroek 		if (d == NULL)
1641*b4f34f94SDavid van Moolenbroek 			return;
1642*b4f34f94SDavid van Moolenbroek 		rc = prog_sysctl(name, namelen + 1, d, &sz, NULL, 0);
1643*b4f34f94SDavid van Moolenbroek 		if (rc == -1) {
1644*b4f34f94SDavid van Moolenbroek 			free(d);
1645*b4f34f94SDavid van Moolenbroek 			d = NULL;
1646*b4f34f94SDavid van Moolenbroek 			if (i == 0 && errno == ENOMEM)
1647*b4f34f94SDavid van Moolenbroek 				i = 1;
1648*b4f34f94SDavid van Moolenbroek 			else
1649*b4f34f94SDavid van Moolenbroek 				return;
1650*b4f34f94SDavid van Moolenbroek 		}
1651*b4f34f94SDavid van Moolenbroek 	} while (d == NULL);
1652*b4f34f94SDavid van Moolenbroek 
1653*b4f34f94SDavid van Moolenbroek 	/*
1654*b4f34f94SDavid van Moolenbroek 	 * hokey nested loop here, giving O(n**2) behavior, but should
1655*b4f34f94SDavid van Moolenbroek 	 * suffice for now
1656*b4f34f94SDavid van Moolenbroek 	 */
1657*b4f34f94SDavid van Moolenbroek 	plim = /*LINTED ptr cast*/(struct sysctldesc *)((char*)d + sz);
1658*b4f34f94SDavid van Moolenbroek 	child_cnt = (pnode->sysctl_flags & CTLTYPE_NODE) ? pnode->sysctl_clen
1659*b4f34f94SDavid van Moolenbroek 	    : 0;
1660*b4f34f94SDavid van Moolenbroek 	for (i = 0; i < child_cnt; i++) {
1661*b4f34f94SDavid van Moolenbroek 		node = &pnode->sysctl_child[i];
1662*b4f34f94SDavid van Moolenbroek 		for (p = d; p < plim; p = NEXT_DESCR(p))
1663*b4f34f94SDavid van Moolenbroek 			if (node->sysctl_num == p->descr_num)
1664*b4f34f94SDavid van Moolenbroek 				break;
1665*b4f34f94SDavid van Moolenbroek 		if (p < plim && node->sysctl_ver == p->descr_ver) {
1666*b4f34f94SDavid van Moolenbroek 			/*
1667*b4f34f94SDavid van Moolenbroek 			 * match found, attempt to attach description
1668*b4f34f94SDavid van Moolenbroek 			 */
1669*b4f34f94SDavid van Moolenbroek 			if (p->descr_len == 1)
1670*b4f34f94SDavid van Moolenbroek 				desc = NULL;
1671*b4f34f94SDavid van Moolenbroek 			else
1672*b4f34f94SDavid van Moolenbroek 				desc = malloc(p->descr_len);
1673*b4f34f94SDavid van Moolenbroek 			if (desc == NULL)
1674*b4f34f94SDavid van Moolenbroek 				desc = (char *)-1;
1675*b4f34f94SDavid van Moolenbroek 			else
1676*b4f34f94SDavid van Moolenbroek 				memcpy(desc, &p->descr_str[0], p->descr_len);
1677*b4f34f94SDavid van Moolenbroek 			node->sysctl_desc = desc;
1678*b4f34f94SDavid van Moolenbroek 		}
1679*b4f34f94SDavid van Moolenbroek 	}
1680*b4f34f94SDavid van Moolenbroek 
1681*b4f34f94SDavid van Moolenbroek 	free(d);
1682*b4f34f94SDavid van Moolenbroek }
1683*b4f34f94SDavid van Moolenbroek 
1684*b4f34f94SDavid van Moolenbroek static void
trim_whitespace(char * s,int dir)1685*b4f34f94SDavid van Moolenbroek trim_whitespace(char *s, int dir)
1686*b4f34f94SDavid van Moolenbroek {
1687*b4f34f94SDavid van Moolenbroek 	char *i, *o;
1688*b4f34f94SDavid van Moolenbroek 
1689*b4f34f94SDavid van Moolenbroek 	i = o = s;
1690*b4f34f94SDavid van Moolenbroek 	if (dir & 1)
1691*b4f34f94SDavid van Moolenbroek 		while (isspace((unsigned char)*i))
1692*b4f34f94SDavid van Moolenbroek 			i++;
1693*b4f34f94SDavid van Moolenbroek 	while ((*o++ = *i++) != '\0');
1694*b4f34f94SDavid van Moolenbroek 	o -= 2; /* already past nul, skip back to before it */
1695*b4f34f94SDavid van Moolenbroek 	if (dir & 2)
1696*b4f34f94SDavid van Moolenbroek 		while (o > s && isspace((unsigned char)*o))
1697*b4f34f94SDavid van Moolenbroek 			*o-- = '\0';
1698*b4f34f94SDavid van Moolenbroek }
1699*b4f34f94SDavid van Moolenbroek 
1700*b4f34f94SDavid van Moolenbroek void
sysctlerror(int soft)1701*b4f34f94SDavid van Moolenbroek sysctlerror(int soft)
1702*b4f34f94SDavid van Moolenbroek {
1703*b4f34f94SDavid van Moolenbroek 	if (soft) {
1704*b4f34f94SDavid van Moolenbroek 		switch (errno) {
1705*b4f34f94SDavid van Moolenbroek 		case ENOENT:
1706*b4f34f94SDavid van Moolenbroek 		case ENOPROTOOPT:
1707*b4f34f94SDavid van Moolenbroek 		case ENOTDIR:
1708*b4f34f94SDavid van Moolenbroek 		case EINVAL:
1709*b4f34f94SDavid van Moolenbroek 		case EOPNOTSUPP:
1710*b4f34f94SDavid van Moolenbroek 		case EPROTONOSUPPORT:
1711*b4f34f94SDavid van Moolenbroek 			if (Aflag || req)
1712*b4f34f94SDavid van Moolenbroek 				sysctlperror("%s: the value is not available "
1713*b4f34f94SDavid van Moolenbroek 				    "(%s)\n", gsname, strerror(errno));
1714*b4f34f94SDavid van Moolenbroek 			return;
1715*b4f34f94SDavid van Moolenbroek 		}
1716*b4f34f94SDavid van Moolenbroek 	}
1717*b4f34f94SDavid van Moolenbroek 
1718*b4f34f94SDavid van Moolenbroek 	if (Aflag || req)
1719*b4f34f94SDavid van Moolenbroek 		sysctlperror("%s: %s\n", gsname, strerror(errno));
1720*b4f34f94SDavid van Moolenbroek 	if (!soft)
1721*b4f34f94SDavid van Moolenbroek 		EXIT(EXIT_FAILURE);
1722*b4f34f94SDavid van Moolenbroek }
1723*b4f34f94SDavid van Moolenbroek 
1724*b4f34f94SDavid van Moolenbroek void
sysctlparseerror(u_int namelen,const char * pname)1725*b4f34f94SDavid van Moolenbroek sysctlparseerror(u_int namelen, const char *pname)
1726*b4f34f94SDavid van Moolenbroek {
1727*b4f34f94SDavid van Moolenbroek 
1728*b4f34f94SDavid van Moolenbroek 	if (qflag) {
1729*b4f34f94SDavid van Moolenbroek 		errs++;
1730*b4f34f94SDavid van Moolenbroek 		return;
1731*b4f34f94SDavid van Moolenbroek 	}
1732*b4f34f94SDavid van Moolenbroek 	sysctlperror("%s level name '%s' in '%s' is invalid\n",
1733*b4f34f94SDavid van Moolenbroek 		     lname[namelen], gsname, pname);
1734*b4f34f94SDavid van Moolenbroek }
1735*b4f34f94SDavid van Moolenbroek 
1736*b4f34f94SDavid van Moolenbroek static void
sysctlperror(const char * fmt,...)1737*b4f34f94SDavid van Moolenbroek sysctlperror(const char *fmt, ...)
1738*b4f34f94SDavid van Moolenbroek {
1739*b4f34f94SDavid van Moolenbroek 	va_list ap;
1740*b4f34f94SDavid van Moolenbroek 
1741*b4f34f94SDavid van Moolenbroek 	(void)fprintf(warnfp, "%s: ", getprogname());
1742*b4f34f94SDavid van Moolenbroek 	if (fn)
1743*b4f34f94SDavid van Moolenbroek 		(void)fprintf(warnfp, "%s#%zu: ", fn, nr);
1744*b4f34f94SDavid van Moolenbroek 	va_start(ap, fmt);
1745*b4f34f94SDavid van Moolenbroek 	(void)vfprintf(warnfp, fmt, ap);
1746*b4f34f94SDavid van Moolenbroek 	va_end(ap);
1747*b4f34f94SDavid van Moolenbroek 	errs++;
1748*b4f34f94SDavid van Moolenbroek }
1749*b4f34f94SDavid van Moolenbroek 
1750*b4f34f94SDavid van Moolenbroek 
1751*b4f34f94SDavid van Moolenbroek /*
1752*b4f34f94SDavid van Moolenbroek  * ********************************************************************
1753*b4f34f94SDavid van Moolenbroek  * how to write to a "simple" node
1754*b4f34f94SDavid van Moolenbroek  * ********************************************************************
1755*b4f34f94SDavid van Moolenbroek  */
1756*b4f34f94SDavid van Moolenbroek static void
write_number(int * name,u_int namelen,struct sysctlnode * node,char * value)1757*b4f34f94SDavid van Moolenbroek write_number(int *name, u_int namelen, struct sysctlnode *node, char *value)
1758*b4f34f94SDavid van Moolenbroek {
1759*b4f34f94SDavid van Moolenbroek 	u_int ii, io;
1760*b4f34f94SDavid van Moolenbroek 	u_quad_t qi, qo;
1761*b4f34f94SDavid van Moolenbroek 	size_t si, so;
1762*b4f34f94SDavid van Moolenbroek 	bool bi, bo;
1763*b4f34f94SDavid van Moolenbroek 	int rc;
1764*b4f34f94SDavid van Moolenbroek 	void *i, *o;
1765*b4f34f94SDavid van Moolenbroek 	char *t;
1766*b4f34f94SDavid van Moolenbroek 
1767*b4f34f94SDavid van Moolenbroek 	if (fn)
1768*b4f34f94SDavid van Moolenbroek 		trim_whitespace(value, 3);
1769*b4f34f94SDavid van Moolenbroek 
1770*b4f34f94SDavid van Moolenbroek 	si = so = 0;
1771*b4f34f94SDavid van Moolenbroek 	i = o = NULL;
1772*b4f34f94SDavid van Moolenbroek 	bi = bo = false;
1773*b4f34f94SDavid van Moolenbroek 	errno = 0;
1774*b4f34f94SDavid van Moolenbroek 	qi = strtouq(value, &t, 0);
1775*b4f34f94SDavid van Moolenbroek 	if (qi == UQUAD_MAX && errno == ERANGE) {
1776*b4f34f94SDavid van Moolenbroek 		sysctlperror("%s: %s\n", value, strerror(errno));
1777*b4f34f94SDavid van Moolenbroek 		EXIT(EXIT_FAILURE);
1778*b4f34f94SDavid van Moolenbroek 	}
1779*b4f34f94SDavid van Moolenbroek 	if (t == value || *t != '\0') {
1780*b4f34f94SDavid van Moolenbroek 		sysctlperror("%s: not a number\n", value);
1781*b4f34f94SDavid van Moolenbroek 		EXIT(EXIT_FAILURE);
1782*b4f34f94SDavid van Moolenbroek 	}
1783*b4f34f94SDavid van Moolenbroek 
1784*b4f34f94SDavid van Moolenbroek 	switch (SYSCTL_TYPE(node->sysctl_flags)) {
1785*b4f34f94SDavid van Moolenbroek 	case CTLTYPE_INT:
1786*b4f34f94SDavid van Moolenbroek 		ii = (u_int)qi;
1787*b4f34f94SDavid van Moolenbroek 		io = (u_int)(qi >> 32);
1788*b4f34f94SDavid van Moolenbroek 		if (io != (u_int)-1 && io != 0) {
1789*b4f34f94SDavid van Moolenbroek 			sysctlperror("%s: %s\n", value, strerror(ERANGE));
1790*b4f34f94SDavid van Moolenbroek 			EXIT(EXIT_FAILURE);
1791*b4f34f94SDavid van Moolenbroek 		}
1792*b4f34f94SDavid van Moolenbroek 		o = &io;
1793*b4f34f94SDavid van Moolenbroek 		so = sizeof(io);
1794*b4f34f94SDavid van Moolenbroek 		i = &ii;
1795*b4f34f94SDavid van Moolenbroek 		si = sizeof(ii);
1796*b4f34f94SDavid van Moolenbroek 		break;
1797*b4f34f94SDavid van Moolenbroek 	case CTLTYPE_BOOL:
1798*b4f34f94SDavid van Moolenbroek 		bi = (bool)qi;
1799*b4f34f94SDavid van Moolenbroek 		o = &bo;
1800*b4f34f94SDavid van Moolenbroek 		so = sizeof(bo);
1801*b4f34f94SDavid van Moolenbroek 		i = &bi;
1802*b4f34f94SDavid van Moolenbroek 		si = sizeof(bi);
1803*b4f34f94SDavid van Moolenbroek 		break;
1804*b4f34f94SDavid van Moolenbroek 	case CTLTYPE_QUAD:
1805*b4f34f94SDavid van Moolenbroek 		o = &qo;
1806*b4f34f94SDavid van Moolenbroek 		so = sizeof(qo);
1807*b4f34f94SDavid van Moolenbroek 		i = &qi;
1808*b4f34f94SDavid van Moolenbroek 		si = sizeof(qi);
1809*b4f34f94SDavid van Moolenbroek 		break;
1810*b4f34f94SDavid van Moolenbroek 	}
1811*b4f34f94SDavid van Moolenbroek 
1812*b4f34f94SDavid van Moolenbroek 	rc = prog_sysctl(name, namelen, o, &so, i, si);
1813*b4f34f94SDavid van Moolenbroek 	if (rc == -1) {
1814*b4f34f94SDavid van Moolenbroek 		sysctlerror(0);
1815*b4f34f94SDavid van Moolenbroek 		return;
1816*b4f34f94SDavid van Moolenbroek 	}
1817*b4f34f94SDavid van Moolenbroek 
1818*b4f34f94SDavid van Moolenbroek 	switch (SYSCTL_TYPE(node->sysctl_flags)) {
1819*b4f34f94SDavid van Moolenbroek 	case CTLTYPE_INT:
1820*b4f34f94SDavid van Moolenbroek 		display_number(node, gsname, &io, sizeof(io), DISPLAY_OLD);
1821*b4f34f94SDavid van Moolenbroek 		display_number(node, gsname, &ii, sizeof(ii), DISPLAY_NEW);
1822*b4f34f94SDavid van Moolenbroek 		break;
1823*b4f34f94SDavid van Moolenbroek 	case CTLTYPE_BOOL:
1824*b4f34f94SDavid van Moolenbroek 		display_number(node, gsname, &bo, sizeof(bo), DISPLAY_OLD);
1825*b4f34f94SDavid van Moolenbroek 		display_number(node, gsname, &bi, sizeof(bi), DISPLAY_NEW);
1826*b4f34f94SDavid van Moolenbroek 		break;
1827*b4f34f94SDavid van Moolenbroek 	case CTLTYPE_QUAD:
1828*b4f34f94SDavid van Moolenbroek 		display_number(node, gsname, &qo, sizeof(qo), DISPLAY_OLD);
1829*b4f34f94SDavid van Moolenbroek 		display_number(node, gsname, &qi, sizeof(qi), DISPLAY_NEW);
1830*b4f34f94SDavid van Moolenbroek 		break;
1831*b4f34f94SDavid van Moolenbroek 	}
1832*b4f34f94SDavid van Moolenbroek }
1833*b4f34f94SDavid van Moolenbroek 
1834*b4f34f94SDavid van Moolenbroek static void
write_string(int * name,u_int namelen,struct sysctlnode * node,char * value)1835*b4f34f94SDavid van Moolenbroek write_string(int *name, u_int namelen, struct sysctlnode *node, char *value)
1836*b4f34f94SDavid van Moolenbroek {
1837*b4f34f94SDavid van Moolenbroek 	char *i, *o;
1838*b4f34f94SDavid van Moolenbroek 	size_t si, so;
1839*b4f34f94SDavid van Moolenbroek 	int rc;
1840*b4f34f94SDavid van Moolenbroek 
1841*b4f34f94SDavid van Moolenbroek 	i = value;
1842*b4f34f94SDavid van Moolenbroek 	si = strlen(i) + 1;
1843*b4f34f94SDavid van Moolenbroek 	so = node->sysctl_size;
1844*b4f34f94SDavid van Moolenbroek 	if (si > so && so != 0) {
1845*b4f34f94SDavid van Moolenbroek 		sysctlperror("%s: string too long\n", value);
1846*b4f34f94SDavid van Moolenbroek 		EXIT(EXIT_FAILURE);
1847*b4f34f94SDavid van Moolenbroek 	}
1848*b4f34f94SDavid van Moolenbroek 	o = malloc(so);
1849*b4f34f94SDavid van Moolenbroek 	if (o == NULL) {
1850*b4f34f94SDavid van Moolenbroek 		sysctlperror("%s: !malloc failed!\n", gsname);
1851*b4f34f94SDavid van Moolenbroek 		exit(EXIT_FAILURE);
1852*b4f34f94SDavid van Moolenbroek 	}
1853*b4f34f94SDavid van Moolenbroek 
1854*b4f34f94SDavid van Moolenbroek 	rc = prog_sysctl(name, namelen, o, &so, i, si);
1855*b4f34f94SDavid van Moolenbroek 	if (rc == -1) {
1856*b4f34f94SDavid van Moolenbroek 		sysctlerror(0);
1857*b4f34f94SDavid van Moolenbroek 		return;
1858*b4f34f94SDavid van Moolenbroek 	}
1859*b4f34f94SDavid van Moolenbroek 
1860*b4f34f94SDavid van Moolenbroek 	display_string(node, gsname, o, so, DISPLAY_OLD);
1861*b4f34f94SDavid van Moolenbroek 	display_string(node, gsname, i, si, DISPLAY_NEW);
1862*b4f34f94SDavid van Moolenbroek 	free(o);
1863*b4f34f94SDavid van Moolenbroek }
1864*b4f34f94SDavid van Moolenbroek 
1865*b4f34f94SDavid van Moolenbroek /*
1866*b4f34f94SDavid van Moolenbroek  * ********************************************************************
1867*b4f34f94SDavid van Moolenbroek  * simple ways to print stuff consistently
1868*b4f34f94SDavid van Moolenbroek  * ********************************************************************
1869*b4f34f94SDavid van Moolenbroek  */
1870*b4f34f94SDavid van Moolenbroek static void
display_number(const struct sysctlnode * node,const char * name,const void * data,size_t sz,int n)1871*b4f34f94SDavid van Moolenbroek display_number(const struct sysctlnode *node, const char *name,
1872*b4f34f94SDavid van Moolenbroek 	       const void *data, size_t sz, int n)
1873*b4f34f94SDavid van Moolenbroek {
1874*b4f34f94SDavid van Moolenbroek 	u_quad_t q;
1875*b4f34f94SDavid van Moolenbroek 	bool b;
1876*b4f34f94SDavid van Moolenbroek 	int i;
1877*b4f34f94SDavid van Moolenbroek 
1878*b4f34f94SDavid van Moolenbroek 	if (qflag)
1879*b4f34f94SDavid van Moolenbroek 		return;
1880*b4f34f94SDavid van Moolenbroek 	if ((nflag || rflag) && (n == DISPLAY_OLD))
1881*b4f34f94SDavid van Moolenbroek 		return;
1882*b4f34f94SDavid van Moolenbroek 
1883*b4f34f94SDavid van Moolenbroek 	if (rflag && n != DISPLAY_OLD) {
1884*b4f34f94SDavid van Moolenbroek 		fwrite(data, sz, 1, stdout);
1885*b4f34f94SDavid van Moolenbroek 		return;
1886*b4f34f94SDavid van Moolenbroek 	}
1887*b4f34f94SDavid van Moolenbroek 
1888*b4f34f94SDavid van Moolenbroek 	if (!nflag) {
1889*b4f34f94SDavid van Moolenbroek 		if (n == DISPLAY_VALUE)
1890*b4f34f94SDavid van Moolenbroek 			printf("%s%s", name, eq);
1891*b4f34f94SDavid van Moolenbroek 		else if (n == DISPLAY_OLD)
1892*b4f34f94SDavid van Moolenbroek 			printf("%s: ", name);
1893*b4f34f94SDavid van Moolenbroek 	}
1894*b4f34f94SDavid van Moolenbroek 
1895*b4f34f94SDavid van Moolenbroek 	if (xflag > 1) {
1896*b4f34f94SDavid van Moolenbroek 		if (n != DISPLAY_NEW)
1897*b4f34f94SDavid van Moolenbroek 			printf("\n");
1898*b4f34f94SDavid van Moolenbroek 		hex_dump(data, sz);
1899*b4f34f94SDavid van Moolenbroek 		return;
1900*b4f34f94SDavid van Moolenbroek 	}
1901*b4f34f94SDavid van Moolenbroek 
1902*b4f34f94SDavid van Moolenbroek 	switch (SYSCTL_TYPE(node->sysctl_flags)) {
1903*b4f34f94SDavid van Moolenbroek 	case CTLTYPE_INT:
1904*b4f34f94SDavid van Moolenbroek 		memcpy(&i, data, sz);
1905*b4f34f94SDavid van Moolenbroek 		if (xflag)
1906*b4f34f94SDavid van Moolenbroek 			printf("0x%0*x", (int)sz * 2, i);
1907*b4f34f94SDavid van Moolenbroek 		else if (node->sysctl_flags & CTLFLAG_HEX)
1908*b4f34f94SDavid van Moolenbroek 			printf("%#x", i);
1909*b4f34f94SDavid van Moolenbroek 		else if (node->sysctl_flags & CTLFLAG_UNSIGNED)
1910*b4f34f94SDavid van Moolenbroek 			printf("%u", i);
1911*b4f34f94SDavid van Moolenbroek 		else
1912*b4f34f94SDavid van Moolenbroek 			printf("%d", i);
1913*b4f34f94SDavid van Moolenbroek 		break;
1914*b4f34f94SDavid van Moolenbroek 	case CTLTYPE_BOOL:
1915*b4f34f94SDavid van Moolenbroek 		memcpy(&b, data, sz);
1916*b4f34f94SDavid van Moolenbroek 		if (xflag)
1917*b4f34f94SDavid van Moolenbroek 			printf("0x%0*x", (int)sz * 2, b);
1918*b4f34f94SDavid van Moolenbroek 		else if (node->sysctl_flags & CTLFLAG_HEX)
1919*b4f34f94SDavid van Moolenbroek 			printf("%#x", b);
1920*b4f34f94SDavid van Moolenbroek 		else
1921*b4f34f94SDavid van Moolenbroek 			printf("%d", b);
1922*b4f34f94SDavid van Moolenbroek 		break;
1923*b4f34f94SDavid van Moolenbroek 	case CTLTYPE_QUAD:
1924*b4f34f94SDavid van Moolenbroek 		memcpy(&q, data, sz);
1925*b4f34f94SDavid van Moolenbroek 		if (xflag)
1926*b4f34f94SDavid van Moolenbroek 			printf("0x%0*" PRIx64, (int)sz * 2, q);
1927*b4f34f94SDavid van Moolenbroek 		else if (node->sysctl_flags & CTLFLAG_HEX)
1928*b4f34f94SDavid van Moolenbroek 			printf("%#" PRIx64, q);
1929*b4f34f94SDavid van Moolenbroek 		else if (node->sysctl_flags & CTLFLAG_UNSIGNED)
1930*b4f34f94SDavid van Moolenbroek 			printf("%" PRIu64, q);
1931*b4f34f94SDavid van Moolenbroek 		else
1932*b4f34f94SDavid van Moolenbroek 			printf("%" PRIu64, q);
1933*b4f34f94SDavid van Moolenbroek 		break;
1934*b4f34f94SDavid van Moolenbroek 	}
1935*b4f34f94SDavid van Moolenbroek 
1936*b4f34f94SDavid van Moolenbroek 	if (n == DISPLAY_OLD)
1937*b4f34f94SDavid van Moolenbroek 		printf(" -> ");
1938*b4f34f94SDavid van Moolenbroek 	else
1939*b4f34f94SDavid van Moolenbroek 		printf("\n");
1940*b4f34f94SDavid van Moolenbroek }
1941*b4f34f94SDavid van Moolenbroek 
1942*b4f34f94SDavid van Moolenbroek static void
display_string(const struct sysctlnode * node,const char * name,const void * data,size_t sz,int n)1943*b4f34f94SDavid van Moolenbroek display_string(const struct sysctlnode *node, const char *name,
1944*b4f34f94SDavid van Moolenbroek 	       const void *data, size_t sz, int n)
1945*b4f34f94SDavid van Moolenbroek {
1946*b4f34f94SDavid van Moolenbroek 	const unsigned char *buf = data;
1947*b4f34f94SDavid van Moolenbroek 	int ni;
1948*b4f34f94SDavid van Moolenbroek 
1949*b4f34f94SDavid van Moolenbroek 	if (qflag)
1950*b4f34f94SDavid van Moolenbroek 		return;
1951*b4f34f94SDavid van Moolenbroek 	if ((nflag || rflag) && (n == DISPLAY_OLD))
1952*b4f34f94SDavid van Moolenbroek 		return;
1953*b4f34f94SDavid van Moolenbroek 
1954*b4f34f94SDavid van Moolenbroek 	if (rflag && n != DISPLAY_OLD) {
1955*b4f34f94SDavid van Moolenbroek 		fwrite(data, sz, 1, stdout);
1956*b4f34f94SDavid van Moolenbroek 		return;
1957*b4f34f94SDavid van Moolenbroek 	}
1958*b4f34f94SDavid van Moolenbroek 
1959*b4f34f94SDavid van Moolenbroek 	if (!nflag) {
1960*b4f34f94SDavid van Moolenbroek 		if (n == DISPLAY_VALUE)
1961*b4f34f94SDavid van Moolenbroek 			printf("%s%s", name, eq);
1962*b4f34f94SDavid van Moolenbroek 		else if (n == DISPLAY_OLD)
1963*b4f34f94SDavid van Moolenbroek 			printf("%s: ", name);
1964*b4f34f94SDavid van Moolenbroek 	}
1965*b4f34f94SDavid van Moolenbroek 
1966*b4f34f94SDavid van Moolenbroek 	if (xflag > 1) {
1967*b4f34f94SDavid van Moolenbroek 		if (n != DISPLAY_NEW)
1968*b4f34f94SDavid van Moolenbroek 			printf("\n");
1969*b4f34f94SDavid van Moolenbroek 		hex_dump(data, sz);
1970*b4f34f94SDavid van Moolenbroek 		return;
1971*b4f34f94SDavid van Moolenbroek 	}
1972*b4f34f94SDavid van Moolenbroek 
1973*b4f34f94SDavid van Moolenbroek 	if (xflag || node->sysctl_flags & CTLFLAG_HEX) {
1974*b4f34f94SDavid van Moolenbroek 		for (ni = 0; ni < (int)sz; ni++) {
1975*b4f34f94SDavid van Moolenbroek 			if (xflag)
1976*b4f34f94SDavid van Moolenbroek 				printf("%02x", buf[ni]);
1977*b4f34f94SDavid van Moolenbroek 			if (buf[ni] == '\0')
1978*b4f34f94SDavid van Moolenbroek 				break;
1979*b4f34f94SDavid van Moolenbroek 			if (!xflag)
1980*b4f34f94SDavid van Moolenbroek 				printf("\\x%2.2x", buf[ni]);
1981*b4f34f94SDavid van Moolenbroek 		}
1982*b4f34f94SDavid van Moolenbroek 	}
1983*b4f34f94SDavid van Moolenbroek 	else
1984*b4f34f94SDavid van Moolenbroek 		printf("%.*s", (int)sz, buf);
1985*b4f34f94SDavid van Moolenbroek 
1986*b4f34f94SDavid van Moolenbroek 	if (n == DISPLAY_OLD)
1987*b4f34f94SDavid van Moolenbroek 		printf(" -> ");
1988*b4f34f94SDavid van Moolenbroek 	else
1989*b4f34f94SDavid van Moolenbroek 		printf("\n");
1990*b4f34f94SDavid van Moolenbroek }
1991*b4f34f94SDavid van Moolenbroek 
1992*b4f34f94SDavid van Moolenbroek /*ARGSUSED*/
1993*b4f34f94SDavid van Moolenbroek static void
display_struct(const struct sysctlnode * node,const char * name,const void * data,size_t sz,int n)1994*b4f34f94SDavid van Moolenbroek display_struct(const struct sysctlnode *node, const char *name,
1995*b4f34f94SDavid van Moolenbroek 	       const void *data, size_t sz, int n)
1996*b4f34f94SDavid van Moolenbroek {
1997*b4f34f94SDavid van Moolenbroek 	const unsigned char *buf = data;
1998*b4f34f94SDavid van Moolenbroek 	int ni;
1999*b4f34f94SDavid van Moolenbroek 	size_t more;
2000*b4f34f94SDavid van Moolenbroek 
2001*b4f34f94SDavid van Moolenbroek 	if (qflag)
2002*b4f34f94SDavid van Moolenbroek 		return;
2003*b4f34f94SDavid van Moolenbroek 	if (!(xflag || rflag)) {
2004*b4f34f94SDavid van Moolenbroek 		if (Aflag || req)
2005*b4f34f94SDavid van Moolenbroek 			sysctlperror(
2006*b4f34f94SDavid van Moolenbroek 			    "%s: this type is unknown to this program\n",
2007*b4f34f94SDavid van Moolenbroek 			    gsname);
2008*b4f34f94SDavid van Moolenbroek 		return;
2009*b4f34f94SDavid van Moolenbroek 	}
2010*b4f34f94SDavid van Moolenbroek 	if ((nflag || rflag) && (n == DISPLAY_OLD))
2011*b4f34f94SDavid van Moolenbroek 		return;
2012*b4f34f94SDavid van Moolenbroek 
2013*b4f34f94SDavid van Moolenbroek 	if (rflag && n != DISPLAY_OLD) {
2014*b4f34f94SDavid van Moolenbroek 		fwrite(data, sz, 1, stdout);
2015*b4f34f94SDavid van Moolenbroek 		return;
2016*b4f34f94SDavid van Moolenbroek 	}
2017*b4f34f94SDavid van Moolenbroek 
2018*b4f34f94SDavid van Moolenbroek         if (!nflag) {
2019*b4f34f94SDavid van Moolenbroek                 if (n == DISPLAY_VALUE)
2020*b4f34f94SDavid van Moolenbroek                         printf("%s%s", name, eq);
2021*b4f34f94SDavid van Moolenbroek                 else if (n == DISPLAY_OLD)
2022*b4f34f94SDavid van Moolenbroek                         printf("%s: ", name);
2023*b4f34f94SDavid van Moolenbroek         }
2024*b4f34f94SDavid van Moolenbroek 
2025*b4f34f94SDavid van Moolenbroek 	if (xflag > 1) {
2026*b4f34f94SDavid van Moolenbroek 		if (n != DISPLAY_NEW)
2027*b4f34f94SDavid van Moolenbroek 			printf("\n");
2028*b4f34f94SDavid van Moolenbroek 		hex_dump(data, sz);
2029*b4f34f94SDavid van Moolenbroek 		return;
2030*b4f34f94SDavid van Moolenbroek 	}
2031*b4f34f94SDavid van Moolenbroek 
2032*b4f34f94SDavid van Moolenbroek 	if (sz > 16) {
2033*b4f34f94SDavid van Moolenbroek 		more = sz - 16;
2034*b4f34f94SDavid van Moolenbroek 		sz = 16;
2035*b4f34f94SDavid van Moolenbroek 	}
2036*b4f34f94SDavid van Moolenbroek 	else
2037*b4f34f94SDavid van Moolenbroek 		more = 0;
2038*b4f34f94SDavid van Moolenbroek 	for (ni = 0; ni < (int)sz; ni++)
2039*b4f34f94SDavid van Moolenbroek 		printf("%02x", buf[ni]);
2040*b4f34f94SDavid van Moolenbroek 	if (more)
2041*b4f34f94SDavid van Moolenbroek 		printf("...(%zu more bytes)", more);
2042*b4f34f94SDavid van Moolenbroek 	printf("\n");
2043*b4f34f94SDavid van Moolenbroek }
2044*b4f34f94SDavid van Moolenbroek 
2045*b4f34f94SDavid van Moolenbroek static void
hex_dump(const unsigned char * buf,size_t len)2046*b4f34f94SDavid van Moolenbroek hex_dump(const unsigned char *buf, size_t len)
2047*b4f34f94SDavid van Moolenbroek {
2048*b4f34f94SDavid van Moolenbroek 	unsigned int i;
2049*b4f34f94SDavid van Moolenbroek 	int j;
2050*b4f34f94SDavid van Moolenbroek 	char line[80], tmp[12];
2051*b4f34f94SDavid van Moolenbroek 
2052*b4f34f94SDavid van Moolenbroek 	memset(line, ' ', sizeof(line));
2053*b4f34f94SDavid van Moolenbroek 	for (i = 0, j = 15; i < len; i++) {
2054*b4f34f94SDavid van Moolenbroek 		j = i % 16;
2055*b4f34f94SDavid van Moolenbroek 		/* reset line */
2056*b4f34f94SDavid van Moolenbroek 		if (j == 0) {
2057*b4f34f94SDavid van Moolenbroek 			line[58] = '|';
2058*b4f34f94SDavid van Moolenbroek 			line[77] = '|';
2059*b4f34f94SDavid van Moolenbroek 			line[78] = 0;
2060*b4f34f94SDavid van Moolenbroek 			snprintf(tmp, sizeof(tmp), "%07x", i);
2061*b4f34f94SDavid van Moolenbroek 			memcpy(&line[0], tmp, 7);
2062*b4f34f94SDavid van Moolenbroek 		}
2063*b4f34f94SDavid van Moolenbroek 		/* copy out hex version of byte */
2064*b4f34f94SDavid van Moolenbroek 		snprintf(tmp, sizeof(tmp), "%02x", buf[i]);
2065*b4f34f94SDavid van Moolenbroek 		memcpy(&line[9 + j * 3], tmp, 2);
2066*b4f34f94SDavid van Moolenbroek 		/* copy out plain version of byte */
2067*b4f34f94SDavid van Moolenbroek 		line[60 + j] = (isprint(buf[i])) ? buf[i] : '.';
2068*b4f34f94SDavid van Moolenbroek 		/* print a full line and erase it */
2069*b4f34f94SDavid van Moolenbroek 		if (j == 15) {
2070*b4f34f94SDavid van Moolenbroek 			printf("%s\n", line);
2071*b4f34f94SDavid van Moolenbroek 			memset(line, ' ', sizeof(line));
2072*b4f34f94SDavid van Moolenbroek 		}
2073*b4f34f94SDavid van Moolenbroek 	}
2074*b4f34f94SDavid van Moolenbroek 	if (line[0] != ' ')
2075*b4f34f94SDavid van Moolenbroek 		printf("%s\n", line);
2076*b4f34f94SDavid van Moolenbroek 	printf("%07zu bytes\n", len);
2077*b4f34f94SDavid van Moolenbroek }
2078*b4f34f94SDavid van Moolenbroek 
2079*b4f34f94SDavid van Moolenbroek /*
2080*b4f34f94SDavid van Moolenbroek  * ********************************************************************
2081*b4f34f94SDavid van Moolenbroek  * functions that handle particular nodes
2082*b4f34f94SDavid van Moolenbroek  * ********************************************************************
2083*b4f34f94SDavid van Moolenbroek  */
2084*b4f34f94SDavid van Moolenbroek /*ARGSUSED*/
2085*b4f34f94SDavid van Moolenbroek static void
printother(HANDLER_ARGS)2086*b4f34f94SDavid van Moolenbroek printother(HANDLER_ARGS)
2087*b4f34f94SDavid van Moolenbroek {
2088*b4f34f94SDavid van Moolenbroek 	int rc;
2089*b4f34f94SDavid van Moolenbroek 	void *p;
2090*b4f34f94SDavid van Moolenbroek 	size_t sz1, sz2;
2091*b4f34f94SDavid van Moolenbroek 
2092*b4f34f94SDavid van Moolenbroek 	if (!(Aflag || req) || Mflag)
2093*b4f34f94SDavid van Moolenbroek 		return;
2094*b4f34f94SDavid van Moolenbroek 
2095*b4f34f94SDavid van Moolenbroek 	/*
2096*b4f34f94SDavid van Moolenbroek 	 * okay...you asked for it, so let's give it a go
2097*b4f34f94SDavid van Moolenbroek 	 */
2098*b4f34f94SDavid van Moolenbroek 	while (type != CTLTYPE_NODE && (xflag || rflag)) {
2099*b4f34f94SDavid van Moolenbroek 		rc = prog_sysctl(name, namelen, NULL, &sz1, NULL, 0);
2100*b4f34f94SDavid van Moolenbroek 		if (rc == -1 || sz1 == 0)
2101*b4f34f94SDavid van Moolenbroek 			break;
2102*b4f34f94SDavid van Moolenbroek 		p = malloc(sz1);
2103*b4f34f94SDavid van Moolenbroek 		if (p == NULL)
2104*b4f34f94SDavid van Moolenbroek 			break;
2105*b4f34f94SDavid van Moolenbroek 		sz2 = sz1;
2106*b4f34f94SDavid van Moolenbroek 		rc = prog_sysctl(name, namelen, p, &sz2, NULL, 0);
2107*b4f34f94SDavid van Moolenbroek 		if (rc == -1 || sz1 != sz2) {
2108*b4f34f94SDavid van Moolenbroek 			free(p);
2109*b4f34f94SDavid van Moolenbroek 			break;
2110*b4f34f94SDavid van Moolenbroek 		}
2111*b4f34f94SDavid van Moolenbroek 		display_struct(pnode, gsname, p, sz1, DISPLAY_VALUE);
2112*b4f34f94SDavid van Moolenbroek 		free(p);
2113*b4f34f94SDavid van Moolenbroek 		return;
2114*b4f34f94SDavid van Moolenbroek 	}
2115*b4f34f94SDavid van Moolenbroek 
2116*b4f34f94SDavid van Moolenbroek 	/*
2117*b4f34f94SDavid van Moolenbroek 	 * that didn't work...do we have a specific message for this
2118*b4f34f94SDavid van Moolenbroek 	 * thing?
2119*b4f34f94SDavid van Moolenbroek 	 */
2120*b4f34f94SDavid van Moolenbroek 	if (v != NULL) {
2121*b4f34f94SDavid van Moolenbroek 		sysctlperror("%s: use '%s' to view this information\n",
2122*b4f34f94SDavid van Moolenbroek 			     gsname, (const char *)v);
2123*b4f34f94SDavid van Moolenbroek 		return;
2124*b4f34f94SDavid van Moolenbroek 	}
2125*b4f34f94SDavid van Moolenbroek 
2126*b4f34f94SDavid van Moolenbroek 	/*
2127*b4f34f94SDavid van Moolenbroek 	 * hmm...i wonder if we have any generic hints?
2128*b4f34f94SDavid van Moolenbroek 	 */
2129*b4f34f94SDavid van Moolenbroek 	switch (name[0]) {
2130*b4f34f94SDavid van Moolenbroek 	case CTL_NET:
2131*b4f34f94SDavid van Moolenbroek 		sysctlperror("%s: use 'netstat' to view this information\n",
2132*b4f34f94SDavid van Moolenbroek 			     sname);
2133*b4f34f94SDavid van Moolenbroek 		break;
2134*b4f34f94SDavid van Moolenbroek 	case CTL_DEBUG:
2135*b4f34f94SDavid van Moolenbroek 		sysctlperror("%s: missing 'options DEBUG' from kernel?\n",
2136*b4f34f94SDavid van Moolenbroek 			     sname);
2137*b4f34f94SDavid van Moolenbroek 		break;
2138*b4f34f94SDavid van Moolenbroek 	case CTL_DDB:
2139*b4f34f94SDavid van Moolenbroek 		sysctlperror("%s: missing 'options DDB' from kernel?\n",
2140*b4f34f94SDavid van Moolenbroek 			     sname);
2141*b4f34f94SDavid van Moolenbroek 		break;
2142*b4f34f94SDavid van Moolenbroek 	case CTL_VENDOR:
2143*b4f34f94SDavid van Moolenbroek 		sysctlperror("%s: no vendor extensions installed\n",
2144*b4f34f94SDavid van Moolenbroek 			     sname);
2145*b4f34f94SDavid van Moolenbroek 		break;
2146*b4f34f94SDavid van Moolenbroek 	}
2147*b4f34f94SDavid van Moolenbroek }
2148*b4f34f94SDavid van Moolenbroek 
2149*b4f34f94SDavid van Moolenbroek /*ARGSUSED*/
2150*b4f34f94SDavid van Moolenbroek static void
kern_clockrate(HANDLER_ARGS)2151*b4f34f94SDavid van Moolenbroek kern_clockrate(HANDLER_ARGS)
2152*b4f34f94SDavid van Moolenbroek {
2153*b4f34f94SDavid van Moolenbroek 	struct clockinfo clkinfo;
2154*b4f34f94SDavid van Moolenbroek 	size_t sz;
2155*b4f34f94SDavid van Moolenbroek 	int rc;
2156*b4f34f94SDavid van Moolenbroek 
2157*b4f34f94SDavid van Moolenbroek 	sz = sizeof(clkinfo);
2158*b4f34f94SDavid van Moolenbroek 	rc = prog_sysctl(name, namelen, &clkinfo, &sz, NULL, 0);
2159*b4f34f94SDavid van Moolenbroek 	if (rc == -1) {
2160*b4f34f94SDavid van Moolenbroek 		sysctlerror(1);
2161*b4f34f94SDavid van Moolenbroek 		return;
2162*b4f34f94SDavid van Moolenbroek 	}
2163*b4f34f94SDavid van Moolenbroek 	if (sz != sizeof(clkinfo))
2164*b4f34f94SDavid van Moolenbroek 		errx(EXIT_FAILURE, "%s: !returned size wrong!", sname);
2165*b4f34f94SDavid van Moolenbroek 
2166*b4f34f94SDavid van Moolenbroek 	if (xflag || rflag) {
2167*b4f34f94SDavid van Moolenbroek 		display_struct(pnode, sname, &clkinfo, sz,
2168*b4f34f94SDavid van Moolenbroek 			       DISPLAY_VALUE);
2169*b4f34f94SDavid van Moolenbroek 		return;
2170*b4f34f94SDavid van Moolenbroek 	}
2171*b4f34f94SDavid van Moolenbroek 	else if (!nflag)
2172*b4f34f94SDavid van Moolenbroek 		printf("%s: ", sname);
2173*b4f34f94SDavid van Moolenbroek 	printf("tick = %d, tickadj = %d, hz = %d, profhz = %d, stathz = %d\n",
2174*b4f34f94SDavid van Moolenbroek 	       clkinfo.tick, clkinfo.tickadj,
2175*b4f34f94SDavid van Moolenbroek 	       clkinfo.hz, clkinfo.profhz, clkinfo.stathz);
2176*b4f34f94SDavid van Moolenbroek }
2177*b4f34f94SDavid van Moolenbroek 
2178*b4f34f94SDavid van Moolenbroek /*ARGSUSED*/
2179*b4f34f94SDavid van Moolenbroek static void
kern_boottime(HANDLER_ARGS)2180*b4f34f94SDavid van Moolenbroek kern_boottime(HANDLER_ARGS)
2181*b4f34f94SDavid van Moolenbroek {
2182*b4f34f94SDavid van Moolenbroek 	struct timeval timeval;
2183*b4f34f94SDavid van Moolenbroek 	time_t boottime;
2184*b4f34f94SDavid van Moolenbroek 	size_t sz;
2185*b4f34f94SDavid van Moolenbroek 	int rc;
2186*b4f34f94SDavid van Moolenbroek 
2187*b4f34f94SDavid van Moolenbroek 	sz = sizeof(timeval);
2188*b4f34f94SDavid van Moolenbroek 	rc = prog_sysctl(name, namelen, &timeval, &sz, NULL, 0);
2189*b4f34f94SDavid van Moolenbroek 	if (rc == -1) {
2190*b4f34f94SDavid van Moolenbroek 		sysctlerror(1);
2191*b4f34f94SDavid van Moolenbroek 		return;
2192*b4f34f94SDavid van Moolenbroek 	}
2193*b4f34f94SDavid van Moolenbroek 	if (sz != sizeof(timeval))
2194*b4f34f94SDavid van Moolenbroek 		errx(EXIT_FAILURE, "%s: !returned size wrong!", sname);
2195*b4f34f94SDavid van Moolenbroek 
2196*b4f34f94SDavid van Moolenbroek 	boottime = timeval.tv_sec;
2197*b4f34f94SDavid van Moolenbroek 	if (xflag || rflag)
2198*b4f34f94SDavid van Moolenbroek 		display_struct(pnode, sname, &timeval, sz,
2199*b4f34f94SDavid van Moolenbroek 			       DISPLAY_VALUE);
2200*b4f34f94SDavid van Moolenbroek 	else if (!nflag)
2201*b4f34f94SDavid van Moolenbroek 		/* ctime() provides the \n */
2202*b4f34f94SDavid van Moolenbroek 		printf("%s%s%s", sname, eq, ctime(&boottime));
2203*b4f34f94SDavid van Moolenbroek 	else if (nflag == 1)
2204*b4f34f94SDavid van Moolenbroek 		printf("%ld\n", (long)boottime);
2205*b4f34f94SDavid van Moolenbroek 	else
2206*b4f34f94SDavid van Moolenbroek 		printf("%ld.%06ld\n", (long)timeval.tv_sec,
2207*b4f34f94SDavid van Moolenbroek 		       (long)timeval.tv_usec);
2208*b4f34f94SDavid van Moolenbroek }
2209*b4f34f94SDavid van Moolenbroek 
2210*b4f34f94SDavid van Moolenbroek /*ARGSUSED*/
2211*b4f34f94SDavid van Moolenbroek static void
kern_consdev(HANDLER_ARGS)2212*b4f34f94SDavid van Moolenbroek kern_consdev(HANDLER_ARGS)
2213*b4f34f94SDavid van Moolenbroek {
2214*b4f34f94SDavid van Moolenbroek 	dev_t cons;
2215*b4f34f94SDavid van Moolenbroek 	size_t sz;
2216*b4f34f94SDavid van Moolenbroek 	int rc;
2217*b4f34f94SDavid van Moolenbroek 
2218*b4f34f94SDavid van Moolenbroek 	sz = sizeof(cons);
2219*b4f34f94SDavid van Moolenbroek 	rc = prog_sysctl(name, namelen, &cons, &sz, NULL, 0);
2220*b4f34f94SDavid van Moolenbroek 	if (rc == -1) {
2221*b4f34f94SDavid van Moolenbroek 		sysctlerror(1);
2222*b4f34f94SDavid van Moolenbroek 		return;
2223*b4f34f94SDavid van Moolenbroek 	}
2224*b4f34f94SDavid van Moolenbroek 	if (sz != sizeof(cons))
2225*b4f34f94SDavid van Moolenbroek 		errx(EXIT_FAILURE, "%s: !returned size wrong!", sname);
2226*b4f34f94SDavid van Moolenbroek 
2227*b4f34f94SDavid van Moolenbroek 	if (xflag || rflag)
2228*b4f34f94SDavid van Moolenbroek 		display_struct(pnode, sname, &cons, sz,
2229*b4f34f94SDavid van Moolenbroek 			       DISPLAY_VALUE);
2230*b4f34f94SDavid van Moolenbroek 	else {
2231*b4f34f94SDavid van Moolenbroek 		if (!nflag)
2232*b4f34f94SDavid van Moolenbroek 			printf("%s%s", sname, eq);
2233*b4f34f94SDavid van Moolenbroek 		if (nflag < 2 && (sname = devname(cons, S_IFCHR)) != NULL)
2234*b4f34f94SDavid van Moolenbroek 			printf("%s\n", sname);
2235*b4f34f94SDavid van Moolenbroek 		else
2236*b4f34f94SDavid van Moolenbroek 			printf("0x%llx\n", (unsigned long long)cons);
2237*b4f34f94SDavid van Moolenbroek 	}
2238*b4f34f94SDavid van Moolenbroek }
2239*b4f34f94SDavid van Moolenbroek 
2240*b4f34f94SDavid van Moolenbroek /*ARGSUSED*/
2241*b4f34f94SDavid van Moolenbroek static void
kern_cp_time(HANDLER_ARGS)2242*b4f34f94SDavid van Moolenbroek kern_cp_time(HANDLER_ARGS)
2243*b4f34f94SDavid van Moolenbroek {
2244*b4f34f94SDavid van Moolenbroek 	u_int64_t *cp_time;
2245*b4f34f94SDavid van Moolenbroek 	size_t sz, osz;
2246*b4f34f94SDavid van Moolenbroek 	int rc, i, n;
2247*b4f34f94SDavid van Moolenbroek 	char s[sizeof("kern.cp_time.nnnnnn")];
2248*b4f34f94SDavid van Moolenbroek 	const char *tname;
2249*b4f34f94SDavid van Moolenbroek 
2250*b4f34f94SDavid van Moolenbroek 	/*
2251*b4f34f94SDavid van Moolenbroek 	 * three things to do here.
2252*b4f34f94SDavid van Moolenbroek 	 * case 1: get sum (no Aflag and namelen == 2)
2253*b4f34f94SDavid van Moolenbroek 	 * case 2: get specific processor (namelen == 3)
2254*b4f34f94SDavid van Moolenbroek 	 * case 3: get all processors (Aflag and namelen == 2)
2255*b4f34f94SDavid van Moolenbroek 	 */
2256*b4f34f94SDavid van Moolenbroek 
2257*b4f34f94SDavid van Moolenbroek 	if (namelen == 2 && Aflag) {
2258*b4f34f94SDavid van Moolenbroek 		sz = sizeof(n);
2259*b4f34f94SDavid van Moolenbroek 		rc = sysctlbyname("hw.ncpu", &n, &sz, NULL, 0);
2260*b4f34f94SDavid van Moolenbroek 		if (rc != 0)
2261*b4f34f94SDavid van Moolenbroek 			return; /* XXX print an error, eh? */
2262*b4f34f94SDavid van Moolenbroek 		n++; /* Add on space for the sum. */
2263*b4f34f94SDavid van Moolenbroek 		sz = n * sizeof(u_int64_t) * CPUSTATES;
2264*b4f34f94SDavid van Moolenbroek 	}
2265*b4f34f94SDavid van Moolenbroek 	else {
2266*b4f34f94SDavid van Moolenbroek 		n = -1; /* Just print one data set. */
2267*b4f34f94SDavid van Moolenbroek 		sz = sizeof(u_int64_t) * CPUSTATES;
2268*b4f34f94SDavid van Moolenbroek 	}
2269*b4f34f94SDavid van Moolenbroek 
2270*b4f34f94SDavid van Moolenbroek 	cp_time = malloc(sz);
2271*b4f34f94SDavid van Moolenbroek 	if (cp_time == NULL) {
2272*b4f34f94SDavid van Moolenbroek 		sysctlerror(1);
2273*b4f34f94SDavid van Moolenbroek 		return;
2274*b4f34f94SDavid van Moolenbroek 	}
2275*b4f34f94SDavid van Moolenbroek 
2276*b4f34f94SDavid van Moolenbroek 	osz = sz;
2277*b4f34f94SDavid van Moolenbroek 	rc = prog_sysctl(name, namelen, cp_time + (n != -1) * CPUSTATES, &osz,
2278*b4f34f94SDavid van Moolenbroek 		    NULL, 0);
2279*b4f34f94SDavid van Moolenbroek 
2280*b4f34f94SDavid van Moolenbroek 	if (rc == -1) {
2281*b4f34f94SDavid van Moolenbroek 		sysctlerror(1);
2282*b4f34f94SDavid van Moolenbroek 		free(cp_time);
2283*b4f34f94SDavid van Moolenbroek 		return;
2284*b4f34f94SDavid van Moolenbroek 	}
2285*b4f34f94SDavid van Moolenbroek 
2286*b4f34f94SDavid van Moolenbroek 	/*
2287*b4f34f94SDavid van Moolenbroek 	 * Check, but account for space we'll occupy with the sum.
2288*b4f34f94SDavid van Moolenbroek 	 */
2289*b4f34f94SDavid van Moolenbroek 	if (osz != sz - (n != -1) * CPUSTATES * sizeof(u_int64_t))
2290*b4f34f94SDavid van Moolenbroek 		errx(EXIT_FAILURE, "%s: !returned size wrong!", sname);
2291*b4f34f94SDavid van Moolenbroek 
2292*b4f34f94SDavid van Moolenbroek 	/*
2293*b4f34f94SDavid van Moolenbroek 	 * Compute the actual sum.  Two calls would be easier (we
2294*b4f34f94SDavid van Moolenbroek 	 * could just call ourselves recursively above), but the
2295*b4f34f94SDavid van Moolenbroek 	 * numbers wouldn't add up.
2296*b4f34f94SDavid van Moolenbroek 	 */
2297*b4f34f94SDavid van Moolenbroek 	if (n != -1) {
2298*b4f34f94SDavid van Moolenbroek 		memset(cp_time, 0, sizeof(u_int64_t) * CPUSTATES);
2299*b4f34f94SDavid van Moolenbroek 		for (i = 1; i < n; i++) {
2300*b4f34f94SDavid van Moolenbroek 			cp_time[CP_USER] += cp_time[i * CPUSTATES + CP_USER];
2301*b4f34f94SDavid van Moolenbroek                         cp_time[CP_NICE] += cp_time[i * CPUSTATES + CP_NICE];
2302*b4f34f94SDavid van Moolenbroek                         cp_time[CP_SYS] += cp_time[i * CPUSTATES + CP_SYS];
2303*b4f34f94SDavid van Moolenbroek                         cp_time[CP_INTR] += cp_time[i * CPUSTATES + CP_INTR];
2304*b4f34f94SDavid van Moolenbroek                         cp_time[CP_IDLE] += cp_time[i * CPUSTATES + CP_IDLE];
2305*b4f34f94SDavid van Moolenbroek 		}
2306*b4f34f94SDavid van Moolenbroek 	}
2307*b4f34f94SDavid van Moolenbroek 
2308*b4f34f94SDavid van Moolenbroek 	tname = sname;
2309*b4f34f94SDavid van Moolenbroek 	for (i = 0; n == -1 || i < n; i++) {
2310*b4f34f94SDavid van Moolenbroek 		if (i > 0) {
2311*b4f34f94SDavid van Moolenbroek 			(void)snprintf(s, sizeof(s), "%s%s%d", sname, sep,
2312*b4f34f94SDavid van Moolenbroek 				       i - 1);
2313*b4f34f94SDavid van Moolenbroek 			tname = s;
2314*b4f34f94SDavid van Moolenbroek 		}
2315*b4f34f94SDavid van Moolenbroek 		if (xflag || rflag)
2316*b4f34f94SDavid van Moolenbroek 			display_struct(pnode, tname, cp_time + (i * CPUSTATES),
2317*b4f34f94SDavid van Moolenbroek 				       sizeof(u_int64_t) * CPUSTATES,
2318*b4f34f94SDavid van Moolenbroek 				       DISPLAY_VALUE);
2319*b4f34f94SDavid van Moolenbroek 		else {
2320*b4f34f94SDavid van Moolenbroek 			if (!nflag)
2321*b4f34f94SDavid van Moolenbroek 				printf("%s: ", tname);
2322*b4f34f94SDavid van Moolenbroek 			printf("user = %" PRIu64
2323*b4f34f94SDavid van Moolenbroek 			       ", nice = %" PRIu64
2324*b4f34f94SDavid van Moolenbroek 			       ", sys = %" PRIu64
2325*b4f34f94SDavid van Moolenbroek 			       ", intr = %" PRIu64
2326*b4f34f94SDavid van Moolenbroek 			       ", idle = %" PRIu64
2327*b4f34f94SDavid van Moolenbroek 			       "\n",
2328*b4f34f94SDavid van Moolenbroek 			       cp_time[i * CPUSTATES + CP_USER],
2329*b4f34f94SDavid van Moolenbroek 			       cp_time[i * CPUSTATES + CP_NICE],
2330*b4f34f94SDavid van Moolenbroek 			       cp_time[i * CPUSTATES + CP_SYS],
2331*b4f34f94SDavid van Moolenbroek 			       cp_time[i * CPUSTATES + CP_INTR],
2332*b4f34f94SDavid van Moolenbroek 			       cp_time[i * CPUSTATES + CP_IDLE]);
2333*b4f34f94SDavid van Moolenbroek 		}
2334*b4f34f94SDavid van Moolenbroek 		/*
2335*b4f34f94SDavid van Moolenbroek 		 * Just printing the one node.
2336*b4f34f94SDavid van Moolenbroek 		 */
2337*b4f34f94SDavid van Moolenbroek 		if (n == -1)
2338*b4f34f94SDavid van Moolenbroek 			break;
2339*b4f34f94SDavid van Moolenbroek 	}
2340*b4f34f94SDavid van Moolenbroek 
2341*b4f34f94SDavid van Moolenbroek 	free(cp_time);
2342*b4f34f94SDavid van Moolenbroek }
2343*b4f34f94SDavid van Moolenbroek 
2344*b4f34f94SDavid van Moolenbroek /*ARGSUSED*/
2345*b4f34f94SDavid van Moolenbroek static void
kern_drivers(HANDLER_ARGS)2346*b4f34f94SDavid van Moolenbroek kern_drivers(HANDLER_ARGS)
2347*b4f34f94SDavid van Moolenbroek {
2348*b4f34f94SDavid van Moolenbroek 	struct kinfo_drivers *kd;
2349*b4f34f94SDavid van Moolenbroek 	size_t sz, i;
2350*b4f34f94SDavid van Moolenbroek 	int rc;
2351*b4f34f94SDavid van Moolenbroek 	const char *comma;
2352*b4f34f94SDavid van Moolenbroek 
2353*b4f34f94SDavid van Moolenbroek 	rc = prog_sysctl(name, namelen, NULL, &sz, NULL, 0);
2354*b4f34f94SDavid van Moolenbroek 	if (rc == -1) {
2355*b4f34f94SDavid van Moolenbroek 		sysctlerror(1);
2356*b4f34f94SDavid van Moolenbroek 		return;
2357*b4f34f94SDavid van Moolenbroek 	}
2358*b4f34f94SDavid van Moolenbroek 
2359*b4f34f94SDavid van Moolenbroek 	if (sz % sizeof(*kd))
2360*b4f34f94SDavid van Moolenbroek 		err(EXIT_FAILURE, "bad size %zu for kern.drivers", sz);
2361*b4f34f94SDavid van Moolenbroek 
2362*b4f34f94SDavid van Moolenbroek 	kd = malloc(sz);
2363*b4f34f94SDavid van Moolenbroek 	if (kd == NULL) {
2364*b4f34f94SDavid van Moolenbroek 		sysctlerror(1);
2365*b4f34f94SDavid van Moolenbroek 		return;
2366*b4f34f94SDavid van Moolenbroek 	}
2367*b4f34f94SDavid van Moolenbroek 
2368*b4f34f94SDavid van Moolenbroek 	rc = prog_sysctl(name, namelen, kd, &sz, NULL, 0);
2369*b4f34f94SDavid van Moolenbroek 	if (rc == -1) {
2370*b4f34f94SDavid van Moolenbroek 		sysctlerror(1);
2371*b4f34f94SDavid van Moolenbroek 		free(kd);
2372*b4f34f94SDavid van Moolenbroek 		return;
2373*b4f34f94SDavid van Moolenbroek 	}
2374*b4f34f94SDavid van Moolenbroek 
2375*b4f34f94SDavid van Moolenbroek 	comma = "";
2376*b4f34f94SDavid van Moolenbroek 	if (!nflag)
2377*b4f34f94SDavid van Moolenbroek 		printf("%s%s", sname, eq);
2378*b4f34f94SDavid van Moolenbroek 	for (i = 0, sz /= sizeof(*kd); i < sz; i++) {
2379*b4f34f94SDavid van Moolenbroek 		(void)printf("%s[%d %d %s]", comma, kd[i].d_cmajor,
2380*b4f34f94SDavid van Moolenbroek 		    kd[i].d_bmajor, kd[i].d_name);
2381*b4f34f94SDavid van Moolenbroek 		comma = ", ";
2382*b4f34f94SDavid van Moolenbroek 	}
2383*b4f34f94SDavid van Moolenbroek 	(void)printf("\n");
2384*b4f34f94SDavid van Moolenbroek 	free(kd);
2385*b4f34f94SDavid van Moolenbroek }
2386*b4f34f94SDavid van Moolenbroek 
2387*b4f34f94SDavid van Moolenbroek /*ARGSUSED*/
2388*b4f34f94SDavid van Moolenbroek static void
kern_cp_id(HANDLER_ARGS)2389*b4f34f94SDavid van Moolenbroek kern_cp_id(HANDLER_ARGS)
2390*b4f34f94SDavid van Moolenbroek {
2391*b4f34f94SDavid van Moolenbroek 	u_int64_t *cp_id;
2392*b4f34f94SDavid van Moolenbroek 	size_t sz, osz;
2393*b4f34f94SDavid van Moolenbroek 	int rc, i, n;
2394*b4f34f94SDavid van Moolenbroek 	char s[sizeof("kern.cp_id.nnnnnn")];
2395*b4f34f94SDavid van Moolenbroek 	const char *tname;
2396*b4f34f94SDavid van Moolenbroek 	struct sysctlnode node = *pnode;
2397*b4f34f94SDavid van Moolenbroek 
2398*b4f34f94SDavid van Moolenbroek 	/*
2399*b4f34f94SDavid van Moolenbroek 	 * three things to do here.
2400*b4f34f94SDavid van Moolenbroek 	 * case 1: print a specific cpu id (namelen == 3)
2401*b4f34f94SDavid van Moolenbroek 	 * case 2: print all cpu ids separately (Aflag set)
2402*b4f34f94SDavid van Moolenbroek 	 * case 3: print all cpu ids on one line
2403*b4f34f94SDavid van Moolenbroek 	 */
2404*b4f34f94SDavid van Moolenbroek 
2405*b4f34f94SDavid van Moolenbroek 	if (namelen == 2) {
2406*b4f34f94SDavid van Moolenbroek 		sz = sizeof(n);
2407*b4f34f94SDavid van Moolenbroek 		rc = sysctlbyname("hw.ncpu", &n, &sz, NULL, 0);
2408*b4f34f94SDavid van Moolenbroek 		if (rc != 0)
2409*b4f34f94SDavid van Moolenbroek 			return; /* XXX print an error, eh? */
2410*b4f34f94SDavid van Moolenbroek 		sz = n * sizeof(u_int64_t);
2411*b4f34f94SDavid van Moolenbroek 	}
2412*b4f34f94SDavid van Moolenbroek 	else {
2413*b4f34f94SDavid van Moolenbroek 		n = -1; /* Just print one cpu id. */
2414*b4f34f94SDavid van Moolenbroek 		sz = sizeof(u_int64_t);
2415*b4f34f94SDavid van Moolenbroek 	}
2416*b4f34f94SDavid van Moolenbroek 
2417*b4f34f94SDavid van Moolenbroek 	cp_id = malloc(sz);
2418*b4f34f94SDavid van Moolenbroek 	if (cp_id == NULL) {
2419*b4f34f94SDavid van Moolenbroek 		sysctlerror(1);
2420*b4f34f94SDavid van Moolenbroek 		return;
2421*b4f34f94SDavid van Moolenbroek 	}
2422*b4f34f94SDavid van Moolenbroek 
2423*b4f34f94SDavid van Moolenbroek 	osz = sz;
2424*b4f34f94SDavid van Moolenbroek 	rc = prog_sysctl(name, namelen, cp_id, &osz, NULL, 0);
2425*b4f34f94SDavid van Moolenbroek 	if (rc == -1) {
2426*b4f34f94SDavid van Moolenbroek 		sysctlerror(1);
2427*b4f34f94SDavid van Moolenbroek 		free(cp_id);
2428*b4f34f94SDavid van Moolenbroek 		return;
2429*b4f34f94SDavid van Moolenbroek 	}
2430*b4f34f94SDavid van Moolenbroek 
2431*b4f34f94SDavid van Moolenbroek 	/*
2432*b4f34f94SDavid van Moolenbroek 	 * Check that we got back what we asked for.
2433*b4f34f94SDavid van Moolenbroek 	 */
2434*b4f34f94SDavid van Moolenbroek 	if (osz != sz)
2435*b4f34f94SDavid van Moolenbroek 		errx(EXIT_FAILURE, "%s: !returned size wrong!", sname);
2436*b4f34f94SDavid van Moolenbroek 
2437*b4f34f94SDavid van Moolenbroek 	/* pretend for output purposes */
2438*b4f34f94SDavid van Moolenbroek 	node.sysctl_flags = SYSCTL_FLAGS(pnode->sysctl_flags) |
2439*b4f34f94SDavid van Moolenbroek 		SYSCTL_TYPE(CTLTYPE_QUAD);
2440*b4f34f94SDavid van Moolenbroek 
2441*b4f34f94SDavid van Moolenbroek 	tname = sname;
2442*b4f34f94SDavid van Moolenbroek 	if (namelen == 3)
2443*b4f34f94SDavid van Moolenbroek 		display_number(&node, tname, cp_id,
2444*b4f34f94SDavid van Moolenbroek 			       sizeof(u_int64_t),
2445*b4f34f94SDavid van Moolenbroek 			       DISPLAY_VALUE);
2446*b4f34f94SDavid van Moolenbroek 	else if (Aflag) {
2447*b4f34f94SDavid van Moolenbroek 		for (i = 0; i < n; i++)
2448*b4f34f94SDavid van Moolenbroek 			(void)snprintf(s, sizeof(s), "%s%s%d", sname, sep, i);
2449*b4f34f94SDavid van Moolenbroek 			tname = s;
2450*b4f34f94SDavid van Moolenbroek 			display_number(&node, tname, &cp_id[i],
2451*b4f34f94SDavid van Moolenbroek 				       sizeof(u_int64_t),
2452*b4f34f94SDavid van Moolenbroek 				       DISPLAY_VALUE);
2453*b4f34f94SDavid van Moolenbroek 	}
2454*b4f34f94SDavid van Moolenbroek 	else {
2455*b4f34f94SDavid van Moolenbroek 		if (xflag || rflag)
2456*b4f34f94SDavid van Moolenbroek 			display_struct(pnode, tname, cp_id, sz, DISPLAY_VALUE);
2457*b4f34f94SDavid van Moolenbroek 		else {
2458*b4f34f94SDavid van Moolenbroek 			if (!nflag)
2459*b4f34f94SDavid van Moolenbroek 				printf("%s: ", tname);
2460*b4f34f94SDavid van Moolenbroek 			for (i = 0; i < n; i++) {
2461*b4f34f94SDavid van Moolenbroek 				if (i)
2462*b4f34f94SDavid van Moolenbroek 					printf(", ");
2463*b4f34f94SDavid van Moolenbroek 				printf("%d = %" PRIu64, i, cp_id[i]);
2464*b4f34f94SDavid van Moolenbroek 			}
2465*b4f34f94SDavid van Moolenbroek 			printf("\n");
2466*b4f34f94SDavid van Moolenbroek 		}
2467*b4f34f94SDavid van Moolenbroek 	}
2468*b4f34f94SDavid van Moolenbroek 
2469*b4f34f94SDavid van Moolenbroek 	free(cp_id);
2470*b4f34f94SDavid van Moolenbroek }
2471*b4f34f94SDavid van Moolenbroek 
2472*b4f34f94SDavid van Moolenbroek /*ARGSUSED*/
2473*b4f34f94SDavid van Moolenbroek static void
vm_loadavg(HANDLER_ARGS)2474*b4f34f94SDavid van Moolenbroek vm_loadavg(HANDLER_ARGS)
2475*b4f34f94SDavid van Moolenbroek {
2476*b4f34f94SDavid van Moolenbroek 	struct loadavg loadavg;
2477*b4f34f94SDavid van Moolenbroek 	size_t sz;
2478*b4f34f94SDavid van Moolenbroek 	int rc;
2479*b4f34f94SDavid van Moolenbroek 
2480*b4f34f94SDavid van Moolenbroek 	sz = sizeof(loadavg);
2481*b4f34f94SDavid van Moolenbroek 	rc = prog_sysctl(name, namelen, &loadavg, &sz, NULL, 0);
2482*b4f34f94SDavid van Moolenbroek 	if (rc == -1) {
2483*b4f34f94SDavid van Moolenbroek 		sysctlerror(1);
2484*b4f34f94SDavid van Moolenbroek 		return;
2485*b4f34f94SDavid van Moolenbroek 	}
2486*b4f34f94SDavid van Moolenbroek 	if (sz != sizeof(loadavg))
2487*b4f34f94SDavid van Moolenbroek 		errx(EXIT_FAILURE, "%s: !returned size wrong!", sname);
2488*b4f34f94SDavid van Moolenbroek 
2489*b4f34f94SDavid van Moolenbroek 	if (xflag || rflag) {
2490*b4f34f94SDavid van Moolenbroek 		display_struct(pnode, sname, &loadavg, sz,
2491*b4f34f94SDavid van Moolenbroek 			       DISPLAY_VALUE);
2492*b4f34f94SDavid van Moolenbroek 		return;
2493*b4f34f94SDavid van Moolenbroek 	}
2494*b4f34f94SDavid van Moolenbroek 	if (!nflag)
2495*b4f34f94SDavid van Moolenbroek 		printf("%s: ", sname);
2496*b4f34f94SDavid van Moolenbroek 	printf("%.2f %.2f %.2f\n",
2497*b4f34f94SDavid van Moolenbroek 	       (double) loadavg.ldavg[0] / loadavg.fscale,
2498*b4f34f94SDavid van Moolenbroek 	       (double) loadavg.ldavg[1] / loadavg.fscale,
2499*b4f34f94SDavid van Moolenbroek 	       (double) loadavg.ldavg[2] / loadavg.fscale);
2500*b4f34f94SDavid van Moolenbroek }
2501*b4f34f94SDavid van Moolenbroek 
2502*b4f34f94SDavid van Moolenbroek /*ARGSUSED*/
2503*b4f34f94SDavid van Moolenbroek static void
proc_limit(HANDLER_ARGS)2504*b4f34f94SDavid van Moolenbroek proc_limit(HANDLER_ARGS)
2505*b4f34f94SDavid van Moolenbroek {
2506*b4f34f94SDavid van Moolenbroek 	u_quad_t olim, *newp, nlim;
2507*b4f34f94SDavid van Moolenbroek 	size_t osz, nsz;
2508*b4f34f94SDavid van Moolenbroek 	char *t;
2509*b4f34f94SDavid van Moolenbroek 	int rc;
2510*b4f34f94SDavid van Moolenbroek 
2511*b4f34f94SDavid van Moolenbroek 	if (fn)
2512*b4f34f94SDavid van Moolenbroek 		trim_whitespace(value, 3);
2513*b4f34f94SDavid van Moolenbroek 
2514*b4f34f94SDavid van Moolenbroek 	osz = sizeof(olim);
2515*b4f34f94SDavid van Moolenbroek 	if (value != NULL) {
2516*b4f34f94SDavid van Moolenbroek 		nsz = sizeof(nlim);
2517*b4f34f94SDavid van Moolenbroek 		newp = &nlim;
2518*b4f34f94SDavid van Moolenbroek 		if (strcmp(value, "unlimited") == 0)
2519*b4f34f94SDavid van Moolenbroek 			nlim = RLIM_INFINITY;
2520*b4f34f94SDavid van Moolenbroek 		else {
2521*b4f34f94SDavid van Moolenbroek 			errno = 0;
2522*b4f34f94SDavid van Moolenbroek 			nlim = strtouq(value, &t, 0);
2523*b4f34f94SDavid van Moolenbroek 			if (t == value || *t != '\0' || errno != 0) {
2524*b4f34f94SDavid van Moolenbroek 				sysctlperror("%s: '%s' is not a valid limit\n",
2525*b4f34f94SDavid van Moolenbroek 					     sname, value);
2526*b4f34f94SDavid van Moolenbroek 				EXIT(EXIT_FAILURE);
2527*b4f34f94SDavid van Moolenbroek 			}
2528*b4f34f94SDavid van Moolenbroek 		}
2529*b4f34f94SDavid van Moolenbroek 	}
2530*b4f34f94SDavid van Moolenbroek 	else {
2531*b4f34f94SDavid van Moolenbroek 		nsz = 0;
2532*b4f34f94SDavid van Moolenbroek 		newp = NULL;
2533*b4f34f94SDavid van Moolenbroek 	}
2534*b4f34f94SDavid van Moolenbroek 
2535*b4f34f94SDavid van Moolenbroek 	rc = prog_sysctl(name, namelen, &olim, &osz, newp, nsz);
2536*b4f34f94SDavid van Moolenbroek 	if (rc == -1) {
2537*b4f34f94SDavid van Moolenbroek 		sysctlerror(newp == NULL);
2538*b4f34f94SDavid van Moolenbroek 		return;
2539*b4f34f94SDavid van Moolenbroek 	}
2540*b4f34f94SDavid van Moolenbroek 
2541*b4f34f94SDavid van Moolenbroek 	if (newp && qflag)
2542*b4f34f94SDavid van Moolenbroek 		return;
2543*b4f34f94SDavid van Moolenbroek 
2544*b4f34f94SDavid van Moolenbroek 	if (rflag || xflag || olim != RLIM_INFINITY)
2545*b4f34f94SDavid van Moolenbroek 		display_number(pnode, sname, &olim, sizeof(olim),
2546*b4f34f94SDavid van Moolenbroek 			       newp ? DISPLAY_OLD : DISPLAY_VALUE);
2547*b4f34f94SDavid van Moolenbroek 	else
2548*b4f34f94SDavid van Moolenbroek 		display_string(pnode, sname, "unlimited", 10,
2549*b4f34f94SDavid van Moolenbroek 			       newp ? DISPLAY_OLD : DISPLAY_VALUE);
2550*b4f34f94SDavid van Moolenbroek 
2551*b4f34f94SDavid van Moolenbroek 	if (newp) {
2552*b4f34f94SDavid van Moolenbroek 		if (rflag || xflag || nlim != RLIM_INFINITY)
2553*b4f34f94SDavid van Moolenbroek 			display_number(pnode, sname, &nlim, sizeof(nlim),
2554*b4f34f94SDavid van Moolenbroek 				       DISPLAY_NEW);
2555*b4f34f94SDavid van Moolenbroek 		else
2556*b4f34f94SDavid van Moolenbroek 			display_string(pnode, sname, "unlimited", 10,
2557*b4f34f94SDavid van Moolenbroek 				       DISPLAY_NEW);
2558*b4f34f94SDavid van Moolenbroek 	}
2559*b4f34f94SDavid van Moolenbroek }
2560*b4f34f94SDavid van Moolenbroek 
2561*b4f34f94SDavid van Moolenbroek #ifdef CPU_DISKINFO
2562*b4f34f94SDavid van Moolenbroek /*ARGSUSED*/
2563*b4f34f94SDavid van Moolenbroek static void
machdep_diskinfo(HANDLER_ARGS)2564*b4f34f94SDavid van Moolenbroek machdep_diskinfo(HANDLER_ARGS)
2565*b4f34f94SDavid van Moolenbroek {
2566*b4f34f94SDavid van Moolenbroek 	struct disklist *dl;
2567*b4f34f94SDavid van Moolenbroek 	struct biosdisk_info *bi;
2568*b4f34f94SDavid van Moolenbroek 	struct nativedisk_info *ni;
2569*b4f34f94SDavid van Moolenbroek 	int rc;
2570*b4f34f94SDavid van Moolenbroek 	size_t sz;
2571*b4f34f94SDavid van Moolenbroek 	uint i, b, lim;
2572*b4f34f94SDavid van Moolenbroek 
2573*b4f34f94SDavid van Moolenbroek 	rc = prog_sysctl(name, namelen, NULL, &sz, NULL, 0);
2574*b4f34f94SDavid van Moolenbroek 	if (rc == -1) {
2575*b4f34f94SDavid van Moolenbroek 		sysctlerror(1);
2576*b4f34f94SDavid van Moolenbroek 		return;
2577*b4f34f94SDavid van Moolenbroek 	}
2578*b4f34f94SDavid van Moolenbroek 	dl = malloc(sz);
2579*b4f34f94SDavid van Moolenbroek 	if (dl == NULL) {
2580*b4f34f94SDavid van Moolenbroek 		sysctlerror(1);
2581*b4f34f94SDavid van Moolenbroek 		return;
2582*b4f34f94SDavid van Moolenbroek 	}
2583*b4f34f94SDavid van Moolenbroek 	rc = prog_sysctl(name, namelen, dl, &sz, NULL, 0);
2584*b4f34f94SDavid van Moolenbroek 	if (rc == -1) {
2585*b4f34f94SDavid van Moolenbroek 		sysctlerror(1);
2586*b4f34f94SDavid van Moolenbroek 		return;
2587*b4f34f94SDavid van Moolenbroek 	}
2588*b4f34f94SDavid van Moolenbroek 
2589*b4f34f94SDavid van Moolenbroek 	if (!nflag)
2590*b4f34f94SDavid van Moolenbroek 		printf("%s: ", sname);
2591*b4f34f94SDavid van Moolenbroek 	lim = dl->dl_nbiosdisks;
2592*b4f34f94SDavid van Moolenbroek 	if (lim > MAX_BIOSDISKS)
2593*b4f34f94SDavid van Moolenbroek 		lim = MAX_BIOSDISKS;
2594*b4f34f94SDavid van Moolenbroek 	for (bi = dl->dl_biosdisks, i = 0; i < lim; bi++, i++)
2595*b4f34f94SDavid van Moolenbroek 		printf("%x:%" PRIu64 "(%d/%d/%d),%x ",
2596*b4f34f94SDavid van Moolenbroek 		       bi->bi_dev, bi->bi_lbasecs,
2597*b4f34f94SDavid van Moolenbroek 		       bi->bi_cyl, bi->bi_head, bi->bi_sec,
2598*b4f34f94SDavid van Moolenbroek 		       bi->bi_flags);
2599*b4f34f94SDavid van Moolenbroek 	lim = dl->dl_nnativedisks;
2600*b4f34f94SDavid van Moolenbroek 	ni = dl->dl_nativedisks;
2601*b4f34f94SDavid van Moolenbroek 	bi = dl->dl_biosdisks;
2602*b4f34f94SDavid van Moolenbroek 	/* LINTED -- pointer casts are tedious */
2603*b4f34f94SDavid van Moolenbroek 	if ((char *)&ni[lim] != (char *)dl + sz) {
2604*b4f34f94SDavid van Moolenbroek 		sysctlperror("%s: size mismatch\n", gsname);
2605*b4f34f94SDavid van Moolenbroek 		return;
2606*b4f34f94SDavid van Moolenbroek 	}
2607*b4f34f94SDavid van Moolenbroek 	for (i = 0; i < lim; ni++, i++) {
2608*b4f34f94SDavid van Moolenbroek 		char t = ':';
2609*b4f34f94SDavid van Moolenbroek 		printf(" %.*s", (int)sizeof ni->ni_devname,
2610*b4f34f94SDavid van Moolenbroek 		       ni->ni_devname);
2611*b4f34f94SDavid van Moolenbroek 		for (b = 0; b < (unsigned int)ni->ni_nmatches; t = ',', b++)
2612*b4f34f94SDavid van Moolenbroek 			printf("%c%x", t,
2613*b4f34f94SDavid van Moolenbroek 			       bi[ni->ni_biosmatches[b]].bi_dev);
2614*b4f34f94SDavid van Moolenbroek 	}
2615*b4f34f94SDavid van Moolenbroek 	printf("\n");
2616*b4f34f94SDavid van Moolenbroek 	free(dl);
2617*b4f34f94SDavid van Moolenbroek }
2618*b4f34f94SDavid van Moolenbroek #endif /* CPU_DISKINFO */
2619*b4f34f94SDavid van Moolenbroek 
2620*b4f34f94SDavid van Moolenbroek /*ARGSUSED*/
2621*b4f34f94SDavid van Moolenbroek static void
mode_bits(HANDLER_ARGS)2622*b4f34f94SDavid van Moolenbroek mode_bits(HANDLER_ARGS)
2623*b4f34f94SDavid van Moolenbroek {
2624*b4f34f94SDavid van Moolenbroek 	char buf[12], outbuf[100];
2625*b4f34f94SDavid van Moolenbroek 	int o, m, *newp, rc;
2626*b4f34f94SDavid van Moolenbroek 	size_t osz, nsz;
2627*b4f34f94SDavid van Moolenbroek 	mode_t om, mm;
2628*b4f34f94SDavid van Moolenbroek 
2629*b4f34f94SDavid van Moolenbroek 	if (fn)
2630*b4f34f94SDavid van Moolenbroek 		trim_whitespace(value, 3);
2631*b4f34f94SDavid van Moolenbroek 
2632*b4f34f94SDavid van Moolenbroek 	newp = NULL;
2633*b4f34f94SDavid van Moolenbroek 	osz = sizeof(o);
2634*b4f34f94SDavid van Moolenbroek 	if (value != NULL) {
2635*b4f34f94SDavid van Moolenbroek 		void *foo;
2636*b4f34f94SDavid van Moolenbroek 		int tt;
2637*b4f34f94SDavid van Moolenbroek 		size_t ttsz = sizeof(tt);
2638*b4f34f94SDavid van Moolenbroek 		mode_t old_umask;
2639*b4f34f94SDavid van Moolenbroek 
2640*b4f34f94SDavid van Moolenbroek 		nsz = sizeof(m);
2641*b4f34f94SDavid van Moolenbroek 		newp = &m;
2642*b4f34f94SDavid van Moolenbroek 		errno = 0;
2643*b4f34f94SDavid van Moolenbroek 		rc = prog_sysctl(name, namelen, &tt, &ttsz, NULL, 0);
2644*b4f34f94SDavid van Moolenbroek 		if (rc == -1) {
2645*b4f34f94SDavid van Moolenbroek 			sysctlperror("%s: failed query\n", sname);
2646*b4f34f94SDavid van Moolenbroek 			return;
2647*b4f34f94SDavid van Moolenbroek 		}
2648*b4f34f94SDavid van Moolenbroek 
2649*b4f34f94SDavid van Moolenbroek 		old_umask = umask(0);
2650*b4f34f94SDavid van Moolenbroek 		foo = setmode(value);
2651*b4f34f94SDavid van Moolenbroek 		umask(old_umask);
2652*b4f34f94SDavid van Moolenbroek 		if (foo == NULL) {
2653*b4f34f94SDavid van Moolenbroek 			sysctlperror("%s: '%s' is an invalid mode\n", sname,
2654*b4f34f94SDavid van Moolenbroek 				     value);
2655*b4f34f94SDavid van Moolenbroek 			EXIT(EXIT_FAILURE);
2656*b4f34f94SDavid van Moolenbroek 		}
2657*b4f34f94SDavid van Moolenbroek 		old_umask = umask(0);
2658*b4f34f94SDavid van Moolenbroek 		m = getmode(foo, (mode_t)tt);
2659*b4f34f94SDavid van Moolenbroek 		umask(old_umask);
2660*b4f34f94SDavid van Moolenbroek 		if (errno) {
2661*b4f34f94SDavid van Moolenbroek 			sysctlperror("%s: '%s' is an invalid mode\n", sname,
2662*b4f34f94SDavid van Moolenbroek 				     value);
2663*b4f34f94SDavid van Moolenbroek 			EXIT(EXIT_FAILURE);
2664*b4f34f94SDavid van Moolenbroek 		}
2665*b4f34f94SDavid van Moolenbroek 	}
2666*b4f34f94SDavid van Moolenbroek 	else {
2667*b4f34f94SDavid van Moolenbroek 		nsz = 0;
2668*b4f34f94SDavid van Moolenbroek 		newp = NULL;
2669*b4f34f94SDavid van Moolenbroek 	}
2670*b4f34f94SDavid van Moolenbroek 
2671*b4f34f94SDavid van Moolenbroek 	rc = prog_sysctl(name, namelen, &o, &osz, newp, nsz);
2672*b4f34f94SDavid van Moolenbroek 	if (rc == -1) {
2673*b4f34f94SDavid van Moolenbroek 		sysctlerror(newp == NULL);
2674*b4f34f94SDavid van Moolenbroek 		return;
2675*b4f34f94SDavid van Moolenbroek 	}
2676*b4f34f94SDavid van Moolenbroek 
2677*b4f34f94SDavid van Moolenbroek 	if (newp && qflag)
2678*b4f34f94SDavid van Moolenbroek 		return;
2679*b4f34f94SDavid van Moolenbroek 
2680*b4f34f94SDavid van Moolenbroek 	om = (mode_t)o;
2681*b4f34f94SDavid van Moolenbroek 	mm = (mode_t)m;
2682*b4f34f94SDavid van Moolenbroek 
2683*b4f34f94SDavid van Moolenbroek 	if (rflag || xflag)
2684*b4f34f94SDavid van Moolenbroek 		display_number(pnode, sname, &o, sizeof(o),
2685*b4f34f94SDavid van Moolenbroek 			       newp ? DISPLAY_OLD : DISPLAY_VALUE);
2686*b4f34f94SDavid van Moolenbroek 	else {
2687*b4f34f94SDavid van Moolenbroek 		memset(buf, 0, sizeof(buf));
2688*b4f34f94SDavid van Moolenbroek 		strmode(om, buf);
2689*b4f34f94SDavid van Moolenbroek 		rc = snprintf(outbuf, sizeof(outbuf), "%04o (%s)", om, buf + 1);
2690*b4f34f94SDavid van Moolenbroek 		display_string(pnode, sname, outbuf, rc, newp ? DISPLAY_OLD : DISPLAY_VALUE);
2691*b4f34f94SDavid van Moolenbroek 	}
2692*b4f34f94SDavid van Moolenbroek 
2693*b4f34f94SDavid van Moolenbroek 	if (newp) {
2694*b4f34f94SDavid van Moolenbroek 		if (rflag || xflag)
2695*b4f34f94SDavid van Moolenbroek 			display_number(pnode, sname, &m, sizeof(m),
2696*b4f34f94SDavid van Moolenbroek 				       DISPLAY_NEW);
2697*b4f34f94SDavid van Moolenbroek 		else {
2698*b4f34f94SDavid van Moolenbroek 			memset(buf, 0, sizeof(buf));
2699*b4f34f94SDavid van Moolenbroek 			strmode(mm, buf);
2700*b4f34f94SDavid van Moolenbroek 			rc = snprintf(outbuf, sizeof(outbuf), "%04o (%s)", mm, buf + 1);
2701*b4f34f94SDavid van Moolenbroek 			display_string(pnode, sname, outbuf, rc, DISPLAY_NEW);
2702*b4f34f94SDavid van Moolenbroek 		}
2703*b4f34f94SDavid van Moolenbroek 	}
2704*b4f34f94SDavid van Moolenbroek }
2705*b4f34f94SDavid van Moolenbroek 
2706*b4f34f94SDavid van Moolenbroek typedef __BITMAP_TYPE(, uint32_t, 0x10000) bitmap;
2707*b4f34f94SDavid van Moolenbroek 
2708*b4f34f94SDavid van Moolenbroek static char *
bitmask_print(const bitmap * o)2709*b4f34f94SDavid van Moolenbroek bitmask_print(const bitmap *o)
2710*b4f34f94SDavid van Moolenbroek {
2711*b4f34f94SDavid van Moolenbroek 	char *s, *os;
2712*b4f34f94SDavid van Moolenbroek 
2713*b4f34f94SDavid van Moolenbroek 	s = os = NULL;
2714*b4f34f94SDavid van Moolenbroek 	for (size_t i = 0; i < MAXPORTS; i++)
2715*b4f34f94SDavid van Moolenbroek 		if (__BITMAP_ISSET(i, o)) {
2716*b4f34f94SDavid van Moolenbroek 			int rv;
2717*b4f34f94SDavid van Moolenbroek 
2718*b4f34f94SDavid van Moolenbroek 			if (os)
2719*b4f34f94SDavid van Moolenbroek 			    	rv = asprintf(&s, "%s,%zu", os, i);
2720*b4f34f94SDavid van Moolenbroek 			else
2721*b4f34f94SDavid van Moolenbroek 			    	rv = asprintf(&s, "%zu", i);
2722*b4f34f94SDavid van Moolenbroek 			if (rv == -1)
2723*b4f34f94SDavid van Moolenbroek 				err(EXIT_FAILURE, "%s 1", __func__);
2724*b4f34f94SDavid van Moolenbroek 			free(os);
2725*b4f34f94SDavid van Moolenbroek 			os = s;
2726*b4f34f94SDavid van Moolenbroek 		}
2727*b4f34f94SDavid van Moolenbroek 	if (s == NULL && (s = strdup("")) == NULL)
2728*b4f34f94SDavid van Moolenbroek 		err(EXIT_FAILURE, "%s 2", __func__);
2729*b4f34f94SDavid van Moolenbroek 	return s;
2730*b4f34f94SDavid van Moolenbroek }
2731*b4f34f94SDavid van Moolenbroek 
2732*b4f34f94SDavid van Moolenbroek static void
bitmask_scan(const void * v,bitmap * o)2733*b4f34f94SDavid van Moolenbroek bitmask_scan(const void *v, bitmap *o)
2734*b4f34f94SDavid van Moolenbroek {
2735*b4f34f94SDavid van Moolenbroek 	char *s = strdup(v);
2736*b4f34f94SDavid van Moolenbroek 	if (s == NULL)
2737*b4f34f94SDavid van Moolenbroek 		err(EXIT_FAILURE, "%s", __func__);
2738*b4f34f94SDavid van Moolenbroek 
2739*b4f34f94SDavid van Moolenbroek 	__BITMAP_ZERO(o);
2740*b4f34f94SDavid van Moolenbroek 	for (s = strtok(s, ","); s; s = strtok(NULL, ",")) {
2741*b4f34f94SDavid van Moolenbroek 		char *e;
2742*b4f34f94SDavid van Moolenbroek 		errno = 0;
2743*b4f34f94SDavid van Moolenbroek 		unsigned long l = strtoul(s, &e, 0);
2744*b4f34f94SDavid van Moolenbroek 		if ((l == ULONG_MAX && errno == ERANGE) || s == e || *e)
2745*b4f34f94SDavid van Moolenbroek 			errx(EXIT_FAILURE, "Invalid port: %s", s);
2746*b4f34f94SDavid van Moolenbroek 		if (l >= MAXPORTS)
2747*b4f34f94SDavid van Moolenbroek 			errx(EXIT_FAILURE, "Port out of range: %s", s);
2748*b4f34f94SDavid van Moolenbroek 		__BITMAP_SET(l, o);
2749*b4f34f94SDavid van Moolenbroek 	}
2750*b4f34f94SDavid van Moolenbroek }
2751*b4f34f94SDavid van Moolenbroek 
2752*b4f34f94SDavid van Moolenbroek 
2753*b4f34f94SDavid van Moolenbroek static void
reserve(HANDLER_ARGS)2754*b4f34f94SDavid van Moolenbroek reserve(HANDLER_ARGS)
2755*b4f34f94SDavid van Moolenbroek {
2756*b4f34f94SDavid van Moolenbroek 	int rc;
2757*b4f34f94SDavid van Moolenbroek 	size_t osz, nsz;
2758*b4f34f94SDavid van Moolenbroek 	bitmap o, n;
2759*b4f34f94SDavid van Moolenbroek 
2760*b4f34f94SDavid van Moolenbroek 	if (fn)
2761*b4f34f94SDavid van Moolenbroek 		trim_whitespace(value, 3);
2762*b4f34f94SDavid van Moolenbroek 
2763*b4f34f94SDavid van Moolenbroek 	osz = sizeof(o);
2764*b4f34f94SDavid van Moolenbroek 	if (value) {
2765*b4f34f94SDavid van Moolenbroek 		bitmask_scan(value, &n);
2766*b4f34f94SDavid van Moolenbroek 		value = (char *)&n;
2767*b4f34f94SDavid van Moolenbroek 		nsz = sizeof(n);
2768*b4f34f94SDavid van Moolenbroek 	} else
2769*b4f34f94SDavid van Moolenbroek 		nsz = 0;
2770*b4f34f94SDavid van Moolenbroek 
2771*b4f34f94SDavid van Moolenbroek 	rc = prog_sysctl(name, namelen, &o, &osz, value, nsz);
2772*b4f34f94SDavid van Moolenbroek 	if (rc == -1) {
2773*b4f34f94SDavid van Moolenbroek 		sysctlerror(value == NULL);
2774*b4f34f94SDavid van Moolenbroek 		return;
2775*b4f34f94SDavid van Moolenbroek 	}
2776*b4f34f94SDavid van Moolenbroek 
2777*b4f34f94SDavid van Moolenbroek 	if (value && qflag)
2778*b4f34f94SDavid van Moolenbroek 		return;
2779*b4f34f94SDavid van Moolenbroek 
2780*b4f34f94SDavid van Moolenbroek 	if (rflag || xflag)
2781*b4f34f94SDavid van Moolenbroek 		display_struct(pnode, sname, &o, sizeof(o),
2782*b4f34f94SDavid van Moolenbroek 		    value ? DISPLAY_OLD : DISPLAY_VALUE);
2783*b4f34f94SDavid van Moolenbroek 	else {
2784*b4f34f94SDavid van Moolenbroek 		char *s = bitmask_print(&o);
2785*b4f34f94SDavid van Moolenbroek 		display_string(pnode, sname, s, strlen(s),
2786*b4f34f94SDavid van Moolenbroek 		    value ? DISPLAY_OLD : DISPLAY_VALUE);
2787*b4f34f94SDavid van Moolenbroek 		free(s);
2788*b4f34f94SDavid van Moolenbroek 	}
2789*b4f34f94SDavid van Moolenbroek 
2790*b4f34f94SDavid van Moolenbroek 	if (value) {
2791*b4f34f94SDavid van Moolenbroek 		if (rflag || xflag)
2792*b4f34f94SDavid van Moolenbroek 			display_struct(pnode, sname, &n, sizeof(n),
2793*b4f34f94SDavid van Moolenbroek 			    DISPLAY_NEW);
2794*b4f34f94SDavid van Moolenbroek 		else {
2795*b4f34f94SDavid van Moolenbroek 			char *s = bitmask_print(&n);
2796*b4f34f94SDavid van Moolenbroek 			display_string(pnode, sname, s, strlen(s), DISPLAY_NEW);
2797*b4f34f94SDavid van Moolenbroek 			free(s);
2798*b4f34f94SDavid van Moolenbroek 		}
2799*b4f34f94SDavid van Moolenbroek 	}
2800*b4f34f94SDavid van Moolenbroek }
2801