xref: /onnv-gate/usr/src/lib/libbsm/common/getdaent.c (revision 4893:0177e932e294)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
51676Sjpk  * Common Development and Distribution License (the "License").
61676Sjpk  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*4893Stz204579  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
270Sstevel@tonic-gate 
281676Sjpk #include <ctype.h>
291676Sjpk #include <string.h>
301676Sjpk #include <stdlib.h>
311676Sjpk #include <tsol/label.h>
321676Sjpk #include <bsm/devices.h>
331676Sjpk #include <bsm/devalloc.h>
341676Sjpk 
351676Sjpk extern char *_strdup_null(char *);
360Sstevel@tonic-gate 
370Sstevel@tonic-gate static struct _dabuff {
381676Sjpk 	FILE		*_daf;	/* pointer into /etc/security/device_allocate */
391676Sjpk 	devalloc_t	_interpdevalloc;
401676Sjpk 	char		_interpdaline[DA_BUFSIZE + 1];
411676Sjpk 	char		 *_DEVALLOC;
420Sstevel@tonic-gate } *__dabuff;
430Sstevel@tonic-gate 
441676Sjpk #define	daf	(_da->_daf)
451676Sjpk #define	interpdevalloc	(_da->_interpdevalloc)
461676Sjpk #define	interpdaline	(_da->_interpdaline)
471676Sjpk #define	DEVALLOC_FILE	(_da->_DEVALLOC)
481676Sjpk static devalloc_t	*da_interpret(char *);
491676Sjpk 
501676Sjpk int da_matchname(devalloc_t *, char *);
511676Sjpk int da_matchtype(devalloc_t *, char *);
521676Sjpk 
531676Sjpk static int system_labeled = 0;
540Sstevel@tonic-gate 
550Sstevel@tonic-gate /*
561676Sjpk  * trim_white -
571676Sjpk  *	trims off leading and trailing white space from input string.
581676Sjpk  * 	The leading white space is skipped by moving the pointer forward.
591676Sjpk  * 	The trailing white space is removed by nulling the white space
601676Sjpk  *	characters.
611676Sjpk  *	returns pointer to non-white string, else returns NULL if input string
621676Sjpk  *	is null or if the resulting string has zero length.
630Sstevel@tonic-gate  */
641676Sjpk char *
trim_white(char * ptr)651676Sjpk trim_white(char *ptr)
660Sstevel@tonic-gate {
671676Sjpk 	char	*tptr;
681676Sjpk 
690Sstevel@tonic-gate 	if (ptr == NULL)
700Sstevel@tonic-gate 		return (NULL);
711676Sjpk 	while (isspace(*ptr))
720Sstevel@tonic-gate 		ptr++;
731676Sjpk 	tptr = ptr + strlen(ptr);
741676Sjpk 	while (tptr != ptr && isspace(tptr[-1]))
751676Sjpk 		--tptr;
761676Sjpk 	*tptr = '\0';
771676Sjpk 	if (*ptr == '\0')
780Sstevel@tonic-gate 		return (NULL);
791676Sjpk 
800Sstevel@tonic-gate 	return (ptr);
810Sstevel@tonic-gate }
820Sstevel@tonic-gate 
830Sstevel@tonic-gate /*
841676Sjpk  * pack_white -
851676Sjpk  *	trims off multiple occurrences of white space from input string.
861676Sjpk  * 	returns the number of spaces retained
870Sstevel@tonic-gate  */
881676Sjpk int
pack_white(char * ptr)891676Sjpk pack_white(char *ptr)
900Sstevel@tonic-gate {
911676Sjpk 	int	cnt = 0;
921676Sjpk 	char	*tptr, ch;
931676Sjpk 
941676Sjpk 	if (ptr == NULL)
951676Sjpk 		return (0);
961676Sjpk 	tptr = ptr;
971676Sjpk 	while (isspace(*tptr))
981676Sjpk 		tptr++;
991676Sjpk 	for (;;) {
1001676Sjpk 		while ((ch = *tptr) != '\0' && !isspace(ch)) {
1011676Sjpk 			*ptr++ = ch;
1021676Sjpk 			tptr++;
1031676Sjpk 		}
1041676Sjpk 		while (isspace(*tptr))
1051676Sjpk 			tptr++;
1061676Sjpk 		if (*tptr == '\0')
1071676Sjpk 			break;
1081676Sjpk 		*ptr++ = ' ';
1091676Sjpk 		cnt++;
1101676Sjpk 	}
1111676Sjpk 	*ptr = '\0';
1121676Sjpk 
1131676Sjpk 	return (cnt);
1140Sstevel@tonic-gate }
1150Sstevel@tonic-gate 
1160Sstevel@tonic-gate /*
1171676Sjpk  * getdadmline -
1181676Sjpk  *	reads one device_alloc/device_maps line from stream into buff of len
1191676Sjpk  *	bytes. Continued lines from stream are concatenated into one line in
1201676Sjpk  *	buff. Comments are removed from buff.
1211676Sjpk  *	returns the number of characters in buff, else returns 0 if no
1221676Sjpk  * 	characters are read or an error occurred.
1230Sstevel@tonic-gate  */
1241676Sjpk int
getdadmline(char * buff,int len,FILE * stream)1251676Sjpk getdadmline(char *buff, int len, FILE *stream)
1260Sstevel@tonic-gate {
1271676Sjpk 	int 	tmpcnt;
1281676Sjpk 	int 	charcnt = 0;
1291676Sjpk 	int 	fileerr = 0;
1301676Sjpk 	int 	contline = 0;
1311676Sjpk 	char 	*cp;
1321676Sjpk 	char 	*ccp;
1330Sstevel@tonic-gate 
1340Sstevel@tonic-gate 	do {
1350Sstevel@tonic-gate 		cp = buff;
1360Sstevel@tonic-gate 		*cp = NULL;
1370Sstevel@tonic-gate 		do {
1381676Sjpk 			contline = 0;
1390Sstevel@tonic-gate 			if (fgets(cp, len - charcnt, stream) == NULL) {
1400Sstevel@tonic-gate 				fileerr = 1;
1410Sstevel@tonic-gate 				break;
1420Sstevel@tonic-gate 			}
1431676Sjpk 			ccp = strchr(cp, '\n');
1440Sstevel@tonic-gate 			if (ccp != NULL) {
1451676Sjpk 				if (ccp != cp && ccp[-1] == '\\') {
1461676Sjpk 					ccp--;
1470Sstevel@tonic-gate 					contline = 1;
1481676Sjpk 				}
1491676Sjpk 				else
1500Sstevel@tonic-gate 					contline = 0;
1510Sstevel@tonic-gate 				*ccp = NULL;
1520Sstevel@tonic-gate 			}
1530Sstevel@tonic-gate 			tmpcnt = strlen(cp);
1541676Sjpk 			cp += tmpcnt;
1551676Sjpk 			charcnt += tmpcnt;
1560Sstevel@tonic-gate 		} while ((contline) || (charcnt == 0));
1570Sstevel@tonic-gate 		ccp = strpbrk(buff, "#");
1580Sstevel@tonic-gate 		if (ccp != NULL)
1590Sstevel@tonic-gate 			*ccp = NULL;
1600Sstevel@tonic-gate 		charcnt = strlen(buff);
1610Sstevel@tonic-gate 	} while ((fileerr == 0) && (charcnt == 0));
1621676Sjpk 
1631676Sjpk 	if (fileerr && !charcnt)
1640Sstevel@tonic-gate 		return (0);
1651676Sjpk 	else
1660Sstevel@tonic-gate 		return (charcnt);
1670Sstevel@tonic-gate }
1680Sstevel@tonic-gate 
1691676Sjpk /*
1701676Sjpk  * _daalloc -
1711676Sjpk  *	allocates common buffers and structures.
1721676Sjpk  * 	returns pointer to the new structure, else returns NULL on error.
1731676Sjpk  */
1741676Sjpk static struct _dabuff *
_daalloc(void)1751676Sjpk _daalloc(void)
1760Sstevel@tonic-gate {
1771676Sjpk 	struct _dabuff	*_da = __dabuff;
1780Sstevel@tonic-gate 
1791676Sjpk 	if (_da == NULL) {
1801676Sjpk 		_da = (struct _dabuff *)calloc((unsigned)1,
1811676Sjpk 		    (unsigned)sizeof (*__dabuff));
1821676Sjpk 		if (_da == NULL)
1831676Sjpk 			return (NULL);
1841676Sjpk 		DEVALLOC_FILE = "/etc/security/device_allocate";
1851676Sjpk 		daf = NULL;
1861676Sjpk 		__dabuff = _da;
1871676Sjpk 		system_labeled = is_system_labeled();
1880Sstevel@tonic-gate 	}
1891676Sjpk 
1901676Sjpk 	return (__dabuff);
1910Sstevel@tonic-gate }
1920Sstevel@tonic-gate 
1930Sstevel@tonic-gate /*
1941676Sjpk  * getdadmfield -
1951676Sjpk  *	gets individual fields separated by skip in ptr.
1960Sstevel@tonic-gate  */
1971676Sjpk char *
getdadmfield(char * ptr,char * skip)1981676Sjpk getdadmfield(char *ptr, char *skip)
1990Sstevel@tonic-gate {
2001676Sjpk 	static char	*tptr = NULL;
2011676Sjpk 	char		*pend;
2020Sstevel@tonic-gate 
2031676Sjpk 	/* check for a continuing search */
2041676Sjpk 	if (ptr == NULL)
2051676Sjpk 		ptr = tptr;
2061676Sjpk 	/* check for source end */
2071676Sjpk 	if (ptr == NULL || *ptr == '\0')
2081676Sjpk 		return (NULL);
2091676Sjpk 	/* find terminator */
2101676Sjpk 	pend = strpbrk(ptr, skip);
2111676Sjpk 	/* terminate and set continuation pointer */
2121676Sjpk 	if (pend != NULL) {
2131676Sjpk 		*pend++ = '\0';
2141676Sjpk 		tptr = pend;
2151676Sjpk 	} else
2161676Sjpk 		tptr = NULL;
2171676Sjpk 	/*
2181676Sjpk 	 * trim off any surrounding white space, return what's left
2191676Sjpk 	 */
2201676Sjpk 
2211676Sjpk 	return (trim_white(ptr));
2220Sstevel@tonic-gate }
2230Sstevel@tonic-gate 
2240Sstevel@tonic-gate /*
2251676Sjpk  * setdaent -
2261676Sjpk  *	rewinds the device_allocate file to the begining.
2270Sstevel@tonic-gate  */
2280Sstevel@tonic-gate 
2290Sstevel@tonic-gate void
setdaent(void)2301676Sjpk setdaent(void)
2310Sstevel@tonic-gate {
2321676Sjpk 	struct _dabuff	*_da = _daalloc();
2330Sstevel@tonic-gate 
2341676Sjpk 	if (_da == NULL)
2350Sstevel@tonic-gate 		return;
2361676Sjpk 	if (daf == NULL)
2371914Scasper 		daf = fopen(DEVALLOC_FILE, "rF");
2381676Sjpk 	else
2390Sstevel@tonic-gate 		rewind(daf);
2400Sstevel@tonic-gate }
2410Sstevel@tonic-gate 
2420Sstevel@tonic-gate /*
2431676Sjpk  * enddaent -
2441676Sjpk  *	closes device_allocate file.
2450Sstevel@tonic-gate  */
2460Sstevel@tonic-gate 
2470Sstevel@tonic-gate void
enddaent(void)2481676Sjpk enddaent(void)
2490Sstevel@tonic-gate {
2501676Sjpk 	struct _dabuff	*_da = _daalloc();
2510Sstevel@tonic-gate 
2521676Sjpk 	if (_da == NULL)
2530Sstevel@tonic-gate 		return;
2540Sstevel@tonic-gate 	if (daf != NULL) {
2550Sstevel@tonic-gate 		(void) fclose(daf);
2560Sstevel@tonic-gate 		daf = NULL;
2570Sstevel@tonic-gate 	}
2580Sstevel@tonic-gate }
2590Sstevel@tonic-gate 
2600Sstevel@tonic-gate /*
2611676Sjpk  * setdafile -
2621676Sjpk  *	changes the default device_allocate file to the one specified.
2631676Sjpk  * 	It does not close the previous file. If this is desired, enddaent
2641676Sjpk  *	should be called prior to setdafile.
2650Sstevel@tonic-gate  */
2660Sstevel@tonic-gate void
setdafile(char * file)2671676Sjpk setdafile(char *file)
2680Sstevel@tonic-gate {
2691676Sjpk 	struct _dabuff	*_da = _daalloc();
2700Sstevel@tonic-gate 
2711676Sjpk 	if (_da == NULL)
2720Sstevel@tonic-gate 		return;
2730Sstevel@tonic-gate 	if (daf != NULL) {
2740Sstevel@tonic-gate 		(void) fclose(daf);
2750Sstevel@tonic-gate 		daf = NULL;
2760Sstevel@tonic-gate 	}
2771676Sjpk 	DEVALLOC_FILE = file;
2780Sstevel@tonic-gate }
2790Sstevel@tonic-gate 
2801676Sjpk void
freedaent(devalloc_t * dap)2811676Sjpk freedaent(devalloc_t *dap)
2821676Sjpk {
2831676Sjpk 	if (dap == NULL)
2841676Sjpk 		return;
2851676Sjpk 	_kva_free(dap->da_devopts);
2861676Sjpk 	dap->da_devopts = NULL;
2871676Sjpk }
2880Sstevel@tonic-gate 
2890Sstevel@tonic-gate /*
2901676Sjpk  * getdaon -
2911676Sjpk  *	checks if device_allocate has string DEVICE_ALLOCATION=ON or
2921676Sjpk  *	DEVICE_ALLOCATION=OFF string in it.
2931676Sjpk  *	returns 1 if the string is DEVICE_ALLOCATION=ON, 0 if it is
2941676Sjpk  *	DEVICE_ALLOCATION=OFF, -1 if neither string present.
2951676Sjpk  */
2961676Sjpk int
getdaon()2971676Sjpk getdaon()
2981676Sjpk {
2991676Sjpk 	int		is_on = -1;
3001676Sjpk 	char		line1[DA_BUFSIZE + 1];
3011676Sjpk 	struct _dabuff *_da = _daalloc();
3021676Sjpk 
3031676Sjpk 	setdaent();
3041676Sjpk 	if ((_da == NULL) || (daf == NULL)) {
3051676Sjpk 		enddaent();
3061676Sjpk 		return (is_on);
3071676Sjpk 	}
3081676Sjpk 	while (getdadmline(line1, (int)sizeof (line1), daf) != 0) {
3091676Sjpk 		if (strncmp(line1, DA_ON_STR, (strlen(DA_ON_STR) - 1)) == 0) {
3101676Sjpk 			is_on = 1;
3111676Sjpk 			break;
3121676Sjpk 		} else if (strncmp(line1, DA_OFF_STR,
3131676Sjpk 		    (strlen(DA_OFF_STR) - 1)) == 0) {
3141676Sjpk 			is_on = 0;
3151676Sjpk 			break;
3161676Sjpk 		}
3171676Sjpk 	}
3181676Sjpk 	enddaent();
3191676Sjpk 
3201676Sjpk 	return (is_on);
3211676Sjpk }
3221676Sjpk 
3231676Sjpk /*
3241676Sjpk  * getdaent -
3251676Sjpk  *	When first called, returns a pointer to the first devalloc_t
3261676Sjpk  * 	structure in device_allocate; thereafter, it returns a pointer to the
3271676Sjpk  *	next devalloc_t structure in the file. Thus, successive calls can be
3281676Sjpk  *	used to search the entire file.
3291676Sjpk  *	call to getdaent should be bracketed by setdaent and enddaent.
3301676Sjpk  *	returns NULL on error.
3310Sstevel@tonic-gate  */
3320Sstevel@tonic-gate devalloc_t *
getdaent(void)3331676Sjpk getdaent(void)
3340Sstevel@tonic-gate {
3351676Sjpk 	char		line1[DA_BUFSIZE + 1];
3361676Sjpk 	devalloc_t	*da;
3371676Sjpk 	struct _dabuff	*_da = _daalloc();
3381676Sjpk 
3391676Sjpk 	if ((_da == 0) || (daf == NULL))
3401676Sjpk 		return (NULL);
3410Sstevel@tonic-gate 
3421676Sjpk 	while (getdadmline(line1, (int)sizeof (line1), daf) != 0) {
3431676Sjpk 		if ((strncmp(line1, DA_ON_STR, (strlen(DA_ON_STR) - 1)) == 0) ||
3441676Sjpk 		    (strncmp(line1, DA_OFF_STR, (strlen(DA_OFF_STR) - 1)) == 0))
3451676Sjpk 			continue;
3461676Sjpk 		if ((da = da_interpret(line1)) == NULL)
3471676Sjpk 			continue;
3481676Sjpk 		return (da);
3490Sstevel@tonic-gate 	}
3500Sstevel@tonic-gate 
3511676Sjpk 	return (NULL);
3520Sstevel@tonic-gate }
3530Sstevel@tonic-gate 
3540Sstevel@tonic-gate /*
3551676Sjpk  * getdanam
3561676Sjpk  * 	searches from the beginning of device_allocate for the device specified
3571676Sjpk  * 	by its name.
3581676Sjpk  *	call to getdanam should be bracketed by setdaent and enddaent.
3591676Sjpk  * 	returns pointer to devalloc_t for the device if it is found, else
3601676Sjpk  *	returns NULL if device not found or in case of error.
3610Sstevel@tonic-gate  */
3620Sstevel@tonic-gate devalloc_t *
getdanam(char * name)3631676Sjpk getdanam(char *name)
3640Sstevel@tonic-gate {
3651676Sjpk 	char		line[DA_BUFSIZE + 1];
3661676Sjpk 	devalloc_t	*da;
3671676Sjpk 	struct _dabuff	*_da = _daalloc();
3680Sstevel@tonic-gate 
3691676Sjpk 	if ((name == NULL) || (_da == 0) || (daf == NULL))
3700Sstevel@tonic-gate 		return (NULL);
3710Sstevel@tonic-gate 
3721676Sjpk 	while (getdadmline(line, (int)sizeof (line), daf) != 0) {
3731676Sjpk 		if (strstr(line, name) == NULL)
3741676Sjpk 			continue;
3751676Sjpk 		if ((da = da_interpret(line)) == NULL)
3761676Sjpk 			continue;
3771676Sjpk 		if (da_matchname(da, name)) {
3781676Sjpk 			enddaent();
3791676Sjpk 			return (da);
3801676Sjpk 		}
3811676Sjpk 		freedaent(da);
3821676Sjpk 	}
3831676Sjpk 
3841676Sjpk 	return (NULL);
3850Sstevel@tonic-gate }
3860Sstevel@tonic-gate 
3870Sstevel@tonic-gate /*
3881676Sjpk  * getdatype -
3891676Sjpk  * 	searches from the beginning of device_allocate for the device specified
3901676Sjpk  * 	by its type.
3911676Sjpk  *	call to getdatype should be bracketed by setdaent and enddaent.
3921676Sjpk  * 	returns pointer to devalloc_t for the device if it is found, else
3931676Sjpk  *	returns NULL if device not found or in case of error.
3940Sstevel@tonic-gate  */
3951676Sjpk devalloc_t *
getdatype(char * type)3961676Sjpk getdatype(char *type)
3970Sstevel@tonic-gate {
3981676Sjpk 	char		line1[DA_BUFSIZE + 1];
3991676Sjpk 	devalloc_t	*da;
4001676Sjpk 	struct _dabuff	*_da = _daalloc();
4011676Sjpk 
4021676Sjpk 	if ((type == NULL) || (_da == NULL) || (daf == NULL))
4031676Sjpk 		return (NULL);
4040Sstevel@tonic-gate 
4051676Sjpk 	while (getdadmline(line1, (int)sizeof (line1), daf) != 0) {
4061676Sjpk 		if (strstr(line1, type) == NULL)
4071676Sjpk 			continue;
4081676Sjpk 		if ((da = da_interpret(line1)) == NULL)
4091676Sjpk 			continue;
4101676Sjpk 		if (da_matchtype(da, type))
4111676Sjpk 			return (da);
4121676Sjpk 		freedaent(da);
4131676Sjpk 	}
4141676Sjpk 
4151676Sjpk 	return (NULL);
4161676Sjpk }
4171676Sjpk 
4181676Sjpk /*
4191676Sjpk  * da_matchname -
4201676Sjpk  *	checks if the specified devalloc_t is for the device specified.
4211676Sjpk  * 	returns 1 if it is, else returns 0.
4221676Sjpk  */
4231676Sjpk int
da_matchname(devalloc_t * dap,char * name)4241676Sjpk da_matchname(devalloc_t *dap, char *name)
4251676Sjpk {
4261676Sjpk 	if (dap->da_devname == NULL)
4270Sstevel@tonic-gate 		return (0);
4281676Sjpk 
4291676Sjpk 	return ((strcmp(dap->da_devname, name) == 0));
4301676Sjpk }
4311676Sjpk 
4321676Sjpk /*
4331676Sjpk  * da_matchtype -
4341676Sjpk  *	checks if the specified devalloc_t is for the device type specified.
4351676Sjpk  *	returns 1 if match found, else, returns 0.
4361676Sjpk  */
4371676Sjpk int
da_matchtype(devalloc_t * da,char * type)4381676Sjpk da_matchtype(devalloc_t *da, char *type)
4391676Sjpk {
4401676Sjpk 	if (da->da_devtype == NULL)
4410Sstevel@tonic-gate 		return (0);
4421676Sjpk 
4431676Sjpk 	return ((strcmp(da->da_devtype, type) == 0));
4441676Sjpk }
4451676Sjpk 
4461676Sjpk /*
4471676Sjpk  * da_match -
4481676Sjpk  * 	calls da_matchname or da_matchdev as appropriate.
4491676Sjpk  */
4501676Sjpk int
da_match(devalloc_t * dap,da_args * dargs)4511676Sjpk da_match(devalloc_t *dap, da_args *dargs)
4521676Sjpk {
4531676Sjpk 	if (dargs->devinfo->devname)
4541676Sjpk 		return (da_matchname(dap, dargs->devinfo->devname));
4551676Sjpk 	else if (dargs->devinfo->devtype)
4561676Sjpk 		return (da_matchtype(dap, dargs->devinfo->devtype));
4571676Sjpk 
4580Sstevel@tonic-gate 	return (0);
4590Sstevel@tonic-gate }
4600Sstevel@tonic-gate 
4610Sstevel@tonic-gate /*
4621676Sjpk  * da_interpret -
4631676Sjpk  *	parses val and initializes pointers in devalloc_t.
4641676Sjpk  * 	returns pointer to parsed devalloc_t entry, else returns NULL on error.
4650Sstevel@tonic-gate  */
4660Sstevel@tonic-gate static devalloc_t  *
da_interpret(char * val)4671676Sjpk da_interpret(char *val)
4680Sstevel@tonic-gate {
4691676Sjpk 	struct _dabuff	*_da = _daalloc();
4701676Sjpk 	char	*opts;
4711676Sjpk 	int	i;
4721676Sjpk 	kva_t	*kvap;
4731676Sjpk 	kv_t	*kvp;
4741676Sjpk 
4751676Sjpk 	if (_da == NULL)
4761676Sjpk 		return (NULL);
4771676Sjpk 
4781676Sjpk 	(void) strcpy(interpdaline, val);
4791676Sjpk 	interpdevalloc.da_devname = getdadmfield(interpdaline, KV_DELIMITER);
4801676Sjpk 	interpdevalloc.da_devtype = getdadmfield(NULL, KV_DELIMITER);
4811676Sjpk 	opts = getdadmfield(NULL, KV_DELIMITER);
4821676Sjpk 	(void) getdadmfield(NULL, KV_DELIMITER);	/* reserved field */
4831676Sjpk 	interpdevalloc.da_devauth = getdadmfield(NULL, KV_DELIMITER);
4841676Sjpk 	interpdevalloc.da_devexec = getdadmfield(NULL, KV_DELIMITER);
4851676Sjpk 	interpdevalloc.da_devopts = NULL;
4861676Sjpk 	if (interpdevalloc.da_devname == NULL ||
4871676Sjpk 	    interpdevalloc.da_devtype == NULL)
4881676Sjpk 		return (NULL);
4891676Sjpk 	if ((opts != NULL) &&
4901676Sjpk 	    (strncmp(opts, DA_RESERVED, strlen(DA_RESERVED)) != 0)) {
4911676Sjpk 		interpdevalloc.da_devopts =
4921676Sjpk 		    _str2kva(opts, KV_ASSIGN, KV_TOKEN_DELIMIT);
4931676Sjpk 	}
4941676Sjpk 	/* remove any extraneous whitespace in the options */
4951676Sjpk 	if ((kvap = interpdevalloc.da_devopts) != NULL) {
4961676Sjpk 		for (i = 0, kvp = kvap->data; i < kvap->length; i++, kvp++) {
4971676Sjpk 			(void) pack_white(kvp->key);
4981676Sjpk 			(void) pack_white(kvp->value);
4991676Sjpk 		}
5001676Sjpk 	}
5010Sstevel@tonic-gate 
5021676Sjpk 	if (system_labeled) {
5031676Sjpk 		/* if label range is not defined, use the default range. */
5041676Sjpk 		int		i = 0, nlen = 0;
5051676Sjpk 		char		*minstr = NULL, *maxstr = NULL;
5061676Sjpk 		kva_t		*nkvap = NULL;
5071676Sjpk 		kv_t		*ndata = NULL, *odata = NULL;
5080Sstevel@tonic-gate 
5091676Sjpk 		if (kvap == NULL) {
5101676Sjpk 			nlen = 2;	/* minlabel, maxlabel */
5111676Sjpk 		} else {
5121676Sjpk 			nlen += kvap->length;
5131676Sjpk 			if ((minstr = kva_match(kvap, DAOPT_MINLABEL)) == NULL)
5141676Sjpk 				nlen++;
5151676Sjpk 			if ((maxstr = kva_match(kvap, DAOPT_MAXLABEL)) == NULL)
5161676Sjpk 				nlen++;
5171676Sjpk 		}
5181676Sjpk 		if ((minstr != NULL) && (maxstr != NULL))
5191676Sjpk 			/*
5201676Sjpk 			 * label range provided; we don't need to construct
5211676Sjpk 			 * default range.
5221676Sjpk 			 */
5231676Sjpk 			goto out;
5241676Sjpk 		nkvap = _new_kva(nlen);
5251676Sjpk 		ndata = nkvap->data;
5261676Sjpk 		if (kvap != NULL) {
5271676Sjpk 			for (i = 0; i < kvap->length; i++) {
5281676Sjpk 				odata = kvap->data;
5291676Sjpk 				ndata[i].key = _strdup_null(odata[i].key);
5301676Sjpk 				ndata[i].value = _strdup_null(odata[i].value);
5311676Sjpk 				nkvap->length++;
5321676Sjpk 			}
5331676Sjpk 		}
5341676Sjpk 		if (minstr == NULL) {
5351676Sjpk 			ndata[i].key = strdup(DAOPT_MINLABEL);
5361676Sjpk 			ndata[i].value = strdup(DA_DEFAULT_MIN);
5371676Sjpk 			nkvap->length++;
5381676Sjpk 			i++;
5391676Sjpk 		}
5401676Sjpk 		if (maxstr == NULL) {
5411676Sjpk 			ndata[i].key = strdup(DAOPT_MAXLABEL);
5421676Sjpk 			ndata[i].value = strdup(DA_DEFAULT_MAX);
5431676Sjpk 			nkvap->length++;
5441676Sjpk 		}
5451676Sjpk 		interpdevalloc.da_devopts = nkvap;
5461676Sjpk 	}
5471676Sjpk 
5481676Sjpk out:
5490Sstevel@tonic-gate 	return (&interpdevalloc);
5500Sstevel@tonic-gate }
551