FreeBSD/lib/libjail/jail.c
/*
 * Put a name and value into a jail parameter element, converting the value
 * to internal form.
 */
Put a name and value into a jail parameter element, converting the value
to internal form.
Put a name and value into a jail parameter element converting the value to internal form .
int
jailparam_import(struct jailparam *jp, const char *value)
{
	char *p, *ep, *tvalue;
	const char *avalue;
	int i, nval, fw;
	if (value == NULL)
		return (0);
	if ((jp->jp_ctltype & CTLTYPE) == CTLTYPE_STRING) {
		jp->jp_value = strdup(value);
		if (jp->jp_value == NULL) {
			strerror_r(errno, jail_errmsg, JAIL_ERRMSGLEN);
			return (-1);
		}
		return (0);
	}
	nval = 1;
	if (jp->jp_elemlen) {
		if (value[0] == '\0' || (value[0] == '-' && value[1] == '\0')) {
			jp->jp_value = strdup("");
			if (jp->jp_value == NULL) {
				strerror_r(errno, jail_errmsg, JAIL_ERRMSGLEN);
				return (-1);
			}
			jp->jp_valuelen = 0;
			return (0);
		}
		for (p = strchr(value, ','); p; p = strchr(p + 1, ','))
			nval++;
		jp->jp_valuelen = jp->jp_elemlen * nval;
	}
	jp->jp_value = malloc(jp->jp_valuelen);
	if (jp->jp_value == NULL) {
		strerror_r(errno, jail_errmsg, JAIL_ERRMSGLEN);
		return (-1);
	}
	avalue = value;
	for (i = 0; i < nval; i++) {
		fw = nval == 1 ? strlen(avalue) : strcspn(avalue, ",");
		switch (jp->jp_ctltype & CTLTYPE) {
		case CTLTYPE_INT:
			if (jp->jp_flags & (JP_BOOL | JP_NOBOOL)) {
				if (!jailparam_import_enum(bool_values, 2,
				    avalue, fw, &((int *)jp->jp_value)[i])) {
					snprintf(jail_errmsg,
					    JAIL_ERRMSGLEN, "%s: "
					    "unknown boolean value \"%.*s\"",
					    jp->jp_name, fw, avalue);
					errno = EINVAL;
					goto error;
				}
				break;
			}
			if (jp->jp_flags & JP_JAILSYS) {
				if (value[0] == '\0')
					((int *)jp->jp_value)[i] = JAIL_SYS_NEW;
				else if (!jailparam_import_enum(jailsys_values,
				    sizeof(jailsys_values) /
				    sizeof(jailsys_values[0]), avalue, fw,
				    &((int *)jp->jp_value)[i])) {
					snprintf(jail_errmsg,
					    JAIL_ERRMSGLEN, "%s: "
					    "unknown jailsys value \"%.*s\"",
					    jp->jp_name, fw, avalue);
					errno = EINVAL;
					goto error;
				}
				break;
			}
			((int *)jp->jp_value)[i] = strtol(avalue, &ep, 10);
		integer_test:
			if (ep != avalue + fw) {
				snprintf(jail_errmsg, JAIL_ERRMSGLEN,
				    "%s: non-integer value \"%.*s\"",
				    jp->jp_name, fw, avalue);
				errno = EINVAL;
				goto error;
			}
			break;
		case CTLTYPE_UINT:
			((unsigned *)jp->jp_value)[i] =
			    strtoul(avalue, &ep, 10);
			goto integer_test;
		case CTLTYPE_LONG:
			((long *)jp->jp_value)[i] = strtol(avalue, &ep, 10);
			goto integer_test;
		case CTLTYPE_ULONG:
			((unsigned long *)jp->jp_value)[i] =
			    strtoul(avalue, &ep, 10);
			goto integer_test;
		case CTLTYPE_S64:
			((int64_t *)jp->jp_value)[i] =
			    strtoimax(avalue, &ep, 10);
			goto integer_test;
		case CTLTYPE_U64:
			((uint64_t *)jp->jp_value)[i] =
			    strtoumax(avalue, &ep, 10);
			goto integer_test;
		case CTLTYPE_STRUCT:
			tvalue = alloca(fw + 1);
			strlcpy(tvalue, avalue, fw + 1);
			switch (jp->jp_structtype) {
			case JPS_IN_ADDR:
				if (inet_pton(AF_INET, tvalue,
				    &((struct in_addr *)jp->jp_value)[i]) != 1)
				{
					snprintf(jail_errmsg,
					    JAIL_ERRMSGLEN,
					    "%s: not an IPv4 address: %s",
					    jp->jp_name, tvalue);
					errno = EINVAL;
					goto error;
				}
				break;
			case JPS_IN6_ADDR:
				if (inet_pton(AF_INET6, tvalue,
				    &((struct in6_addr *)jp->jp_value)[i]) != 1)
				{
					snprintf(jail_errmsg,
					    JAIL_ERRMSGLEN,
					    "%s: not an IPv6 address: %s",
					    jp->jp_name, tvalue);
					errno = EINVAL;
					goto error;
				}
				break;
			default:
				goto unknown_type;
			}
			break;
		default:
		unknown_type:
			snprintf(jail_errmsg, JAIL_ERRMSGLEN,
			    "unknown type for %s", jp->jp_name);
			errno = ENOENT;
			goto error;
		}
		avalue += fw + 1;
	}
	return (0);
 error:
	free(jp->jp_value);
	jp->jp_value = NULL;
	return (-1);
}
int jailparam_import ( struct jailparam * jp , const char * value ) { char * p , * ep , * tvalue ; const char * avalue ; int i , nval , fw ; if ( value == NULL ) return ( 0 ) ; if ( ( jp -> jp_ctltype & CTLTYPE ) == CTLTYPE_STRING ) { jp -> jp_value = strdup ( value ) ; if ( jp -> jp_value == NULL ) { strerror_r ( errno , jail_errmsg , JAIL_ERRMSGLEN ) ; return ( -1 ) ; } return ( 0 ) ; } nval = 1 ; if ( jp -> jp_elemlen ) { if ( value [ 0 ] == ' \0 ' || ( value [ 0 ] == ' ' && value [ 1 ] == ' \0 ' ) ) { jp -> jp_value = strdup ( " " ) ; if ( jp -> jp_value == NULL ) { strerror_r ( errno , jail_errmsg , JAIL_ERRMSGLEN ) ; return ( -1 ) ; } jp -> jp_valuelen = 0 ; return ( 0 ) ; } for ( p = strchr ( value , ' ' ) ; p ; p = strchr ( p + 1 , ' ' ) ) nval ++ ; jp -> jp_valuelen = jp -> jp_elemlen * nval ; } jp -> jp_value = malloc ( jp -> jp_valuelen ) ; if ( jp -> jp_value == NULL ) { strerror_r ( errno , jail_errmsg , JAIL_ERRMSGLEN ) ; return ( -1 ) ; } avalue = value ; for ( i = 0 ; i < nval ; i ++ ) { fw = nval == 1 ? strlen ( avalue ) : strcspn ( avalue , " " ) ; switch ( jp -> jp_ctltype & CTLTYPE ) { case CTLTYPE_INT : if ( jp -> jp_flags & ( JP_BOOL | JP_NOBOOL ) ) { if ( ! jailparam_import_enum ( bool_values , 2 , avalue , fw , & ( ( int * ) jp -> jp_value ) [ i ] ) ) { snprintf ( jail_errmsg , JAIL_ERRMSGLEN , " " " \" \" " , jp -> jp_name , fw , avalue ) ; errno = EINVAL ; goto error ; } break ; } if ( jp -> jp_flags & JP_JAILSYS ) { if ( value [ 0 ] == ' \0 ' ) ( ( int * ) jp -> jp_value ) [ i ] = JAIL_SYS_NEW ; else if ( ! jailparam_import_enum ( jailsys_values , sizeof ( jailsys_values ) / sizeof ( jailsys_values [ 0 ] ) , avalue , fw , & ( ( int * ) jp -> jp_value ) [ i ] ) ) { snprintf ( jail_errmsg , JAIL_ERRMSGLEN , " " " \" \" " , jp -> jp_name , fw , avalue ) ; errno = EINVAL ; goto error ; } break ; } ( ( int * ) jp -> jp_value ) [ i ] = strtol ( avalue , & ep , 10 ) ; integer_test : if ( ep != avalue + fw ) { snprintf ( jail_errmsg , JAIL_ERRMSGLEN , " \" \" " , jp -> jp_name , fw , avalue ) ; errno = EINVAL ; goto error ; } break ; case CTLTYPE_UINT : ( ( unsigned * ) jp -> jp_value ) [ i ] = strtoul ( avalue , & ep , 10 ) ; goto integer_test ; case CTLTYPE_LONG : ( ( long * ) jp -> jp_value ) [ i ] = strtol ( avalue , & ep , 10 ) ; goto integer_test ; case CTLTYPE_ULONG : ( ( unsigned long * ) jp -> jp_value ) [ i ] = strtoul ( avalue , & ep , 10 ) ; goto integer_test ; case CTLTYPE_S64 : ( ( int64_t * ) jp -> jp_value ) [ i ] = strtoimax ( avalue , & ep , 10 ) ; goto integer_test ; case CTLTYPE_U64 : ( ( uint64_t * ) jp -> jp_value ) [ i ] = strtoumax ( avalue , & ep , 10 ) ; goto integer_test ; case CTLTYPE_STRUCT : tvalue = alloca ( fw + 1 ) ; strlcpy ( tvalue , avalue , fw + 1 ) ; switch ( jp -> jp_structtype ) { case JPS_IN_ADDR : if ( inet_pton ( AF_INET , tvalue , & ( ( struct in_addr * ) jp -> jp_value ) [ i ] ) != 1 ) { snprintf ( jail_errmsg , JAIL_ERRMSGLEN , " " , jp -> jp_name , tvalue ) ; errno = EINVAL ; goto error ; } break ; case JPS_IN6_ADDR : if ( inet_pton ( AF_INET6 , tvalue , & ( ( struct in6_addr * ) jp -> jp_value ) [ i ] ) != 1 ) { snprintf ( jail_errmsg , JAIL_ERRMSGLEN , " " , jp -> jp_name , tvalue ) ; errno = EINVAL ; goto error ; } break ; default : goto unknown_type ; } break ; default : unknown_type : snprintf ( jail_errmsg , JAIL_ERRMSGLEN , " " , jp -> jp_name ) ; errno = ENOENT ; goto error ; } avalue += fw + 1 ; } return ( 0 ) ; error : free ( jp -> jp_value ) ; jp -> jp_value = NULL ; return ( -1 ) ; }
Put a name and value into a jail parameter element, converting the value
 to internal form.
Put a name and value into a jail parameter element converting the value to internal form .
/*
				 * Allow setting a jailsys parameter to "new"
				 * in a booleanesque fashion.
				 */