kernel/sysctl: Add handling of uint32_t.
[dragonfly.git] / sbin / sysctl / sysctl.c
blob0bb9e17d964dbcffd82bf55c1d60ad242b49632c
1 /*
2 * Copyright (c) 1993
3 * The Regents of the University of California. All rights reserved.
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. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
29 * @(#) Copyright (c) 1993 The Regents of the University of California. All rights reserved.
30 * @(#)from: sysctl.c 8.1 (Berkeley) 6/6/93
31 * $FreeBSD: src/sbin/sysctl/sysctl.c,v 1.25.2.11 2003/05/01 22:48:08 trhodes Exp $
34 #include <sys/types.h>
35 #include <sys/stat.h>
36 #include <sys/sysctl.h>
37 #include <sys/resource.h>
38 #include <sys/sensors.h>
39 #include <sys/param.h>
41 #ifdef __x86_64__
42 #include <sys/efi.h>
43 #include <machine/metadata.h>
44 #endif
46 #include <machine/inttypes.h>
48 #include <ctype.h>
49 #include <err.h>
50 #include <errno.h>
51 #include <stdio.h>
52 #include <stdlib.h>
53 #include <string.h>
54 #include <unistd.h>
56 static int aflag, bflag, dflag, eflag, Nflag, nflag, oflag, xflag;
57 static int iflag, qflag;
59 static int oidfmt(int *, size_t, char *, u_int *);
60 static int parse(const char *);
61 static int show_var(int *, size_t);
62 static int sysctl_all(int *, size_t);
63 static void set_T_dev_t(const char *, void **, size_t *);
64 static int set_IK(const char *, int *);
66 static void
67 usage(void)
70 fprintf(stderr, "%s\n%s\n",
71 "usage: sysctl [-bdeNnox] variable[=value] ...",
72 " sysctl [-bdeNnox] -a");
73 exit(1);
76 int
77 main(int argc, char **argv)
79 int ch;
80 int warncount;
82 setbuf(stdout,0);
83 setbuf(stderr,0);
85 while ((ch = getopt(argc, argv, "AabdeiNnoqwxX")) != -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 'i':
104 iflag = 1;
105 break;
106 case 'N':
107 Nflag = 1;
108 break;
109 case 'n':
110 nflag = 1;
111 break;
112 case 'o':
113 oflag = 1;
114 break;
115 case 'q':
116 qflag = 1;
117 break;
118 case 'w':
119 /* compatibility */
120 /* ignored */
121 break;
122 case 'X':
123 /* compatibility */
124 aflag = xflag = 1;
125 break;
126 case 'x':
127 xflag = 1;
128 break;
129 default:
130 usage();
133 argc -= optind;
134 argv += optind;
136 if (Nflag && nflag)
137 usage();
138 if (aflag && argc == 0)
139 exit(sysctl_all(0, 0));
140 if (argc == 0)
141 usage();
142 warncount = 0;
143 while (argc-- > 0)
144 warncount += parse(*argv++);
146 return warncount;
150 * Parse a name into a MIB entry.
151 * Lookup and print out the MIB entry if it exists.
152 * Set a new value if requested.
154 static int
155 parse(const char *string)
157 size_t len;
158 int i, j;
159 void *newval = NULL;
160 uint32_t u32val;
161 int intval;
162 unsigned int uintval;
163 long longval;
164 unsigned long ulongval;
165 size_t newsize = 0;
166 quad_t quadval;
167 u_quad_t uquadval;
168 int mib[CTL_MAXNAME];
169 char *cp, fmt[BUFSIZ];
170 const char *name;
171 char *name_allocated = NULL;
172 u_int kind;
174 if ((cp = strchr(string, '=')) != NULL) {
175 if ((name_allocated = malloc(cp - string + 1)) == NULL)
176 err(1, "malloc failed");
177 strlcpy(name_allocated, string, cp - string + 1);
178 name = name_allocated;
180 while (isspace(*++cp))
183 newval = cp;
184 newsize = strlen(cp);
185 } else {
186 name = string;
189 len = CTL_MAXNAME;
190 if (sysctlnametomib(name, mib, &len) < 0) {
191 if (iflag)
192 return 0;
193 if (qflag)
194 return 1;
195 if (errno == ENOENT) {
196 errx(1, "unknown oid '%s'", name);
197 } else {
198 err(1, "sysctlnametomib(\"%s\")", name);
202 if (oidfmt(mib, len, fmt, &kind)) {
203 warn("couldn't find format of oid '%s'", name);
204 if (iflag)
205 return 1;
206 exit(1);
209 if (newval == NULL) {
210 if ((kind & CTLTYPE) == CTLTYPE_NODE) {
211 sysctl_all(mib, len);
212 } else {
213 i = show_var(mib, len);
214 if (!i && !bflag)
215 putchar('\n');
217 } else {
218 if ((kind & CTLTYPE) == CTLTYPE_NODE)
219 errx(1, "oid '%s' isn't a leaf node", name);
221 if (!(kind&CTLFLAG_WR))
222 errx(1, "oid '%s' is read only", name);
224 switch (kind & CTLTYPE) {
225 case CTLTYPE_INT:
226 if (!(strcmp(fmt, "IK") == 0)) {
227 if (!set_IK(newval, &intval))
228 errx(1, "invalid value '%s'",
229 (char *)newval);
230 } else
231 intval = (int) strtol(newval, NULL, 0);
232 newval = &intval;
233 newsize = sizeof(intval);
234 break;
235 case CTLTYPE_UINT:
236 uintval = (int) strtoul(newval, NULL, 0);
237 newval = &uintval;
238 newsize = sizeof uintval;
239 break;
240 case CTLTYPE_LONG:
241 longval = strtol(newval, NULL, 0);
242 newval = &longval;
243 newsize = sizeof longval;
244 break;
245 case CTLTYPE_ULONG:
246 ulongval = strtoul(newval, NULL, 0);
247 newval = &ulongval;
248 newsize = sizeof ulongval;
249 break;
250 case CTLTYPE_STRING:
251 break;
252 case CTLTYPE_QUAD:
253 quadval = strtoq(newval, NULL, 0);
254 newval = &quadval;
255 newsize = sizeof(quadval);
256 break;
257 case CTLTYPE_UQUAD:
258 uquadval = strtouq(newval, NULL, 0);
259 newval = &uquadval;
260 newsize = sizeof(uquadval);
261 break;
262 case CTLTYPE_U32:
263 u32val = (uint32_t)strtoul(newval, NULL, 0);
264 newval = &u32val;
265 newsize = sizeof(u32val);
266 break;
267 case CTLTYPE_OPAQUE:
268 if (strcmp(fmt, "T,dev_t") == 0 ||
269 strcmp(fmt, "T,udev_t") == 0
271 set_T_dev_t((char*)newval, &newval,
272 &newsize);
273 break;
275 /* FALLTHROUGH */
276 default:
277 errx(1, "oid '%s' is type %d,"
278 " cannot set that", name,
279 kind & CTLTYPE);
282 i = show_var(mib, len);
283 if (sysctl(mib, len, 0, 0, newval, newsize) == -1) {
284 if (!i && !bflag)
285 putchar('\n');
286 switch (errno) {
287 case EOPNOTSUPP:
288 errx(1, "%s: value is not available",
289 string);
290 case ENOTDIR:
291 errx(1, "%s: specification is incomplete",
292 string);
293 case ENOMEM:
294 errx(1, "%s: type is unknown to this program",
295 string);
296 default:
297 warn("%s", string);
298 return 1;
301 if (!bflag)
302 printf(" -> ");
303 i = nflag;
304 nflag = 1;
305 j = show_var(mib, len);
306 if (!j && !bflag)
307 putchar('\n');
308 nflag = i;
311 if (name_allocated != NULL)
312 free(name_allocated);
314 return 0;
317 /* These functions will dump out various interesting structures. */
319 static int
320 S_clockinfo(size_t l2, void *p)
322 struct clockinfo *ci = (struct clockinfo*)p;
323 if (l2 != sizeof(*ci))
324 err(1, "S_clockinfo %zu != %zu", l2, sizeof(*ci));
325 printf("{ hz = %d, tick = %d, tickadj = %d, profhz = %d, stathz = %d }",
326 ci->hz, ci->tick, ci->tickadj, ci->profhz, ci->stathz);
327 return (0);
330 static int
331 S_loadavg(size_t l2, void *p)
333 struct loadavg *tv = (struct loadavg*)p;
335 if (l2 != sizeof(*tv))
336 err(1, "S_loadavg %zu != %zu", l2, sizeof(*tv));
338 printf("{ %.2f %.2f %.2f }",
339 (double)tv->ldavg[0]/(double)tv->fscale,
340 (double)tv->ldavg[1]/(double)tv->fscale,
341 (double)tv->ldavg[2]/(double)tv->fscale);
342 return (0);
345 static int
346 S_timespec(size_t l2, void *p)
348 struct timespec *ts = (struct timespec*)p;
349 time_t tv_sec;
350 char *p1, *p2;
352 if (l2 != sizeof(*ts))
353 err(1, "S_timespec %zu != %zu", l2, sizeof(*ts));
354 printf("{ sec = %ld, nsec = %ld } ",
355 ts->tv_sec, ts->tv_nsec);
356 tv_sec = ts->tv_sec;
357 p1 = strdup(ctime(&tv_sec));
358 for (p2=p1; *p2 ; p2++)
359 if (*p2 == '\n')
360 *p2 = '\0';
361 fputs(p1, stdout);
362 return (0);
365 static int
366 S_timeval(size_t l2, void *p)
368 struct timeval *tv = (struct timeval*)p;
369 time_t tv_sec;
370 char *p1, *p2;
372 if (l2 != sizeof(*tv))
373 err(1, "S_timeval %zu != %zu", l2, sizeof(*tv));
374 printf("{ sec = %ld, usec = %ld } ",
375 tv->tv_sec, tv->tv_usec);
376 tv_sec = tv->tv_sec;
377 p1 = strdup(ctime(&tv_sec));
378 for (p2=p1; *p2 ; p2++)
379 if (*p2 == '\n')
380 *p2 = '\0';
381 fputs(p1, stdout);
382 return (0);
385 static int
386 S_sensor(size_t l2, void *p)
388 struct sensor *s = (struct sensor *)p;
390 if (l2 != sizeof(*s)) {
391 warnx("S_sensor %zu != %zu", l2, sizeof(*s));
392 return (1);
395 if (s->flags & SENSOR_FINVALID) {
397 * XXX: with this flag, the node should be entirely ignored,
398 * but as the magic-based sysctl(8) is not too flexible, we
399 * simply have to print out that the sensor is invalid.
401 printf("invalid");
402 return (0);
405 if (s->flags & SENSOR_FUNKNOWN)
406 printf("unknown");
407 else {
408 switch (s->type) {
409 case SENSOR_TEMP:
410 printf("%.2f degC",
411 (s->value - 273150000) / 1000000.0);
412 break;
413 case SENSOR_FANRPM:
414 printf("%jd RPM", (intmax_t)s->value);
415 break;
416 case SENSOR_VOLTS_DC:
417 printf("%.2f VDC", s->value / 1000000.0);
418 break;
419 case SENSOR_WATTS:
420 printf("%.2f W", s->value / 1000000.0);
421 break;
422 case SENSOR_AMPS:
423 printf("%.2f A", s->value / 1000000.0);
424 break;
425 case SENSOR_WATTHOUR:
426 printf("%.2f Wh", s->value / 1000000.0);
427 break;
428 case SENSOR_AMPHOUR:
429 printf("%.2f Ah", s->value / 1000000.0);
430 break;
431 case SENSOR_INDICATOR:
432 printf("%s", s->value ? "On" : "Off");
433 break;
434 case SENSOR_FREQ:
435 printf("%jd Hz", (intmax_t)s->value);
436 break;
437 case SENSOR_ECC:
438 case SENSOR_INTEGER:
439 printf("%jd", (intmax_t)s->value);
440 break;
441 case SENSOR_PERCENT:
442 printf("%.2f%%", s->value / 1000.0);
443 break;
444 case SENSOR_LUX:
445 printf("%.2f lx", s->value / 1000000.0);
446 break;
447 case SENSOR_DRIVE:
449 const char *name;
451 switch (s->value) {
452 case SENSOR_DRIVE_EMPTY:
453 name = "empty";
454 break;
455 case SENSOR_DRIVE_READY:
456 name = "ready";
457 break;
458 case SENSOR_DRIVE_POWERUP:
459 name = "powering up";
460 break;
461 case SENSOR_DRIVE_ONLINE:
462 name = "online";
463 break;
464 case SENSOR_DRIVE_IDLE:
465 name = "idle";
466 break;
467 case SENSOR_DRIVE_ACTIVE:
468 name = "active";
469 break;
470 case SENSOR_DRIVE_REBUILD:
471 name = "rebuilding";
472 break;
473 case SENSOR_DRIVE_POWERDOWN:
474 name = "powering down";
475 break;
476 case SENSOR_DRIVE_FAIL:
477 name = "failed";
478 break;
479 case SENSOR_DRIVE_PFAIL:
480 name = "degraded";
481 break;
482 default:
483 name = "unknown";
484 break;
486 printf("%s", name);
487 break;
489 case SENSOR_TIMEDELTA:
490 printf("%.6f secs", s->value / 1000000000.0);
491 break;
492 default:
493 printf("unknown");
497 if (s->desc[0] != '\0')
498 printf(" (%s)", s->desc);
500 switch (s->status) {
501 case SENSOR_S_UNSPEC:
502 break;
503 case SENSOR_S_OK:
504 printf(", OK");
505 break;
506 case SENSOR_S_WARN:
507 printf(", WARNING");
508 break;
509 case SENSOR_S_CRIT:
510 printf(", CRITICAL");
511 break;
512 case SENSOR_S_UNKNOWN:
513 printf(", UNKNOWN");
514 break;
517 if (s->tv.tv_sec) {
518 time_t t = s->tv.tv_sec;
519 char ct[26];
521 ctime_r(&t, ct);
522 ct[19] = '\0';
523 printf(", %s.%03ld", ct, s->tv.tv_usec / 1000);
526 return (0);
529 #ifdef __x86_64__
530 static int
531 S_efi_map(size_t l2, void *p)
533 struct efi_map_header *efihdr;
534 struct efi_md *map;
535 const char *type;
536 size_t efisz;
537 int ndesc, i;
539 static const char *types[] = {
540 "Reserved",
541 "LoaderCode",
542 "LoaderData",
543 "BootServicesCode",
544 "BootServicesData",
545 "RuntimeServicesCode",
546 "RuntimeServicesData",
547 "ConventionalMemory",
548 "UnusableMemory",
549 "ACPIReclaimMemory",
550 "ACPIMemoryNVS",
551 "MemoryMappedIO",
552 "MemoryMappedIOPortSpace",
553 "PalCode"
557 * Memory map data provided by UEFI via the GetMemoryMap
558 * Boot Services API.
560 if (l2 < sizeof(*efihdr)) {
561 warnx("S_efi_map length less than header");
562 return (1);
564 efihdr = p;
565 efisz = (sizeof(struct efi_map_header) + 0xf) & ~0xf;
566 map = (struct efi_md *)((uint8_t *)efihdr + efisz);
568 if (efihdr->descriptor_size == 0)
569 return (0);
570 if (l2 != efisz + efihdr->memory_size) {
571 warnx("S_efi_map length mismatch %zu vs %zu", l2, efisz +
572 efihdr->memory_size);
573 return (1);
575 ndesc = efihdr->memory_size / efihdr->descriptor_size;
577 printf("\n%23s %12s %12s %8s %4s",
578 "Type", "Physical", "Virtual", "#Pages", "Attr");
580 for (i = 0; i < ndesc; i++,
581 map = efi_next_descriptor(map, efihdr->descriptor_size)) {
582 if (map->md_type <= EFI_MD_TYPE_PALCODE)
583 type = types[map->md_type];
584 else
585 type = "<INVALID>";
586 printf("\n%23s %012lx %12p %08lx ", type, map->md_phys,
587 map->md_virt, map->md_pages);
588 if (map->md_attr & EFI_MD_ATTR_UC)
589 printf("UC ");
590 if (map->md_attr & EFI_MD_ATTR_WC)
591 printf("WC ");
592 if (map->md_attr & EFI_MD_ATTR_WT)
593 printf("WT ");
594 if (map->md_attr & EFI_MD_ATTR_WB)
595 printf("WB ");
596 if (map->md_attr & EFI_MD_ATTR_UCE)
597 printf("UCE ");
598 if (map->md_attr & EFI_MD_ATTR_WP)
599 printf("WP ");
600 if (map->md_attr & EFI_MD_ATTR_RP)
601 printf("RP ");
602 if (map->md_attr & EFI_MD_ATTR_XP)
603 printf("XP ");
604 if (map->md_attr & EFI_MD_ATTR_RT)
605 printf("RUNTIME");
607 return (0);
609 #endif
611 static int
612 T_dev_t(size_t l2, void *p)
614 dev_t *d = (dev_t *)p;
615 if (l2 != sizeof(*d))
616 err(1, "T_dev_T %zu != %zu", l2, sizeof(*d));
617 if ((int)(*d) != -1) {
618 if (minor(*d) > 255 || minor(*d) < 0)
619 printf("{ major = %d, minor = 0x%x }",
620 major(*d), minor(*d));
621 else
622 printf("{ major = %d, minor = %d }",
623 major(*d), minor(*d));
625 return (0);
628 static void
629 set_T_dev_t(const char *path, void **val, size_t *size)
631 static struct stat statb;
633 if (strcmp(path, "none") && strcmp(path, "off")) {
634 int rc = stat (path, &statb);
635 if (rc) {
636 err(1, "cannot stat %s", path);
639 if (!S_ISCHR(statb.st_mode)) {
640 errx(1, "must specify a device special file.");
642 } else {
643 statb.st_rdev = NODEV;
645 *val = (char*) &statb.st_rdev;
646 *size = sizeof statb.st_rdev;
649 static int
650 set_IK(const char *str, int *val)
652 float temp;
653 int len, kelv;
654 const char *p;
655 char *endptr;
657 if ((len = strlen(str)) == 0)
658 return (0);
659 p = &str[len - 1];
660 if (*p == 'C' || *p == 'F') {
661 temp = strtof(str, &endptr);
662 if (endptr == str || endptr != p)
663 return 0;
664 if (*p == 'F')
665 temp = (temp - 32) * 5 / 9;
666 kelv = temp * 10 + 2732;
667 } else {
669 * I would like to just use, 0 but it would make numbers
670 * like '023' which were interpreted as decimal before
671 * suddenly interpreted as octal.
673 if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X'))
674 kelv = (int)strtol(str, &endptr, 0);
675 else
676 kelv = (int)strtol(str, &endptr, 10);
677 if (endptr == str || *endptr != '\0')
678 return 0;
680 *val = kelv;
681 return 1;
685 * These functions uses a presently undocumented interface to the kernel
686 * to walk the tree and get the type so it can print the value.
687 * This interface is under work and consideration, and should probably
688 * be killed with a big axe by the first person who can find the time.
689 * (be aware though, that the proper interface isn't as obvious as it
690 * may seem, there are various conflicting requirements.
693 static int
694 oidfmt(int *oid, size_t len, char *fmt, u_int *kind)
696 int qoid[CTL_MAXNAME+2];
697 u_char buf[BUFSIZ];
698 int i;
699 size_t j;
701 qoid[0] = 0;
702 qoid[1] = 4;
703 memcpy(qoid + 2, oid, len * sizeof(int));
705 j = sizeof(buf);
706 i = sysctl(qoid, len + 2, buf, &j, 0, 0);
707 if (i)
708 err(1, "sysctl fmt %d %zu %d", i, j, errno);
710 if (kind)
711 *kind = *(u_int *)buf;
713 if (fmt)
714 strcpy(fmt, (char *)(buf + sizeof(u_int)));
715 return 0;
719 * This formats and outputs the value of one variable
721 * Returns zero if anything was actually output.
722 * Returns one if didn't know what to do with this.
723 * Return minus one if we had errors.
726 static int
727 show_var(int *oid, size_t nlen)
729 u_char buf[BUFSIZ], *val = NULL, *p, *nul;
730 char name[BUFSIZ], *fmt;
731 const char *sep, *spacer;
732 int qoid[CTL_MAXNAME+2];
733 int i;
734 size_t j, len;
735 u_int kind;
736 int (*func)(size_t, void *);
737 int error = 0;
739 qoid[0] = 0;
740 memcpy(qoid + 2, oid, nlen * sizeof(int));
742 qoid[1] = 1;
743 j = sizeof(name);
744 i = sysctl(qoid, nlen + 2, name, &j, 0, 0);
745 if (i || !j)
746 err(1, "sysctl name %d %zu %d", i, j, errno);
748 if (Nflag) {
749 printf("%s", name);
750 return (0);
753 if (eflag)
754 sep = "=";
755 else
756 sep = ": ";
758 if (dflag) { /* just print description */
759 qoid[1] = 5;
760 j = sizeof(buf);
761 i = sysctl(qoid, nlen + 2, buf, &j, 0, 0);
762 if (!nflag)
763 printf("%s%s", name, sep);
764 printf("%s", buf);
765 return(0);
767 /* find an estimate of how much we need for this var */
768 j = 0;
769 i = sysctl(oid, nlen, 0, &j, 0, 0);
770 j += j; /* we want to be sure :-) */
772 val = malloc(j + 1);
773 if (val == NULL)
774 return (1);
776 len = j;
777 i = sysctl(oid, nlen, val, &len, 0, 0);
778 if (i || !len) {
779 error = 1;
780 goto done;
783 if (bflag) {
784 fwrite(val, 1, len, stdout);
785 goto done;
788 val[len] = '\0';
789 fmt = buf;
790 oidfmt(oid, nlen, fmt, &kind);
791 p = val;
792 switch (*fmt) {
793 case 'A':
794 if (!nflag)
795 printf("%s%s", name, sep);
796 nul = memchr(p, '\0', len);
797 fwrite(p, nul == NULL ? (int)len : nul - p, 1, stdout);
798 return (0);
800 case 'I':
801 if (!nflag)
802 printf("%s%s", name, sep);
803 fmt++;
804 spacer = "";
805 while (len >= sizeof(int)) {
806 if(*fmt == 'U')
807 printf("%s%u", spacer, *(unsigned int *)p);
808 else if (*fmt == 'K' && *(int *)p >= 0)
809 printf("%s%.1fC", spacer, (*(int *)p - 2732) / 10.0);
810 else
811 printf("%s%d", spacer, *(int *)p);
812 spacer = " ";
813 len -= sizeof(int);
814 p += sizeof(int);
816 goto done;
818 case 'L':
819 if (!nflag)
820 printf("%s%s", name, sep);
821 fmt++;
822 spacer = "";
823 while (len >= sizeof(long)) {
824 if(*fmt == 'U')
825 printf("%s%lu", spacer, *(unsigned long *)p);
826 else
827 printf("%s%ld", spacer, *(long *)p);
828 spacer = " ";
829 len -= sizeof(long);
830 p += sizeof(long);
832 goto done;
834 case 'P':
835 if (!nflag)
836 printf("%s%s", name, sep);
837 printf("%p", *(void **)p);
838 goto done;
840 case 'Q':
841 if (!nflag)
842 printf("%s%s", name, sep);
843 fmt++;
844 spacer = "";
845 while (len >= sizeof(quad_t)) {
846 if(*fmt == 'U') {
847 printf("%s%ju",
848 spacer, (uintmax_t)*(u_quad_t *)p);
849 } else {
850 printf("%s%jd",
851 spacer, (intmax_t)*(quad_t *)p);
853 spacer = " ";
854 len -= sizeof(int64_t);
855 p += sizeof(int64_t);
857 goto done;
859 case 'T':
860 case 'S':
861 if (!oflag && !xflag) {
862 i = 0;
863 if (strcmp(fmt, "S,clockinfo") == 0)
864 func = S_clockinfo;
865 else if (strcmp(fmt, "S,timespec") == 0)
866 func = S_timespec;
867 else if (strcmp(fmt, "S,timeval") == 0)
868 func = S_timeval;
869 else if (strcmp(fmt, "S,loadavg") == 0)
870 func = S_loadavg;
871 else if (strcmp(fmt, "S,sensor") == 0)
872 func = S_sensor;
873 #ifdef __x86_64__
874 else if (strcmp(fmt, "S,efi_map_header") == 0)
875 func = S_efi_map;
876 #endif
877 else if (strcmp(fmt, "T,dev_t") == 0)
878 func = T_dev_t;
879 else if (strcmp(fmt, "T,udev_t") == 0)
880 func = T_dev_t;
881 else
882 func = NULL;
883 if (func) {
884 if (!nflag)
885 printf("%s%s", name, sep);
886 error = (*func)(len, p);
887 goto done;
890 /* FALL THROUGH */
891 default:
892 if (!oflag && !xflag) {
893 error = 1;
894 goto done;
896 if (!nflag)
897 printf("%s%s", name, sep);
898 printf("Format:%s Length:%zu Dump:0x", fmt, len);
899 while (len-- && (xflag || p < val + 16))
900 printf("%02x", *p++);
901 if (!xflag && len > 16)
902 printf("...");
903 goto done;
906 done:
907 if (val != NULL)
908 free(val);
909 return (error);
912 static int
913 sysctl_all(int *oid, size_t len)
915 int name1[22], name2[22];
916 int retval;
917 size_t i, l1, l2;
919 name1[0] = 0;
920 name1[1] = 2;
921 l1 = 2;
922 if (len) {
923 memcpy(name1+2, oid, len * sizeof(int));
924 l1 += len;
925 } else {
926 name1[2] = 1;
927 l1++;
929 for (;;) {
930 l2 = sizeof(name2);
931 retval = sysctl(name1, l1, name2, &l2, 0, 0);
932 if (retval < 0) {
933 if (errno == ENOENT)
934 return 0;
935 else
936 err(1, "sysctl(getnext) %d %zu", retval, l2);
939 l2 /= sizeof(int);
941 if (l2 < len)
942 return 0;
944 for (i = 0; i < len; i++)
945 if (name2[i] != oid[i])
946 return 0;
948 retval = show_var(name2, l2);
949 if (retval == 0 && !bflag)
950 putchar('\n');
952 memcpy(name1+2, name2, l2 * sizeof(int));
953 l1 = 2 + l2;