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

6-freebsd-12
Last change on this file was a69293c, checked in by Jan Sommer <jan.sommer@…>, on 04/17/20 at 08:24:08

i386: Port to RTEMS

  • Update imported files to compile rtems-libbsd for i386 based BSPs
  • Mostly commenting out parts which create compile or link errors in

RTEMS, but aren't needed

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