]>
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> | |
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 |
70 | static int aflag, bflag, dflag, eflag, hflag, iflag; |
71 | static int Nflag, nflag, oflag, qflag, xflag, warncount; | |
1815bff5 | 72 | |
1815bff5 | 73 | static int oidfmt(int *, int, char *, u_int *); |
1a7e3f61 A |
74 | static void parse(const char *); |
75 | #ifdef __APPLE__ | |
c3a08f59 | 76 | static int show_var(int *, int, int); |
1a7e3f61 A |
77 | #else |
78 | static int show_var(int *, int); | |
79 | #endif | |
80 | static int sysctl_all(int *oid, int len); | |
1815bff5 A |
81 | static int name2oid(char *, int *); |
82 | ||
1a7e3f61 A |
83 | #ifndef __APPLE__ |
84 | static 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 | |
98 | const struct ctlname names[] = CTL_NAMES; | |
99 | const struct ctlname user_names[] = CTL_USER_NAMES; | |
100 | const int user_names_count = sizeof(user_names) / sizeof(*user_names); | |
101 | #endif | |
1815bff5 | 102 | |
1a7e3f61 A |
103 | static void |
104 | usage(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 |
113 | int |
114 | main(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 | */ | |
194 | static void | |
1a7e3f61 | 195 | parse(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 | ||
390 | static int | |
391 | S_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 | ||
411 | static int | |
412 | S_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 | ||
427 | static int | |
428 | S_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__ |
452 | static int | |
453 | S_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 | ||
485 | static int | |
486 | set_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 |
514 | static int |
515 | S_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 |
532 | static int |
533 | T_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 |
552 | static int |
553 | S_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 | ||
583 | static int | |
584 | name2oid(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 | ||
622 | static int | |
623 | oidfmt(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 |
705 | static int ctl_sign[CTLTYPE+1] = { |
706 | [CTLTYPE_INT] = 1, | |
707 | [CTLTYPE_LONG] = 1, | |
708 | [CTLTYPE_S64] = 1, | |
709 | }; | |
710 | ||
711 | static 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 | 727 | static int |
1a7e3f61 | 728 | #ifdef __APPLE__ |
c3a08f59 | 729 | show_var(int *oid, int nlen, int show_masked) |
1a7e3f61 A |
730 | #else |
731 | show_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 | |
938 | static void | |
939 | sysctl_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 | |
955 | static int | |
1a7e3f61 | 956 | sysctl_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 | } |