source: rtems-libbsd/freebsd/sbin/sysctl/sysctl.c @ 0577772

55-freebsd-126-freebsd-12
Last change on this file since 0577772 was 0577772, checked in by Sebastian Huber <sebastian.huber@…>, on 01/09/17 at 13:47:04

Update to FreeBSD head 2017-01-09

Git mirror commit 1f8e4a995a6ede4bdb24e6d335ccda2bdb0175ab.

  • Property mode set to 100644
File size: 26.0 KB
Line 
1#include <machine/rtems-bsd-user-space.h>
2
3#ifdef __rtems__
4#include "rtems-bsd-sysctl-namespace.h"
5#endif /* __rtems__ */
6
7/*
8 * Copyright (c) 1993
9 *      The Regents of the University of California.  All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 *    notice, this list of conditions and the following disclaimer in the
18 *    documentation and/or other materials provided with the distribution.
19 * 4. Neither the name of the University nor the names of its contributors
20 *    may be used to endorse or promote products derived from this software
21 *    without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 */
35
36#ifndef lint
37static const char copyright[] =
38"@(#) Copyright (c) 1993\n\
39        The Regents of the University of California.  All rights reserved.\n";
40#endif /* not lint */
41
42#ifndef lint
43#if 0
44static char sccsid[] = "@(#)from: sysctl.c      8.1 (Berkeley) 6/6/93";
45#endif
46static const char rcsid[] =
47  "$FreeBSD$";
48#endif /* not lint */
49
50#ifdef __rtems__
51#define __need_getopt_newlib
52#include <getopt.h>
53#include <machine/rtems-bsd-program.h>
54#include <machine/rtems-bsd-commands.h>
55#endif /* __rtems__ */
56#include <rtems/bsd/sys/param.h>
57#include <sys/time.h>
58#include <rtems/bsd/sys/resource.h>
59#include <sys/stat.h>
60#include <sys/sysctl.h>
61#include <sys/vmmeter.h>
62
63#ifdef __amd64__
64#include <sys/efi.h>
65#include <machine/metadata.h>
66#endif
67
68#if defined(__amd64__) || defined(__i386__)
69#include <machine/pc/bios.h>
70#endif
71
72#include <assert.h>
73#include <ctype.h>
74#include <err.h>
75#include <errno.h>
76#include <inttypes.h>
77#include <locale.h>
78#include <stdio.h>
79#include <stdlib.h>
80#include <string.h>
81#include <sysexits.h>
82#include <unistd.h>
83#ifdef __rtems__
84#include "rtems-bsd-sysctl-sysctl-data.h"
85#endif /* __rtems__ */
86
87static const char *conffile;
88
89static int      aflag, bflag, Bflag, dflag, eflag, hflag, iflag;
90static int      Nflag, nflag, oflag, qflag, tflag, Tflag, Wflag, xflag;
91
92static int      oidfmt(int *, int, char *, u_int *);
93static int      parsefile(const char *);
94static int      parse(const char *, int);
95static int      show_var(int *, int);
96static int      sysctl_all(int *oid, int len);
97static int      name2oid(const char *, int *);
98
99static int      strIKtoi(const char *, char **, const char *);
100
101static int ctl_sign[CTLTYPE+1] = {
102        [CTLTYPE_INT] = 1,
103        [CTLTYPE_LONG] = 1,
104        [CTLTYPE_S8] = 1,
105        [CTLTYPE_S16] = 1,
106        [CTLTYPE_S32] = 1,
107        [CTLTYPE_S64] = 1,
108};
109
110static int ctl_size[CTLTYPE+1] = {
111        [CTLTYPE_INT] = sizeof(int),
112        [CTLTYPE_UINT] = sizeof(u_int),
113        [CTLTYPE_LONG] = sizeof(long),
114        [CTLTYPE_ULONG] = sizeof(u_long),
115        [CTLTYPE_S8] = sizeof(int8_t),
116        [CTLTYPE_S16] = sizeof(int16_t),
117        [CTLTYPE_S32] = sizeof(int32_t),
118        [CTLTYPE_S64] = sizeof(int64_t),
119        [CTLTYPE_U8] = sizeof(uint8_t),
120        [CTLTYPE_U16] = sizeof(uint16_t),
121        [CTLTYPE_U32] = sizeof(uint32_t),
122        [CTLTYPE_U64] = sizeof(uint64_t),
123};
124
125static const char *ctl_typename[CTLTYPE+1] = {
126        [CTLTYPE_INT] = "integer",
127        [CTLTYPE_UINT] = "unsigned integer",
128        [CTLTYPE_LONG] = "long integer",
129        [CTLTYPE_ULONG] = "unsigned long",
130        [CTLTYPE_U8] = "uint8_t",
131        [CTLTYPE_U16] = "uint16_t",
132        [CTLTYPE_U32] = "uint32_t",
133        [CTLTYPE_U64] = "uint64_t",
134        [CTLTYPE_S8] = "int8_t",
135        [CTLTYPE_S16] = "int16_t",
136        [CTLTYPE_S32] = "int32_t",
137        [CTLTYPE_S64] = "int64_t",
138        [CTLTYPE_NODE] = "node",
139        [CTLTYPE_STRING] = "string",
140        [CTLTYPE_OPAQUE] = "opaque",
141};
142
143static void
144usage(void)
145{
146
147        (void)fprintf(stderr, "%s\n%s\n",
148            "usage: sysctl [-bdehiNnoqTtWx] [ -B <bufsize> ] [-f filename] name[=value] ...",
149            "       sysctl [-bdehNnoqTtWx] [ -B <bufsize> ] -a");
150        exit(1);
151}
152
153#ifdef __rtems__
154static int main(int argc, char *argv[]);
155
156RTEMS_LINKER_RWSET(bsd_prog_sysctl, char);
157
158int
159rtems_bsd_command_sysctl(int argc, char *argv[])
160{
161        int exit_code;
162        void *data_begin;
163        size_t data_size;
164
165        data_begin = RTEMS_LINKER_SET_BEGIN(bsd_prog_sysctl);
166        data_size = RTEMS_LINKER_SET_SIZE(bsd_prog_sysctl);
167
168        rtems_bsd_program_lock();
169        exit_code = rtems_bsd_program_call_main_with_data_restore("sysctl",
170            main, argc, argv, data_begin, data_size);
171        rtems_bsd_program_unlock();
172
173        return exit_code;
174}
175#endif /* __rtems__ */
176int
177main(int argc, char **argv)
178{
179        int ch;
180        int warncount = 0;
181
182        setlocale(LC_NUMERIC, "");
183        setbuf(stdout,0);
184        setbuf(stderr,0);
185
186        while ((ch = getopt(argc, argv, "AabB:def:hiNnoqtTwWxX")) != -1) {
187                switch (ch) {
188                case 'A':
189                        /* compatibility */
190                        aflag = oflag = 1;
191                        break;
192                case 'a':
193                        aflag = 1;
194                        break;
195                case 'b':
196                        bflag = 1;
197                        break;
198                case 'B':
199                        Bflag = strtol(optarg, NULL, 0);
200                        break;
201                case 'd':
202                        dflag = 1;
203                        break;
204                case 'e':
205                        eflag = 1;
206                        break;
207                case 'f':
208                        conffile = optarg;
209                        break;
210                case 'h':
211                        hflag = 1;
212                        break;
213                case 'i':
214                        iflag = 1;
215                        break;
216                case 'N':
217                        Nflag = 1;
218                        break;
219                case 'n':
220                        nflag = 1;
221                        break;
222                case 'o':
223                        oflag = 1;
224                        break;
225                case 'q':
226                        qflag = 1;
227                        break;
228                case 't':
229                        tflag = 1;
230                        break;
231                case 'T':
232                        Tflag = 1;
233                        break;
234                case 'w':
235                        /* compatibility */
236                        /* ignored */
237                        break;
238                case 'W':
239                        Wflag = 1;
240                        break;
241                case 'X':
242                        /* compatibility */
243                        aflag = xflag = 1;
244                        break;
245                case 'x':
246                        xflag = 1;
247                        break;
248                default:
249                        usage();
250                }
251        }
252        argc -= optind;
253        argv += optind;
254
255        if (Nflag && nflag)
256                usage();
257        if (aflag && argc == 0)
258                exit(sysctl_all(0, 0));
259        if (argc == 0 && conffile == NULL)
260                usage();
261
262        warncount = 0;
263        if (conffile != NULL)
264                warncount += parsefile(conffile);
265
266        while (argc-- > 0)
267                warncount += parse(*argv++, 0);
268
269        return (warncount);
270}
271
272/*
273 * Parse a name into a MIB entry.
274 * Lookup and print out the MIB entry if it exists.
275 * Set a new value if requested.
276 */
277static int
278parse(const char *string, int lineno)
279{
280        int len, i, j;
281        const void *newval;
282        const char *newvalstr = NULL;
283        int8_t i8val;
284        uint8_t u8val;
285        int16_t i16val;
286        uint16_t u16val;
287        int32_t i32val;
288        uint32_t u32val;
289        int intval;
290        unsigned int uintval;
291        long longval;
292        unsigned long ulongval;
293        size_t newsize = Bflag;
294        int64_t i64val;
295        uint64_t u64val;
296        int mib[CTL_MAXNAME];
297        char *cp, *bufp, buf[BUFSIZ], *endptr = NULL, fmt[BUFSIZ], line[BUFSIZ];
298        u_int kind;
299
300        if (lineno)
301                snprintf(line, sizeof(line), " at line %d", lineno);
302        else
303                line[0] = '\0';
304
305        cp = buf;
306        if (snprintf(buf, BUFSIZ, "%s", string) >= BUFSIZ) {
307                warnx("oid too long: '%s'%s", string, line);
308                return (1);
309        }
310        bufp = strsep(&cp, "=:");
311        if (cp != NULL) {
312                /* Tflag just lists tunables, do not allow assignment */
313                if (Tflag || Wflag) {
314                        warnx("Can't set variables when using -T or -W");
315                        usage();
316                }
317                while (isspace(*cp))
318                        cp++;
319                /* Strip a pair of " or ' if any. */
320                switch (*cp) {
321                case '\"':
322                case '\'':
323                        if (cp[strlen(cp) - 1] == *cp)
324                                cp[strlen(cp) - 1] = '\0';
325                        cp++;
326                }
327                newvalstr = cp;
328                newsize = strlen(cp);
329        }
330        /* Trim spaces */
331        cp = bufp + strlen(bufp) - 1;
332        while (cp >= bufp && isspace((int)*cp)) {
333                *cp = '\0';
334                cp--;
335        }
336        len = name2oid(bufp, mib);
337
338        if (len < 0) {
339                if (iflag)
340                        return (0);
341                if (qflag)
342                        return (1);
343                else {
344                        if (errno == ENOENT) {
345                                warnx("unknown oid '%s'%s", bufp, line);
346                        } else {
347                                warn("unknown oid '%s'%s", bufp, line);
348                        }
349                        return (1);
350                }
351        }
352
353        if (oidfmt(mib, len, fmt, &kind)) {
354                warn("couldn't find format of oid '%s'%s", bufp, line);
355                if (iflag)
356                        return (1);
357                else
358                        exit(1);
359        }
360
361        if (newvalstr == NULL || dflag) {
362                if ((kind & CTLTYPE) == CTLTYPE_NODE) {
363                        if (dflag) {
364                                i = show_var(mib, len);
365                                if (!i && !bflag)
366                                        putchar('\n');
367                        }
368                        sysctl_all(mib, len);
369                } else {
370                        i = show_var(mib, len);
371                        if (!i && !bflag)
372                                putchar('\n');
373                }
374        } else {
375                if ((kind & CTLTYPE) == CTLTYPE_NODE) {
376                        warnx("oid '%s' isn't a leaf node%s", bufp, line);
377                        return (1);
378                }
379
380                if (!(kind & CTLFLAG_WR)) {
381                        if (kind & CTLFLAG_TUN) {
382                                warnx("oid '%s' is a read only tunable%s", bufp, line);
383                                warnx("Tunable values are set in /boot/loader.conf");
384                        } else
385                                warnx("oid '%s' is read only%s", bufp, line);
386                        return (1);
387                }
388
389                switch (kind & CTLTYPE) {
390                case CTLTYPE_INT:
391                case CTLTYPE_UINT:
392                case CTLTYPE_LONG:
393                case CTLTYPE_ULONG:
394                case CTLTYPE_S8:
395                case CTLTYPE_S16:
396                case CTLTYPE_S32:
397                case CTLTYPE_S64:
398                case CTLTYPE_U8:
399                case CTLTYPE_U16:
400                case CTLTYPE_U32:
401                case CTLTYPE_U64:
402                        if (strlen(newvalstr) == 0) {
403                                warnx("empty numeric value");
404                                return (1);
405                        }
406                        /* FALLTHROUGH */
407                case CTLTYPE_STRING:
408                        break;
409                default:
410                        warnx("oid '%s' is type %d,"
411                                " cannot set that%s", bufp,
412                                kind & CTLTYPE, line);
413                        return (1);
414                }
415
416                errno = 0;
417
418                switch (kind & CTLTYPE) {
419                        case CTLTYPE_INT:
420                                if (strncmp(fmt, "IK", 2) == 0)
421                                        intval = strIKtoi(newvalstr, &endptr, fmt);
422                                else
423                                        intval = (int)strtol(newvalstr, &endptr,
424                                            0);
425                                newval = &intval;
426                                newsize = sizeof(intval);
427                                break;
428                        case CTLTYPE_UINT:
429                                uintval = (int) strtoul(newvalstr, &endptr, 0);
430                                newval = &uintval;
431                                newsize = sizeof(uintval);
432                                break;
433                        case CTLTYPE_LONG:
434                                longval = strtol(newvalstr, &endptr, 0);
435                                newval = &longval;
436                                newsize = sizeof(longval);
437                                break;
438                        case CTLTYPE_ULONG:
439                                ulongval = strtoul(newvalstr, &endptr, 0);
440                                newval = &ulongval;
441                                newsize = sizeof(ulongval);
442                                break;
443                        case CTLTYPE_STRING:
444                                newval = newvalstr;
445                                break;
446                        case CTLTYPE_S8:
447                                i8val = (int8_t)strtol(newvalstr, &endptr, 0);
448                                newval = &i8val;
449                                newsize = sizeof(i8val);
450                                break;
451                        case CTLTYPE_S16:
452                                i16val = (int16_t)strtol(newvalstr, &endptr,
453                                    0);
454                                newval = &i16val;
455                                newsize = sizeof(i16val);
456                                break;
457                        case CTLTYPE_S32:
458                                i32val = (int32_t)strtol(newvalstr, &endptr,
459                                    0);
460                                newval = &i32val;
461                                newsize = sizeof(i32val);
462                                break;
463                        case CTLTYPE_S64:
464                                i64val = strtoimax(newvalstr, &endptr, 0);
465                                newval = &i64val;
466                                newsize = sizeof(i64val);
467                                break;
468                        case CTLTYPE_U8:
469                                u8val = (uint8_t)strtoul(newvalstr, &endptr, 0);
470                                newval = &u8val;
471                                newsize = sizeof(u8val);
472                                break;
473                        case CTLTYPE_U16:
474                                u16val = (uint16_t)strtoul(newvalstr, &endptr,
475                                    0);
476                                newval = &u16val;
477                                newsize = sizeof(u16val);
478                                break;
479                        case CTLTYPE_U32:
480                                u32val = (uint32_t)strtoul(newvalstr, &endptr,
481                                    0);
482                                newval = &u32val;
483                                newsize = sizeof(u32val);
484                                break;
485                        case CTLTYPE_U64:
486                                u64val = strtoumax(newvalstr, &endptr, 0);
487                                newval = &u64val;
488                                newsize = sizeof(u64val);
489                                break;
490                        default:
491                                /* NOTREACHED */
492                                abort();
493                }
494
495                if (errno != 0 || endptr == newvalstr ||
496                    (endptr != NULL && *endptr != '\0')) {
497                        warnx("invalid %s '%s'%s", ctl_typename[kind & CTLTYPE],
498                            newvalstr, line);
499                        return (1);
500                }
501
502                i = show_var(mib, len);
503                if (sysctl(mib, len, 0, 0, newval, newsize) == -1) {
504                        if (!i && !bflag)
505                                putchar('\n');
506                        switch (errno) {
507                        case EOPNOTSUPP:
508                                warnx("%s: value is not available%s",
509                                        string, line);
510                                return (1);
511                        case ENOTDIR:
512                                warnx("%s: specification is incomplete%s",
513                                        string, line);
514                                return (1);
515                        case ENOMEM:
516                                warnx("%s: type is unknown to this program%s",
517                                        string, line);
518                                return (1);
519                        default:
520                                warn("%s%s", string, line);
521                                return (1);
522                        }
523                }
524                if (!bflag)
525                        printf(" -> ");
526                i = nflag;
527                nflag = 1;
528                j = show_var(mib, len);
529                if (!j && !bflag)
530                        putchar('\n');
531                nflag = i;
532        }
533
534        return (0);
535}
536
537static int
538parsefile(const char *filename)
539{
540        FILE *file;
541        char line[BUFSIZ], *p, *pq, *pdq;
542        int warncount = 0, lineno = 0;
543
544        file = fopen(filename, "r");
545        if (file == NULL)
546                err(EX_NOINPUT, "%s", filename);
547        while (fgets(line, sizeof(line), file) != NULL) {
548                lineno++;
549                p = line;
550                pq = strchr(line, '\'');
551                pdq = strchr(line, '\"');
552                /* Replace the first # with \0. */
553                while((p = strchr(p, '#')) != NULL) {
554                        if (pq != NULL && p > pq) {
555                                if ((p = strchr(pq+1, '\'')) != NULL)
556                                        *(++p) = '\0';
557                                break;
558                        } else if (pdq != NULL && p > pdq) {
559                                if ((p = strchr(pdq+1, '\"')) != NULL)
560                                        *(++p) = '\0';
561                                break;
562                        } else if (p == line || *(p-1) != '\\') {
563                                *p = '\0';
564                                break;
565                        }
566                        p++;
567                }
568                /* Trim spaces */
569                p = line + strlen(line) - 1;
570                while (p >= line && isspace((int)*p)) {
571                        *p = '\0';
572                        p--;
573                }
574                p = line;
575                while (isspace((int)*p))
576                        p++;
577                if (*p == '\0')
578                        continue;
579                else
580                        warncount += parse(p, lineno);
581        }
582        fclose(file);
583
584        return (warncount);
585}
586
587/* These functions will dump out various interesting structures. */
588
589#ifndef __rtems__
590static int
591S_clockinfo(size_t l2, void *p)
592{
593        struct clockinfo *ci = (struct clockinfo*)p;
594
595        if (l2 != sizeof(*ci)) {
596                warnx("S_clockinfo %zu != %zu", l2, sizeof(*ci));
597                return (1);
598        }
599        printf(hflag ? "{ hz = %'d, tick = %'d, profhz = %'d, stathz = %'d }" :
600                "{ hz = %d, tick = %d, profhz = %d, stathz = %d }",
601                ci->hz, ci->tick, ci->profhz, ci->stathz);
602        return (0);
603}
604#endif /* __rtems__ */
605
606static int
607S_loadavg(size_t l2, void *p)
608{
609        struct loadavg *tv = (struct loadavg*)p;
610
611        if (l2 != sizeof(*tv)) {
612                warnx("S_loadavg %zu != %zu", l2, sizeof(*tv));
613                return (1);
614        }
615        printf(hflag ? "{ %'.2f %'.2f %'.2f }" : "{ %.2f %.2f %.2f }",
616                (double)tv->ldavg[0]/(double)tv->fscale,
617                (double)tv->ldavg[1]/(double)tv->fscale,
618                (double)tv->ldavg[2]/(double)tv->fscale);
619        return (0);
620}
621
622static int
623S_timeval(size_t l2, void *p)
624{
625        struct timeval *tv = (struct timeval*)p;
626        time_t tv_sec;
627        char *p1, *p2;
628
629        if (l2 != sizeof(*tv)) {
630                warnx("S_timeval %zu != %zu", l2, sizeof(*tv));
631                return (1);
632        }
633        printf(hflag ? "{ sec = %'jd, usec = %'ld } " :
634                "{ sec = %jd, usec = %ld } ",
635                (intmax_t)tv->tv_sec, tv->tv_usec);
636        tv_sec = tv->tv_sec;
637        p1 = strdup(ctime(&tv_sec));
638        for (p2=p1; *p2 ; p2++)
639                if (*p2 == '\n')
640                        *p2 = '\0';
641        fputs(p1, stdout);
642        free(p1);
643        return (0);
644}
645
646static int
647S_vmtotal(size_t l2, void *p)
648{
649        struct vmtotal *v = (struct vmtotal *)p;
650        int pageKilo = getpagesize() / 1024;
651
652        if (l2 != sizeof(*v)) {
653                warnx("S_vmtotal %zu != %zu", l2, sizeof(*v));
654                return (1);
655        }
656
657        printf(
658            "\nSystem wide totals computed every five seconds:"
659            " (values in kilobytes)\n");
660        printf("===============================================\n");
661        printf(
662            "Processes:\t\t(RUNQ: %hd Disk Wait: %hd Page Wait: "
663            "%hd Sleep: %hd)\n",
664            v->t_rq, v->t_dw, v->t_pw, v->t_sl);
665        printf(
666            "Virtual Memory:\t\t(Total: %jdK Active: %jdK)\n",
667            (intmax_t)v->t_vm * pageKilo, (intmax_t)v->t_avm * pageKilo);
668        printf("Real Memory:\t\t(Total: %jdK Active: %jdK)\n",
669            (intmax_t)v->t_rm * pageKilo, (intmax_t)v->t_arm * pageKilo);
670        printf("Shared Virtual Memory:\t(Total: %jdK Active: %jdK)\n",
671            (intmax_t)v->t_vmshr * pageKilo, (intmax_t)v->t_avmshr * pageKilo);
672        printf("Shared Real Memory:\t(Total: %jdK Active: %jdK)\n",
673            (intmax_t)v->t_rmshr * pageKilo, (intmax_t)v->t_armshr * pageKilo);
674        printf("Free Memory:\t%jdK", (intmax_t)v->t_free * pageKilo);
675
676        return (0);
677}
678
679#ifdef __amd64__
680static int
681S_efi_map(size_t l2, void *p)
682{
683        struct efi_map_header *efihdr;
684        struct efi_md *map;
685        const char *type;
686        size_t efisz;
687        int ndesc, i;
688
689        static const char *types[] = {
690                "Reserved",
691                "LoaderCode",
692                "LoaderData",
693                "BootServicesCode",
694                "BootServicesData",
695                "RuntimeServicesCode",
696                "RuntimeServicesData",
697                "ConventionalMemory",
698                "UnusableMemory",
699                "ACPIReclaimMemory",
700                "ACPIMemoryNVS",
701                "MemoryMappedIO",
702                "MemoryMappedIOPortSpace",
703                "PalCode"
704        };
705
706        /*
707         * Memory map data provided by UEFI via the GetMemoryMap
708         * Boot Services API.
709         */
710        if (l2 < sizeof(*efihdr)) {
711                warnx("S_efi_map length less than header");
712                return (1);
713        }
714        efihdr = p;
715        efisz = (sizeof(struct efi_map_header) + 0xf) & ~0xf;
716        map = (struct efi_md *)((uint8_t *)efihdr + efisz);
717
718        if (efihdr->descriptor_size == 0)
719                return (0);
720        if (l2 != efisz + efihdr->memory_size) {
721                warnx("S_efi_map length mismatch %zu vs %zu", l2, efisz +
722                    efihdr->memory_size);
723                return (1);
724        }               
725        ndesc = efihdr->memory_size / efihdr->descriptor_size;
726
727        printf("\n%23s %12s %12s %8s %4s",
728            "Type", "Physical", "Virtual", "#Pages", "Attr");
729
730        for (i = 0; i < ndesc; i++,
731            map = efi_next_descriptor(map, efihdr->descriptor_size)) {
732                if (map->md_type <= EFI_MD_TYPE_PALCODE)
733                        type = types[map->md_type];
734                else
735                        type = "<INVALID>";
736                printf("\n%23s %012lx %12p %08lx ", type, map->md_phys,
737                    map->md_virt, map->md_pages);
738                if (map->md_attr & EFI_MD_ATTR_UC)
739                        printf("UC ");
740                if (map->md_attr & EFI_MD_ATTR_WC)
741                        printf("WC ");
742                if (map->md_attr & EFI_MD_ATTR_WT)
743                        printf("WT ");
744                if (map->md_attr & EFI_MD_ATTR_WB)
745                        printf("WB ");
746                if (map->md_attr & EFI_MD_ATTR_UCE)
747                        printf("UCE ");
748                if (map->md_attr & EFI_MD_ATTR_WP)
749                        printf("WP ");
750                if (map->md_attr & EFI_MD_ATTR_RP)
751                        printf("RP ");
752                if (map->md_attr & EFI_MD_ATTR_XP)
753                        printf("XP ");
754                if (map->md_attr & EFI_MD_ATTR_RT)
755                        printf("RUNTIME");
756        }
757        return (0);
758}
759#endif
760
761#if defined(__amd64__) || defined(__i386__)
762static int
763S_bios_smap_xattr(size_t l2, void *p)
764{
765        struct bios_smap_xattr *smap, *end;
766
767        if (l2 % sizeof(*smap) != 0) {
768                warnx("S_bios_smap_xattr %zu is not a multiple of %zu", l2,
769                    sizeof(*smap));
770                return (1);
771        }
772
773        end = (struct bios_smap_xattr *)((char *)p + l2);
774        for (smap = p; smap < end; smap++)
775                printf("\nSMAP type=%02x, xattr=%02x, base=%016jx, len=%016jx",
776                    smap->type, smap->xattr, (uintmax_t)smap->base,
777                    (uintmax_t)smap->length);
778        return (0);
779}
780#endif
781
782static int
783strIKtoi(const char *str, char **endptrp, const char *fmt)
784{
785        int kelv;
786        float temp;
787        size_t len;
788        const char *p;
789        int prec, i;
790
791        assert(errno == 0);
792
793        len = strlen(str);
794        /* caller already checked this */
795        assert(len > 0);
796
797        /*
798         * A format of "IK" is in deciKelvin. A format of "IK3" is in
799         * milliKelvin. The single digit following IK is log10 of the
800         * multiplying factor to convert Kelvin into the untis of this sysctl,
801         * or the dividing factor to convert the sysctl value to Kelvin. Numbers
802         * larger than 6 will run into precision issues with 32-bit integers.
803         * Characters that aren't ASCII digits after the 'K' are ignored. No
804         * localization is present because this is an interface from the kernel
805         * to this program (eg not an end-user interface), so isdigit() isn't
806         * used here.
807         */
808        if (fmt[2] != '\0' && fmt[2] >= '0' && fmt[2] <= '9')
809                prec = fmt[2] - '0';
810        else
811                prec = 1;
812        p = &str[len - 1];
813        if (*p == 'C' || *p == 'F' || *p == 'K') {
814                temp = strtof(str, endptrp);
815                if (*endptrp != str && *endptrp == p && errno == 0) {
816                        if (*p == 'F')
817                                temp = (temp - 32) * 5 / 9;
818                        *endptrp = NULL;
819                        if (*p != 'K')
820                                temp += 273.15;
821                        for (i = 0; i < prec; i++)
822                                temp *= 10.0;
823                        return ((int)(temp + 0.5));
824                }
825        } else {
826                /* No unit specified -> treat it as a raw number */
827                kelv = (int)strtol(str, endptrp, 10);
828                if (*endptrp != str && *endptrp == p && errno == 0) {
829                        *endptrp = NULL;
830                        return (kelv);
831                }
832        }
833
834        errno = ERANGE;
835        return (0);
836}
837
838/*
839 * These functions uses a presently undocumented interface to the kernel
840 * to walk the tree and get the type so it can print the value.
841 * This interface is under work and consideration, and should probably
842 * be killed with a big axe by the first person who can find the time.
843 * (be aware though, that the proper interface isn't as obvious as it
844 * may seem, there are various conflicting requirements.
845 */
846
847static int
848name2oid(const char *name, int *oidp)
849{
850        int oid[2];
851        int i;
852        size_t j;
853
854        oid[0] = 0;
855        oid[1] = 3;
856
857        j = CTL_MAXNAME * sizeof(int);
858        i = sysctl(oid, 2, oidp, &j, name, strlen(name));
859        if (i < 0)
860                return (i);
861        j /= sizeof(int);
862        return (j);
863}
864
865static int
866oidfmt(int *oid, int len, char *fmt, u_int *kind)
867{
868        int qoid[CTL_MAXNAME+2];
869        u_char buf[BUFSIZ];
870        int i;
871        size_t j;
872
873        qoid[0] = 0;
874        qoid[1] = 4;
875        memcpy(qoid + 2, oid, len * sizeof(int));
876
877        j = sizeof(buf);
878        i = sysctl(qoid, len + 2, buf, &j, 0, 0);
879        if (i)
880                err(1, "sysctl fmt %d %zu %d", i, j, errno);
881
882        if (kind)
883                *kind = *(u_int *)buf;
884
885        if (fmt)
886                strcpy(fmt, (char *)(buf + sizeof(u_int)));
887        return (0);
888}
889
890/*
891 * This formats and outputs the value of one variable
892 *
893 * Returns zero if anything was actually output.
894 * Returns one if didn't know what to do with this.
895 * Return minus one if we had errors.
896 */
897static int
898show_var(int *oid, int nlen)
899{
900        u_char buf[BUFSIZ], *val, *oval, *p;
901        char name[BUFSIZ], fmt[BUFSIZ];
902        const char *sep, *sep1, *prntype;
903        int qoid[CTL_MAXNAME+2];
904        uintmax_t umv;
905        intmax_t mv;
906        int i, hexlen, sign, ctltype;
907        size_t intlen;
908        size_t j, len;
909        u_int kind;
910        float base;
911        int (*func)(size_t, void *);
912        int prec;
913
914        /* Silence GCC. */
915        umv = mv = intlen = 0;
916
917        bzero(buf, BUFSIZ);
918        bzero(fmt, BUFSIZ);
919        bzero(name, BUFSIZ);
920        qoid[0] = 0;
921        memcpy(qoid + 2, oid, nlen * sizeof(int));
922
923        qoid[1] = 1;
924        j = sizeof(name);
925        i = sysctl(qoid, nlen + 2, name, &j, 0, 0);
926        if (i || !j)
927                err(1, "sysctl name %d %zu %d", i, j, errno);
928
929        oidfmt(oid, nlen, fmt, &kind);
930        /* if Wflag then only list sysctls that are writeable and not stats. */
931        if (Wflag && ((kind & CTLFLAG_WR) == 0 || (kind & CTLFLAG_STATS) != 0))
932                return 1;
933
934        /* if Tflag then only list sysctls that are tuneables. */
935        if (Tflag && (kind & CTLFLAG_TUN) == 0)
936                return 1;
937
938        if (Nflag) {
939                printf("%s", name);
940                return (0);
941        }
942
943        if (eflag)
944                sep = "=";
945        else
946                sep = ": ";
947
948        ctltype = (kind & CTLTYPE);
949        if (tflag || dflag) {
950                if (!nflag)
951                        printf("%s%s", name, sep);
952                if (ctl_typename[ctltype] != NULL)
953                        prntype = ctl_typename[ctltype];
954                else
955                        prntype = "unknown";
956                if (tflag && dflag)
957                        printf("%s%s", prntype, sep);
958                else if (tflag) {
959                        printf("%s", prntype);
960                        return (0);
961                }
962                qoid[1] = 5;
963                j = sizeof(buf);
964                i = sysctl(qoid, nlen + 2, buf, &j, 0, 0);
965                printf("%s", buf);
966                return (0);
967        }
968        /* find an estimate of how much we need for this var */
969        if (Bflag)
970                j = Bflag;
971        else {
972                j = 0;
973                i = sysctl(oid, nlen, 0, &j, 0, 0);
974                j += j; /* we want to be sure :-) */
975        }
976
977        val = oval = malloc(j + 1);
978        if (val == NULL) {
979                warnx("malloc failed");
980                return (1);
981        }
982        len = j;
983        i = sysctl(oid, nlen, val, &len, 0, 0);
984        if (i != 0 || (len == 0 && ctltype != CTLTYPE_STRING)) {
985                free(oval);
986                return (1);
987        }
988
989        if (bflag) {
990                fwrite(val, 1, len, stdout);
991                free(oval);
992                return (0);
993        }
994        val[len] = '\0';
995        p = val;
996        sign = ctl_sign[ctltype];
997        intlen = ctl_size[ctltype];
998
999        switch (ctltype) {
1000        case CTLTYPE_STRING:
1001                if (!nflag)
1002                        printf("%s%s", name, sep);
1003                printf("%.*s", (int)len, p);
1004                free(oval);
1005                return (0);
1006
1007        case CTLTYPE_INT:
1008        case CTLTYPE_UINT:
1009        case CTLTYPE_LONG:
1010        case CTLTYPE_ULONG:
1011        case CTLTYPE_S8:
1012        case CTLTYPE_S16:
1013        case CTLTYPE_S32:
1014        case CTLTYPE_S64:
1015        case CTLTYPE_U8:
1016        case CTLTYPE_U16:
1017        case CTLTYPE_U32:
1018        case CTLTYPE_U64:
1019                if (!nflag)
1020                        printf("%s%s", name, sep);
1021                hexlen = 2 + (intlen * CHAR_BIT + 3) / 4;
1022                sep1 = "";
1023                while (len >= intlen) {
1024                        switch (kind & CTLTYPE) {
1025                        case CTLTYPE_INT:
1026                        case CTLTYPE_UINT:
1027                                umv = *(u_int *)p;
1028                                mv = *(int *)p;
1029                                break;
1030                        case CTLTYPE_LONG:
1031                        case CTLTYPE_ULONG:
1032                                umv = *(u_long *)p;
1033                                mv = *(long *)p;
1034                                break;
1035                        case CTLTYPE_S8:
1036                        case CTLTYPE_U8:
1037                                umv = *(uint8_t *)p;
1038                                mv = *(int8_t *)p;
1039                                break;
1040                        case CTLTYPE_S16:
1041                        case CTLTYPE_U16:
1042                                umv = *(uint16_t *)p;
1043                                mv = *(int16_t *)p;
1044                                break;
1045                        case CTLTYPE_S32:
1046                        case CTLTYPE_U32:
1047                                umv = *(uint32_t *)p;
1048                                mv = *(int32_t *)p;
1049                                break;
1050                        case CTLTYPE_S64:
1051                        case CTLTYPE_U64:
1052                                umv = *(uint64_t *)p;
1053                                mv = *(int64_t *)p;
1054                                break;
1055                        }
1056                        fputs(sep1, stdout);
1057                        if (xflag)
1058                                printf("%#0*jx", hexlen, umv);
1059                        else if (!sign)
1060                                printf(hflag ? "%'ju" : "%ju", umv);
1061                        else if (fmt[1] == 'K') {
1062                                if (mv < 0)
1063                                        printf("%jd", mv);
1064                                else {
1065                                        /*
1066                                         * See strIKtoi for details on fmt.
1067                                         */
1068                                        prec = 1;
1069                                        if (fmt[2] != '\0')
1070                                                prec = fmt[2] - '0';
1071                                        base = 1.0;
1072                                        for (int i = 0; i < prec; i++)
1073                                                base *= 10.0;
1074                                        printf("%.*fC", prec,
1075                                            (float)mv / base - 273.15);
1076                                }
1077                        } else
1078                                printf(hflag ? "%'jd" : "%jd", mv);
1079                        sep1 = " ";
1080                        len -= intlen;
1081                        p += intlen;
1082                }
1083                free(oval);
1084                return (0);
1085
1086        case CTLTYPE_OPAQUE:
1087                i = 0;
1088                if (strcmp(fmt, "S,clockinfo") == 0)
1089#ifndef __rtems__
1090                        func = S_clockinfo;
1091#else /* __rtems__ */
1092                        func = NULL;
1093#endif /* __rtems__ */
1094                else if (strcmp(fmt, "S,timeval") == 0)
1095                        func = S_timeval;
1096                else if (strcmp(fmt, "S,loadavg") == 0)
1097                        func = S_loadavg;
1098                else if (strcmp(fmt, "S,vmtotal") == 0)
1099                        func = S_vmtotal;
1100#ifdef __amd64__
1101                else if (strcmp(fmt, "S,efi_map_header") == 0)
1102                        func = S_efi_map;
1103#endif
1104#if defined(__amd64__) || defined(__i386__)
1105                else if (strcmp(fmt, "S,bios_smap_xattr") == 0)
1106                        func = S_bios_smap_xattr;
1107#endif
1108                else
1109                        func = NULL;
1110                if (func) {
1111                        if (!nflag)
1112                                printf("%s%s", name, sep);
1113                        i = (*func)(len, p);
1114                        free(oval);
1115                        return (i);
1116                }
1117                /* FALLTHROUGH */
1118        default:
1119                if (!oflag && !xflag) {
1120                        free(oval);
1121                        return (1);
1122                }
1123                if (!nflag)
1124                        printf("%s%s", name, sep);
1125                printf("Format:%s Length:%zu Dump:0x", fmt, len);
1126                while (len-- && (xflag || p < val + 16))
1127                        printf("%02x", *p++);
1128                if (!xflag && len > 16)
1129                        printf("...");
1130                free(oval);
1131                return (0);
1132        }
1133        free(oval);
1134        return (1);
1135}
1136
1137static int
1138sysctl_all(int *oid, int len)
1139{
1140        int name1[22], name2[22];
1141        int i, j;
1142        size_t l1, l2;
1143
1144        name1[0] = 0;
1145        name1[1] = 2;
1146        l1 = 2;
1147        if (len) {
1148                memcpy(name1+2, oid, len * sizeof(int));
1149                l1 += len;
1150        } else {
1151                name1[2] = 1;
1152                l1++;
1153        }
1154        for (;;) {
1155                l2 = sizeof(name2);
1156                j = sysctl(name1, l1, name2, &l2, 0, 0);
1157                if (j < 0) {
1158                        if (errno == ENOENT)
1159                                return (0);
1160                        else
1161                                err(1, "sysctl(getnext) %d %zu", j, l2);
1162                }
1163
1164                l2 /= sizeof(int);
1165
1166                if (len < 0 || l2 < (unsigned int)len)
1167                        return (0);
1168
1169                for (i = 0; i < len; i++)
1170                        if (name2[i] != oid[i])
1171                                return (0);
1172
1173                i = show_var(name2, l2);
1174                if (!i && !bflag)
1175                        putchar('\n');
1176
1177                memcpy(name1+2, name2, l2 * sizeof(int));
1178                l1 = 2 + l2;
1179        }
1180}
Note: See TracBrowser for help on using the repository browser.