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 = ⅈ
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