sysctl(8): Fix handling of uquad type sysctls (wrong variable was taken).
[dragonfly.git] / sbin / sysctl / sysctl.c
... / ...
CommitLineData
1/*
2 * Copyright (c) 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 * @(#) Copyright (c) 1993 The Regents of the University of California. All rights reserved.
34 * @(#)from: sysctl.c 8.1 (Berkeley) 6/6/93
35 * $FreeBSD: src/sbin/sysctl/sysctl.c,v 1.25.2.11 2003/05/01 22:48:08 trhodes Exp $
36 */
37
38#ifdef __i386__
39#include <sys/diskslice.h> /* used for bootdev parsing */
40#include <sys/reboot.h> /* used for bootdev parsing */
41#endif
42#include <sys/types.h>
43#include <sys/stat.h>
44#include <sys/sysctl.h>
45#include <sys/resource.h>
46#include <sys/sensors.h>
47#include <sys/param.h>
48
49#include <machine/inttypes.h>
50
51#include <ctype.h>
52#include <err.h>
53#include <errno.h>
54#include <stdio.h>
55#include <stdlib.h>
56#include <string.h>
57#include <unistd.h>
58
59static int aflag, bflag, dflag, eflag, Nflag, nflag, oflag, xflag;
60
61static int oidfmt(int *, size_t, char *, u_int *);
62static void parse(const char *);
63static int show_var(int *, size_t);
64static int sysctl_all(int *, size_t);
65static void set_T_dev_t(const char *, void **, size_t *);
66static int set_IK(const char *, int *);
67
68static void
69usage(void)
70{
71
72 fprintf(stderr, "%s\n%s\n",
73 "usage: sysctl [-bdeNnox] variable[=value] ...",
74 " sysctl [-bdeNnox] -a");
75 exit(1);
76}
77
78int
79main(int argc, char **argv)
80{
81 int ch;
82 setbuf(stdout,0);
83 setbuf(stderr,0);
84
85 while ((ch = getopt(argc, argv, "AabdeNnowxX")) != -1) {
86 switch (ch) {
87 case 'A':
88 /* compatibility */
89 aflag = oflag = 1;
90 break;
91 case 'a':
92 aflag = 1;
93 break;
94 case 'b':
95 bflag = 1;
96 break;
97 case 'd':
98 dflag = 1;
99 break;
100 case 'e':
101 eflag = 1;
102 break;
103 case 'N':
104 Nflag = 1;
105 break;
106 case 'n':
107 nflag = 1;
108 break;
109 case 'o':
110 oflag = 1;
111 break;
112 case 'w':
113 /* compatibility */
114 /* ignored */
115 break;
116 case 'X':
117 /* compatibility */
118 aflag = xflag = 1;
119 break;
120 case 'x':
121 xflag = 1;
122 break;
123 default:
124 usage();
125 }
126 }
127 argc -= optind;
128 argv += optind;
129
130 if (Nflag && nflag)
131 usage();
132 if (aflag && argc == 0)
133 exit(sysctl_all(0, 0));
134 if (argc == 0)
135 usage();
136 while (argc-- > 0)
137 parse(*argv++);
138 exit(0);
139}
140
141/*
142 * Parse a name into a MIB entry.
143 * Lookup and print out the MIB entry if it exists.
144 * Set a new value if requested.
145 */
146static void
147parse(const char *string)
148{
149 size_t len;
150 int i, j;
151 void *newval = NULL;
152 int intval;
153 unsigned int uintval;
154 long longval;
155 unsigned long ulongval;
156 size_t newsize = 0;
157 quad_t quadval;
158 u_quad_t uquadval;
159 int mib[CTL_MAXNAME];
160 char *cp, fmt[BUFSIZ];
161 const char *name;
162 char *name_allocated = NULL;
163 u_int kind;
164
165 if ((cp = strchr(string, '=')) != NULL) {
166 if ((name_allocated = malloc(cp - string + 1)) == NULL)
167 err(1, "malloc failed");
168 strlcpy(name_allocated, string, cp - string + 1);
169 name = name_allocated;
170
171 while (isspace(*++cp))
172 ;
173
174 newval = cp;
175 newsize = strlen(cp);
176 } else {
177 name = string;
178 }
179
180 len = CTL_MAXNAME;
181 if (sysctlnametomib(name, mib, &len) < 0) {
182 if (errno == ENOENT) {
183 errx(1, "unknown oid '%s'", name);
184 } else {
185 err(1, "sysctlnametomib(\"%s\")", name);
186 }
187 }
188
189 if (oidfmt(mib, len, fmt, &kind))
190 err(1, "couldn't find format of oid '%s'", name);
191
192 if (newval == NULL) {
193 if ((kind & CTLTYPE) == CTLTYPE_NODE) {
194 sysctl_all(mib, len);
195 } else {
196 i = show_var(mib, len);
197 if (!i && !bflag)
198 putchar('\n');
199 }
200 } else {
201 if ((kind & CTLTYPE) == CTLTYPE_NODE)
202 errx(1, "oid '%s' isn't a leaf node", name);
203
204 if (!(kind&CTLFLAG_WR))
205 errx(1, "oid '%s' is read only", name);
206
207 switch (kind & CTLTYPE) {
208 case CTLTYPE_INT:
209 if (!strcmp(fmt, "IK") == 0) {
210 if (!set_IK(newval, &intval))
211 errx(1, "invalid value '%s'",
212 (char *)newval);
213 } else
214 intval = (int) strtol(newval, NULL, 0);
215 newval = &intval;
216 newsize = sizeof(intval);
217 break;
218 case CTLTYPE_UINT:
219 uintval = (int) strtoul(newval, NULL, 0);
220 newval = &uintval;
221 newsize = sizeof uintval;
222 break;
223 case CTLTYPE_LONG:
224 longval = strtol(newval, NULL, 0);
225 newval = &longval;
226 newsize = sizeof longval;
227 break;
228 case CTLTYPE_ULONG:
229 ulongval = strtoul(newval, NULL, 0);
230 newval = &ulongval;
231 newsize = sizeof ulongval;
232 break;
233 case CTLTYPE_STRING:
234 break;
235 case CTLTYPE_QUAD:
236 quadval = strtoq(newval, NULL, 0);
237 newval = &quadval;
238 newsize = sizeof(quadval);
239 break;
240 case CTLTYPE_UQUAD:
241 uquadval = strtouq(newval, NULL, 0);
242 newval = &uquadval;
243 newsize = sizeof(uquadval);
244 break;
245 case CTLTYPE_OPAQUE:
246 if (strcmp(fmt, "T,dev_t") == 0 ||
247 strcmp(fmt, "T,udev_t") == 0
248 ) {
249 set_T_dev_t((char*)newval, &newval,
250 &newsize);
251 break;
252 }
253 /* FALLTHROUGH */
254 default:
255 errx(1, "oid '%s' is type %d,"
256 " cannot set that", name,
257 kind & CTLTYPE);
258 }
259
260 i = show_var(mib, len);
261 if (sysctl(mib, len, 0, 0, newval, newsize) == -1) {
262 if (!i && !bflag)
263 putchar('\n');
264 switch (errno) {
265 case EOPNOTSUPP:
266 errx(1, "%s: value is not available",
267 string);
268 case ENOTDIR:
269 errx(1, "%s: specification is incomplete",
270 string);
271 case ENOMEM:
272 errx(1, "%s: type is unknown to this program",
273 string);
274 default:
275 warn("%s", string);
276 return;
277 }
278 }
279 if (!bflag)
280 printf(" -> ");
281 i = nflag;
282 nflag = 1;
283 j = show_var(mib, len);
284 if (!j && !bflag)
285 putchar('\n');
286 nflag = i;
287 }
288
289 if (name_allocated != NULL)
290 free(name_allocated);
291}
292
293/* These functions will dump out various interesting structures. */
294
295static int
296S_clockinfo(int l2, void *p)
297{
298 struct clockinfo *ci = (struct clockinfo*)p;
299 if (l2 != sizeof(*ci))
300 err(1, "S_clockinfo %d != %zu", l2, sizeof(*ci));
301 printf("{ hz = %d, tick = %d, tickadj = %d, profhz = %d, stathz = %d }",
302 ci->hz, ci->tick, ci->tickadj, ci->profhz, ci->stathz);
303 return (0);
304}
305
306static int
307S_loadavg(int l2, void *p)
308{
309 struct loadavg *tv = (struct loadavg*)p;
310
311 if (l2 != sizeof(*tv))
312 err(1, "S_loadavg %d != %zu", l2, sizeof(*tv));
313
314 printf("{ %.2f %.2f %.2f }",
315 (double)tv->ldavg[0]/(double)tv->fscale,
316 (double)tv->ldavg[1]/(double)tv->fscale,
317 (double)tv->ldavg[2]/(double)tv->fscale);
318 return (0);
319}
320
321static int
322S_timespec(int l2, void *p)
323{
324 struct timespec *ts = (struct timespec*)p;
325 time_t tv_sec;
326 char *p1, *p2;
327
328 if (l2 != sizeof(*ts))
329 err(1, "S_timespec %d != %zu", l2, sizeof(*ts));
330 printf("{ sec = %ld, nsec = %ld } ",
331 ts->tv_sec, ts->tv_nsec);
332 tv_sec = ts->tv_sec;
333 p1 = strdup(ctime(&tv_sec));
334 for (p2=p1; *p2 ; p2++)
335 if (*p2 == '\n')
336 *p2 = '\0';
337 fputs(p1, stdout);
338 return (0);
339}
340
341static int
342S_timeval(int l2, void *p)
343{
344 struct timeval *tv = (struct timeval*)p;
345 time_t tv_sec;
346 char *p1, *p2;
347
348 if (l2 != sizeof(*tv))
349 err(1, "S_timeval %d != %zu", l2, sizeof(*tv));
350 printf("{ sec = %ld, usec = %ld } ",
351 tv->tv_sec, tv->tv_usec);
352 tv_sec = tv->tv_sec;
353 p1 = strdup(ctime(&tv_sec));
354 for (p2=p1; *p2 ; p2++)
355 if (*p2 == '\n')
356 *p2 = '\0';
357 fputs(p1, stdout);
358 return (0);
359}
360
361static int
362S_sensor(int l2, void *p)
363{
364 struct sensor *s = (struct sensor *)p;
365
366 if (l2 != sizeof(*s)) {
367 warnx("S_sensor %d != %zu", l2, sizeof(*s));
368 return (1);
369 }
370
371 if (s->flags & SENSOR_FINVALID) {
372 /*
373 * XXX: with this flag, the node should be entirely ignored,
374 * but as the magic-based sysctl(8) is not too flexible, we
375 * simply have to print out that the sensor is invalid.
376 */
377 printf("invalid");
378 return (0);
379 }
380
381 if (s->flags & SENSOR_FUNKNOWN)
382 printf("unknown");
383 else {
384 switch (s->type) {
385 case SENSOR_TEMP:
386 printf("%.2f degC",
387 (s->value - 273150000) / 1000000.0);
388 break;
389 case SENSOR_FANRPM:
390 printf("%jd RPM", (intmax_t)s->value);
391 break;
392 case SENSOR_VOLTS_DC:
393 printf("%.2f VDC", s->value / 1000000.0);
394 break;
395 case SENSOR_AMPS:
396 printf("%.2f A", s->value / 1000000.0);
397 break;
398 case SENSOR_WATTHOUR:
399 printf("%.2f Wh", s->value / 1000000.0);
400 break;
401 case SENSOR_AMPHOUR:
402 printf("%.2f Ah", s->value / 1000000.0);
403 break;
404 case SENSOR_INDICATOR:
405 printf("%s", s->value ? "On" : "Off");
406 break;
407 case SENSOR_INTEGER:
408 printf("%jd", (intmax_t)s->value);
409 break;
410 case SENSOR_PERCENT:
411 printf("%.2f%%", s->value / 1000.0);
412 break;
413 case SENSOR_LUX:
414 printf("%.2f lx", s->value / 1000000.0);
415 break;
416 case SENSOR_DRIVE:
417 {
418 const char *name;
419
420 switch (s->value) {
421 case SENSOR_DRIVE_EMPTY:
422 name = "empty";
423 break;
424 case SENSOR_DRIVE_READY:
425 name = "ready";
426 break;
427 case SENSOR_DRIVE_POWERUP:
428 name = "powering up";
429 break;
430 case SENSOR_DRIVE_ONLINE:
431 name = "online";
432 break;
433 case SENSOR_DRIVE_IDLE:
434 name = "idle";
435 break;
436 case SENSOR_DRIVE_ACTIVE:
437 name = "active";
438 break;
439 case SENSOR_DRIVE_REBUILD:
440 name = "rebuilding";
441 break;
442 case SENSOR_DRIVE_POWERDOWN:
443 name = "powering down";
444 break;
445 case SENSOR_DRIVE_FAIL:
446 name = "failed";
447 break;
448 case SENSOR_DRIVE_PFAIL:
449 name = "degraded";
450 break;
451 default:
452 name = "unknown";
453 break;
454 }
455 printf(name);
456 break;
457 }
458 case SENSOR_TIMEDELTA:
459 printf("%.6f secs", s->value / 1000000000.0);
460 break;
461 default:
462 printf("unknown");
463 }
464 }
465
466 if (s->desc[0] != '\0')
467 printf(" (%s)", s->desc);
468
469 switch (s->status) {
470 case SENSOR_S_UNSPEC:
471 break;
472 case SENSOR_S_OK:
473 printf(", OK");
474 break;
475 case SENSOR_S_WARN:
476 printf(", WARNING");
477 break;
478 case SENSOR_S_CRIT:
479 printf(", CRITICAL");
480 break;
481 case SENSOR_S_UNKNOWN:
482 printf(", UNKNOWN");
483 break;
484 }
485
486 if (s->tv.tv_sec) {
487 time_t t = s->tv.tv_sec;
488 char ct[26];
489
490 ctime_r(&t, ct);
491 ct[19] = '\0';
492 printf(", %s.%03ld", ct, s->tv.tv_usec / 1000);
493 }
494
495 return (0);
496}
497
498static int
499T_dev_t(int l2, void *p)
500{
501 dev_t *d = (dev_t *)p;
502 if (l2 != sizeof(*d))
503 err(1, "T_dev_T %d != %zu", l2, sizeof(*d));
504 if ((int)(*d) != -1) {
505 if (minor(*d) > 255 || minor(*d) < 0)
506 printf("{ major = %d, minor = 0x%x }",
507 major(*d), minor(*d));
508 else
509 printf("{ major = %d, minor = %d }",
510 major(*d), minor(*d));
511 }
512 return (0);
513}
514
515static void
516set_T_dev_t(const char *path, void **val, size_t *size)
517{
518 static struct stat statb;
519
520 if (strcmp(path, "none") && strcmp(path, "off")) {
521 int rc = stat (path, &statb);
522 if (rc) {
523 err(1, "cannot stat %s", path);
524 }
525
526 if (!S_ISCHR(statb.st_mode)) {
527 errx(1, "must specify a device special file.");
528 }
529 } else {
530 statb.st_rdev = NODEV;
531 }
532 *val = (char*) &statb.st_rdev;
533 *size = sizeof statb.st_rdev;
534}
535
536static int
537set_IK(const char *str, int *val)
538{
539 float temp;
540 int len, kelv;
541 const char *p;
542 char *endptr;
543
544 if ((len = strlen(str)) == 0)
545 return (0);
546 p = &str[len - 1];
547 if (*p == 'C' || *p == 'F') {
548 temp = strtof(str, &endptr);
549 if (endptr == str || endptr != p)
550 return 0;
551 if (*p == 'F')
552 temp = (temp - 32) * 5 / 9;
553 kelv = temp * 10 + 2732;
554 } else {
555 kelv = (int)strtol(str, &endptr, 10);
556 if (endptr == str || *endptr != '\0')
557 return 0;
558 }
559 *val = kelv;
560 return 1;
561}
562
563/*
564 * These functions uses a presently undocumented interface to the kernel
565 * to walk the tree and get the type so it can print the value.
566 * This interface is under work and consideration, and should probably
567 * be killed with a big axe by the first person who can find the time.
568 * (be aware though, that the proper interface isn't as obvious as it
569 * may seem, there are various conflicting requirements.
570 */
571
572static int
573oidfmt(int *oid, size_t len, char *fmt, u_int *kind)
574{
575 int qoid[CTL_MAXNAME+2];
576 u_char buf[BUFSIZ];
577 int i;
578 size_t j;
579
580 qoid[0] = 0;
581 qoid[1] = 4;
582 memcpy(qoid + 2, oid, len * sizeof(int));
583
584 j = sizeof(buf);
585 i = sysctl(qoid, len + 2, buf, &j, 0, 0);
586 if (i)
587 err(1, "sysctl fmt %d %zu %d", i, j, errno);
588
589 if (kind)
590 *kind = *(u_int *)buf;
591
592 if (fmt)
593 strcpy(fmt, (char *)(buf + sizeof(u_int)));
594 return 0;
595}
596
597#ifdef __i386__
598/*
599 * Code to map a bootdev major number into a suitable device name.
600 * Major numbers are mapped into names as in boot2.c
601 */
602struct _foo {
603 int majdev;
604 const char *name;
605} maj2name[] = {
606 { 30, "ad" },
607 { 0, "wd" },
608 { 1, "wfd" },
609 { 2, "fd" },
610 { 4, "da" },
611 { -1, NULL } /* terminator */
612};
613
614static int
615machdep_bootdev(u_long value)
616{
617 int majdev, unit, slice, part;
618 struct _foo *p;
619
620 if ((value & B_MAGICMASK) != B_DEVMAGIC) {
621 printf("invalid (0x%08lx)", value);
622 return 0;
623 }
624 majdev = B_TYPE(value);
625 unit = B_UNIT(value);
626 slice = B_SLICE(value);
627 part = B_PARTITION(value);
628 if (majdev == 2) { /* floppy, as known to the boot block... */
629 printf("/dev/fd%d", unit);
630 return 0;
631 }
632 for (p = maj2name; p->name != NULL && p->majdev != majdev ; p++) ;
633 if (p->name != NULL) { /* found */
634 if (slice == WHOLE_DISK_SLICE)
635 printf("/dev/%s%d%c", p->name, unit, part);
636 else
637 printf("/dev/%s%ds%d%c",
638 p->name, unit, slice - BASE_SLICE + 1, part + 'a');
639 } else
640 printf("unknown (major %d unit %d slice %d part %d)",
641 majdev, unit, slice, part);
642 return 0;
643}
644#endif
645
646/*
647 * This formats and outputs the value of one variable
648 *
649 * Returns zero if anything was actually output.
650 * Returns one if didn't know what to do with this.
651 * Return minus one if we had errors.
652 */
653
654static int
655show_var(int *oid, size_t nlen)
656{
657 u_char buf[BUFSIZ], *val = NULL, *p, *nul;
658 char name[BUFSIZ], *fmt;
659 const char *sep, *spacer;
660 int qoid[CTL_MAXNAME+2];
661 int i;
662 size_t j, len;
663 u_int kind;
664 int (*func)(int, void *);
665 int error = 0;
666
667 qoid[0] = 0;
668 memcpy(qoid + 2, oid, nlen * sizeof(int));
669
670 qoid[1] = 1;
671 j = sizeof(name);
672 i = sysctl(qoid, nlen + 2, name, &j, 0, 0);
673 if (i || !j)
674 err(1, "sysctl name %d %zu %d", i, j, errno);
675
676 if (Nflag) {
677 printf("%s", name);
678 return (0);
679 }
680
681 if (eflag)
682 sep = "=";
683 else
684 sep = ": ";
685
686 if (dflag) { /* just print description */
687 qoid[1] = 5;
688 j = sizeof(buf);
689 i = sysctl(qoid, nlen + 2, buf, &j, 0, 0);
690 if (!nflag)
691 printf("%s%s", name, sep);
692 printf("%s", buf);
693 return(0);
694 }
695 /* find an estimate of how much we need for this var */
696 j = 0;
697 i = sysctl(oid, nlen, 0, &j, 0, 0);
698 j += j; /* we want to be sure :-) */
699
700 val = malloc(j + 1);
701 if (val == NULL)
702 return (1);
703
704 len = j;
705 i = sysctl(oid, nlen, val, &len, 0, 0);
706 if (i || !len) {
707 error = 1;
708 goto done;
709 }
710
711 if (bflag) {
712 fwrite(val, 1, len, stdout);
713 goto done;
714 }
715
716 val[len] = '\0';
717 fmt = buf;
718 oidfmt(oid, nlen, fmt, &kind);
719 p = val;
720 switch (*fmt) {
721 case 'A':
722 if (!nflag)
723 printf("%s%s", name, sep);
724 nul = memchr(p, '\0', len);
725 fwrite(p, nul == NULL ? (int)len : nul - p, 1, stdout);
726 return (0);
727
728 case 'I':
729 if (!nflag)
730 printf("%s%s", name, sep);
731 fmt++;
732 spacer = "";
733 while (len >= sizeof(int)) {
734 if(*fmt == 'U')
735 printf("%s%u", spacer, *(unsigned int *)p);
736 else if (*fmt == 'K' && *(int *)p >= 0)
737 printf("%s%.1fC", spacer, (*(int *)p - 2732) / 10.0);
738 else
739 printf("%s%d", spacer, *(int *)p);
740 spacer = " ";
741 len -= sizeof(int);
742 p += sizeof(int);
743 }
744 goto done;
745
746 case 'L':
747 if (!nflag)
748 printf("%s%s", name, sep);
749 fmt++;
750#ifdef __i386__
751 if (!strcmp(name, "machdep.guessed_bootdev"))
752 return machdep_bootdev(*(unsigned long *)p);
753#endif
754 spacer = "";
755 while (len >= sizeof(long)) {
756 if(*fmt == 'U')
757 printf("%s%lu", spacer, *(unsigned long *)p);
758 else
759 printf("%s%ld", spacer, *(long *)p);
760 spacer = " ";
761 len -= sizeof(long);
762 p += sizeof(long);
763 }
764 goto done;
765
766 case 'P':
767 if (!nflag)
768 printf("%s%s", name, sep);
769 printf("%p", *(void **)p);
770 goto done;
771
772 case 'Q':
773 if (!nflag)
774 printf("%s%s", name, sep);
775 fmt++;
776 spacer = "";
777 while (len >= sizeof(quad_t)) {
778 if(*fmt == 'U') {
779 printf("%s%ju",
780 spacer, (uintmax_t)*(u_quad_t *)p);
781 } else {
782 printf("%s%jd",
783 spacer, (intmax_t)*(quad_t *)p);
784 }
785 spacer = " ";
786 len -= sizeof(int64_t);
787 p += sizeof(int64_t);
788 }
789 goto done;
790
791 case 'T':
792 case 'S':
793 if (!oflag && !xflag) {
794 i = 0;
795 if (strcmp(fmt, "S,clockinfo") == 0)
796 func = S_clockinfo;
797 else if (strcmp(fmt, "S,timespec") == 0)
798 func = S_timespec;
799 else if (strcmp(fmt, "S,timeval") == 0)
800 func = S_timeval;
801 else if (strcmp(fmt, "S,loadavg") == 0)
802 func = S_loadavg;
803 else if (strcmp(fmt, "S,sensor") == 0)
804 func = S_sensor;
805 else if (strcmp(fmt, "T,dev_t") == 0)
806 func = T_dev_t;
807 else if (strcmp(fmt, "T,udev_t") == 0)
808 func = T_dev_t;
809 else
810 func = NULL;
811 if (func) {
812 if (!nflag)
813 printf("%s%s", name, sep);
814 error = (*func)(len, p);
815 goto done;
816 }
817 }
818 /* FALL THROUGH */
819 default:
820 if (!oflag && !xflag) {
821 error = 1;
822 goto done;
823 }
824 if (!nflag)
825 printf("%s%s", name, sep);
826 printf("Format:%s Length:%zu Dump:0x", fmt, len);
827 while (len-- && (xflag || p < val + 16))
828 printf("%02x", *p++);
829 if (!xflag && len > 16)
830 printf("...");
831 goto done;
832 }
833
834done:
835 if (val != NULL)
836 free(val);
837 return (error);
838}
839
840static int
841sysctl_all(int *oid, size_t len)
842{
843 int name1[22], name2[22];
844 int retval;
845 size_t i, l1, l2;
846
847 name1[0] = 0;
848 name1[1] = 2;
849 l1 = 2;
850 if (len) {
851 memcpy(name1+2, oid, len * sizeof(int));
852 l1 += len;
853 } else {
854 name1[2] = 1;
855 l1++;
856 }
857 for (;;) {
858 l2 = sizeof(name2);
859 retval = sysctl(name1, l1, name2, &l2, 0, 0);
860 if (retval < 0) {
861 if (errno == ENOENT)
862 return 0;
863 else
864 err(1, "sysctl(getnext) %d %zu", retval, l2);
865 }
866
867 l2 /= sizeof(int);
868
869 if (l2 < len)
870 return 0;
871
872 for (i = 0; i < len; i++)
873 if (name2[i] != oid[i])
874 return 0;
875
876 retval = show_var(name2, l2);
877 if (retval == 0 && !bflag)
878 putchar('\n');
879
880 memcpy(name1+2, name2, l2 * sizeof(int));
881 l1 = 2 + l2;
882 }
883}