xref: /titanic_52/usr/src/lib/libadm/common/devtab.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
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 /*
23*7c478bd9Sstevel@tonic-gate  * Copyright (c) 1996-1998 by Sun Microsystems, Inc.
24*7c478bd9Sstevel@tonic-gate  * All Rights reserved.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
27*7c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate 
30*7c478bd9Sstevel@tonic-gate #pragma	ident	"%Z%%M%	%I%	%E% SMI"	/* SVr4.0 1.2 */
31*7c478bd9Sstevel@tonic-gate /*LINTLIBRARY*/
32*7c478bd9Sstevel@tonic-gate 
33*7c478bd9Sstevel@tonic-gate /*
34*7c478bd9Sstevel@tonic-gate  * devtab.c
35*7c478bd9Sstevel@tonic-gate  *
36*7c478bd9Sstevel@tonic-gate  *  Contains functions that deal with the device table and are not for
37*7c478bd9Sstevel@tonic-gate  *  consumption by the general user population.
38*7c478bd9Sstevel@tonic-gate  *
39*7c478bd9Sstevel@tonic-gate  *  Functions defined:
40*7c478bd9Sstevel@tonic-gate  *	_opendevtab()		Opens the device table for commands
41*7c478bd9Sstevel@tonic-gate  *	_setdevtab()		Rewinds the open device table
42*7c478bd9Sstevel@tonic-gate  *	_enddevtab()		Closes the open device table
43*7c478bd9Sstevel@tonic-gate  *	_getdevtabent()		Gets the next entry in the device table
44*7c478bd9Sstevel@tonic-gate  *	_freedevtabent()	Frees memory allocated to a device-table entry
45*7c478bd9Sstevel@tonic-gate  *	_getdevrec()		Gets a specific record from the device table
46*7c478bd9Sstevel@tonic-gate  *	_devtabpath()		Get the pathname of the device table file
47*7c478bd9Sstevel@tonic-gate  *	_validalias()		Is a value a valid alias?
48*7c478bd9Sstevel@tonic-gate  */
49*7c478bd9Sstevel@tonic-gate 
50*7c478bd9Sstevel@tonic-gate /*
51*7c478bd9Sstevel@tonic-gate  *  Header files
52*7c478bd9Sstevel@tonic-gate  *
53*7c478bd9Sstevel@tonic-gate  *	<sys/sysmacros.h>	System macro definitions
54*7c478bd9Sstevel@tonic-gate  *	<sys/types.h>		System data types
55*7c478bd9Sstevel@tonic-gate  *	<sys/mkdev.h>		Device Macros
56*7c478bd9Sstevel@tonic-gate  *	<unistd.h>		System Symbolic Constants
57*7c478bd9Sstevel@tonic-gate  *	<stdio.h>		Standard I/O definitions
58*7c478bd9Sstevel@tonic-gate  *	<string.h>		String handling definitions
59*7c478bd9Sstevel@tonic-gate  *	<ctype.h>		Character types and macros
60*7c478bd9Sstevel@tonic-gate  *	<errno.h>		Error codes
61*7c478bd9Sstevel@tonic-gate  *	<sys/stat.h>		File status information
62*7c478bd9Sstevel@tonic-gate  *	<devmgmt.h>		Global Device Management definitions
63*7c478bd9Sstevel@tonic-gate  *	"devtab.h"		Local Device Management definitions
64*7c478bd9Sstevel@tonic-gate  */
65*7c478bd9Sstevel@tonic-gate 
66*7c478bd9Sstevel@tonic-gate #include	<sys/sysmacros.h>
67*7c478bd9Sstevel@tonic-gate #include	<sys/types.h>
68*7c478bd9Sstevel@tonic-gate #ifndef SUNOS41
69*7c478bd9Sstevel@tonic-gate #include	<sys/mkdev.h>
70*7c478bd9Sstevel@tonic-gate #endif
71*7c478bd9Sstevel@tonic-gate #include	<unistd.h>
72*7c478bd9Sstevel@tonic-gate #include	<stdio.h>
73*7c478bd9Sstevel@tonic-gate #include	<string.h>
74*7c478bd9Sstevel@tonic-gate #include	<ctype.h>
75*7c478bd9Sstevel@tonic-gate #include	<errno.h>
76*7c478bd9Sstevel@tonic-gate #include	<sys/stat.h>
77*7c478bd9Sstevel@tonic-gate #include	<devmgmt.h>
78*7c478bd9Sstevel@tonic-gate #include	"devtab.h"
79*7c478bd9Sstevel@tonic-gate #include	<stdlib.h>
80*7c478bd9Sstevel@tonic-gate 
81*7c478bd9Sstevel@tonic-gate /*
82*7c478bd9Sstevel@tonic-gate  *  Static data definitions:
83*7c478bd9Sstevel@tonic-gate  *	dtabrecnum	Record number of the current record (0 to n-1)
84*7c478bd9Sstevel@tonic-gate  *	leftoff		Addr of char to begin next parse using
85*7c478bd9Sstevel@tonic-gate  *			getfld(), getattrval(), getquoted()
86*7c478bd9Sstevel@tonic-gate  *	recbufsz	The size of the buffer used for reading records
87*7c478bd9Sstevel@tonic-gate  *	recbuf		Addr of malloc() buffer for reading records
88*7c478bd9Sstevel@tonic-gate  *	xtndcnt		Number of malloc()/realloc() calls on record buffer
89*7c478bd9Sstevel@tonic-gate  */
90*7c478bd9Sstevel@tonic-gate 
91*7c478bd9Sstevel@tonic-gate static	int		xtndcnt = 0;
92*7c478bd9Sstevel@tonic-gate static	char		*recbuf = NULL;
93*7c478bd9Sstevel@tonic-gate static	int		recbufsz = 0;
94*7c478bd9Sstevel@tonic-gate 
95*7c478bd9Sstevel@tonic-gate static	char		*leftoff = NULL;
96*7c478bd9Sstevel@tonic-gate static	int		dtabrecnum = 0;
97*7c478bd9Sstevel@tonic-gate 
98*7c478bd9Sstevel@tonic-gate /*
99*7c478bd9Sstevel@tonic-gate  * int samedev(x, y)
100*7c478bd9Sstevel@tonic-gate  *	struct stat	x, y
101*7c478bd9Sstevel@tonic-gate  *
102*7c478bd9Sstevel@tonic-gate  *	Compares pertinent information in a stat() structure
103*7c478bd9Sstevel@tonic-gate  *	to see if the two structures describe the same device.
104*7c478bd9Sstevel@tonic-gate  *	If the file modes are the same and they have the same
105*7c478bd9Sstevel@tonic-gate  *	file system and i-node (i.e. they're links) or they
106*7c478bd9Sstevel@tonic-gate  *	are block or character devices and have the same major
107*7c478bd9Sstevel@tonic-gate  *	and minor device numbers (i.e. "mknod"s for the same
108*7c478bd9Sstevel@tonic-gate  *	device), it's the same device.
109*7c478bd9Sstevel@tonic-gate  *
110*7c478bd9Sstevel@tonic-gate  *   Returns:  int
111*7c478bd9Sstevel@tonic-gate  *	TRUE if the two structures describe the same device
112*7c478bd9Sstevel@tonic-gate  *	FALSE otherwise
113*7c478bd9Sstevel@tonic-gate  */
114*7c478bd9Sstevel@tonic-gate 
115*7c478bd9Sstevel@tonic-gate static int
116*7c478bd9Sstevel@tonic-gate samedev(struct stat64 x, struct stat64 y)
117*7c478bd9Sstevel@tonic-gate {
118*7c478bd9Sstevel@tonic-gate 	int	same;
119*7c478bd9Sstevel@tonic-gate 
120*7c478bd9Sstevel@tonic-gate 
121*7c478bd9Sstevel@tonic-gate 	/* If the devices are of the same type ... */
122*7c478bd9Sstevel@tonic-gate 	if ((x.st_mode & 0170000) == (y.st_mode & 0170000)) {
123*7c478bd9Sstevel@tonic-gate 
124*7c478bd9Sstevel@tonic-gate 		/*
125*7c478bd9Sstevel@tonic-gate 		 * If they are described by the same inode on the same device,
126*7c478bd9Sstevel@tonic-gate 		 * the two devices are the same.  Otherwise, if the devices are
127*7c478bd9Sstevel@tonic-gate 		 * character-special or block-special devices, try to match by
128*7c478bd9Sstevel@tonic-gate 		 * device type and major and minor device numbers.
129*7c478bd9Sstevel@tonic-gate 		 */
130*7c478bd9Sstevel@tonic-gate 
131*7c478bd9Sstevel@tonic-gate 	    if ((x.st_dev == y.st_dev) && (x.st_ino == y.st_ino)) same = TRUE;
132*7c478bd9Sstevel@tonic-gate 	    else
133*7c478bd9Sstevel@tonic-gate 		if (((x.st_mode & 0170000) == 0020000) ||
134*7c478bd9Sstevel@tonic-gate 		    ((x.st_mode & 0170000) == 0060000)) {
135*7c478bd9Sstevel@tonic-gate 		    if ((major(x.st_rdev) == major(y.st_rdev)) &&
136*7c478bd9Sstevel@tonic-gate 			(minor(x.st_rdev) == minor(y.st_rdev))) same = TRUE;
137*7c478bd9Sstevel@tonic-gate 		    else same = FALSE;
138*7c478bd9Sstevel@tonic-gate 		} else same = FALSE;
139*7c478bd9Sstevel@tonic-gate 
140*7c478bd9Sstevel@tonic-gate 	} else same = FALSE;
141*7c478bd9Sstevel@tonic-gate 
142*7c478bd9Sstevel@tonic-gate 	return (same);
143*7c478bd9Sstevel@tonic-gate }
144*7c478bd9Sstevel@tonic-gate 
145*7c478bd9Sstevel@tonic-gate /*
146*7c478bd9Sstevel@tonic-gate  *  void _setdevtab()
147*7c478bd9Sstevel@tonic-gate  *
148*7c478bd9Sstevel@tonic-gate  *	This function rewinds the open device table so that the next
149*7c478bd9Sstevel@tonic-gate  *	_getdevtabent() returns the first record in the device table.
150*7c478bd9Sstevel@tonic-gate  *
151*7c478bd9Sstevel@tonic-gate  *  Arguments:  None
152*7c478bd9Sstevel@tonic-gate  *
153*7c478bd9Sstevel@tonic-gate  *  Returns:  Void
154*7c478bd9Sstevel@tonic-gate  */
155*7c478bd9Sstevel@tonic-gate 
156*7c478bd9Sstevel@tonic-gate void
157*7c478bd9Sstevel@tonic-gate _setdevtab(void)
158*7c478bd9Sstevel@tonic-gate {
159*7c478bd9Sstevel@tonic-gate 	/*  If the device table file is open, rewind the file  */
160*7c478bd9Sstevel@tonic-gate 	if (oam_devtab != NULL) {
161*7c478bd9Sstevel@tonic-gate 	    rewind(oam_devtab);
162*7c478bd9Sstevel@tonic-gate 	    dtabrecnum = 0;
163*7c478bd9Sstevel@tonic-gate 	}
164*7c478bd9Sstevel@tonic-gate }
165*7c478bd9Sstevel@tonic-gate 
166*7c478bd9Sstevel@tonic-gate /*
167*7c478bd9Sstevel@tonic-gate  *  void _enddevtab()
168*7c478bd9Sstevel@tonic-gate  *
169*7c478bd9Sstevel@tonic-gate  *	This function closes the open device table.  It resets the
170*7c478bd9Sstevel@tonic-gate  *	open device table external variable to NULL.
171*7c478bd9Sstevel@tonic-gate  *
172*7c478bd9Sstevel@tonic-gate  *  Arguments:  None
173*7c478bd9Sstevel@tonic-gate  *
174*7c478bd9Sstevel@tonic-gate  *  Returns:  Void
175*7c478bd9Sstevel@tonic-gate  */
176*7c478bd9Sstevel@tonic-gate 
177*7c478bd9Sstevel@tonic-gate void
178*7c478bd9Sstevel@tonic-gate _enddevtab(void)
179*7c478bd9Sstevel@tonic-gate {
180*7c478bd9Sstevel@tonic-gate 	/*  If the device table file is open, close it  */
181*7c478bd9Sstevel@tonic-gate 	if (oam_devtab != NULL) {
182*7c478bd9Sstevel@tonic-gate 	    (void) fclose(oam_devtab);
183*7c478bd9Sstevel@tonic-gate 	    oam_devtab = NULL;
184*7c478bd9Sstevel@tonic-gate 	    dtabrecnum = 0;
185*7c478bd9Sstevel@tonic-gate 	}
186*7c478bd9Sstevel@tonic-gate }
187*7c478bd9Sstevel@tonic-gate 
188*7c478bd9Sstevel@tonic-gate /*
189*7c478bd9Sstevel@tonic-gate  *  char *getfld(ptr, delims)
190*7c478bd9Sstevel@tonic-gate  *	char   *ptr
191*7c478bd9Sstevel@tonic-gate  *	char   *delims
192*7c478bd9Sstevel@tonic-gate  *
193*7c478bd9Sstevel@tonic-gate  *  Notes:
194*7c478bd9Sstevel@tonic-gate  *    -	Can't use "strtok()" because of its use of static data.  The caller
195*7c478bd9Sstevel@tonic-gate  *	may be using strtok() and we'll really mess them up.
196*7c478bd9Sstevel@tonic-gate  *    - The function returns NULL if it didn't find any token -- '\0' can't
197*7c478bd9Sstevel@tonic-gate  *	be a delimiter using this algorithm.
198*7c478bd9Sstevel@tonic-gate  */
199*7c478bd9Sstevel@tonic-gate 
200*7c478bd9Sstevel@tonic-gate static char *
201*7c478bd9Sstevel@tonic-gate getfld(
202*7c478bd9Sstevel@tonic-gate 	char   *ptr,		/* String to parse */
203*7c478bd9Sstevel@tonic-gate 	char   *delims)		/* List of delimiters */
204*7c478bd9Sstevel@tonic-gate {
205*7c478bd9Sstevel@tonic-gate 	int	done;		/* TRUE if we're finished */
206*7c478bd9Sstevel@tonic-gate 	char   *p, *q;		/* Temp pointers */
207*7c478bd9Sstevel@tonic-gate 
208*7c478bd9Sstevel@tonic-gate 	/*
209*7c478bd9Sstevel@tonic-gate 	 *  Figure out where to start.
210*7c478bd9Sstevel@tonic-gate 	 *  If given a pointer, use that.
211*7c478bd9Sstevel@tonic-gate 	 *  Otherwise, use where we left off.
212*7c478bd9Sstevel@tonic-gate 	 */
213*7c478bd9Sstevel@tonic-gate 
214*7c478bd9Sstevel@tonic-gate 	p = ptr ? ptr : leftoff;
215*7c478bd9Sstevel@tonic-gate 
216*7c478bd9Sstevel@tonic-gate 
217*7c478bd9Sstevel@tonic-gate 	/*
218*7c478bd9Sstevel@tonic-gate 	 *  If there's anything to parse, search the string for the first
219*7c478bd9Sstevel@tonic-gate 	 *  occurrence of any of the delimiters.  If one is found, change it
220*7c478bd9Sstevel@tonic-gate 	 *  to '\0' and remember the place to start for next time.  If not
221*7c478bd9Sstevel@tonic-gate 	 *  found, forget the restart address and prepare to return NULL.
222*7c478bd9Sstevel@tonic-gate 	 *  Don't terminate on "escaped" characters.
223*7c478bd9Sstevel@tonic-gate 	 */
224*7c478bd9Sstevel@tonic-gate 
225*7c478bd9Sstevel@tonic-gate 	if (p) {				    /* Anything to do ?? */
226*7c478bd9Sstevel@tonic-gate 	    q = p;				    /* Where to begin */
227*7c478bd9Sstevel@tonic-gate 	    done = FALSE;			    /* We're not done yet */
228*7c478bd9Sstevel@tonic-gate 	    while (*q && !done) {		    /* Any more chars */
229*7c478bd9Sstevel@tonic-gate 		if (*q == '\\') {		    /* Escaped ? */
230*7c478bd9Sstevel@tonic-gate 		    if (*(++q)) q++;		    /* Skip escaped char */
231*7c478bd9Sstevel@tonic-gate 		} else				    /* Not escaped */
232*7c478bd9Sstevel@tonic-gate 		    if (!strchr(delims, *q)) q++;   /* Skip non-delim */
233*7c478bd9Sstevel@tonic-gate 		    else done = TRUE;		    /* Otherwise, done */
234*7c478bd9Sstevel@tonic-gate 	    }
235*7c478bd9Sstevel@tonic-gate 	    if (*q) {				    /* Terminator found? */
236*7c478bd9Sstevel@tonic-gate 		*q++ = '\0';			    /* Null-terminate token */
237*7c478bd9Sstevel@tonic-gate 		leftoff = q;			    /* Remember restart pt. */
238*7c478bd9Sstevel@tonic-gate 	    } else
239*7c478bd9Sstevel@tonic-gate 		leftoff = p = NULL;		    /* Nothin found or left */
240*7c478bd9Sstevel@tonic-gate 	}
241*7c478bd9Sstevel@tonic-gate 
242*7c478bd9Sstevel@tonic-gate 	/*  Finished  */
243*7c478bd9Sstevel@tonic-gate 	return (p);				    /* Return ptr to token */
244*7c478bd9Sstevel@tonic-gate }
245*7c478bd9Sstevel@tonic-gate 
246*7c478bd9Sstevel@tonic-gate /*
247*7c478bd9Sstevel@tonic-gate  *  char *getquoted(ptr)
248*7c478bd9Sstevel@tonic-gate  *	char   *ptr;
249*7c478bd9Sstevel@tonic-gate  *
250*7c478bd9Sstevel@tonic-gate  *	This function extracts a quoted string from the string pointed
251*7c478bd9Sstevel@tonic-gate  *	to by <ptr>, or, if <ptr> is NULL, wherever we left off
252*7c478bd9Sstevel@tonic-gate  *	last time.
253*7c478bd9Sstevel@tonic-gate  *
254*7c478bd9Sstevel@tonic-gate  *  Arguments:
255*7c478bd9Sstevel@tonic-gate  *	char *ptr	Pointer to the character-string to parse, or
256*7c478bd9Sstevel@tonic-gate  *			(char *) NULL if we're to pick up where we
257*7c478bd9Sstevel@tonic-gate  *			[getquoted(), getfld(), and getattrval()] left off.
258*7c478bd9Sstevel@tonic-gate  *
259*7c478bd9Sstevel@tonic-gate  *  Returns:  char *
260*7c478bd9Sstevel@tonic-gate  *	The address of malloc()ed space that contains the possibly quoted
261*7c478bd9Sstevel@tonic-gate  *	string.
262*7c478bd9Sstevel@tonic-gate  *
263*7c478bd9Sstevel@tonic-gate  *  Notes:
264*7c478bd9Sstevel@tonic-gate  *    -	This code only works if it can assume that the last character in
265*7c478bd9Sstevel@tonic-gate  *	the string it's parsing is a '\n', something that is guarenteed
266*7c478bd9Sstevel@tonic-gate  *	by the getnextrec() function.
267*7c478bd9Sstevel@tonic-gate  */
268*7c478bd9Sstevel@tonic-gate 
269*7c478bd9Sstevel@tonic-gate static char *
270*7c478bd9Sstevel@tonic-gate getquoted(char *ptr)
271*7c478bd9Sstevel@tonic-gate {
272*7c478bd9Sstevel@tonic-gate 	/*  Automatic data  */
273*7c478bd9Sstevel@tonic-gate 	char   *rtn;		/* Value to return */
274*7c478bd9Sstevel@tonic-gate 	char   *p, *q;		/* Temps */
275*7c478bd9Sstevel@tonic-gate 
276*7c478bd9Sstevel@tonic-gate 	/* Figure out where to start off */
277*7c478bd9Sstevel@tonic-gate 	p = ptr ? ptr : leftoff;
278*7c478bd9Sstevel@tonic-gate 
279*7c478bd9Sstevel@tonic-gate 	/* If there's anything to parse and it's a quoted string ... */
280*7c478bd9Sstevel@tonic-gate 	if ((p) && (*p == '"') && (p = getfld(p+1, "\""))) {
281*7c478bd9Sstevel@tonic-gate 
282*7c478bd9Sstevel@tonic-gate 	    /* Copy string for the caller */
283*7c478bd9Sstevel@tonic-gate 	    if (rtn = malloc(strlen(p)+1)) {	/* Malloc() space */
284*7c478bd9Sstevel@tonic-gate 		q = rtn;			/* Set up temp ptr */
285*7c478bd9Sstevel@tonic-gate 		do {
286*7c478bd9Sstevel@tonic-gate 		    if (*p == '\\') p++;	/* Skip escape */
287*7c478bd9Sstevel@tonic-gate 		    *q++ = *p;			/* Copy char */
288*7c478bd9Sstevel@tonic-gate 		} while (*p++); 		/* While there's chars */
289*7c478bd9Sstevel@tonic-gate 	    } else leftoff = rtn = NULL;
290*7c478bd9Sstevel@tonic-gate 	} else leftoff = rtn = NULL;
291*7c478bd9Sstevel@tonic-gate 
292*7c478bd9Sstevel@tonic-gate 	/* Fini */
293*7c478bd9Sstevel@tonic-gate 	return (rtn);
294*7c478bd9Sstevel@tonic-gate }
295*7c478bd9Sstevel@tonic-gate 
296*7c478bd9Sstevel@tonic-gate /*
297*7c478bd9Sstevel@tonic-gate  *  struct attrval *getattrval(ptr)
298*7c478bd9Sstevel@tonic-gate  *	char   *ptr
299*7c478bd9Sstevel@tonic-gate  *
300*7c478bd9Sstevel@tonic-gate  *	This function extracts the next attr=val pair from <ptr> or wherever
301*7c478bd9Sstevel@tonic-gate  *	getfld() left off...
302*7c478bd9Sstevel@tonic-gate  *
303*7c478bd9Sstevel@tonic-gate  *  Arguments:
304*7c478bd9Sstevel@tonic-gate  *	char *ptr	The string to parse, or (char *) NULL if we're to
305*7c478bd9Sstevel@tonic-gate  *			begin wherever we left off last time.
306*7c478bd9Sstevel@tonic-gate  *
307*7c478bd9Sstevel@tonic-gate  *  Returns:  struct attrval *
308*7c478bd9Sstevel@tonic-gate  *	The address of a malloc()ed structure containing the attribute and the
309*7c478bd9Sstevel@tonic-gate  *	value of the attr=val pair extracted.
310*7c478bd9Sstevel@tonic-gate  */
311*7c478bd9Sstevel@tonic-gate 
312*7c478bd9Sstevel@tonic-gate static struct attrval *
313*7c478bd9Sstevel@tonic-gate getattrval(char *ptr)
314*7c478bd9Sstevel@tonic-gate {
315*7c478bd9Sstevel@tonic-gate 	/*  Automatic data  */
316*7c478bd9Sstevel@tonic-gate 	struct attrval *rtn;		/* Ptr to struct to return */
317*7c478bd9Sstevel@tonic-gate 	char		*p, *q;		/* Temp pointers */
318*7c478bd9Sstevel@tonic-gate 
319*7c478bd9Sstevel@tonic-gate 
320*7c478bd9Sstevel@tonic-gate 	/*  Use what's given to us or wherever we left off  */
321*7c478bd9Sstevel@tonic-gate 	p = ptr ? ptr : leftoff;
322*7c478bd9Sstevel@tonic-gate 
323*7c478bd9Sstevel@tonic-gate 	/*  If there's anything to parse, extract the next attr=val pair  */
324*7c478bd9Sstevel@tonic-gate 	if (p) {
325*7c478bd9Sstevel@tonic-gate 
326*7c478bd9Sstevel@tonic-gate 	    /*  Eat white space  */
327*7c478bd9Sstevel@tonic-gate 	    while (*p && isspace((unsigned char)*p)) p++;
328*7c478bd9Sstevel@tonic-gate 
329*7c478bd9Sstevel@tonic-gate 	    /*  Extract the attribute name, if any  */
330*7c478bd9Sstevel@tonic-gate 	    if (*p && getfld(p, "=")) {
331*7c478bd9Sstevel@tonic-gate 
332*7c478bd9Sstevel@tonic-gate 		/*  Allocate space for the structure we're building  */
333*7c478bd9Sstevel@tonic-gate 		if (rtn = malloc(sizeof (struct attrval))) {
334*7c478bd9Sstevel@tonic-gate 
335*7c478bd9Sstevel@tonic-gate 		    /*  Allocate space for the attribute name  */
336*7c478bd9Sstevel@tonic-gate 		    if (rtn->attr = malloc(strlen(p)+1)) {
337*7c478bd9Sstevel@tonic-gate 
338*7c478bd9Sstevel@tonic-gate 			/*  Copy the attribute name into alloc'd space  */
339*7c478bd9Sstevel@tonic-gate 			q = rtn->attr;			/* Set up temp ptr */
340*7c478bd9Sstevel@tonic-gate 			do {
341*7c478bd9Sstevel@tonic-gate 			    if (*p == '\\') p++;	/* Skip escape */
342*7c478bd9Sstevel@tonic-gate 			    *q++ = *p;			/* Copy char */
343*7c478bd9Sstevel@tonic-gate 			} while (*p++); 		/* While more */
344*7c478bd9Sstevel@tonic-gate 
345*7c478bd9Sstevel@tonic-gate 			/*  Extract the value  */
346*7c478bd9Sstevel@tonic-gate 			if (!(rtn->val = getquoted(NULL))) {
347*7c478bd9Sstevel@tonic-gate 			    /* Error getting value, free resources */
348*7c478bd9Sstevel@tonic-gate 			    free(rtn->attr);
349*7c478bd9Sstevel@tonic-gate 			    free(rtn);
350*7c478bd9Sstevel@tonic-gate 			    leftoff = NULL;
351*7c478bd9Sstevel@tonic-gate 			    rtn = NULL;
352*7c478bd9Sstevel@tonic-gate 			}
353*7c478bd9Sstevel@tonic-gate 		    } else {
354*7c478bd9Sstevel@tonic-gate 			/* Error getting space for attribute, free resources */
355*7c478bd9Sstevel@tonic-gate 			free(rtn);
356*7c478bd9Sstevel@tonic-gate 			leftoff = NULL;
357*7c478bd9Sstevel@tonic-gate 			rtn = NULL;
358*7c478bd9Sstevel@tonic-gate 		    }
359*7c478bd9Sstevel@tonic-gate 
360*7c478bd9Sstevel@tonic-gate 		} else {
361*7c478bd9Sstevel@tonic-gate 		    /* No space for attr struct */
362*7c478bd9Sstevel@tonic-gate 		    leftoff = NULL;
363*7c478bd9Sstevel@tonic-gate 		    rtn = NULL;
364*7c478bd9Sstevel@tonic-gate 		}
365*7c478bd9Sstevel@tonic-gate 
366*7c478bd9Sstevel@tonic-gate 	    } else {
367*7c478bd9Sstevel@tonic-gate 		/* No attribute name */
368*7c478bd9Sstevel@tonic-gate 		leftoff = NULL;
369*7c478bd9Sstevel@tonic-gate 		rtn = NULL;
370*7c478bd9Sstevel@tonic-gate 	    }
371*7c478bd9Sstevel@tonic-gate 
372*7c478bd9Sstevel@tonic-gate 	} else {
373*7c478bd9Sstevel@tonic-gate 	    /* Nothing to parse */
374*7c478bd9Sstevel@tonic-gate 	    leftoff = NULL;
375*7c478bd9Sstevel@tonic-gate 	    rtn = NULL;
376*7c478bd9Sstevel@tonic-gate 	}
377*7c478bd9Sstevel@tonic-gate 
378*7c478bd9Sstevel@tonic-gate 	/* Done */
379*7c478bd9Sstevel@tonic-gate 	return (rtn);
380*7c478bd9Sstevel@tonic-gate }
381*7c478bd9Sstevel@tonic-gate 
382*7c478bd9Sstevel@tonic-gate /*
383*7c478bd9Sstevel@tonic-gate  *  char *getnextrec()
384*7c478bd9Sstevel@tonic-gate  *
385*7c478bd9Sstevel@tonic-gate  *	This function gets the next record from the input stream "oam_devtab"
386*7c478bd9Sstevel@tonic-gate  *	and puts it in the device-table record buffer (whose address is in
387*7c478bd9Sstevel@tonic-gate  *	"recbuf").  If the buffer is not allocated or is too small to
388*7c478bd9Sstevel@tonic-gate  *	accommodate the record, the function allocates more space to the
389*7c478bd9Sstevel@tonic-gate  *	buffer.
390*7c478bd9Sstevel@tonic-gate  *
391*7c478bd9Sstevel@tonic-gate  *  Arguments:  None
392*7c478bd9Sstevel@tonic-gate  *
393*7c478bd9Sstevel@tonic-gate  *  Returns:  char *
394*7c478bd9Sstevel@tonic-gate  *	The address of the buffer containing the record.
395*7c478bd9Sstevel@tonic-gate  *
396*7c478bd9Sstevel@tonic-gate  *  Static Data Referenced:
397*7c478bd9Sstevel@tonic-gate  *	recbuf		Address of the buffer containing records read from the
398*7c478bd9Sstevel@tonic-gate  *			device table file
399*7c478bd9Sstevel@tonic-gate  *	recbufsz	Current size of the record buffer
400*7c478bd9Sstevel@tonic-gate  *	xtndcnt		Number of times the record buffer has been extended
401*7c478bd9Sstevel@tonic-gate  *	oam_devtab	Device table stream, expected to be open for (at
402*7c478bd9Sstevel@tonic-gate  *			least) reading
403*7c478bd9Sstevel@tonic-gate  *
404*7c478bd9Sstevel@tonic-gate  *  Notes:
405*7c478bd9Sstevel@tonic-gate  *    - The string returned in the buffer <buf> ALWAYS end in a '\n' (newline)
406*7c478bd9Sstevel@tonic-gate  *	character followed by a '\0' (null).
407*7c478bd9Sstevel@tonic-gate  */
408*7c478bd9Sstevel@tonic-gate 
409*7c478bd9Sstevel@tonic-gate static char *
410*7c478bd9Sstevel@tonic-gate getnextrec(void)
411*7c478bd9Sstevel@tonic-gate {
412*7c478bd9Sstevel@tonic-gate 	/* Automatic data */
413*7c478bd9Sstevel@tonic-gate 	char		*recp;		/* Value to return */
414*7c478bd9Sstevel@tonic-gate 	char		*p;		/* Temp pointer */
415*7c478bd9Sstevel@tonic-gate 	int		done;		/* TRUE if we're finished */
416*7c478bd9Sstevel@tonic-gate 	int		reclen;		/* Number of chars in record */
417*7c478bd9Sstevel@tonic-gate 
418*7c478bd9Sstevel@tonic-gate 
419*7c478bd9Sstevel@tonic-gate 	/* If there's no buffer for records, try to get one */
420*7c478bd9Sstevel@tonic-gate 	if (!recbuf) {
421*7c478bd9Sstevel@tonic-gate 	    if (recbuf = malloc(DTAB_BUFSIZ)) {
422*7c478bd9Sstevel@tonic-gate 		recbufsz = DTAB_BUFSIZ;
423*7c478bd9Sstevel@tonic-gate 		xtndcnt = 0;
424*7c478bd9Sstevel@tonic-gate 	    } else return (NULL);
425*7c478bd9Sstevel@tonic-gate 	}
426*7c478bd9Sstevel@tonic-gate 
427*7c478bd9Sstevel@tonic-gate 
428*7c478bd9Sstevel@tonic-gate 	/* Get the next record */
429*7c478bd9Sstevel@tonic-gate 	recp = fgets(recbuf, recbufsz, oam_devtab);
430*7c478bd9Sstevel@tonic-gate 	done = FALSE;
431*7c478bd9Sstevel@tonic-gate 
432*7c478bd9Sstevel@tonic-gate 	/* While we've something to return and we're not finished ... */
433*7c478bd9Sstevel@tonic-gate 	while (recp && !done) {
434*7c478bd9Sstevel@tonic-gate 
435*7c478bd9Sstevel@tonic-gate 	    /* If our return string isn't a null-string ... */
436*7c478bd9Sstevel@tonic-gate 	    if ((reclen = (int)strlen(recp)) != 0) {
437*7c478bd9Sstevel@tonic-gate 
438*7c478bd9Sstevel@tonic-gate 		/* If we have a complete record, we're finished */
439*7c478bd9Sstevel@tonic-gate 		if ((*(recp+reclen-1) == '\n') &&
440*7c478bd9Sstevel@tonic-gate 		    ((reclen == 1) || (*(recp+reclen-2) != '\\'))) done = TRUE;
441*7c478bd9Sstevel@tonic-gate 		else while (!done) {
442*7c478bd9Sstevel@tonic-gate 
443*7c478bd9Sstevel@tonic-gate 			/*
444*7c478bd9Sstevel@tonic-gate 			 * Need to complete the record.  A complete record is
445*7c478bd9Sstevel@tonic-gate 			 * one which is terminated by an unescaped new-line
446*7c478bd9Sstevel@tonic-gate 			 * character.
447*7c478bd9Sstevel@tonic-gate 			 */
448*7c478bd9Sstevel@tonic-gate 
449*7c478bd9Sstevel@tonic-gate 		    /* If the buffer is full, expand it and continue reading */
450*7c478bd9Sstevel@tonic-gate 		    if (reclen == recbufsz-1) {
451*7c478bd9Sstevel@tonic-gate 
452*7c478bd9Sstevel@tonic-gate 			/* Have we reached our maximum extension count? */
453*7c478bd9Sstevel@tonic-gate 			if (xtndcnt < XTND_MAXCNT) {
454*7c478bd9Sstevel@tonic-gate 
455*7c478bd9Sstevel@tonic-gate 			    /* Expand the record buffer */
456*7c478bd9Sstevel@tonic-gate 			    if (p = realloc(recbuf,
457*7c478bd9Sstevel@tonic-gate 				(size_t)recbufsz+DTAB_BUFINC)) {
458*7c478bd9Sstevel@tonic-gate 
459*7c478bd9Sstevel@tonic-gate 				/* Update buffer information */
460*7c478bd9Sstevel@tonic-gate 				xtndcnt++;
461*7c478bd9Sstevel@tonic-gate 				recbuf = p;
462*7c478bd9Sstevel@tonic-gate 				recbufsz += DTAB_BUFINC;
463*7c478bd9Sstevel@tonic-gate 
464*7c478bd9Sstevel@tonic-gate 			    } else {
465*7c478bd9Sstevel@tonic-gate 
466*7c478bd9Sstevel@tonic-gate 				/* Expansion failed */
467*7c478bd9Sstevel@tonic-gate 				recp = NULL;
468*7c478bd9Sstevel@tonic-gate 				done = TRUE;
469*7c478bd9Sstevel@tonic-gate 			    }
470*7c478bd9Sstevel@tonic-gate 
471*7c478bd9Sstevel@tonic-gate 			} else {
472*7c478bd9Sstevel@tonic-gate 
473*7c478bd9Sstevel@tonic-gate 			    /* Maximum extend count exceeded.  Insane table */
474*7c478bd9Sstevel@tonic-gate 			    recp = NULL;
475*7c478bd9Sstevel@tonic-gate 			    done = TRUE;
476*7c478bd9Sstevel@tonic-gate 			}
477*7c478bd9Sstevel@tonic-gate 
478*7c478bd9Sstevel@tonic-gate 		    }
479*7c478bd9Sstevel@tonic-gate 
480*7c478bd9Sstevel@tonic-gate 		    /* Complete the record */
481*7c478bd9Sstevel@tonic-gate 		    if (!done) {
482*7c478bd9Sstevel@tonic-gate 
483*7c478bd9Sstevel@tonic-gate 			/* Read stuff into the expanded space */
484*7c478bd9Sstevel@tonic-gate 			if (fgets(recbuf+reclen, recbufsz-reclen, oam_devtab)) {
485*7c478bd9Sstevel@tonic-gate 			    reclen = (int)strlen(recbuf);
486*7c478bd9Sstevel@tonic-gate 			    recp = recbuf;
487*7c478bd9Sstevel@tonic-gate 			    if ((*(recp+reclen-1) == '\n') &&
488*7c478bd9Sstevel@tonic-gate 				((reclen == 1) || (*(recp+reclen-2) != '\\')))
489*7c478bd9Sstevel@tonic-gate 				    done = TRUE;
490*7c478bd9Sstevel@tonic-gate 			} else {
491*7c478bd9Sstevel@tonic-gate 			    /* Read failed, corrupt record? */
492*7c478bd9Sstevel@tonic-gate 			    recp = NULL;
493*7c478bd9Sstevel@tonic-gate 			    done = TRUE;
494*7c478bd9Sstevel@tonic-gate 			}
495*7c478bd9Sstevel@tonic-gate 		    }
496*7c478bd9Sstevel@tonic-gate 
497*7c478bd9Sstevel@tonic-gate 		}   /* End incomplete record handling */
498*7c478bd9Sstevel@tonic-gate 
499*7c478bd9Sstevel@tonic-gate 	    } else {
500*7c478bd9Sstevel@tonic-gate 
501*7c478bd9Sstevel@tonic-gate 		/* Read a null string?  (corrupt table) */
502*7c478bd9Sstevel@tonic-gate 		recp = NULL;
503*7c478bd9Sstevel@tonic-gate 		done = TRUE;
504*7c478bd9Sstevel@tonic-gate 	    }
505*7c478bd9Sstevel@tonic-gate 
506*7c478bd9Sstevel@tonic-gate 	}   /* while (recp && !done) */
507*7c478bd9Sstevel@tonic-gate 
508*7c478bd9Sstevel@tonic-gate 	/* Return what we've got (if anything) */
509*7c478bd9Sstevel@tonic-gate 	return (recp);
510*7c478bd9Sstevel@tonic-gate }
511*7c478bd9Sstevel@tonic-gate 
512*7c478bd9Sstevel@tonic-gate /*
513*7c478bd9Sstevel@tonic-gate  *  char *_devtabpath()
514*7c478bd9Sstevel@tonic-gate  *
515*7c478bd9Sstevel@tonic-gate  *	Get the pathname of the device table
516*7c478bd9Sstevel@tonic-gate  *
517*7c478bd9Sstevel@tonic-gate  *  Arguments:  None
518*7c478bd9Sstevel@tonic-gate  *
519*7c478bd9Sstevel@tonic-gate  *  Returns:  char *
520*7c478bd9Sstevel@tonic-gate  *	Returns the pathname to the device table of NULL if
521*7c478bd9Sstevel@tonic-gate  *	there was a problem getting the memory needed to contain the
522*7c478bd9Sstevel@tonic-gate  *	pathname.
523*7c478bd9Sstevel@tonic-gate  *
524*7c478bd9Sstevel@tonic-gate  *  Algorithm:
525*7c478bd9Sstevel@tonic-gate  *	1.  If OAM_DEVTAB is defined in the environment and is not
526*7c478bd9Sstevel@tonic-gate  *	    defined as "", it returns the value of that environment
527*7c478bd9Sstevel@tonic-gate  *	    variable.
528*7c478bd9Sstevel@tonic-gate  *	2.  Otherwise, use the value of the environment variable DTAB_PATH.
529*7c478bd9Sstevel@tonic-gate  */
530*7c478bd9Sstevel@tonic-gate 
531*7c478bd9Sstevel@tonic-gate 
532*7c478bd9Sstevel@tonic-gate char *
533*7c478bd9Sstevel@tonic-gate _devtabpath(void)
534*7c478bd9Sstevel@tonic-gate {
535*7c478bd9Sstevel@tonic-gate 
536*7c478bd9Sstevel@tonic-gate 	/* Automatic data */
537*7c478bd9Sstevel@tonic-gate #ifdef	DEBUG
538*7c478bd9Sstevel@tonic-gate 	char		*path;		/* Ptr to path in environment */
539*7c478bd9Sstevel@tonic-gate #endif
540*7c478bd9Sstevel@tonic-gate 	char		*rtnval;		/* Ptr to value to return */
541*7c478bd9Sstevel@tonic-gate 
542*7c478bd9Sstevel@tonic-gate 
543*7c478bd9Sstevel@tonic-gate 	/*
544*7c478bd9Sstevel@tonic-gate 	 * If compiled with -DDEBUG=1,
545*7c478bd9Sstevel@tonic-gate 	 * look for the pathname in the environment
546*7c478bd9Sstevel@tonic-gate 	 */
547*7c478bd9Sstevel@tonic-gate 
548*7c478bd9Sstevel@tonic-gate #ifdef	DEBUG
549*7c478bd9Sstevel@tonic-gate 	if (((path = getenv(OAM_DEVTAB)) != NULL) && (*path)) {
550*7c478bd9Sstevel@tonic-gate 	    if (rtnval = malloc(strlen(path)+1))
551*7c478bd9Sstevel@tonic-gate 		(void) strcpy(rtnval, path);
552*7c478bd9Sstevel@tonic-gate 	} else {
553*7c478bd9Sstevel@tonic-gate #endif
554*7c478bd9Sstevel@tonic-gate 		/*
555*7c478bd9Sstevel@tonic-gate 		 * Use the standard device table.
556*7c478bd9Sstevel@tonic-gate 		 */
557*7c478bd9Sstevel@tonic-gate 
558*7c478bd9Sstevel@tonic-gate 	    if (rtnval = malloc(strlen(DTAB_PATH)+1))
559*7c478bd9Sstevel@tonic-gate 		(void) strcpy(rtnval, DTAB_PATH);
560*7c478bd9Sstevel@tonic-gate 
561*7c478bd9Sstevel@tonic-gate #ifdef	DEBUG
562*7c478bd9Sstevel@tonic-gate 	}
563*7c478bd9Sstevel@tonic-gate #endif
564*7c478bd9Sstevel@tonic-gate 
565*7c478bd9Sstevel@tonic-gate 	/* Finished */
566*7c478bd9Sstevel@tonic-gate 	return (rtnval);
567*7c478bd9Sstevel@tonic-gate }
568*7c478bd9Sstevel@tonic-gate 
569*7c478bd9Sstevel@tonic-gate /*
570*7c478bd9Sstevel@tonic-gate  *  int _opendevtab(mode)
571*7c478bd9Sstevel@tonic-gate  *	char   *mode
572*7c478bd9Sstevel@tonic-gate  *
573*7c478bd9Sstevel@tonic-gate  *	The _opendevtab() function opens a device table for a command.
574*7c478bd9Sstevel@tonic-gate  *
575*7c478bd9Sstevel@tonic-gate  *  Arguments:
576*7c478bd9Sstevel@tonic-gate  *	mode	The open mode to use to open the file.  (i.e. "r" for
577*7c478bd9Sstevel@tonic-gate  *		reading, "w" for writing.  See FOPEN(BA_OS) in SVID.)
578*7c478bd9Sstevel@tonic-gate  *
579*7c478bd9Sstevel@tonic-gate  *  Returns:  int
580*7c478bd9Sstevel@tonic-gate  *	TRUE if it successfully opens the device table file, FALSE otherwise
581*7c478bd9Sstevel@tonic-gate  */
582*7c478bd9Sstevel@tonic-gate 
583*7c478bd9Sstevel@tonic-gate int
584*7c478bd9Sstevel@tonic-gate _opendevtab(char *mode)
585*7c478bd9Sstevel@tonic-gate {
586*7c478bd9Sstevel@tonic-gate 	/*
587*7c478bd9Sstevel@tonic-gate 	 *  Automatic data
588*7c478bd9Sstevel@tonic-gate 	 */
589*7c478bd9Sstevel@tonic-gate 
590*7c478bd9Sstevel@tonic-gate 	char   *devtabname;		/* Ptr to the device table name */
591*7c478bd9Sstevel@tonic-gate 	int	rtnval;			/* Value to return */
592*7c478bd9Sstevel@tonic-gate 
593*7c478bd9Sstevel@tonic-gate 
594*7c478bd9Sstevel@tonic-gate 	rtnval = TRUE;
595*7c478bd9Sstevel@tonic-gate 	if (devtabname = _devtabpath()) {
596*7c478bd9Sstevel@tonic-gate 	    if (oam_devtab) (void) fclose(oam_devtab);
597*7c478bd9Sstevel@tonic-gate 	    if (oam_devtab = fopen(devtabname, mode))
598*7c478bd9Sstevel@tonic-gate 		dtabrecnum = 0;  /* :-) */
599*7c478bd9Sstevel@tonic-gate 	    else rtnval = FALSE; /* :-( */
600*7c478bd9Sstevel@tonic-gate 	} else rtnval = FALSE;   /* :-( */
601*7c478bd9Sstevel@tonic-gate 	return (rtnval);
602*7c478bd9Sstevel@tonic-gate }
603*7c478bd9Sstevel@tonic-gate 
604*7c478bd9Sstevel@tonic-gate /*
605*7c478bd9Sstevel@tonic-gate  *  int _validalias(alias)
606*7c478bd9Sstevel@tonic-gate  *	char   *alias
607*7c478bd9Sstevel@tonic-gate  *
608*7c478bd9Sstevel@tonic-gate  *	Determine if <alias> is a valid alias.  Returns TRUE if it is
609*7c478bd9Sstevel@tonic-gate  *	a valid alias, FALSE otherwise.
610*7c478bd9Sstevel@tonic-gate  *
611*7c478bd9Sstevel@tonic-gate  *  Arguments:
612*7c478bd9Sstevel@tonic-gate  *	alias		Value to check out
613*7c478bd9Sstevel@tonic-gate  *
614*7c478bd9Sstevel@tonic-gate  *  Returns:  int
615*7c478bd9Sstevel@tonic-gate  *	TRUE if <alias> is a valid alias, FALSE otherwise.
616*7c478bd9Sstevel@tonic-gate  */
617*7c478bd9Sstevel@tonic-gate 
618*7c478bd9Sstevel@tonic-gate int
619*7c478bd9Sstevel@tonic-gate _validalias(char   *alias)			/* Alias to validate */
620*7c478bd9Sstevel@tonic-gate {
621*7c478bd9Sstevel@tonic-gate 	/* Automatic data */
622*7c478bd9Sstevel@tonic-gate 	char		*p;		/* Temp pointer */
623*7c478bd9Sstevel@tonic-gate 	size_t		len;		/* Length of <alias> */
624*7c478bd9Sstevel@tonic-gate 	int		rtn;		/* Value to return */
625*7c478bd9Sstevel@tonic-gate 
626*7c478bd9Sstevel@tonic-gate 
627*7c478bd9Sstevel@tonic-gate 	/* Assume the worst */
628*7c478bd9Sstevel@tonic-gate 	rtn = FALSE;
629*7c478bd9Sstevel@tonic-gate 
630*7c478bd9Sstevel@tonic-gate 	/*
631*7c478bd9Sstevel@tonic-gate 	 * A valid alias contains 0 < i <= 14 characters.  The first
632*7c478bd9Sstevel@tonic-gate 	 * must be alphanumeric or "@$_." and the rest must be alphanumeric
633*7c478bd9Sstevel@tonic-gate 	 * or "@#$_+-."
634*7c478bd9Sstevel@tonic-gate 	 */
635*7c478bd9Sstevel@tonic-gate 
636*7c478bd9Sstevel@tonic-gate 	/* Check length */
637*7c478bd9Sstevel@tonic-gate 	if ((alias != NULL) && ((len = strlen(alias)) > 0) && (len <= 14)) {
638*7c478bd9Sstevel@tonic-gate 
639*7c478bd9Sstevel@tonic-gate 	    /* Check the first character */
640*7c478bd9Sstevel@tonic-gate 	    p = alias;
641*7c478bd9Sstevel@tonic-gate 	    if (isalnum((unsigned char)*p) || strchr("@$_.", *p)) {
642*7c478bd9Sstevel@tonic-gate 
643*7c478bd9Sstevel@tonic-gate 		/* Check the rest of the characters */
644*7c478bd9Sstevel@tonic-gate 		for (p++; *p && (isalnum((unsigned char)*p) ||
645*7c478bd9Sstevel@tonic-gate 			strchr("@#$_-+.", *p)); p++)
646*7c478bd9Sstevel@tonic-gate 			;
647*7c478bd9Sstevel@tonic-gate 		if (!(*p)) rtn = TRUE;
648*7c478bd9Sstevel@tonic-gate 	    }
649*7c478bd9Sstevel@tonic-gate 	}
650*7c478bd9Sstevel@tonic-gate 
651*7c478bd9Sstevel@tonic-gate 	/* Return indicator... */
652*7c478bd9Sstevel@tonic-gate 	return (rtn);
653*7c478bd9Sstevel@tonic-gate 
654*7c478bd9Sstevel@tonic-gate }   /* int _validalias() */
655*7c478bd9Sstevel@tonic-gate 
656*7c478bd9Sstevel@tonic-gate /*
657*7c478bd9Sstevel@tonic-gate  *  struct devtabent *_getdevtabent()
658*7c478bd9Sstevel@tonic-gate  *
659*7c478bd9Sstevel@tonic-gate  *  	This function returns the next entry in the device table.
660*7c478bd9Sstevel@tonic-gate  *	If no device table is open, it opens the standard device table
661*7c478bd9Sstevel@tonic-gate  *	and returns the first record in the table.
662*7c478bd9Sstevel@tonic-gate  *
663*7c478bd9Sstevel@tonic-gate  *  Arguments:  None.
664*7c478bd9Sstevel@tonic-gate  *
665*7c478bd9Sstevel@tonic-gate  *  Returns:  struct devtabent *
666*7c478bd9Sstevel@tonic-gate  *	Pointer to the next record in the device table, or
667*7c478bd9Sstevel@tonic-gate  *	(struct devtabent *) NULL if it was unable to open the file or there
668*7c478bd9Sstevel@tonic-gate  *	are no more records to read.  "errno" reflects the situation.  If
669*7c478bd9Sstevel@tonic-gate  *	errno is not changed and the function returns NULL, there are no more
670*7c478bd9Sstevel@tonic-gate  *	records to read.  If errno is set, it indicates the error.
671*7c478bd9Sstevel@tonic-gate  *
672*7c478bd9Sstevel@tonic-gate  *  Notes:
673*7c478bd9Sstevel@tonic-gate  *    - The caller should set "errno" to 0 before calling this function.
674*7c478bd9Sstevel@tonic-gate  */
675*7c478bd9Sstevel@tonic-gate 
676*7c478bd9Sstevel@tonic-gate struct devtabent *
677*7c478bd9Sstevel@tonic-gate _getdevtabent(void)
678*7c478bd9Sstevel@tonic-gate {
679*7c478bd9Sstevel@tonic-gate 	/*  Automatic data  */
680*7c478bd9Sstevel@tonic-gate 	struct devtabent	*ent;	/* Ptr to dev table entry structure */
681*7c478bd9Sstevel@tonic-gate 	struct attrval		*attr;	/* Ptr to struct for attr/val pair */
682*7c478bd9Sstevel@tonic-gate 	struct attrval		*t;	/* Tmp ptr to attr/val struct */
683*7c478bd9Sstevel@tonic-gate 	char			*record; /* Ptr to the record just read */
684*7c478bd9Sstevel@tonic-gate 	char			*p, *q;	/* Tmp char ptrs */
685*7c478bd9Sstevel@tonic-gate 	int			done;	/* TRUE if we've built an entry */
686*7c478bd9Sstevel@tonic-gate 
687*7c478bd9Sstevel@tonic-gate 
688*7c478bd9Sstevel@tonic-gate 	/*  Open the device table if it's not already open */
689*7c478bd9Sstevel@tonic-gate 	if (oam_devtab == NULL) {
690*7c478bd9Sstevel@tonic-gate 	    if (!_opendevtab("r"))
691*7c478bd9Sstevel@tonic-gate 		return (NULL);
692*7c478bd9Sstevel@tonic-gate 	}
693*7c478bd9Sstevel@tonic-gate 
694*7c478bd9Sstevel@tonic-gate 	/*  Get space for the structure we're returning  */
695*7c478bd9Sstevel@tonic-gate 	if (!(ent = malloc(sizeof (struct devtabent)))) {
696*7c478bd9Sstevel@tonic-gate 	    return (NULL);
697*7c478bd9Sstevel@tonic-gate 	}
698*7c478bd9Sstevel@tonic-gate 
699*7c478bd9Sstevel@tonic-gate 	done = FALSE;
700*7c478bd9Sstevel@tonic-gate 	while (!done && (record = getnextrec())) {
701*7c478bd9Sstevel@tonic-gate 
702*7c478bd9Sstevel@tonic-gate 	    /* Save record number in structure */
703*7c478bd9Sstevel@tonic-gate 	    ent->entryno = dtabrecnum++;
704*7c478bd9Sstevel@tonic-gate 
705*7c478bd9Sstevel@tonic-gate 	    /* Comment record?  If so, just save the value and we're through */
706*7c478bd9Sstevel@tonic-gate 	    if (strchr("#\n", *record) || isspace((unsigned char)*record)) {
707*7c478bd9Sstevel@tonic-gate 		ent->comment = TRUE;
708*7c478bd9Sstevel@tonic-gate 		done = TRUE;
709*7c478bd9Sstevel@tonic-gate 		if (ent->attrstr = malloc(strlen(record)+1)) {
710*7c478bd9Sstevel@tonic-gate 		    q = ent->attrstr;
711*7c478bd9Sstevel@tonic-gate 		    p = record;
712*7c478bd9Sstevel@tonic-gate 		    do {
713*7c478bd9Sstevel@tonic-gate 			if (*p == '\\') p++;
714*7c478bd9Sstevel@tonic-gate 			*q++ = *p;
715*7c478bd9Sstevel@tonic-gate 		    } while (*p++);
716*7c478bd9Sstevel@tonic-gate 		} else {
717*7c478bd9Sstevel@tonic-gate 		    free(ent);
718*7c478bd9Sstevel@tonic-gate 		    ent = NULL;
719*7c478bd9Sstevel@tonic-gate 		}
720*7c478bd9Sstevel@tonic-gate 	    }
721*7c478bd9Sstevel@tonic-gate 
722*7c478bd9Sstevel@tonic-gate 	    else {
723*7c478bd9Sstevel@tonic-gate 
724*7c478bd9Sstevel@tonic-gate 		/* Record is a data record.   Parse it. */
725*7c478bd9Sstevel@tonic-gate 		ent->comment = FALSE;
726*7c478bd9Sstevel@tonic-gate 		ent->attrstr = NULL;  /* For now */
727*7c478bd9Sstevel@tonic-gate 
728*7c478bd9Sstevel@tonic-gate 		/* Extract the device alias */
729*7c478bd9Sstevel@tonic-gate 		if (p = getfld(record, ":")) {
730*7c478bd9Sstevel@tonic-gate 		    if (*p) {
731*7c478bd9Sstevel@tonic-gate 			if (ent->alias = malloc(strlen(p)+1)) {
732*7c478bd9Sstevel@tonic-gate 			    q = ent->alias;
733*7c478bd9Sstevel@tonic-gate 			    do {
734*7c478bd9Sstevel@tonic-gate 				if (*p == '\\') p++;
735*7c478bd9Sstevel@tonic-gate 				*q++ = *p;
736*7c478bd9Sstevel@tonic-gate 			    } while (*p++);
737*7c478bd9Sstevel@tonic-gate 			}
738*7c478bd9Sstevel@tonic-gate 		    } else ent->alias = NULL;
739*7c478bd9Sstevel@tonic-gate 
740*7c478bd9Sstevel@tonic-gate 		    /* Extract the character-device name */
741*7c478bd9Sstevel@tonic-gate 		    if ((p = getfld(NULL, ":")) == NULL) {
742*7c478bd9Sstevel@tonic-gate 			if (ent->alias)
743*7c478bd9Sstevel@tonic-gate 			    free(ent->alias);
744*7c478bd9Sstevel@tonic-gate 		    } else {
745*7c478bd9Sstevel@tonic-gate 			if (*p) {
746*7c478bd9Sstevel@tonic-gate 			    if (ent->cdevice = malloc(strlen(p)+1)) {
747*7c478bd9Sstevel@tonic-gate 				q = ent->cdevice;
748*7c478bd9Sstevel@tonic-gate 				do {
749*7c478bd9Sstevel@tonic-gate 				    if (*p == '\\') p++;
750*7c478bd9Sstevel@tonic-gate 				    *q++ = *p;
751*7c478bd9Sstevel@tonic-gate 				} while (*p++);
752*7c478bd9Sstevel@tonic-gate 			    }
753*7c478bd9Sstevel@tonic-gate 			} else ent->cdevice = NULL;
754*7c478bd9Sstevel@tonic-gate 
755*7c478bd9Sstevel@tonic-gate 			/* Extract the block-device name */
756*7c478bd9Sstevel@tonic-gate 			if (!(p = getfld(NULL, ":"))) {
757*7c478bd9Sstevel@tonic-gate 			    if (ent->alias) free(ent->alias);
758*7c478bd9Sstevel@tonic-gate 			    if (ent->cdevice) free(ent->cdevice);
759*7c478bd9Sstevel@tonic-gate 			} else {
760*7c478bd9Sstevel@tonic-gate 			    if (*p) {
761*7c478bd9Sstevel@tonic-gate 				if (ent->bdevice = malloc(strlen(p)+1)) {
762*7c478bd9Sstevel@tonic-gate 				    q = ent->bdevice;
763*7c478bd9Sstevel@tonic-gate 				    do {
764*7c478bd9Sstevel@tonic-gate 					if (*p == '\\') p++;
765*7c478bd9Sstevel@tonic-gate 					*q++ = *p;
766*7c478bd9Sstevel@tonic-gate 				    } while (*p++);
767*7c478bd9Sstevel@tonic-gate 				}
768*7c478bd9Sstevel@tonic-gate 			    } else
769*7c478bd9Sstevel@tonic-gate 				ent->bdevice = NULL;
770*7c478bd9Sstevel@tonic-gate 
771*7c478bd9Sstevel@tonic-gate 			    /* Extract the pathname */
772*7c478bd9Sstevel@tonic-gate 			    if ((p = getfld(NULL, ":\n")) == NULL) {
773*7c478bd9Sstevel@tonic-gate 				if (ent->alias) free(ent->alias);
774*7c478bd9Sstevel@tonic-gate 				if (ent->cdevice) free(ent->cdevice);
775*7c478bd9Sstevel@tonic-gate 				if (ent->bdevice) free(ent->bdevice);
776*7c478bd9Sstevel@tonic-gate 			    } else {
777*7c478bd9Sstevel@tonic-gate 				if (*p) {
778*7c478bd9Sstevel@tonic-gate 				    if (ent->pathname = malloc(strlen(p)+1)) {
779*7c478bd9Sstevel@tonic-gate 					q = ent->pathname;
780*7c478bd9Sstevel@tonic-gate 					do {
781*7c478bd9Sstevel@tonic-gate 					    if (*p == '\\') p++;
782*7c478bd9Sstevel@tonic-gate 					    *q++ = *p;
783*7c478bd9Sstevel@tonic-gate 					} while (*p++);
784*7c478bd9Sstevel@tonic-gate 				    }
785*7c478bd9Sstevel@tonic-gate 				} else
786*7c478bd9Sstevel@tonic-gate 				    ent->pathname = NULL;
787*7c478bd9Sstevel@tonic-gate 
788*7c478bd9Sstevel@tonic-gate 				/* Found a valid record */
789*7c478bd9Sstevel@tonic-gate 				done = TRUE;
790*7c478bd9Sstevel@tonic-gate 
791*7c478bd9Sstevel@tonic-gate 				/*
792*7c478bd9Sstevel@tonic-gate 				 * Extract attributes, build a linked list of
793*7c478bd9Sstevel@tonic-gate 				 * 'em (may be none)
794*7c478bd9Sstevel@tonic-gate 				 */
795*7c478bd9Sstevel@tonic-gate 				if (attr = getattrval(NULL)) {
796*7c478bd9Sstevel@tonic-gate 				    ent->attrlist = attr;
797*7c478bd9Sstevel@tonic-gate 				    t = attr;
798*7c478bd9Sstevel@tonic-gate 				    while (attr = getattrval(NULL)) {
799*7c478bd9Sstevel@tonic-gate 					t->next = attr;
800*7c478bd9Sstevel@tonic-gate 					t = attr;
801*7c478bd9Sstevel@tonic-gate 				    }
802*7c478bd9Sstevel@tonic-gate 				    t->next = NULL;
803*7c478bd9Sstevel@tonic-gate 				} else
804*7c478bd9Sstevel@tonic-gate 				    ent->attrlist = NULL;
805*7c478bd9Sstevel@tonic-gate 
806*7c478bd9Sstevel@tonic-gate 			    } /* pathname extracted */
807*7c478bd9Sstevel@tonic-gate 			} /* bdevice extracted */
808*7c478bd9Sstevel@tonic-gate 		    } /* cdevice extracted */
809*7c478bd9Sstevel@tonic-gate 		} /* alias extracted */
810*7c478bd9Sstevel@tonic-gate 	    }
811*7c478bd9Sstevel@tonic-gate 	} /* !done && record read */
812*7c478bd9Sstevel@tonic-gate 
813*7c478bd9Sstevel@tonic-gate 	/*  If no entry was read, free space allocated to the structure  */
814*7c478bd9Sstevel@tonic-gate 	if (!done) {
815*7c478bd9Sstevel@tonic-gate 	    free(ent);
816*7c478bd9Sstevel@tonic-gate 	    ent = NULL;
817*7c478bd9Sstevel@tonic-gate 	}
818*7c478bd9Sstevel@tonic-gate 
819*7c478bd9Sstevel@tonic-gate 	return (ent);
820*7c478bd9Sstevel@tonic-gate }
821*7c478bd9Sstevel@tonic-gate 
822*7c478bd9Sstevel@tonic-gate /*
823*7c478bd9Sstevel@tonic-gate  *  void _freedevtabent(devtabent)
824*7c478bd9Sstevel@tonic-gate  *	struct devtabent       *devtabent;
825*7c478bd9Sstevel@tonic-gate  *
826*7c478bd9Sstevel@tonic-gate  *	This function frees space allocated to a device table entry.
827*7c478bd9Sstevel@tonic-gate  *
828*7c478bd9Sstevel@tonic-gate  *  Arguments:
829*7c478bd9Sstevel@tonic-gate  *	struct devtabent *devtabent	The structure whose space is to be
830*7c478bd9Sstevel@tonic-gate  *					freed.
831*7c478bd9Sstevel@tonic-gate  *
832*7c478bd9Sstevel@tonic-gate  *  Returns:  void
833*7c478bd9Sstevel@tonic-gate  */
834*7c478bd9Sstevel@tonic-gate 
835*7c478bd9Sstevel@tonic-gate void
836*7c478bd9Sstevel@tonic-gate _freedevtabent(struct devtabent *ent)
837*7c478bd9Sstevel@tonic-gate {
838*7c478bd9Sstevel@tonic-gate 	/*
839*7c478bd9Sstevel@tonic-gate 	 * Automatic data
840*7c478bd9Sstevel@tonic-gate 	 */
841*7c478bd9Sstevel@tonic-gate 
842*7c478bd9Sstevel@tonic-gate 	struct attrval *p;		/* Structure being freed */
843*7c478bd9Sstevel@tonic-gate 	struct attrval *q;		/* Next structure to free */
844*7c478bd9Sstevel@tonic-gate 
845*7c478bd9Sstevel@tonic-gate 	if (!ent->comment) {
846*7c478bd9Sstevel@tonic-gate 
847*7c478bd9Sstevel@tonic-gate 		/*
848*7c478bd9Sstevel@tonic-gate 		 *  Free the attribute list.  For each item in the attribute
849*7c478bd9Sstevel@tonic-gate 		 *  list,
850*7c478bd9Sstevel@tonic-gate 		 *    1.  Free the attribute name (always defined),
851*7c478bd9Sstevel@tonic-gate 		 *    2.  Free the value (if any -- it's not defined if we're
852*7c478bd9Sstevel@tonic-gate 		 *		changing an existing attribute),
853*7c478bd9Sstevel@tonic-gate 		 *    3.  Free the space allocated to the structure.
854*7c478bd9Sstevel@tonic-gate 		 */
855*7c478bd9Sstevel@tonic-gate 
856*7c478bd9Sstevel@tonic-gate 	    q = ent->attrlist;
857*7c478bd9Sstevel@tonic-gate 	    if (q)
858*7c478bd9Sstevel@tonic-gate 		do {
859*7c478bd9Sstevel@tonic-gate 		    p = q;
860*7c478bd9Sstevel@tonic-gate 		    q = p->next;
861*7c478bd9Sstevel@tonic-gate 		    free(p->attr);
862*7c478bd9Sstevel@tonic-gate 		    if (p->val) free(p->val);
863*7c478bd9Sstevel@tonic-gate 		    free(p);
864*7c478bd9Sstevel@tonic-gate 		} while (q);
865*7c478bd9Sstevel@tonic-gate 
866*7c478bd9Sstevel@tonic-gate 	    /* Free the standard fields (alias, cdevice, bdevice, pathname) */
867*7c478bd9Sstevel@tonic-gate 	    if (ent->alias) free(ent->alias);
868*7c478bd9Sstevel@tonic-gate 	    if (ent->cdevice) free(ent->cdevice);
869*7c478bd9Sstevel@tonic-gate 	    if (ent->bdevice) free(ent->bdevice);
870*7c478bd9Sstevel@tonic-gate 	    if (ent->pathname) free(ent->pathname);
871*7c478bd9Sstevel@tonic-gate 	}
872*7c478bd9Sstevel@tonic-gate 
873*7c478bd9Sstevel@tonic-gate 	/* Free the attribute string */
874*7c478bd9Sstevel@tonic-gate 	if (ent->attrstr) free(ent->attrstr);
875*7c478bd9Sstevel@tonic-gate 
876*7c478bd9Sstevel@tonic-gate 	/* Free the space allocated to the structure */
877*7c478bd9Sstevel@tonic-gate 	free(ent);
878*7c478bd9Sstevel@tonic-gate }
879*7c478bd9Sstevel@tonic-gate 
880*7c478bd9Sstevel@tonic-gate /*
881*7c478bd9Sstevel@tonic-gate  *  struct devtabent *_getdevrec(device)
882*7c478bd9Sstevel@tonic-gate  *	char *device
883*7c478bd9Sstevel@tonic-gate  *
884*7c478bd9Sstevel@tonic-gate  *	Thie _getdevrec() function returns a pointer to a structure that
885*7c478bd9Sstevel@tonic-gate  *	contains the information in the device-table entry that describes
886*7c478bd9Sstevel@tonic-gate  *	the device <device>.
887*7c478bd9Sstevel@tonic-gate  *
888*7c478bd9Sstevel@tonic-gate  *	The device <device> can be a device alias, a pathname contained in
889*7c478bd9Sstevel@tonic-gate  *	the entry as the "cdevice", "bdevice", or "pathname" attribute,
890*7c478bd9Sstevel@tonic-gate  *	or a pathname to a device described using the "cdevice", "bdevice",
891*7c478bd9Sstevel@tonic-gate  *	or "pathname" attribute (depending on whether the pathname references
892*7c478bd9Sstevel@tonic-gate  *	a character-special file, block-special file, or something else,
893*7c478bd9Sstevel@tonic-gate  *	respectively.
894*7c478bd9Sstevel@tonic-gate  *
895*7c478bd9Sstevel@tonic-gate  *  Arguments:
896*7c478bd9Sstevel@tonic-gate  *	char *device	A character-string describing the device whose record
897*7c478bd9Sstevel@tonic-gate  *			is to be retrieved from the device table.
898*7c478bd9Sstevel@tonic-gate  *
899*7c478bd9Sstevel@tonic-gate  *  Returns:  struct devtabent *
900*7c478bd9Sstevel@tonic-gate  *	A pointer to a structure describing the device.
901*7c478bd9Sstevel@tonic-gate  *
902*7c478bd9Sstevel@tonic-gate  *  Notes:
903*7c478bd9Sstevel@tonic-gate  *    -	Someday, add a cache so that repeated requests for the same record
904*7c478bd9Sstevel@tonic-gate  *	don't require going to the filesystem.  (Maybe -- this might belong
905*7c478bd9Sstevel@tonic-gate  *	in devattr()...)
906*7c478bd9Sstevel@tonic-gate  */
907*7c478bd9Sstevel@tonic-gate 
908*7c478bd9Sstevel@tonic-gate struct devtabent *
909*7c478bd9Sstevel@tonic-gate _getdevrec(char	*device)			/* The device to search for */
910*7c478bd9Sstevel@tonic-gate {
911*7c478bd9Sstevel@tonic-gate 	/*
912*7c478bd9Sstevel@tonic-gate 	 *  Automatic data
913*7c478bd9Sstevel@tonic-gate 	 */
914*7c478bd9Sstevel@tonic-gate 
915*7c478bd9Sstevel@tonic-gate 	struct stat64		devstatbuf;	/* Stat struct, <device> */
916*7c478bd9Sstevel@tonic-gate 	struct stat64		tblstatbuf;	/* Stat struct, tbl entry */
917*7c478bd9Sstevel@tonic-gate 	struct devtabent	*devrec;	/* Pointer to current record */
918*7c478bd9Sstevel@tonic-gate 	int			found;		/* TRUE if record found */
919*7c478bd9Sstevel@tonic-gate 	int			olderrno;	/* Old value of errno */
920*7c478bd9Sstevel@tonic-gate 
921*7c478bd9Sstevel@tonic-gate 
922*7c478bd9Sstevel@tonic-gate 	/*
923*7c478bd9Sstevel@tonic-gate 	 *  Search the device table looking for the requested device
924*7c478bd9Sstevel@tonic-gate 	 */
925*7c478bd9Sstevel@tonic-gate 
926*7c478bd9Sstevel@tonic-gate 	_setdevtab();
927*7c478bd9Sstevel@tonic-gate 	olderrno = errno;
928*7c478bd9Sstevel@tonic-gate 	found = FALSE;
929*7c478bd9Sstevel@tonic-gate 	if ((device != NULL) && !_validalias(device)) {
930*7c478bd9Sstevel@tonic-gate 	    while (!found && (devrec = _getdevtabent())) {
931*7c478bd9Sstevel@tonic-gate 		if (!devrec->comment) {
932*7c478bd9Sstevel@tonic-gate 		    if (devrec->cdevice)
933*7c478bd9Sstevel@tonic-gate 			if (strcmp(device, devrec->cdevice) == 0) found = TRUE;
934*7c478bd9Sstevel@tonic-gate 		    if (devrec->bdevice)
935*7c478bd9Sstevel@tonic-gate 			if (strcmp(device, devrec->bdevice) == 0) found = TRUE;
936*7c478bd9Sstevel@tonic-gate 		    if (devrec->pathname)
937*7c478bd9Sstevel@tonic-gate 			if (strcmp(device, devrec->pathname) == 0) found = TRUE;
938*7c478bd9Sstevel@tonic-gate 		} else _freedevtabent(devrec);
939*7c478bd9Sstevel@tonic-gate 	    }
940*7c478bd9Sstevel@tonic-gate 
941*7c478bd9Sstevel@tonic-gate 		/*
942*7c478bd9Sstevel@tonic-gate 		 *  If the device <device> wasn't named explicitly in the device
943*7c478bd9Sstevel@tonic-gate 		 *  table, compare it against like entries by comparing file-
944*7c478bd9Sstevel@tonic-gate 		 *  system, major device number, and minor device number
945*7c478bd9Sstevel@tonic-gate 		 */
946*7c478bd9Sstevel@tonic-gate 
947*7c478bd9Sstevel@tonic-gate 	    if (!found) {
948*7c478bd9Sstevel@tonic-gate 		_setdevtab();
949*7c478bd9Sstevel@tonic-gate 
950*7c478bd9Sstevel@tonic-gate 		/*  Status the file <device>.  If fails, invalid device */
951*7c478bd9Sstevel@tonic-gate 		if (stat64(device, &devstatbuf) != 0) errno = ENODEV;
952*7c478bd9Sstevel@tonic-gate 		else {
953*7c478bd9Sstevel@tonic-gate 
954*7c478bd9Sstevel@tonic-gate 			/*
955*7c478bd9Sstevel@tonic-gate 			 *  If <device> is a block-special device.  See if it is
956*7c478bd9Sstevel@tonic-gate 			 *  in the table by matching its file-system indicator
957*7c478bd9Sstevel@tonic-gate 			 * and major/minor device numbers against the
958*7c478bd9Sstevel@tonic-gate 			 * file-system and major/minor device numbers of the
959*7c478bd9Sstevel@tonic-gate 			 * "bdevice" entries.
960*7c478bd9Sstevel@tonic-gate 			 */
961*7c478bd9Sstevel@tonic-gate 
962*7c478bd9Sstevel@tonic-gate 		    if ((devstatbuf.st_mode & 0170000) == 0020000) {
963*7c478bd9Sstevel@tonic-gate 			while (!found && (devrec = _getdevtabent())) {
964*7c478bd9Sstevel@tonic-gate 			    if (!devrec->comment &&
965*7c478bd9Sstevel@tonic-gate 				(devrec->cdevice != NULL))
966*7c478bd9Sstevel@tonic-gate 				if (stat64(devrec->cdevice, &tblstatbuf) == 0) {
967*7c478bd9Sstevel@tonic-gate 				    if (samedev(tblstatbuf, devstatbuf))
968*7c478bd9Sstevel@tonic-gate 					found = TRUE;
969*7c478bd9Sstevel@tonic-gate 				} else {
970*7c478bd9Sstevel@tonic-gate 					/* Ignore stat() errs */
971*7c478bd9Sstevel@tonic-gate 					errno = olderrno;
972*7c478bd9Sstevel@tonic-gate 				}
973*7c478bd9Sstevel@tonic-gate 			    if (!found) _freedevtabent(devrec);
974*7c478bd9Sstevel@tonic-gate 			}
975*7c478bd9Sstevel@tonic-gate 		    }
976*7c478bd9Sstevel@tonic-gate 
977*7c478bd9Sstevel@tonic-gate 			/*
978*7c478bd9Sstevel@tonic-gate 			 * If <device> is a block-special device.  See if it is
979*7c478bd9Sstevel@tonic-gate 			 * in the table by matching its file-system indicator
980*7c478bd9Sstevel@tonic-gate 			 * and major/minor device numbers against the
981*7c478bd9Sstevel@tonic-gate 			 * file-system and major/minor device numbers of the
982*7c478bd9Sstevel@tonic-gate 			 * "bdevice" entries.
983*7c478bd9Sstevel@tonic-gate 			 */
984*7c478bd9Sstevel@tonic-gate 
985*7c478bd9Sstevel@tonic-gate 		    else if ((devstatbuf.st_mode & 0170000) == 0060000) {
986*7c478bd9Sstevel@tonic-gate 			while (!found && (devrec = _getdevtabent())) {
987*7c478bd9Sstevel@tonic-gate 			    if (!devrec->comment &&
988*7c478bd9Sstevel@tonic-gate 				(devrec->bdevice != NULL))
989*7c478bd9Sstevel@tonic-gate 				if (stat64(devrec->bdevice, &tblstatbuf) == 0) {
990*7c478bd9Sstevel@tonic-gate 				    if (samedev(tblstatbuf, devstatbuf))
991*7c478bd9Sstevel@tonic-gate 					found = TRUE;
992*7c478bd9Sstevel@tonic-gate 				} else {
993*7c478bd9Sstevel@tonic-gate 					/* Ignore stat() errs */
994*7c478bd9Sstevel@tonic-gate 					errno = olderrno;
995*7c478bd9Sstevel@tonic-gate 				}
996*7c478bd9Sstevel@tonic-gate 			    if (!found) _freedevtabent(devrec);
997*7c478bd9Sstevel@tonic-gate 			}
998*7c478bd9Sstevel@tonic-gate 		    }
999*7c478bd9Sstevel@tonic-gate 
1000*7c478bd9Sstevel@tonic-gate 			/*
1001*7c478bd9Sstevel@tonic-gate 			 * If <device> is neither a block-special or character-
1002*7c478bd9Sstevel@tonic-gate 			 * special device.  See if it is in the table by
1003*7c478bd9Sstevel@tonic-gate 			 * matching its file-system indicator and major/minor
1004*7c478bd9Sstevel@tonic-gate 			 * device numbers against the file-system and
1005*7c478bd9Sstevel@tonic-gate 			 * major/minor device numbers of the "pathname" entries.
1006*7c478bd9Sstevel@tonic-gate 			 */
1007*7c478bd9Sstevel@tonic-gate 
1008*7c478bd9Sstevel@tonic-gate 		    else {
1009*7c478bd9Sstevel@tonic-gate 			while (!found && (devrec = _getdevtabent())) {
1010*7c478bd9Sstevel@tonic-gate 			    if (!devrec->comment &&
1011*7c478bd9Sstevel@tonic-gate 				(devrec->pathname != NULL))
1012*7c478bd9Sstevel@tonic-gate 				if (stat64(devrec->pathname,
1013*7c478bd9Sstevel@tonic-gate 				    &tblstatbuf) == 0) {
1014*7c478bd9Sstevel@tonic-gate 				    if (samedev(tblstatbuf, devstatbuf))
1015*7c478bd9Sstevel@tonic-gate 					found = TRUE;
1016*7c478bd9Sstevel@tonic-gate 				} else {
1017*7c478bd9Sstevel@tonic-gate 					/* Ignore stat() errs */
1018*7c478bd9Sstevel@tonic-gate 					errno = olderrno;
1019*7c478bd9Sstevel@tonic-gate 				}
1020*7c478bd9Sstevel@tonic-gate 			    if (!found) _freedevtabent(devrec);
1021*7c478bd9Sstevel@tonic-gate 			}
1022*7c478bd9Sstevel@tonic-gate 		    }
1023*7c478bd9Sstevel@tonic-gate 
1024*7c478bd9Sstevel@tonic-gate 		    if (!found) {
1025*7c478bd9Sstevel@tonic-gate 			devrec = NULL;
1026*7c478bd9Sstevel@tonic-gate 			errno = ENODEV;
1027*7c478bd9Sstevel@tonic-gate 		    }
1028*7c478bd9Sstevel@tonic-gate 
1029*7c478bd9Sstevel@tonic-gate 		} /* End case where stat() on the <device> succeeded */
1030*7c478bd9Sstevel@tonic-gate 
1031*7c478bd9Sstevel@tonic-gate 	    } /* End case handling pathname not explicitly in device table */
1032*7c478bd9Sstevel@tonic-gate 
1033*7c478bd9Sstevel@tonic-gate 	} /* End case handling <device> as a fully-qualified pathname */
1034*7c478bd9Sstevel@tonic-gate 
1035*7c478bd9Sstevel@tonic-gate 
1036*7c478bd9Sstevel@tonic-gate 	/*
1037*7c478bd9Sstevel@tonic-gate 	 *  Otherwise the device <device> is an alias.
1038*7c478bd9Sstevel@tonic-gate 	 *  Search the table for a record that has as the "alias" attribute
1039*7c478bd9Sstevel@tonic-gate 	 *  the value <device>.
1040*7c478bd9Sstevel@tonic-gate 	 */
1041*7c478bd9Sstevel@tonic-gate 
1042*7c478bd9Sstevel@tonic-gate 	else {
1043*7c478bd9Sstevel@tonic-gate 	    while (!found && (devrec = _getdevtabent())) {
1044*7c478bd9Sstevel@tonic-gate 		if (!devrec->comment && (device != NULL) &&
1045*7c478bd9Sstevel@tonic-gate 		    strcmp(device, devrec->alias) == 0)
1046*7c478bd9Sstevel@tonic-gate 		    found = TRUE;
1047*7c478bd9Sstevel@tonic-gate 		else _freedevtabent(devrec);
1048*7c478bd9Sstevel@tonic-gate 	    }
1049*7c478bd9Sstevel@tonic-gate 	    if (!found) {
1050*7c478bd9Sstevel@tonic-gate 		devrec = NULL;
1051*7c478bd9Sstevel@tonic-gate 		errno = ENODEV;
1052*7c478bd9Sstevel@tonic-gate 	    }
1053*7c478bd9Sstevel@tonic-gate 	}
1054*7c478bd9Sstevel@tonic-gate 
1055*7c478bd9Sstevel@tonic-gate 	/* Fini */
1056*7c478bd9Sstevel@tonic-gate 	return (devrec);
1057*7c478bd9Sstevel@tonic-gate }
1058