xref: /illumos-gate/usr/src/lib/libadm/common/dgrpent.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,1998,2002 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  * dgrpent.c
35*7c478bd9Sstevel@tonic-gate  *
36*7c478bd9Sstevel@tonic-gate  *  Contains functions that deal with the device-group 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  *	_opendgrptab()		Opens the device-group table for commands
41*7c478bd9Sstevel@tonic-gate  *	_setdgrptab()		Rewinds the open device table
42*7c478bd9Sstevel@tonic-gate  *	_enddgrptab()		Closes the open device table
43*7c478bd9Sstevel@tonic-gate  *	_getdgrptabent()	Gets the next entry in the device table
44*7c478bd9Sstevel@tonic-gate  *	_freedgrptabent()	Frees memory allocated to a device-table entry
45*7c478bd9Sstevel@tonic-gate  *	_getdgrprec()		Gets a specific record from the device table
46*7c478bd9Sstevel@tonic-gate  *	_dgrptabpath()		Gets the pathname of the device group file
47*7c478bd9Sstevel@tonic-gate  */
48*7c478bd9Sstevel@tonic-gate 
49*7c478bd9Sstevel@tonic-gate /*
50*7c478bd9Sstevel@tonic-gate  *  Header files
51*7c478bd9Sstevel@tonic-gate  *	<sys/types.h>	System data types
52*7c478bd9Sstevel@tonic-gate  *	<unistd.h>	Standard UNIX(r) definitions
53*7c478bd9Sstevel@tonic-gate  *	<stdio.h>	Standard I/O Definitions
54*7c478bd9Sstevel@tonic-gate  *	<string.h>	String handling definitions
55*7c478bd9Sstevel@tonic-gate  *	<ctype.h>	Character types and macros
56*7c478bd9Sstevel@tonic-gate  *	<errno.h>	Errorcode definitions
57*7c478bd9Sstevel@tonic-gate  *	<sys/stat.h>	File status information
58*7c478bd9Sstevel@tonic-gate  *	<devmgmt.h>	Global Device Management definitions
59*7c478bd9Sstevel@tonic-gate  *	"devtab.h"	Local device table definitions
60*7c478bd9Sstevel@tonic-gate  */
61*7c478bd9Sstevel@tonic-gate 
62*7c478bd9Sstevel@tonic-gate #include	<sys/types.h>
63*7c478bd9Sstevel@tonic-gate #include	<unistd.h>
64*7c478bd9Sstevel@tonic-gate #include	<stdio.h>
65*7c478bd9Sstevel@tonic-gate #include	<string.h>
66*7c478bd9Sstevel@tonic-gate #include	<ctype.h>
67*7c478bd9Sstevel@tonic-gate #include	<errno.h>
68*7c478bd9Sstevel@tonic-gate #include	<sys/stat.h>
69*7c478bd9Sstevel@tonic-gate #include	<devmgmt.h>
70*7c478bd9Sstevel@tonic-gate #include	"devtab.h"
71*7c478bd9Sstevel@tonic-gate #include	<stdlib.h>
72*7c478bd9Sstevel@tonic-gate 
73*7c478bd9Sstevel@tonic-gate /*
74*7c478bd9Sstevel@tonic-gate  *  Local definitions
75*7c478bd9Sstevel@tonic-gate  */
76*7c478bd9Sstevel@tonic-gate 
77*7c478bd9Sstevel@tonic-gate 
78*7c478bd9Sstevel@tonic-gate /*
79*7c478bd9Sstevel@tonic-gate  *  Static data definitions:
80*7c478bd9Sstevel@tonic-gate  *	leftoff		Addr of char to begin next parse using
81*7c478bd9Sstevel@tonic-gate  *			getfld(), getattrval(), getquoted()
82*7c478bd9Sstevel@tonic-gate  *	recbufsz	The size of the buffer used for reading records
83*7c478bd9Sstevel@tonic-gate  *	recbuf		Addr of malloc() buffer for reading records
84*7c478bd9Sstevel@tonic-gate  *	recnum		Record number of next record to read
85*7c478bd9Sstevel@tonic-gate  *	xtndcnt		Number of times the buffer has been extended
86*7c478bd9Sstevel@tonic-gate  */
87*7c478bd9Sstevel@tonic-gate 
88*7c478bd9Sstevel@tonic-gate static	char		*leftoff = NULL;
89*7c478bd9Sstevel@tonic-gate static	int		recbufsz = 0;
90*7c478bd9Sstevel@tonic-gate static	char		*recbuf = NULL;
91*7c478bd9Sstevel@tonic-gate static	int		recnum = 0;
92*7c478bd9Sstevel@tonic-gate static	int		xtndcnt = 0;
93*7c478bd9Sstevel@tonic-gate 
94*7c478bd9Sstevel@tonic-gate /*
95*7c478bd9Sstevel@tonic-gate  *  void _setdgrptab()
96*7c478bd9Sstevel@tonic-gate  *
97*7c478bd9Sstevel@tonic-gate  *	This function rewinds the open device table so that the next
98*7c478bd9Sstevel@tonic-gate  *	_getdgrptabent() returns the first record in the device table.
99*7c478bd9Sstevel@tonic-gate  *
100*7c478bd9Sstevel@tonic-gate  *  Arguments:  None
101*7c478bd9Sstevel@tonic-gate  *
102*7c478bd9Sstevel@tonic-gate  *  Returns:  Void
103*7c478bd9Sstevel@tonic-gate  */
104*7c478bd9Sstevel@tonic-gate 
105*7c478bd9Sstevel@tonic-gate void
_setdgrptab(void)106*7c478bd9Sstevel@tonic-gate _setdgrptab(void)
107*7c478bd9Sstevel@tonic-gate {
108*7c478bd9Sstevel@tonic-gate 	/*  If the device table file is open, rewind the file  */
109*7c478bd9Sstevel@tonic-gate 	if (oam_dgroup) {
110*7c478bd9Sstevel@tonic-gate 	    rewind(oam_dgroup);
111*7c478bd9Sstevel@tonic-gate 	    recnum = 0;
112*7c478bd9Sstevel@tonic-gate 	}
113*7c478bd9Sstevel@tonic-gate }
114*7c478bd9Sstevel@tonic-gate 
115*7c478bd9Sstevel@tonic-gate /*
116*7c478bd9Sstevel@tonic-gate  *  void _enddgrptab()
117*7c478bd9Sstevel@tonic-gate  *
118*7c478bd9Sstevel@tonic-gate  *	This function closes the open device table.  It resets the
119*7c478bd9Sstevel@tonic-gate  *	open device table external variable to NULL.
120*7c478bd9Sstevel@tonic-gate  *
121*7c478bd9Sstevel@tonic-gate  *  Arguments:  None
122*7c478bd9Sstevel@tonic-gate  *
123*7c478bd9Sstevel@tonic-gate  *  Returns:  Void
124*7c478bd9Sstevel@tonic-gate  */
125*7c478bd9Sstevel@tonic-gate 
126*7c478bd9Sstevel@tonic-gate void
_enddgrptab(void)127*7c478bd9Sstevel@tonic-gate _enddgrptab(void)
128*7c478bd9Sstevel@tonic-gate {
129*7c478bd9Sstevel@tonic-gate 	/*  If the device table file is open, close it  */
130*7c478bd9Sstevel@tonic-gate 	if (oam_dgroup) {
131*7c478bd9Sstevel@tonic-gate 	    (void) fclose(oam_dgroup);
132*7c478bd9Sstevel@tonic-gate 	    recnum = 0;
133*7c478bd9Sstevel@tonic-gate 	    oam_dgroup = NULL;
134*7c478bd9Sstevel@tonic-gate 	}
135*7c478bd9Sstevel@tonic-gate }
136*7c478bd9Sstevel@tonic-gate 
137*7c478bd9Sstevel@tonic-gate /*
138*7c478bd9Sstevel@tonic-gate  *  char *getfld(ptr, delims)
139*7c478bd9Sstevel@tonic-gate  *	char   *ptr
140*7c478bd9Sstevel@tonic-gate  *	char   *delims
141*7c478bd9Sstevel@tonic-gate  *
142*7c478bd9Sstevel@tonic-gate  *  Notes:
143*7c478bd9Sstevel@tonic-gate  *    -	Can't use "strtok()" because of its use of static data.  The caller
144*7c478bd9Sstevel@tonic-gate  *	may be using strtok() and we'll really mess them up.
145*7c478bd9Sstevel@tonic-gate  *    - The function returns NULL if it didn't find any token -- '\0' can't
146*7c478bd9Sstevel@tonic-gate  *	be a delimiter using this algorithm.
147*7c478bd9Sstevel@tonic-gate  */
148*7c478bd9Sstevel@tonic-gate 
149*7c478bd9Sstevel@tonic-gate static char *
getfld(char * ptr,char * delims)150*7c478bd9Sstevel@tonic-gate getfld(
151*7c478bd9Sstevel@tonic-gate 	char   *ptr,		/* String to parse */
152*7c478bd9Sstevel@tonic-gate 	char   *delims)		/* List of delimiters */
153*7c478bd9Sstevel@tonic-gate {
154*7c478bd9Sstevel@tonic-gate 	char   *p, *q;
155*7c478bd9Sstevel@tonic-gate 
156*7c478bd9Sstevel@tonic-gate 	/*
157*7c478bd9Sstevel@tonic-gate 	 *  Figure out where to start.
158*7c478bd9Sstevel@tonic-gate 	 *  If given a pointer, use that.
159*7c478bd9Sstevel@tonic-gate 	 *  Otherwise, use where we left off.
160*7c478bd9Sstevel@tonic-gate 	 */
161*7c478bd9Sstevel@tonic-gate 
162*7c478bd9Sstevel@tonic-gate 	p = ptr ? ptr : leftoff;
163*7c478bd9Sstevel@tonic-gate 
164*7c478bd9Sstevel@tonic-gate 
165*7c478bd9Sstevel@tonic-gate 	/*
166*7c478bd9Sstevel@tonic-gate 	 *  If there's anything to parse, search the string for the first
167*7c478bd9Sstevel@tonic-gate 	 *  occurrence of any of the delimiters.  If one is found, change it
168*7c478bd9Sstevel@tonic-gate 	 *  to '\0' and remember the place to start for next time.  If not
169*7c478bd9Sstevel@tonic-gate 	 *  found, forget the restart address and prepare to return NULL
170*7c478bd9Sstevel@tonic-gate 	 */
171*7c478bd9Sstevel@tonic-gate 
172*7c478bd9Sstevel@tonic-gate 	if (p) {
173*7c478bd9Sstevel@tonic-gate 	    while (*p && isspace((unsigned char)*p)) p++;
174*7c478bd9Sstevel@tonic-gate 	    if (*p) {
175*7c478bd9Sstevel@tonic-gate 		q = p;
176*7c478bd9Sstevel@tonic-gate 		while (*q && !strchr(delims, *q)) q++;
177*7c478bd9Sstevel@tonic-gate 		if (*q) {
178*7c478bd9Sstevel@tonic-gate 		    *q++ = '\0';
179*7c478bd9Sstevel@tonic-gate 		    leftoff = q;
180*7c478bd9Sstevel@tonic-gate 		} else leftoff = NULL;
181*7c478bd9Sstevel@tonic-gate 	    } else leftoff = p = NULL;
182*7c478bd9Sstevel@tonic-gate 	}
183*7c478bd9Sstevel@tonic-gate 
184*7c478bd9Sstevel@tonic-gate 	/*  Finished  */
185*7c478bd9Sstevel@tonic-gate 	return (p);
186*7c478bd9Sstevel@tonic-gate }
187*7c478bd9Sstevel@tonic-gate 
188*7c478bd9Sstevel@tonic-gate /*
189*7c478bd9Sstevel@tonic-gate  *  char *getnextrec()
190*7c478bd9Sstevel@tonic-gate  *
191*7c478bd9Sstevel@tonic-gate  *	This function gets the next record from the input stream "oam_dgroup"
192*7c478bd9Sstevel@tonic-gate  *	and puts it in the device-group table record buffer (whose address is
193*7c478bd9Sstevel@tonic-gate  *	in "recbuf").  If the buffer is not allocated or is too small to
194*7c478bd9Sstevel@tonic-gate  *	accommodate the record, the function allocates more space to the
195*7c478bd9Sstevel@tonic-gate  *	buffer.
196*7c478bd9Sstevel@tonic-gate  *
197*7c478bd9Sstevel@tonic-gate  *  Arguments:  None
198*7c478bd9Sstevel@tonic-gate  *
199*7c478bd9Sstevel@tonic-gate  *  Returns:  char *
200*7c478bd9Sstevel@tonic-gate  *	The address of the buffer containing the record.
201*7c478bd9Sstevel@tonic-gate  *
202*7c478bd9Sstevel@tonic-gate  *  Static Data Referenced:
203*7c478bd9Sstevel@tonic-gate  *	recbuf		Address of the buffer containing records read from the
204*7c478bd9Sstevel@tonic-gate  *			device table file
205*7c478bd9Sstevel@tonic-gate  *	recbufsz	Current size of the record buffer
206*7c478bd9Sstevel@tonic-gate  *	xtndcnt		Number of times the record buffer has been extended
207*7c478bd9Sstevel@tonic-gate  *	oam_dgroup	Device-group table stream, expected to be open for (at
208*7c478bd9Sstevel@tonic-gate  *			least) reading
209*7c478bd9Sstevel@tonic-gate  *
210*7c478bd9Sstevel@tonic-gate  *  Notes:
211*7c478bd9Sstevel@tonic-gate  *    - The string returned in the buffer <buf> ALWAYS end in a '\n' (newline)
212*7c478bd9Sstevel@tonic-gate  *	character followed by a '\0' (null).
213*7c478bd9Sstevel@tonic-gate  */
214*7c478bd9Sstevel@tonic-gate 
215*7c478bd9Sstevel@tonic-gate static char *
getnextrec(void)216*7c478bd9Sstevel@tonic-gate getnextrec(void)
217*7c478bd9Sstevel@tonic-gate {
218*7c478bd9Sstevel@tonic-gate 	/* Automatic data */
219*7c478bd9Sstevel@tonic-gate 	char		*recp;		/* Value to return */
220*7c478bd9Sstevel@tonic-gate 	char		*p;		/* Temp pointer */
221*7c478bd9Sstevel@tonic-gate 	int		done;		/* TRUE if we're finished */
222*7c478bd9Sstevel@tonic-gate 	int		reclen;		/* Number of chars in record */
223*7c478bd9Sstevel@tonic-gate 
224*7c478bd9Sstevel@tonic-gate 
225*7c478bd9Sstevel@tonic-gate 	/* If there's no buffer for records, try to get one */
226*7c478bd9Sstevel@tonic-gate 	if (!recbuf) {
227*7c478bd9Sstevel@tonic-gate 	    if (recbuf = malloc(DGRP_BUFSIZ)) {
228*7c478bd9Sstevel@tonic-gate 		recbufsz = DGRP_BUFSIZ;
229*7c478bd9Sstevel@tonic-gate 		xtndcnt = 0;
230*7c478bd9Sstevel@tonic-gate 	    } else return (NULL);
231*7c478bd9Sstevel@tonic-gate 	}
232*7c478bd9Sstevel@tonic-gate 
233*7c478bd9Sstevel@tonic-gate 
234*7c478bd9Sstevel@tonic-gate 	/* Get the next record */
235*7c478bd9Sstevel@tonic-gate 	recp = fgets(recbuf, recbufsz, oam_dgroup);
236*7c478bd9Sstevel@tonic-gate 	done = FALSE;
237*7c478bd9Sstevel@tonic-gate 
238*7c478bd9Sstevel@tonic-gate 	/* While we've something to return and we're not finished ... */
239*7c478bd9Sstevel@tonic-gate 	while (recp && !done) {
240*7c478bd9Sstevel@tonic-gate 
241*7c478bd9Sstevel@tonic-gate 	    /* If our return string isn't a null-string ... */
242*7c478bd9Sstevel@tonic-gate 	    if ((reclen = (int)strlen(recp)) != 0) {
243*7c478bd9Sstevel@tonic-gate 
244*7c478bd9Sstevel@tonic-gate 		/* If we have a complete record, we're finished */
245*7c478bd9Sstevel@tonic-gate 		if (*(recp+reclen-1) == '\n') done = TRUE;
246*7c478bd9Sstevel@tonic-gate 		else while (!done) {
247*7c478bd9Sstevel@tonic-gate 
248*7c478bd9Sstevel@tonic-gate 		/*
249*7c478bd9Sstevel@tonic-gate 		 * Need to complete the record.  A complete record is one
250*7c478bd9Sstevel@tonic-gate 		 * which is terminated by a new-line character
251*7c478bd9Sstevel@tonic-gate 		 */
252*7c478bd9Sstevel@tonic-gate 
253*7c478bd9Sstevel@tonic-gate 		    /* If the buffer is full, expand it and continue reading */
254*7c478bd9Sstevel@tonic-gate 		    if (reclen == recbufsz-1) {
255*7c478bd9Sstevel@tonic-gate 
256*7c478bd9Sstevel@tonic-gate 			/* Have we reached our maximum extension count? */
257*7c478bd9Sstevel@tonic-gate 			if (xtndcnt < XTND_MAXCNT) {
258*7c478bd9Sstevel@tonic-gate 
259*7c478bd9Sstevel@tonic-gate 			    /* Expand the record buffer */
260*7c478bd9Sstevel@tonic-gate 			    if (p = realloc(recbuf,
261*7c478bd9Sstevel@tonic-gate 				(size_t)(recbufsz+DGRP_BUFINC))) {
262*7c478bd9Sstevel@tonic-gate 
263*7c478bd9Sstevel@tonic-gate 				/* Update buffer information */
264*7c478bd9Sstevel@tonic-gate 				xtndcnt++;
265*7c478bd9Sstevel@tonic-gate 				recbuf = p;
266*7c478bd9Sstevel@tonic-gate 				recbufsz += DGRP_BUFINC;
267*7c478bd9Sstevel@tonic-gate 
268*7c478bd9Sstevel@tonic-gate 			    } else {
269*7c478bd9Sstevel@tonic-gate 
270*7c478bd9Sstevel@tonic-gate 				/* Expansion failed */
271*7c478bd9Sstevel@tonic-gate 				recp = NULL;
272*7c478bd9Sstevel@tonic-gate 				done = TRUE;
273*7c478bd9Sstevel@tonic-gate 			    }
274*7c478bd9Sstevel@tonic-gate 
275*7c478bd9Sstevel@tonic-gate 			} else {
276*7c478bd9Sstevel@tonic-gate 
277*7c478bd9Sstevel@tonic-gate 			    /* Maximum extend count exceeded.  Insane table */
278*7c478bd9Sstevel@tonic-gate 			    recp = NULL;
279*7c478bd9Sstevel@tonic-gate 			    done = TRUE;
280*7c478bd9Sstevel@tonic-gate 			}
281*7c478bd9Sstevel@tonic-gate 
282*7c478bd9Sstevel@tonic-gate 		    }
283*7c478bd9Sstevel@tonic-gate 
284*7c478bd9Sstevel@tonic-gate 		    /* Complete the record */
285*7c478bd9Sstevel@tonic-gate 		    if (!done) {
286*7c478bd9Sstevel@tonic-gate 
287*7c478bd9Sstevel@tonic-gate 			/* Read stuff into the expanded space */
288*7c478bd9Sstevel@tonic-gate 			if (fgets(recbuf+reclen, recbufsz-reclen, oam_dgroup)) {
289*7c478bd9Sstevel@tonic-gate 			    reclen = (int)strlen(recbuf);
290*7c478bd9Sstevel@tonic-gate 			    recp = recbuf;
291*7c478bd9Sstevel@tonic-gate 			    if (*(recp+reclen-1) == '\n') done = TRUE;
292*7c478bd9Sstevel@tonic-gate 			} else {
293*7c478bd9Sstevel@tonic-gate 			    /* Read failed, corrupt record? */
294*7c478bd9Sstevel@tonic-gate 			    recp = NULL;
295*7c478bd9Sstevel@tonic-gate 			    done = TRUE;
296*7c478bd9Sstevel@tonic-gate 			}
297*7c478bd9Sstevel@tonic-gate 		    }
298*7c478bd9Sstevel@tonic-gate 
299*7c478bd9Sstevel@tonic-gate 		}   /* End incomplete record handling */
300*7c478bd9Sstevel@tonic-gate 
301*7c478bd9Sstevel@tonic-gate 	    } else {
302*7c478bd9Sstevel@tonic-gate 
303*7c478bd9Sstevel@tonic-gate 		/* Read a null string?  (corrupt table) */
304*7c478bd9Sstevel@tonic-gate 		recp = NULL;
305*7c478bd9Sstevel@tonic-gate 		done = TRUE;
306*7c478bd9Sstevel@tonic-gate 	    }
307*7c478bd9Sstevel@tonic-gate 
308*7c478bd9Sstevel@tonic-gate 	}   /* while (recp && !done) */
309*7c478bd9Sstevel@tonic-gate 
310*7c478bd9Sstevel@tonic-gate 	/* Return what we've got (if anything) */
311*7c478bd9Sstevel@tonic-gate 	return (recp);
312*7c478bd9Sstevel@tonic-gate }
313*7c478bd9Sstevel@tonic-gate 
314*7c478bd9Sstevel@tonic-gate /*
315*7c478bd9Sstevel@tonic-gate  *  char *_dgrptabpath()
316*7c478bd9Sstevel@tonic-gate  *
317*7c478bd9Sstevel@tonic-gate  *	Get the pathname of the device-group table file
318*7c478bd9Sstevel@tonic-gate  *
319*7c478bd9Sstevel@tonic-gate  *  Arguments:  None
320*7c478bd9Sstevel@tonic-gate  *
321*7c478bd9Sstevel@tonic-gate  *  Returns:  char *
322*7c478bd9Sstevel@tonic-gate  *	Returns the pathname to the device group table of (char *) NULL if
323*7c478bd9Sstevel@tonic-gate  *	there was a problem getting the memory needed to contain the
324*7c478bd9Sstevel@tonic-gate  *	pathname.
325*7c478bd9Sstevel@tonic-gate  *
326*7c478bd9Sstevel@tonic-gate  *  Algorithm:
327*7c478bd9Sstevel@tonic-gate  *	1.  If OAM_DGRP is defined in the environment and is not
328*7c478bd9Sstevel@tonic-gate  *	    defined as "", it returns the value of that environment
329*7c478bd9Sstevel@tonic-gate  *	    variable.
330*7c478bd9Sstevel@tonic-gate  *	2.  Otherwise, use the devault pathname (as defined by the
331*7c478bd9Sstevel@tonic-gate  *	    environment variable DGRP_PATH in <devmgmt.h>.
332*7c478bd9Sstevel@tonic-gate  */
333*7c478bd9Sstevel@tonic-gate 
334*7c478bd9Sstevel@tonic-gate 
335*7c478bd9Sstevel@tonic-gate char *
_dgrptabpath(void)336*7c478bd9Sstevel@tonic-gate _dgrptabpath(void)
337*7c478bd9Sstevel@tonic-gate {
338*7c478bd9Sstevel@tonic-gate 
339*7c478bd9Sstevel@tonic-gate 	/* Automatic data */
340*7c478bd9Sstevel@tonic-gate #ifdef	DEBUG
341*7c478bd9Sstevel@tonic-gate 	char		*path;		/* Ptr to path in environment */
342*7c478bd9Sstevel@tonic-gate #endif
343*7c478bd9Sstevel@tonic-gate 	char		*rtnval;		/* Ptr to value to return */
344*7c478bd9Sstevel@tonic-gate 
345*7c478bd9Sstevel@tonic-gate 
346*7c478bd9Sstevel@tonic-gate 	/*
347*7c478bd9Sstevel@tonic-gate 	 * If compiled with -DDEBUG=1,
348*7c478bd9Sstevel@tonic-gate 	 * look for the pathname in the environment
349*7c478bd9Sstevel@tonic-gate 	 */
350*7c478bd9Sstevel@tonic-gate 
351*7c478bd9Sstevel@tonic-gate #ifdef	DEBUG
352*7c478bd9Sstevel@tonic-gate 	if (((path = getenv(OAM_DGROUP)) != NULL) && (*path)) {
353*7c478bd9Sstevel@tonic-gate 	    if (rtnval = malloc(strlen(path)+1))
354*7c478bd9Sstevel@tonic-gate 		(void) strcpy(rtnval, path);
355*7c478bd9Sstevel@tonic-gate 	} else {
356*7c478bd9Sstevel@tonic-gate #endif
357*7c478bd9Sstevel@tonic-gate 	/*
358*7c478bd9Sstevel@tonic-gate 	 * Use the default name.
359*7c478bd9Sstevel@tonic-gate 	 */
360*7c478bd9Sstevel@tonic-gate 
361*7c478bd9Sstevel@tonic-gate 	    if (rtnval = malloc(strlen(DGRP_PATH)+1))
362*7c478bd9Sstevel@tonic-gate 		(void) strcpy(rtnval, DGRP_PATH);
363*7c478bd9Sstevel@tonic-gate 
364*7c478bd9Sstevel@tonic-gate #ifdef	DEBUG
365*7c478bd9Sstevel@tonic-gate 	}
366*7c478bd9Sstevel@tonic-gate #endif
367*7c478bd9Sstevel@tonic-gate 
368*7c478bd9Sstevel@tonic-gate 	/* Finished */
369*7c478bd9Sstevel@tonic-gate 	return (rtnval);
370*7c478bd9Sstevel@tonic-gate }
371*7c478bd9Sstevel@tonic-gate 
372*7c478bd9Sstevel@tonic-gate /*
373*7c478bd9Sstevel@tonic-gate  *  int _opendgrptab(mode)
374*7c478bd9Sstevel@tonic-gate  *	char   *mode
375*7c478bd9Sstevel@tonic-gate  *
376*7c478bd9Sstevel@tonic-gate  *	The _opendgrptab() function opens a device-group table for a command.
377*7c478bd9Sstevel@tonic-gate  *
378*7c478bd9Sstevel@tonic-gate  *  Arguments:
379*7c478bd9Sstevel@tonic-gate  *	mode	The open mode to use to open the file.  (i.e. "r" for
380*7c478bd9Sstevel@tonic-gate  *		reading, "w" for writing.  See FOPEN(BA_OS) in SVID.)
381*7c478bd9Sstevel@tonic-gate  *
382*7c478bd9Sstevel@tonic-gate  *  Returns:  int
383*7c478bd9Sstevel@tonic-gate  *	TRUE if successful, FALSE otherwise
384*7c478bd9Sstevel@tonic-gate  */
385*7c478bd9Sstevel@tonic-gate 
386*7c478bd9Sstevel@tonic-gate int
_opendgrptab(char * mode)387*7c478bd9Sstevel@tonic-gate _opendgrptab(char *mode)
388*7c478bd9Sstevel@tonic-gate {
389*7c478bd9Sstevel@tonic-gate 	/* Automatic data */
390*7c478bd9Sstevel@tonic-gate 	char   *dgrptabname;	/* Ptr to the device-group table name */
391*7c478bd9Sstevel@tonic-gate 	int	rtnval;		/* Value to return */
392*7c478bd9Sstevel@tonic-gate 
393*7c478bd9Sstevel@tonic-gate 	rtnval = TRUE;
394*7c478bd9Sstevel@tonic-gate 	if (dgrptabname = _dgrptabpath()) {
395*7c478bd9Sstevel@tonic-gate 	    if (oam_dgroup) (void) fclose(oam_dgroup);
396*7c478bd9Sstevel@tonic-gate 	    if (oam_dgroup = fopen(dgrptabname, mode)) {
397*7c478bd9Sstevel@tonic-gate 		xtndcnt = 0;
398*7c478bd9Sstevel@tonic-gate 		recnum = 0;
399*7c478bd9Sstevel@tonic-gate 	    } else rtnval = FALSE;  /* :-( */
400*7c478bd9Sstevel@tonic-gate 	} else rtnval = FALSE;    /* :-( */
401*7c478bd9Sstevel@tonic-gate 	return (rtnval);
402*7c478bd9Sstevel@tonic-gate }
403*7c478bd9Sstevel@tonic-gate 
404*7c478bd9Sstevel@tonic-gate /*
405*7c478bd9Sstevel@tonic-gate  *  struct dgrptabent *_getdgrptabent()
406*7c478bd9Sstevel@tonic-gate  *
407*7c478bd9Sstevel@tonic-gate  *  	This function returns the next entry in the device-group table.
408*7c478bd9Sstevel@tonic-gate  *	If no device-group table is open, it opens the standard device-group
409*7c478bd9Sstevel@tonic-gate  *      table and returns the first record in the table.
410*7c478bd9Sstevel@tonic-gate  *
411*7c478bd9Sstevel@tonic-gate  *  Arguments:  None.
412*7c478bd9Sstevel@tonic-gate  *
413*7c478bd9Sstevel@tonic-gate  *  Returns:  struct dgrptabent *
414*7c478bd9Sstevel@tonic-gate  *	Pointer to the next record in the device-group table, or
415*7c478bd9Sstevel@tonic-gate  *	(struct dgrptabent *) NULL if it was unable to open the file or there
416*7c478bd9Sstevel@tonic-gate  *	are no more records to read.  "errno" reflects the situation.  If
417*7c478bd9Sstevel@tonic-gate  *	errno is not changed and the function returns NULL, there are no more
418*7c478bd9Sstevel@tonic-gate  *	records to read.  If errno is set, it indicates the error.
419*7c478bd9Sstevel@tonic-gate  *
420*7c478bd9Sstevel@tonic-gate  *  Notes:
421*7c478bd9Sstevel@tonic-gate  *    - The caller should set "errno" to 0 before calling this function.
422*7c478bd9Sstevel@tonic-gate  */
423*7c478bd9Sstevel@tonic-gate 
424*7c478bd9Sstevel@tonic-gate struct dgrptabent *
_getdgrptabent(void)425*7c478bd9Sstevel@tonic-gate _getdgrptabent(void)
426*7c478bd9Sstevel@tonic-gate {
427*7c478bd9Sstevel@tonic-gate 	/*  Automatic data  */
428*7c478bd9Sstevel@tonic-gate 	struct dgrptabent	*ent;		/* Dev table entry structure */
429*7c478bd9Sstevel@tonic-gate 	struct member		*q, *r;		/* Tmps for member structs */
430*7c478bd9Sstevel@tonic-gate 	char			*record;		/* Record just read */
431*7c478bd9Sstevel@tonic-gate 	char			*p;		/* Tmp char ptr */
432*7c478bd9Sstevel@tonic-gate 	int			done;		/* TRUE if built an entry */
433*7c478bd9Sstevel@tonic-gate 
434*7c478bd9Sstevel@tonic-gate 
435*7c478bd9Sstevel@tonic-gate 	/*  Open the device-group table if it's not already open */
436*7c478bd9Sstevel@tonic-gate 	if (!oam_dgroup)
437*7c478bd9Sstevel@tonic-gate 	    if (!_opendgrptab("r"))
438*7c478bd9Sstevel@tonic-gate 		return (NULL);
439*7c478bd9Sstevel@tonic-gate 
440*7c478bd9Sstevel@tonic-gate 
441*7c478bd9Sstevel@tonic-gate 	/*  Get space for the structure we're returning  */
442*7c478bd9Sstevel@tonic-gate 	if (!(ent = malloc(sizeof (struct dgrptabent)))) {
443*7c478bd9Sstevel@tonic-gate 	    return (NULL);
444*7c478bd9Sstevel@tonic-gate 	}
445*7c478bd9Sstevel@tonic-gate 
446*7c478bd9Sstevel@tonic-gate 	done = FALSE;
447*7c478bd9Sstevel@tonic-gate 	while (!done && (record = getnextrec())) {
448*7c478bd9Sstevel@tonic-gate 
449*7c478bd9Sstevel@tonic-gate 	    /* Is this a comment record or a data record */
450*7c478bd9Sstevel@tonic-gate 	    if (strchr("#\n", *record) ||
451*7c478bd9Sstevel@tonic-gate 			isspace((unsigned char)*record)) {
452*7c478bd9Sstevel@tonic-gate 
453*7c478bd9Sstevel@tonic-gate 		/*
454*7c478bd9Sstevel@tonic-gate 		 *  Record is a comment record
455*7c478bd9Sstevel@tonic-gate 		 */
456*7c478bd9Sstevel@tonic-gate 		ent->comment = TRUE;
457*7c478bd9Sstevel@tonic-gate 		ent->entryno = recnum++;
458*7c478bd9Sstevel@tonic-gate 
459*7c478bd9Sstevel@tonic-gate 		/* Alloc space for the comment and save pointer in struct */
460*7c478bd9Sstevel@tonic-gate 		if (ent->dataspace = malloc(strlen(record)+1)) {
461*7c478bd9Sstevel@tonic-gate 		    (void) strcpy(ent->dataspace, record);
462*7c478bd9Sstevel@tonic-gate 		} else {
463*7c478bd9Sstevel@tonic-gate 		    free(ent);
464*7c478bd9Sstevel@tonic-gate 		    ent = NULL;
465*7c478bd9Sstevel@tonic-gate 		}
466*7c478bd9Sstevel@tonic-gate 		done = TRUE;
467*7c478bd9Sstevel@tonic-gate 
468*7c478bd9Sstevel@tonic-gate 	    } else {
469*7c478bd9Sstevel@tonic-gate 
470*7c478bd9Sstevel@tonic-gate 		/*
471*7c478bd9Sstevel@tonic-gate 		 *  Record is a data record
472*7c478bd9Sstevel@tonic-gate 		 */
473*7c478bd9Sstevel@tonic-gate 		ent->comment = FALSE;
474*7c478bd9Sstevel@tonic-gate 
475*7c478bd9Sstevel@tonic-gate 		/* Extract the device-group name */
476*7c478bd9Sstevel@tonic-gate 		if (p = getfld(record, ":")) {
477*7c478bd9Sstevel@tonic-gate 
478*7c478bd9Sstevel@tonic-gate 		/* Record is a proper record */
479*7c478bd9Sstevel@tonic-gate 		    done = TRUE;
480*7c478bd9Sstevel@tonic-gate 		    ent->entryno = recnum++;
481*7c478bd9Sstevel@tonic-gate 
482*7c478bd9Sstevel@tonic-gate 		    /* Copy device group name into malloc()ed space */
483*7c478bd9Sstevel@tonic-gate 		    if (!(ent->name = malloc(strlen(p)+1))) {
484*7c478bd9Sstevel@tonic-gate 
485*7c478bd9Sstevel@tonic-gate 			free(ent);
486*7c478bd9Sstevel@tonic-gate 			return (NULL);
487*7c478bd9Sstevel@tonic-gate 		    }
488*7c478bd9Sstevel@tonic-gate 		    (void) strcpy(ent->name, p);
489*7c478bd9Sstevel@tonic-gate 
490*7c478bd9Sstevel@tonic-gate 			/*
491*7c478bd9Sstevel@tonic-gate 			 * Extract the membership from the membership list
492*7c478bd9Sstevel@tonic-gate 			 */
493*7c478bd9Sstevel@tonic-gate 
494*7c478bd9Sstevel@tonic-gate 		    /* Get the 1st member */
495*7c478bd9Sstevel@tonic-gate 		    ent->dataspace = NULL;
496*7c478bd9Sstevel@tonic-gate 		    while (((p = getfld(NULL, ",\n")) != NULL) && !(*p))
497*7c478bd9Sstevel@tonic-gate 			;
498*7c478bd9Sstevel@tonic-gate 		    if (p) {
499*7c478bd9Sstevel@tonic-gate 			if (!(q = malloc(sizeof (struct member)))) {
500*7c478bd9Sstevel@tonic-gate 
501*7c478bd9Sstevel@tonic-gate 			    free(ent->name);
502*7c478bd9Sstevel@tonic-gate 			    free(ent);
503*7c478bd9Sstevel@tonic-gate 			    return (NULL);
504*7c478bd9Sstevel@tonic-gate 			}
505*7c478bd9Sstevel@tonic-gate 			if (!(q->name = malloc(strlen(p)+1))) {
506*7c478bd9Sstevel@tonic-gate 			    free(q);
507*7c478bd9Sstevel@tonic-gate 			    free(ent->name);
508*7c478bd9Sstevel@tonic-gate 			    free((char *)ent);
509*7c478bd9Sstevel@tonic-gate 			    return (NULL);
510*7c478bd9Sstevel@tonic-gate 			}
511*7c478bd9Sstevel@tonic-gate 			(void) strcpy(q->name, p);
512*7c478bd9Sstevel@tonic-gate 			ent->membership = q;
513*7c478bd9Sstevel@tonic-gate 			q->next = NULL;
514*7c478bd9Sstevel@tonic-gate 
515*7c478bd9Sstevel@tonic-gate 			/* Get the rest of the members */
516*7c478bd9Sstevel@tonic-gate 			while (p = getfld(NULL, ",\n"))
517*7c478bd9Sstevel@tonic-gate 			    if (*p) {
518*7c478bd9Sstevel@tonic-gate 				if (!(r = malloc(sizeof (struct member)))) {
519*7c478bd9Sstevel@tonic-gate 				    for (q = ent->membership; q; q = r) {
520*7c478bd9Sstevel@tonic-gate 					free(q->name);
521*7c478bd9Sstevel@tonic-gate 					r = q->next;
522*7c478bd9Sstevel@tonic-gate 					free(q);
523*7c478bd9Sstevel@tonic-gate 				    }
524*7c478bd9Sstevel@tonic-gate 				    free(ent->name);
525*7c478bd9Sstevel@tonic-gate 				    free(ent);
526*7c478bd9Sstevel@tonic-gate 				    return (NULL);
527*7c478bd9Sstevel@tonic-gate 				}
528*7c478bd9Sstevel@tonic-gate 				if (!(r->name = malloc(strlen(p)+1))) {
529*7c478bd9Sstevel@tonic-gate 				    free(r);
530*7c478bd9Sstevel@tonic-gate 				    for (q = ent->membership; q; q = r) {
531*7c478bd9Sstevel@tonic-gate 					free(q->name);
532*7c478bd9Sstevel@tonic-gate 					r = q->next;
533*7c478bd9Sstevel@tonic-gate 					free(q);
534*7c478bd9Sstevel@tonic-gate 				    }
535*7c478bd9Sstevel@tonic-gate 				    free(ent->name);
536*7c478bd9Sstevel@tonic-gate 				    free(ent);
537*7c478bd9Sstevel@tonic-gate 				    return (NULL);
538*7c478bd9Sstevel@tonic-gate 				}
539*7c478bd9Sstevel@tonic-gate 
540*7c478bd9Sstevel@tonic-gate 				q->next = r;
541*7c478bd9Sstevel@tonic-gate 				(void) strcpy(r->name, p);
542*7c478bd9Sstevel@tonic-gate 				r->next = NULL;
543*7c478bd9Sstevel@tonic-gate 				q = r;
544*7c478bd9Sstevel@tonic-gate 			    }
545*7c478bd9Sstevel@tonic-gate 
546*7c478bd9Sstevel@tonic-gate 		    } else {
547*7c478bd9Sstevel@tonic-gate 			/* No members */
548*7c478bd9Sstevel@tonic-gate 			ent->membership = NULL;
549*7c478bd9Sstevel@tonic-gate 		    }
550*7c478bd9Sstevel@tonic-gate 
551*7c478bd9Sstevel@tonic-gate 		}   /* record contains a group name */
552*7c478bd9Sstevel@tonic-gate 
553*7c478bd9Sstevel@tonic-gate 	    }   /* record is a data record */
554*7c478bd9Sstevel@tonic-gate 
555*7c478bd9Sstevel@tonic-gate 	}   /* while (!done && there's more records) */
556*7c478bd9Sstevel@tonic-gate 
557*7c478bd9Sstevel@tonic-gate 
558*7c478bd9Sstevel@tonic-gate 	/*  An entry read?  If not, free alloc'd space and return NULL */
559*7c478bd9Sstevel@tonic-gate 	if (!done) {
560*7c478bd9Sstevel@tonic-gate 	    free(ent);
561*7c478bd9Sstevel@tonic-gate 	    ent = NULL;
562*7c478bd9Sstevel@tonic-gate 	}
563*7c478bd9Sstevel@tonic-gate 
564*7c478bd9Sstevel@tonic-gate 	/* Finis */
565*7c478bd9Sstevel@tonic-gate 	return (ent);
566*7c478bd9Sstevel@tonic-gate }
567*7c478bd9Sstevel@tonic-gate 
568*7c478bd9Sstevel@tonic-gate /*
569*7c478bd9Sstevel@tonic-gate  *  void _freedgrptabent(dgrptabent)
570*7c478bd9Sstevel@tonic-gate  *	struct dgrptabent       *dgrptabent;
571*7c478bd9Sstevel@tonic-gate  *
572*7c478bd9Sstevel@tonic-gate  *	This function frees space allocated to a device table entry.
573*7c478bd9Sstevel@tonic-gate  *
574*7c478bd9Sstevel@tonic-gate  *  Arguments:
575*7c478bd9Sstevel@tonic-gate  *	struct dgrptabent *dgrptabent	The structure whose space is to be
576*7c478bd9Sstevel@tonic-gate  *					freed.
577*7c478bd9Sstevel@tonic-gate  *
578*7c478bd9Sstevel@tonic-gate  *  Returns:  void
579*7c478bd9Sstevel@tonic-gate  */
580*7c478bd9Sstevel@tonic-gate 
581*7c478bd9Sstevel@tonic-gate void
_freedgrptabent(struct dgrptabent * ent)582*7c478bd9Sstevel@tonic-gate _freedgrptabent(struct dgrptabent *ent)	/* Structure to free */
583*7c478bd9Sstevel@tonic-gate {
584*7c478bd9Sstevel@tonic-gate 	/*
585*7c478bd9Sstevel@tonic-gate 	 * Automatic data
586*7c478bd9Sstevel@tonic-gate 	 */
587*7c478bd9Sstevel@tonic-gate 
588*7c478bd9Sstevel@tonic-gate 	struct member  *p;		/* Structure being freed */
589*7c478bd9Sstevel@tonic-gate 	struct member  *q;		/* Next structure to free */
590*7c478bd9Sstevel@tonic-gate 
591*7c478bd9Sstevel@tonic-gate 	/*
592*7c478bd9Sstevel@tonic-gate 	 *  Free the space allocated to the membership structure.
593*7c478bd9Sstevel@tonic-gate 	 */
594*7c478bd9Sstevel@tonic-gate 
595*7c478bd9Sstevel@tonic-gate 	if (!ent->comment) {
596*7c478bd9Sstevel@tonic-gate 	    if ((q = ent->membership) != NULL) do {
597*7c478bd9Sstevel@tonic-gate 		p = q;
598*7c478bd9Sstevel@tonic-gate 		q = p->next;
599*7c478bd9Sstevel@tonic-gate 		if (p->name) free(p->name);
600*7c478bd9Sstevel@tonic-gate 		free(p);
601*7c478bd9Sstevel@tonic-gate 	    } while (q);
602*7c478bd9Sstevel@tonic-gate 
603*7c478bd9Sstevel@tonic-gate 	    /* Free the device group name */
604*7c478bd9Sstevel@tonic-gate 	    if (ent->name) free(ent->name);
605*7c478bd9Sstevel@tonic-gate 	}
606*7c478bd9Sstevel@tonic-gate 
607*7c478bd9Sstevel@tonic-gate 	/* Free the membership string */
608*7c478bd9Sstevel@tonic-gate 	if (ent->dataspace) free(ent->dataspace);
609*7c478bd9Sstevel@tonic-gate }
610*7c478bd9Sstevel@tonic-gate 
611*7c478bd9Sstevel@tonic-gate /*
612*7c478bd9Sstevel@tonic-gate  *  struct dgrptabent *_getdgrprec(dgroup)
613*7c478bd9Sstevel@tonic-gate  *	char *dgroup
614*7c478bd9Sstevel@tonic-gate  *
615*7c478bd9Sstevel@tonic-gate  *	Thie _getdgrprec() function returns a pointer to a structure that
616*7c478bd9Sstevel@tonic-gate  *	contains the information in the device-group table entry that describes
617*7c478bd9Sstevel@tonic-gate  *	the device-group <dgroup>.
618*7c478bd9Sstevel@tonic-gate  *
619*7c478bd9Sstevel@tonic-gate  *  Arguments:
620*7c478bd9Sstevel@tonic-gate  *	char *dgroup	A character-string describing the device-group whose
621*7c478bd9Sstevel@tonic-gate  *			record is to be retrieved from the device-group table.
622*7c478bd9Sstevel@tonic-gate  *
623*7c478bd9Sstevel@tonic-gate  *  Returns:  struct dgrptabent *
624*7c478bd9Sstevel@tonic-gate  *	A pointer to a structure describing the device group.
625*7c478bd9Sstevel@tonic-gate  */
626*7c478bd9Sstevel@tonic-gate 
627*7c478bd9Sstevel@tonic-gate struct dgrptabent *
_getdgrprec(char * dgroup)628*7c478bd9Sstevel@tonic-gate _getdgrprec(char *dgroup)		/* dgroup to search for */
629*7c478bd9Sstevel@tonic-gate {
630*7c478bd9Sstevel@tonic-gate 	/*
631*7c478bd9Sstevel@tonic-gate 	 *  Automatic data
632*7c478bd9Sstevel@tonic-gate 	 */
633*7c478bd9Sstevel@tonic-gate 
634*7c478bd9Sstevel@tonic-gate 	struct dgrptabent	*dgrprec;	/* Pointer to current record */
635*7c478bd9Sstevel@tonic-gate 	int			found;		/* FLAG, TRUE if found */
636*7c478bd9Sstevel@tonic-gate 
637*7c478bd9Sstevel@tonic-gate 
638*7c478bd9Sstevel@tonic-gate 	/*
639*7c478bd9Sstevel@tonic-gate 	 *  Search the device-group table looking for the requested
640*7c478bd9Sstevel@tonic-gate 	 *  device group
641*7c478bd9Sstevel@tonic-gate 	 */
642*7c478bd9Sstevel@tonic-gate 
643*7c478bd9Sstevel@tonic-gate 	_setdgrptab();
644*7c478bd9Sstevel@tonic-gate 	errno = 0;
645*7c478bd9Sstevel@tonic-gate 	found = FALSE;
646*7c478bd9Sstevel@tonic-gate 	while (!found && (dgrprec = _getdgrptabent())) {
647*7c478bd9Sstevel@tonic-gate 	    if (!dgrprec->comment && strcmp(dgroup, dgrprec->name) == 0)
648*7c478bd9Sstevel@tonic-gate 		found = TRUE;
649*7c478bd9Sstevel@tonic-gate 	    else _freedgrptabent(dgrprec);
650*7c478bd9Sstevel@tonic-gate 	}
651*7c478bd9Sstevel@tonic-gate 
652*7c478bd9Sstevel@tonic-gate 	/*  Set up return codes if we've failed  */
653*7c478bd9Sstevel@tonic-gate 	if (!found) {
654*7c478bd9Sstevel@tonic-gate 	    if (errno == 0) errno = EINVAL;
655*7c478bd9Sstevel@tonic-gate 	    dgrprec = NULL;
656*7c478bd9Sstevel@tonic-gate 	}
657*7c478bd9Sstevel@tonic-gate 
658*7c478bd9Sstevel@tonic-gate 	/*  Finis  */
659*7c478bd9Sstevel@tonic-gate 	return (dgrprec);
660*7c478bd9Sstevel@tonic-gate }
661