usched: Allow process to change self cpu affinity
[dragonfly.git] / sbin / sysctl / sysctl.c
blob64785fabf66143ee6f8a0e9c5363765b436196d9
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 int intval;
161 unsigned int uintval;
162 long longval;
163 unsigned long ulongval;
164 size_t newsize = 0;
165 quad_t quadval;
166 u_quad_t uquadval;
167 int mib[CTL_MAXNAME];
168 char *cp, fmt[BUFSIZ];
169 const char *name;
170 char *name_allocated = NULL;
171 u_int kind;
173 if ((cp = strchr(string, '=')) != NULL) {
174 if ((name_allocated = malloc(cp - string + 1)) == NULL)
175 err(1, "malloc failed");
176 strlcpy(name_allocated, string, cp - string + 1);
177 name = name_allocated;
179 while (isspace(*++cp))
182 newval = cp;
183 newsize = strlen(cp);
184 } else {
185 name = string;
188 len = CTL_MAXNAME;
189 if (sysctlnametomib(name, mib, &len) < 0) {
190 if (iflag)
191 return 0;
192 if (qflag)
193 return 1;
194 if (errno == ENOENT) {
195 errx(1, "unknown oid '%s'", name);
196 } else {
197 err(1, "sysctlnametomib(\"%s\")", name);
201 if (oidfmt(mib, len, fmt, &kind)) {
202 warn("couldn't find format of oid '%s'", name);
203 if (iflag)
204 return 1;
205 exit(1);
208 if (newval == NULL) {
209 if ((kind & CTLTYPE) == CTLTYPE_NODE) {
210 sysctl_all(mib, len);
211 } else {
212 i = show_var(mib, len);
213 if (!i && !bflag)
214 putchar('\n');
216 } else {
217 if ((kind & CTLTYPE) == CTLTYPE_NODE)
218 errx(1, "oid '%s' isn't a leaf node", name);
220 if (!(kind&CTLFLAG_WR))
221 errx(1, "oid '%s' is read only", name);
223 switch (kind & CTLTYPE) {
224 case CTLTYPE_INT:
225 if (!(strcmp(fmt, "IK") == 0)) {
226 if (!set_IK(newval, &intval))
227 errx(1, "invalid value '%s'",
228 (char *)newval);
229 } else
230 intval = (int) strtol(newval, NULL, 0);
231 newval = &intval;
232 newsize = sizeof(intval);
233 break;
234 case CTLTYPE_UINT:
235 uintval = (int) strtoul(newval, NULL, 0);
236 newval = &uintval;
237 newsize = sizeof uintval;
238 break;
239 case CTLTYPE_LONG:
240 longval = strtol(newval, NULL, 0);
241 newval = &longval;
242 newsize = sizeof longval;
243 break;
244 case CTLTYPE_ULONG:
245 ulongval = strtoul(newval, NULL, 0);
246 newval = &ulongval;
247 newsize = sizeof ulongval;
248 break;
249 case CTLTYPE_STRING:
250 break;
251 case CTLTYPE_QUAD:
252 quadval = strtoq(newval, NULL, 0);
253 newval = &quadval;
254 newsize = sizeof(quadval);
255 break;
256 case CTLTYPE_UQUAD:
257 uquadval = strtouq(newval, NULL, 0);
258 newval = &uquadval;
259 newsize = sizeof(uquadval);
260 break;
261 case CTLTYPE_OPAQUE:
262 if (strcmp(fmt, "T,dev_t") == 0 ||
263 strcmp(fmt, "T,udev_t") == 0
265 set_T_dev_t((char*)newval, &newval,
266 &newsize);
267 break;
269 /* FALLTHROUGH */
270 default:
271 errx(1, "oid '%s' is type %d,"
272 " cannot set that", name,
273 kind & CTLTYPE);
276 i = show_var(mib, len);
277 if (sysctl(mib, len, 0, 0, newval, newsize) == -1) {
278 if (!i && !bflag)
279 putchar('\n');
280 switch (errno) {
281 case EOPNOTSUPP:
282 errx(1, "%s: value is not available",
283 string);
284 case ENOTDIR:
285 errx(1, "%s: specification is incomplete",
286 string);
287 case ENOMEM:
288 errx(1, "%s: type is unknown to this program",
289 string);
290 default:
291 warn("%s", string);
292 return 1;
295 if (!bflag)
296 printf(" -> ");
297 i = nflag;
298 nflag = 1;
299 j = show_var(mib, len);
300 if (!j && !bflag)
301 putchar('\n');
302 nflag = i;
305 if (name_allocated != NULL)
306 free(name_allocated);
308 return 0;
311 /* These functions will dump out various interesting structures. */
313 static int
314 S_clockinfo(size_t l2, void *p)
316 struct clockinfo *ci = (struct clockinfo*)p;
317 if (l2 != sizeof(*ci))
318 err(1, "S_clockinfo %zu != %zu", l2, sizeof(*ci));
319 printf("{ hz = %d, tick = %d, tickadj = %d, profhz = %d, stathz = %d }",
320 ci->hz, ci->tick, ci->tickadj, ci->profhz, ci->stathz);
321 return (0);
324 static int
325 S_loadavg(size_t l2, void *p)
327 struct loadavg *tv = (struct loadavg*)p;
329 if (l2 != sizeof(*tv))
330 err(1, "S_loadavg %zu != %zu", l2, sizeof(*tv));
332 printf("{ %.2f %.2f %.2f }",
333 (double)tv->ldavg[0]/(double)tv->fscale,
334 (double)tv->ldavg[1]/(double)tv->fscale,
335 (double)tv->ldavg[2]/(double)tv->fscale);
336 return (0);
339 static int
340 S_timespec(size_t l2, void *p)
342 struct timespec *ts = (struct timespec*)p;
343 time_t tv_sec;
344 char *p1, *p2;
346 if (l2 != sizeof(*ts))
347 err(1, "S_timespec %zu != %zu", l2, sizeof(*ts));
348 printf("{ sec = %ld, nsec = %ld } ",
349 ts->tv_sec, ts->tv_nsec);
350 tv_sec = ts->tv_sec;
351 p1 = strdup(ctime(&tv_sec));
352 for (p2=p1; *p2 ; p2++)
353 if (*p2 == '\n')
354 *p2 = '\0';
355 fputs(p1, stdout);
356 return (0);
359 static int
360 S_timeval(size_t l2, void *p)
362 struct timeval *tv = (struct timeval*)p;
363 time_t tv_sec;
364 char *p1, *p2;
366 if (l2 != sizeof(*tv))
367 err(1, "S_timeval %zu != %zu", l2, sizeof(*tv));
368 printf("{ sec = %ld, usec = %ld } ",
369 tv->tv_sec, tv->tv_usec);
370 tv_sec = tv->tv_sec;
371 p1 = strdup(ctime(&tv_sec));
372 for (p2=p1; *p2 ; p2++)
373 if (*p2 == '\n')
374 *p2 = '\0';
375 fputs(p1, stdout);
376 return (0);
379 static int
380 S_sensor(size_t l2, void *p)
382 struct sensor *s = (struct sensor *)p;
384 if (l2 != sizeof(*s)) {
385 warnx("S_sensor %zu != %zu", l2, sizeof(*s));
386 return (1);
389 if (s->flags & SENSOR_FINVALID) {
391 * XXX: with this flag, the node should be entirely ignored,
392 * but as the magic-based sysctl(8) is not too flexible, we
393 * simply have to print out that the sensor is invalid.
395 printf("invalid");
396 return (0);
399 if (s->flags & SENSOR_FUNKNOWN)
400 printf("unknown");
401 else {
402 switch (s->type) {
403 case SENSOR_TEMP:
404 printf("%.2f degC",
405 (s->value - 273150000) / 1000000.0);
406 break;
407 case SENSOR_FANRPM:
408 printf("%jd RPM", (intmax_t)s->value);
409 break;
410 case SENSOR_VOLTS_DC:
411 printf("%.2f VDC", s->value / 1000000.0);
412 break;
413 case SENSOR_WATTS:
414 printf("%.2f W", s->value / 1000000.0);
415 break;
416 case SENSOR_AMPS:
417 printf("%.2f A", s->value / 1000000.0);
418 break;
419 case SENSOR_WATTHOUR:
420 printf("%.2f Wh", s->value / 1000000.0);
421 break;
422 case SENSOR_AMPHOUR:
423 printf("%.2f Ah", s->value / 1000000.0);
424 break;
425 case SENSOR_INDICATOR:
426 printf("%s", s->value ? "On" : "Off");
427 break;
428 case SENSOR_FREQ:
429 printf("%jd Hz", (intmax_t)s->value);
430 break;
431 case SENSOR_ECC:
432 case SENSOR_INTEGER:
433 printf("%jd", (intmax_t)s->value);
434 break;
435 case SENSOR_PERCENT:
436 printf("%.2f%%", s->value / 1000.0);
437 break;
438 case SENSOR_LUX:
439 printf("%.2f lx", s->value / 1000000.0);
440 break;
441 case SENSOR_DRIVE:
443 const char *name;
445 switch (s->value) {
446 case SENSOR_DRIVE_EMPTY:
447 name = "empty";
448 break;
449 case SENSOR_DRIVE_READY:
450 name = "ready";
451 break;
452 case SENSOR_DRIVE_POWERUP:
453 name = "powering up";
454 break;
455 case SENSOR_DRIVE_ONLINE:
456 name = "online";
457 break;
458 case SENSOR_DRIVE_IDLE:
459 name = "idle";
460 break;
461 case SENSOR_DRIVE_ACTIVE:
462 name = "active";
463 break;
464 case SENSOR_DRIVE_REBUILD:
465 name = "rebuilding";
466 break;
467 case SENSOR_DRIVE_POWERDOWN:
468 name = "powering down";
469 break;
470 case SENSOR_DRIVE_FAIL:
471 name = "failed";
472 break;
473 case SENSOR_DRIVE_PFAIL:
474 name = "degraded";
475 break;
476 default:
477 name = "unknown";
478 break;
480 printf("%s", name);
481 break;
483 case SENSOR_TIMEDELTA:
484 printf("%.6f secs", s->value / 1000000000.0);
485 break;
486 default:
487 printf("unknown");
491 if (s->desc[0] != '\0')
492 printf(" (%s)", s->desc);
494 switch (s->status) {
495 case SENSOR_S_UNSPEC:
496 break;
497 case SENSOR_S_OK:
498 printf(", OK");
499 break;
500 case SENSOR_S_WARN:
501 printf(", WARNING");
502 break;
503 case SENSOR_S_CRIT:
504 printf(", CRITICAL");
505 break;
506 case SENSOR_S_UNKNOWN:
507 printf(", UNKNOWN");
508 break;
511 if (s->tv.tv_sec) {
512 time_t t = s->tv.tv_sec;
513 char ct[26];
515 ctime_r(&t, ct);
516 ct[19] = '\0';
517 printf(", %s.%03ld", ct, s->tv.tv_usec / 1000);
520 return (0);
523 #ifdef __x86_64__
524 static int
525 S_efi_map(size_t l2, void *p)
527 struct efi_map_header *efihdr;
528 struct efi_md *map;
529 const char *type;
530 size_t efisz;
531 int ndesc, i;
533 static const char *types[] = {
534 "Reserved",
535 "LoaderCode",
536 "LoaderData",
537 "BootServicesCode",
538 "BootServicesData",
539 "RuntimeServicesCode",
540 "RuntimeServicesData",
541 "ConventionalMemory",
542 "UnusableMemory",
543 "ACPIReclaimMemory",
544 "ACPIMemoryNVS",
545 "MemoryMappedIO",
546 "MemoryMappedIOPortSpace",
547 "PalCode"
551 * Memory map data provided by UEFI via the GetMemoryMap
552 * Boot Services API.
554 if (l2 < sizeof(*efihdr)) {
555 warnx("S_efi_map length less than header");
556 return (1);
558 efihdr = p;
559 efisz = (sizeof(struct efi_map_header) + 0xf) & ~0xf;
560 map = (struct efi_md *)((uint8_t *)efihdr + efisz);
562 if (efihdr->descriptor_size == 0)
563 return (0);
564 if (l2 != efisz + efihdr->memory_size) {
565 warnx("S_efi_map length mismatch %zu vs %zu", l2, efisz +
566 efihdr->memory_size);
567 return (1);
569 ndesc = efihdr->memory_size / efihdr->descriptor_size;
571 printf("\n%23s %12s %12s %8s %4s",
572 "Type", "Physical", "Virtual", "#Pages", "Attr");
574 for (i = 0; i < ndesc; i++,
575 map = efi_next_descriptor(map, efihdr->descriptor_size)) {
576 if (map->md_type <= EFI_MD_TYPE_PALCODE)
577 type = types[map->md_type];
578 else
579 type = "<INVALID>";
580 printf("\n%23s %012lx %12p %08lx ", type, map->md_phys,
581 map->md_virt, map->md_pages);
582 if (map->md_attr & EFI_MD_ATTR_UC)
583 printf("UC ");
584 if (map->md_attr & EFI_MD_ATTR_WC)
585 printf("WC ");
586 if (map->md_attr & EFI_MD_ATTR_WT)
587 printf("WT ");
588 if (map->md_attr & EFI_MD_ATTR_WB)
589 printf("WB ");
590 if (map->md_attr & EFI_MD_ATTR_UCE)
591 printf("UCE ");
592 if (map->md_attr & EFI_MD_ATTR_WP)
593 printf("WP ");
594 if (map->md_attr & EFI_MD_ATTR_RP)
595 printf("RP ");
596 if (map->md_attr & EFI_MD_ATTR_XP)
597 printf("XP ");
598 if (map->md_attr & EFI_MD_ATTR_RT)
599 printf("RUNTIME");
601 return (0);
603 #endif
605 static int
606 T_dev_t(size_t l2, void *p)
608 dev_t *d = (dev_t *)p;
609 if (l2 != sizeof(*d))
610 err(1, "T_dev_T %zu != %zu", l2, sizeof(*d));
611 if ((int)(*d) != -1) {
612 if (minor(*d) > 255 || minor(*d) < 0)
613 printf("{ major = %d, minor = 0x%x }",
614 major(*d), minor(*d));
615 else
616 printf("{ major = %d, minor = %d }",
617 major(*d), minor(*d));
619 return (0);
622 static void
623 set_T_dev_t(const char *path, void **val, size_t *size)
625 static struct stat statb;
627 if (strcmp(path, "none") && strcmp(path, "off")) {
628 int rc = stat (path, &statb);
629 if (rc) {
630 err(1, "cannot stat %s", path);
633 if (!S_ISCHR(statb.st_mode)) {
634 errx(1, "must specify a device special file.");
636 } else {
637 statb.st_rdev = NODEV;
639 *val = (char*) &statb.st_rdev;
640 *size = sizeof statb.st_rdev;
643 static int
644 set_IK(const char *str, int *val)
646 float temp;
647 int len, kelv;
648 const char *p;
649 char *endptr;
651 if ((len = strlen(str)) == 0)
652 return (0);
653 p = &str[len - 1];
654 if (*p == 'C' || *p == 'F') {
655 temp = strtof(str, &endptr);
656 if (endptr == str || endptr != p)
657 return 0;
658 if (*p == 'F')
659 temp = (temp - 32) * 5 / 9;
660 kelv = temp * 10 + 2732;
661 } else {
663 * I would like to just use, 0 but it would make numbers
664 * like '023' which were interpreted as decimal before
665 * suddenly interpreted as octal.
667 if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X'))
668 kelv = (int)strtol(str, &endptr, 0);
669 else
670 kelv = (int)strtol(str, &endptr, 10);
671 if (endptr == str || *endptr != '\0')
672 return 0;
674 *val = kelv;
675 return 1;
679 * These functions uses a presently undocumented interface to the kernel
680 * to walk the tree and get the type so it can print the value.
681 * This interface is under work and consideration, and should probably
682 * be killed with a big axe by the first person who can find the time.
683 * (be aware though, that the proper interface isn't as obvious as it
684 * may seem, there are various conflicting requirements.
687 static int
688 oidfmt(int *oid, size_t len, char *fmt, u_int *kind)
690 int qoid[CTL_MAXNAME+2];
691 u_char buf[BUFSIZ];
692 int i;
693 size_t j;
695 qoid[0] = 0;
696 qoid[1] = 4;
697 memcpy(qoid + 2, oid, len * sizeof(int));
699 j = sizeof(buf);
700 i = sysctl(qoid, len + 2, buf, &j, 0, 0);
701 if (i)
702 err(1, "sysctl fmt %d %zu %d", i, j, errno);
704 if (kind)
705 *kind = *(u_int *)buf;
707 if (fmt)
708 strcpy(fmt, (char *)(buf + sizeof(u_int)));
709 return 0;
713 * This formats and outputs the value of one variable
715 * Returns zero if anything was actually output.
716 * Returns one if didn't know what to do with this.
717 * Return minus one if we had errors.
720 static int
721 show_var(int *oid, size_t nlen)
723 u_char buf[BUFSIZ], *val = NULL, *p, *nul;
724 char name[BUFSIZ], *fmt;
725 const char *sep, *spacer;
726 int qoid[CTL_MAXNAME+2];
727 int i;
728 size_t j, len;
729 u_int kind;
730 int (*func)(size_t, void *);
731 int error = 0;
733 qoid[0] = 0;
734 memcpy(qoid + 2, oid, nlen * sizeof(int));
736 qoid[1] = 1;
737 j = sizeof(name);
738 i = sysctl(qoid, nlen + 2, name, &j, 0, 0);
739 if (i || !j)
740 err(1, "sysctl name %d %zu %d", i, j, errno);
742 if (Nflag) {
743 printf("%s", name);
744 return (0);
747 if (eflag)
748 sep = "=";
749 else
750 sep = ": ";
752 if (dflag) { /* just print description */
753 qoid[1] = 5;
754 j = sizeof(buf);
755 i = sysctl(qoid, nlen + 2, buf, &j, 0, 0);
756 if (!nflag)
757 printf("%s%s", name, sep);
758 printf("%s", buf);
759 return(0);
761 /* find an estimate of how much we need for this var */
762 j = 0;
763 i = sysctl(oid, nlen, 0, &j, 0, 0);
764 j += j; /* we want to be sure :-) */
766 val = malloc(j + 1);
767 if (val == NULL)
768 return (1);
770 len = j;
771 i = sysctl(oid, nlen, val, &len, 0, 0);
772 if (i || !len) {
773 error = 1;
774 goto done;
777 if (bflag) {
778 fwrite(val, 1, len, stdout);
779 goto done;
782 val[len] = '\0';
783 fmt = buf;
784 oidfmt(oid, nlen, fmt, &kind);
785 p = val;
786 switch (*fmt) {
787 case 'A':
788 if (!nflag)
789 printf("%s%s", name, sep);
790 nul = memchr(p, '\0', len);
791 fwrite(p, nul == NULL ? (int)len : nul - p, 1, stdout);
792 return (0);
794 case 'I':
795 if (!nflag)
796 printf("%s%s", name, sep);
797 fmt++;
798 spacer = "";
799 while (len >= sizeof(int)) {
800 if(*fmt == 'U')
801 printf("%s%u", spacer, *(unsigned int *)p);
802 else if (*fmt == 'K' && *(int *)p >= 0)
803 printf("%s%.1fC", spacer, (*(int *)p - 2732) / 10.0);
804 else
805 printf("%s%d", spacer, *(int *)p);
806 spacer = " ";
807 len -= sizeof(int);
808 p += sizeof(int);
810 goto done;
812 case 'L':
813 if (!nflag)
814 printf("%s%s", name, sep);
815 fmt++;
816 spacer = "";
817 while (len >= sizeof(long)) {
818 if(*fmt == 'U')
819 printf("%s%lu", spacer, *(unsigned long *)p);
820 else
821 printf("%s%ld", spacer, *(long *)p);
822 spacer = " ";
823 len -= sizeof(long);
824 p += sizeof(long);
826 goto done;
828 case 'P':
829 if (!nflag)
830 printf("%s%s", name, sep);
831 printf("%p", *(void **)p);
832 goto done;
834 case 'Q':
835 if (!nflag)
836 printf("%s%s", name, sep);
837 fmt++;
838 spacer = "";
839 while (len >= sizeof(quad_t)) {
840 if(*fmt == 'U') {
841 printf("%s%ju",
842 spacer, (uintmax_t)*(u_quad_t *)p);
843 } else {
844 printf("%s%jd",
845 spacer, (intmax_t)*(quad_t *)p);
847 spacer = " ";
848 len -= sizeof(int64_t);
849 p += sizeof(int64_t);
851 goto done;
853 case 'T':
854 case 'S':
855 if (!oflag && !xflag) {
856 i = 0;
857 if (strcmp(fmt, "S,clockinfo") == 0)
858 func = S_clockinfo;
859 else if (strcmp(fmt, "S,timespec") == 0)
860 func = S_timespec;
861 else if (strcmp(fmt, "S,timeval") == 0)
862 func = S_timeval;
863 else if (strcmp(fmt, "S,loadavg") == 0)
864 func = S_loadavg;
865 else if (strcmp(fmt, "S,sensor") == 0)
866 func = S_sensor;
867 #ifdef __x86_64__
868 else if (strcmp(fmt, "S,efi_map_header") == 0)
869 func = S_efi_map;
870 #endif
871 else if (strcmp(fmt, "T,dev_t") == 0)
872 func = T_dev_t;
873 else if (strcmp(fmt, "T,udev_t") == 0)
874 func = T_dev_t;
875 else
876 func = NULL;
877 if (func) {
878 if (!nflag)
879 printf("%s%s", name, sep);
880 error = (*func)(len, p);
881 goto done;
884 /* FALL THROUGH */
885 default:
886 if (!oflag && !xflag) {
887 error = 1;
888 goto done;
890 if (!nflag)
891 printf("%s%s", name, sep);
892 printf("Format:%s Length:%zu Dump:0x", fmt, len);
893 while (len-- && (xflag || p < val + 16))
894 printf("%02x", *p++);
895 if (!xflag && len > 16)
896 printf("...");
897 goto done;
900 done:
901 if (val != NULL)
902 free(val);
903 return (error);
906 static int
907 sysctl_all(int *oid, size_t len)
909 int name1[22], name2[22];
910 int retval;
911 size_t i, l1, l2;
913 name1[0] = 0;
914 name1[1] = 2;
915 l1 = 2;
916 if (len) {
917 memcpy(name1+2, oid, len * sizeof(int));
918 l1 += len;
919 } else {
920 name1[2] = 1;
921 l1++;
923 for (;;) {
924 l2 = sizeof(name2);
925 retval = sysctl(name1, l1, name2, &l2, 0, 0);
926 if (retval < 0) {
927 if (errno == ENOENT)
928 return 0;
929 else
930 err(1, "sysctl(getnext) %d %zu", retval, l2);
933 l2 /= sizeof(int);
935 if (l2 < len)
936 return 0;
938 for (i = 0; i < len; i++)
939 if (name2[i] != oid[i])
940 return 0;
942 retval = show_var(name2, l2);
943 if (retval == 0 && !bflag)
944 putchar('\n');
946 memcpy(name1+2, name2, l2 * sizeof(int));
947 l1 = 2 + l2;