xref: /titanic_53/usr/src/lib/libbsm/common/getdment.c (revision 7e3e5701c73b753fb9dd17a0cbe0568b4cdda39e)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
545916cd2Sjpk  * Common Development and Distribution License (the "License").
645916cd2Sjpk  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22*7e3e5701SJan Parcel  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate #include <string.h>
27*7e3e5701SJan Parcel #include <strings.h>
2845916cd2Sjpk #include <stdlib.h>
29*7e3e5701SJan Parcel #include <unistd.h>
30*7e3e5701SJan Parcel #include <limits.h>
31*7e3e5701SJan Parcel #include <device_info.h>
327c478bd9Sstevel@tonic-gate #include <bsm/devices.h>
3345916cd2Sjpk #include <bsm/devalloc.h>
347c478bd9Sstevel@tonic-gate 
3545916cd2Sjpk char *strtok_r(char *, const char *, char **);
3645916cd2Sjpk 
3745916cd2Sjpk /* externs from getdaent.c */
3845916cd2Sjpk extern char *trim_white(char *);
3945916cd2Sjpk extern int pack_white(char *);
4045916cd2Sjpk extern char *getdadmfield(char *, char *);
4145916cd2Sjpk extern int getdadmline(char *, int, FILE *);
427c478bd9Sstevel@tonic-gate 
437c478bd9Sstevel@tonic-gate static struct _dmapbuff {
4445916cd2Sjpk 	FILE		*_dmapf;	/* for /etc/security/device_maps */
457c478bd9Sstevel@tonic-gate 	devmap_t	_interpdevmap;
4645916cd2Sjpk 	char		_interpdmline[DA_BUFSIZE + 1];
477c478bd9Sstevel@tonic-gate 	char		*_DEVMAP;
487c478bd9Sstevel@tonic-gate } *__dmapbuff;
497c478bd9Sstevel@tonic-gate 
507c478bd9Sstevel@tonic-gate #define	dmapf	(_dmap->_dmapf)
517c478bd9Sstevel@tonic-gate #define	interpdevmap	(_dmap->_interpdevmap)
5245916cd2Sjpk #define	interpdmline	(_dmap->_interpdmline)
5345916cd2Sjpk #define	DEVMAPS_FILE	(_dmap->_DEVMAP)
5445916cd2Sjpk 
5545916cd2Sjpk devmap_t	*dmap_interpret(char *, devmap_t *);
5645916cd2Sjpk static devmap_t	*dmap_interpretf(char *, devmap_t *);
5745916cd2Sjpk static devmap_t *dmap_dlexpand(devmap_t *);
5845916cd2Sjpk 
5945916cd2Sjpk int	dmap_matchdev(devmap_t *, char *);
6045916cd2Sjpk int	dmap_matchname(devmap_t *, char *);
6145916cd2Sjpk 
6245916cd2Sjpk 
637c478bd9Sstevel@tonic-gate /*
6445916cd2Sjpk  * _dmapalloc -
6545916cd2Sjpk  *	allocates common buffers and structures.
6645916cd2Sjpk  *	returns pointer to the new structure, else returns NULL on error.
677c478bd9Sstevel@tonic-gate  */
6845916cd2Sjpk static struct _dmapbuff *
6945916cd2Sjpk _dmapalloc(void)
707c478bd9Sstevel@tonic-gate {
7145916cd2Sjpk 	struct _dmapbuff *_dmap = __dmapbuff;
7245916cd2Sjpk 
7345916cd2Sjpk 	if (_dmap == NULL) {
7445916cd2Sjpk 		_dmap = (struct _dmapbuff *)calloc((unsigned)1,
7545916cd2Sjpk 		    (unsigned)sizeof (*__dmapbuff));
7645916cd2Sjpk 		if (_dmap == NULL)
777c478bd9Sstevel@tonic-gate 			return (NULL);
7845916cd2Sjpk 		DEVMAPS_FILE = "/etc/security/device_maps";
7945916cd2Sjpk 		dmapf = NULL;
8045916cd2Sjpk 		__dmapbuff = _dmap;
817c478bd9Sstevel@tonic-gate 	}
8245916cd2Sjpk 
8345916cd2Sjpk 	return (_dmap);
847c478bd9Sstevel@tonic-gate }
8545916cd2Sjpk 
867c478bd9Sstevel@tonic-gate /*
8745916cd2Sjpk  * setdmapent -
8845916cd2Sjpk  *	rewinds the device_maps file to the beginning.
8945916cd2Sjpk  */
9045916cd2Sjpk void
9145916cd2Sjpk setdmapent(void)
9245916cd2Sjpk {
9345916cd2Sjpk 	struct _dmapbuff *_dmap = _dmapalloc();
9445916cd2Sjpk 
9545916cd2Sjpk 	if (_dmap == NULL)
9645916cd2Sjpk 		return;
9745916cd2Sjpk 	if (dmapf == NULL)
98004388ebScasper 		dmapf = fopen(DEVMAPS_FILE, "rF");
9945916cd2Sjpk 	else
10045916cd2Sjpk 		rewind(dmapf);
10145916cd2Sjpk }
10245916cd2Sjpk 
10345916cd2Sjpk /*
10445916cd2Sjpk  * enddmapent -
10545916cd2Sjpk  *	closes device_maps file.
10645916cd2Sjpk  */
10745916cd2Sjpk void
10845916cd2Sjpk enddmapent(void)
10945916cd2Sjpk {
11045916cd2Sjpk 	struct _dmapbuff *_dmap = _dmapalloc();
11145916cd2Sjpk 
11245916cd2Sjpk 	if (_dmap == NULL)
11345916cd2Sjpk 		return;
11445916cd2Sjpk 	if (dmapf != NULL) {
11545916cd2Sjpk 		(void) fclose(dmapf);
11645916cd2Sjpk 		dmapf = NULL;
11745916cd2Sjpk 	}
11845916cd2Sjpk }
11945916cd2Sjpk 
12045916cd2Sjpk void
12145916cd2Sjpk freedmapent(devmap_t *dmap)
12245916cd2Sjpk {
12345916cd2Sjpk 	char	**darp;
12445916cd2Sjpk 
12545916cd2Sjpk 	if ((darp = dmap->dmap_devarray) != NULL) {
12645916cd2Sjpk 		while (*darp != NULL)
12745916cd2Sjpk 			free(*darp++);
12845916cd2Sjpk 		free(dmap->dmap_devarray);
12945916cd2Sjpk 		dmap->dmap_devarray = NULL;
13045916cd2Sjpk 	}
13145916cd2Sjpk }
13245916cd2Sjpk 
13345916cd2Sjpk /*
13445916cd2Sjpk  * setdmapfile -
13545916cd2Sjpk  *	changes the default device_maps file to the one specified.
13645916cd2Sjpk  *	It does not close the previous file. If this is desired, enddmapent
13745916cd2Sjpk  *	should be called prior to setdampfile.
13845916cd2Sjpk  */
13945916cd2Sjpk void
14045916cd2Sjpk setdmapfile(char *file)
14145916cd2Sjpk {
14245916cd2Sjpk 	struct _dmapbuff *_dmap = _dmapalloc();
14345916cd2Sjpk 
14445916cd2Sjpk 	if (_dmap == NULL)
14545916cd2Sjpk 		return;
14645916cd2Sjpk 	if (dmapf != NULL) {
14745916cd2Sjpk 		(void) fclose(dmapf);
14845916cd2Sjpk 		dmapf = NULL;
14945916cd2Sjpk 	}
15045916cd2Sjpk 	DEVMAPS_FILE = file;
15145916cd2Sjpk }
15245916cd2Sjpk 
15345916cd2Sjpk /*
15445916cd2Sjpk  * getdmapent -
15545916cd2Sjpk  * 	When first called, returns a pointer to the first devmap_t structure
15645916cd2Sjpk  * 	in device_maps; thereafter, it returns a pointer to the next devmap_t
15745916cd2Sjpk  *	structure in the file. Thus successive calls can be used to read the
15845916cd2Sjpk  *	entire file.
15945916cd2Sjpk  *	call to getdmapent should be bracketed by setdmapent and enddmapent.
16045916cd2Sjpk  * 	returns pointer to devmap_t found, else returns NULL if no entry found
16145916cd2Sjpk  * 	or on error.
16245916cd2Sjpk  */
16345916cd2Sjpk devmap_t *
16445916cd2Sjpk getdmapent(void)
16545916cd2Sjpk {
16645916cd2Sjpk 	devmap_t		*dmap;
16745916cd2Sjpk 	struct _dmapbuff 	*_dmap = _dmapalloc();
16845916cd2Sjpk 
16945916cd2Sjpk 	if ((_dmap == 0) || (dmapf == NULL))
17045916cd2Sjpk 		return (NULL);
17145916cd2Sjpk 
17245916cd2Sjpk 	while (getdadmline(interpdmline, (int)sizeof (interpdmline),
17345916cd2Sjpk 	    dmapf) != 0) {
17445916cd2Sjpk 		if ((dmap = dmap_interpret(interpdmline,
17545916cd2Sjpk 		    &interpdevmap)) == NULL)
17645916cd2Sjpk 			continue;
17745916cd2Sjpk 		return (dmap);
17845916cd2Sjpk 	}
17945916cd2Sjpk 
18045916cd2Sjpk 	return (NULL);
18145916cd2Sjpk }
18245916cd2Sjpk 
18345916cd2Sjpk /*
18445916cd2Sjpk  * getdmapnam -
18545916cd2Sjpk  *	searches from the beginning of device_maps for the device specified by
18645916cd2Sjpk  *	its name.
18745916cd2Sjpk  *	call to getdmapnam should be bracketed by setdmapent and enddmapent.
18845916cd2Sjpk  * 	returns pointer to devmapt_t for the device if it is found, else
18945916cd2Sjpk  * 	returns NULL if device not found or in case of error.
19045916cd2Sjpk  */
19145916cd2Sjpk devmap_t *
19245916cd2Sjpk getdmapnam(char *name)
19345916cd2Sjpk {
19445916cd2Sjpk 	devmap_t		*dmap;
19545916cd2Sjpk 	struct _dmapbuff	*_dmap = _dmapalloc();
19645916cd2Sjpk 
19745916cd2Sjpk 	if ((name == NULL) || (_dmap == 0) || (dmapf == NULL))
19845916cd2Sjpk 		return (NULL);
19945916cd2Sjpk 
20045916cd2Sjpk 	while (getdadmline(interpdmline, (int)sizeof (interpdmline),
20145916cd2Sjpk 	    dmapf) != 0) {
20245916cd2Sjpk 		if (strstr(interpdmline, name) == NULL)
20345916cd2Sjpk 			continue;
20445916cd2Sjpk 		if ((dmap = dmap_interpretf(interpdmline,
20545916cd2Sjpk 		    &interpdevmap)) == NULL)
20645916cd2Sjpk 			continue;
20745916cd2Sjpk 		if (dmap_matchname(dmap, name)) {
20845916cd2Sjpk 			if ((dmap = dmap_dlexpand(dmap)) == NULL)
20945916cd2Sjpk 				continue;
21045916cd2Sjpk 			enddmapent();
21145916cd2Sjpk 			return (dmap);
21245916cd2Sjpk 		}
21345916cd2Sjpk 		freedmapent(dmap);
21445916cd2Sjpk 	}
21545916cd2Sjpk 
21645916cd2Sjpk 	return (NULL);
21745916cd2Sjpk }
21845916cd2Sjpk 
21945916cd2Sjpk /*
22045916cd2Sjpk  * getdmapdev -
22145916cd2Sjpk  *	searches from the beginning of device_maps for the device specified by
22245916cd2Sjpk  *	its logical name.
22345916cd2Sjpk  *	call to getdmapdev should be bracketed by setdmapent and enddmapent.
22445916cd2Sjpk  * 	returns  pointer to the devmap_t for the device if device is found,
22545916cd2Sjpk  *	else returns NULL if device not found or on error.
22645916cd2Sjpk  */
22745916cd2Sjpk devmap_t *
22845916cd2Sjpk getdmapdev(char *dev)
22945916cd2Sjpk {
23045916cd2Sjpk 	devmap_t		*dmap;
23145916cd2Sjpk 	struct _dmapbuff	*_dmap = _dmapalloc();
23245916cd2Sjpk 
23345916cd2Sjpk 	if ((dev == NULL) || (_dmap == 0) || (dmapf == NULL))
23445916cd2Sjpk 		return (NULL);
23545916cd2Sjpk 
23645916cd2Sjpk 	while (getdadmline(interpdmline, (int)sizeof (interpdmline),
23745916cd2Sjpk 	    dmapf) != 0) {
23845916cd2Sjpk 		if ((dmap = dmap_interpret(interpdmline,
23945916cd2Sjpk 		    &interpdevmap)) == NULL)
24045916cd2Sjpk 			continue;
24145916cd2Sjpk 		if (dmap_matchdev(dmap, dev)) {
24245916cd2Sjpk 			enddmapent();
24345916cd2Sjpk 			return (dmap);
24445916cd2Sjpk 		}
24545916cd2Sjpk 		freedmapent(dmap);
24645916cd2Sjpk 	}
24745916cd2Sjpk 
24845916cd2Sjpk 	return (NULL);
24945916cd2Sjpk }
25045916cd2Sjpk 
25145916cd2Sjpk /*
25245916cd2Sjpk  * getdmaptype -
25345916cd2Sjpk  *	searches from the beginning of device_maps for the device specified by
25445916cd2Sjpk  *	its type.
25545916cd2Sjpk  *	call to getdmaptype should be bracketed by setdmapent and enddmapent.
25645916cd2Sjpk  * 	returns pointer to devmap_t found, else returns NULL if no entry found
25745916cd2Sjpk  * 	or on error.
25845916cd2Sjpk  */
25945916cd2Sjpk devmap_t *
26045916cd2Sjpk getdmaptype(char *type)
26145916cd2Sjpk {
26245916cd2Sjpk 	devmap_t		*dmap;
26345916cd2Sjpk 	struct _dmapbuff	*_dmap = _dmapalloc();
26445916cd2Sjpk 
26545916cd2Sjpk 	if ((type == NULL) || (_dmap == 0) || (dmapf == NULL))
26645916cd2Sjpk 		return (NULL);
26745916cd2Sjpk 
26845916cd2Sjpk 	while (getdadmline(interpdmline, (int)sizeof (interpdmline),
26945916cd2Sjpk 	    dmapf) != 0) {
27045916cd2Sjpk 		if ((dmap = dmap_interpretf(interpdmline,
27145916cd2Sjpk 		    &interpdevmap)) == NULL)
27245916cd2Sjpk 			continue;
27345916cd2Sjpk 		if (dmap->dmap_devtype != NULL &&
27445916cd2Sjpk 		    strcmp(type, dmap->dmap_devtype) == 0) {
27545916cd2Sjpk 			if ((dmap = dmap_dlexpand(dmap)) == NULL)
27645916cd2Sjpk 				continue;
27745916cd2Sjpk 			return (dmap);
27845916cd2Sjpk 		}
27945916cd2Sjpk 		freedmapent(dmap);
28045916cd2Sjpk 	}
28145916cd2Sjpk 
28245916cd2Sjpk 	return (NULL);
28345916cd2Sjpk }
28445916cd2Sjpk 
28545916cd2Sjpk /*
286*7e3e5701SJan Parcel  * dmap_match_one_dev -
287*7e3e5701SJan Parcel  *    Checks if the specified devmap_t contains strings
288*7e3e5701SJan Parcel  *    for the same logical link as the device specified.
289*7e3e5701SJan Parcel  *    This guarantees that the beginnings of a devlist build
290*7e3e5701SJan Parcel  *    match a more-complete devlist for the same device.
291*7e3e5701SJan Parcel  *
292*7e3e5701SJan Parcel  *    Returns 1 for a match, else returns 0.
293*7e3e5701SJan Parcel  */
294*7e3e5701SJan Parcel static int
295*7e3e5701SJan Parcel dmap_match_one_dev(devmap_t *dmap, char *dev)
296*7e3e5701SJan Parcel {
297*7e3e5701SJan Parcel 	char **dva;
298*7e3e5701SJan Parcel 	char *dv;
299*7e3e5701SJan Parcel 
300*7e3e5701SJan Parcel 	if (dmap->dmap_devarray == NULL)
301*7e3e5701SJan Parcel 		return (0);
302*7e3e5701SJan Parcel 
303*7e3e5701SJan Parcel 	for (dva = dmap->dmap_devarray; (dv = *dva) != NULL; dva++) {
304*7e3e5701SJan Parcel 		if (strstr(dev, dv) != NULL)
305*7e3e5701SJan Parcel 			return (1);
306*7e3e5701SJan Parcel 	}
307*7e3e5701SJan Parcel 	return (0);
308*7e3e5701SJan Parcel }
309*7e3e5701SJan Parcel 
310*7e3e5701SJan Parcel /*
31145916cd2Sjpk  * dmap_matchdev -
31245916cd2Sjpk  * 	checks if the specified devmap_t is for the device specified.
31345916cd2Sjpk  *	returns 1 if it is, else returns 0.
31445916cd2Sjpk  */
31545916cd2Sjpk int
31645916cd2Sjpk dmap_matchdev(devmap_t *dmap, char *dev)
31745916cd2Sjpk {
31845916cd2Sjpk 	char **dva;
31945916cd2Sjpk 	char *dv;
32045916cd2Sjpk 
32145916cd2Sjpk 	if (dmap->dmap_devarray == NULL)
32245916cd2Sjpk 		return (0);
32345916cd2Sjpk 	for (dva = dmap->dmap_devarray; (dv = *dva) != NULL; dva ++) {
32445916cd2Sjpk 		if (strcmp(dv, dev) == 0)
32545916cd2Sjpk 			return (1);
32645916cd2Sjpk 	}
32745916cd2Sjpk 
32845916cd2Sjpk 	return (0);
32945916cd2Sjpk }
33045916cd2Sjpk 
33145916cd2Sjpk /*
332*7e3e5701SJan Parcel  * Requires a match of the /dev/?dsk links, not just the logical devname
333*7e3e5701SJan Parcel  * Returns 1 for match found, 0 for match not found, 2 for invalid arguments.
334*7e3e5701SJan Parcel  */
335*7e3e5701SJan Parcel int
336*7e3e5701SJan Parcel dmap_exact_dev(devmap_t *dmap, char *dev, int *num)
337*7e3e5701SJan Parcel {
338*7e3e5701SJan Parcel 	char *dv;
339*7e3e5701SJan Parcel 
340*7e3e5701SJan Parcel 	if ((dev == NULL) || (dmap->dmap_devname == NULL))
341*7e3e5701SJan Parcel 		return (2);
342*7e3e5701SJan Parcel 	dv = dmap->dmap_devname;
343*7e3e5701SJan Parcel 	dv +=  strcspn(dmap->dmap_devname, "0123456789");
344*7e3e5701SJan Parcel 	if (sscanf(dv, "%d", num) != 1)
345*7e3e5701SJan Parcel 		return (2);
346*7e3e5701SJan Parcel 	/* during some add processes, dev can be shorter than dmap */
347*7e3e5701SJan Parcel 	return (dmap_match_one_dev(dmap, dev));
348*7e3e5701SJan Parcel }
349*7e3e5701SJan Parcel 
350*7e3e5701SJan Parcel /*
35145916cd2Sjpk  * dmap_matchtype -
35245916cd2Sjpk  *	checks if the specified devmap_t is for the device specified.
35345916cd2Sjpk  *	returns 1 if it is, else returns 0.
35445916cd2Sjpk  */
35545916cd2Sjpk int
35645916cd2Sjpk dmap_matchtype(devmap_t *dmap, char *type)
35745916cd2Sjpk {
35845916cd2Sjpk 	if ((dmap->dmap_devtype == NULL) || (type == NULL))
35945916cd2Sjpk 		return (0);
36045916cd2Sjpk 
36145916cd2Sjpk 	return ((strcmp(dmap->dmap_devtype, type) == 0));
36245916cd2Sjpk }
36345916cd2Sjpk 
36445916cd2Sjpk /*
36545916cd2Sjpk  * dmap_matchname -
36645916cd2Sjpk  * 	checks if the specified devmap_t is for the device specified.
36745916cd2Sjpk  * 	returns 1 if it is, else returns 0.
36845916cd2Sjpk  */
36945916cd2Sjpk int
37045916cd2Sjpk dmap_matchname(devmap_t *dmap, char *name)
37145916cd2Sjpk {
37245916cd2Sjpk 	if (dmap->dmap_devname == NULL)
37345916cd2Sjpk 		return (0);
37445916cd2Sjpk 
37545916cd2Sjpk 	return ((strcmp(dmap->dmap_devname, name) == 0));
37645916cd2Sjpk }
37745916cd2Sjpk 
37845916cd2Sjpk /*
379*7e3e5701SJan Parcel  * dmap_physname: path to /devices device
380*7e3e5701SJan Parcel  * Returns:
381*7e3e5701SJan Parcel  *	strdup'd (i.e. malloc'd) real device file if successful
382*7e3e5701SJan Parcel  *      NULL on error
383*7e3e5701SJan Parcel  */
384*7e3e5701SJan Parcel char *
385*7e3e5701SJan Parcel dmap_physname(devmap_t *dmap)
386*7e3e5701SJan Parcel {
387*7e3e5701SJan Parcel 	char *oldlink;
388*7e3e5701SJan Parcel 	char stage_link[PATH_MAX + 1];
389*7e3e5701SJan Parcel 
390*7e3e5701SJan Parcel 	if ((dmap == NULL) || (dmap->dmap_devarray == NULL) ||
391*7e3e5701SJan Parcel 	    (dmap->dmap_devarray[0] == NULL))
392*7e3e5701SJan Parcel 		return (NULL);
393*7e3e5701SJan Parcel 
394*7e3e5701SJan Parcel 	(void) strncpy(stage_link, dmap->dmap_devarray[0], sizeof (stage_link));
395*7e3e5701SJan Parcel 
396*7e3e5701SJan Parcel 	if (devfs_resolve_link(stage_link, &oldlink) == 0)
397*7e3e5701SJan Parcel 		return (oldlink);
398*7e3e5701SJan Parcel 	return (NULL);
399*7e3e5701SJan Parcel }
400*7e3e5701SJan Parcel 
401*7e3e5701SJan Parcel /*
40245916cd2Sjpk  * dm_match -
40345916cd2Sjpk  *	calls dmap_matchname or dmap_matchtype as appropriate.
40445916cd2Sjpk  */
40545916cd2Sjpk int
40645916cd2Sjpk dm_match(devmap_t *dmap, da_args *dargs)
40745916cd2Sjpk {
40845916cd2Sjpk 	if (dargs->devinfo->devname)
40945916cd2Sjpk 		return (dmap_matchname(dmap, dargs->devinfo->devname));
41045916cd2Sjpk 	else if (dargs->devinfo->devtype)
41145916cd2Sjpk 		return (dmap_matchtype(dmap, dargs->devinfo->devtype));
41245916cd2Sjpk 
41345916cd2Sjpk 	return (0);
41445916cd2Sjpk }
41545916cd2Sjpk 
41645916cd2Sjpk /*
41745916cd2Sjpk  * dmap_interpret -
41845916cd2Sjpk  *	calls dmap_interpretf and dmap_dlexpand to parse devmap_t line.
41945916cd2Sjpk  *	returns  pointer to parsed devmapt_t entry, else returns NULL on error.
42045916cd2Sjpk  */
42145916cd2Sjpk devmap_t  *
42245916cd2Sjpk dmap_interpret(char *val, devmap_t *dm)
42345916cd2Sjpk {
42445916cd2Sjpk 	if (dmap_interpretf(val, dm) == NULL)
42545916cd2Sjpk 		return (NULL);
42645916cd2Sjpk 
42745916cd2Sjpk 	return (dmap_dlexpand(dm));
42845916cd2Sjpk }
42945916cd2Sjpk 
43045916cd2Sjpk /*
43145916cd2Sjpk  * dmap_interpretf -
43245916cd2Sjpk  * 	parses string "val" and initializes pointers in the given devmap_t to
43345916cd2Sjpk  * 	fields in "val".
43445916cd2Sjpk  * 	returns pointer to updated devmap_t.
43545916cd2Sjpk  */
43645916cd2Sjpk static devmap_t  *
43745916cd2Sjpk dmap_interpretf(char *val, devmap_t *dm)
43845916cd2Sjpk {
43945916cd2Sjpk 	dm->dmap_devname = getdadmfield(val, KV_TOKEN_DELIMIT);
44045916cd2Sjpk 	dm->dmap_devtype = getdadmfield(NULL, KV_TOKEN_DELIMIT);
44145916cd2Sjpk 	dm->dmap_devlist = getdadmfield(NULL, KV_TOKEN_DELIMIT);
44245916cd2Sjpk 	dm->dmap_devarray = NULL;
44345916cd2Sjpk 	if (dm->dmap_devname == NULL ||
44445916cd2Sjpk 	    dm->dmap_devtype == NULL ||
44545916cd2Sjpk 	    dm->dmap_devlist == NULL)
44645916cd2Sjpk 		return (NULL);
44745916cd2Sjpk 
44845916cd2Sjpk 	return (dm);
44945916cd2Sjpk }
45045916cd2Sjpk 
45145916cd2Sjpk /*
45245916cd2Sjpk  * dmap_dlexpand -
45345916cd2Sjpk  * 	expands dmap_devlist of the form `devlist_generate`
45445916cd2Sjpk  *	returns unexpanded form if there is no '\`' or in case of error.
45545916cd2Sjpk  */
45645916cd2Sjpk static devmap_t *
45745916cd2Sjpk dmap_dlexpand(devmap_t *dmp)
45845916cd2Sjpk {
45945916cd2Sjpk 	char	tmplist[DA_BUFSIZE + 1];
46045916cd2Sjpk 	char	*cp, *cpl, **darp;
46145916cd2Sjpk 	int	count;
46245916cd2Sjpk 	FILE	*expansion;
46345916cd2Sjpk 
46445916cd2Sjpk 	dmp->dmap_devarray = NULL;
46545916cd2Sjpk 	if (dmp->dmap_devlist == NULL)
46645916cd2Sjpk 		return (NULL);
46745916cd2Sjpk 	if (*(dmp->dmap_devlist) != '`') {
46845916cd2Sjpk 		(void) strcpy(tmplist, dmp->dmap_devlist);
46945916cd2Sjpk 	} else {
47045916cd2Sjpk 		(void) strcpy(tmplist, dmp->dmap_devlist + 1);
47145916cd2Sjpk 		if ((cp = strchr(tmplist, '`')) != NULL)
47245916cd2Sjpk 			*cp = '\0';
473004388ebScasper 		if ((expansion = popen(tmplist, "rF")) == NULL)
47445916cd2Sjpk 			return (NULL);
47545916cd2Sjpk 		count = fread(tmplist, 1, sizeof (tmplist) - 1, expansion);
47645916cd2Sjpk 		(void) pclose(expansion);
47745916cd2Sjpk 		tmplist[count] = '\0';
47845916cd2Sjpk 	}
47945916cd2Sjpk 
48045916cd2Sjpk 	/* cleanup the list */
48145916cd2Sjpk 	count = pack_white(tmplist);
48245916cd2Sjpk 	dmp->dmap_devarray = darp =
48345916cd2Sjpk 	    (char **)malloc((count + 2) * sizeof (char *));
48445916cd2Sjpk 	if (darp == NULL)
48545916cd2Sjpk 		return (NULL);
48645916cd2Sjpk 	cp = tmplist;
48745916cd2Sjpk 	while ((cp = strtok_r(cp, " ", &cpl)) != NULL) {
48845916cd2Sjpk 		*darp = strdup(cp);
48945916cd2Sjpk 		if (*darp == NULL) {
49045916cd2Sjpk 			freedmapent(dmp);
49145916cd2Sjpk 			return (NULL);
49245916cd2Sjpk 		}
49345916cd2Sjpk 		darp++;
49445916cd2Sjpk 		cp = NULL;
49545916cd2Sjpk 	}
49645916cd2Sjpk 	*darp = NULL;
49745916cd2Sjpk 
49845916cd2Sjpk 	return (dmp);
49945916cd2Sjpk }
50045916cd2Sjpk 
50145916cd2Sjpk /*
50245916cd2Sjpk  * dmapskip -
50345916cd2Sjpk  * 	scans input string to find next colon or end of line.
50445916cd2Sjpk  *	returns pointer to next char.
5057c478bd9Sstevel@tonic-gate  */
5067c478bd9Sstevel@tonic-gate static char *
50745916cd2Sjpk dmapskip(char *p)
5087c478bd9Sstevel@tonic-gate {
5097c478bd9Sstevel@tonic-gate 	while (*p && *p != ':' && *p != '\n')
5107c478bd9Sstevel@tonic-gate 		++p;
5117c478bd9Sstevel@tonic-gate 	if (*p == '\n')
5127c478bd9Sstevel@tonic-gate 		*p = '\0';
5137c478bd9Sstevel@tonic-gate 	else if (*p != '\0')
5147c478bd9Sstevel@tonic-gate 		*p++ = '\0';
51545916cd2Sjpk 
5167c478bd9Sstevel@tonic-gate 	return (p);
5177c478bd9Sstevel@tonic-gate }
51845916cd2Sjpk 
5197c478bd9Sstevel@tonic-gate /*
52045916cd2Sjpk  * dmapdskip -
52145916cd2Sjpk  * 	scans input string to find next space or end of line.
52245916cd2Sjpk  *	returns pointer to next char.
5237c478bd9Sstevel@tonic-gate  */
5247c478bd9Sstevel@tonic-gate static char *
52545916cd2Sjpk dmapdskip(p)
52645916cd2Sjpk 	register char *p;
5277c478bd9Sstevel@tonic-gate {
5287c478bd9Sstevel@tonic-gate 	while (*p && *p != ' ' && *p != '\n')
5297c478bd9Sstevel@tonic-gate 		++p;
5307c478bd9Sstevel@tonic-gate 	if (*p != '\0')
5317c478bd9Sstevel@tonic-gate 		*p++ = '\0';
53245916cd2Sjpk 
5337c478bd9Sstevel@tonic-gate 	return (p);
5347c478bd9Sstevel@tonic-gate }
5357c478bd9Sstevel@tonic-gate 
53645916cd2Sjpk char *
53745916cd2Sjpk getdmapfield(char *ptr)
5387c478bd9Sstevel@tonic-gate {
5397c478bd9Sstevel@tonic-gate 	static	char	*tptr;
54045916cd2Sjpk 
5417c478bd9Sstevel@tonic-gate 	if (ptr == NULL)
5427c478bd9Sstevel@tonic-gate 		ptr = tptr;
5437c478bd9Sstevel@tonic-gate 	if (ptr == NULL)
5447c478bd9Sstevel@tonic-gate 		return (NULL);
5457c478bd9Sstevel@tonic-gate 	tptr = dmapskip(ptr);
5467c478bd9Sstevel@tonic-gate 	ptr = trim_white(ptr);
5477c478bd9Sstevel@tonic-gate 	if (ptr == NULL)
5487c478bd9Sstevel@tonic-gate 		return (NULL);
5497c478bd9Sstevel@tonic-gate 	if (*ptr == NULL)
5507c478bd9Sstevel@tonic-gate 		return (NULL);
55145916cd2Sjpk 
5527c478bd9Sstevel@tonic-gate 	return (ptr);
5537c478bd9Sstevel@tonic-gate }
55445916cd2Sjpk 
55545916cd2Sjpk char *
55645916cd2Sjpk getdmapdfield(char *ptr)
5577c478bd9Sstevel@tonic-gate {
5587c478bd9Sstevel@tonic-gate 	static	char	*tptr;
5597c478bd9Sstevel@tonic-gate 	if (ptr != NULL) {
5607c478bd9Sstevel@tonic-gate 		ptr = trim_white(ptr);
5617c478bd9Sstevel@tonic-gate 	} else {
5627c478bd9Sstevel@tonic-gate 		ptr = tptr;
5637c478bd9Sstevel@tonic-gate 	}
5647c478bd9Sstevel@tonic-gate 	if (ptr == NULL)
5657c478bd9Sstevel@tonic-gate 		return (NULL);
5667c478bd9Sstevel@tonic-gate 	tptr = dmapdskip(ptr);
5677c478bd9Sstevel@tonic-gate 	if (ptr == NULL)
5687c478bd9Sstevel@tonic-gate 		return (NULL);
5697c478bd9Sstevel@tonic-gate 	if (*ptr == NULL)
5707c478bd9Sstevel@tonic-gate 		return (NULL);
57145916cd2Sjpk 
5727c478bd9Sstevel@tonic-gate 	return (ptr);
5737c478bd9Sstevel@tonic-gate }
574