diff options
author | Chris Johns <chrisj@rtems.org> | 2016-05-06 15:06:08 +1000 |
---|---|---|
committer | Chris Johns <chrisj@rtems.org> | 2016-05-06 15:07:56 +1000 |
commit | 83eb07c4d64d5acef6813bc6ce0b014ed0d6026d (patch) | |
tree | 730b2ad8981dce791cd68625a25614e937962902 | |
parent | Fix sysctl support. (diff) | |
download | rtems-libbsd-83eb07c4d64d5acef6813bc6ce0b014ed0d6026d.tar.bz2 |
Add sbin/sysctl
-rw-r--r-- | freebsd/lib/libc/stdlib/strtoimax.c | 165 | ||||
-rw-r--r-- | freebsd/lib/libc/stdlib/strtoumax.c | 143 | ||||
-rw-r--r-- | freebsd/sbin/sysctl/sysctl.c | 784 | ||||
-rwxr-xr-x | libbsd.py | 3 | ||||
-rw-r--r-- | libbsd_waf.py | 3 | ||||
-rw-r--r-- | rtemsbsd/include/machine/rtems-bsd-commands.h | 2 | ||||
-rw-r--r-- | rtemsbsd/include/rtems/netcmds-config.h | 2 | ||||
-rw-r--r-- | rtemsbsd/rtems/rtems-bsd-shell-netcmds.c | 9 | ||||
-rw-r--r-- | testsuite/include/rtems/bsd/test/default-network-init.h | 3 |
9 files changed, 1113 insertions, 1 deletions
diff --git a/freebsd/lib/libc/stdlib/strtoimax.c b/freebsd/lib/libc/stdlib/strtoimax.c new file mode 100644 index 00000000..d7103b3a --- /dev/null +++ b/freebsd/lib/libc/stdlib/strtoimax.c @@ -0,0 +1,165 @@ +#include <machine/rtems-bsd-user-space.h> + +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "from @(#)strtol.c 8.1 (Berkeley) 6/4/93"; +#endif /* LIBC_SCCS and not lint */ +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <ctype.h> +#include <errno.h> +#include <stdlib.h> +#include <inttypes.h> +#ifndef __rtems__ +#include "xlocale_private.h" +#else +#define locale_t void* +#define isspace_l(_c, _l) isspace(_c) +static void* __get_locale(void) { return NULL; } +#endif /* __rtems__ */ + +/* + * Convert a string to an intmax_t integer. + * + * Assumes that the upper and lower case + * alphabets and digits are each contiguous. + */ +intmax_t +strtoimax_l(const char * __restrict nptr, char ** __restrict endptr, int base, + locale_t locale) +{ + const char *s; + uintmax_t acc; + char c; + uintmax_t cutoff; + int neg, any, cutlim; +#ifndef __rtems__ + FIX_LOCALE(locale); +#else + locale = NULL; +#endif /* __rtems__ */ + + /* + * Skip white space and pick up leading +/- sign if any. + * If base is 0, allow 0x for hex and 0 for octal, else + * assume decimal; if base is already 16, allow 0x. + */ + s = nptr; + do { + c = *s++; + } while (isspace_l((unsigned char)c, locale)); + if (c == '-') { + neg = 1; + c = *s++; + } else { + neg = 0; + if (c == '+') + c = *s++; + } + if ((base == 0 || base == 16) && + c == '0' && (*s == 'x' || *s == 'X') && + ((s[1] >= '0' && s[1] <= '9') || + (s[1] >= 'A' && s[1] <= 'F') || + (s[1] >= 'a' && s[1] <= 'f'))) { + c = s[1]; + s += 2; + base = 16; + } + if (base == 0) + base = c == '0' ? 8 : 10; + acc = any = 0; + if (base < 2 || base > 36) + goto noconv; + + /* + * Compute the cutoff value between legal numbers and illegal + * numbers. That is the largest legal value, divided by the + * base. An input number that is greater than this value, if + * followed by a legal input character, is too big. One that + * is equal to this value may be valid or not; the limit + * between valid and invalid numbers is then based on the last + * digit. For instance, if the range for intmax_t is + * [-9223372036854775808..9223372036854775807] and the input base + * is 10, cutoff will be set to 922337203685477580 and cutlim to + * either 7 (neg==0) or 8 (neg==1), meaning that if we have + * accumulated a value > 922337203685477580, or equal but the + * next digit is > 7 (or 8), the number is too big, and we will + * return a range error. + * + * Set 'any' if any `digits' consumed; make it negative to indicate + * overflow. + */ + cutoff = neg ? (uintmax_t)-(INTMAX_MIN + INTMAX_MAX) + INTMAX_MAX + : INTMAX_MAX; + cutlim = cutoff % base; + cutoff /= base; + for ( ; ; c = *s++) { + if (c >= '0' && c <= '9') + c -= '0'; + else if (c >= 'A' && c <= 'Z') + c -= 'A' - 10; + else if (c >= 'a' && c <= 'z') + c -= 'a' - 10; + else + break; + if (c >= base) + break; + if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) + any = -1; + else { + any = 1; + acc *= base; + acc += c; + } + } + if (any < 0) { + acc = neg ? INTMAX_MIN : INTMAX_MAX; + errno = ERANGE; + } else if (!any) { +noconv: + errno = EINVAL; + } else if (neg) + acc = -acc; + if (endptr != NULL) + *endptr = (char *)(any ? s - 1 : nptr); + return (acc); +} +intmax_t +strtoimax(const char * __restrict nptr, char ** __restrict endptr, int base) +{ + return strtoimax_l(nptr, endptr, base, __get_locale()); +} diff --git a/freebsd/lib/libc/stdlib/strtoumax.c b/freebsd/lib/libc/stdlib/strtoumax.c new file mode 100644 index 00000000..4098ce81 --- /dev/null +++ b/freebsd/lib/libc/stdlib/strtoumax.c @@ -0,0 +1,143 @@ +#include <machine/rtems-bsd-user-space.h> + +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "from @(#)strtoul.c 8.1 (Berkeley) 6/4/93"; +#endif /* LIBC_SCCS and not lint */ +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <ctype.h> +#include <errno.h> +#include <stdlib.h> +#include <inttypes.h> +#ifndef __rtems__ +#include "xlocale_private.h" +#else +#define locale_t void* +#define isspace_l(_c, _l) isspace(_c) +static void* __get_locale(void) { return NULL; } +#endif /* __rtems__ */ + +/* + * Convert a string to a uintmax_t integer. + * + * Assumes that the upper and lower case + * alphabets and digits are each contiguous. + */ +uintmax_t +strtoumax_l(const char * __restrict nptr, char ** __restrict endptr, int base, + locale_t locale) +{ + const char *s; + uintmax_t acc; + char c; + uintmax_t cutoff; + int neg, any, cutlim; +#ifndef __rtems__ + FIX_LOCALE(locale); +#else + locale = NULL; +#endif /* __rtems__ */ + + /* + * See strtoimax for comments as to the logic used. + */ + s = nptr; + do { + c = *s++; + } while (isspace_l((unsigned char)c, locale)); + if (c == '-') { + neg = 1; + c = *s++; + } else { + neg = 0; + if (c == '+') + c = *s++; + } + if ((base == 0 || base == 16) && + c == '0' && (*s == 'x' || *s == 'X') && + ((s[1] >= '0' && s[1] <= '9') || + (s[1] >= 'A' && s[1] <= 'F') || + (s[1] >= 'a' && s[1] <= 'f'))) { + c = s[1]; + s += 2; + base = 16; + } + if (base == 0) + base = c == '0' ? 8 : 10; + acc = any = 0; + if (base < 2 || base > 36) + goto noconv; + + cutoff = UINTMAX_MAX / base; + cutlim = UINTMAX_MAX % base; + for ( ; ; c = *s++) { + if (c >= '0' && c <= '9') + c -= '0'; + else if (c >= 'A' && c <= 'Z') + c -= 'A' - 10; + else if (c >= 'a' && c <= 'z') + c -= 'a' - 10; + else + break; + if (c >= base) + break; + if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) + any = -1; + else { + any = 1; + acc *= base; + acc += c; + } + } + if (any < 0) { + acc = UINTMAX_MAX; + errno = ERANGE; + } else if (!any) { +noconv: + errno = EINVAL; + } else if (neg) + acc = -acc; + if (endptr != NULL) + *endptr = (char *)(any ? s - 1 : nptr); + return (acc); +} +uintmax_t +strtoumax(const char * __restrict nptr, char ** __restrict endptr, int base) +{ + return strtoumax_l(nptr, endptr, base, __get_locale()); +} diff --git a/freebsd/sbin/sysctl/sysctl.c b/freebsd/sbin/sysctl/sysctl.c new file mode 100644 index 00000000..9d7a8692 --- /dev/null +++ b/freebsd/sbin/sysctl/sysctl.c @@ -0,0 +1,784 @@ +#include <machine/rtems-bsd-user-space.h> + +/* + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static const char copyright[] = +"@(#) Copyright (c) 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +#if 0 +static char sccsid[] = "@(#)from: sysctl.c 8.1 (Berkeley) 6/6/93"; +#endif +static const char rcsid[] = + "$FreeBSD$"; +#endif /* not lint */ +#ifdef __rtems__ +#define __need_getopt_newlib +#include <getopt.h> +#include <machine/rtems-bsd-program.h> +#include <machine/rtems-bsd-commands.h> +#endif /* __rtems__ */ + +#include <rtems/bsd/sys/param.h> +#include <rtems/bsd/sys/time.h> +#include <rtems/bsd/sys/resource.h> +#include <sys/stat.h> +#include <sys/sysctl.h> +#include <sys/vmmeter.h> + +#include <ctype.h> +#include <err.h> +#include <errno.h> +#include <inttypes.h> +#include <locale.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +static int aflag, bflag, dflag, eflag, hflag, iflag; +static int Nflag, nflag, oflag, qflag, xflag, warncount; + +static int oidfmt(int *, int, char *, u_int *); +static void parse(const char *); +static int show_var(int *, int); +static int sysctl_all(int *oid, int len); +static int name2oid(char *, int *); + +static int set_IK(const char *, int *); + +static void +usage(void) +{ + + (void)fprintf(stderr, "%s\n%s\n", + "usage: sysctl [-bdehiNnoqx] name[=value] ...", + " sysctl [-bdehNnoqx] -a"); + exit(1); +} + +#ifdef __rtems__ +static int main(int argc, char **argv); + +int rtems_bsd_command_sysctl(int argc, char *argv[]) +{ + int exit_code; + + rtems_bsd_program_lock(); + + aflag = bflag = dflag = eflag = hflag = iflag = 0; + Nflag = nflag = oflag = qflag = xflag = warncount = 0; + + exit_code = rtems_bsd_program_call_main("sysctl", main, argc, argv); + + rtems_bsd_program_unlock(); + + return exit_code; +} +#endif /* __rtems__ */ + +int +main(int argc, char **argv) +{ + int ch; + +#ifdef __rtems__ + struct getopt_data getopt_data; + memset(&getopt_data, 0, sizeof(getopt_data)); +#define optind getopt_data.optind +#define optarg getopt_data.optarg +#define opterr getopt_data.opterr +#define optopt getopt_data.optopt +#define getopt(argc, argv, opt) getopt_r(argc, argv, "+" opt, &getopt_data) +#endif /* __rtems__ */ + +#ifndef __rtems__ + setlocale(LC_NUMERIC, ""); + setbuf(stdout,0); + setbuf(stderr,0); +#endif /* __rtems__ */ + + while ((ch = getopt(argc, argv, "AabdehiNnoqwxX")) != -1) { + switch (ch) { + case 'A': + /* compatibility */ + aflag = oflag = 1; + break; + case 'a': + aflag = 1; + break; + case 'b': + bflag = 1; + break; + case 'd': + dflag = 1; + break; + case 'e': + eflag = 1; + break; + case 'h': + hflag = 1; + break; + case 'i': + iflag = 1; + break; + case 'N': + Nflag = 1; + break; + case 'n': + nflag = 1; + break; + case 'o': + oflag = 1; + break; + case 'q': + qflag = 1; + break; + case 'w': + /* compatibility */ + /* ignored */ + break; + case 'X': + /* compatibility */ + aflag = xflag = 1; + break; + case 'x': + xflag = 1; + break; + default: + usage(); + } + } + argc -= optind; + argv += optind; + + if (Nflag && nflag) + usage(); + if (aflag && argc == 0) + exit(sysctl_all(0, 0)); + if (argc == 0) + usage(); + + warncount = 0; + while (argc-- > 0) + parse(*argv++); + exit(warncount); +} + +/* + * Parse a name into a MIB entry. + * Lookup and print out the MIB entry if it exists. + * Set a new value if requested. + */ +static void +parse(const char *string) +{ + int len, i, j; + void *newval = 0; + int intval; + unsigned int uintval; + long longval; + unsigned long ulongval; + size_t newsize = 0; + int64_t i64val; + uint64_t u64val; + int mib[CTL_MAXNAME]; + char *cp, *bufp, buf[BUFSIZ], *endptr, fmt[BUFSIZ]; + u_int kind; + + cp = buf; + if (snprintf(buf, BUFSIZ, "%s", string) >= BUFSIZ) + errx(1, "oid too long: '%s'", string); + bufp = strsep(&cp, "="); + if (cp != NULL) { + while (isspace(*cp)) + cp++; + newval = cp; + newsize = strlen(cp); + } + len = name2oid(bufp, mib); + + if (len < 0) { + if (iflag) + return; + if (qflag) + exit(1); + else + errx(1, "unknown oid '%s'", bufp); + } + + if (oidfmt(mib, len, fmt, &kind)) + err(1, "couldn't find format of oid '%s'", bufp); + + if (newval == NULL || dflag) { + if ((kind & CTLTYPE) == CTLTYPE_NODE) { + if (dflag) { + i = show_var(mib, len); + if (!i && !bflag) + putchar('\n'); + } + sysctl_all(mib, len); + } else { + i = show_var(mib, len); + if (!i && !bflag) + putchar('\n'); + } + } else { + if ((kind & CTLTYPE) == CTLTYPE_NODE) + errx(1, "oid '%s' isn't a leaf node", bufp); + + if (!(kind & CTLFLAG_WR)) { + if (kind & CTLFLAG_TUN) { + warnx("oid '%s' is a read only tunable", bufp); + errx(1, "Tunable values are set in /boot/loader.conf"); + } else { + errx(1, "oid '%s' is read only", bufp); + } + } + + if ((kind & CTLTYPE) == CTLTYPE_INT || + (kind & CTLTYPE) == CTLTYPE_UINT || + (kind & CTLTYPE) == CTLTYPE_LONG || + (kind & CTLTYPE) == CTLTYPE_ULONG || + (kind & CTLTYPE) == CTLTYPE_S64 || + (kind & CTLTYPE) == CTLTYPE_U64) { + if (strlen(newval) == 0) + errx(1, "empty numeric value"); + } + + switch (kind & CTLTYPE) { + case CTLTYPE_INT: + if (strcmp(fmt, "IK") == 0) { + if (!set_IK(newval, &intval)) + errx(1, "invalid value '%s'", + (char *)newval); + } else { + intval = (int)strtol(newval, &endptr, + 0); + if (endptr == newval || *endptr != '\0') + errx(1, "invalid integer '%s'", + (char *)newval); + } + newval = &intval; + newsize = sizeof(intval); + break; + case CTLTYPE_UINT: + uintval = (int) strtoul(newval, &endptr, 0); + if (endptr == newval || *endptr != '\0') + errx(1, "invalid unsigned integer '%s'", + (char *)newval); + newval = &uintval; + newsize = sizeof(uintval); + break; + case CTLTYPE_LONG: + longval = strtol(newval, &endptr, 0); + if (endptr == newval || *endptr != '\0') + errx(1, "invalid long integer '%s'", + (char *)newval); + newval = &longval; + newsize = sizeof(longval); + break; + case CTLTYPE_ULONG: + ulongval = strtoul(newval, &endptr, 0); + if (endptr == newval || *endptr != '\0') + errx(1, "invalid unsigned long integer" + " '%s'", (char *)newval); + newval = &ulongval; + newsize = sizeof(ulongval); + break; + case CTLTYPE_STRING: + break; + case CTLTYPE_S64: + i64val = strtoimax(newval, &endptr, 0); + if (endptr == newval || *endptr != '\0') + errx(1, "invalid int64_t '%s'", + (char *)newval); + newval = &i64val; + newsize = sizeof(i64val); + break; + case CTLTYPE_U64: + u64val = strtoumax(newval, &endptr, 0); + if (endptr == newval || *endptr != '\0') + errx(1, "invalid uint64_t '%s'", + (char *)newval); + newval = &u64val; + newsize = sizeof(u64val); + break; + case CTLTYPE_OPAQUE: + /* FALLTHROUGH */ + default: + errx(1, "oid '%s' is type %d," + " cannot set that", bufp, + kind & CTLTYPE); + } + + i = show_var(mib, len); + if (sysctl(mib, len, 0, 0, newval, newsize) == -1) { + if (!i && !bflag) + putchar('\n'); + switch (errno) { + case EOPNOTSUPP: + errx(1, "%s: value is not available", + string); + case ENOTDIR: + errx(1, "%s: specification is incomplete", + string); + case ENOMEM: + errx(1, "%s: type is unknown to this program", + string); + default: + warn("%s", string); + warncount++; + return; + } + } + if (!bflag) + printf(" -> "); + i = nflag; + nflag = 1; + j = show_var(mib, len); + if (!j && !bflag) + putchar('\n'); + nflag = i; + } +} + +/* These functions will dump out various interesting structures. */ + +static int +S_clockinfo(int l2, void *p) +{ +#ifndef __rtems__ + struct clockinfo *ci = (struct clockinfo*)p; + + if (l2 != sizeof(*ci)) { + warnx("S_clockinfo %d != %zu", l2, sizeof(*ci)); + return (1); + } + printf(hflag ? "{ hz = %'d, tick = %'d, profhz = %'d, stathz = %'d }" : + "{ hz = %d, tick = %d, profhz = %d, stathz = %d }", + ci->hz, ci->tick, ci->profhz, ci->stathz); +#endif /* __rtems__ */ + return (0); +} + +static int +S_loadavg(int l2, void *p) +{ + struct loadavg *tv = (struct loadavg*)p; + + if (l2 != sizeof(*tv)) { + warnx("S_loadavg %d != %zu", l2, sizeof(*tv)); + return (1); + } + printf(hflag ? "{ %'.2f %'.2f %'.2f }" : "{ %.2f %.2f %.2f }", + (double)tv->ldavg[0]/(double)tv->fscale, + (double)tv->ldavg[1]/(double)tv->fscale, + (double)tv->ldavg[2]/(double)tv->fscale); + return (0); +} + +static int +S_timeval(int l2, void *p) +{ + struct timeval *tv = (struct timeval*)p; + time_t tv_sec; + char *p1, *p2; + + if (l2 != sizeof(*tv)) { + warnx("S_timeval %d != %zu", l2, sizeof(*tv)); + return (1); + } + printf(hflag ? "{ sec = %'jd, usec = %'ld } " : + "{ sec = %jd, usec = %ld } ", + (intmax_t)tv->tv_sec, tv->tv_usec); + tv_sec = tv->tv_sec; + p1 = strdup(ctime(&tv_sec)); + for (p2=p1; *p2 ; p2++) + if (*p2 == '\n') + *p2 = '\0'; + fputs(p1, stdout); + free(p1); + return (0); +} + +static int +S_vmtotal(int l2, void *p) +{ + struct vmtotal *v = (struct vmtotal *)p; + int pageKilo = getpagesize() / 1024; + + if (l2 != sizeof(*v)) { + warnx("S_vmtotal %d != %zu", l2, sizeof(*v)); + return (1); + } + + printf( + "\nSystem wide totals computed every five seconds:" + " (values in kilobytes)\n"); + printf("===============================================\n"); + printf( + "Processes:\t\t(RUNQ: %hd Disk Wait: %hd Page Wait: " + "%hd Sleep: %hd)\n", + v->t_rq, v->t_dw, v->t_pw, v->t_sl); + printf( + "Virtual Memory:\t\t(Total: %dK Active: %dK)\n", + v->t_vm * pageKilo, v->t_avm * pageKilo); + printf("Real Memory:\t\t(Total: %dK Active: %dK)\n", + v->t_rm * pageKilo, v->t_arm * pageKilo); + printf("Shared Virtual Memory:\t(Total: %dK Active: %dK)\n", + v->t_vmshr * pageKilo, v->t_avmshr * pageKilo); + printf("Shared Real Memory:\t(Total: %dK Active: %dK)\n", + v->t_rmshr * pageKilo, v->t_armshr * pageKilo); + printf("Free Memory:\t%dK\n", v->t_free * pageKilo); + + return (0); +} + +static int +set_IK(const char *str, int *val) +{ + float temp; + int len, kelv; + const char *p; + char *endptr; + + if ((len = strlen(str)) == 0) + return (0); + p = &str[len - 1]; + if (*p == 'C' || *p == 'F') { + temp = strtof(str, &endptr); + if (endptr == str || endptr != p) + return (0); + if (*p == 'F') + temp = (temp - 32) * 5 / 9; + kelv = temp * 10 + 2732; + } else { + kelv = (int)strtol(str, &endptr, 10); + if (endptr == str || *endptr != '\0') + return (0); + } + *val = kelv; + return (1); +} + +/* + * These functions uses a presently undocumented interface to the kernel + * to walk the tree and get the type so it can print the value. + * This interface is under work and consideration, and should probably + * be killed with a big axe by the first person who can find the time. + * (be aware though, that the proper interface isn't as obvious as it + * may seem, there are various conflicting requirements. + */ + +static int +name2oid(char *name, int *oidp) +{ + int oid[2]; + int i; + size_t j; + + oid[0] = 0; + oid[1] = 3; + + j = CTL_MAXNAME * sizeof(int); + i = sysctl(oid, 2, oidp, &j, name, strlen(name)); + if (i < 0) + return (i); + j /= sizeof(int); + return (j); +} + +static int +oidfmt(int *oid, int len, char *fmt, u_int *kind) +{ + int qoid[CTL_MAXNAME+2]; + u_char buf[BUFSIZ]; + int i; + size_t j; + + qoid[0] = 0; + qoid[1] = 4; + memcpy(qoid + 2, oid, len * sizeof(int)); + + j = sizeof(buf); + i = sysctl(qoid, len + 2, buf, &j, 0, 0); + if (i) + err(1, "sysctl fmt %d %zu %d", i, j, errno); + + if (kind) + *kind = *(u_int *)buf; + + if (fmt) + strcpy(fmt, (char *)(buf + sizeof(u_int))); + return (0); +} + +static int ctl_sign[CTLTYPE+1] = { + [CTLTYPE_INT] = 1, + [CTLTYPE_LONG] = 1, + [CTLTYPE_S64] = 1, +}; + +static int ctl_size[CTLTYPE+1] = { + [CTLTYPE_INT] = sizeof(int), + [CTLTYPE_UINT] = sizeof(u_int), + [CTLTYPE_LONG] = sizeof(long), + [CTLTYPE_ULONG] = sizeof(u_long), + [CTLTYPE_S64] = sizeof(int64_t), + [CTLTYPE_U64] = sizeof(int64_t), +}; + +/* + * This formats and outputs the value of one variable + * + * Returns zero if anything was actually output. + * Returns one if didn't know what to do with this. + * Return minus one if we had errors. + */ +static int +show_var(int *oid, int nlen) +{ + u_char buf[BUFSIZ], *val, *oval, *p; + char name[BUFSIZ], *fmt; + const char *sep, *sep1; + int qoid[CTL_MAXNAME+2]; + uintmax_t umv; + intmax_t mv; + int i, hexlen, sign, ctltype; + size_t intlen; + size_t j, len; + u_int kind; + int (*func)(int, void *); + + /* Silence GCC. */ + umv = mv = intlen = 0; + + bzero(buf, BUFSIZ); + bzero(name, BUFSIZ); + qoid[0] = 0; + memcpy(qoid + 2, oid, nlen * sizeof(int)); + + qoid[1] = 1; + j = sizeof(name); + i = sysctl(qoid, nlen + 2, name, &j, 0, 0); + if (i || !j) + err(1, "sysctl name %d %zu %d", i, j, errno); + + if (Nflag) { + printf("%s", name); + return (0); + } + + if (eflag) + sep = "="; + else + sep = ": "; + + if (dflag) { /* just print description */ + qoid[1] = 5; + j = sizeof(buf); + i = sysctl(qoid, nlen + 2, buf, &j, 0, 0); + if (!nflag) + printf("%s%s", name, sep); + printf("%s", buf); + return (0); + } + /* find an estimate of how much we need for this var */ + j = 0; + i = sysctl(oid, nlen, 0, &j, 0, 0); + j += j; /* we want to be sure :-) */ + + val = oval = malloc(j + 1); + if (val == NULL) { + warnx("malloc failed"); + return (1); + } + len = j; + i = sysctl(oid, nlen, val, &len, 0, 0); + if (i || !len) { + free(oval); + return (1); + } + + if (bflag) { + fwrite(val, 1, len, stdout); + free(oval); + return (0); + } + val[len] = '\0'; + fmt = buf; + oidfmt(oid, nlen, fmt, &kind); + p = val; + ctltype = (kind & CTLTYPE); + sign = ctl_sign[ctltype]; + intlen = ctl_size[ctltype]; + + switch (ctltype) { + case CTLTYPE_STRING: + if (!nflag) + printf("%s%s", name, sep); + printf("%.*s", (int)len, p); + free(oval); + return (0); + + case CTLTYPE_INT: + case CTLTYPE_UINT: + case CTLTYPE_LONG: + case CTLTYPE_ULONG: + case CTLTYPE_S64: + case CTLTYPE_U64: + if (!nflag) + printf("%s%s", name, sep); + hexlen = 2 + (intlen * CHAR_BIT + 3) / 4; + sep1 = ""; + while (len >= intlen) { + switch (kind & CTLTYPE) { + case CTLTYPE_INT: + case CTLTYPE_UINT: + umv = *(u_int *)p; + mv = *(int *)p; + break; + case CTLTYPE_LONG: + case CTLTYPE_ULONG: + umv = *(u_long *)p; + mv = *(long *)p; + break; + case CTLTYPE_S64: + case CTLTYPE_U64: + umv = *(uint64_t *)p; + mv = *(int64_t *)p; + break; + } + fputs(sep1, stdout); + if (xflag) + printf("%#0*jx", hexlen, umv); + else if (!sign) + printf(hflag ? "%'ju" : "%ju", umv); + else if (fmt[1] == 'K') { + if (mv < 0) + printf("%jd", mv); + else + printf("%.1fC", (mv - 2732.0) / 10); + } else + printf(hflag ? "%'jd" : "%jd", mv); + sep1 = " "; + len -= intlen; + p += intlen; + } + free(oval); + return (0); + + case CTLTYPE_OPAQUE: + i = 0; + if (strcmp(fmt, "S,clockinfo") == 0) + func = S_clockinfo; + else if (strcmp(fmt, "S,timeval") == 0) + func = S_timeval; + else if (strcmp(fmt, "S,loadavg") == 0) + func = S_loadavg; + else if (strcmp(fmt, "S,vmtotal") == 0) + func = S_vmtotal; + else + func = NULL; + if (func) { + if (!nflag) + printf("%s%s", name, sep); + i = (*func)(len, p); + free(oval); + return (i); + } + /* FALLTHROUGH */ + default: + if (!oflag && !xflag) { + free(oval); + return (1); + } + if (!nflag) + printf("%s%s", name, sep); + printf("Format:%s Length:%zu Dump:0x", fmt, len); + while (len-- && (xflag || p < val + 16)) + printf("%02x", *p++); + if (!xflag && len > 16) + printf("..."); + free(oval); + return (0); + } + free(oval); + return (1); +} + +static int +sysctl_all(int *oid, int len) +{ + int name1[22], name2[22]; + int i, j; + size_t l1, l2; + + name1[0] = 0; + name1[1] = 2; + l1 = 2; + if (len) { + memcpy(name1+2, oid, len * sizeof(int)); + l1 += len; + } else { + name1[2] = 1; + l1++; + } + for (;;) { + l2 = sizeof(name2); + j = sysctl(name1, l1, name2, &l2, 0, 0); + if (j < 0) { + if (errno == ENOENT) + return (0); + else + err(1, "sysctl(getnext) %d %zu", j, l2); + } + + l2 /= sizeof(int); + + if (len < 0 || l2 < (unsigned int)len) + return (0); + + for (i = 0; i < len; i++) + if (name2[i] != oid[i]) + return (0); + + i = show_var(name2, l2); + if (!i && !bflag) + putchar('\n'); + + memcpy(name1+2, name2, l2 * sizeof(int)); + l1 = 2 + l2; + } +} @@ -1952,7 +1952,9 @@ def user_space(mm): 'lib/libc/resolv/res_state.c', 'lib/libc/resolv/res_update.c', 'lib/libc/stdio/fgetln.c', + 'lib/libc/stdlib/strtoimax.c', 'lib/libc/stdlib/strtonum.c', + 'lib/libc/stdlib/strtoumax.c', 'lib/libc/string/strsep.c', 'lib/libipsec/ipsec_dump_policy.c', 'lib/libipsec/ipsec_get_policylen.c', @@ -2002,6 +2004,7 @@ def user_space(mm): 'sbin/ping6/ping6.c', 'sbin/ping/ping.c', 'sbin/route/route.c', + 'sbin/sysctl/sysctl.c', 'usr.bin/netstat/atalk.c', 'usr.bin/netstat/bpf.c', 'usr.bin/netstat/if.c', diff --git a/libbsd_waf.py b/libbsd_waf.py index 93cf6062..1f50306b 100644 --- a/libbsd_waf.py +++ b/libbsd_waf.py @@ -283,7 +283,9 @@ def build(bld): 'freebsd/lib/libc/resolv/res_state.c', 'freebsd/lib/libc/resolv/res_update.c', 'freebsd/lib/libc/stdio/fgetln.c', + 'freebsd/lib/libc/stdlib/strtoimax.c', 'freebsd/lib/libc/stdlib/strtonum.c', + 'freebsd/lib/libc/stdlib/strtoumax.c', 'freebsd/lib/libc/string/strsep.c', 'freebsd/lib/libipsec/ipsec_dump_policy.c', 'freebsd/lib/libipsec/ipsec_get_policylen.c', @@ -333,6 +335,7 @@ def build(bld): 'freebsd/sbin/ping/ping.c', 'freebsd/sbin/ping6/ping6.c', 'freebsd/sbin/route/route.c', + 'freebsd/sbin/sysctl/sysctl.c', 'freebsd/usr.bin/netstat/atalk.c', 'freebsd/usr.bin/netstat/bpf.c', 'freebsd/usr.bin/netstat/if.c', diff --git a/rtemsbsd/include/machine/rtems-bsd-commands.h b/rtemsbsd/include/machine/rtems-bsd-commands.h index df251787..8fd865e8 100644 --- a/rtemsbsd/include/machine/rtems-bsd-commands.h +++ b/rtemsbsd/include/machine/rtems-bsd-commands.h @@ -60,6 +60,8 @@ int rtems_bsd_command_dhcpcd(int argc, char **argv); int rtems_bsd_command_tcpdump(int argc, char **argv); +int rtems_bsd_command_sysctl(int argc, char **argv); + __END_DECLS #endif /* _RTEMS_BSD_MACHINE_RTEMS_BSD_COMMANDS_H_ */ diff --git a/rtemsbsd/include/rtems/netcmds-config.h b/rtemsbsd/include/rtems/netcmds-config.h index f69b17b5..d2d15ea2 100644 --- a/rtemsbsd/include/rtems/netcmds-config.h +++ b/rtemsbsd/include/rtems/netcmds-config.h @@ -37,6 +37,8 @@ extern rtems_shell_cmd_t rtems_shell_HOSTNAME_Command; extern rtems_shell_cmd_t rtems_shell_TCPDUMP_Command; +extern rtems_shell_cmd_t rtems_shell_SYSCTL_Command; + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/rtemsbsd/rtems/rtems-bsd-shell-netcmds.c b/rtemsbsd/rtems/rtems-bsd-shell-netcmds.c index e6eea024..1271ff36 100644 --- a/rtemsbsd/rtems/rtems-bsd-shell-netcmds.c +++ b/rtemsbsd/rtems/rtems-bsd-shell-netcmds.c @@ -54,3 +54,12 @@ rtems_shell_cmd_t rtems_shell_TCPDUMP_Command = { NULL, /* alias */ NULL /* next */ }; + +rtems_shell_cmd_t rtems_shell_SYSCTL_Command = { + "sysctl", /* name */ + "sysctl [-bdehiNnoRTqx] [-f filename] name[=value] ...", /* usage */ + "net", /* topic */ + rtems_bsd_command_sysctl, /* command */ + NULL, /* alias */ + NULL /* next */ +}; diff --git a/testsuite/include/rtems/bsd/test/default-network-init.h b/testsuite/include/rtems/bsd/test/default-network-init.h index 380d5aaa..e93ee8e9 100644 --- a/testsuite/include/rtems/bsd/test/default-network-init.h +++ b/testsuite/include/rtems/bsd/test/default-network-init.h @@ -342,7 +342,8 @@ SYSINIT_NEED_NET_IF_VLAN; &rtems_shell_ROUTE_Command, \ &rtems_shell_NETSTAT_Command, \ &rtems_shell_IFCONFIG_Command, \ - &rtems_shell_TCPDUMP_Command + &rtems_shell_TCPDUMP_Command, \ + &rtems_shell_SYSCTL_Command #define CONFIGURE_SHELL_COMMAND_CPUUSE #define CONFIGURE_SHELL_COMMAND_PERIODUSE |