Пример #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 int
parse(const char *string, int lineno)
{
	int len, i, j;
	const void *newval;
	const char *newvalstr = NULL;
	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 = NULL, 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) {
		warnx("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++;
		}
		newvalstr = 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 (newvalstr == 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) {
			warnx("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);
		}

		switch (kind & CTLTYPE) {
		case CTLTYPE_INT:
		case CTLTYPE_UINT:
		case CTLTYPE_LONG:
		case CTLTYPE_ULONG:
		case CTLTYPE_S64:
		case CTLTYPE_U64:
			if (strlen(newvalstr) == 0) {
				warnx("empty numeric value");
				return (1);
			}
			/* FALLTHROUGH */
		case CTLTYPE_STRING:
			break;
		default:
			warnx("oid '%s' is type %d,"
				" cannot set that%s", bufp,
				kind & CTLTYPE, line);
			return (1);
		}

		errno = 0;

		switch (kind & CTLTYPE) {
			case CTLTYPE_INT:
				if (strcmp(fmt, "IK") == 0)
					intval = strIKtoi(newvalstr, &endptr);
				else
					intval = (int)strtol(newvalstr, &endptr,
					    0);
				newval = &intval;
				newsize = sizeof(intval);
				break;
			case CTLTYPE_UINT:
				uintval = (int) strtoul(newvalstr, &endptr, 0);
				newval = &uintval;
				newsize = sizeof(uintval);
				break;
			case CTLTYPE_LONG:
				longval = strtol(newvalstr, &endptr, 0);
				newval = &longval;
				newsize = sizeof(longval);
				break;
			case CTLTYPE_ULONG:
				ulongval = strtoul(newvalstr, &endptr, 0);
				newval = &ulongval;
				newsize = sizeof(ulongval);
				break;
			case CTLTYPE_STRING:
				newval = newvalstr;
				break;
			case CTLTYPE_S64:
				i64val = strtoimax(newvalstr, &endptr, 0);
				newval = &i64val;
				newsize = sizeof(i64val);
				break;
			case CTLTYPE_U64:
				u64val = strtoumax(newvalstr, &endptr, 0);
				newval = &u64val;
				newsize = sizeof(u64val);
				break;
			default:
				/* NOTREACHED */
				abort();
		}

		if (errno != 0 || endptr == newvalstr ||
		    (endptr != NULL && *endptr != '\0')) {
			warnx("invalid %s '%s'%s", ctl_typename[kind & CTLTYPE],
			    newvalstr, 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);
}
Пример #2
0
/*
 * Parse a single numeric value, append it to 'newbuf', and update
 * 'newsize'.  Returns true if the value was parsed and false if the
 * value was invalid.  Non-numeric types (strings) are handled
 * directly in parse().
 */
static bool
parse_numeric(const char *newvalstr, const char *fmt, u_int kind,
    void **newbufp, size_t *newsizep)
{
	void *newbuf;
	const void *newval;
	int8_t i8val;
	uint8_t u8val;
	int16_t i16val;
	uint16_t u16val;
	int32_t i32val;
	uint32_t u32val;
	int intval;
	unsigned int uintval;
	long longval;
	unsigned long ulongval;
	int64_t i64val;
	uint64_t u64val;
	size_t valsize;
	char *endptr = NULL;
	
	errno = 0;

	switch (kind & CTLTYPE) {
	case CTLTYPE_INT:
		if (strncmp(fmt, "IK", 2) == 0)
			intval = strIKtoi(newvalstr, &endptr, fmt);
		else
			intval = (int)strtol(newvalstr, &endptr, 0);
		newval = &intval;
		valsize = sizeof(intval);
		break;
	case CTLTYPE_UINT:
		uintval = (int) strtoul(newvalstr, &endptr, 0);
		newval = &uintval;
		valsize = sizeof(uintval);
		break;
	case CTLTYPE_LONG:
		longval = strtol(newvalstr, &endptr, 0);
		newval = &longval;
		valsize = sizeof(longval);
		break;
	case CTLTYPE_ULONG:
		ulongval = strtoul(newvalstr, &endptr, 0);
		newval = &ulongval;
		valsize = sizeof(ulongval);
		break;
	case CTLTYPE_S8:
		i8val = (int8_t)strtol(newvalstr, &endptr, 0);
		newval = &i8val;
		valsize = sizeof(i8val);
		break;
	case CTLTYPE_S16:
		i16val = (int16_t)strtol(newvalstr, &endptr, 0);
		newval = &i16val;
		valsize = sizeof(i16val);
		break;
	case CTLTYPE_S32:
		i32val = (int32_t)strtol(newvalstr, &endptr, 0);
		newval = &i32val;
		valsize = sizeof(i32val);
		break;
	case CTLTYPE_S64:
		i64val = strtoimax(newvalstr, &endptr, 0);
		newval = &i64val;
		valsize = sizeof(i64val);
		break;
	case CTLTYPE_U8:
		u8val = (uint8_t)strtoul(newvalstr, &endptr, 0);
		newval = &u8val;
		valsize = sizeof(u8val);
		break;
	case CTLTYPE_U16:
		u16val = (uint16_t)strtoul(newvalstr, &endptr, 0);
		newval = &u16val;
		valsize = sizeof(u16val);
		break;
	case CTLTYPE_U32:
		u32val = (uint32_t)strtoul(newvalstr, &endptr, 0);
		newval = &u32val;
		valsize = sizeof(u32val);
		break;
	case CTLTYPE_U64:
		u64val = strtoumax(newvalstr, &endptr, 0);
		newval = &u64val;
		valsize = sizeof(u64val);
		break;
	default:
		/* NOTREACHED */
		abort();
	}
	
	if (errno != 0 || endptr == newvalstr ||
	    (endptr != NULL && *endptr != '\0'))
		return (false);

	newbuf = realloc(*newbufp, *newsizep + valsize);
	if (newbuf == NULL)
		err(1, "out of memory");
	memcpy((char *)newbuf + *newsizep, newval, valsize);
	*newbufp = newbuf;
	*newsizep += valsize;
	
	return (true);
}
Пример #3
0
static int
luaA_sysctl_set(lua_State *L)
{
	int	i;
	int	len;
	int	mib[CTL_MAXNAME];
	int8_t i8val;
	uint8_t u8val;
	int16_t i16val;
	uint16_t u16val;
	int32_t i32val;
	uint32_t u32val;
	int intval;
	unsigned int uintval;
	long longval;
	unsigned long ulongval;
	int64_t i64val;
	uint64_t u64val;
	u_int	kind;
	size_t	s;
	size_t newsize = 0;
	char	fmt[BUFSIZ];
	char	bufp[BUFSIZ];
	char	strerrorbuf[BUFSIZ];
	char	nvalbuf[BUFSIZ];
	char	*endptr;
	const void	*newval = NULL;
	const char *newvalstr = NULL;

	/* get first argument from lua */
	s = strlcpy(bufp, luaL_checkstring(L, 1), sizeof(bufp));
	if (s >= sizeof(bufp))
		return (luaL_error(L, "oid too long: '%s'", bufp));
	/* 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"));
	newvalstr = nvalbuf;
	newsize = s;

	len = name2oid(bufp, mib);
	if (len < 0)
		return (luaL_error(L, "unknown iod '%s'", bufp));
	if (oidfmt(mib, len, fmt, sizeof(fmt), &kind) != 0)
		return (luaL_error(L, "couldn't find format of oid '%s'", bufp));
	if ((kind & CTLTYPE) == CTLTYPE_NODE)
		return (luaL_error(L, "oid '%s' isn't a leaf node", bufp));
	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", bufp));
		else
			return (luaL_error(L, "oid '%s' is read only", bufp));
	}

	switch (kind & CTLTYPE) {
	case CTLTYPE_INT:
	case CTLTYPE_UINT:
	case CTLTYPE_LONG:
	case CTLTYPE_ULONG:
	case CTLTYPE_S8:
	case CTLTYPE_S16:
	case CTLTYPE_S32:
	case CTLTYPE_S64:
	case CTLTYPE_U8:
	case CTLTYPE_U16:
	case CTLTYPE_U32:
	case CTLTYPE_U64:
		if (strlen(newvalstr) == 0)
			return (luaL_error(L, "empty numeric value"));
		/* FALLTHROUGH */
	case CTLTYPE_STRING:
		break;
	default:
		return (luaL_error(L, "oid '%s' is type %d, cannot set that",
		    bufp, kind & CTLTYPE));
	}

	errno = 0;

	switch (kind & CTLTYPE) {
		case CTLTYPE_INT:
			if (strncmp(fmt, "IK", 2) == 0)
				intval = strIKtoi(newvalstr, &endptr, fmt);
			else
				intval = (int)strtol(newvalstr, &endptr,
				    0);
			newval = &intval;
			newsize = sizeof(intval);
			break;
		case CTLTYPE_UINT:
			uintval = (int) strtoul(newvalstr, &endptr, 0);
			newval = &uintval;
			newsize = sizeof(uintval);
			break;
		case CTLTYPE_LONG:
			longval = strtol(newvalstr, &endptr, 0);
			newval = &longval;
			newsize = sizeof(longval);
			break;
		case CTLTYPE_ULONG:
			ulongval = strtoul(newvalstr, &endptr, 0);
			newval = &ulongval;
			newsize = sizeof(ulongval);
			break;
		case CTLTYPE_STRING:
			newval = newvalstr;
			break;
		case CTLTYPE_S8:
			i8val = (int8_t)strtol(newvalstr, &endptr, 0);
			newval = &i8val;
			newsize = sizeof(i8val);
			break;
		case CTLTYPE_S16:
			i16val = (int16_t)strtol(newvalstr, &endptr,
			    0);
			newval = &i16val;
			newsize = sizeof(i16val);
			break;
		case CTLTYPE_S32:
			i32val = (int32_t)strtol(newvalstr, &endptr,
			    0);
			newval = &i32val;
			newsize = sizeof(i32val);
			break;
		case CTLTYPE_S64:
			i64val = strtoimax(newvalstr, &endptr, 0);
			newval = &i64val;
			newsize = sizeof(i64val);
			break;
		case CTLTYPE_U8:
			u8val = (uint8_t)strtoul(newvalstr, &endptr, 0);
			newval = &u8val;
			newsize = sizeof(u8val);
			break;
		case CTLTYPE_U16:
			u16val = (uint16_t)strtoul(newvalstr, &endptr,
			    0);
			newval = &u16val;
			newsize = sizeof(u16val);
			break;
		case CTLTYPE_U32:
			u32val = (uint32_t)strtoul(newvalstr, &endptr,
			    0);
			newval = &u32val;
			newsize = sizeof(u32val);
			break;
		case CTLTYPE_U64:
			u64val = strtoumax(newvalstr, &endptr, 0);
			newval = &u64val;
			newsize = sizeof(u64val);
			break;
		default:
			/* NOTREACHED */
			return (luaL_error(L, "unexpected type %d (bug)",
			    kind & CTLTYPE));
	}

	if (errno != 0 || endptr == newvalstr ||
	    (endptr != NULL && *endptr != '\0')) {
		return (luaL_error(L, "invalid %s '%s'",
		    ctl_typename[kind & CTLTYPE], newvalstr));
	}


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