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