Esempio n. 1
0
/*
 * 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)
{
	size_t len;
	int i, j;
	void *newval = NULL;
	int intval;
	unsigned int uintval;
	long longval;
	unsigned long ulongval;
	size_t newsize = 0;
	quad_t quadval;
	u_quad_t uquadval;
	int mib[CTL_MAXNAME];
	char *cp, fmt[BUFSIZ];
	const char *name;
	char *name_allocated = NULL;
	u_int kind;

	if ((cp = strchr(string, '=')) != NULL) {
		if ((name_allocated = malloc(cp - string + 1)) == NULL)
			err(1, "malloc failed");
		strlcpy(name_allocated, string, cp - string + 1);
		name = name_allocated;
		
		while (isspace(*++cp))
			;

		newval = cp;
		newsize = strlen(cp);
	} else {
		name = string;
	}

	len = CTL_MAXNAME;
	if (sysctlnametomib(name, mib, &len) < 0) {
		if (errno == ENOENT) {
			errx(1, "unknown oid '%s'", name);
		} else {
			err(1, "sysctlnametomib(\"%s\")", name);
		}
	}

	if (oidfmt(mib, len, fmt, &kind))
		err(1, "couldn't find format of oid '%s'", name);

	if (newval == NULL) {
		if ((kind & CTLTYPE) == CTLTYPE_NODE) {
			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", name);

		if (!(kind&CTLFLAG_WR))
			errx(1, "oid '%s' is read only", name);
	
		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, NULL, 0);
				newval = &intval;
				newsize = sizeof(intval);
				break;
			case CTLTYPE_UINT:
				uintval = (int) strtoul(newval, NULL, 0);
				newval = &uintval;
				newsize = sizeof uintval;
				break;
			case CTLTYPE_LONG:
				longval = strtol(newval, NULL, 0);
				newval = &longval;
				newsize = sizeof longval;
				break;
			case CTLTYPE_ULONG:
				ulongval = strtoul(newval, NULL, 0);
				newval = &ulongval;
				newsize = sizeof ulongval;
				break;
			case CTLTYPE_STRING:
				break;
			case CTLTYPE_QUAD:
				quadval = strtoq(newval, NULL, 0);
				newval = &quadval;
				newsize = sizeof(quadval);
				break;
			case CTLTYPE_UQUAD:
				uquadval = strtouq(newval, NULL, 0);
				newval = &uquadval;
				newsize = sizeof(uquadval);
				break;
			case CTLTYPE_OPAQUE:
				if (strcmp(fmt, "T,dev_t") == 0 ||
				    strcmp(fmt, "T,udev_t") == 0
				) {
					set_T_dev_t((char*)newval, &newval,
						    &newsize);
					break;
				}
				/* FALLTHROUGH */
			default:
				errx(1, "oid '%s' is type %d,"
					" cannot set that", name,
					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);
				return;
			}
		}
		if (!bflag)
			printf(" -> ");
		i = nflag;
		nflag = 1;
		j = show_var(mib, len);
		if (!j && !bflag)
			putchar('\n');
		nflag = i;
	}

	if (name_allocated != NULL)
		free(name_allocated);
}
Esempio n. 2
0
/*
 * 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(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;

	bufp = buf;
	if (snprintf(buf, BUFSIZ, "%s", string) >= BUFSIZ)
		errx(1, "oid too long: '%s'", string);
	if ((cp = strchr(string, '=')) != NULL) {
		*strchr(buf, '=') = '\0';
		*cp++ = '\0';
		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) {
		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;
	}
}
Esempio n. 3
0
/*
 * Parse a name into a MIB entry.
 * Lookup and print out the MIB entry if it exists.
 * Set a new value if requested.
 */
static int
parse(const char *string, int lineno)
{
	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], line[BUFSIZ];
	u_int kind;

	if (lineno)
		snprintf(line, sizeof(line), " at line %d", lineno);
	else
		line[0] = '\0';

	cp = buf;
	if (snprintf(buf, BUFSIZ, "%s", string) >= BUFSIZ) {
		warn("oid too long: '%s'%s", string, line);
		return (1);
	}
	bufp = strsep(&cp, "=:");
	if (cp != NULL) {
		/* Tflag just lists tunables, do not allow assignment */
		if (Tflag || Wflag) {
			warnx("Can't set variables when using -T or -W");
			usage();
		}
		while (isspace(*cp))
			cp++;
		/* Strip a pair of " or ' if any. */
		switch (*cp) {
		case '\"':
		case '\'':
			if (cp[strlen(cp) - 1] == *cp)
				cp[strlen(cp) - 1] = '\0';
			cp++;
		}
		newval = cp;
		newsize = strlen(cp);
	}
	len = name2oid(bufp, mib);

	if (len < 0) {
		if (iflag)
			return (0);
		if (qflag)
			return (1);
		else {
			warn("unknown oid '%s'%s", bufp, line);
			return (1);
		}
	}

	if (oidfmt(mib, len, fmt, &kind)) {
		warn("couldn't find format of oid '%s'%s", bufp, line);
		if (iflag)
			return (1);
		else
			exit(1);
	}

	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) {
			warn("oid '%s' isn't a leaf node%s", bufp, line);
			return (1);
		}

		if (!(kind & CTLFLAG_WR)) {
			if (kind & CTLFLAG_TUN) {
				warnx("oid '%s' is a read only tunable%s", bufp, line);
				warnx("Tunable values are set in /boot/loader.conf");
			} else
				warnx("oid '%s' is read only%s", bufp, line);
			return (1);
		}

		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) {
				warnx("empty numeric value");
				return (1);
			}
		}

		switch (kind & CTLTYPE) {
			case CTLTYPE_INT:
				if (strcmp(fmt, "IK") == 0) {
					if (!set_IK(newval, &intval)) {
						warnx("invalid value '%s'%s",
						    (char *)newval, line);
						return (1);
					}
 				} else {
					intval = (int)strtol(newval, &endptr,
					    0);
					if (endptr == newval || *endptr != '\0') {
						warnx("invalid integer '%s'%s",
						    (char *)newval, line);
						return (1);
					}
				}
				newval = &intval;
				newsize = sizeof(intval);
				break;
			case CTLTYPE_UINT:
				uintval = (int) strtoul(newval, &endptr, 0);
				if (endptr == newval || *endptr != '\0') {
					warnx("invalid unsigned integer '%s'%s",
					    (char *)newval, line);
					return (1);
				}
				newval = &uintval;
				newsize = sizeof(uintval);
				break;
			case CTLTYPE_LONG:
				longval = strtol(newval, &endptr, 0);
				if (endptr == newval || *endptr != '\0') {
					warnx("invalid long integer '%s'%s",
					    (char *)newval, line);
					return (1);
				}
				newval = &longval;
				newsize = sizeof(longval);
				break;
			case CTLTYPE_ULONG:
				ulongval = strtoul(newval, &endptr, 0);
				if (endptr == newval || *endptr != '\0') {
					warnx("invalid unsigned long integer"
					    " '%s'%s", (char *)newval, line);
					return (1);
				}
				newval = &ulongval;
				newsize = sizeof(ulongval);
				break;
			case CTLTYPE_STRING:
				break;
			case CTLTYPE_S64:
				i64val = strtoimax(newval, &endptr, 0);
				if (endptr == newval || *endptr != '\0') {
					warnx("invalid int64_t '%s'%s",
					    (char *)newval, line);
					return (1);
				}
				newval = &i64val;
				newsize = sizeof(i64val);
				break;
			case CTLTYPE_U64:
				u64val = strtoumax(newval, &endptr, 0);
				if (endptr == newval || *endptr != '\0') {
					warnx("invalid uint64_t '%s'%s",
					    (char *)newval, line);
					return (1);
				}
				newval = &u64val;
				newsize = sizeof(u64val);
				break;
			case CTLTYPE_OPAQUE:
				/* FALLTHROUGH */
			default:
				warnx("oid '%s' is type %d,"
					" cannot set that%s", bufp,
					kind & CTLTYPE, line);
				return (1);
		}

		i = show_var(mib, len);
		if (sysctl(mib, len, 0, 0, newval, newsize) == -1) {
			if (!i && !bflag)
				putchar('\n');
			switch (errno) {
			case EOPNOTSUPP:
				warnx("%s: value is not available%s",
					string, line);
				return (1);
			case ENOTDIR:
				warnx("%s: specification is incomplete%s",
					string, line);
				return (1);
			case ENOMEM:
				warnx("%s: type is unknown to this program%s",
					string, line);
				return (1);
			default:
				warn("%s%s", string, line);
				return (1);
			}
		}
		if (!bflag)
			printf(" -> ");
		i = nflag;
		nflag = 1;
		j = show_var(mib, len);
		if (!j && !bflag)
			putchar('\n');
		nflag = i;
	}

	return (0);
}
Esempio n. 4
0
static int
luaA_sysctl_set(lua_State *L)
{
    int i, len, intval, mib[CTL_MAXNAME];
    unsigned int uintval;
    long longval;
    unsigned long ulongval;
    quad_t quadval;
    size_t s, newsize = 0;
    u_int kind;
    char fmt[BUFSIZ], key[BUFSIZ], nvalbuf[BUFSIZ];
    const char *errmsg;
    void *newval = NULL;

    /* get first argument from lua */
    s = strlcpy(key, luaL_checkstring(L, 1), sizeof(key));
    if (s >= sizeof(key))
        return (luaL_error(L, "first arg too long"));
    /* get second argument from lua */
    s = strlcpy(nvalbuf, luaL_checkstring(L, 2), sizeof(nvalbuf));
    if (s >= sizeof(nvalbuf))
        return (luaL_error(L, "second arg too long"));
    newval = nvalbuf;
    newsize = s;

    len = name2oid(key, mib);
    if (len < 0)
        return (luaL_error(L, "unknown iod '%s'", key));

    if (oidfmt(mib, len, fmt, &kind) != 0)
        return (luaL_error(L, "couldn't find format of oid '%s'", key));

    if ((kind & CTLTYPE) == CTLTYPE_NODE)
        return (luaL_error(L, "oid '%s' isn't a leaf node", key));

    if (!(kind & CTLFLAG_WR)) {
        return (luaL_error(L, "oid '%s' is %s", key,
                    (kind & CTLFLAG_TUN) ? "read only tunable" : "read only"));
    }

    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)
            return (luaL_error(L, "empty numeric value"));
    }

    switch (kind & CTLTYPE) {
    case CTLTYPE_INT:
        if (strcmp(fmt, "IK") == 0) {
            if (!set_IK(newval, &intval))
                return (luaL_error(L, "invalid value '%s'", (char *)newval));
        }
        else {
            intval = (int)strtonum(newval, INT_MIN, INT_MAX, &errmsg);
            if (errmsg) {
                return (luaL_error(L, "bad integer: %s (%s)",
                            (char *)newval, errmsg));
            }
        }
        newval = &intval;
        newsize = sizeof(intval);
        break;
    case CTLTYPE_UINT:
        uintval = (unsigned int)strtonum(newval, 0, UINT_MAX, &errmsg);
        if (errmsg) {
            return (luaL_error(L, "bad unsigned integer: %s (%s)",
                        (char *)newval, errmsg));
        }
        newval = &uintval;
        newsize = sizeof(uintval);
        break;
    case CTLTYPE_LONG:
        longval = (long)strtonum(newval, LONG_MIN, LONG_MAX, &errmsg);
        if (errmsg) {
            return (luaL_error(L,"bad long integer: %s (%s)",
                        (char *)newval, errmsg));
        }
        newval = &longval;
        newsize = sizeof(longval);
        break;
    case CTLTYPE_ULONG:
        ulongval = (unsigned long)strtonum(newval, 0, ULONG_MAX, &errmsg);
        if (errmsg) {
            return (luaL_error(L, "bad unsigned long integer: %s (%s)",
                        (char *)newval, errmsg));
        }
        newval = &ulongval;
        newsize = sizeof(ulongval);
        break;
    case CTLTYPE_STRING:
        break;
    case CTLTYPE_S64:
    case CTLTYPE_U64:
        quadval = (quad_t)strtonum(newval, LLONG_MIN, LLONG_MAX, &errmsg);
        if (errmsg) {
            return (luaL_error(L, "bad quad_t integer: %s (%s)",
                        (char *)newval, errmsg));
        }
        newval = &quadval;
        newsize = sizeof(quadval);
        break;
    case CTLTYPE_OPAQUE:
        if (strcmp(fmt, "T,dev_t") == 0) {
            set_T_dev_t(L, newval, &newval, &newsize);
            break;
        }
        /* FALLTHROUGH */
    default:
        return (luaL_error(L, "oid '%s' is type %d, cannot set that",
                    key, kind & CTLTYPE));
    }

    if (sysctl(mib, len, 0, 0, newval, newsize) == -1) {
        switch (errno) {
        case EOPNOTSUPP:
            return (luaL_error(L, "%s: value is not available", key));
        case ENOTDIR:
            return (luaL_error(L, "%s: specification is incomplete", key));
        case ENOMEM:
            /* really? with ENOMEM !?! */
            return (luaL_error(L, "%s: type is unknown to this program", key));
        default:
            i = strerror_r(errno, nvalbuf, sizeof(nvalbuf));
            if (i != 0)
                return (luaL_error(L, "strerror_r(3) failed"));
            else
                return (luaL_error(L, "%s: %s", key, nvalbuf));
        }
    }

    return (0);
}
Esempio n. 5
0
static int
luaA_sysctl_set(lua_State *L)
{
	int	i;
	int	len;
	int	intval;
	int	mib[CTL_MAXNAME];
	unsigned int uintval;
	u_int	kind;
	long	longval;
	unsigned long ulongval;
	size_t	s;
	size_t newsize = 0;
#if __FreeBSD_version < 900000
	quad_t	quadval;
#else
	int64_t i64val;
	uint64_t u64val;
	intmax_t intmaxval;
	uintmax_t uintmaxval;
#endif
	char	fmt[BUFSIZ];
	char	oid[BUFSIZ];
	char	nvalbuf[BUFSIZ];
	char	*endptr;
	void	*newval = NULL;

	/* get first argument from lua */
	s = strlcpy(oid, luaL_checkstring(L, 1), sizeof(oid));
	if (s >= sizeof(oid))
		return (luaL_error(L, "oid too long: '%s'", oid));
	/* get second argument from lua */
	s = strlcpy(nvalbuf, luaL_checkstring(L, 2), sizeof(nvalbuf));
	if (s >= sizeof(nvalbuf))
		return (luaL_error(L, "new value too long"));
	newval = nvalbuf;
	newsize = s;

	len = name2oid(oid, mib);
	if (len < 0)
		return (luaL_error(L, "unknown iod '%s'", oid));
	if (oidfmt(mib, len, fmt, sizeof(fmt), &kind) != 0)
		return (luaL_error(L, "couldn't find format of oid '%s'", oid));
	if ((kind & CTLTYPE) == CTLTYPE_NODE)
		return (luaL_error(L, "oid '%s' isn't a leaf node", oid));
	if (!(kind & CTLFLAG_WR)) {
		if (kind & CTLFLAG_TUN)
			return (luaL_error(L, "oid '%s' is a read only tunable. "
					"Tunable values are set in /boot/loader.conf", oid));
		else
			return (luaL_error(L, "oid '%s' is read only", oid));
	}
	if ((kind & CTLTYPE) == CTLTYPE_INT	||
	    (kind & CTLTYPE) == CTLTYPE_UINT	||
	    (kind & CTLTYPE) == CTLTYPE_LONG	||
	    (kind & CTLTYPE) == CTLTYPE_ULONG	||
#if __FreeBSD_version < 900000
	    (kind & CTLTYPE) == CTLTYPE_QUAD
#else
	    (kind & CTLTYPE) == CTLTYPE_S64 || (kind & CTLTYPE) == CTLTYPE_U64
#endif
	) {
		if (strlen(newval) == 0)
			return (luaL_error(L, "empty numeric value"));
	}

	switch (kind & CTLTYPE) {
	case CTLTYPE_INT:
		if (strcmp(fmt, "IK") == 0) {
			if (!set_IK(newval, &intval))
				return (luaL_error(L, "invalid value '%s'", (char *)newval));
		} else {
			longval = strtol(newval, &endptr, 0);
			if (endptr == newval || *endptr != '\0' ||
					longval > INT_MAX || longval < INT_MIN) {
				return (luaL_error(L, "invalid integer: '%s'", (char *)newval));
			}
			intval = (int)longval;
		}
		newval = &intval;
		newsize = sizeof(intval);
		break;
	case CTLTYPE_UINT:
		ulongval = strtoul(newval, &endptr, 0);
		if (endptr == newval || *endptr != '\0' || ulongval > UINT_MAX) {
			return (luaL_error(L, "invalid unsigned integer: '%s'", (char *)newval));
		}
		uintval = (unsigned int)ulongval;
		newval = &uintval;
		newsize = sizeof(uintval);
		break;
	case CTLTYPE_LONG:
		longval = strtol(newval, &endptr, 0);
		if (endptr == newval || *endptr != '\0') {
			return (luaL_error(L, "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') {
			return (luaL_error(L, "invalid unsigned long integer: '%s'",
					(char *)newval));
		}
		newval = &ulongval;
		newsize = sizeof(ulongval);
		break;
	case CTLTYPE_STRING:
		break;
#if __FreeBSD_version < 900000
	case CTLTYPE_QUAD:
		quadval = strtoq(newval, &endptr, 0);
		if (endptr == newval || *endptr != '\0') {
			return (luaL_error(L, "invalid quad_t: '%s'", (char *)newval));
		}
		newval = &quadval;
		newsize = sizeof(quadval);
		break;
#else
	case CTLTYPE_S64:
		intmaxval = strtoimax(newval, &endptr, 0);
		if (endptr == newval || *endptr != '\0' ||
				intmaxval > INT64_MAX || intmaxval < INT64_MIN) {
			return (luaL_error(L, "invalid int64_t integer: '%s'", (char *)newval));
		}
		i64val = (int64_t)intmaxval;
		newval = &i64val;
		newsize = sizeof(i64val);
		break;
	case CTLTYPE_U64:
		uintmaxval = strtoumax(newval, &endptr, 0);
		if (endptr == newval || *endptr != '\0' || uintmaxval > UINT64_MAX) {
			return (luaL_error(L, "invalid int64_t integer: '%s'", (char *)newval));
		}
		u64val = (uint64_t)uintmaxval;
		newval = &u64val;
		newsize = sizeof(u64val);
		break;
#endif
	case CTLTYPE_OPAQUE:
		if (strcmp(fmt, "T,dev_t") == 0) {
			set_T_dev_t(L, newval, &newval, &newsize);
			break;
		}
		/* FALLTHROUGH */
	default:
		return (luaL_error(L, "oid '%s' is type %d, cannot set that",
		    oid, kind & CTLTYPE));
	}

	if (sysctl(mib, len, NULL, NULL, newval, newsize) == -1) {
		switch (errno) {
		case EOPNOTSUPP:
			return (luaL_error(L, "%s: value is not available", oid));
		case ENOTDIR:
			return (luaL_error(L, "%s: specification is incomplete", oid));
		case ENOMEM:
			/* really? with ENOMEM !?! */
			return (luaL_error(L, "%s: type is unknown to this program", oid));
		default:
			i = strerror_r(errno, nvalbuf, sizeof(nvalbuf));
			if (i != 0)
				return (luaL_error(L, "strerror_r failed"));
			else
				return (luaL_error(L, "%s: %s", oid, nvalbuf));
		}
		/* NOTREACHED */
	}
	return (0);
}