]> git.saurik.com Git - apple/system_cmds.git/blame - sysctl.tproj/sysctl.c
system_cmds-880.40.5.tar.gz
[apple/system_cmds.git] / sysctl.tproj / sysctl.c
CommitLineData
1815bff5
A
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.
1815bff5
A
13 * 4. 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.
16 *
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.
28 */
29
34d340d7 30#include <sys/cdefs.h>
1815bff5 31#ifndef lint
1a7e3f61 32__unused static const char copyright[] =
1815bff5
A
33"@(#) Copyright (c) 1993\n\
34 The Regents of the University of California. All rights reserved.\n";
35#endif /* not lint */
36
37#ifndef lint
1a7e3f61
A
38#if 0
39static char sccsid[] = "@(#)from: sysctl.c 8.1 (Berkeley) 6/6/93";
40#endif
cf37c299 41__unused static const char rcsid[] =
1a7e3f61 42 "$FreeBSD$";
1815bff5
A
43#endif /* not lint */
44
45#include <sys/param.h>
1a7e3f61
A
46#include <sys/time.h>
47#include <sys/resource.h>
1815bff5
A
48#include <sys/stat.h>
49#include <sys/sysctl.h>
1815bff5
A
50#ifdef __APPLE__
51#include <mach/machine/vm_param.h>
52#include <mach/machine/vm_types.h>
53#include <mach/mach_types.h>
1a7e3f61
A
54#else // !__APPLE__
55#include <sys/vmmeter.h>
56#endif // !__APPLE__
1815bff5 57
1815bff5 58#include <ctype.h>
1a7e3f61
A
59#include <err.h>
60#include <errno.h>
61#include <inttypes.h>
62#include <locale.h>
c0bbac3a
A
63#ifdef __APPLE__
64#endif
1815bff5
A
65#include <stdio.h>
66#include <stdlib.h>
67#include <string.h>
1a7e3f61 68#include <unistd.h>
1815bff5 69
1a7e3f61
A
70static int aflag, bflag, dflag, eflag, hflag, iflag;
71static int Nflag, nflag, oflag, qflag, xflag, warncount;
1815bff5 72
1815bff5 73static int oidfmt(int *, int, char *, u_int *);
1a7e3f61
A
74static void parse(const char *);
75#ifdef __APPLE__
c3a08f59 76static int show_var(int *, int, int);
1a7e3f61
A
77#else
78static int show_var(int *, int);
79#endif
80static int sysctl_all(int *oid, int len);
1815bff5
A
81static int name2oid(char *, int *);
82
1a7e3f61
A
83#ifndef __APPLE__
84static int set_IK(const char *, int *);
85#endif
1815bff5 86
1a7e3f61
A
87#ifdef __APPLE__
88// Shims for FreeBSD source compatibility.
89#define CTLTYPE_UINT 0xa
90#define CTLTYPE_LONG 0xb
91#define CTLTYPE_ULONG 0xc
92#define CTLTYPE_S64 0xd
93#define CTLTYPE_U64 0xe
94
95#define CTLFLAG_TUN 0
96
97// Support for CTL_USER
98const struct ctlname names[] = CTL_NAMES;
99const struct ctlname user_names[] = CTL_USER_NAMES;
100const int user_names_count = sizeof(user_names) / sizeof(*user_names);
101#endif
1815bff5 102
1a7e3f61
A
103static void
104usage(void)
105{
1815bff5 106
1a7e3f61
A
107 (void)fprintf(stderr, "%s\n%s\n",
108 "usage: sysctl [-bdehiNnoqx] name[=value] ...",
109 " sysctl [-bdehNnoqx] -a");
110 exit(1);
1815bff5
A
111}
112
1a7e3f61
A
113int
114main(int argc, char **argv)
1815bff5 115{
1a7e3f61 116 int ch;
1815bff5 117
1a7e3f61
A
118 setlocale(LC_NUMERIC, "");
119 setbuf(stdout,0);
120 setbuf(stderr,0);
1815bff5 121
1a7e3f61
A
122 while ((ch = getopt(argc, argv, "AabdehiNnoqwxX")) != -1) {
123 switch (ch) {
124 case 'A':
125 /* compatibility */
126 aflag = oflag = 1;
1815bff5 127 break;
1a7e3f61
A
128 case 'a':
129 aflag = 1;
1815bff5 130 break;
1a7e3f61
A
131 case 'b':
132 bflag = 1;
1815bff5 133 break;
1a7e3f61
A
134 case 'd':
135 dflag = 1;
1815bff5 136 break;
1a7e3f61
A
137 case 'e':
138 eflag = 1;
1815bff5 139 break;
1a7e3f61
A
140 case 'h':
141 hflag = 1;
142 break;
143 case 'i':
144 iflag = 1;
145 break;
146 case 'N':
147 Nflag = 1;
148 break;
149 case 'n':
150 nflag = 1;
151 break;
152 case 'o':
153 oflag = 1;
154 break;
155 case 'q':
156 qflag = 1;
157 break;
158 case 'w':
159 /* compatibility */
160 /* ignored */
1815bff5 161 break;
1a7e3f61
A
162 case 'X':
163 /* compatibility */
164 aflag = xflag = 1;
165 break;
166 case 'x':
167 xflag = 1;
168 break;
169 default:
170 usage();
ef8ad44b 171 }
1815bff5 172 }
1a7e3f61
A
173 argc -= optind;
174 argv += optind;
1815bff5 175
1a7e3f61
A
176 if (Nflag && nflag)
177 usage();
178 if (aflag && argc == 0)
179 exit(sysctl_all(0, 0));
180 if (argc == 0)
181 usage();
1815bff5 182
1a7e3f61
A
183 warncount = 0;
184 while (argc-- > 0)
185 parse(*argv++);
186 exit(warncount);
1815bff5
A
187}
188
189/*
190 * Parse a name into a MIB entry.
191 * Lookup and print out the MIB entry if it exists.
192 * Set a new value if requested.
193 */
194static void
1a7e3f61 195parse(const char *string)
1815bff5
A
196{
197 int len, i, j;
198 void *newval = 0;
1a7e3f61 199 int intval;
1815bff5 200 unsigned int uintval;
1a7e3f61
A
201 long longval;
202 unsigned long ulongval;
203 size_t newsize = 0;
204 int64_t i64val;
205 uint64_t u64val;
1815bff5 206 int mib[CTL_MAXNAME];
1a7e3f61 207 char *cp, *bufp, buf[BUFSIZ], *endptr, fmt[BUFSIZ];
1815bff5
A
208 u_int kind;
209
1a7e3f61 210 cp = buf;
ef8ad44b 211 if (snprintf(buf, BUFSIZ, "%s", string) >= BUFSIZ)
1a7e3f61
A
212 errx(1, "oid too long: '%s'", string);
213 bufp = strsep(&cp, "=");
214 if (cp != NULL) {
1815bff5
A
215 while (isspace(*cp))
216 cp++;
217 newval = cp;
218 newsize = strlen(cp);
1815bff5
A
219 }
220 len = name2oid(bufp, mib);
221
222 if (len < 0) {
1a7e3f61
A
223 if (iflag)
224 return;
225 if (qflag)
226 exit(1);
227 else
228 errx(1, "unknown oid '%s'", bufp);
1815bff5
A
229 }
230
231 if (oidfmt(mib, len, fmt, &kind))
1a7e3f61 232 err(1, "couldn't find format of oid '%s'", bufp);
1815bff5 233
1a7e3f61 234 if (newval == NULL || dflag) {
1815bff5 235 if ((kind & CTLTYPE) == CTLTYPE_NODE) {
1a7e3f61
A
236 if (dflag) {
237#ifdef __APPLE__
238 i = show_var(mib, len, 1);
239#else
240 i = show_var(mib, len);
241#endif
242 if (!i && !bflag)
243 putchar('\n');
244 }
1815bff5 245 sysctl_all(mib, len);
1815bff5 246 } else {
1a7e3f61 247#ifdef __APPLE__
c3a08f59 248 i = show_var(mib, len, 1);
1a7e3f61
A
249#else
250 i = show_var(mib, len);
251#endif
1815bff5
A
252 if (!i && !bflag)
253 putchar('\n');
254 }
255 } else {
256 if ((kind & CTLTYPE) == CTLTYPE_NODE)
257 errx(1, "oid '%s' isn't a leaf node", bufp);
258
1a7e3f61
A
259 if (!(kind & CTLFLAG_WR)) {
260 if (kind & CTLFLAG_TUN) {
261 warnx("oid '%s' is a read only tunable", bufp);
262 errx(1, "Tunable values are set in /boot/loader.conf");
263 } else {
264 errx(1, "oid '%s' is read only", bufp);
265 }
266 }
267
268 if ((kind & CTLTYPE) == CTLTYPE_INT ||
269 (kind & CTLTYPE) == CTLTYPE_UINT ||
270 (kind & CTLTYPE) == CTLTYPE_LONG ||
271 (kind & CTLTYPE) == CTLTYPE_ULONG ||
272 (kind & CTLTYPE) == CTLTYPE_S64 ||
273 (kind & CTLTYPE) == CTLTYPE_U64) {
274 if (strlen(newval) == 0)
275 errx(1, "empty numeric value");
276 }
277
1815bff5
A
278 switch (kind & CTLTYPE) {
279 case CTLTYPE_INT:
1a7e3f61
A
280 if (strcmp(fmt, "IK") == 0) {
281#ifndef __APPLE__
282 if (!set_IK(newval, &intval))
283#endif
284 errx(1, "invalid value '%s'",
285 (char *)newval);
286 } else {
287 intval = (int)strtol(newval, &endptr,
288 0);
289 if (endptr == newval || *endptr != '\0')
290 errx(1, "invalid integer '%s'",
291 (char *)newval);
1815bff5 292 }
1a7e3f61
A
293 newval = &intval;
294 newsize = sizeof(intval);
295 break;
296 case CTLTYPE_UINT:
297 uintval = (int) strtoul(newval, &endptr, 0);
298 if (endptr == newval || *endptr != '\0')
299 errx(1, "invalid unsigned integer '%s'",
300 (char *)newval);
301 newval = &uintval;
302 newsize = sizeof(uintval);
303 break;
304 case CTLTYPE_LONG:
305 longval = strtol(newval, &endptr, 0);
306 if (endptr == newval || *endptr != '\0')
307 errx(1, "invalid long integer '%s'",
308 (char *)newval);
309 newval = &longval;
310 newsize = sizeof(longval);
311 break;
312 case CTLTYPE_ULONG:
313 ulongval = strtoul(newval, &endptr, 0);
314 if (endptr == newval || *endptr != '\0')
315 errx(1, "invalid unsigned long integer"
316 " '%s'", (char *)newval);
317 newval = &ulongval;
318 newsize = sizeof(ulongval);
1815bff5
A
319 break;
320 case CTLTYPE_STRING:
321 break;
1a7e3f61
A
322 case CTLTYPE_S64:
323 i64val = strtoimax(newval, &endptr, 0);
324 if (endptr == newval || *endptr != '\0')
325 errx(1, "invalid int64_t '%s'",
326 (char *)newval);
327 newval = &i64val;
328 newsize = sizeof(i64val);
329 break;
330 case CTLTYPE_U64:
331 u64val = strtoumax(newval, &endptr, 0);
332 if (endptr == newval || *endptr != '\0')
333 errx(1, "invalid uint64_t '%s'",
334 (char *)newval);
335 newval = &u64val;
336 newsize = sizeof(u64val);
1815bff5 337 break;
1a7e3f61
A
338 case CTLTYPE_OPAQUE:
339 /* FALLTHROUGH */
1815bff5
A
340 default:
341 errx(1, "oid '%s' is type %d,"
342 " cannot set that", bufp,
343 kind & CTLTYPE);
344 }
345
1a7e3f61 346#ifdef __APPLE__
c3a08f59 347 i = show_var(mib, len, 1);
1a7e3f61
A
348#else
349 i = show_var(mib, len);
350#endif
1815bff5
A
351 if (sysctl(mib, len, 0, 0, newval, newsize) == -1) {
352 if (!i && !bflag)
353 putchar('\n');
354 switch (errno) {
1a7e3f61 355#ifdef __APPLE__
34d340d7 356 case ENOTSUP:
1a7e3f61
A
357#endif // __APPLE__
358 case EOPNOTSUPP:
359 errx(1, "%s: value is not available",
1815bff5
A
360 string);
361 case ENOTDIR:
1a7e3f61 362 errx(1, "%s: specification is incomplete",
1815bff5
A
363 string);
364 case ENOMEM:
1a7e3f61 365 errx(1, "%s: type is unknown to this program",
1815bff5
A
366 string);
367 default:
368 warn("%s", string);
1a7e3f61 369 warncount++;
1815bff5
A
370 return;
371 }
372 }
373 if (!bflag)
374 printf(" -> ");
375 i = nflag;
376 nflag = 1;
1a7e3f61 377#ifdef __APPLE__
c3a08f59 378 j = show_var(mib, len, 1);
1a7e3f61
A
379#else
380 j = show_var(mib, len);
381#endif
1815bff5
A
382 if (!j && !bflag)
383 putchar('\n');
384 nflag = i;
385 }
386}
387
388/* These functions will dump out various interesting structures. */
389
390static int
391S_clockinfo(int l2, void *p)
392{
393 struct clockinfo *ci = (struct clockinfo*)p;
8459d725
A
394
395 if (l2 != sizeof(*ci)) {
1a7e3f61 396 warnx("S_clockinfo %d != %zu", l2, sizeof(*ci));
8459d725
A
397 return (1);
398 }
1a7e3f61 399#ifdef __APPLE__
8459d725 400 printf(hflag ? "{ hz = %'d, tick = %'d, tickadj = %'d, profhz = %'d, stathz = %'d }" :
1a7e3f61
A
401 "{ hz = %d, tick = %d, tickadj = %d, profhz = %d, stathz = %d }",
402 ci->hz, ci->tick, ci->tickadj, ci->profhz, ci->stathz);
403#else
404 printf(hflag ? "{ hz = %'d, tick = %'d, profhz = %'d, stathz = %'d }" :
405 "{ hz = %d, tick = %d, profhz = %d, stathz = %d }",
406 ci->hz, ci->tick, ci->profhz, ci->stathz);
407#endif
1815bff5
A
408 return (0);
409}
410
411static int
412S_loadavg(int l2, void *p)
413{
414 struct loadavg *tv = (struct loadavg*)p;
415
8459d725 416 if (l2 != sizeof(*tv)) {
1a7e3f61 417 warnx("S_loadavg %d != %zu", l2, sizeof(*tv));
8459d725
A
418 return (1);
419 }
420 printf(hflag ? "{ %'.2f %'.2f %'.2f }" : "{ %.2f %.2f %.2f }",
1815bff5
A
421 (double)tv->ldavg[0]/(double)tv->fscale,
422 (double)tv->ldavg[1]/(double)tv->fscale,
423 (double)tv->ldavg[2]/(double)tv->fscale);
424 return (0);
425}
426
427static int
428S_timeval(int l2, void *p)
429{
430 struct timeval *tv = (struct timeval*)p;
431 time_t tv_sec;
432 char *p1, *p2;
433
8459d725 434 if (l2 != sizeof(*tv)) {
1a7e3f61 435 warnx("S_timeval %d != %zu", l2, sizeof(*tv));
8459d725
A
436 return (1);
437 }
438 printf(hflag ? "{ sec = %'jd, usec = %'ld } " :
439 "{ sec = %jd, usec = %ld } ",
440 (intmax_t)tv->tv_sec, (long)tv->tv_usec);
1815bff5
A
441 tv_sec = tv->tv_sec;
442 p1 = strdup(ctime(&tv_sec));
443 for (p2=p1; *p2 ; p2++)
444 if (*p2 == '\n')
445 *p2 = '\0';
446 fputs(p1, stdout);
8459d725 447 free(p1);
1815bff5
A
448 return (0);
449}
450
1a7e3f61
A
451#ifndef __APPLE__
452static int
453S_vmtotal(int l2, void *p)
454{
455 struct vmtotal *v = (struct vmtotal *)p;
456 int pageKilo = getpagesize() / 1024;
457
458 if (l2 != sizeof(*v)) {
459 warnx("S_vmtotal %d != %zu", l2, sizeof(*v));
460 return (1);
461 }
462
463 printf(
464 "\nSystem wide totals computed every five seconds:"
465 " (values in kilobytes)\n");
466 printf("===============================================\n");
467 printf(
468 "Processes:\t\t(RUNQ: %hd Disk Wait: %hd Page Wait: "
469 "%hd Sleep: %hd)\n",
470 v->t_rq, v->t_dw, v->t_pw, v->t_sl);
471 printf(
472 "Virtual Memory:\t\t(Total: %dK Active: %dK)\n",
473 v->t_vm * pageKilo, v->t_avm * pageKilo);
474 printf("Real Memory:\t\t(Total: %dK Active: %dK)\n",
475 v->t_rm * pageKilo, v->t_arm * pageKilo);
476 printf("Shared Virtual Memory:\t(Total: %dK Active: %dK)\n",
477 v->t_vmshr * pageKilo, v->t_avmshr * pageKilo);
478 printf("Shared Real Memory:\t(Total: %dK Active: %dK)\n",
479 v->t_rmshr * pageKilo, v->t_armshr * pageKilo);
480 printf("Free Memory:\t%dK\n", v->t_free * pageKilo);
481
482 return (0);
483}
484
485static int
486set_IK(const char *str, int *val)
487{
488 float temp;
489 int len, kelv;
490 const char *p;
491 char *endptr;
492
493 if ((len = strlen(str)) == 0)
494 return (0);
495 p = &str[len - 1];
496 if (*p == 'C' || *p == 'F') {
497 temp = strtof(str, &endptr);
498 if (endptr == str || endptr != p)
499 return (0);
500 if (*p == 'F')
501 temp = (temp - 32) * 5 / 9;
502 kelv = temp * 10 + 2732;
503 } else {
504 kelv = (int)strtol(str, &endptr, 10);
505 if (endptr == str || *endptr != '\0')
506 return (0);
507 }
508 *val = kelv;
509 return (1);
510}
511#endif // !__APPLE__
512
513#ifdef __APPLE__
34d340d7
A
514static int
515S_xswusage(int l2, void *p)
516{
8459d725 517 struct xsw_usage *xsu = (struct xsw_usage *)p;
cf37c299 518
8459d725
A
519 if (l2 != sizeof(*xsu)) {
520 warnx("S_xswusage %d != %ld", l2, sizeof(*xsu));
521 return (1);
522 }
34d340d7
A
523 fprintf(stdout,
524 "total = %.2fM used = %.2fM free = %.2fM %s",
8459d725
A
525 ((double)xsu->xsu_total) / (1024.0 * 1024.0),
526 ((double)xsu->xsu_used) / (1024.0 * 1024.0),
527 ((double)xsu->xsu_avail) / (1024.0 * 1024.0),
34d340d7 528 xsu->xsu_encrypted ? "(encrypted)" : "");
8459d725 529 return (0);
34d340d7
A
530}
531
1815bff5
A
532static int
533T_dev_t(int l2, void *p)
534{
535 dev_t *d = (dev_t *)p;
8459d725
A
536
537 if (l2 != sizeof(*d)) {
538 warnx("T_dev_T %d != %ld", l2, sizeof(*d));
539 return (1);
540 }
1815bff5
A
541 if ((int)(*d) != -1) {
542 if (minor(*d) > 255 || minor(*d) < 0)
543 printf("{ major = %d, minor = 0x%x }",
544 major(*d), minor(*d));
545 else
546 printf("{ major = %d, minor = %d }",
547 major(*d), minor(*d));
548 }
549 return (0);
550}
551
1a7e3f61
A
552static int
553S_quads(int len, void *p)
554{
555 size_t size = sizeof(int64_t);
556 if (len & (size-1)) {
557 return 1;
558 }
559 while (len > 0) {
560 int64_t i = *(int64_t *)p;
561 printf("%llu", i);
562 if (len > size) {
563 len -= size;
564 p = (uintptr_t)p + size;
565 printf(" ");
566 } else {
567 break;
568 }
569 }
570 return 0;
571}
572#endif // __APPLE__
573
1815bff5
A
574/*
575 * These functions uses a presently undocumented interface to the kernel
576 * to walk the tree and get the type so it can print the value.
577 * This interface is under work and consideration, and should probably
578 * be killed with a big axe by the first person who can find the time.
579 * (be aware though, that the proper interface isn't as obvious as it
580 * may seem, there are various conflicting requirements.
581 */
582
583static int
584name2oid(char *name, int *oidp)
585{
586 int oid[2];
587 int i;
588 size_t j;
589
1a7e3f61
A
590#ifdef __APPLE__
591 // Support for CTL_USER
592 const char *user = names[CTL_USER].ctl_name;
593 j = strlen(user);
594 if (!strncmp(name, user, j)) {
595 oidp[0] = CTL_USER;
596 if (name[j] == '.') {
597 for (i = 1; i < user_names_count; ++i) {
598 if (!strcmp(&name[j+1], user_names[i].ctl_name)) {
599 oidp[1] = i;
600 return 2;
601 }
602 }
603 return -1;
604 } else if (name[j] == 0) {
605 return 1;
606 }
607 return -1;
608 }
609#endif
610
1815bff5
A
611 oid[0] = 0;
612 oid[1] = 3;
613
1a7e3f61 614 j = CTL_MAXNAME * sizeof(int);
1815bff5 615 i = sysctl(oid, 2, oidp, &j, name, strlen(name));
1a7e3f61
A
616 if (i < 0)
617 return (i);
618 j /= sizeof(int);
619 return (int)j;
1815bff5
A
620}
621
622static int
623oidfmt(int *oid, int len, char *fmt, u_int *kind)
624{
625 int qoid[CTL_MAXNAME+2];
626 u_char buf[BUFSIZ];
627 int i;
628 size_t j;
629
630 qoid[0] = 0;
631 qoid[1] = 4;
632 memcpy(qoid + 2, oid, len * sizeof(int));
633
8459d725 634 j = sizeof(buf);
1815bff5 635 i = sysctl(qoid, len + 2, buf, &j, 0, 0);
1a7e3f61
A
636#ifdef __APPLE__
637 if (i && errno == ENOENT) {
638 // Support for CTL_USER
639 if (oid[0] == CTL_USER) {
640 if (len == 1) {
641 *kind = CTLTYPE_NODE;
642 return 0;
643 } else if (len == 2 && oid[1] < user_names_count) {
644 *kind = user_names[oid[1]].ctl_type;
645 return 0;
646 }
647 }
648 return 1;
8459d725 649 }
1a7e3f61
A
650#endif
651 if (i)
652 err(1, "sysctl fmt %d %zu %d", i, j, errno);
1815bff5
A
653
654 if (kind)
1a7e3f61
A
655#ifdef __APPLE__
656 memcpy(kind, buf, sizeof(*kind));
657#else
1815bff5 658 *kind = *(u_int *)buf;
1a7e3f61 659#endif
1815bff5
A
660
661 if (fmt)
662 strcpy(fmt, (char *)(buf + sizeof(u_int)));
1a7e3f61
A
663
664#ifdef __APPLE__
665 // Map Darwin sysctl types to FreeBSD types.
666 // - 0 with "I" -> CTLTYPE_INT
667 // - 0 with "S," -> CTLTYPE_STRUCT
668 // - CTLTYPE_INT with "IU" -> CTLTYPE_UINT
669 // - CTLTYPE_INT with "L" -> CTLTYPE_LONG
670 // - CTLTYPE_QUAD -> CTLTYPE_S64
671 // - CTLTYPE_QUAD with "*U" -> CTLTYPE_U64
672 if (kind) {
673 switch (*kind & CTLTYPE) {
674 case 0:
675 case CTLTYPE_INT:
676 if (buf[sizeof(u_int)] == 'S') {
677 *kind = (*kind & ~CTLTYPE) | CTLTYPE_STRUCT;
678 } else if (buf[sizeof(u_int)] == 'I') {
679 *kind = (*kind & ~CTLTYPE) | CTLTYPE_INT;
680 if (buf[sizeof(u_int)+1] == 'U') {
681 *kind = (*kind & ~CTLTYPE) | CTLTYPE_UINT;
682 }
683 } else if (buf[sizeof(u_int)] == 'L') {
684 *kind = (*kind & ~CTLTYPE) | CTLTYPE_LONG;
887d5eed
A
685 if (buf[sizeof(u_int)+1] == 'U') {
686 *kind = (*kind & ~CTLTYPE) | CTLTYPE_ULONG;
687 }
1a7e3f61
A
688 }
689 break;
690 case CTLTYPE_QUAD:
691 *kind = (*kind & ~CTLTYPE);
692 if (fmt && strchr(fmt, 'U')) {
693 *kind |= CTLTYPE_U64;
694 } else {
695 *kind |= CTLTYPE_S64;
696 }
697 break;
698 }
699 }
700#endif
cf37c299 701
8459d725 702 return (0);
1815bff5
A
703}
704
1a7e3f61
A
705static int ctl_sign[CTLTYPE+1] = {
706 [CTLTYPE_INT] = 1,
707 [CTLTYPE_LONG] = 1,
708 [CTLTYPE_S64] = 1,
709};
710
711static int ctl_size[CTLTYPE+1] = {
712 [CTLTYPE_INT] = sizeof(int),
713 [CTLTYPE_UINT] = sizeof(u_int),
714 [CTLTYPE_LONG] = sizeof(long),
715 [CTLTYPE_ULONG] = sizeof(u_long),
716 [CTLTYPE_S64] = sizeof(int64_t),
717 [CTLTYPE_U64] = sizeof(int64_t),
718};
719
1815bff5
A
720/*
721 * This formats and outputs the value of one variable
722 *
723 * Returns zero if anything was actually output.
724 * Returns one if didn't know what to do with this.
725 * Return minus one if we had errors.
726 */
1815bff5 727static int
1a7e3f61 728#ifdef __APPLE__
c3a08f59 729show_var(int *oid, int nlen, int show_masked)
1a7e3f61
A
730#else
731show_var(int *oid, int nlen)
732#endif
1815bff5 733{
1a7e3f61
A
734 u_char buf[BUFSIZ], *val, *oval, *p;
735 char name[BUFSIZ], *fmt;
736 const char *sep, *sep1;
1815bff5 737 int qoid[CTL_MAXNAME+2];
1a7e3f61
A
738 uintmax_t umv;
739 intmax_t mv;
740 int i, hexlen, sign, ctltype;
741 size_t intlen;
1815bff5
A
742 size_t j, len;
743 u_int kind;
1a7e3f61
A
744 int (*func)(int, void *);
745
746 /* Silence GCC. */
747 umv = mv = intlen = 0;
1815bff5 748
1a7e3f61
A
749 bzero(buf, BUFSIZ);
750 bzero(name, BUFSIZ);
1815bff5
A
751 qoid[0] = 0;
752 memcpy(qoid + 2, oid, nlen * sizeof(int));
c0bbac3a
A
753 fmt = (char *)buf;
754 oidfmt(oid, nlen, fmt, &kind);
755
756#ifdef __APPLE__
757 if (!show_masked && (kind & CTLFLAG_MASKED)) {
758 return (1);
759 }
760#endif
1815bff5 761
1a7e3f61
A
762#ifdef __APPLE__
763 // Support for CTL_USER
764 if (nlen >= 1 && oid[0] == CTL_USER) {
765 const char *user_name = "";
766 sep = "";
767 i = oid[1];
768 if (nlen == 2 && i > 0 && i < user_names_count) {
769 user_name = user_names[i].ctl_name;
770 sep = ".";
771 }
772 j = snprintf(name, sizeof(name), "%s%s%s",
773 names[CTL_USER].ctl_name, sep, user_name);
774 i = 0;
775 } else {
776#endif
1815bff5 777 qoid[1] = 1;
1a7e3f61 778 j = sizeof(name);
1815bff5
A
779 i = sysctl(qoid, nlen + 2, name, &j, 0, 0);
780 if (i || !j)
1a7e3f61
A
781 err(1, "sysctl name %d %zu %d", i, j, errno);
782#ifdef __APPLE__
783 }
784#endif
1815bff5 785
1a7e3f61
A
786 if (Nflag) {
787 printf("%s", name);
788 return (0);
789 }
790
791 if (eflag)
792 sep = "=";
793 else
794 sep = ": ";
795
796 if (dflag) { /* just print description */
797 qoid[1] = 5;
798 j = sizeof(buf);
799 i = sysctl(qoid, nlen + 2, buf, &j, 0, 0);
800 if (!nflag)
801 printf("%s%s", name, sep);
802 printf("%s", buf);
803 return (0);
804 }
1815bff5
A
805 /* find an estimate of how much we need for this var */
806 j = 0;
807 i = sysctl(oid, nlen, 0, &j, 0, 0);
808 j += j; /* we want to be sure :-) */
809
1a7e3f61
A
810 val = oval = malloc(j + 1);
811 if (val == NULL) {
812 warnx("malloc failed");
813 return (1);
814 }
1815bff5
A
815 len = j;
816 i = sysctl(oid, nlen, val, &len, 0, 0);
b51d5b5f 817 if (i || !len) {
1a7e3f61
A
818 free(oval);
819 return (1);
b51d5b5f 820 }
1815bff5
A
821
822 if (bflag) {
823 fwrite(val, 1, len, stdout);
1a7e3f61
A
824 free(oval);
825 return (0);
8459d725 826 }
1a7e3f61 827 val[len] = '\0';
1a7e3f61
A
828 p = val;
829 ctltype = (kind & CTLTYPE);
830 sign = ctl_sign[ctltype];
831 intlen = ctl_size[ctltype];
1815bff5 832
1a7e3f61
A
833 switch (ctltype) {
834 case CTLTYPE_STRING:
1815bff5 835 if (!nflag)
1a7e3f61
A
836 printf("%s%s", name, sep);
837 printf("%.*s", (int)len, p);
838 free(oval);
839 return (0);
1815bff5 840
1a7e3f61
A
841 case CTLTYPE_INT:
842 case CTLTYPE_UINT:
843 case CTLTYPE_LONG:
844 case CTLTYPE_ULONG:
845 case CTLTYPE_S64:
846 case CTLTYPE_U64:
c3a08f59 847 if (!nflag)
1a7e3f61
A
848 printf("%s%s", name, sep);
849 hexlen = (int)(2 + (intlen * CHAR_BIT + 3) / 4);
850 sep1 = "";
851 while (len >= intlen) {
852 switch (kind & CTLTYPE) {
853 case CTLTYPE_INT:
854 case CTLTYPE_UINT:
855 umv = *(u_int *)(void *)p;
856 mv = *(int *)(void *)p;
857 break;
858 case CTLTYPE_LONG:
859 case CTLTYPE_ULONG:
860 umv = *(u_long *)(void *)p;
861 mv = *(long *)(void *)p;
862 break;
863 case CTLTYPE_S64:
864 case CTLTYPE_U64:
865 umv = *(uint64_t *)(void *)p;
866 mv = *(int64_t *)(void *)p;
867 break;
868 }
869 fputs(sep1, stdout);
870 if (xflag)
871 printf("%#0*jx", hexlen, umv);
872 else if (!sign)
873 printf(hflag ? "%'ju" : "%ju", umv);
874 else if (fmt[1] == 'K') {
875 if (mv < 0)
876 printf("%jd", mv);
877 else
878 printf("%.1fC", (mv - 2732.0) / 10);
879 } else
880 printf(hflag ? "%'jd" : "%jd", mv);
881 sep1 = " ";
882 len -= intlen;
883 p += intlen;
c3a08f59 884 }
1a7e3f61
A
885 free(oval);
886 return (0);
c3a08f59 887
1a7e3f61 888 case CTLTYPE_OPAQUE:
1815bff5 889 i = 0;
1a7e3f61
A
890 if (strcmp(fmt, "S,clockinfo") == 0)
891 func = S_clockinfo;
892 else if (strcmp(fmt, "S,timeval") == 0)
893 func = S_timeval;
894 else if (strcmp(fmt, "S,loadavg") == 0)
895 func = S_loadavg;
896#ifdef __APPLE__
897 else if (!strcmp(fmt, "S,xsw_usage"))
898 func = S_xswusage;
899 else if (!strcmp(fmt, "T,dev_t"))
900 func = T_dev_t;
901 else if (!strcmp(fmt, "Q"))
902 func = S_quads;
903#else // !__APPLE__
904 else if (strcmp(fmt, "S,vmtotal") == 0)
905 func = S_vmtotal;
906#endif // !__APPLE__
907 else
908 func = NULL;
1815bff5
A
909 if (func) {
910 if (!nflag)
1a7e3f61
A
911 printf("%s%s", name, sep);
912 i = (*func)((int)len, p);
913 free(oval);
914 return (i);
1815bff5 915 }
1a7e3f61 916 /* FALLTHROUGH */
1815bff5 917 default:
1a7e3f61
A
918 if (!oflag && !xflag) {
919 free(oval);
920 return (1);
b51d5b5f 921 }
1815bff5 922 if (!nflag)
1a7e3f61
A
923 printf("%s%s", name, sep);
924 printf("Format:%s Length:%zu Dump:0x", fmt, len);
925 while (len-- && (xflag || p < val + 16))
1815bff5 926 printf("%02x", *p++);
1a7e3f61 927 if (!xflag && len > 16)
1815bff5 928 printf("...");
1a7e3f61
A
929 free(oval);
930 return (0);
1815bff5 931 }
1a7e3f61
A
932 free(oval);
933 return (1);
934}
b51d5b5f 935
1a7e3f61
A
936#ifdef __APPLE__
937// Support for CTL_USER
938static void
939sysctl_all_user(int *oid, int len)
940{
941 int i, j;
942 if (len > 1 || (len == 1 && oid[0] != CTL_USER)) {
943 return;
944 }
945 for (i = 0; i < user_names_count; ++i) {
946 int oid[2] = { CTL_USER, i };
947 j = show_var(oid, 2, 0);
948 if (!j && !bflag) {
949 putchar('\n');
950 }
951 }
1815bff5 952}
1a7e3f61 953#endif
1815bff5
A
954
955static int
1a7e3f61 956sysctl_all(int *oid, int len)
1815bff5 957{
c0bbac3a
A
958#ifdef __APPLE__
959#endif
960
1815bff5
A
961 int name1[22], name2[22];
962 int i, j;
963 size_t l1, l2;
964
1a7e3f61
A
965#ifdef __APPLE__
966 sysctl_all_user(oid, len);
967#endif
968
1815bff5
A
969 name1[0] = 0;
970 name1[1] = 2;
971 l1 = 2;
972 if (len) {
1a7e3f61 973 memcpy(name1+2, oid, len * sizeof(int));
1815bff5
A
974 l1 += len;
975 } else {
976 name1[2] = 1;
977 l1++;
978 }
1a7e3f61
A
979 for (;;) {
980 l2 = sizeof(name2);
981 j = sysctl(name1, (u_int)l1, name2, &l2, 0, 0);
1815bff5
A
982 if (j < 0) {
983 if (errno == ENOENT)
1a7e3f61 984 return (0);
1815bff5 985 else
1a7e3f61 986 err(1, "sysctl(getnext) %d %zu", j, l2);
1815bff5
A
987 }
988
1a7e3f61 989 l2 /= sizeof(int);
1815bff5 990
1a7e3f61
A
991 if (len < 0 || l2 < (unsigned int)len)
992 return (0);
1815bff5
A
993
994 for (i = 0; i < len; i++)
995 if (name2[i] != oid[i])
1a7e3f61 996 return (0);
1815bff5 997
1a7e3f61
A
998#ifdef __APPLE__
999 i = show_var(name2, (u_int)l2, 0);
1000#else
1001 i = show_var(name2, (u_int)l2);
1002#endif
1815bff5
A
1003 if (!i && !bflag)
1004 putchar('\n');
1005
1a7e3f61 1006 memcpy(name1+2, name2, l2 * sizeof(int));
1815bff5
A
1007 l1 = 2 + l2;
1008 }
1009}