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