sysctl.c revision 1.79 1 1.79 atatat /* $NetBSD: sysctl.c,v 1.79 2004/02/19 06:44:18 atatat Exp $ */
2 1.75 atatat
3 1.75 atatat /*-
4 1.75 atatat * Copyright (c) 2003 The NetBSD Foundation, Inc.
5 1.75 atatat * All rights reserved.
6 1.75 atatat *
7 1.75 atatat * This code is derived from software contributed to The NetBSD Foundation
8 1.75 atatat * by Andrew Brown.
9 1.75 atatat *
10 1.75 atatat * Redistribution and use in source and binary forms, with or without
11 1.75 atatat * modification, are permitted provided that the following conditions
12 1.75 atatat * are met:
13 1.75 atatat * 1. Redistributions of source code must retain the above copyright
14 1.75 atatat * notice, this list of conditions and the following disclaimer.
15 1.75 atatat * 2. Redistributions in binary form must reproduce the above copyright
16 1.75 atatat * notice, this list of conditions and the following disclaimer in the
17 1.75 atatat * documentation and/or other materials provided with the distribution.
18 1.75 atatat * 3. Neither the name of The NetBSD Foundation nor the names of its
19 1.75 atatat * contributors may be used to endorse or promote products derived
20 1.75 atatat * from this software without specific prior written permission.
21 1.75 atatat *
22 1.75 atatat * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
23 1.75 atatat * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24 1.75 atatat * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
25 1.75 atatat * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
26 1.75 atatat * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27 1.75 atatat * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28 1.75 atatat * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29 1.75 atatat * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30 1.75 atatat * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31 1.75 atatat * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 1.75 atatat * POSSIBILITY OF SUCH DAMAGE.
33 1.75 atatat */
34 1.9 thorpej
35 1.1 cgd /*
36 1.1 cgd * Copyright (c) 1993
37 1.1 cgd * The Regents of the University of California. All rights reserved.
38 1.1 cgd *
39 1.1 cgd * Redistribution and use in source and binary forms, with or without
40 1.1 cgd * modification, are permitted provided that the following conditions
41 1.1 cgd * are met:
42 1.1 cgd * 1. Redistributions of source code must retain the above copyright
43 1.1 cgd * notice, this list of conditions and the following disclaimer.
44 1.1 cgd * 2. Redistributions in binary form must reproduce the above copyright
45 1.1 cgd * notice, this list of conditions and the following disclaimer in the
46 1.1 cgd * documentation and/or other materials provided with the distribution.
47 1.71 agc * 3. Neither the name of the University nor the names of its contributors
48 1.1 cgd * may be used to endorse or promote products derived from this software
49 1.1 cgd * without specific prior written permission.
50 1.1 cgd *
51 1.1 cgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
52 1.1 cgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
53 1.1 cgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
54 1.1 cgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
55 1.1 cgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
56 1.1 cgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
57 1.1 cgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
58 1.1 cgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
59 1.1 cgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
60 1.1 cgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
61 1.1 cgd * SUCH DAMAGE.
62 1.1 cgd */
63 1.1 cgd
64 1.14 christos #include <sys/cdefs.h>
65 1.1 cgd #ifndef lint
66 1.14 christos __COPYRIGHT(
67 1.1 cgd "@(#) Copyright (c) 1993\n\
68 1.14 christos The Regents of the University of California. All rights reserved.\n");
69 1.1 cgd #endif /* not lint */
70 1.1 cgd
71 1.1 cgd #ifndef lint
72 1.9 thorpej #if 0
73 1.9 thorpej static char sccsid[] = "@(#)sysctl.c 8.1 (Berkeley) 6/6/93";
74 1.9 thorpej #else
75 1.79 atatat __RCSID("$NetBSD: sysctl.c,v 1.79 2004/02/19 06:44:18 atatat Exp $");
76 1.9 thorpej #endif
77 1.1 cgd #endif /* not lint */
78 1.1 cgd
79 1.75 atatat #include <sys/types.h>
80 1.1 cgd #include <sys/param.h>
81 1.1 cgd #include <sys/sysctl.h>
82 1.17 thorpej #include <sys/mount.h>
83 1.22 bouyer #include <sys/resource.h>
84 1.75 atatat #include <sys/stat.h>
85 1.75 atatat #include <sys/sched.h>
86 1.75 atatat #include <sys/socket.h>
87 1.1 cgd #include <netinet/in.h>
88 1.1 cgd #include <netinet/ip_var.h>
89 1.8 thorpej #include <netinet/tcp.h>
90 1.8 thorpej #include <netinet/tcp_timer.h>
91 1.8 thorpej #include <netinet/tcp_var.h>
92 1.24 itojun #include <netinet/icmp6.h>
93 1.75 atatat #include <nfs/rpcv2.h>
94 1.75 atatat #include <nfs/nfsproto.h>
95 1.75 atatat #include <nfs/nfs.h>
96 1.75 atatat #include <machine/cpu.h>
97 1.20 itojun #include <netkey/key_var.h>
98 1.20 itojun
99 1.75 atatat #include <assert.h>
100 1.75 atatat #include <ctype.h>
101 1.14 christos #include <err.h>
102 1.1 cgd #include <errno.h>
103 1.75 atatat #include <inttypes.h>
104 1.75 atatat #include <stdarg.h>
105 1.1 cgd #include <stdio.h>
106 1.1 cgd #include <stdlib.h>
107 1.1 cgd #include <string.h>
108 1.75 atatat #include <time.h>
109 1.15 tron #include <unistd.h>
110 1.1 cgd
111 1.75 atatat /*
112 1.75 atatat * this needs to be able to do the printing and the setting
113 1.75 atatat */
114 1.75 atatat #define HANDLER_PROTO const char *, const char *, char *, \
115 1.75 atatat int *, u_int, const struct sysctlnode *, \
116 1.75 atatat u_int, void *
117 1.75 atatat #define HANDLER_ARGS const char *sname, const char *dname, char *value, \
118 1.75 atatat int *name, u_int namelen, const struct sysctlnode *pnode, \
119 1.75 atatat u_int type, void *v
120 1.75 atatat #define DISPLAY_VALUE 0
121 1.75 atatat #define DISPLAY_OLD 1
122 1.75 atatat #define DISPLAY_NEW 2
123 1.75 atatat
124 1.75 atatat /*
125 1.75 atatat * generic routines
126 1.75 atatat */
127 1.75 atatat static struct handlespec *findprinter(const int *, u_int);
128 1.75 atatat static struct handlespec *findwriter(const int *, u_int);
129 1.75 atatat static void print_tree(int *, u_int, struct sysctlnode *, u_int, int);
130 1.75 atatat static void write_number(int *, u_int, struct sysctlnode *, char *);
131 1.75 atatat static void write_string(int *, u_int, struct sysctlnode *, char *);
132 1.75 atatat static void display_number(const struct sysctlnode *, const char *,
133 1.75 atatat const void *, size_t, int);
134 1.75 atatat static void display_string(const struct sysctlnode *, const char *,
135 1.75 atatat const void *, size_t, int);
136 1.75 atatat static void display_struct(const struct sysctlnode *, const char *,
137 1.75 atatat const void *, size_t, int);
138 1.75 atatat static void hex_dump(const unsigned char *, size_t);
139 1.75 atatat static void usage(void);
140 1.75 atatat static void parse(char *);
141 1.75 atatat static void cparse(char *);
142 1.75 atatat static void dparse(char *);
143 1.75 atatat static void sysctlerror(int);
144 1.56 christos
145 1.75 atatat /*
146 1.75 atatat * unexported from some place else (XXX tbd)
147 1.75 atatat */
148 1.75 atatat int learn_tree(int *, u_int, struct sysctlnode *);
149 1.78 atatat int sysctlbyname(const char *, void *, size_t *, void *, size_t);
150 1.78 atatat int sysctlgetmibinfo(const char *, int *, u_int *,
151 1.78 atatat char *, size_t *, struct sysctlnode **);
152 1.22 bouyer
153 1.75 atatat /*
154 1.75 atatat * "handlers"
155 1.75 atatat */
156 1.75 atatat static void printother(HANDLER_PROTO);
157 1.75 atatat static void kern_clockrate(HANDLER_PROTO);
158 1.75 atatat static void kern_boottime(HANDLER_PROTO);
159 1.75 atatat static void kern_consdev(HANDLER_PROTO);
160 1.75 atatat static void kern_cp_time(HANDLER_PROTO);
161 1.75 atatat static void vm_loadavg(HANDLER_PROTO);
162 1.75 atatat static void proc_limit(HANDLER_PROTO);
163 1.75 atatat #ifdef CPU_DISKINFO
164 1.75 atatat static void machdep_diskinfo(HANDLER_PROTO);
165 1.75 atatat #endif /* CPU_DISKINFO */
166 1.1 cgd
167 1.75 atatat struct handlespec {
168 1.75 atatat int ps_name[CTL_MAXNAME];
169 1.75 atatat void (*ps_p)(HANDLER_PROTO);
170 1.75 atatat void (*ps_w)(HANDLER_PROTO);
171 1.75 atatat void *ps_d;
172 1.75 atatat } handlers[] = {
173 1.75 atatat { { CTL_KERN, KERN_CLOCKRATE }, kern_clockrate },
174 1.75 atatat { { CTL_KERN, KERN_VNODE }, printother, NULL, "pstat" },
175 1.75 atatat { { CTL_KERN, KERN_PROC }, printother, NULL, "ps" },
176 1.75 atatat { { CTL_KERN, KERN_PROC2 }, printother, NULL, "ps" },
177 1.75 atatat { { CTL_KERN, KERN_PROC_ARGS }, printother, NULL, "ps" },
178 1.75 atatat { { CTL_KERN, KERN_FILE }, printother, NULL, "pstat" },
179 1.75 atatat { { CTL_KERN, KERN_NTPTIME }, printother, NULL,
180 1.75 atatat "ntpdc -c kerninfo" },
181 1.75 atatat { { CTL_KERN, KERN_MSGBUF }, printother, NULL, "dmesg" },
182 1.75 atatat { { CTL_KERN, KERN_BOOTTIME }, kern_boottime },
183 1.75 atatat { { CTL_KERN, KERN_CONSDEV }, kern_consdev },
184 1.75 atatat { { CTL_KERN, KERN_CP_TIME }, kern_cp_time },
185 1.75 atatat { { CTL_KERN, KERN_SYSVIPC_INFO }, printother, NULL, "ipcs" },
186 1.75 atatat { { CTL_VM, VM_METER }, printother, NULL,
187 1.75 atatat "vmstat' or 'systat" },
188 1.75 atatat { { CTL_VM, VM_LOADAVG }, vm_loadavg },
189 1.75 atatat { { CTL_VM, VM_UVMEXP }, printother, NULL,
190 1.75 atatat "vmstat' or 'systat" },
191 1.75 atatat { { CTL_VM, VM_UVMEXP2 }, printother, NULL,
192 1.75 atatat "vmstat' or 'systat" },
193 1.75 atatat { { CTL_VFS, 2 /* NFS */, NFS_NFSSTATS },
194 1.75 atatat printother, NULL, "nfsstat" },
195 1.75 atatat { { CTL_NET }, printother, NULL, NULL },
196 1.75 atatat { { CTL_NET, PF_LOCAL }, printother, NULL, NULL },
197 1.75 atatat { { CTL_NET, PF_INET, IPPROTO_TCP, TCPCTL_IDENT },
198 1.75 atatat printother, NULL, "identd" },
199 1.75 atatat { { CTL_NET, PF_INET6, IPPROTO_TCP, TCPCTL_IDENT },
200 1.75 atatat printother, NULL, "identd" },
201 1.75 atatat
202 1.75 atatat { { CTL_NET, PF_INET6, IPPROTO_ICMPV6, ICMPV6CTL_ND6_DRLIST },
203 1.79 atatat printother, NULL, "ndp" },
204 1.75 atatat { { CTL_NET, PF_INET6, IPPROTO_ICMPV6, ICMPV6CTL_ND6_PRLIST },
205 1.79 atatat printother, NULL, "ndp" },
206 1.75 atatat
207 1.75 atatat
208 1.75 atatat { { CTL_NET, PF_KEY, KEYCTL_DUMPSA },
209 1.75 atatat printother, NULL, "setkey" },
210 1.75 atatat { { CTL_NET, PF_KEY, KEYCTL_DUMPSP },
211 1.75 atatat printother, NULL, "setkey" },
212 1.75 atatat /* { { CTL_DEBUG }, printother, NULL, NULL }, */
213 1.75 atatat { { CTL_HW, HW_DISKSTATS }, printother, NULL, "iostat" },
214 1.75 atatat #ifdef CPU_CONSDEV
215 1.75 atatat { { CTL_MACHDEP, CPU_CONSDEV }, kern_consdev },
216 1.75 atatat #endif /* CPU_CONSDEV */
217 1.75 atatat #ifdef CPU_DISKINFO
218 1.75 atatat { { CTL_MACHDEP, CPU_DISKINFO },machdep_diskinfo },
219 1.75 atatat #endif /* CPU_CONSDEV */
220 1.75 atatat { { CTL_DDB }, printother, NULL, NULL },
221 1.75 atatat { { CTL_PROC, -1, PROC_PID_LIMIT, -1, -1 }, proc_limit, proc_limit },
222 1.75 atatat { { CTL_UNSPEC }, },
223 1.1 cgd };
224 1.56 christos
225 1.75 atatat struct sysctlnode my_root = {
226 1.75 atatat #if defined(lint)
227 1.75 atatat 0
228 1.75 atatat #else /* defined(lint) */
229 1.75 atatat .sysctl_flags = SYSCTL_ROOT|
230 1.75 atatat SYSCTL_TYPE(CTLTYPE_NODE),
231 1.75 atatat .sysctl_size = sizeof(struct sysctlnode),
232 1.75 atatat .sysctl_num = 0,
233 1.75 atatat .sysctl_name = "(prog_root)",
234 1.75 atatat #endif /* defined(lint) */
235 1.1 cgd };
236 1.1 cgd
237 1.75 atatat int Aflag, aflag, Mflag, nflag, qflag, rflag, wflag, xflag;
238 1.75 atatat int req;
239 1.65 lukem FILE *warnfp = stderr;
240 1.1 cgd
241 1.1 cgd /*
242 1.75 atatat * vah-riables n stuff
243 1.1 cgd */
244 1.75 atatat char gsname[SYSCTL_NAMELEN * CTL_MAXNAME + CTL_MAXNAME],
245 1.75 atatat gdname[10 * CTL_MAXNAME + CTL_MAXNAME];
246 1.75 atatat char sep[2] = ".", *eq = " = ";
247 1.75 atatat const char *lname[] = {
248 1.75 atatat "top", "second", "third", "fourth", "fifth", "sixth",
249 1.75 atatat "seventh", "eighth", "ninth", "tenth", "eleventh", "twelfth"
250 1.75 atatat };
251 1.1 cgd
252 1.22 bouyer /*
253 1.75 atatat * you've heard of main, haven't you?
254 1.22 bouyer */
255 1.1 cgd int
256 1.53 simonb main(int argc, char *argv[])
257 1.1 cgd {
258 1.27 tsarna char *fn = NULL;
259 1.75 atatat int name[CTL_MAXNAME];
260 1.75 atatat int ch;
261 1.1 cgd
262 1.75 atatat while ((ch = getopt(argc, argv, "Aaef:Mnqrwx")) != -1) {
263 1.1 cgd switch (ch) {
264 1.1 cgd case 'A':
265 1.75 atatat Aflag++;
266 1.1 cgd break;
267 1.1 cgd case 'a':
268 1.75 atatat aflag++;
269 1.1 cgd break;
270 1.72 grant case 'e':
271 1.75 atatat eq = "=";
272 1.72 grant break;
273 1.27 tsarna case 'f':
274 1.27 tsarna fn = optarg;
275 1.75 atatat wflag++;
276 1.75 atatat break;
277 1.75 atatat case 'M':
278 1.75 atatat Mflag++;
279 1.27 tsarna break;
280 1.1 cgd case 'n':
281 1.75 atatat nflag++;
282 1.1 cgd break;
283 1.58 sommerfe case 'q':
284 1.75 atatat qflag++;
285 1.75 atatat break;
286 1.75 atatat case 'r':
287 1.75 atatat rflag++;
288 1.58 sommerfe break;
289 1.1 cgd case 'w':
290 1.75 atatat wflag++;
291 1.75 atatat break;
292 1.75 atatat case 'x':
293 1.75 atatat xflag++;
294 1.1 cgd break;
295 1.1 cgd default:
296 1.1 cgd usage();
297 1.1 cgd }
298 1.1 cgd }
299 1.58 sommerfe
300 1.75 atatat argc -= optind;
301 1.75 atatat argv += optind;
302 1.75 atatat
303 1.58 sommerfe if (qflag && !wflag)
304 1.58 sommerfe usage();
305 1.75 atatat if (xflag && rflag)
306 1.75 atatat usage();
307 1.75 atatat /* if ((xflag || rflag) && wflag)
308 1.75 atatat usage(); */
309 1.75 atatat /* if (aflag && Mflag)
310 1.75 atatat usage(); */
311 1.79 atatat if ((Aflag || Mflag) && argc == 0 && fn == NULL)
312 1.75 atatat aflag = 1;
313 1.58 sommerfe
314 1.75 atatat if (Aflag)
315 1.75 atatat warnfp = stdout;
316 1.75 atatat req = 0;
317 1.1 cgd
318 1.75 atatat if (aflag) {
319 1.75 atatat print_tree(&name[0], 0, NULL, CTLTYPE_NODE, 1);
320 1.75 atatat /* if (argc == 0) */
321 1.75 atatat return (0);
322 1.1 cgd }
323 1.27 tsarna
324 1.27 tsarna if (fn) {
325 1.27 tsarna FILE *fp;
326 1.27 tsarna char *l;
327 1.58 sommerfe
328 1.27 tsarna fp = fopen(fn, "r");
329 1.27 tsarna if (fp == NULL) {
330 1.27 tsarna err(1, "%s", fn);
331 1.27 tsarna } else {
332 1.75 atatat while ((l = fparseln(fp, NULL, NULL, NULL, 0)) != NULL)
333 1.75 atatat {
334 1.75 atatat if (*l) {
335 1.75 atatat parse(l);
336 1.75 atatat free(l);
337 1.75 atatat }
338 1.27 tsarna }
339 1.27 tsarna fclose(fp);
340 1.27 tsarna }
341 1.75 atatat return (0);
342 1.27 tsarna }
343 1.75 atatat
344 1.75 atatat if (argc == 0)
345 1.75 atatat usage();
346 1.75 atatat
347 1.75 atatat while (argc-- > 0)
348 1.75 atatat parse(*argv++);
349 1.75 atatat
350 1.75 atatat return (0);
351 1.1 cgd }
352 1.1 cgd
353 1.1 cgd /*
354 1.75 atatat * ********************************************************************
355 1.75 atatat * how to find someone special to handle the reading (or maybe even
356 1.75 atatat * writing) of a particular node
357 1.75 atatat * ********************************************************************
358 1.1 cgd */
359 1.75 atatat static struct handlespec *
360 1.75 atatat findprinter(const int *name, u_int namelen)
361 1.75 atatat {
362 1.75 atatat struct handlespec *p;
363 1.75 atatat int i, j;
364 1.75 atatat
365 1.75 atatat if (namelen < 1)
366 1.75 atatat return (NULL);
367 1.75 atatat
368 1.75 atatat p = &handlers[0];
369 1.75 atatat for (i = 0; p[i].ps_name[0] != CTL_UNSPEC; i++) {
370 1.75 atatat for (j = 0; j < namelen; j++)
371 1.75 atatat if (p[i].ps_name[j] != name[j] &&
372 1.75 atatat p[i].ps_name[j] != -1)
373 1.75 atatat break;
374 1.75 atatat if (j == namelen && p[i].ps_p != NULL)
375 1.75 atatat return (&p[i]);
376 1.75 atatat }
377 1.75 atatat
378 1.75 atatat return (NULL);
379 1.75 atatat }
380 1.75 atatat
381 1.75 atatat static struct handlespec *
382 1.75 atatat findwriter(const int *name, u_int namelen)
383 1.1 cgd {
384 1.75 atatat struct handlespec *p;
385 1.75 atatat int i, j;
386 1.75 atatat
387 1.75 atatat if (namelen < 1)
388 1.75 atatat return (NULL);
389 1.1 cgd
390 1.75 atatat p = &handlers[0];
391 1.75 atatat for (i = 0; p[i].ps_name[0] != CTL_UNSPEC; i++) {
392 1.75 atatat for (j = 0; j < namelen; j++)
393 1.75 atatat if (p[i].ps_name[j] != name[j] &&
394 1.75 atatat p[i].ps_name[j] != -1)
395 1.75 atatat break;
396 1.75 atatat if (j == namelen && p[i].ps_w != NULL)
397 1.75 atatat return (&p[i]);
398 1.1 cgd }
399 1.75 atatat
400 1.75 atatat return (NULL);
401 1.1 cgd }
402 1.1 cgd
403 1.1 cgd /*
404 1.75 atatat * ********************************************************************
405 1.75 atatat * convert this special number to a special string so we can print the
406 1.75 atatat * mib
407 1.75 atatat * ********************************************************************
408 1.1 cgd */
409 1.75 atatat static const char *
410 1.75 atatat sf(u_int f)
411 1.1 cgd {
412 1.75 atatat static char s[256];
413 1.75 atatat char *c;
414 1.75 atatat
415 1.75 atatat s[0] = '\0';
416 1.75 atatat c = "";
417 1.75 atatat
418 1.75 atatat #define print_flag(_f, _s, _c, _q, _x) \
419 1.75 atatat if ((/*CONSTCOND*/_x) ? \
420 1.75 atatat (((_f) & (_x)) == (__CONCAT(SYSCTL_,_q))) : \
421 1.75 atatat ((_f) & (__CONCAT(SYSCTL_,_q)))) { \
422 1.75 atatat strlcat((_s), (_c), sizeof(_s)); \
423 1.75 atatat strlcat((_s), __STRING(_q), sizeof(_s)); \
424 1.75 atatat (_c) = ","; \
425 1.75 atatat (_f) &= ~(__CONCAT(SYSCTL_,_q)|(_x)); \
426 1.75 atatat }
427 1.75 atatat print_flag(f, s, c, READONLY, SYSCTL_READWRITE);
428 1.75 atatat print_flag(f, s, c, READONLY1, SYSCTL_READWRITE);
429 1.75 atatat print_flag(f, s, c, READONLY2, SYSCTL_READWRITE);
430 1.75 atatat print_flag(f, s, c, READWRITE, SYSCTL_READWRITE);
431 1.75 atatat print_flag(f, s, c, ANYWRITE, 0);
432 1.75 atatat print_flag(f, s, c, PRIVATE, 0);
433 1.75 atatat print_flag(f, s, c, PERMANENT, 0);
434 1.75 atatat print_flag(f, s, c, OWNDATA, 0);
435 1.75 atatat print_flag(f, s, c, IMMEDIATE, 0);
436 1.75 atatat print_flag(f, s, c, HEX, 0);
437 1.75 atatat print_flag(f, s, c, ROOT, 0);
438 1.75 atatat print_flag(f, s, c, ANYNUMBER, 0);
439 1.75 atatat print_flag(f, s, c, HIDDEN, 0);
440 1.75 atatat print_flag(f, s, c, ALIAS, 0);
441 1.75 atatat #undef print_flag
442 1.75 atatat
443 1.75 atatat if (f) {
444 1.75 atatat char foo[9];
445 1.75 atatat snprintf(foo, sizeof(foo), "%x", f);
446 1.75 atatat strlcat(s, c, sizeof(s));
447 1.75 atatat strlcat(s, foo, sizeof(s));
448 1.75 atatat }
449 1.1 cgd
450 1.75 atatat return (s);
451 1.75 atatat }
452 1.72 grant
453 1.75 atatat static const char *
454 1.75 atatat st(u_int t)
455 1.75 atatat {
456 1.1 cgd
457 1.75 atatat switch (t) {
458 1.75 atatat case CTLTYPE_NODE:
459 1.75 atatat return "NODE";
460 1.75 atatat case CTLTYPE_INT:
461 1.75 atatat return "INT";
462 1.75 atatat case CTLTYPE_STRING:
463 1.75 atatat return "STRING";
464 1.75 atatat case CTLTYPE_QUAD:
465 1.75 atatat return "QUAD";
466 1.75 atatat case CTLTYPE_STRUCT:
467 1.75 atatat return "STRUCT";
468 1.75 atatat }
469 1.1 cgd
470 1.75 atatat return "???";
471 1.75 atatat }
472 1.46 chs
473 1.75 atatat /*
474 1.75 atatat * ********************************************************************
475 1.75 atatat * print this node and any others underneath it
476 1.75 atatat * ********************************************************************
477 1.75 atatat */
478 1.75 atatat static void
479 1.75 atatat print_tree(int *name, u_int namelen, struct sysctlnode *pnode, u_int type,
480 1.75 atatat int add)
481 1.75 atatat {
482 1.75 atatat struct sysctlnode *node;
483 1.75 atatat int rc, ni;
484 1.75 atatat size_t sz;
485 1.75 atatat char *sp, *dp, n[20];
486 1.75 atatat struct handlespec *p;
487 1.75 atatat
488 1.75 atatat sp = &gsname[strlen(gsname)];
489 1.75 atatat dp = &gdname[strlen(gdname)];
490 1.75 atatat
491 1.75 atatat if (sp != &gsname[0] && dp == &gdname[0]) {
492 1.75 atatat /*
493 1.75 atatat * aw...shucks. now we must play catch up
494 1.75 atatat */
495 1.75 atatat for (ni = 0; ni < namelen; ni++) {
496 1.75 atatat (void)snprintf(n, sizeof(n), "%d", name[ni]);
497 1.75 atatat if (ni > 0)
498 1.75 atatat strncat(gdname, ".", sizeof(gdname));
499 1.75 atatat strncat(gdname, n, sizeof(gdname));
500 1.1 cgd }
501 1.75 atatat }
502 1.1 cgd
503 1.75 atatat if (pnode == NULL)
504 1.75 atatat pnode = &my_root;
505 1.75 atatat else if (add) {
506 1.75 atatat snprintf(n, sizeof(n), "%d", pnode->sysctl_num);
507 1.75 atatat if (namelen > 1) {
508 1.75 atatat strncat(gsname, sep, sizeof(gsname));
509 1.75 atatat strncat(gdname, ".", sizeof(gdname));
510 1.75 atatat }
511 1.75 atatat strncat(gsname, pnode->sysctl_name, sizeof(gsname));
512 1.75 atatat strncat(gdname, n, sizeof(gdname));
513 1.75 atatat }
514 1.75 atatat
515 1.75 atatat if (Mflag && pnode != &my_root) {
516 1.75 atatat if (nflag)
517 1.75 atatat printf("%s: ", gdname);
518 1.75 atatat else
519 1.75 atatat printf("%s (%s): ", gsname, gdname);
520 1.75 atatat printf("CTLTYPE_%s", st(type));
521 1.75 atatat if (type == CTLTYPE_NODE) {
522 1.75 atatat if (SYSCTL_FLAGS(pnode->sysctl_flags) & SYSCTL_ALIAS)
523 1.75 atatat printf(", alias %d",
524 1.75 atatat pnode->sysctl_alias);
525 1.75 atatat else
526 1.75 atatat printf(", children %d/%d",
527 1.75 atatat pnode->sysctl_clen,
528 1.75 atatat pnode->sysctl_csize);
529 1.75 atatat }
530 1.75 atatat printf(", size %zu", pnode->sysctl_size);
531 1.75 atatat printf(", flags 0x%x<%s>",
532 1.75 atatat SYSCTL_FLAGS(pnode->sysctl_flags),
533 1.75 atatat sf(SYSCTL_FLAGS(pnode->sysctl_flags)));
534 1.75 atatat if (pnode->sysctl_func)
535 1.75 atatat printf(", func=%p", pnode->sysctl_func);
536 1.75 atatat printf(", ver=%d", pnode->sysctl_ver);
537 1.75 atatat printf("\n");
538 1.75 atatat if (type != CTLTYPE_NODE) {
539 1.75 atatat *sp = *dp = '\0';
540 1.1 cgd return;
541 1.1 cgd }
542 1.75 atatat }
543 1.75 atatat
544 1.75 atatat /*
545 1.75 atatat * if this is an alias and we added our name, that means we
546 1.75 atatat * got here by recursing down into the tree, so skip it. The
547 1.75 atatat * only way to print an aliased node is with either -M or by
548 1.75 atatat * name specifically.
549 1.75 atatat */
550 1.75 atatat if (SYSCTL_FLAGS(pnode->sysctl_flags) & SYSCTL_ALIAS && add) {
551 1.75 atatat *sp = *dp = '\0';
552 1.1 cgd return;
553 1.75 atatat }
554 1.1 cgd
555 1.75 atatat p = findprinter(name, namelen);
556 1.75 atatat if (type != CTLTYPE_NODE && p != NULL) {
557 1.75 atatat (*p->ps_p)(gsname, gdname, NULL, name, namelen, pnode, type,
558 1.75 atatat p->ps_d);
559 1.75 atatat *sp = *dp = '\0';
560 1.75 atatat return;
561 1.75 atatat }
562 1.1 cgd
563 1.75 atatat if (type != CTLTYPE_NODE && pnode->sysctl_size == 0) {
564 1.75 atatat rc = sysctl(&name[0], namelen, NULL, &sz, NULL, 0);
565 1.75 atatat if (rc == -1) {
566 1.75 atatat sysctlerror(1);
567 1.75 atatat *sp = *dp = '\0';
568 1.18 thorpej return;
569 1.75 atatat }
570 1.75 atatat if (sz == 0) {
571 1.75 atatat if ((Aflag || req) && !Mflag)
572 1.75 atatat printf("%s: node contains no data\n", gsname);
573 1.75 atatat *sp = *dp = '\0';
574 1.18 thorpej return;
575 1.18 thorpej }
576 1.75 atatat }
577 1.75 atatat else
578 1.75 atatat sz = pnode->sysctl_size;
579 1.17 thorpej
580 1.75 atatat switch (type) {
581 1.75 atatat case CTLTYPE_NODE: {
582 1.75 atatat learn_tree(name, namelen, pnode);
583 1.75 atatat node = pnode->sysctl_child;
584 1.75 atatat if (node == NULL) {
585 1.75 atatat if (p != NULL)
586 1.75 atatat (*p->ps_p)(gsname, gdname, NULL, name, namelen,
587 1.75 atatat pnode, type, p->ps_d);
588 1.75 atatat else if ((Aflag || req) && !Mflag)
589 1.75 atatat printf("%s: no children\n", gsname);
590 1.75 atatat }
591 1.75 atatat else {
592 1.75 atatat req = 0;
593 1.75 atatat for (ni = 0; ni < pnode->sysctl_clen; ni++) {
594 1.75 atatat name[namelen] = node[ni].sysctl_num;
595 1.75 atatat if ((node[ni].sysctl_flags & SYSCTL_HIDDEN) &&
596 1.75 atatat !(Aflag || req))
597 1.75 atatat continue;
598 1.75 atatat print_tree(name, namelen + 1, &node[ni],
599 1.75 atatat SYSCTL_TYPE(node[ni].sysctl_flags),
600 1.75 atatat 1);
601 1.75 atatat }
602 1.75 atatat }
603 1.1 cgd break;
604 1.75 atatat }
605 1.75 atatat case CTLTYPE_INT: {
606 1.75 atatat int i;
607 1.75 atatat rc = sysctl(name, namelen, &i, &sz, NULL, 0);
608 1.75 atatat if (rc == -1) {
609 1.75 atatat sysctlerror(1);
610 1.75 atatat break;
611 1.75 atatat }
612 1.75 atatat display_number(pnode, gsname, &i, sizeof(i), DISPLAY_VALUE);
613 1.22 bouyer break;
614 1.75 atatat }
615 1.75 atatat case CTLTYPE_STRING: {
616 1.75 atatat unsigned char buf[1024], *tbuf;
617 1.75 atatat tbuf = buf;
618 1.75 atatat sz = sizeof(buf);
619 1.75 atatat rc = sysctl(&name[0], namelen, tbuf, &sz, NULL, 0);
620 1.75 atatat if (rc == -1 && errno == ENOMEM) {
621 1.75 atatat tbuf = malloc(sz);
622 1.75 atatat if (tbuf == NULL) {
623 1.75 atatat sysctlerror(1);
624 1.75 atatat break;
625 1.75 atatat }
626 1.75 atatat rc = sysctl(&name[0], namelen, tbuf, &sz, NULL, 0);
627 1.56 christos }
628 1.75 atatat if (rc == -1)
629 1.75 atatat sysctlerror(1);
630 1.75 atatat else
631 1.75 atatat display_string(pnode, gsname, buf, sz, DISPLAY_VALUE);
632 1.75 atatat if (tbuf != buf)
633 1.75 atatat free(tbuf);
634 1.56 christos break;
635 1.1 cgd }
636 1.75 atatat case CTLTYPE_QUAD: {
637 1.75 atatat u_quad_t q;
638 1.75 atatat sz = sizeof(q);
639 1.75 atatat rc = sysctl(&name[0], namelen, &q, &sz, NULL, 0);
640 1.75 atatat if (rc == -1) {
641 1.75 atatat sysctlerror(1);
642 1.75 atatat break;
643 1.75 atatat }
644 1.75 atatat display_number(pnode, gsname, &q, sizeof(q), DISPLAY_VALUE);
645 1.75 atatat break;
646 1.1 cgd }
647 1.75 atatat case CTLTYPE_STRUCT: {
648 1.75 atatat /*
649 1.75 atatat * we shouldn't actually get here, but if we
650 1.75 atatat * do, would it be nice to have *something* to
651 1.75 atatat * do other than completely ignore the
652 1.75 atatat * request.
653 1.75 atatat */
654 1.75 atatat unsigned char *d;
655 1.75 atatat if ((d = malloc(sz)) == NULL) {
656 1.75 atatat fprintf(warnfp, "%s: !malloc failed!\n", gsname);
657 1.1 cgd break;
658 1.75 atatat }
659 1.75 atatat rc = sysctl(&name[0], namelen, d, &sz, NULL, 0);
660 1.75 atatat if (rc == -1) {
661 1.75 atatat sysctlerror(1);
662 1.1 cgd break;
663 1.1 cgd }
664 1.75 atatat display_struct(pnode, gsname, d, sz, DISPLAY_VALUE);
665 1.75 atatat free(d);
666 1.75 atatat break;
667 1.1 cgd }
668 1.75 atatat default:
669 1.75 atatat /* should i print an error here? */
670 1.75 atatat break;
671 1.75 atatat }
672 1.75 atatat
673 1.75 atatat *sp = *dp = '\0';
674 1.75 atatat }
675 1.75 atatat
676 1.75 atatat /*
677 1.75 atatat * ********************************************************************
678 1.75 atatat * parse a request, possibly determining that it's a create or destroy
679 1.75 atatat * request
680 1.75 atatat * ********************************************************************
681 1.75 atatat */
682 1.75 atatat static void
683 1.75 atatat parse(char *l)
684 1.75 atatat {
685 1.75 atatat struct sysctlnode *node;
686 1.75 atatat struct handlespec *w;
687 1.75 atatat int name[CTL_MAXNAME];
688 1.75 atatat u_int namelen, type;
689 1.75 atatat char *key, *value, *dot;
690 1.75 atatat size_t sz;
691 1.75 atatat
692 1.75 atatat req = 1;
693 1.75 atatat key = l;
694 1.75 atatat value = strchr(l, '=');
695 1.75 atatat if (value != NULL) {
696 1.75 atatat if (!wflag) {
697 1.65 lukem fprintf(warnfp,
698 1.75 atatat "%s: Must specify -w to set variables\n",
699 1.75 atatat getprogname());
700 1.75 atatat exit(1);
701 1.1 cgd }
702 1.75 atatat *value++ = '\0';
703 1.1 cgd }
704 1.1 cgd
705 1.75 atatat if ((dot = strpbrk(key, "./")) == NULL)
706 1.75 atatat sep[0] = '.';
707 1.75 atatat else
708 1.75 atatat sep[0] = dot[0];
709 1.75 atatat sep[1] = '\0';
710 1.1 cgd
711 1.75 atatat if (key[0] == sep[0] && key[1] == sep[0]) {
712 1.75 atatat if (value != NULL)
713 1.75 atatat value[-1] = '=';
714 1.75 atatat if (strncmp(key + 2, "create=", 7) == 0)
715 1.75 atatat cparse(key + 9);
716 1.75 atatat else if (strncmp(key + 2, "destroy=", 8) == 0)
717 1.75 atatat dparse(key + 10);
718 1.1 cgd else
719 1.75 atatat fprintf(warnfp, "%s: unable to parse '%s'\n",
720 1.75 atatat getprogname(), key);
721 1.32 simonb return;
722 1.32 simonb }
723 1.32 simonb
724 1.75 atatat node = &my_root;
725 1.75 atatat namelen = CTL_MAXNAME;
726 1.75 atatat sz = sizeof(gsname);
727 1.75 atatat
728 1.78 atatat if (sysctlgetmibinfo(key, &name[0], &namelen, gsname, &sz, &node) == -1)
729 1.75 atatat {
730 1.75 atatat fprintf(warnfp, "%s: %s level name '%s' in '%s' is invalid\n",
731 1.75 atatat getprogname(), lname[namelen], gsname, l);
732 1.75 atatat exit(1);
733 1.75 atatat }
734 1.75 atatat
735 1.75 atatat type = SYSCTL_TYPE(node->sysctl_flags);
736 1.75 atatat
737 1.75 atatat if (value == NULL) {
738 1.75 atatat print_tree(&name[0], namelen, node, type, 0);
739 1.75 atatat gsname[0] = '\0';
740 1.69 dsl return;
741 1.69 dsl }
742 1.69 dsl
743 1.75 atatat if (type != CTLTYPE_NODE && (w = findwriter(name, namelen)) != NULL) {
744 1.75 atatat (*w->ps_w)(gsname, gdname, value, name, namelen, node, type,
745 1.75 atatat w->ps_d);
746 1.75 atatat gsname[0] = '\0';
747 1.26 fvdl return;
748 1.26 fvdl }
749 1.58 sommerfe
750 1.1 cgd switch (type) {
751 1.75 atatat case CTLTYPE_NODE:
752 1.75 atatat /*
753 1.75 atatat * XXX old behavior is to print. should we error instead?
754 1.75 atatat */
755 1.75 atatat print_tree(&name[0], namelen, node, CTLTYPE_NODE, 1);
756 1.75 atatat break;
757 1.1 cgd case CTLTYPE_INT:
758 1.75 atatat write_number(&name[0], namelen, node, value);
759 1.75 atatat break;
760 1.1 cgd case CTLTYPE_STRING:
761 1.75 atatat write_string(&name[0], namelen, node, value);
762 1.75 atatat break;
763 1.75 atatat case CTLTYPE_QUAD:
764 1.75 atatat write_number(&name[0], namelen, node, value);
765 1.75 atatat break;
766 1.75 atatat case CTLTYPE_STRUCT:
767 1.75 atatat /*
768 1.75 atatat * XXX old behavior is to print. should we error instead?
769 1.75 atatat */
770 1.75 atatat /* fprintf(warnfp, "you can't write to %s\n", gsname); */
771 1.75 atatat print_tree(&name[0], namelen, node, type, 0);
772 1.75 atatat break;
773 1.75 atatat }
774 1.75 atatat }
775 1.75 atatat
776 1.75 atatat /*
777 1.75 atatat
778 1.75 atatat //create=foo.bar.whatever...,
779 1.75 atatat [type=(int|quad|string|struct|node),]
780 1.75 atatat [size=###,]
781 1.75 atatat [n=###,]
782 1.75 atatat [flags=(tiohxparw12),]
783 1.75 atatat [addr=0x####,|symbol=...|value=...]
784 1.75 atatat
785 1.75 atatat size is optional for some types. type must be set before anything
786 1.75 atatat else. nodes can have [r12whp], but nothing else applies. if no
787 1.75 atatat size or type is given, node is asserted. writeable is the default,
788 1.75 atatat with [r12w] being read-only, writeable below securelevel 1,
789 1.75 atatat writeable below securelevel 2, and unconditionally writeable
790 1.75 atatat respectively. if you specify addr, it is assumed to be the name of
791 1.75 atatat a kernel symbol, if value, SYSCTL_OWNDATA will be asserted for
792 1.75 atatat strings, SYSCTL_IMMEDIATE for ints and u_quad_ts. you cannot
793 1.75 atatat specify both value and addr.
794 1.75 atatat
795 1.75 atatat */
796 1.75 atatat
797 1.75 atatat static void
798 1.75 atatat cparse(char *l)
799 1.75 atatat {
800 1.75 atatat struct sysctlnode node;
801 1.75 atatat size_t sz;
802 1.75 atatat char *nname, *key, *value, *data, *addr, *c, *t;
803 1.75 atatat int name[CTL_MAXNAME], i, rc, method, flags, rw;
804 1.75 atatat u_int namelen, type;
805 1.75 atatat u_quad_t q;
806 1.75 atatat long li, lo;
807 1.75 atatat
808 1.75 atatat /*
809 1.75 atatat * these are the pieces that make up the description of a new
810 1.75 atatat * node
811 1.75 atatat */
812 1.75 atatat memset(&node, 0, sizeof(node));
813 1.75 atatat node.sysctl_num = CTL_CREATE; /* any number is fine */
814 1.75 atatat flags = 0;
815 1.75 atatat rw = -1;
816 1.75 atatat type = 0;
817 1.75 atatat sz = 0;
818 1.75 atatat data = addr = NULL;
819 1.75 atatat memset(name, 0, sizeof(name));
820 1.75 atatat namelen = 0;
821 1.75 atatat method = 0;
822 1.75 atatat
823 1.75 atatat /*
824 1.75 atatat * misc stuff used when constructing
825 1.75 atatat */
826 1.75 atatat i = 0;
827 1.75 atatat q = 0;
828 1.75 atatat key = NULL;
829 1.75 atatat value = NULL;
830 1.75 atatat
831 1.75 atatat /*
832 1.75 atatat * the name of the thing we're trying to create is first, so
833 1.75 atatat * pick it off.
834 1.75 atatat */
835 1.75 atatat nname = l;
836 1.75 atatat if ((c = strchr(nname, ',')) != NULL)
837 1.75 atatat *c++ = '\0';
838 1.75 atatat
839 1.75 atatat while (c != NULL) {
840 1.75 atatat
841 1.75 atatat /*
842 1.75 atatat * pull off the next "key=value" pair
843 1.75 atatat */
844 1.75 atatat key = c;
845 1.75 atatat if ((t = strchr(key, '=')) != NULL) {
846 1.75 atatat *t++ = '\0';
847 1.75 atatat value = t;
848 1.75 atatat }
849 1.75 atatat else
850 1.75 atatat value = NULL;
851 1.75 atatat
852 1.75 atatat /*
853 1.75 atatat * if the "key" is "value", then that eats the rest of
854 1.75 atatat * the string, so we're done, otherwise bite it off at
855 1.75 atatat * the next comma.
856 1.75 atatat */
857 1.75 atatat if (strcmp(key, "value") == 0) {
858 1.75 atatat c = NULL;
859 1.75 atatat data = value;
860 1.75 atatat break;
861 1.75 atatat }
862 1.75 atatat else {
863 1.75 atatat if ((c = strchr(value, ',')) != NULL)
864 1.75 atatat *c++ = '\0';
865 1.75 atatat }
866 1.75 atatat
867 1.75 atatat /*
868 1.75 atatat * note that we (mostly) let the invoker of sysctl(8)
869 1.75 atatat * play rampant here and depend on the kernel to tell
870 1.75 atatat * them that they were wrong. well...within reason.
871 1.75 atatat * we later check the various parameters against each
872 1.75 atatat * other to make sure it makes some sort of sense.
873 1.75 atatat */
874 1.75 atatat if (strcmp(key, "addr") == 0) {
875 1.75 atatat /*
876 1.75 atatat * we can't check these two. only the kernel
877 1.75 atatat * can tell us when it fails to find the name
878 1.75 atatat * (or if the address is invalid).
879 1.75 atatat */
880 1.75 atatat if (method != 0) {
881 1.75 atatat fprintf(warnfp,
882 1.75 atatat "%s: %s: already have %s for new node\n",
883 1.75 atatat getprogname(), nname,
884 1.75 atatat method == CTL_CREATE ? "addr" : "symbol");
885 1.75 atatat exit(1);
886 1.75 atatat }
887 1.75 atatat errno = 0;
888 1.75 atatat addr = (void*)strtoul(value, &t, 0);
889 1.75 atatat if (*t != '\0' || errno != 0) {
890 1.75 atatat fprintf(warnfp,
891 1.75 atatat "%s: %s: '%s' is not a valid address\n",
892 1.75 atatat getprogname(), nname, value);
893 1.75 atatat exit(1);
894 1.75 atatat }
895 1.75 atatat method = CTL_CREATE;
896 1.75 atatat }
897 1.75 atatat else if (strcmp(key, "symbol") == 0) {
898 1.75 atatat if (method != 0) {
899 1.75 atatat fprintf(warnfp,
900 1.75 atatat "%s: %s: already have %s for new node\n",
901 1.75 atatat getprogname(), nname,
902 1.75 atatat method == CTL_CREATE ? "addr" : "symbol");
903 1.75 atatat exit(1);
904 1.75 atatat }
905 1.75 atatat addr = value;
906 1.75 atatat method = CTL_CREATESYM;
907 1.75 atatat }
908 1.75 atatat else if (strcmp(key, "type") == 0) {
909 1.75 atatat if (strcmp(value, "node") == 0)
910 1.75 atatat type = CTLTYPE_NODE;
911 1.75 atatat else if (strcmp(value, "int") == 0) {
912 1.75 atatat sz = sizeof(int);
913 1.75 atatat type = CTLTYPE_INT;
914 1.75 atatat }
915 1.75 atatat else if (strcmp(value, "string") == 0)
916 1.75 atatat type = CTLTYPE_STRING;
917 1.75 atatat else if (strcmp(value, "quad") == 0) {
918 1.75 atatat sz = sizeof(u_quad_t);
919 1.75 atatat type = CTLTYPE_QUAD;
920 1.75 atatat }
921 1.75 atatat else if (strcmp(value, "struct") == 0)
922 1.75 atatat type = CTLTYPE_STRUCT;
923 1.75 atatat else {
924 1.75 atatat fprintf(warnfp,
925 1.75 atatat "%s: %s: '%s' is not a valid type\n",
926 1.75 atatat getprogname(), nname, value);
927 1.75 atatat exit(1);
928 1.75 atatat }
929 1.75 atatat }
930 1.75 atatat else if (strcmp(key, "size") == 0) {
931 1.75 atatat errno = 0;
932 1.75 atatat /*
933 1.75 atatat * yes, i know size_t is not an unsigned long,
934 1.75 atatat * but we can all agree that it ought to be,
935 1.75 atatat * right?
936 1.75 atatat */
937 1.75 atatat sz = strtoul(value, &t, 0);
938 1.75 atatat if (*t != '\0' || errno != 0) {
939 1.75 atatat fprintf(warnfp,
940 1.75 atatat "%s: %s: '%s' is not a valid size\n",
941 1.75 atatat getprogname(), nname, value);
942 1.75 atatat exit(1);
943 1.75 atatat }
944 1.75 atatat }
945 1.75 atatat else if (strcmp(key, "n") == 0) {
946 1.75 atatat errno = 0;
947 1.75 atatat li = strtol(value, &t, 0);
948 1.75 atatat node.sysctl_num = li;
949 1.75 atatat lo = node.sysctl_num;
950 1.75 atatat if (*t != '\0' || errno != 0 || li != lo || lo < 0) {
951 1.75 atatat fprintf(warnfp,
952 1.75 atatat "%s: %s: '%s' is not a valid mib number\n",
953 1.75 atatat getprogname(), nname, value);
954 1.75 atatat exit(1);
955 1.75 atatat }
956 1.75 atatat }
957 1.75 atatat else if (strcmp(key, "flags") == 0) {
958 1.75 atatat t = value;
959 1.75 atatat while (*t != '\0') {
960 1.75 atatat switch (*t) {
961 1.75 atatat case 'a':
962 1.75 atatat flags |= SYSCTL_ANYWRITE;
963 1.75 atatat break;
964 1.75 atatat case 'h':
965 1.75 atatat flags |= SYSCTL_HIDDEN;
966 1.75 atatat break;
967 1.75 atatat case 'i':
968 1.75 atatat flags |= SYSCTL_IMMEDIATE;
969 1.75 atatat break;
970 1.75 atatat case 'o':
971 1.75 atatat flags |= SYSCTL_OWNDATA;
972 1.75 atatat break;
973 1.75 atatat case 'p':
974 1.75 atatat flags |= SYSCTL_PRIVATE;
975 1.75 atatat break;
976 1.75 atatat case 'x':
977 1.75 atatat flags |= SYSCTL_HEX;
978 1.75 atatat break;
979 1.75 atatat
980 1.75 atatat case 'r':
981 1.75 atatat rw = SYSCTL_READONLY;
982 1.75 atatat break;
983 1.75 atatat case '1':
984 1.75 atatat rw = SYSCTL_READONLY1;
985 1.75 atatat break;
986 1.75 atatat case '2':
987 1.75 atatat rw = SYSCTL_READONLY2;
988 1.75 atatat break;
989 1.75 atatat case 'w':
990 1.75 atatat rw = SYSCTL_READWRITE;
991 1.75 atatat break;
992 1.75 atatat default:
993 1.75 atatat fprintf(warnfp,
994 1.75 atatat "%s: %s: '%c' is not a valid flag\n",
995 1.75 atatat getprogname(), nname, *t);
996 1.75 atatat exit(1);
997 1.75 atatat }
998 1.75 atatat t++;
999 1.75 atatat }
1000 1.75 atatat }
1001 1.75 atatat else {
1002 1.75 atatat fprintf(warnfp, "%s: %s: unrecognized keyword '%s'\n",
1003 1.75 atatat getprogname(), nname, key);
1004 1.75 atatat exit(1);
1005 1.75 atatat }
1006 1.75 atatat }
1007 1.75 atatat
1008 1.75 atatat /*
1009 1.75 atatat * now that we've finished parsing the given string, fill in
1010 1.75 atatat * anything they didn't specify
1011 1.75 atatat */
1012 1.75 atatat if (type == 0)
1013 1.75 atatat type = CTLTYPE_NODE;
1014 1.75 atatat
1015 1.75 atatat /*
1016 1.75 atatat * the "data" can be interpreted various ways depending on the
1017 1.75 atatat * type of node we're creating, as can the size
1018 1.75 atatat */
1019 1.75 atatat if (data != NULL) {
1020 1.75 atatat if (addr != NULL) {
1021 1.75 atatat fprintf(warnfp,
1022 1.75 atatat "%s: %s: cannot specify both value and "
1023 1.75 atatat "address\n", getprogname(), nname);
1024 1.75 atatat exit(1);
1025 1.75 atatat }
1026 1.75 atatat
1027 1.75 atatat switch (type) {
1028 1.75 atatat case CTLTYPE_INT:
1029 1.75 atatat errno = 0;
1030 1.75 atatat li = strtol(data, &t, 0);
1031 1.75 atatat i = li;
1032 1.75 atatat lo = i;
1033 1.75 atatat if (*t != '\0' || errno != 0 || li != lo || lo < 0) {
1034 1.75 atatat fprintf(warnfp,
1035 1.75 atatat "%s: %s: '%s' is not a valid integer\n",
1036 1.75 atatat getprogname(), nname, value);
1037 1.75 atatat exit(1);
1038 1.75 atatat }
1039 1.75 atatat if (!(flags & SYSCTL_OWNDATA)) {
1040 1.75 atatat flags |= SYSCTL_IMMEDIATE;
1041 1.75 atatat node.sysctl_idata = i;
1042 1.75 atatat }
1043 1.75 atatat else
1044 1.75 atatat node.sysctl_data = &i;
1045 1.75 atatat if (sz == 0)
1046 1.75 atatat sz = sizeof(int);
1047 1.75 atatat break;
1048 1.75 atatat case CTLTYPE_STRING:
1049 1.75 atatat flags |= SYSCTL_OWNDATA;
1050 1.75 atatat node.sysctl_data = data;
1051 1.75 atatat if (sz == 0)
1052 1.75 atatat sz = strlen(data) + 1;
1053 1.75 atatat else if (sz < strlen(data) + 1) {
1054 1.75 atatat fprintf(warnfp, "%s: %s: ignoring size=%zu for "
1055 1.75 atatat "string node, too small for given "
1056 1.75 atatat "value\n", getprogname(), nname, sz);
1057 1.75 atatat sz = strlen(data) + 1;
1058 1.75 atatat }
1059 1.75 atatat break;
1060 1.75 atatat case CTLTYPE_QUAD:
1061 1.75 atatat errno = 0;
1062 1.75 atatat q = strtouq(data, &t, 0);
1063 1.75 atatat if (*t != '\0' || errno != 0) {
1064 1.75 atatat fprintf(warnfp,
1065 1.75 atatat "%s: %s: '%s' is not a valid quad\n",
1066 1.75 atatat getprogname(), nname, value);
1067 1.75 atatat exit(1);
1068 1.75 atatat }
1069 1.75 atatat if (!(flags & SYSCTL_OWNDATA)) {
1070 1.75 atatat flags |= SYSCTL_IMMEDIATE;
1071 1.75 atatat node.sysctl_qdata = q;
1072 1.75 atatat }
1073 1.75 atatat else
1074 1.75 atatat node.sysctl_data = &q;
1075 1.75 atatat if (sz == 0)
1076 1.75 atatat sz = sizeof(u_quad_t);
1077 1.75 atatat break;
1078 1.75 atatat case CTLTYPE_STRUCT:
1079 1.75 atatat fprintf(warnfp,
1080 1.75 atatat "%s: %s: struct not initializable\n",
1081 1.75 atatat getprogname(), nname);
1082 1.75 atatat exit(1);
1083 1.75 atatat }
1084 1.75 atatat
1085 1.75 atatat /*
1086 1.75 atatat * these methods have all provided local starting
1087 1.75 atatat * values that the kernel must copy in
1088 1.75 atatat */
1089 1.75 atatat }
1090 1.75 atatat
1091 1.75 atatat /*
1092 1.75 atatat * hmm...no data, but we have an address of data. that's
1093 1.75 atatat * fine.
1094 1.75 atatat */
1095 1.75 atatat else if (addr != 0)
1096 1.75 atatat node.sysctl_data = (void*)addr;
1097 1.75 atatat
1098 1.75 atatat /*
1099 1.75 atatat * no data and no address? well...okay. we might be able to
1100 1.75 atatat * manage that.
1101 1.75 atatat */
1102 1.75 atatat else if (type != CTLTYPE_NODE) {
1103 1.75 atatat if (sz == 0) {
1104 1.75 atatat fprintf(warnfp,
1105 1.75 atatat "%s: %s: need a size or a starting value\n",
1106 1.75 atatat getprogname(), nname);
1107 1.75 atatat exit(1);
1108 1.75 atatat }
1109 1.75 atatat if (!(flags & SYSCTL_IMMEDIATE))
1110 1.75 atatat flags |= SYSCTL_OWNDATA;
1111 1.75 atatat }
1112 1.75 atatat
1113 1.75 atatat /*
1114 1.75 atatat * now we do a few sanity checks on the description we've
1115 1.75 atatat * assembled
1116 1.75 atatat */
1117 1.75 atatat if ((flags & SYSCTL_IMMEDIATE) &&
1118 1.75 atatat (type == CTLTYPE_STRING || type == CTLTYPE_STRUCT)) {
1119 1.75 atatat fprintf(warnfp,
1120 1.75 atatat "%s: %s: cannot make an immediate %s\n",
1121 1.75 atatat getprogname(), nname,
1122 1.75 atatat (type == CTLTYPE_STRING) ? "string" : "struct");
1123 1.75 atatat exit(1);
1124 1.75 atatat }
1125 1.75 atatat if (type == CTLTYPE_NODE && node.sysctl_data != NULL) {
1126 1.75 atatat fprintf(warnfp, "%s: %s: nodes do not have data\n",
1127 1.75 atatat getprogname(), nname);
1128 1.75 atatat exit(1);
1129 1.75 atatat }
1130 1.75 atatat
1131 1.75 atatat /*
1132 1.75 atatat * some types must have a particular size
1133 1.75 atatat */
1134 1.75 atatat if (sz != 0) {
1135 1.75 atatat if ((type == CTLTYPE_INT && sz != sizeof(int)) ||
1136 1.75 atatat (type == CTLTYPE_QUAD && sz != sizeof(u_quad_t)) ||
1137 1.75 atatat (type == CTLTYPE_NODE && sz != 0)) {
1138 1.75 atatat fprintf(warnfp, "%s: %s: wrong size for type\n",
1139 1.75 atatat getprogname(), nname);
1140 1.75 atatat exit(1);
1141 1.75 atatat }
1142 1.75 atatat }
1143 1.75 atatat else if (type == CTLTYPE_STRUCT) {
1144 1.75 atatat fprintf(warnfp, "%s: %s: struct must have size\n",
1145 1.75 atatat getprogname(), nname);
1146 1.75 atatat exit(1);
1147 1.75 atatat }
1148 1.75 atatat
1149 1.75 atatat /*
1150 1.75 atatat * now...if no one said anything yet, we default nodes or
1151 1.75 atatat * any type that owns data being writeable, and everything
1152 1.75 atatat * else being readonly.
1153 1.75 atatat */
1154 1.75 atatat if (rw == -1) {
1155 1.75 atatat if (type == CTLTYPE_NODE ||
1156 1.75 atatat (flags & (SYSCTL_OWNDATA|SYSCTL_IMMEDIATE)))
1157 1.75 atatat rw = SYSCTL_READWRITE;
1158 1.75 atatat else
1159 1.75 atatat rw = SYSCTL_READONLY;
1160 1.75 atatat }
1161 1.75 atatat
1162 1.75 atatat /*
1163 1.75 atatat * if a kernel address was specified, that can't be made
1164 1.75 atatat * writeable by us.
1165 1.75 atatat if (rw != SYSCTL_READONLY && addr) {
1166 1.75 atatat fprintf(warnfp, "%s: %s: kernel data can only be readable\n",
1167 1.75 atatat getprogname(), nname);
1168 1.75 atatat exit(1);
1169 1.75 atatat }
1170 1.75 atatat */
1171 1.75 atatat
1172 1.75 atatat /*
1173 1.75 atatat * what separator were they using in the full name of the new
1174 1.75 atatat * node?
1175 1.75 atatat */
1176 1.75 atatat if ((t = strpbrk(nname, "./")) == NULL)
1177 1.75 atatat sep[0] = '.';
1178 1.75 atatat else
1179 1.75 atatat sep[0] = t[0];
1180 1.75 atatat sep[1] = '\0';
1181 1.75 atatat
1182 1.75 atatat /*
1183 1.75 atatat * put it all together, now. t'ain't much, is it?
1184 1.75 atatat */
1185 1.75 atatat node.sysctl_flags = flags|rw|type;
1186 1.75 atatat node.sysctl_size = sz;
1187 1.75 atatat t = strrchr(nname, sep[0]);
1188 1.75 atatat if (t != NULL)
1189 1.75 atatat strlcpy(node.sysctl_name, t + 1, sizeof(node.sysctl_name));
1190 1.75 atatat else
1191 1.75 atatat strlcpy(node.sysctl_name, nname, sizeof(node.sysctl_name));
1192 1.75 atatat
1193 1.75 atatat /*
1194 1.75 atatat * if this is a new top-level node, then we don't need to find
1195 1.75 atatat * the mib for its parent
1196 1.75 atatat */
1197 1.75 atatat if (t == NULL) {
1198 1.75 atatat namelen = 0;
1199 1.75 atatat gsname[0] = '\0';
1200 1.75 atatat }
1201 1.75 atatat
1202 1.75 atatat /*
1203 1.75 atatat * on the other hand, if it's not a top-level node...
1204 1.75 atatat */
1205 1.75 atatat else {
1206 1.75 atatat namelen = sizeof(name) / sizeof(name[0]);
1207 1.75 atatat sz = sizeof(gsname);
1208 1.75 atatat *t = '\0';
1209 1.78 atatat rc = sysctlgetmibinfo(nname, &name[0], &namelen,
1210 1.78 atatat gsname, &sz, NULL);
1211 1.75 atatat *t = sep[0];
1212 1.75 atatat if (rc == -1) {
1213 1.75 atatat fprintf(warnfp,
1214 1.75 atatat "%s: %s level name '%s' in '%s' is invalid\n",
1215 1.75 atatat getprogname(), lname[namelen], gsname, nname);
1216 1.75 atatat exit(1);
1217 1.1 cgd }
1218 1.75 atatat }
1219 1.75 atatat
1220 1.75 atatat /*
1221 1.75 atatat * yes, a new node is being created
1222 1.75 atatat */
1223 1.75 atatat if (method != 0)
1224 1.75 atatat name[namelen++] = method;
1225 1.75 atatat else
1226 1.75 atatat name[namelen++] = CTL_CREATE;
1227 1.75 atatat
1228 1.75 atatat sz = sizeof(node);
1229 1.75 atatat rc = sysctl(&name[0], namelen, &node, &sz, &node, sizeof(node));
1230 1.75 atatat
1231 1.75 atatat if (rc == -1) {
1232 1.75 atatat fprintf(warnfp,
1233 1.75 atatat "%s: %s: CTL_CREATE failed: %s\n",
1234 1.75 atatat getprogname(), nname, strerror(errno));
1235 1.75 atatat exit(1);
1236 1.75 atatat }
1237 1.75 atatat else if (!qflag && !nflag)
1238 1.75 atatat printf("%s(%s): (created)\n", nname, st(type));
1239 1.75 atatat }
1240 1.75 atatat
1241 1.75 atatat static void
1242 1.75 atatat dparse(char *l)
1243 1.75 atatat {
1244 1.75 atatat struct sysctlnode node;
1245 1.75 atatat size_t sz;
1246 1.75 atatat int name[CTL_MAXNAME], rc;
1247 1.75 atatat u_int namelen;
1248 1.75 atatat
1249 1.75 atatat memset(name, 0, sizeof(name));
1250 1.75 atatat namelen = sizeof(name) / sizeof(name[0]);
1251 1.75 atatat sz = sizeof(gsname);
1252 1.78 atatat rc = sysctlgetmibinfo(l, &name[0], &namelen, gsname, &sz, NULL);
1253 1.75 atatat if (rc == -1) {
1254 1.75 atatat fprintf(warnfp,
1255 1.75 atatat "%s: %s level name '%s' in '%s' is invalid\n",
1256 1.75 atatat getprogname(), lname[namelen], gsname, l);
1257 1.75 atatat exit(1);
1258 1.75 atatat }
1259 1.75 atatat
1260 1.75 atatat memset(&node, 0, sizeof(node));
1261 1.75 atatat node.sysctl_num = name[namelen - 1];
1262 1.75 atatat name[namelen - 1] = CTL_DESTROY;
1263 1.75 atatat
1264 1.75 atatat sz = sizeof(node);
1265 1.75 atatat rc = sysctl(&name[0], namelen, &node, &sz, &node, sizeof(node));
1266 1.75 atatat
1267 1.75 atatat if (rc == -1) {
1268 1.75 atatat fprintf(warnfp,
1269 1.75 atatat "%s: %s: CTL_DESTROY failed: %s\n",
1270 1.75 atatat getprogname(), l, strerror(errno));
1271 1.75 atatat exit(1);
1272 1.75 atatat }
1273 1.75 atatat else if (!qflag && !nflag)
1274 1.75 atatat printf("%s(%s): (destroyed)\n", gsname,
1275 1.75 atatat st(SYSCTL_TYPE(node.sysctl_flags)));
1276 1.75 atatat }
1277 1.75 atatat
1278 1.75 atatat /*
1279 1.75 atatat * ********************************************************************
1280 1.75 atatat * when things go wrong...
1281 1.75 atatat * ********************************************************************
1282 1.75 atatat */
1283 1.75 atatat static void
1284 1.75 atatat usage(void)
1285 1.75 atatat {
1286 1.75 atatat const char *progname = getprogname();
1287 1.1 cgd
1288 1.75 atatat (void)fprintf(stderr,
1289 1.77 jmmv "usage:\t%s %s\n"
1290 1.75 atatat "\t%s %s\n"
1291 1.75 atatat "\t%s %s\n"
1292 1.75 atatat "\t%s %s\n"
1293 1.75 atatat "\t%s %s\n"
1294 1.75 atatat "\t%s %s\n",
1295 1.75 atatat progname, "[-ne] [-x[x]|-r] variable ...",
1296 1.75 atatat progname, "[-ne] [-q] -w variable=value ...",
1297 1.75 atatat progname, "[-ne] -a",
1298 1.75 atatat progname, "[-ne] -A",
1299 1.75 atatat progname, "[-ne] -M",
1300 1.75 atatat progname, "[-ne] [-q] -f file");
1301 1.75 atatat exit(1);
1302 1.22 bouyer }
1303 1.22 bouyer
1304 1.75 atatat void
1305 1.75 atatat sysctlerror(int soft)
1306 1.75 atatat {
1307 1.75 atatat if (soft) {
1308 1.75 atatat switch (errno) {
1309 1.75 atatat case ENOENT:
1310 1.75 atatat case ENOPROTOOPT:
1311 1.75 atatat case ENOTDIR:
1312 1.75 atatat case EOPNOTSUPP:
1313 1.75 atatat case EPROTONOSUPPORT:
1314 1.75 atatat if (Aflag || req)
1315 1.75 atatat fprintf(warnfp,
1316 1.75 atatat "%s: the value is not available\n",
1317 1.75 atatat gsname);
1318 1.75 atatat return;
1319 1.22 bouyer }
1320 1.75 atatat }
1321 1.75 atatat
1322 1.75 atatat fprintf(warnfp, "%s: sysctl() failed with %s\n",
1323 1.75 atatat gsname, strerror(errno));
1324 1.75 atatat if (!soft)
1325 1.75 atatat exit(1);
1326 1.75 atatat }
1327 1.75 atatat
1328 1.75 atatat /*
1329 1.75 atatat * ********************************************************************
1330 1.75 atatat * how to write to a "simple" node
1331 1.75 atatat * ********************************************************************
1332 1.75 atatat */
1333 1.75 atatat static void
1334 1.75 atatat write_number(int *name, u_int namelen, struct sysctlnode *node, char *value)
1335 1.75 atatat {
1336 1.75 atatat int ii, io;
1337 1.75 atatat u_quad_t qi, qo;
1338 1.75 atatat size_t si, so;
1339 1.75 atatat int rc;
1340 1.75 atatat void *i, *o;
1341 1.75 atatat char *t;
1342 1.75 atatat
1343 1.75 atatat si = so = 0;
1344 1.75 atatat i = o = NULL;
1345 1.75 atatat errno = 0;
1346 1.75 atatat qi = strtouq(value, &t, 0);
1347 1.75 atatat if (errno != 0) {
1348 1.75 atatat fprintf(warnfp, "%s: value too large\n", value);
1349 1.75 atatat exit(1);
1350 1.75 atatat }
1351 1.75 atatat if (*t != '\0') {
1352 1.75 atatat fprintf(warnfp, "%s: not a number\n", value);
1353 1.75 atatat exit(1);
1354 1.75 atatat }
1355 1.75 atatat
1356 1.75 atatat switch (SYSCTL_TYPE(node->sysctl_flags)) {
1357 1.75 atatat case CTLTYPE_INT:
1358 1.75 atatat ii = (int)qi;
1359 1.75 atatat qo = ii;
1360 1.75 atatat if (qo != qi) {
1361 1.75 atatat fprintf(warnfp, "%s: value too large\n", value);
1362 1.75 atatat exit(1);
1363 1.75 atatat }
1364 1.75 atatat o = &io;
1365 1.75 atatat so = sizeof(io);
1366 1.75 atatat i = ⅈ
1367 1.75 atatat si = sizeof(ii);
1368 1.75 atatat break;
1369 1.75 atatat case CTLTYPE_QUAD:
1370 1.75 atatat o = &qo;
1371 1.75 atatat so = sizeof(qo);
1372 1.75 atatat i = &qi;
1373 1.75 atatat si = sizeof(qi);
1374 1.75 atatat break;
1375 1.75 atatat }
1376 1.75 atatat
1377 1.75 atatat rc = sysctl(name, namelen, o, &so, i, si);
1378 1.75 atatat if (rc == -1)
1379 1.75 atatat sysctlerror(0);
1380 1.75 atatat
1381 1.75 atatat switch (SYSCTL_TYPE(node->sysctl_flags)) {
1382 1.75 atatat case CTLTYPE_INT:
1383 1.75 atatat display_number(node, gsname, &io, sizeof(io), DISPLAY_OLD);
1384 1.75 atatat display_number(node, gsname, &ii, sizeof(ii), DISPLAY_NEW);
1385 1.75 atatat break;
1386 1.75 atatat case CTLTYPE_QUAD:
1387 1.75 atatat display_number(node, gsname, &qo, sizeof(qo), DISPLAY_OLD);
1388 1.75 atatat display_number(node, gsname, &qi, sizeof(qi), DISPLAY_NEW);
1389 1.75 atatat break;
1390 1.75 atatat }
1391 1.75 atatat }
1392 1.75 atatat
1393 1.75 atatat static void
1394 1.75 atatat write_string(int *name, u_int namelen, struct sysctlnode *node, char *value)
1395 1.75 atatat {
1396 1.75 atatat char *i, *o;
1397 1.75 atatat size_t si, so;
1398 1.75 atatat int rc;
1399 1.75 atatat
1400 1.75 atatat i = value;
1401 1.75 atatat si = strlen(i) + 1;
1402 1.75 atatat so = node->sysctl_size;
1403 1.75 atatat if (si > so && so != 0) {
1404 1.75 atatat fprintf(warnfp, "%s: string too long\n", value);
1405 1.75 atatat exit(1);
1406 1.75 atatat }
1407 1.75 atatat o = malloc(so);
1408 1.75 atatat if (o == NULL) {
1409 1.75 atatat fprintf(warnfp, "%s: !malloc failed!\n", gsname);
1410 1.75 atatat exit(1);
1411 1.75 atatat }
1412 1.75 atatat
1413 1.75 atatat rc = sysctl(name, namelen, o, &so, i, si);
1414 1.75 atatat if (rc == -1)
1415 1.75 atatat sysctlerror(0);
1416 1.75 atatat
1417 1.75 atatat display_string(node, gsname, o, so, DISPLAY_OLD);
1418 1.75 atatat display_string(node, gsname, i, si, DISPLAY_NEW);
1419 1.75 atatat free(o);
1420 1.75 atatat }
1421 1.75 atatat
1422 1.75 atatat /*
1423 1.75 atatat * ********************************************************************
1424 1.75 atatat * simple ways to print stuff consistently
1425 1.75 atatat * ********************************************************************
1426 1.75 atatat */
1427 1.75 atatat static void
1428 1.75 atatat display_number(const struct sysctlnode *node, const char *name,
1429 1.75 atatat const void *data, size_t sz, int n)
1430 1.75 atatat {
1431 1.75 atatat u_quad_t q;
1432 1.75 atatat int i;
1433 1.75 atatat
1434 1.75 atatat if (qflag)
1435 1.75 atatat return;
1436 1.75 atatat if ((nflag || rflag) && (n == DISPLAY_OLD))
1437 1.75 atatat return;
1438 1.75 atatat
1439 1.75 atatat if (rflag && n != DISPLAY_OLD) {
1440 1.75 atatat fwrite(data, sz, 1, stdout);
1441 1.75 atatat return;
1442 1.75 atatat }
1443 1.75 atatat
1444 1.75 atatat if (!nflag) {
1445 1.75 atatat if (n == DISPLAY_VALUE)
1446 1.75 atatat printf("%s%s", name, eq);
1447 1.75 atatat else if (n == DISPLAY_OLD)
1448 1.75 atatat printf("%s: ", name);
1449 1.75 atatat }
1450 1.75 atatat
1451 1.75 atatat if (xflag > 1) {
1452 1.79 atatat if (n != DISPLAY_NEW)
1453 1.79 atatat printf("\n");
1454 1.75 atatat hex_dump(data, sz);
1455 1.22 bouyer return;
1456 1.75 atatat }
1457 1.22 bouyer
1458 1.75 atatat switch (SYSCTL_TYPE(node->sysctl_flags)) {
1459 1.75 atatat case CTLTYPE_INT:
1460 1.75 atatat memcpy(&i, data, sz);
1461 1.75 atatat if (xflag)
1462 1.75 atatat printf("0x%0*x", (int)sz * 2, i);
1463 1.75 atatat else if (node->sysctl_flags & SYSCTL_HEX)
1464 1.75 atatat printf("%#x", i);
1465 1.75 atatat else
1466 1.75 atatat printf("%d", i);
1467 1.75 atatat break;
1468 1.1 cgd case CTLTYPE_QUAD:
1469 1.75 atatat memcpy(&q, data, sz);
1470 1.75 atatat if (xflag)
1471 1.75 atatat printf("0x%0*" PRIx64, (int)sz * 2, q);
1472 1.75 atatat else if (node->sysctl_flags & SYSCTL_HEX)
1473 1.75 atatat printf("%#" PRIx64, q);
1474 1.75 atatat else
1475 1.75 atatat printf("%" PRIu64, q);
1476 1.75 atatat break;
1477 1.75 atatat }
1478 1.75 atatat
1479 1.75 atatat if (n == DISPLAY_OLD)
1480 1.75 atatat printf(" -> ");
1481 1.75 atatat else
1482 1.75 atatat printf("\n");
1483 1.75 atatat }
1484 1.75 atatat
1485 1.75 atatat static void
1486 1.75 atatat display_string(const struct sysctlnode *node, const char *name,
1487 1.75 atatat const void *data, size_t sz, int n)
1488 1.75 atatat {
1489 1.75 atatat const unsigned char *buf = data;
1490 1.75 atatat int ni;
1491 1.75 atatat
1492 1.75 atatat if (qflag)
1493 1.75 atatat return;
1494 1.75 atatat if ((nflag || rflag) && (n == DISPLAY_OLD))
1495 1.75 atatat return;
1496 1.75 atatat
1497 1.75 atatat if (rflag && n != DISPLAY_OLD) {
1498 1.75 atatat fwrite(data, sz, 1, stdout);
1499 1.75 atatat return;
1500 1.75 atatat }
1501 1.75 atatat
1502 1.75 atatat if (!nflag) {
1503 1.75 atatat if (n == DISPLAY_VALUE)
1504 1.75 atatat printf("%s%s", name, eq);
1505 1.75 atatat else if (n == DISPLAY_OLD)
1506 1.75 atatat printf("%s: ", name);
1507 1.75 atatat }
1508 1.75 atatat
1509 1.75 atatat if (xflag > 1) {
1510 1.79 atatat if (n != DISPLAY_NEW)
1511 1.79 atatat printf("\n");
1512 1.75 atatat hex_dump(data, sz);
1513 1.75 atatat return;
1514 1.75 atatat }
1515 1.75 atatat
1516 1.75 atatat if (xflag || node->sysctl_flags & SYSCTL_HEX) {
1517 1.75 atatat for (ni = 0; ni < (int)sz; ni++) {
1518 1.75 atatat if (xflag)
1519 1.75 atatat printf("%02x", buf[ni]);
1520 1.75 atatat if (buf[ni] == '\0')
1521 1.75 atatat break;
1522 1.75 atatat if (!xflag)
1523 1.75 atatat printf("\\x%2.2x", buf[ni]);
1524 1.1 cgd }
1525 1.75 atatat }
1526 1.75 atatat else
1527 1.75 atatat printf("%.*s", (int)sz, buf);
1528 1.75 atatat
1529 1.75 atatat if (n == DISPLAY_OLD)
1530 1.75 atatat printf(" -> ");
1531 1.75 atatat else
1532 1.75 atatat printf("\n");
1533 1.75 atatat }
1534 1.75 atatat
1535 1.75 atatat /*ARGSUSED*/
1536 1.75 atatat static void
1537 1.75 atatat display_struct(const struct sysctlnode *node, const char *name,
1538 1.75 atatat const void *data, size_t sz, int n)
1539 1.75 atatat {
1540 1.75 atatat const unsigned char *buf = data;
1541 1.75 atatat int ni;
1542 1.75 atatat size_t more;
1543 1.75 atatat
1544 1.75 atatat if (qflag)
1545 1.75 atatat return;
1546 1.75 atatat if (!(xflag || rflag)) {
1547 1.75 atatat if (Aflag || req)
1548 1.75 atatat fprintf(warnfp,
1549 1.75 atatat "%s: this type is unknown to this program\n",
1550 1.75 atatat gsname);
1551 1.75 atatat return;
1552 1.75 atatat }
1553 1.75 atatat if ((nflag || rflag) && (n == DISPLAY_OLD))
1554 1.1 cgd return;
1555 1.1 cgd
1556 1.75 atatat if (rflag && n != DISPLAY_OLD) {
1557 1.75 atatat fwrite(data, sz, 1, stdout);
1558 1.1 cgd return;
1559 1.75 atatat }
1560 1.1 cgd
1561 1.75 atatat if (!nflag) {
1562 1.75 atatat if (n == DISPLAY_VALUE)
1563 1.75 atatat printf("%s%s", name, eq);
1564 1.75 atatat else if (n == DISPLAY_OLD)
1565 1.75 atatat printf("%s: ", name);
1566 1.75 atatat }
1567 1.75 atatat
1568 1.75 atatat if (xflag > 1) {
1569 1.79 atatat if (n != DISPLAY_NEW)
1570 1.79 atatat printf("\n");
1571 1.75 atatat hex_dump(data, sz);
1572 1.1 cgd return;
1573 1.1 cgd }
1574 1.75 atatat
1575 1.75 atatat if (sz > 16) {
1576 1.75 atatat more = sz - 16;
1577 1.75 atatat sz = 16;
1578 1.75 atatat }
1579 1.75 atatat else
1580 1.75 atatat more = 0;
1581 1.75 atatat for (ni = 0; ni < (int)sz; ni++)
1582 1.75 atatat printf("%02x", buf[ni]);
1583 1.75 atatat if (more)
1584 1.75 atatat printf("...(%zu more bytes)", more);
1585 1.75 atatat printf("\n");
1586 1.75 atatat }
1587 1.75 atatat
1588 1.75 atatat static void
1589 1.75 atatat hex_dump(const unsigned char *buf, size_t len)
1590 1.75 atatat {
1591 1.75 atatat int i, j;
1592 1.75 atatat char line[80], tmp[12];
1593 1.75 atatat
1594 1.75 atatat memset(line, ' ', sizeof(line));
1595 1.75 atatat for (i = 0, j = 15; i < len; i++) {
1596 1.75 atatat j = i % 16;
1597 1.75 atatat /* reset line */
1598 1.75 atatat if (j == 0) {
1599 1.75 atatat line[58] = '|';
1600 1.75 atatat line[77] = '|';
1601 1.75 atatat line[78] = 0;
1602 1.75 atatat snprintf(tmp, sizeof(tmp), "%07d", i);
1603 1.75 atatat memcpy(&line[0], tmp, 7);
1604 1.75 atatat }
1605 1.75 atatat /* copy out hex version of byte */
1606 1.75 atatat snprintf(tmp, sizeof(tmp), "%02x", buf[i]);
1607 1.75 atatat memcpy(&line[9 + j * 3], tmp, 2);
1608 1.75 atatat /* copy out plain version of byte */
1609 1.75 atatat line[60 + j] = (isprint(buf[i])) ? buf[i] : '.';
1610 1.75 atatat /* print a full line and erase it */
1611 1.75 atatat if (j == 15) {
1612 1.75 atatat printf("%s\n", line);
1613 1.75 atatat memset(line, ' ', sizeof(line));
1614 1.75 atatat }
1615 1.75 atatat }
1616 1.75 atatat if (line[0] != ' ')
1617 1.75 atatat printf("%s\n", line);
1618 1.75 atatat printf("%07zu bytes\n", len);
1619 1.1 cgd }
1620 1.1 cgd
1621 1.1 cgd /*
1622 1.75 atatat * ********************************************************************
1623 1.75 atatat * functions that handle particular nodes
1624 1.75 atatat * ********************************************************************
1625 1.1 cgd */
1626 1.75 atatat /*ARGSUSED*/
1627 1.14 christos static void
1628 1.75 atatat printother(HANDLER_ARGS)
1629 1.1 cgd {
1630 1.75 atatat int rc;
1631 1.75 atatat void *p;
1632 1.75 atatat size_t sz1, sz2;
1633 1.1 cgd
1634 1.75 atatat if (!(Aflag || req) || Mflag)
1635 1.1 cgd return;
1636 1.75 atatat
1637 1.75 atatat /*
1638 1.75 atatat * okay...you asked for it, so let's give it a go
1639 1.75 atatat */
1640 1.75 atatat while (type != CTLTYPE_NODE && (xflag || rflag)) {
1641 1.75 atatat rc = sysctl(name, namelen, NULL, &sz1, NULL, 0);
1642 1.75 atatat if (rc == -1 || sz1 == 0)
1643 1.75 atatat break;
1644 1.75 atatat p = malloc(sz1);
1645 1.75 atatat if (p == NULL)
1646 1.75 atatat break;
1647 1.75 atatat sz2 = sz1;
1648 1.75 atatat rc = sysctl(name, namelen, p, &sz2, NULL, 0);
1649 1.75 atatat if (rc == -1 || sz1 != sz2) {
1650 1.75 atatat free(p);
1651 1.75 atatat break;
1652 1.75 atatat }
1653 1.75 atatat display_struct(pnode, gsname, p, sz1, DISPLAY_VALUE);
1654 1.75 atatat free(p);
1655 1.75 atatat return;
1656 1.75 atatat }
1657 1.75 atatat
1658 1.75 atatat /*
1659 1.75 atatat * that didn't work...do we have a specific message for this
1660 1.75 atatat * thing?
1661 1.75 atatat */
1662 1.75 atatat if (v != NULL) {
1663 1.75 atatat fprintf(warnfp, "%s: use '%s' to view this information\n",
1664 1.75 atatat gsname, (const char *)v);
1665 1.75 atatat return;
1666 1.75 atatat }
1667 1.75 atatat
1668 1.75 atatat /*
1669 1.75 atatat * hmm...i wonder if we have any generic hints?
1670 1.75 atatat */
1671 1.75 atatat switch (name[0]) {
1672 1.75 atatat case CTL_NET:
1673 1.75 atatat fprintf(warnfp, "%s: use 'netstat' to view this information\n",
1674 1.75 atatat sname);
1675 1.75 atatat break;
1676 1.75 atatat case CTL_DEBUG:
1677 1.75 atatat fprintf(warnfp, "%s: missing 'options DEBUG' from kernel?\n",
1678 1.75 atatat sname);
1679 1.75 atatat break;
1680 1.75 atatat case CTL_DDB:
1681 1.75 atatat fprintf(warnfp, "%s: missing 'options DDB' from kernel?\n",
1682 1.75 atatat sname);
1683 1.75 atatat break;
1684 1.1 cgd }
1685 1.1 cgd }
1686 1.1 cgd
1687 1.75 atatat /*ARGSUSED*/
1688 1.75 atatat static void
1689 1.75 atatat kern_clockrate(HANDLER_ARGS)
1690 1.75 atatat {
1691 1.75 atatat struct clockinfo clkinfo;
1692 1.75 atatat size_t sz;
1693 1.75 atatat int rc;
1694 1.75 atatat
1695 1.75 atatat sz = sizeof(clkinfo);
1696 1.75 atatat rc = sysctl(name, namelen, &clkinfo, &sz, NULL, 0);
1697 1.75 atatat if (rc == -1) {
1698 1.75 atatat sysctlerror(1);
1699 1.75 atatat return;
1700 1.75 atatat }
1701 1.75 atatat if (sz != sizeof(clkinfo))
1702 1.75 atatat errx(1, "%s: !returned size wrong!", sname);
1703 1.74 jonathan
1704 1.79 atatat if (xflag || rflag) {
1705 1.75 atatat display_struct(pnode, sname, &clkinfo, sz,
1706 1.75 atatat DISPLAY_VALUE);
1707 1.79 atatat return;
1708 1.79 atatat }
1709 1.75 atatat else if (!nflag)
1710 1.75 atatat printf("%s: ", sname);
1711 1.75 atatat printf("tick = %d, tickadj = %d, hz = %d, profhz = %d, stathz = %d\n",
1712 1.75 atatat clkinfo.tick, clkinfo.tickadj,
1713 1.75 atatat clkinfo.hz, clkinfo.profhz, clkinfo.stathz);
1714 1.75 atatat }
1715 1.1 cgd
1716 1.75 atatat /*ARGSUSED*/
1717 1.75 atatat static void
1718 1.75 atatat kern_boottime(HANDLER_ARGS)
1719 1.1 cgd {
1720 1.75 atatat struct timeval timeval;
1721 1.75 atatat time_t boottime;
1722 1.75 atatat size_t sz;
1723 1.75 atatat int rc;
1724 1.75 atatat
1725 1.75 atatat sz = sizeof(timeval);
1726 1.75 atatat rc = sysctl(name, namelen, &timeval, &sz, NULL, 0);
1727 1.75 atatat if (rc == -1) {
1728 1.75 atatat sysctlerror(1);
1729 1.75 atatat return;
1730 1.75 atatat }
1731 1.75 atatat if (sz != sizeof(timeval))
1732 1.75 atatat errx(1, "%s: !returned size wrong!", sname);
1733 1.1 cgd
1734 1.75 atatat boottime = timeval.tv_sec;
1735 1.75 atatat if (xflag || rflag)
1736 1.75 atatat display_struct(pnode, sname, &timeval, sz,
1737 1.75 atatat DISPLAY_VALUE);
1738 1.75 atatat else if (!nflag)
1739 1.75 atatat /* ctime() provides the \n */
1740 1.75 atatat printf("%s%s%s", sname, eq, ctime(&boottime));
1741 1.75 atatat else if (nflag == 1)
1742 1.75 atatat printf("%ld\n", (long)boottime);
1743 1.75 atatat else
1744 1.75 atatat printf("%ld.%06ld\n", (long)timeval.tv_sec,
1745 1.75 atatat (long)timeval.tv_usec);
1746 1.75 atatat }
1747 1.20 itojun
1748 1.75 atatat /*ARGSUSED*/
1749 1.75 atatat static void
1750 1.75 atatat kern_consdev(HANDLER_ARGS)
1751 1.20 itojun {
1752 1.75 atatat dev_t cons;
1753 1.75 atatat size_t sz;
1754 1.75 atatat int rc;
1755 1.75 atatat
1756 1.75 atatat sz = sizeof(cons);
1757 1.75 atatat rc = sysctl(name, namelen, &cons, &sz, NULL, 0);
1758 1.75 atatat if (rc == -1) {
1759 1.75 atatat sysctlerror(1);
1760 1.75 atatat return;
1761 1.75 atatat }
1762 1.75 atatat if (sz != sizeof(cons))
1763 1.75 atatat errx(1, "%s: !returned size wrong!", sname);
1764 1.20 itojun
1765 1.75 atatat if (xflag || rflag)
1766 1.75 atatat display_struct(pnode, sname, &cons, sz,
1767 1.75 atatat DISPLAY_VALUE);
1768 1.75 atatat else if (!nflag)
1769 1.75 atatat printf("%s%s%s\n", sname, eq, devname(cons, S_IFCHR));
1770 1.75 atatat else
1771 1.75 atatat printf("0x%x\n", cons);
1772 1.75 atatat }
1773 1.17 thorpej
1774 1.75 atatat /*ARGSUSED*/
1775 1.75 atatat static void
1776 1.75 atatat kern_cp_time(HANDLER_ARGS)
1777 1.17 thorpej {
1778 1.75 atatat u_int64_t cp_time[CPUSTATES];
1779 1.75 atatat size_t sz;
1780 1.75 atatat int rc;
1781 1.75 atatat
1782 1.75 atatat sz = sizeof(cp_time);
1783 1.75 atatat rc = sysctl(name, namelen, &cp_time, &sz, NULL, 0);
1784 1.75 atatat if (rc == -1) {
1785 1.75 atatat sysctlerror(1);
1786 1.75 atatat return;
1787 1.75 atatat }
1788 1.75 atatat if (sz != sizeof(cp_time))
1789 1.75 atatat errx(1, "%s: !returned size wrong!", sname);
1790 1.17 thorpej
1791 1.79 atatat if (xflag || rflag) {
1792 1.75 atatat display_struct(pnode, sname, &cp_time, sz,
1793 1.75 atatat DISPLAY_VALUE);
1794 1.79 atatat return;
1795 1.79 atatat }
1796 1.75 atatat else if (!nflag)
1797 1.75 atatat printf("%s: ", sname);
1798 1.75 atatat printf("user = %" PRIu64
1799 1.75 atatat ", nice = %" PRIu64
1800 1.75 atatat ", sys = %" PRIu64
1801 1.75 atatat ", intr = %" PRIu64
1802 1.75 atatat ", idle = %" PRIu64
1803 1.75 atatat "\n",
1804 1.75 atatat cp_time[CP_USER],
1805 1.75 atatat cp_time[CP_NICE],
1806 1.75 atatat cp_time[CP_SYS],
1807 1.75 atatat cp_time[CP_INTR],
1808 1.75 atatat cp_time[CP_IDLE]);
1809 1.17 thorpej }
1810 1.17 thorpej
1811 1.75 atatat /*ARGSUSED*/
1812 1.75 atatat static void
1813 1.75 atatat vm_loadavg(HANDLER_ARGS)
1814 1.22 bouyer {
1815 1.75 atatat struct loadavg loadavg;
1816 1.75 atatat size_t sz;
1817 1.75 atatat int rc;
1818 1.75 atatat
1819 1.75 atatat sz = sizeof(loadavg);
1820 1.75 atatat rc = sysctl(name, namelen, &loadavg, &sz, NULL, 0);
1821 1.75 atatat if (rc == -1) {
1822 1.75 atatat sysctlerror(1);
1823 1.75 atatat return;
1824 1.75 atatat }
1825 1.75 atatat if (sz != sizeof(loadavg))
1826 1.75 atatat errx(1, "%s: !returned size wrong!", sname);
1827 1.75 atatat
1828 1.79 atatat if (xflag || rflag) {
1829 1.75 atatat display_struct(pnode, sname, &loadavg, sz,
1830 1.75 atatat DISPLAY_VALUE);
1831 1.79 atatat return;
1832 1.79 atatat }
1833 1.79 atatat if (!nflag)
1834 1.75 atatat printf("%s: ", sname);
1835 1.75 atatat printf("%.2f %.2f %.2f\n",
1836 1.75 atatat (double) loadavg.ldavg[0] / loadavg.fscale,
1837 1.75 atatat (double) loadavg.ldavg[1] / loadavg.fscale,
1838 1.75 atatat (double) loadavg.ldavg[2] / loadavg.fscale);
1839 1.1 cgd }
1840 1.1 cgd
1841 1.75 atatat /*ARGSUSED*/
1842 1.75 atatat static void
1843 1.75 atatat proc_limit(HANDLER_ARGS)
1844 1.1 cgd {
1845 1.75 atatat u_quad_t olim, *newp, nlim;
1846 1.75 atatat size_t osz, nsz;
1847 1.75 atatat char *t;
1848 1.75 atatat int rc;
1849 1.75 atatat
1850 1.75 atatat osz = sizeof(olim);
1851 1.75 atatat if (value != NULL) {
1852 1.75 atatat nsz = sizeof(nlim);
1853 1.75 atatat newp = &nlim;
1854 1.75 atatat if (strcmp(value, "unlimited") == 0)
1855 1.75 atatat nlim = RLIM_INFINITY;
1856 1.75 atatat else {
1857 1.75 atatat errno = 0;
1858 1.75 atatat nlim = strtouq(value, &t, 0);
1859 1.75 atatat if (*t != '\0' || errno != 0) {
1860 1.75 atatat fprintf(warnfp,
1861 1.75 atatat "%s: %s: '%s' is not a valid limit\n",
1862 1.75 atatat getprogname(), sname, value);
1863 1.75 atatat exit(1);
1864 1.75 atatat }
1865 1.75 atatat }
1866 1.75 atatat }
1867 1.75 atatat else {
1868 1.75 atatat nsz = 0;
1869 1.75 atatat newp = NULL;
1870 1.75 atatat }
1871 1.75 atatat
1872 1.75 atatat rc = sysctl(name, namelen, &olim, &osz, newp, nsz);
1873 1.75 atatat if (rc == -1) {
1874 1.75 atatat sysctlerror(newp == NULL);
1875 1.75 atatat return;
1876 1.75 atatat }
1877 1.75 atatat
1878 1.75 atatat if (newp && qflag)
1879 1.75 atatat return;
1880 1.75 atatat
1881 1.75 atatat if (rflag || xflag || olim != RLIM_INFINITY)
1882 1.75 atatat display_number(pnode, sname, &olim, sizeof(olim),
1883 1.75 atatat newp ? DISPLAY_OLD : DISPLAY_VALUE);
1884 1.75 atatat else
1885 1.75 atatat display_string(pnode, sname, "unlimited", 10,
1886 1.75 atatat newp ? DISPLAY_OLD : DISPLAY_VALUE);
1887 1.1 cgd
1888 1.75 atatat if (newp) {
1889 1.75 atatat if (rflag || xflag || nlim != RLIM_INFINITY)
1890 1.75 atatat display_number(pnode, sname, &nlim, sizeof(nlim),
1891 1.75 atatat DISPLAY_NEW);
1892 1.75 atatat else
1893 1.75 atatat display_string(pnode, sname, "unlimited", 10,
1894 1.75 atatat DISPLAY_NEW);
1895 1.1 cgd }
1896 1.1 cgd }
1897 1.1 cgd
1898 1.75 atatat #ifdef CPU_DISKINFO
1899 1.75 atatat /*ARGSUSED*/
1900 1.14 christos static void
1901 1.75 atatat machdep_diskinfo(HANDLER_ARGS)
1902 1.1 cgd {
1903 1.75 atatat struct disklist *dl;
1904 1.75 atatat struct biosdisk_info *bi;
1905 1.75 atatat struct nativedisk_info *ni;
1906 1.75 atatat int rc;
1907 1.75 atatat size_t sz;
1908 1.75 atatat uint i, b, lim;
1909 1.75 atatat
1910 1.75 atatat rc = sysctl(name, namelen, NULL, &sz, NULL, 0);
1911 1.75 atatat if (rc == -1) {
1912 1.75 atatat sysctlerror(1);
1913 1.75 atatat return;
1914 1.75 atatat }
1915 1.75 atatat dl = malloc(sz);
1916 1.75 atatat if (dl == NULL) {
1917 1.75 atatat sysctlerror(1);
1918 1.75 atatat return;
1919 1.75 atatat }
1920 1.75 atatat rc = sysctl(name, namelen, dl, &sz, NULL, 0);
1921 1.75 atatat if (rc == -1) {
1922 1.75 atatat sysctlerror(1);
1923 1.75 atatat return;
1924 1.75 atatat }
1925 1.45 cgd
1926 1.75 atatat if (!nflag)
1927 1.75 atatat printf("%s: ", sname);
1928 1.75 atatat lim = dl->dl_nbiosdisks;
1929 1.75 atatat if (lim > MAX_BIOSDISKS)
1930 1.75 atatat lim = MAX_BIOSDISKS;
1931 1.75 atatat for (bi = dl->dl_biosdisks, i = 0; i < lim; bi++, i++)
1932 1.75 atatat printf("%x:%" PRIu64 "(%d/%d/%d),%x ",
1933 1.75 atatat bi->bi_dev, bi->bi_lbasecs,
1934 1.75 atatat bi->bi_cyl, bi->bi_head, bi->bi_sec,
1935 1.75 atatat bi->bi_flags);
1936 1.75 atatat lim = dl->dl_nnativedisks;
1937 1.75 atatat ni = dl->dl_nativedisks;
1938 1.75 atatat bi = dl->dl_biosdisks;
1939 1.75 atatat /* LINTED -- pointer casts are tedious */
1940 1.75 atatat if ((char *)&ni[lim] != (char *)dl + sz) {
1941 1.75 atatat fprintf(warnfp, "size mismatch\n");
1942 1.75 atatat return;
1943 1.75 atatat }
1944 1.75 atatat for (i = 0; i < lim; ni++, i++) {
1945 1.75 atatat char t = ':';
1946 1.75 atatat printf(" %.*s", (int)sizeof ni->ni_devname,
1947 1.75 atatat ni->ni_devname);
1948 1.75 atatat for (b = 0; b < ni->ni_nmatches; t = ',', b++)
1949 1.75 atatat printf("%c%x", t,
1950 1.75 atatat bi[ni->ni_biosmatches[b]].bi_dev);
1951 1.75 atatat }
1952 1.75 atatat printf("\n");
1953 1.1 cgd }
1954 1.75 atatat #endif /* CPU_DISKINFO */
1955