Wed Mar 18 01:28:25 2009 UTC ()
Format the address/offset of hexdump in hex, not decimal.

Addresses my PR bin/41035


(pgoyette)
diff -r1.126 -r1.127 src/sbin/sysctl/sysctl.c

cvs diff -r1.126 -r1.127 src/sbin/sysctl/sysctl.c (switch to unified diff)

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