[rtems-libbsd commit] Add sbin/sysctl

Chris Johns chrisj at rtems.org
Fri May 6 05:52:09 UTC 2016


Module:    rtems-libbsd
Branch:    master
Commit:    83eb07c4d64d5acef6813bc6ce0b014ed0d6026d
Changeset: http://git.rtems.org/rtems-libbsd/commit/?id=83eb07c4d64d5acef6813bc6ce0b014ed0d6026d

Author:    Chris Johns <chrisj at rtems.org>
Date:      Fri May  6 15:06:08 2016 +1000

Add sbin/sysctl

---

 freebsd/lib/libc/stdlib/strtoimax.c                | 165 +++++
 freebsd/lib/libc/stdlib/strtoumax.c                | 143 ++++
 freebsd/sbin/sysctl/sysctl.c                       | 784 +++++++++++++++++++++
 libbsd.py                                          |   3 +
 libbsd_waf.py                                      |   3 +
 rtemsbsd/include/machine/rtems-bsd-commands.h      |   2 +
 rtemsbsd/include/rtems/netcmds-config.h            |   2 +
 rtemsbsd/rtems/rtems-bsd-shell-netcmds.c           |   9 +
 .../include/rtems/bsd/test/default-network-init.h  |   3 +-
 9 files changed, 1113 insertions(+), 1 deletion(-)

diff --git a/freebsd/lib/libc/stdlib/strtoimax.c b/freebsd/lib/libc/stdlib/strtoimax.c
new file mode 100644
index 0000000..d7103b3
--- /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 0000000..4098ce8
--- /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 0000000..9d7a869
--- /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;
+	}
+}
diff --git a/libbsd.py b/libbsd.py
index 75fb2ec..b0ed161 100755
--- a/libbsd.py
+++ b/libbsd.py
@@ -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 93cf606..1f50306 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 df25178..8fd865e 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 f69b17b..d2d15ea 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 e6eea02..1271ff3 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 380d5aa..e93ee8e 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



More information about the vc mailing list