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