xref: /illumos-gate/usr/src/lib/libadm/common/getdev.c (revision 1da57d55)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
23*7c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
24*7c478bd9Sstevel@tonic-gate 
25*7c478bd9Sstevel@tonic-gate 
26*7c478bd9Sstevel@tonic-gate /*
27*7c478bd9Sstevel@tonic-gate  * Copyright (c) 1997, by Sun Microsystems, Inc.
28*7c478bd9Sstevel@tonic-gate  * All rights reserved.
29*7c478bd9Sstevel@tonic-gate  */
30*7c478bd9Sstevel@tonic-gate 
31*7c478bd9Sstevel@tonic-gate /*LINTLIBRARY*/
32*7c478bd9Sstevel@tonic-gate 
33*7c478bd9Sstevel@tonic-gate /*
34*7c478bd9Sstevel@tonic-gate  *  getdev.c
35*7c478bd9Sstevel@tonic-gate  *
36*7c478bd9Sstevel@tonic-gate  *  Contents:
37*7c478bd9Sstevel@tonic-gate  *	getdev()	List devices that match certain criteria.
38*7c478bd9Sstevel@tonic-gate  */
39*7c478bd9Sstevel@tonic-gate 
40*7c478bd9Sstevel@tonic-gate /*
41*7c478bd9Sstevel@tonic-gate  * Header files referenced:
42*7c478bd9Sstevel@tonic-gate  *	<sys/types.h>	System Data Types
43*7c478bd9Sstevel@tonic-gate  *	<errno.h>	Error handling
44*7c478bd9Sstevel@tonic-gate  *	<fcntl.h>	File controlling
45*7c478bd9Sstevel@tonic-gate  *	<ctype.h>	Character types
46*7c478bd9Sstevel@tonic-gate  *	<string.h>	String handling
47*7c478bd9Sstevel@tonic-gate  *	<devmgmt.h>	Global device-management def'ns
48*7c478bd9Sstevel@tonic-gate  *	"devtab.h"	Local device-management dev'ns
49*7c478bd9Sstevel@tonic-gate  */
50*7c478bd9Sstevel@tonic-gate 
51*7c478bd9Sstevel@tonic-gate #include	<sys/types.h>
52*7c478bd9Sstevel@tonic-gate #include	<errno.h>
53*7c478bd9Sstevel@tonic-gate #include	<fcntl.h>
54*7c478bd9Sstevel@tonic-gate #include	<ctype.h>
55*7c478bd9Sstevel@tonic-gate #include	<string.h>
56*7c478bd9Sstevel@tonic-gate #include	<devmgmt.h>
57*7c478bd9Sstevel@tonic-gate #include	"devtab.h"
58*7c478bd9Sstevel@tonic-gate #include	<stdlib.h>
59*7c478bd9Sstevel@tonic-gate 
60*7c478bd9Sstevel@tonic-gate /*
61*7c478bd9Sstevel@tonic-gate  * Local definitions
62*7c478bd9Sstevel@tonic-gate  *	NULL		Nil address
63*7c478bd9Sstevel@tonic-gate  *	TRUE		Boolean TRUE
64*7c478bd9Sstevel@tonic-gate  *	FALSE		Boolean FALSE
65*7c478bd9Sstevel@tonic-gate  */
66*7c478bd9Sstevel@tonic-gate 
67*7c478bd9Sstevel@tonic-gate #ifndef	NULL
68*7c478bd9Sstevel@tonic-gate #define	NULL			0
69*7c478bd9Sstevel@tonic-gate #endif
70*7c478bd9Sstevel@tonic-gate 
71*7c478bd9Sstevel@tonic-gate #ifndef	TRUE
72*7c478bd9Sstevel@tonic-gate #define	TRUE			('t')
73*7c478bd9Sstevel@tonic-gate #endif
74*7c478bd9Sstevel@tonic-gate 
75*7c478bd9Sstevel@tonic-gate #ifndef	FALSE
76*7c478bd9Sstevel@tonic-gate #define	FALSE			0
77*7c478bd9Sstevel@tonic-gate #endif
78*7c478bd9Sstevel@tonic-gate 
79*7c478bd9Sstevel@tonic-gate 
80*7c478bd9Sstevel@tonic-gate /*
81*7c478bd9Sstevel@tonic-gate  *  Comparison values.  These values are placed in the struct srch
82*7c478bd9Sstevel@tonic-gate  *  structure by buildsearchlist() and are used to compare values
83*7c478bd9Sstevel@tonic-gate  *  in matches().
84*7c478bd9Sstevel@tonic-gate  *	EQUAL		Attribute must equal this value
85*7c478bd9Sstevel@tonic-gate  *	NOTEQUAL	Attribute must not equal this value
86*7c478bd9Sstevel@tonic-gate  *	EXISTS		Attribute must exist
87*7c478bd9Sstevel@tonic-gate  *	NOEXISTS	Attribute must not exist
88*7c478bd9Sstevel@tonic-gate  *	IGNORE		Ignore this entry
89*7c478bd9Sstevel@tonic-gate  *	ENDLIST		This entry ends the list
90*7c478bd9Sstevel@tonic-gate  */
91*7c478bd9Sstevel@tonic-gate 
92*7c478bd9Sstevel@tonic-gate #define	EQUAL			1
93*7c478bd9Sstevel@tonic-gate #define	NOTEQUAL		2
94*7c478bd9Sstevel@tonic-gate #define	EXISTS			3
95*7c478bd9Sstevel@tonic-gate #define	NOEXISTS		4
96*7c478bd9Sstevel@tonic-gate #define	IGNORE			5
97*7c478bd9Sstevel@tonic-gate #define	ENDLIST			0
98*7c478bd9Sstevel@tonic-gate 
99*7c478bd9Sstevel@tonic-gate 
100*7c478bd9Sstevel@tonic-gate /*
101*7c478bd9Sstevel@tonic-gate  *  Structure definitions:
102*7c478bd9Sstevel@tonic-gate  * 	deviceent	Defines a device that matches criteria
103*7c478bd9Sstevel@tonic-gate  *	srch		Describes a criteria
104*7c478bd9Sstevel@tonic-gate  */
105*7c478bd9Sstevel@tonic-gate 
106*7c478bd9Sstevel@tonic-gate struct deviceent {
107*7c478bd9Sstevel@tonic-gate 	struct deviceent	*next;	/* Pointer to next item in the list */
108*7c478bd9Sstevel@tonic-gate 	char			*name;	/* Presentation name of the device */
109*7c478bd9Sstevel@tonic-gate };
110*7c478bd9Sstevel@tonic-gate 
111*7c478bd9Sstevel@tonic-gate struct srch {
112*7c478bd9Sstevel@tonic-gate 	char   *name;			/* Name of field to compare */
113*7c478bd9Sstevel@tonic-gate 	char   *cmp;			/* Value to compare against */
114*7c478bd9Sstevel@tonic-gate 	int	fcn;			/* Type of comparison (see above) */
115*7c478bd9Sstevel@tonic-gate };
116*7c478bd9Sstevel@tonic-gate 
117*7c478bd9Sstevel@tonic-gate 
118*7c478bd9Sstevel@tonic-gate /*
119*7c478bd9Sstevel@tonic-gate  * Local functions referenced
120*7c478bd9Sstevel@tonic-gate  *	oktoaddtolist()		Determines if device can be added to the
121*7c478bd9Sstevel@tonic-gate  *				list by examining the devices list and
122*7c478bd9Sstevel@tonic-gate  *				the options governing the search
123*7c478bd9Sstevel@tonic-gate  *	initdevicelist()	Initializes the linked list of devices
124*7c478bd9Sstevel@tonic-gate  *				to be included in the list-to-return
125*7c478bd9Sstevel@tonic-gate  *	freedevicelist()	Frees the resources allocated to the linked
126*7c478bd9Sstevel@tonic-gate  *				list of devices
127*7c478bd9Sstevel@tonic-gate  *	addtodevicelist()	Adds an entry to the linked list of devices
128*7c478bd9Sstevel@tonic-gate  *	buildsearchlist()	Builds a list of struct srch structures from
129*7c478bd9Sstevel@tonic-gate  *				the criteria strings
130*7c478bd9Sstevel@tonic-gate  *	freesearchlist()	Frees the resources allocated to the list of
131*7c478bd9Sstevel@tonic-gate  *				struct srch structures
132*7c478bd9Sstevel@tonic-gate  *	buildreturnlist()	Builds the list of devices to return from the
133*7c478bd9Sstevel@tonic-gate  *				linked list of devices we've accumulated
134*7c478bd9Sstevel@tonic-gate  *	makealiaslist()		Builds a list of aliases from the list of
135*7c478bd9Sstevel@tonic-gate  *				devices presented by the caller
136*7c478bd9Sstevel@tonic-gate  *	freealiaslist()		Frees the resources allocated to the list of
137*7c478bd9Sstevel@tonic-gate  *				devices aliases
138*7c478bd9Sstevel@tonic-gate  *	getnextmatch()		Get the next device that matches the search
139*7c478bd9Sstevel@tonic-gate  *				criteria
140*7c478bd9Sstevel@tonic-gate  *	matchallcriteria()	See if the device attributes match all of the
141*7c478bd9Sstevel@tonic-gate  *				search criteria
142*7c478bd9Sstevel@tonic-gate  *	matchanycriteria()	See if the device attributes match any of the
143*7c478bd9Sstevel@tonic-gate  *				search criteria
144*7c478bd9Sstevel@tonic-gate  *	matches()		See if the criteria and attribute match
145*7c478bd9Sstevel@tonic-gate  */
146*7c478bd9Sstevel@tonic-gate 
147*7c478bd9Sstevel@tonic-gate static	char		*oktoaddtolist(char   *, char  **, char  **, int);
148*7c478bd9Sstevel@tonic-gate static	void		initdevicelist(void);
149*7c478bd9Sstevel@tonic-gate static	void		freedevicelist(void);
150*7c478bd9Sstevel@tonic-gate static	int		addtodevicelist(char *);
151*7c478bd9Sstevel@tonic-gate static	struct srch	*buildsearchlist(char **);
152*7c478bd9Sstevel@tonic-gate static	void 		freesearchlist(struct srch *);
153*7c478bd9Sstevel@tonic-gate static	char		**buildreturnlist(void);
154*7c478bd9Sstevel@tonic-gate static	char		**makealiaslist(char **);
155*7c478bd9Sstevel@tonic-gate static	void		freealiaslist(char **);
156*7c478bd9Sstevel@tonic-gate static	char		*getnextmatch(struct srch *, int);
157*7c478bd9Sstevel@tonic-gate static	int		matchallcriteria(struct devtabent *, struct srch *);
158*7c478bd9Sstevel@tonic-gate static	int		matchanycriteria(struct devtabent *, struct srch *);
159*7c478bd9Sstevel@tonic-gate static	int		matches(char *, char *, int);
160*7c478bd9Sstevel@tonic-gate 
161*7c478bd9Sstevel@tonic-gate 
162*7c478bd9Sstevel@tonic-gate /*
163*7c478bd9Sstevel@tonic-gate  * Global Data
164*7c478bd9Sstevel@tonic-gate  */
165*7c478bd9Sstevel@tonic-gate 
166*7c478bd9Sstevel@tonic-gate /*
167*7c478bd9Sstevel@tonic-gate  * Static Data
168*7c478bd9Sstevel@tonic-gate  *	devicelisthead	The first item (dummy) in the linked list of devices
169*7c478bd9Sstevel@tonic-gate  *			we're building
170*7c478bd9Sstevel@tonic-gate  *	devicelist	Structure describing the linked list of devices
171*7c478bd9Sstevel@tonic-gate  */
172*7c478bd9Sstevel@tonic-gate 
173*7c478bd9Sstevel@tonic-gate static	struct deviceent	devicelisthead;
174*7c478bd9Sstevel@tonic-gate static	struct {
175*7c478bd9Sstevel@tonic-gate 	struct deviceent	*head;
176*7c478bd9Sstevel@tonic-gate 	int			count;
177*7c478bd9Sstevel@tonic-gate } devicelist = {&devicelisthead, 0};
178*7c478bd9Sstevel@tonic-gate 
179*7c478bd9Sstevel@tonic-gate /*
180*7c478bd9Sstevel@tonic-gate  *  char **getdev(devices, criteria, options)
181*7c478bd9Sstevel@tonic-gate  *	char  **devices
182*7c478bd9Sstevel@tonic-gate  *	char  **criteria
183*7c478bd9Sstevel@tonic-gate  *	int	options
184*7c478bd9Sstevel@tonic-gate  *
185*7c478bd9Sstevel@tonic-gate  *	This function builds a list of devices that match criteria,
186*7c478bd9Sstevel@tonic-gate  *	governed by the device list.
187*7c478bd9Sstevel@tonic-gate  *
188*7c478bd9Sstevel@tonic-gate  *  Arguments:
189*7c478bd9Sstevel@tonic-gate  *	devices		The list of devices to select from or the list of
190*7c478bd9Sstevel@tonic-gate  *			devices to exclude, depending on the value of
191*7c478bd9Sstevel@tonic-gate  *			"options"
192*7c478bd9Sstevel@tonic-gate  *	criteria	The list of criteria governing the device selection
193*7c478bd9Sstevel@tonic-gate  *			Of the form <attr><op><val>
194*7c478bd9Sstevel@tonic-gate  *	options		Options controlling the device selection.  May require
195*7c478bd9Sstevel@tonic-gate  *			that a device meet all of the criteria (default is
196*7c478bd9Sstevel@tonic-gate  *			any one of the criteria), or may require that the
197*7c478bd9Sstevel@tonic-gate  *			devices in the list of devices be excluded from the
198*7c478bd9Sstevel@tonic-gate  *			generated list (default is to select only those
199*7c478bd9Sstevel@tonic-gate  * 			devices in the list)
200*7c478bd9Sstevel@tonic-gate  *
201*7c478bd9Sstevel@tonic-gate  *  Returns:  char **
202*7c478bd9Sstevel@tonic-gate  *	The address of the first item in the list of devices that meet
203*7c478bd9Sstevel@tonic-gate  *	the selection criteria
204*7c478bd9Sstevel@tonic-gate  */
205*7c478bd9Sstevel@tonic-gate 
206*7c478bd9Sstevel@tonic-gate char  **
getdev(char ** devices,char ** criteria,int options)207*7c478bd9Sstevel@tonic-gate getdev(
208*7c478bd9Sstevel@tonic-gate 	char  **devices,		/* List of devices to constrain */
209*7c478bd9Sstevel@tonic-gate 	char  **criteria,		/* List of selection criteria */
210*7c478bd9Sstevel@tonic-gate 	int	options)		/* Options governing the search */
211*7c478bd9Sstevel@tonic-gate {
212*7c478bd9Sstevel@tonic-gate 	/* Automatic data */
213*7c478bd9Sstevel@tonic-gate 	char		**aliases;	/* List of constraining devices */
214*7c478bd9Sstevel@tonic-gate 	char		**returnlist;	/* List of ptrs to aliases to return */
215*7c478bd9Sstevel@tonic-gate 	struct srch	*searchlist;	/* Pointer to searching criteria */
216*7c478bd9Sstevel@tonic-gate 	char		*entry;		/* Pointer to alias in record */
217*7c478bd9Sstevel@tonic-gate 	int		errflag;	/* FLAG:  TRUE if error */
218*7c478bd9Sstevel@tonic-gate 
219*7c478bd9Sstevel@tonic-gate 
220*7c478bd9Sstevel@tonic-gate 	/*
221*7c478bd9Sstevel@tonic-gate 	 *  Initializations
222*7c478bd9Sstevel@tonic-gate 	 */
223*7c478bd9Sstevel@tonic-gate 
224*7c478bd9Sstevel@tonic-gate 	/*  Make sure the exclude/include list is all aliases */
225*7c478bd9Sstevel@tonic-gate 	aliases = makealiaslist(devices);
226*7c478bd9Sstevel@tonic-gate 	if (devices && !aliases)
227*7c478bd9Sstevel@tonic-gate 		return (NULL);
228*7c478bd9Sstevel@tonic-gate 
229*7c478bd9Sstevel@tonic-gate 	/*  Build the search list  */
230*7c478bd9Sstevel@tonic-gate 	if (criteria) {
231*7c478bd9Sstevel@tonic-gate 	    if (!(searchlist = buildsearchlist(criteria)))
232*7c478bd9Sstevel@tonic-gate 		return (NULL);
233*7c478bd9Sstevel@tonic-gate 	} else searchlist = NULL;
234*7c478bd9Sstevel@tonic-gate 
235*7c478bd9Sstevel@tonic-gate 	/*  Initialize searching  */
236*7c478bd9Sstevel@tonic-gate 	initdevicelist();
237*7c478bd9Sstevel@tonic-gate 	_setdevtab();
238*7c478bd9Sstevel@tonic-gate 
239*7c478bd9Sstevel@tonic-gate 
240*7c478bd9Sstevel@tonic-gate 	/*
241*7c478bd9Sstevel@tonic-gate 	 *  Keep on going until we get no more matches
242*7c478bd9Sstevel@tonic-gate 	 */
243*7c478bd9Sstevel@tonic-gate 
244*7c478bd9Sstevel@tonic-gate 	errflag = FALSE;
245*7c478bd9Sstevel@tonic-gate 	while (!errflag && (entry = getnextmatch(searchlist, options))) {
246*7c478bd9Sstevel@tonic-gate 	    if (entry = oktoaddtolist(entry, devices, aliases, options)) {
247*7c478bd9Sstevel@tonic-gate 		errflag = addtodevicelist(entry);
248*7c478bd9Sstevel@tonic-gate 	    }
249*7c478bd9Sstevel@tonic-gate 	}
250*7c478bd9Sstevel@tonic-gate 
251*7c478bd9Sstevel@tonic-gate 
252*7c478bd9Sstevel@tonic-gate 	/*
253*7c478bd9Sstevel@tonic-gate 	 *  Clean up:
254*7c478bd9Sstevel@tonic-gate 	 *    -	Free the entry space we've allocated.
255*7c478bd9Sstevel@tonic-gate 	 *    -	Close the device table.
256*7c478bd9Sstevel@tonic-gate 	 *    - Build the list to return to the caller.
257*7c478bd9Sstevel@tonic-gate 	 *    - Free the accumulate device space (but not the strings!)
258*7c478bd9Sstevel@tonic-gate 	 *    - Free the alias list
259*7c478bd9Sstevel@tonic-gate 	 *    - Return the built list to the caller.
260*7c478bd9Sstevel@tonic-gate 	 */
261*7c478bd9Sstevel@tonic-gate 
262*7c478bd9Sstevel@tonic-gate 	returnlist = buildreturnlist();
263*7c478bd9Sstevel@tonic-gate 	freedevicelist();
264*7c478bd9Sstevel@tonic-gate 	freealiaslist(aliases);
265*7c478bd9Sstevel@tonic-gate 	_enddevtab();
266*7c478bd9Sstevel@tonic-gate 	return (returnlist);
267*7c478bd9Sstevel@tonic-gate }
268*7c478bd9Sstevel@tonic-gate 
269*7c478bd9Sstevel@tonic-gate /*
270*7c478bd9Sstevel@tonic-gate  *  char *oktoaddtolist(devtabentry, devices, aliases, options)
271*7c478bd9Sstevel@tonic-gate  *	char   *devtabentry
272*7c478bd9Sstevel@tonic-gate  *	char  **devices
273*7c478bd9Sstevel@tonic-gate  *	char  **aliases
274*7c478bd9Sstevel@tonic-gate  *	int	options
275*7c478bd9Sstevel@tonic-gate  *
276*7c478bd9Sstevel@tonic-gate  *	This function determines the device "devtabentry" can be
277*7c478bd9Sstevel@tonic-gate  *	added to the list of devices we're accumulating.  If so,
278*7c478bd9Sstevel@tonic-gate  *	it returns the device name (not the alias).
279*7c478bd9Sstevel@tonic-gate  *
280*7c478bd9Sstevel@tonic-gate  *  Arguments:
281*7c478bd9Sstevel@tonic-gate  *	devtabentry	The device alias that may or may not belong in the
282*7c478bd9Sstevel@tonic-gate  *			list we're building.
283*7c478bd9Sstevel@tonic-gate  *	devices		The devices specified by the caller
284*7c478bd9Sstevel@tonic-gate  *	aliases		The aliases of the devices specified by the caller
285*7c478bd9Sstevel@tonic-gate  *			(1-1 correspondence with "devices")
286*7c478bd9Sstevel@tonic-gate  *	options		Options controlling the search
287*7c478bd9Sstevel@tonic-gate  */
288*7c478bd9Sstevel@tonic-gate 
289*7c478bd9Sstevel@tonic-gate static	char *
oktoaddtolist(char * devtabentry,char ** devices,char ** aliases,int options)290*7c478bd9Sstevel@tonic-gate oktoaddtolist(
291*7c478bd9Sstevel@tonic-gate 	char   *devtabentry,	/* Alias to check against list */
292*7c478bd9Sstevel@tonic-gate 	char  **devices,	/* List of devices to check against */
293*7c478bd9Sstevel@tonic-gate 	char  **aliases,	/* List of alias of those devices */
294*7c478bd9Sstevel@tonic-gate 	int	options)	/* Options governing search */
295*7c478bd9Sstevel@tonic-gate {
296*7c478bd9Sstevel@tonic-gate 	/* Automatic data */
297*7c478bd9Sstevel@tonic-gate 	char   *rtnval;		/* Value to return */
298*7c478bd9Sstevel@tonic-gate 	int	found;		/* Flag:  TRUE if found */
299*7c478bd9Sstevel@tonic-gate 
300*7c478bd9Sstevel@tonic-gate 	/* If there's a constraint list, is this device in it? */
301*7c478bd9Sstevel@tonic-gate 	if (devices && aliases) {
302*7c478bd9Sstevel@tonic-gate 
303*7c478bd9Sstevel@tonic-gate 	    /* Set "found" to TRUE if the device is in the list */
304*7c478bd9Sstevel@tonic-gate 	    found = FALSE;
305*7c478bd9Sstevel@tonic-gate 	    while (!found && *aliases) {
306*7c478bd9Sstevel@tonic-gate 		if (strcmp(devtabentry, *aliases) == 0) found = TRUE;
307*7c478bd9Sstevel@tonic-gate 		else {
308*7c478bd9Sstevel@tonic-gate 		    devices++;
309*7c478bd9Sstevel@tonic-gate 		    aliases++;
310*7c478bd9Sstevel@tonic-gate 		}
311*7c478bd9Sstevel@tonic-gate 	    }
312*7c478bd9Sstevel@tonic-gate 
313*7c478bd9Sstevel@tonic-gate 	    /* Set value to return */
314*7c478bd9Sstevel@tonic-gate 	    if (found)
315*7c478bd9Sstevel@tonic-gate 		rtnval = (options & DTAB_EXCLUDEFLAG) ?
316*7c478bd9Sstevel@tonic-gate 		    NULL : *devices;
317*7c478bd9Sstevel@tonic-gate 	    else
318*7c478bd9Sstevel@tonic-gate 		rtnval = (options & DTAB_EXCLUDEFLAG) ?
319*7c478bd9Sstevel@tonic-gate 		    devtabentry : NULL;
320*7c478bd9Sstevel@tonic-gate 
321*7c478bd9Sstevel@tonic-gate 	} else rtnval = devtabentry;  /* No constraint list */
322*7c478bd9Sstevel@tonic-gate 
323*7c478bd9Sstevel@tonic-gate 	return (rtnval);
324*7c478bd9Sstevel@tonic-gate }
325*7c478bd9Sstevel@tonic-gate 
326*7c478bd9Sstevel@tonic-gate /*
327*7c478bd9Sstevel@tonic-gate  *  void initdevicelist()
328*7c478bd9Sstevel@tonic-gate  *
329*7c478bd9Sstevel@tonic-gate  *	This function initializes the list of accumulated devices.
330*7c478bd9Sstevel@tonic-gate  *
331*7c478bd9Sstevel@tonic-gate  *  Arguments:  None
332*7c478bd9Sstevel@tonic-gate  *
333*7c478bd9Sstevel@tonic-gate  *  Returns:  Void.
334*7c478bd9Sstevel@tonic-gate  *
335*7c478bd9Sstevel@tonic-gate  *  Notes:
336*7c478bd9Sstevel@tonic-gate  */
337*7c478bd9Sstevel@tonic-gate 
338*7c478bd9Sstevel@tonic-gate static	void
initdevicelist(void)339*7c478bd9Sstevel@tonic-gate initdevicelist(void)
340*7c478bd9Sstevel@tonic-gate {
341*7c478bd9Sstevel@tonic-gate 	/* Make the list a null list */
342*7c478bd9Sstevel@tonic-gate 	(devicelist.head)->next = NULL;
343*7c478bd9Sstevel@tonic-gate 	devicelist.count = 0;
344*7c478bd9Sstevel@tonic-gate }
345*7c478bd9Sstevel@tonic-gate 
346*7c478bd9Sstevel@tonic-gate /*
347*7c478bd9Sstevel@tonic-gate  *  void freedevicelist()
348*7c478bd9Sstevel@tonic-gate  *
349*7c478bd9Sstevel@tonic-gate  *	This function frees the resources allocated to the linked list of
350*7c478bd9Sstevel@tonic-gate  *	devices we've been accumulating.
351*7c478bd9Sstevel@tonic-gate  *
352*7c478bd9Sstevel@tonic-gate  *  Arguments:  none
353*7c478bd9Sstevel@tonic-gate  *
354*7c478bd9Sstevel@tonic-gate  *  Returns:  void
355*7c478bd9Sstevel@tonic-gate  */
356*7c478bd9Sstevel@tonic-gate 
357*7c478bd9Sstevel@tonic-gate static	void
freedevicelist(void)358*7c478bd9Sstevel@tonic-gate freedevicelist(void)
359*7c478bd9Sstevel@tonic-gate {
360*7c478bd9Sstevel@tonic-gate 	/* Automatic data */
361*7c478bd9Sstevel@tonic-gate 	struct deviceent	*pdevice;	/* Pointer to current entry */
362*7c478bd9Sstevel@tonic-gate 	char			*freeblk;	/* Pointer space to free */
363*7c478bd9Sstevel@tonic-gate 
364*7c478bd9Sstevel@tonic-gate 	/* List has a dummy head node */
365*7c478bd9Sstevel@tonic-gate 	pdevice = (devicelist.head)->next;
366*7c478bd9Sstevel@tonic-gate 	while (pdevice) {
367*7c478bd9Sstevel@tonic-gate 	    freeblk = (char *) pdevice;
368*7c478bd9Sstevel@tonic-gate 	    pdevice = pdevice->next;
369*7c478bd9Sstevel@tonic-gate 	    free(freeblk);
370*7c478bd9Sstevel@tonic-gate 	}
371*7c478bd9Sstevel@tonic-gate }
372*7c478bd9Sstevel@tonic-gate 
373*7c478bd9Sstevel@tonic-gate /*
374*7c478bd9Sstevel@tonic-gate  *  int addtodevicelist(deventry)
375*7c478bd9Sstevel@tonic-gate  *	char   *deventry
376*7c478bd9Sstevel@tonic-gate  *
377*7c478bd9Sstevel@tonic-gate  * 	This function adds the device <deventry> to the list of devices already
378*7c478bd9Sstevel@tonic-gate  *	accumulated.  It will not add the device if that device already exists
379*7c478bd9Sstevel@tonic-gate  *	in the list.  The function returns 0 if successful, -1 if not with
380*7c478bd9Sstevel@tonic-gate  *	"errno" set (by functions called) to indicate the error.
381*7c478bd9Sstevel@tonic-gate  *
382*7c478bd9Sstevel@tonic-gate  *  Arguments:
383*7c478bd9Sstevel@tonic-gate  *	deventry		char *
384*7c478bd9Sstevel@tonic-gate  *				The name of the device to add to the list of
385*7c478bd9Sstevel@tonic-gate  *				accumulated devices
386*7c478bd9Sstevel@tonic-gate  *
387*7c478bd9Sstevel@tonic-gate  *  Returns:
388*7c478bd9Sstevel@tonic-gate  *	0	If successful
389*7c478bd9Sstevel@tonic-gate  *	-1	If failed.  "errno" will be set to a value that indicates the
390*7c478bd9Sstevel@tonic-gate  *		error.
391*7c478bd9Sstevel@tonic-gate  *
392*7c478bd9Sstevel@tonic-gate  *  Notes:
393*7c478bd9Sstevel@tonic-gate  *    -	The memory allocation scheme has the potential to fragment the memory
394*7c478bd9Sstevel@tonic-gate  *	in the malloc heap.  We're allocating space for a local structure,
395*7c478bd9Sstevel@tonic-gate  *	which will be freed by getdev(), then allocating space for the device
396*7c478bd9Sstevel@tonic-gate  *	name, which will be freed (maybe) by the application using getdev().
397*7c478bd9Sstevel@tonic-gate  *	Not worrying about this at the moment.
398*7c478bd9Sstevel@tonic-gate  */
399*7c478bd9Sstevel@tonic-gate 
400*7c478bd9Sstevel@tonic-gate static	int
addtodevicelist(char * deventry)401*7c478bd9Sstevel@tonic-gate addtodevicelist(char *deventry)
402*7c478bd9Sstevel@tonic-gate {
403*7c478bd9Sstevel@tonic-gate 	/* Automatic data */
404*7c478bd9Sstevel@tonic-gate 	struct deviceent	*p;	/* Pointer to current device */
405*7c478bd9Sstevel@tonic-gate 	struct deviceent	*q;	/* Pointer to next device */
406*7c478bd9Sstevel@tonic-gate 	struct deviceent	*new;	/* Pointer to the alloc'd new node */
407*7c478bd9Sstevel@tonic-gate 	char			*str;	/* Pointer to alloc'd space for name */
408*7c478bd9Sstevel@tonic-gate 	int			rtncd;	/* Value to return to the caller */
409*7c478bd9Sstevel@tonic-gate 	int			cmpcd;	/* strcmp() value, comparing names */
410*7c478bd9Sstevel@tonic-gate 	int			done;	/* Loop control, TRUE if done */
411*7c478bd9Sstevel@tonic-gate 
412*7c478bd9Sstevel@tonic-gate 
413*7c478bd9Sstevel@tonic-gate 	/* Initializations */
414*7c478bd9Sstevel@tonic-gate 	rtncd = FALSE;
415*7c478bd9Sstevel@tonic-gate 
416*7c478bd9Sstevel@tonic-gate 
417*7c478bd9Sstevel@tonic-gate 	/*
418*7c478bd9Sstevel@tonic-gate 	 * Find the place in the found device list devicelist where this
419*7c478bd9Sstevel@tonic-gate 	 * device is to reside
420*7c478bd9Sstevel@tonic-gate 	 */
421*7c478bd9Sstevel@tonic-gate 
422*7c478bd9Sstevel@tonic-gate 	p = devicelist.head;
423*7c478bd9Sstevel@tonic-gate 	done = FALSE;
424*7c478bd9Sstevel@tonic-gate 	while (!done) {
425*7c478bd9Sstevel@tonic-gate 	    q = p->next;
426*7c478bd9Sstevel@tonic-gate 	    if (!q) done = TRUE;
427*7c478bd9Sstevel@tonic-gate 	    else if ((cmpcd = strcmp(deventry, q->name)) <= 0) done = TRUE;
428*7c478bd9Sstevel@tonic-gate 	    else p = q;
429*7c478bd9Sstevel@tonic-gate 	}
430*7c478bd9Sstevel@tonic-gate 
431*7c478bd9Sstevel@tonic-gate 	/*
432*7c478bd9Sstevel@tonic-gate 	 *  If the device is not already in the list, insert it in the list
433*7c478bd9Sstevel@tonic-gate 	 */
434*7c478bd9Sstevel@tonic-gate 
435*7c478bd9Sstevel@tonic-gate 	if (!q || (cmpcd != 0)) {
436*7c478bd9Sstevel@tonic-gate 
437*7c478bd9Sstevel@tonic-gate 	    /* Alloc space for the new node */
438*7c478bd9Sstevel@tonic-gate 	    if (new = malloc(sizeof (struct deviceent))) {
439*7c478bd9Sstevel@tonic-gate 
440*7c478bd9Sstevel@tonic-gate 		/* Alloc space for the device character string */
441*7c478bd9Sstevel@tonic-gate 		if (str = malloc(strlen(deventry)+1)) {
442*7c478bd9Sstevel@tonic-gate 
443*7c478bd9Sstevel@tonic-gate 		/*
444*7c478bd9Sstevel@tonic-gate 		 * Insert an entry in the found device list containing
445*7c478bd9Sstevel@tonic-gate 		 * this device name
446*7c478bd9Sstevel@tonic-gate 		 */
447*7c478bd9Sstevel@tonic-gate 		    new->next = q;
448*7c478bd9Sstevel@tonic-gate 		    p->next = new;
449*7c478bd9Sstevel@tonic-gate 		    new->name = strcpy(str, deventry);
450*7c478bd9Sstevel@tonic-gate 		    devicelist.count++;
451*7c478bd9Sstevel@tonic-gate 		}
452*7c478bd9Sstevel@tonic-gate 
453*7c478bd9Sstevel@tonic-gate 		/* Couldn't alloc space for the device name.  Error. */
454*7c478bd9Sstevel@tonic-gate 		else rtncd = TRUE;
455*7c478bd9Sstevel@tonic-gate 	    }
456*7c478bd9Sstevel@tonic-gate 
457*7c478bd9Sstevel@tonic-gate 	    /* Couldn't alloc space for new node in the found list.  Error. */
458*7c478bd9Sstevel@tonic-gate 	    else rtncd = TRUE;
459*7c478bd9Sstevel@tonic-gate 
460*7c478bd9Sstevel@tonic-gate 	}
461*7c478bd9Sstevel@tonic-gate 
462*7c478bd9Sstevel@tonic-gate 	/* Return an value indicating success or failure */
463*7c478bd9Sstevel@tonic-gate 	return (rtncd);
464*7c478bd9Sstevel@tonic-gate }
465*7c478bd9Sstevel@tonic-gate 
466*7c478bd9Sstevel@tonic-gate /*
467*7c478bd9Sstevel@tonic-gate  *  struct srch *buildsearchlist(criteria)
468*7c478bd9Sstevel@tonic-gate  *	char  **criteria
469*7c478bd9Sstevel@tonic-gate  *
470*7c478bd9Sstevel@tonic-gate  *	This function builds a list of search criteria structures from the
471*7c478bd9Sstevel@tonic-gate  *	criteria strings in the list of criteria whose first argument is
472*7c478bd9Sstevel@tonic-gate  *	specified by "criteria".
473*7c478bd9Sstevel@tonic-gate  *
474*7c478bd9Sstevel@tonic-gate  *  Arguments:
475*7c478bd9Sstevel@tonic-gate  *	criteria	The address of the first item in a list of
476*7c478bd9Sstevel@tonic-gate  *			character-strings specifying search criteria
477*7c478bd9Sstevel@tonic-gate  *
478*7c478bd9Sstevel@tonic-gate  *  Returns: struct srch *
479*7c478bd9Sstevel@tonic-gate  *	The address of the structure in the list of structures describing the
480*7c478bd9Sstevel@tonic-gate  *	search criteria.
481*7c478bd9Sstevel@tonic-gate  *
482*7c478bd9Sstevel@tonic-gate  *  Notes:
483*7c478bd9Sstevel@tonic-gate  *    -	The only "regular expression" currently supported by the
484*7c478bd9Sstevel@tonic-gate  *	kywd:exp and kywd!:exp forms is exp=*.  This function assumes
485*7c478bd9Sstevel@tonic-gate  *	that kywd:exp means "if kywd exist" and that kywd!:exp means
486*7c478bd9Sstevel@tonic-gate  *	"if kywd doesn't exist".
487*7c478bd9Sstevel@tonic-gate  */
488*7c478bd9Sstevel@tonic-gate 
489*7c478bd9Sstevel@tonic-gate static 	struct srch *
buildsearchlist(char ** criteria)490*7c478bd9Sstevel@tonic-gate buildsearchlist(char **criteria)	/* Criteria from caller */
491*7c478bd9Sstevel@tonic-gate {
492*7c478bd9Sstevel@tonic-gate 	/*  Automatic data  */
493*7c478bd9Sstevel@tonic-gate 	struct srch	*rtnbuf;	/* Value to return */
494*7c478bd9Sstevel@tonic-gate 	struct srch	*psrch;		/* Running pointer */
495*7c478bd9Sstevel@tonic-gate 	char		*str;		/* Ptr to malloc()ed string space */
496*7c478bd9Sstevel@tonic-gate 	char		*p;		/* Temp pointer to char */
497*7c478bd9Sstevel@tonic-gate 	int		noerror;	/* TRUE if all's well */
498*7c478bd9Sstevel@tonic-gate 	int		n;		/* Temp counter */
499*7c478bd9Sstevel@tonic-gate 	char		**pp;		/* Running ptr to (char *) */
500*7c478bd9Sstevel@tonic-gate 
501*7c478bd9Sstevel@tonic-gate 
502*7c478bd9Sstevel@tonic-gate 	/*  Initializations  */
503*7c478bd9Sstevel@tonic-gate 	rtnbuf = NULL;				/* Nothing to return yet */
504*7c478bd9Sstevel@tonic-gate 	noerror = TRUE;				/* No errors (yet) */
505*7c478bd9Sstevel@tonic-gate 
506*7c478bd9Sstevel@tonic-gate 	/* If we were given any criteria ... */
507*7c478bd9Sstevel@tonic-gate 	if (criteria) {
508*7c478bd9Sstevel@tonic-gate 
509*7c478bd9Sstevel@tonic-gate 	    /* Count the number of criteria in the list */
510*7c478bd9Sstevel@tonic-gate 	    for (n = 1, pp = criteria; *pp++; n++)
511*7c478bd9Sstevel@tonic-gate 		;
512*7c478bd9Sstevel@tonic-gate 
513*7c478bd9Sstevel@tonic-gate 	    /* Allocate space for structures describing the criteria */
514*7c478bd9Sstevel@tonic-gate 	    if (rtnbuf = malloc(n*sizeof (struct srch))) {
515*7c478bd9Sstevel@tonic-gate 
516*7c478bd9Sstevel@tonic-gate 		/* Build structures describing the criteria */
517*7c478bd9Sstevel@tonic-gate 		pp = criteria;
518*7c478bd9Sstevel@tonic-gate 		psrch = rtnbuf;
519*7c478bd9Sstevel@tonic-gate 		while (noerror && *pp) {
520*7c478bd9Sstevel@tonic-gate 
521*7c478bd9Sstevel@tonic-gate 		    /* Keep list sane for cleanup if necessary */
522*7c478bd9Sstevel@tonic-gate 		    psrch->fcn = ENDLIST;
523*7c478bd9Sstevel@tonic-gate 
524*7c478bd9Sstevel@tonic-gate 		    /* Alloc space for strings referenced by the structure */
525*7c478bd9Sstevel@tonic-gate 		    if (str = malloc(strlen(*pp)+1)) {
526*7c478bd9Sstevel@tonic-gate 
527*7c478bd9Sstevel@tonic-gate 			/* Extract field name, function, and compare string */
528*7c478bd9Sstevel@tonic-gate 			(void) strcpy(str, *pp);
529*7c478bd9Sstevel@tonic-gate 
530*7c478bd9Sstevel@tonic-gate 			/* If criteria contains an equal sign ('=') ... */
531*7c478bd9Sstevel@tonic-gate 			if (p = strchr(str+1, '=')) {
532*7c478bd9Sstevel@tonic-gate 			    if (*(p-1) == '!') {
533*7c478bd9Sstevel@tonic-gate 				*(p-1) = '\0';
534*7c478bd9Sstevel@tonic-gate 				psrch->fcn = NOTEQUAL;
535*7c478bd9Sstevel@tonic-gate 			    } else {
536*7c478bd9Sstevel@tonic-gate 				*p = '\0';
537*7c478bd9Sstevel@tonic-gate 				psrch->fcn = EQUAL;
538*7c478bd9Sstevel@tonic-gate 			    }
539*7c478bd9Sstevel@tonic-gate 			    psrch->cmp = p+1;
540*7c478bd9Sstevel@tonic-gate 			    psrch->name = str;
541*7c478bd9Sstevel@tonic-gate 			    psrch++;
542*7c478bd9Sstevel@tonic-gate 			}
543*7c478bd9Sstevel@tonic-gate 
544*7c478bd9Sstevel@tonic-gate 			/* If criteria contains a colon (':') ... */
545*7c478bd9Sstevel@tonic-gate 			else if (p = strchr(str+1, ':')) {
546*7c478bd9Sstevel@tonic-gate 			    if (*(p-1) == '!') {
547*7c478bd9Sstevel@tonic-gate 				*(p-1) = '\0';
548*7c478bd9Sstevel@tonic-gate 				psrch->fcn = NOEXISTS;
549*7c478bd9Sstevel@tonic-gate 			    } else {
550*7c478bd9Sstevel@tonic-gate 				*p = '\0';
551*7c478bd9Sstevel@tonic-gate 				psrch->fcn = EXISTS;
552*7c478bd9Sstevel@tonic-gate 			    }
553*7c478bd9Sstevel@tonic-gate 			    psrch->cmp = p+1;
554*7c478bd9Sstevel@tonic-gate 			    psrch->name = str;
555*7c478bd9Sstevel@tonic-gate 			    psrch++;
556*7c478bd9Sstevel@tonic-gate 			}
557*7c478bd9Sstevel@tonic-gate 		    } else {
558*7c478bd9Sstevel@tonic-gate 			/* Unable to malloc() string space.  Clean up */
559*7c478bd9Sstevel@tonic-gate 			freesearchlist(rtnbuf);
560*7c478bd9Sstevel@tonic-gate 			noerror = FALSE;
561*7c478bd9Sstevel@tonic-gate 		    }
562*7c478bd9Sstevel@tonic-gate 		    /* Next criteria */
563*7c478bd9Sstevel@tonic-gate 		    pp++;
564*7c478bd9Sstevel@tonic-gate 		}
565*7c478bd9Sstevel@tonic-gate 		/* Terminate list */
566*7c478bd9Sstevel@tonic-gate 		if (noerror) psrch->fcn = ENDLIST;
567*7c478bd9Sstevel@tonic-gate 	    }
568*7c478bd9Sstevel@tonic-gate 	}
569*7c478bd9Sstevel@tonic-gate 
570*7c478bd9Sstevel@tonic-gate 	/* Return a pointer to allocated space (if any) */
571*7c478bd9Sstevel@tonic-gate 	return (rtnbuf);
572*7c478bd9Sstevel@tonic-gate }
573*7c478bd9Sstevel@tonic-gate 
574*7c478bd9Sstevel@tonic-gate /*
575*7c478bd9Sstevel@tonic-gate  *  void freesearchlist(list)
576*7c478bd9Sstevel@tonic-gate  *	struct srch  *list
577*7c478bd9Sstevel@tonic-gate  *
578*7c478bd9Sstevel@tonic-gate  *	This function frees the resources allocated to the searchlist <list>.
579*7c478bd9Sstevel@tonic-gate  *
580*7c478bd9Sstevel@tonic-gate  *  Arguments:
581*7c478bd9Sstevel@tonic-gate  *	list		The list whose resources are to be released.
582*7c478bd9Sstevel@tonic-gate  *
583*7c478bd9Sstevel@tonic-gate  *  Returns:  void
584*7c478bd9Sstevel@tonic-gate  */
585*7c478bd9Sstevel@tonic-gate 
586*7c478bd9Sstevel@tonic-gate static	void
freesearchlist(struct srch * list)587*7c478bd9Sstevel@tonic-gate freesearchlist(struct srch *list)
588*7c478bd9Sstevel@tonic-gate {
589*7c478bd9Sstevel@tonic-gate 	/* Automatic data */
590*7c478bd9Sstevel@tonic-gate 	struct srch		*psrch;		/* Running ptr to structs */
591*7c478bd9Sstevel@tonic-gate 
592*7c478bd9Sstevel@tonic-gate 
593*7c478bd9Sstevel@tonic-gate 	/* Free all of the string space allocated for the structure elememts */
594*7c478bd9Sstevel@tonic-gate 	for (psrch = list; psrch->fcn != ENDLIST; psrch++) {
595*7c478bd9Sstevel@tonic-gate 	    free(psrch->name);
596*7c478bd9Sstevel@tonic-gate 	}
597*7c478bd9Sstevel@tonic-gate 
598*7c478bd9Sstevel@tonic-gate 	/* Free the list space */
599*7c478bd9Sstevel@tonic-gate 	free(list);
600*7c478bd9Sstevel@tonic-gate }
601*7c478bd9Sstevel@tonic-gate 
602*7c478bd9Sstevel@tonic-gate /*
603*7c478bd9Sstevel@tonic-gate  *  char **buildreturnlist()
604*7c478bd9Sstevel@tonic-gate  *
605*7c478bd9Sstevel@tonic-gate  *	This function builds a list of addresses of character-strings
606*7c478bd9Sstevel@tonic-gate  *	to be returned from the linked-list of devices we've been
607*7c478bd9Sstevel@tonic-gate  *	building.  It returns a pointer to the first item in that list.
608*7c478bd9Sstevel@tonic-gate  *
609*7c478bd9Sstevel@tonic-gate  *  Arguments:  none
610*7c478bd9Sstevel@tonic-gate  *
611*7c478bd9Sstevel@tonic-gate  *  Returns:  char **
612*7c478bd9Sstevel@tonic-gate  *	The address of the first item in the return list
613*7c478bd9Sstevel@tonic-gate  */
614*7c478bd9Sstevel@tonic-gate 
615*7c478bd9Sstevel@tonic-gate static	char **
buildreturnlist(void)616*7c478bd9Sstevel@tonic-gate buildreturnlist(void)
617*7c478bd9Sstevel@tonic-gate {
618*7c478bd9Sstevel@tonic-gate 	/* Automatic data */
619*7c478bd9Sstevel@tonic-gate 	char			**list;
620*7c478bd9Sstevel@tonic-gate 	char			**q;
621*7c478bd9Sstevel@tonic-gate 	struct deviceent	*p;
622*7c478bd9Sstevel@tonic-gate 
623*7c478bd9Sstevel@tonic-gate 
624*7c478bd9Sstevel@tonic-gate 	/*
625*7c478bd9Sstevel@tonic-gate 	 * Allocate space for the return list,
626*7c478bd9Sstevel@tonic-gate 	 * with space for the terminating node
627*7c478bd9Sstevel@tonic-gate 	 */
628*7c478bd9Sstevel@tonic-gate 
629*7c478bd9Sstevel@tonic-gate 	if (list = malloc((devicelist.count+1)*sizeof (char *))) {
630*7c478bd9Sstevel@tonic-gate 
631*7c478bd9Sstevel@tonic-gate 	/*
632*7c478bd9Sstevel@tonic-gate 	 * Walk the list of accumulated devices, putting pointers to
633*7c478bd9Sstevel@tonic-gate 	 * device names in the list to return
634*7c478bd9Sstevel@tonic-gate 	 */
635*7c478bd9Sstevel@tonic-gate 
636*7c478bd9Sstevel@tonic-gate 	    q = list;
637*7c478bd9Sstevel@tonic-gate 	    for (p = devicelist.head->next; p; p = p->next) *q++ = p->name;
638*7c478bd9Sstevel@tonic-gate 
639*7c478bd9Sstevel@tonic-gate 	    /* End the list with a null-pointer */
640*7c478bd9Sstevel@tonic-gate 	    *q = NULL;
641*7c478bd9Sstevel@tonic-gate 	}
642*7c478bd9Sstevel@tonic-gate 
643*7c478bd9Sstevel@tonic-gate 
644*7c478bd9Sstevel@tonic-gate 	/* Return a pointer to the list we've built */
645*7c478bd9Sstevel@tonic-gate 	return (list);
646*7c478bd9Sstevel@tonic-gate }
647*7c478bd9Sstevel@tonic-gate 
648*7c478bd9Sstevel@tonic-gate /*
649*7c478bd9Sstevel@tonic-gate  *  char **makealiaslist(devices)
650*7c478bd9Sstevel@tonic-gate  *	char  **devices		List of aliases
651*7c478bd9Sstevel@tonic-gate  *
652*7c478bd9Sstevel@tonic-gate  *	Builds a list of aliases of the devices in the "devices"
653*7c478bd9Sstevel@tonic-gate  *	list.  This list will be terminated by (char *) NULL and
654*7c478bd9Sstevel@tonic-gate  *	will have the same number of elements as "devices".  If
655*7c478bd9Sstevel@tonic-gate  *	a device couldn't be found, that alias will be "".  There
656*7c478bd9Sstevel@tonic-gate  *	will be a one-to-one correspondence of devices to aliases
657*7c478bd9Sstevel@tonic-gate  *	in the device list "devices" and the generated list.
658*7c478bd9Sstevel@tonic-gate  *
659*7c478bd9Sstevel@tonic-gate  *  Arguments:
660*7c478bd9Sstevel@tonic-gate  *	devices		The list of devices to derive aliases from
661*7c478bd9Sstevel@tonic-gate  *
662*7c478bd9Sstevel@tonic-gate  *  Returns:  char **
663*7c478bd9Sstevel@tonic-gate  *	The address of the list of addresses of aliases.  The list
664*7c478bd9Sstevel@tonic-gate  *	and aliases will be allocated using the malloc() function.
665*7c478bd9Sstevel@tonic-gate  */
666*7c478bd9Sstevel@tonic-gate 
667*7c478bd9Sstevel@tonic-gate static	char **
makealiaslist(char ** devices)668*7c478bd9Sstevel@tonic-gate makealiaslist(char **devices)
669*7c478bd9Sstevel@tonic-gate {
670*7c478bd9Sstevel@tonic-gate 	/*  Automatic data  */
671*7c478bd9Sstevel@tonic-gate 	char		**pp;		/* Running ptr to (char *) */
672*7c478bd9Sstevel@tonic-gate 	char		**qq;		/* Running ptr to (char *) */
673*7c478bd9Sstevel@tonic-gate 	char		**aliases;	/* List being returned */
674*7c478bd9Sstevel@tonic-gate 	char		*alias;		/* Alias of current device */
675*7c478bd9Sstevel@tonic-gate 	int		olderrno;	/* Value of errno on entry */
676*7c478bd9Sstevel@tonic-gate 	int		noerror;	/* Flag, TRUE if all's well */
677*7c478bd9Sstevel@tonic-gate 	int		n;		/* Count of entries in "devices" */
678*7c478bd9Sstevel@tonic-gate 
679*7c478bd9Sstevel@tonic-gate 
680*7c478bd9Sstevel@tonic-gate 	noerror = TRUE;
681*7c478bd9Sstevel@tonic-gate 	olderrno = errno;
682*7c478bd9Sstevel@tonic-gate 	if (devices) {
683*7c478bd9Sstevel@tonic-gate 
684*7c478bd9Sstevel@tonic-gate 	    /* Get the number of entries in the constaint list */
685*7c478bd9Sstevel@tonic-gate 	    for (n = 1, pp = devices; *pp; pp++) n++;
686*7c478bd9Sstevel@tonic-gate 
687*7c478bd9Sstevel@tonic-gate 	    /* Get space for the alias list */
688*7c478bd9Sstevel@tonic-gate 	    if (aliases = malloc(n*sizeof (char *))) {
689*7c478bd9Sstevel@tonic-gate 
690*7c478bd9Sstevel@tonic-gate 		/* Build the alias list */
691*7c478bd9Sstevel@tonic-gate 		qq = aliases;
692*7c478bd9Sstevel@tonic-gate 		for (pp = devices; noerror && *pp; pp++) {
693*7c478bd9Sstevel@tonic-gate 
694*7c478bd9Sstevel@tonic-gate 		    /* Get the device's alias and put it in the list */
695*7c478bd9Sstevel@tonic-gate 		    if (alias = devattr(*pp, DTAB_ALIAS)) *qq++ = alias;
696*7c478bd9Sstevel@tonic-gate 		    else {
697*7c478bd9Sstevel@tonic-gate 			errno = olderrno;
698*7c478bd9Sstevel@tonic-gate 			if (alias = malloc(strlen("")+1))
699*7c478bd9Sstevel@tonic-gate 			    *qq++ = strcpy(alias, "");
700*7c478bd9Sstevel@tonic-gate 			else {
701*7c478bd9Sstevel@tonic-gate 			    /* No space for a null string?  Yeech... */
702*7c478bd9Sstevel@tonic-gate 			    for (qq = aliases; *qq; qq++) free(*qq);
703*7c478bd9Sstevel@tonic-gate 			    free(aliases);
704*7c478bd9Sstevel@tonic-gate 			    aliases = NULL;
705*7c478bd9Sstevel@tonic-gate 			    noerror = FALSE;
706*7c478bd9Sstevel@tonic-gate 			}
707*7c478bd9Sstevel@tonic-gate 		    }
708*7c478bd9Sstevel@tonic-gate 		}
709*7c478bd9Sstevel@tonic-gate 		if (noerror)
710*7c478bd9Sstevel@tonic-gate 			*qq = NULL;
711*7c478bd9Sstevel@tonic-gate 
712*7c478bd9Sstevel@tonic-gate 	    }
713*7c478bd9Sstevel@tonic-gate 
714*7c478bd9Sstevel@tonic-gate 	} else
715*7c478bd9Sstevel@tonic-gate 		aliases = NULL;  /* No constraint list */
716*7c478bd9Sstevel@tonic-gate 
717*7c478bd9Sstevel@tonic-gate 	/* Return ptr to generated list or NULL if none or error */
718*7c478bd9Sstevel@tonic-gate 	return (aliases);
719*7c478bd9Sstevel@tonic-gate }
720*7c478bd9Sstevel@tonic-gate 
721*7c478bd9Sstevel@tonic-gate /*
722*7c478bd9Sstevel@tonic-gate  *  void freealiaslist(aliaslist)
723*7c478bd9Sstevel@tonic-gate  *	char  **aliaslist;
724*7c478bd9Sstevel@tonic-gate  *
725*7c478bd9Sstevel@tonic-gate  *	Free the space allocated to the aliaslist.  It frees the space
726*7c478bd9Sstevel@tonic-gate  *	allocated to the character-strings referenced by the list then
727*7c478bd9Sstevel@tonic-gate  *	it frees the list.
728*7c478bd9Sstevel@tonic-gate  *
729*7c478bd9Sstevel@tonic-gate  *  Arguments:
730*7c478bd9Sstevel@tonic-gate  *	aliaslist	The address of the first item in the list of
731*7c478bd9Sstevel@tonic-gate  *			aliases that is to be freed
732*7c478bd9Sstevel@tonic-gate  *
733*7c478bd9Sstevel@tonic-gate  *  Returns:  void
734*7c478bd9Sstevel@tonic-gate  */
735*7c478bd9Sstevel@tonic-gate 
736*7c478bd9Sstevel@tonic-gate static	void
freealiaslist(char ** aliaslist)737*7c478bd9Sstevel@tonic-gate freealiaslist(char **aliaslist)		/* Ptr to new device list */
738*7c478bd9Sstevel@tonic-gate {
739*7c478bd9Sstevel@tonic-gate 	/* Automatic Data */
740*7c478bd9Sstevel@tonic-gate 	char   **pp;			/* Running pointer */
741*7c478bd9Sstevel@tonic-gate 
742*7c478bd9Sstevel@tonic-gate 	/* If there's a list ... */
743*7c478bd9Sstevel@tonic-gate 	if (aliaslist) {
744*7c478bd9Sstevel@tonic-gate 
745*7c478bd9Sstevel@tonic-gate 	    /* For each entry in the old list, free the entry */
746*7c478bd9Sstevel@tonic-gate 	    for (pp = aliaslist; *pp; pp++) free(*pp);
747*7c478bd9Sstevel@tonic-gate 
748*7c478bd9Sstevel@tonic-gate 	    /* Free the list */
749*7c478bd9Sstevel@tonic-gate 	    free(aliaslist);
750*7c478bd9Sstevel@tonic-gate 	}
751*7c478bd9Sstevel@tonic-gate }
752*7c478bd9Sstevel@tonic-gate 
753*7c478bd9Sstevel@tonic-gate /*
754*7c478bd9Sstevel@tonic-gate  *  char *getnextmatch(criteria, options)
755*7c478bd9Sstevel@tonic-gate  *	struct srch	       *criteria
756*7c478bd9Sstevel@tonic-gate  *	int			options
757*7c478bd9Sstevel@tonic-gate  *
758*7c478bd9Sstevel@tonic-gate  *  	Gets the next device in the device table that matches the criteria.
759*7c478bd9Sstevel@tonic-gate  *	Returns the alias of that device.
760*7c478bd9Sstevel@tonic-gate  *
761*7c478bd9Sstevel@tonic-gate  *  Arguments:
762*7c478bd9Sstevel@tonic-gate  *	criteria	The linked list of criteria to use to match a device
763*7c478bd9Sstevel@tonic-gate  *	options		Options modifying the criteria (only one that's really
764*7c478bd9Sstevel@tonic-gate  *			important is the DTAB_ANDCRITERIA flag)
765*7c478bd9Sstevel@tonic-gate  *
766*7c478bd9Sstevel@tonic-gate  *  Returns:  char *
767*7c478bd9Sstevel@tonic-gate  *	A pointer to a malloc()ed string containing the alias of the next
768*7c478bd9Sstevel@tonic-gate  *	device that matches the criteria, or (char *) NULL if none.
769*7c478bd9Sstevel@tonic-gate  */
770*7c478bd9Sstevel@tonic-gate 
771*7c478bd9Sstevel@tonic-gate static	char   *
getnextmatch(struct srch * criteria,int options)772*7c478bd9Sstevel@tonic-gate getnextmatch(struct srch *criteria, int options)
773*7c478bd9Sstevel@tonic-gate {
774*7c478bd9Sstevel@tonic-gate 	/* Automatic data */
775*7c478bd9Sstevel@tonic-gate 	struct devtabent	*devtabent;	/* Ptr to current record */
776*7c478bd9Sstevel@tonic-gate 	char			*alias;		/* Alias of device found */
777*7c478bd9Sstevel@tonic-gate 	int			notdone;	/* Flag, done yet? */
778*7c478bd9Sstevel@tonic-gate 	int			noerror;	/* Flag, had an error yet? */
779*7c478bd9Sstevel@tonic-gate 
780*7c478bd9Sstevel@tonic-gate 
781*7c478bd9Sstevel@tonic-gate 	/*
782*7c478bd9Sstevel@tonic-gate 	 *  Initializations:
783*7c478bd9Sstevel@tonic-gate 	 *    -	No alias yet
784*7c478bd9Sstevel@tonic-gate 	 *    - Not finished yet
785*7c478bd9Sstevel@tonic-gate 	 *    -	Make sure there are criteria we're to use
786*7c478bd9Sstevel@tonic-gate 	 */
787*7c478bd9Sstevel@tonic-gate 
788*7c478bd9Sstevel@tonic-gate 	alias = NULL;
789*7c478bd9Sstevel@tonic-gate 	notdone = TRUE;
790*7c478bd9Sstevel@tonic-gate 	noerror = TRUE;
791*7c478bd9Sstevel@tonic-gate 
792*7c478bd9Sstevel@tonic-gate 	/*  If we're to "and" the criteria...  */
793*7c478bd9Sstevel@tonic-gate 	if (options & DTAB_ANDCRITERIA) {
794*7c478bd9Sstevel@tonic-gate 
795*7c478bd9Sstevel@tonic-gate 	/*
796*7c478bd9Sstevel@tonic-gate 	 *  Search the device table until we've got a record that matches
797*7c478bd9Sstevel@tonic-gate 	 *  all of the criteria or we run out of records
798*7c478bd9Sstevel@tonic-gate 	 */
799*7c478bd9Sstevel@tonic-gate 
800*7c478bd9Sstevel@tonic-gate 	    while (notdone && (devtabent = _getdevtabent())) {
801*7c478bd9Sstevel@tonic-gate 		if (!devtabent->comment) {
802*7c478bd9Sstevel@tonic-gate 		    if (!criteria || matchallcriteria(devtabent, criteria)) {
803*7c478bd9Sstevel@tonic-gate 			if (alias = malloc(strlen(devtabent->alias)+1))
804*7c478bd9Sstevel@tonic-gate 			    (void) strcpy(alias, devtabent->alias);
805*7c478bd9Sstevel@tonic-gate 			else noerror = FALSE;
806*7c478bd9Sstevel@tonic-gate 			notdone = FALSE;
807*7c478bd9Sstevel@tonic-gate 		    }
808*7c478bd9Sstevel@tonic-gate 		}
809*7c478bd9Sstevel@tonic-gate 		_freedevtabent(devtabent);
810*7c478bd9Sstevel@tonic-gate 	    }
811*7c478bd9Sstevel@tonic-gate 	} else {
812*7c478bd9Sstevel@tonic-gate 
813*7c478bd9Sstevel@tonic-gate 	/*
814*7c478bd9Sstevel@tonic-gate 	 *  Search the device table until we've got a record that matches
815*7c478bd9Sstevel@tonic-gate 	 *  any of the criteria or we run out of records
816*7c478bd9Sstevel@tonic-gate 	 */
817*7c478bd9Sstevel@tonic-gate 
818*7c478bd9Sstevel@tonic-gate 	    while (notdone && (devtabent = _getdevtabent())) {
819*7c478bd9Sstevel@tonic-gate 		if (!devtabent->comment) {
820*7c478bd9Sstevel@tonic-gate 		    if (!criteria || matchanycriteria(devtabent, criteria)) {
821*7c478bd9Sstevel@tonic-gate 			if (alias = malloc(strlen(devtabent->alias)+1))
822*7c478bd9Sstevel@tonic-gate 			    (void) strcpy(alias, devtabent->alias);
823*7c478bd9Sstevel@tonic-gate 			else noerror = FALSE;
824*7c478bd9Sstevel@tonic-gate 			notdone = FALSE;
825*7c478bd9Sstevel@tonic-gate 		    }
826*7c478bd9Sstevel@tonic-gate 		}
827*7c478bd9Sstevel@tonic-gate 		_freedevtabent(devtabent);
828*7c478bd9Sstevel@tonic-gate 	    }
829*7c478bd9Sstevel@tonic-gate 	}
830*7c478bd9Sstevel@tonic-gate 
831*7c478bd9Sstevel@tonic-gate 
832*7c478bd9Sstevel@tonic-gate 	/* Return pointer to extracted alias (or NULL if none) */
833*7c478bd9Sstevel@tonic-gate 	if ((alias == NULL) && noerror) errno = ENOENT;
834*7c478bd9Sstevel@tonic-gate 	return (alias);
835*7c478bd9Sstevel@tonic-gate }
836*7c478bd9Sstevel@tonic-gate 
837*7c478bd9Sstevel@tonic-gate /*
838*7c478bd9Sstevel@tonic-gate  * int matchallcriteria(devtabent, criteria)
839*7c478bd9Sstevel@tonic-gate  *
840*7c478bd9Sstevel@tonic-gate  *	This function examines the record contained in "devtabent" and
841*7c478bd9Sstevel@tonic-gate  *	determines if that record meets all of the criteria specified by
842*7c478bd9Sstevel@tonic-gate  *	"criteria".
843*7c478bd9Sstevel@tonic-gate  *
844*7c478bd9Sstevel@tonic-gate  * Arguments:
845*7c478bd9Sstevel@tonic-gate  *	struct devtabent *devtabent	The device table entry to examine.
846*7c478bd9Sstevel@tonic-gate  *	struct srch    *criteria	The criteria to match.
847*7c478bd9Sstevel@tonic-gate  *
848*7c478bd9Sstevel@tonic-gate  * Returns:	int
849*7c478bd9Sstevel@tonic-gate  *	Returns TRUE if the record matches criteria, FALSE otherwise.
850*7c478bd9Sstevel@tonic-gate  */
851*7c478bd9Sstevel@tonic-gate 
852*7c478bd9Sstevel@tonic-gate static	int
matchallcriteria(struct devtabent * ent,struct srch * criteria)853*7c478bd9Sstevel@tonic-gate matchallcriteria(
854*7c478bd9Sstevel@tonic-gate 	struct devtabent	*ent,		/* Entry to check */
855*7c478bd9Sstevel@tonic-gate 	struct srch		*criteria)	/* Criteria governing match */
856*7c478bd9Sstevel@tonic-gate {
857*7c478bd9Sstevel@tonic-gate 	/* Automatic data */
858*7c478bd9Sstevel@tonic-gate 	struct srch    *p;		/* Pointer to current criteria */
859*7c478bd9Sstevel@tonic-gate 	struct attrval *q;		/* Pointer to current attr/val pair */
860*7c478bd9Sstevel@tonic-gate 	int		notfound;	/* TRUE if attr found in list */
861*7c478bd9Sstevel@tonic-gate 	int		failed;		/* TRUE if record failed to match */
862*7c478bd9Sstevel@tonic-gate 
863*7c478bd9Sstevel@tonic-gate 
864*7c478bd9Sstevel@tonic-gate 	/* Test only if there's criteria to test against */
865*7c478bd9Sstevel@tonic-gate 	if (criteria && (criteria->fcn != ENDLIST)) {
866*7c478bd9Sstevel@tonic-gate 
867*7c478bd9Sstevel@tonic-gate 	    failed = FALSE;
868*7c478bd9Sstevel@tonic-gate 	    for (p = criteria; !failed && (p->fcn != ENDLIST); p++) {
869*7c478bd9Sstevel@tonic-gate 
870*7c478bd9Sstevel@tonic-gate 		/*
871*7c478bd9Sstevel@tonic-gate 		 * Don't compare against this criteria if it's function is
872*7c478bd9Sstevel@tonic-gate 		 * "IGNORE"
873*7c478bd9Sstevel@tonic-gate 		 */
874*7c478bd9Sstevel@tonic-gate 		if (p->fcn != IGNORE) {
875*7c478bd9Sstevel@tonic-gate 		    if (p->fcn != NOEXISTS) {
876*7c478bd9Sstevel@tonic-gate 
877*7c478bd9Sstevel@tonic-gate 			/*  Alias?  */
878*7c478bd9Sstevel@tonic-gate 			if (strcmp(p->name, DTAB_ALIAS) == 0)
879*7c478bd9Sstevel@tonic-gate 			    failed = !matches(ent->alias, p->cmp, p->fcn);
880*7c478bd9Sstevel@tonic-gate 
881*7c478bd9Sstevel@tonic-gate 			/*  Char special device?  */
882*7c478bd9Sstevel@tonic-gate 			else if (strcmp(p->name, DTAB_CDEVICE) == 0)
883*7c478bd9Sstevel@tonic-gate 			    failed = !matches(ent->cdevice, p->cmp, p->fcn);
884*7c478bd9Sstevel@tonic-gate 
885*7c478bd9Sstevel@tonic-gate 			/*  Block special device?  */
886*7c478bd9Sstevel@tonic-gate 			else if (strcmp(p->name, DTAB_BDEVICE) == 0)
887*7c478bd9Sstevel@tonic-gate 			    failed = !matches(ent->bdevice, p->cmp, p->fcn);
888*7c478bd9Sstevel@tonic-gate 
889*7c478bd9Sstevel@tonic-gate 			/*  Pathname?  */
890*7c478bd9Sstevel@tonic-gate 			else if (strcmp(p->name, DTAB_PATHNAME) == 0)
891*7c478bd9Sstevel@tonic-gate 			    failed = !matches(ent->pathname, p->cmp, p->fcn);
892*7c478bd9Sstevel@tonic-gate 
893*7c478bd9Sstevel@tonic-gate 			/*  Check other attributes...  */
894*7c478bd9Sstevel@tonic-gate 			else {
895*7c478bd9Sstevel@tonic-gate 			    notfound = TRUE;
896*7c478bd9Sstevel@tonic-gate 			    q = ent->attrlist;
897*7c478bd9Sstevel@tonic-gate 			    while (notfound && q) {
898*7c478bd9Sstevel@tonic-gate 				if (strcmp(p->name, q->attr) == 0) {
899*7c478bd9Sstevel@tonic-gate 				    notfound = FALSE;
900*7c478bd9Sstevel@tonic-gate 				    if (!matches(q->val, p->cmp, p->fcn))
901*7c478bd9Sstevel@tonic-gate 					failed = TRUE;
902*7c478bd9Sstevel@tonic-gate 				} else q = q->next;
903*7c478bd9Sstevel@tonic-gate 			    }
904*7c478bd9Sstevel@tonic-gate 			    if (notfound) failed = TRUE;
905*7c478bd9Sstevel@tonic-gate 			}
906*7c478bd9Sstevel@tonic-gate 		    } else {
907*7c478bd9Sstevel@tonic-gate 			if (strcmp(p->name, DTAB_ALIAS) == 0) failed = TRUE;
908*7c478bd9Sstevel@tonic-gate 			else if (strcmp(p->name, DTAB_CDEVICE) == 0)
909*7c478bd9Sstevel@tonic-gate 				failed = FALSE;
910*7c478bd9Sstevel@tonic-gate 			else if (strcmp(p->name, DTAB_BDEVICE) == 0)
911*7c478bd9Sstevel@tonic-gate 				failed = FALSE;
912*7c478bd9Sstevel@tonic-gate 			else if (strcmp(p->name, DTAB_PATHNAME) == 0)
913*7c478bd9Sstevel@tonic-gate 				failed = FALSE;
914*7c478bd9Sstevel@tonic-gate 			else {
915*7c478bd9Sstevel@tonic-gate 			    q = ent->attrlist;
916*7c478bd9Sstevel@tonic-gate 			    while (!failed && q) {
917*7c478bd9Sstevel@tonic-gate 				if (strcmp(p->name, q->attr) == 0)
918*7c478bd9Sstevel@tonic-gate 					failed = TRUE;
919*7c478bd9Sstevel@tonic-gate 				else q = q->next;
920*7c478bd9Sstevel@tonic-gate 			    }
921*7c478bd9Sstevel@tonic-gate 			}
922*7c478bd9Sstevel@tonic-gate 		    }
923*7c478bd9Sstevel@tonic-gate 
924*7c478bd9Sstevel@tonic-gate 		}  /* Search function is not "IGNORE" */
925*7c478bd9Sstevel@tonic-gate 
926*7c478bd9Sstevel@tonic-gate 	    }  /* for loop, checking each criteria */
927*7c478bd9Sstevel@tonic-gate 
928*7c478bd9Sstevel@tonic-gate 	}  /* if (criteria) */
929*7c478bd9Sstevel@tonic-gate 
930*7c478bd9Sstevel@tonic-gate 	else failed = FALSE;  /* No criteria specified, it's a match */
931*7c478bd9Sstevel@tonic-gate 
932*7c478bd9Sstevel@tonic-gate 
933*7c478bd9Sstevel@tonic-gate 	/* Return a value indicating if the record matches all criteria */
934*7c478bd9Sstevel@tonic-gate 	return (!failed);
935*7c478bd9Sstevel@tonic-gate }
936*7c478bd9Sstevel@tonic-gate 
937*7c478bd9Sstevel@tonic-gate /*
938*7c478bd9Sstevel@tonic-gate  * int matchanycriteria(devtabent, criteria)
939*7c478bd9Sstevel@tonic-gate  *
940*7c478bd9Sstevel@tonic-gate  *	This function examines the record contained in "devtabent" and
941*7c478bd9Sstevel@tonic-gate  *	determines if that record meets any of the criteria specified by
942*7c478bd9Sstevel@tonic-gate  *	"criteria".
943*7c478bd9Sstevel@tonic-gate  *
944*7c478bd9Sstevel@tonic-gate  * Arguments:
945*7c478bd9Sstevel@tonic-gate  *	struct devtabent *devtabent	The device table entry to examine.
946*7c478bd9Sstevel@tonic-gate  *	struct srch      *criteria	The criteria to match.
947*7c478bd9Sstevel@tonic-gate  *
948*7c478bd9Sstevel@tonic-gate  * Returns:	int
949*7c478bd9Sstevel@tonic-gate  *	Returns TRUE if the record matches criteria, FALSE otherwise.
950*7c478bd9Sstevel@tonic-gate  */
951*7c478bd9Sstevel@tonic-gate 
952*7c478bd9Sstevel@tonic-gate static	int
matchanycriteria(struct devtabent * ent,struct srch * criteria)953*7c478bd9Sstevel@tonic-gate matchanycriteria(
954*7c478bd9Sstevel@tonic-gate 	struct devtabent	*ent,		/* Entry to check */
955*7c478bd9Sstevel@tonic-gate 	struct srch		*criteria)	/* Criteria governing match */
956*7c478bd9Sstevel@tonic-gate {
957*7c478bd9Sstevel@tonic-gate 	/* Automatic data */
958*7c478bd9Sstevel@tonic-gate 	struct srch    *p;		/* Pointer to current criteria */
959*7c478bd9Sstevel@tonic-gate 	struct attrval *q;		/* Pointer to current attr/val pair */
960*7c478bd9Sstevel@tonic-gate 	int		matched;	/* FLAG: TRUE if record matched */
961*7c478bd9Sstevel@tonic-gate 	int		found;		/* FLAG: TRUE if attribute found */
962*7c478bd9Sstevel@tonic-gate 
963*7c478bd9Sstevel@tonic-gate 
964*7c478bd9Sstevel@tonic-gate 	/* Test only if there's criteria to test against */
965*7c478bd9Sstevel@tonic-gate 	if (criteria && (criteria->fcn != ENDLIST)) {
966*7c478bd9Sstevel@tonic-gate 
967*7c478bd9Sstevel@tonic-gate 	    matched = FALSE;
968*7c478bd9Sstevel@tonic-gate 	    for (p = criteria; !matched && (p->fcn != ENDLIST); p++) {
969*7c478bd9Sstevel@tonic-gate 
970*7c478bd9Sstevel@tonic-gate 		/*
971*7c478bd9Sstevel@tonic-gate 		 * Don't compare against this criteria if it's function is
972*7c478bd9Sstevel@tonic-gate 		 * "IGNORE"
973*7c478bd9Sstevel@tonic-gate 		 */
974*7c478bd9Sstevel@tonic-gate 		if (p->fcn != IGNORE) {
975*7c478bd9Sstevel@tonic-gate 		    if (p->fcn != NOEXISTS) {
976*7c478bd9Sstevel@tonic-gate 
977*7c478bd9Sstevel@tonic-gate 			/*  Alias?  */
978*7c478bd9Sstevel@tonic-gate 			if (strcmp(p->name, DTAB_ALIAS) == 0)
979*7c478bd9Sstevel@tonic-gate 			    matched = matches(ent->alias, p->cmp, p->fcn);
980*7c478bd9Sstevel@tonic-gate 
981*7c478bd9Sstevel@tonic-gate 			/*  Char special device?  */
982*7c478bd9Sstevel@tonic-gate 			else if (strcmp(p->name, DTAB_CDEVICE) == 0)
983*7c478bd9Sstevel@tonic-gate 			    matched = matches(ent->cdevice, p->cmp, p->fcn);
984*7c478bd9Sstevel@tonic-gate 
985*7c478bd9Sstevel@tonic-gate 			/*  Block special device?  */
986*7c478bd9Sstevel@tonic-gate 			else if (strcmp(p->name, DTAB_BDEVICE) == 0)
987*7c478bd9Sstevel@tonic-gate 			    matched = matches(ent->bdevice, p->cmp, p->fcn);
988*7c478bd9Sstevel@tonic-gate 
989*7c478bd9Sstevel@tonic-gate 			/*  Pathname?  */
990*7c478bd9Sstevel@tonic-gate 			else if (strcmp(p->name, DTAB_PATHNAME) == 0)
991*7c478bd9Sstevel@tonic-gate 			    matched = matches(ent->pathname, p->cmp, p->fcn);
992*7c478bd9Sstevel@tonic-gate 
993*7c478bd9Sstevel@tonic-gate 			/*  Check other attributes...  */
994*7c478bd9Sstevel@tonic-gate 			else {
995*7c478bd9Sstevel@tonic-gate 			    q = ent->attrlist;
996*7c478bd9Sstevel@tonic-gate 			    found = FALSE;
997*7c478bd9Sstevel@tonic-gate 			    while (!found && q)
998*7c478bd9Sstevel@tonic-gate 				if (strcmp(p->name, q->attr) == 0) {
999*7c478bd9Sstevel@tonic-gate 				    matched = matches(q->val, p->cmp, p->fcn);
1000*7c478bd9Sstevel@tonic-gate 				    found = TRUE;
1001*7c478bd9Sstevel@tonic-gate 				} else q = q->next;
1002*7c478bd9Sstevel@tonic-gate 			}
1003*7c478bd9Sstevel@tonic-gate 		    } else {
1004*7c478bd9Sstevel@tonic-gate 			if (strcmp(p->name, DTAB_ALIAS) == 0) matched = FALSE;
1005*7c478bd9Sstevel@tonic-gate 			else if (strcmp(p->name, DTAB_CDEVICE) == 0)
1006*7c478bd9Sstevel@tonic-gate 				matched = FALSE;
1007*7c478bd9Sstevel@tonic-gate 			else if (strcmp(p->name, DTAB_BDEVICE) == 0)
1008*7c478bd9Sstevel@tonic-gate 				matched = FALSE;
1009*7c478bd9Sstevel@tonic-gate 			else if (strcmp(p->name, DTAB_PATHNAME) == 0)
1010*7c478bd9Sstevel@tonic-gate 				matched = FALSE;
1011*7c478bd9Sstevel@tonic-gate 			else {
1012*7c478bd9Sstevel@tonic-gate 			    q = ent->attrlist;
1013*7c478bd9Sstevel@tonic-gate 			    matched = TRUE;
1014*7c478bd9Sstevel@tonic-gate 			    while (matched && q) {
1015*7c478bd9Sstevel@tonic-gate 				if (strcmp(p->name, q->attr) == 0)
1016*7c478bd9Sstevel@tonic-gate 					matched = FALSE;
1017*7c478bd9Sstevel@tonic-gate 				else q = q->next;
1018*7c478bd9Sstevel@tonic-gate 			    }
1019*7c478bd9Sstevel@tonic-gate 			}
1020*7c478bd9Sstevel@tonic-gate 		    }
1021*7c478bd9Sstevel@tonic-gate 		}  /* Search function is not "IGNORE" */
1022*7c478bd9Sstevel@tonic-gate 
1023*7c478bd9Sstevel@tonic-gate 	    }  /* for loop, checking each criteria */
1024*7c478bd9Sstevel@tonic-gate 
1025*7c478bd9Sstevel@tonic-gate 	}  /* if (criteria) */
1026*7c478bd9Sstevel@tonic-gate 
1027*7c478bd9Sstevel@tonic-gate 	else matched = TRUE;  /* No criteria specified, it's a match */
1028*7c478bd9Sstevel@tonic-gate 
1029*7c478bd9Sstevel@tonic-gate 
1030*7c478bd9Sstevel@tonic-gate 	/* Return a value indicating if the record matches all criteria */
1031*7c478bd9Sstevel@tonic-gate 	return (matched);
1032*7c478bd9Sstevel@tonic-gate }
1033*7c478bd9Sstevel@tonic-gate 
1034*7c478bd9Sstevel@tonic-gate /*
1035*7c478bd9Sstevel@tonic-gate  *  int matches(value, compare, function)
1036*7c478bd9Sstevel@tonic-gate  *	char   *value
1037*7c478bd9Sstevel@tonic-gate  *	char   *compare
1038*7c478bd9Sstevel@tonic-gate  *	int	function
1039*7c478bd9Sstevel@tonic-gate  *
1040*7c478bd9Sstevel@tonic-gate  *	This function sees if the operation <function> is satisfied by
1041*7c478bd9Sstevel@tonic-gate  *	comparing the value <value> with <compare>.  It returns TRUE
1042*7c478bd9Sstevel@tonic-gate  *	if so, FALSE otherwise.
1043*7c478bd9Sstevel@tonic-gate  *
1044*7c478bd9Sstevel@tonic-gate  *  Arguments:
1045*7c478bd9Sstevel@tonic-gate  *	value		Value to compare
1046*7c478bd9Sstevel@tonic-gate  *	compare		Value to compare against
1047*7c478bd9Sstevel@tonic-gate  *	function	Function to be satisfied
1048*7c478bd9Sstevel@tonic-gate  *
1049*7c478bd9Sstevel@tonic-gate  *  Returns:  int
1050*7c478bd9Sstevel@tonic-gate  *	TRUE if the function is satisfied, FALSE otherwise
1051*7c478bd9Sstevel@tonic-gate  */
1052*7c478bd9Sstevel@tonic-gate 
1053*7c478bd9Sstevel@tonic-gate static	int
matches(char * value,char * compare,int function)1054*7c478bd9Sstevel@tonic-gate matches(char *value, char *compare, int function)
1055*7c478bd9Sstevel@tonic-gate {
1056*7c478bd9Sstevel@tonic-gate 	/*  Automatic data  */
1057*7c478bd9Sstevel@tonic-gate 	int	rtn;		/* Value to return */
1058*7c478bd9Sstevel@tonic-gate 
1059*7c478bd9Sstevel@tonic-gate 
1060*7c478bd9Sstevel@tonic-gate 	if (value == NULL)
1061*7c478bd9Sstevel@tonic-gate 		value = "";
1062*7c478bd9Sstevel@tonic-gate 
1063*7c478bd9Sstevel@tonic-gate 	/* Do case depending on the function */
1064*7c478bd9Sstevel@tonic-gate 	switch (function) {
1065*7c478bd9Sstevel@tonic-gate 
1066*7c478bd9Sstevel@tonic-gate 	/* attr=val */
1067*7c478bd9Sstevel@tonic-gate 	case EQUAL:
1068*7c478bd9Sstevel@tonic-gate 	    rtn = (strcmp(value, compare) == 0);
1069*7c478bd9Sstevel@tonic-gate 	    break;
1070*7c478bd9Sstevel@tonic-gate 
1071*7c478bd9Sstevel@tonic-gate 	/* attr!=val */
1072*7c478bd9Sstevel@tonic-gate 	case NOTEQUAL:
1073*7c478bd9Sstevel@tonic-gate 	    rtn = (strcmp(value, compare) != 0);
1074*7c478bd9Sstevel@tonic-gate 	    break;
1075*7c478bd9Sstevel@tonic-gate 
1076*7c478bd9Sstevel@tonic-gate 	/* attr:* */
1077*7c478bd9Sstevel@tonic-gate 	case EXISTS:
1078*7c478bd9Sstevel@tonic-gate 	    rtn = TRUE;
1079*7c478bd9Sstevel@tonic-gate 	    break;
1080*7c478bd9Sstevel@tonic-gate 
1081*7c478bd9Sstevel@tonic-gate 	/* attr!:* */
1082*7c478bd9Sstevel@tonic-gate 	case NOEXISTS:
1083*7c478bd9Sstevel@tonic-gate 	    rtn = FALSE;
1084*7c478bd9Sstevel@tonic-gate 	    break;
1085*7c478bd9Sstevel@tonic-gate 
1086*7c478bd9Sstevel@tonic-gate 	/* Shouldn't get here... */
1087*7c478bd9Sstevel@tonic-gate 	default:
1088*7c478bd9Sstevel@tonic-gate 	    rtn = FALSE;
1089*7c478bd9Sstevel@tonic-gate 	    break;
1090*7c478bd9Sstevel@tonic-gate 	}
1091*7c478bd9Sstevel@tonic-gate 
1092*7c478bd9Sstevel@tonic-gate 	/* Return a value indicating if the match was made */
1093*7c478bd9Sstevel@tonic-gate 	return (rtn);
1094*7c478bd9Sstevel@tonic-gate }
1095