xref: /onnv-gate/usr/src/lib/libadm/common/putdgrp.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 /*
23*0Sstevel@tonic-gate  * Copyright (c) 1996-1997, by Sun Microsystems, Inc.
24*0Sstevel@tonic-gate  * All Rights reserved.
25*0Sstevel@tonic-gate  */
26*0Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
27*0Sstevel@tonic-gate /*	  All Rights Reserved  	*/
28*0Sstevel@tonic-gate 
29*0Sstevel@tonic-gate 
30*0Sstevel@tonic-gate #pragma	ident	"%Z%%M%	%I%	%E% SMI"	/* SVr4.0 1.2 */
31*0Sstevel@tonic-gate /* LINTLIBRARY */
32*0Sstevel@tonic-gate 
33*0Sstevel@tonic-gate /*
34*0Sstevel@tonic-gate  * putdgrp.c
35*0Sstevel@tonic-gate  *
36*0Sstevel@tonic-gate  * Global Definitions:
37*0Sstevel@tonic-gate  *	_putdgrptabrec()	Write a device-group record to a stream
38*0Sstevel@tonic-gate  *	_rmdgrptabrec()		Remove a device-group table record
39*0Sstevel@tonic-gate  *	_rmdgrpmems()		Remove specific members from a device group
40*0Sstevel@tonic-gate  *	_adddgrptabrec()	Add a device-group record to the table
41*0Sstevel@tonic-gate  */
42*0Sstevel@tonic-gate 
43*0Sstevel@tonic-gate /*
44*0Sstevel@tonic-gate  *  G L O B A L   R E F E R E N C E S
45*0Sstevel@tonic-gate  *
46*0Sstevel@tonic-gate  *	Header Files
47*0Sstevel@tonic-gate  *	Externals Referenced
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>		UNIX System Data Types
53*0Sstevel@tonic-gate  *	<stdio.h>		Standard I/O definitions
54*0Sstevel@tonic-gate  *	<fcntl.h>		Definitions for file control
55*0Sstevel@tonic-gate  *	<errno.h>		Error handling definitions
56*0Sstevel@tonic-gate  *	<string.h>		String Handling Definitions
57*0Sstevel@tonic-gate  *	<unistd.h>		Standard UNIX(r) Definitions
58*0Sstevel@tonic-gate  *	<devmgmt.h>		Device Management Definitions
59*0Sstevel@tonic-gate  *	"devtab.h"		Local Device Management Definitions
60*0Sstevel@tonic-gate  */
61*0Sstevel@tonic-gate 
62*0Sstevel@tonic-gate #include	<sys/types.h>
63*0Sstevel@tonic-gate #include	<sys/stat.h>
64*0Sstevel@tonic-gate #include	<stdio.h>
65*0Sstevel@tonic-gate #include	<fcntl.h>
66*0Sstevel@tonic-gate #include	<errno.h>
67*0Sstevel@tonic-gate #include	<string.h>
68*0Sstevel@tonic-gate #include	<unistd.h>
69*0Sstevel@tonic-gate #include	<stdlib.h>
70*0Sstevel@tonic-gate #include	<devmgmt.h>
71*0Sstevel@tonic-gate #include	"devtab.h"
72*0Sstevel@tonic-gate 
73*0Sstevel@tonic-gate /*
74*0Sstevel@tonic-gate  *  L O C A L   D E F I N I T I O N S
75*0Sstevel@tonic-gate  *	TDGTABNM	Name of the temporary device-group table (in the
76*0Sstevel@tonic-gate  *			directory of the existing table)
77*0Sstevel@tonic-gate  *	TDGTABNMLN	Number of characters added to the directory
78*0Sstevel@tonic-gate  *			name -- the length of the device-group table temp name
79*0Sstevel@tonic-gate  */
80*0Sstevel@tonic-gate 
81*0Sstevel@tonic-gate #define	TDGTABNM	"%sdgroup.%6.6d"
82*0Sstevel@tonic-gate #define	TDGTABNMLN	13
83*0Sstevel@tonic-gate 
84*0Sstevel@tonic-gate 
85*0Sstevel@tonic-gate /*
86*0Sstevel@tonic-gate  * Static functions
87*0Sstevel@tonic-gate  *	lkdgrptab	Locks the device-group table
88*0Sstevel@tonic-gate  *	unlkdgrptab	Unlocks the device-group table
89*0Sstevel@tonic-gate  *	mkdgrptabent	Builds a device-group table entry from the alias and the
90*0Sstevel@tonic-gate  *			list of attr=val pairs given
91*0Sstevel@tonic-gate  *	opennewdgrptab	Opens a new device-group table (as a temp file)
92*0Sstevel@tonic-gate  *	mknewdgrptab	Makes the temp device-group table the new dgrptab
93*0Sstevel@tonic-gate  *	rmnewdgrptab	Remove the temporary device-group table and free space
94*0Sstevel@tonic-gate  *			allocated to the filename of that file.
95*0Sstevel@tonic-gate  */
96*0Sstevel@tonic-gate 
97*0Sstevel@tonic-gate static	int			lkdgrptab(char *o_mode, short lktype);
98*0Sstevel@tonic-gate static	int			unlkdgrptab(void);
99*0Sstevel@tonic-gate static	struct dgrptabent	*mkdgrptabent(char *dgroup, char **members);
100*0Sstevel@tonic-gate static	FILE			*opennewdgrptab(char **pname);
101*0Sstevel@tonic-gate static	int			mknewdgrptab(char *tempname);
102*0Sstevel@tonic-gate static	int			rmnewdgrptab(char *tempname);
103*0Sstevel@tonic-gate 
104*0Sstevel@tonic-gate /*
105*0Sstevel@tonic-gate  * FILE *opennewdgrptab(pname)
106*0Sstevel@tonic-gate  *	char   **pname
107*0Sstevel@tonic-gate  *
108*0Sstevel@tonic-gate  *	Generates a temporary device-group table name from the existing
109*0Sstevel@tonic-gate  *	device-group table name (in the same directory) and opens that
110*0Sstevel@tonic-gate  *	file for writing.  It puts a pointer to the malloc()ed space
111*0Sstevel@tonic-gate  *	containing the temp device-group table's name at the place
112*0Sstevel@tonic-gate  *	referenced by <pname>.
113*0Sstevel@tonic-gate  *
114*0Sstevel@tonic-gate  *  Arguments:
115*0Sstevel@tonic-gate  *	pname	Pointer to the char * to contain the address of the name
116*0Sstevel@tonic-gate  *		of the temporary file
117*0Sstevel@tonic-gate  *
118*0Sstevel@tonic-gate  *  Returns:  FILE *
119*0Sstevel@tonic-gate  *	A pointer to the opened stream or (FILE *) NULL if an error occurred.
120*0Sstevel@tonic-gate  *	If an error occurred, "errno" will be set to reflect the problem.
121*0Sstevel@tonic-gate  */
122*0Sstevel@tonic-gate 
123*0Sstevel@tonic-gate static FILE *
opennewdgrptab(char ** pname)124*0Sstevel@tonic-gate opennewdgrptab(char **pname)	 /* A(ptr to temp filename's path) */
125*0Sstevel@tonic-gate {
126*0Sstevel@tonic-gate 	char   *oldname;		/* Ptr to the dgrptab name */
127*0Sstevel@tonic-gate 	char   *buf;			/* Ptr to the temp file's name */
128*0Sstevel@tonic-gate 	char   *dirname;		/* Directory containing dgrptab */
129*0Sstevel@tonic-gate 	char   *p;			/* Ptr to last '/' in dgrptab name */
130*0Sstevel@tonic-gate 	int    fd;			/* Opened file descriptor */
131*0Sstevel@tonic-gate 	FILE   *fp;			/* Opened file pointer */
132*0Sstevel@tonic-gate 	struct stat64	sbuf;		/* stat buf for old dgrptab file */
133*0Sstevel@tonic-gate 
134*0Sstevel@tonic-gate 
135*0Sstevel@tonic-gate 	/* Initializations */
136*0Sstevel@tonic-gate 	fp = NULL;
137*0Sstevel@tonic-gate 
138*0Sstevel@tonic-gate 	/* Get the name of the device-group table */
139*0Sstevel@tonic-gate 	if (oldname = _dgrptabpath()) {
140*0Sstevel@tonic-gate 	/*
141*0Sstevel@tonic-gate 	 * It is possible for us to have sufficient permissions to create
142*0Sstevel@tonic-gate 	 * the new file without having sufficient permissions to write the
143*0Sstevel@tonic-gate 	 * original dgrptab file.  For consistency with the operations which
144*0Sstevel@tonic-gate 	 * modify the original file by writing it directly we require write
145*0Sstevel@tonic-gate 	 * permissions for the original file in order to make a new one.
146*0Sstevel@tonic-gate 	 */
147*0Sstevel@tonic-gate 	    if ((fd = open(oldname, O_WRONLY)) == -1)
148*0Sstevel@tonic-gate 		return (NULL);
149*0Sstevel@tonic-gate 
150*0Sstevel@tonic-gate 	    if (fstat64(fd, &sbuf) == -1) {
151*0Sstevel@tonic-gate 		(void) close(fd);
152*0Sstevel@tonic-gate 		return (NULL);
153*0Sstevel@tonic-gate 	    }
154*0Sstevel@tonic-gate 	    (void) close(fd);
155*0Sstevel@tonic-gate 
156*0Sstevel@tonic-gate 	    /* Get the directory that the device-group table lives in */
157*0Sstevel@tonic-gate 	    if (p = strrchr(oldname, '/')) {
158*0Sstevel@tonic-gate 		*(p+1) = '\0';
159*0Sstevel@tonic-gate 		dirname = oldname;
160*0Sstevel@tonic-gate 	    } else
161*0Sstevel@tonic-gate 		dirname = "./";
162*0Sstevel@tonic-gate 
163*0Sstevel@tonic-gate 	    /* Get space for the temp dgrptab pathname */
164*0Sstevel@tonic-gate 	    if (buf = malloc(TDGTABNMLN+strlen(dirname)+1)) {
165*0Sstevel@tonic-gate 
166*0Sstevel@tonic-gate 		/*
167*0Sstevel@tonic-gate 		 * Build the name of the temp dgrptab and open the
168*0Sstevel@tonic-gate 		 * file.  We must reset the owner, group and perms to those
169*0Sstevel@tonic-gate 		 * of the original dgrptab file.
170*0Sstevel@tonic-gate 		 */
171*0Sstevel@tonic-gate 		(void) sprintf(buf, TDGTABNM, dirname, getpid());
172*0Sstevel@tonic-gate 		if (fp = fopen(buf, "w")) {
173*0Sstevel@tonic-gate 			*pname = buf;
174*0Sstevel@tonic-gate 			(void) fchmod(fileno(fp), sbuf.st_mode & 0777);
175*0Sstevel@tonic-gate 			(void) fchown(fileno(fp), sbuf.st_uid, sbuf.st_gid);
176*0Sstevel@tonic-gate 		} else {
177*0Sstevel@tonic-gate 			free(buf);
178*0Sstevel@tonic-gate 		}
179*0Sstevel@tonic-gate 	    }
180*0Sstevel@tonic-gate 
181*0Sstevel@tonic-gate 	    /* Free the space containing the dgrptab's name */
182*0Sstevel@tonic-gate 	    free(oldname);
183*0Sstevel@tonic-gate 	}
184*0Sstevel@tonic-gate 
185*0Sstevel@tonic-gate 	/* Finished.  Return what we've got */
186*0Sstevel@tonic-gate 	return (fp);
187*0Sstevel@tonic-gate }
188*0Sstevel@tonic-gate 
189*0Sstevel@tonic-gate /*
190*0Sstevel@tonic-gate  *  int rmnewdgrptab(tempname)
191*0Sstevel@tonic-gate  *	char   *tempname
192*0Sstevel@tonic-gate  *
193*0Sstevel@tonic-gate  *	Unlink the temp dgrptab and free the memory allocated to
194*0Sstevel@tonic-gate  *	contain the name of that file
195*0Sstevel@tonic-gate  *
196*0Sstevel@tonic-gate  *  Arguments:
197*0Sstevel@tonic-gate  *	tempname	Name of the temporary file
198*0Sstevel@tonic-gate  *
199*0Sstevel@tonic-gate  *  Returns: int
200*0Sstevel@tonic-gate  *	TRUE if successful, FALSE otherwise
201*0Sstevel@tonic-gate  */
202*0Sstevel@tonic-gate 
203*0Sstevel@tonic-gate static int
rmnewdgrptab(char * tempname)204*0Sstevel@tonic-gate rmnewdgrptab(char *tempname)
205*0Sstevel@tonic-gate {
206*0Sstevel@tonic-gate 	/* Automatic data */
207*0Sstevel@tonic-gate 	int	noerr;
208*0Sstevel@tonic-gate 
209*0Sstevel@tonic-gate 	/* Unlink the temporary file */
210*0Sstevel@tonic-gate 	noerr = (unlink(tempname) == 0);
211*0Sstevel@tonic-gate 	free(tempname);
212*0Sstevel@tonic-gate 
213*0Sstevel@tonic-gate 	/* Finished */
214*0Sstevel@tonic-gate 	return (noerr);
215*0Sstevel@tonic-gate }
216*0Sstevel@tonic-gate 
217*0Sstevel@tonic-gate /*
218*0Sstevel@tonic-gate  *  int mknewdgrptab(tempname)
219*0Sstevel@tonic-gate  *	char   *tempname
220*0Sstevel@tonic-gate  *
221*0Sstevel@tonic-gate  *	Make the temporary device-group table the new system
222*0Sstevel@tonic-gate  *	device-group table
223*0Sstevel@tonic-gate  *
224*0Sstevel@tonic-gate  *  Arguments:
225*0Sstevel@tonic-gate  *	tempname	Name of the temporary file
226*0Sstevel@tonic-gate  *
227*0Sstevel@tonic-gate  *  Returns:  int
228*0Sstevel@tonic-gate  *	TRUE if successful, FALSE otherwise
229*0Sstevel@tonic-gate  *
230*0Sstevel@tonic-gate  *  Notes:
231*0Sstevel@tonic-gate  *	- Need to use rename() someday instead of link()/unlink()
232*0Sstevel@tonic-gate  *	- This code is somewhat ineffecient in that asks for the name
233*0Sstevel@tonic-gate  *	  of the device-group table more than once.  Done so that we don't
234*0Sstevel@tonic-gate  *	  have to manage that space, but this may be somewhat lazy.
235*0Sstevel@tonic-gate  */
236*0Sstevel@tonic-gate 
237*0Sstevel@tonic-gate static int
mknewdgrptab(char * tempname)238*0Sstevel@tonic-gate mknewdgrptab(char *tempname)		/* Ptr to name of temp dgrp tab */
239*0Sstevel@tonic-gate {
240*0Sstevel@tonic-gate 	char   *dgrpname;		/* Ptr to the dgrptab's name */
241*0Sstevel@tonic-gate 	int	noerr;			/* FLAG, TRUE if all's well */
242*0Sstevel@tonic-gate 
243*0Sstevel@tonic-gate 	/* Get the dgrptab's pathname */
244*0Sstevel@tonic-gate 	if (dgrpname = _dgrptabpath()) {
245*0Sstevel@tonic-gate 
246*0Sstevel@tonic-gate 	    /* Unlink the existing file */
247*0Sstevel@tonic-gate 	    if (unlink(dgrpname) == 0) {
248*0Sstevel@tonic-gate 
249*0Sstevel@tonic-gate 		/* Make the temp file the real device-group table */
250*0Sstevel@tonic-gate 		noerr = (link(tempname, dgrpname) == 0) ? TRUE : FALSE;
251*0Sstevel@tonic-gate 
252*0Sstevel@tonic-gate 		/* Remove the temp file */
253*0Sstevel@tonic-gate 		if (noerr) noerr = rmnewdgrptab(tempname);
254*0Sstevel@tonic-gate 
255*0Sstevel@tonic-gate 	    } else noerr = FALSE;	/* unlink() failed */
256*0Sstevel@tonic-gate 
257*0Sstevel@tonic-gate 	    /* Free the dgrptab's name */
258*0Sstevel@tonic-gate 	    free(dgrpname);
259*0Sstevel@tonic-gate 
260*0Sstevel@tonic-gate 	} else noerr = FALSE; 	/* dgrptabpath() failed */
261*0Sstevel@tonic-gate 
262*0Sstevel@tonic-gate 	/* Finished.  Return success indicator */
263*0Sstevel@tonic-gate 	return (noerr);
264*0Sstevel@tonic-gate }
265*0Sstevel@tonic-gate 
266*0Sstevel@tonic-gate /*
267*0Sstevel@tonic-gate  * int lkdgrptab(o_mode, lktype)
268*0Sstevel@tonic-gate  *	char   *o_mode
269*0Sstevel@tonic-gate  *	short	lktype
270*0Sstevel@tonic-gate  *
271*0Sstevel@tonic-gate  *	Lock the device-group table for writing.  If it isn't available, it
272*0Sstevel@tonic-gate  *	waits until it is.
273*0Sstevel@tonic-gate  *
274*0Sstevel@tonic-gate  *  Arguments:
275*0Sstevel@tonic-gate  *	o_mode	The open() mode to use when opening the device-group table
276*0Sstevel@tonic-gate  *	lktype	The type of lock to apply
277*0Sstevel@tonic-gate  *
278*0Sstevel@tonic-gate  *  Returns:  int
279*0Sstevel@tonic-gate  *	TRUE if successful, FALSE with errno set otherwise
280*0Sstevel@tonic-gate  */
281*0Sstevel@tonic-gate 
282*0Sstevel@tonic-gate static int
lkdgrptab(char * o_mode,short lktype)283*0Sstevel@tonic-gate lkdgrptab(
284*0Sstevel@tonic-gate 	char   *o_mode,				/* Open mode */
285*0Sstevel@tonic-gate 	short	lktype)				/* Lock type */
286*0Sstevel@tonic-gate {
287*0Sstevel@tonic-gate 	/* Automatic data */
288*0Sstevel@tonic-gate 	struct flock	lockinfo;		/* File locking structure */
289*0Sstevel@tonic-gate 	int		noerr;			/* FLAG, TRUE if no error */
290*0Sstevel@tonic-gate 	int		olderrno;		/* Former value of errno */
291*0Sstevel@tonic-gate 
292*0Sstevel@tonic-gate 
293*0Sstevel@tonic-gate 	/* Close the device-group table (if it's open) */
294*0Sstevel@tonic-gate 	_enddgrptab();
295*0Sstevel@tonic-gate 
296*0Sstevel@tonic-gate 	/* Open the device-group table for read/append */
297*0Sstevel@tonic-gate 	noerr = TRUE;
298*0Sstevel@tonic-gate 	if (_opendgrptab(o_mode)) {
299*0Sstevel@tonic-gate 
300*0Sstevel@tonic-gate 	/*
301*0Sstevel@tonic-gate 	 * Lock the device-group table (for writing).  If it's not
302*0Sstevel@tonic-gate 	 * available, wait until it is, then close and open the
303*0Sstevel@tonic-gate 	 * table (modify and delete change the table!) and try
304*0Sstevel@tonic-gate 	 * to lock it again
305*0Sstevel@tonic-gate 	 */
306*0Sstevel@tonic-gate 
307*0Sstevel@tonic-gate 	    /* Build the locking structure */
308*0Sstevel@tonic-gate 	    lockinfo.l_type = lktype;
309*0Sstevel@tonic-gate 	    lockinfo.l_whence = 0;
310*0Sstevel@tonic-gate 	    lockinfo.l_start = 0L;
311*0Sstevel@tonic-gate 	    lockinfo.l_len = 0L;
312*0Sstevel@tonic-gate 	    olderrno = errno;
313*0Sstevel@tonic-gate 
314*0Sstevel@tonic-gate 	    /* Keep on going until we lock the file or an error happens */
315*0Sstevel@tonic-gate 	    while ((fcntl(fileno(oam_dgroup), F_SETLK, &lockinfo) == -1) &&
316*0Sstevel@tonic-gate 		!noerr) {
317*0Sstevel@tonic-gate 
318*0Sstevel@tonic-gate 		/*
319*0Sstevel@tonic-gate 		 * fcntl() failed.
320*0Sstevel@tonic-gate 		 * If errno=EACCES, it's because the file's locked by someone
321*0Sstevel@tonic-gate 		 * else.  Wait for the file to be unlocked, then close and
322*0Sstevel@tonic-gate 		 * reopen the file and try the lock again.
323*0Sstevel@tonic-gate 		 */
324*0Sstevel@tonic-gate 
325*0Sstevel@tonic-gate 		if (errno == EACCES) {
326*0Sstevel@tonic-gate 		    if (fcntl(fileno(oam_dgroup), F_SETLKW, &lockinfo) == -1)
327*0Sstevel@tonic-gate 			noerr = FALSE;
328*0Sstevel@tonic-gate 		    else {
329*0Sstevel@tonic-gate 			_enddgrptab();
330*0Sstevel@tonic-gate 			if (!_opendgrptab(o_mode)) noerr = FALSE;
331*0Sstevel@tonic-gate 			else errno = olderrno;
332*0Sstevel@tonic-gate 		    }
333*0Sstevel@tonic-gate 
334*0Sstevel@tonic-gate 		} else noerr = FALSE;  /* fcntl() failed hard */
335*0Sstevel@tonic-gate 
336*0Sstevel@tonic-gate 	    }   /* End while (fcntl() && !noerr) */
337*0Sstevel@tonic-gate 
338*0Sstevel@tonic-gate 	    /* Don't keep file open if an error happened */
339*0Sstevel@tonic-gate 	    if (!noerr) _enddgrptab();
340*0Sstevel@tonic-gate 
341*0Sstevel@tonic-gate 	} else noerr = FALSE;	/* _opendgrptab() failed */
342*0Sstevel@tonic-gate 
343*0Sstevel@tonic-gate 	/* Done */
344*0Sstevel@tonic-gate 	return (noerr);
345*0Sstevel@tonic-gate }
346*0Sstevel@tonic-gate 
347*0Sstevel@tonic-gate /*
348*0Sstevel@tonic-gate  * int unlkdgrptab()
349*0Sstevel@tonic-gate  *
350*0Sstevel@tonic-gate  *	Unlock the locked device-group table.
351*0Sstevel@tonic-gate  *
352*0Sstevel@tonic-gate  *  Arguments:  None
353*0Sstevel@tonic-gate  *
354*0Sstevel@tonic-gate  *  Returns:  int
355*0Sstevel@tonic-gate  *	Whatever fcntl() returns...
356*0Sstevel@tonic-gate  */
357*0Sstevel@tonic-gate 
358*0Sstevel@tonic-gate static int
unlkdgrptab(void)359*0Sstevel@tonic-gate unlkdgrptab(void)
360*0Sstevel@tonic-gate {
361*0Sstevel@tonic-gate 	/* Automatic data */
362*0Sstevel@tonic-gate 	struct flock	lockinfo;		/* Locking structure */
363*0Sstevel@tonic-gate 	int		noerr;			/* FLAG, TRUE if all's well */
364*0Sstevel@tonic-gate 
365*0Sstevel@tonic-gate 	/* Build the locking structure */
366*0Sstevel@tonic-gate 	lockinfo.l_type = F_UNLCK;		/* Lock type */
367*0Sstevel@tonic-gate 	lockinfo.l_whence = 0;			/* Count from top of file */
368*0Sstevel@tonic-gate 	lockinfo.l_start = 0L;			/* From beginning */
369*0Sstevel@tonic-gate 	lockinfo.l_len = 0L;			/* Length of locked data */
370*0Sstevel@tonic-gate 
371*0Sstevel@tonic-gate 	/* Unlock it */
372*0Sstevel@tonic-gate 	noerr = (fcntl(fileno(oam_dgroup), F_SETLK, &lockinfo) != -1);
373*0Sstevel@tonic-gate 	_enddgrptab();
374*0Sstevel@tonic-gate 
375*0Sstevel@tonic-gate 	/* Finished */
376*0Sstevel@tonic-gate 	return (noerr);
377*0Sstevel@tonic-gate }
378*0Sstevel@tonic-gate 
379*0Sstevel@tonic-gate /*
380*0Sstevel@tonic-gate  * struct dgrptabent *mkdgrptabent(dgroup, members)
381*0Sstevel@tonic-gate  *	char   *dgroup
382*0Sstevel@tonic-gate  *	char  **members
383*0Sstevel@tonic-gate  *
384*0Sstevel@tonic-gate  *	This function builds a struct dgrptabent structure describing the
385*0Sstevel@tonic-gate  *	device-group <dgroup> so that it contains the members in the
386*0Sstevel@tonic-gate  *	membership list <members>.
387*0Sstevel@tonic-gate  *
388*0Sstevel@tonic-gate  *  Arguments:
389*0Sstevel@tonic-gate  *	dgroup		The device-group being added to the device-group table
390*0Sstevel@tonic-gate  *	members		The members of the device-group
391*0Sstevel@tonic-gate  *
392*0Sstevel@tonic-gate  *  Returns:  struct dgrptabent *
393*0Sstevel@tonic-gate  *	A completed struct dgrptabent structure containing the description
394*0Sstevel@tonic-gate  *	of the device group.  The structure, and all of the data in the
395*0Sstevel@tonic-gate  *	structure are each in space allocated using the malloc() function
396*0Sstevel@tonic-gate  *	and should be freed using the free() function (or the _freedgrptabent()
397*0Sstevel@tonic-gate  *	function.
398*0Sstevel@tonic-gate  */
399*0Sstevel@tonic-gate 
400*0Sstevel@tonic-gate static struct dgrptabent *
mkdgrptabent(char * dgroup,char ** members)401*0Sstevel@tonic-gate mkdgrptabent(
402*0Sstevel@tonic-gate 	char   *dgroup,		/* Device-group being created (or modified) */
403*0Sstevel@tonic-gate 	char  **members)	/* Members to add to that entry */
404*0Sstevel@tonic-gate {
405*0Sstevel@tonic-gate 	/* Automatic data */
406*0Sstevel@tonic-gate 	struct dgrptabent	*ent;	/* Ptr to struct we're making */
407*0Sstevel@tonic-gate 	struct member		*prev;	/* Ptr to prev attr/val struct */
408*0Sstevel@tonic-gate 	struct member		*member;	/* Ptr to current struct */
409*0Sstevel@tonic-gate 	char			**pp;	/* Ptr into list of ptrs */
410*0Sstevel@tonic-gate 	int			noerr;	/* TRUE if all's well */
411*0Sstevel@tonic-gate 
412*0Sstevel@tonic-gate 
413*0Sstevel@tonic-gate 	/* No problems (yet) */
414*0Sstevel@tonic-gate 	noerr = TRUE;
415*0Sstevel@tonic-gate 
416*0Sstevel@tonic-gate 	/* Get space for the structure */
417*0Sstevel@tonic-gate 	if (ent = malloc(sizeof (struct dgrptabent))) {
418*0Sstevel@tonic-gate 
419*0Sstevel@tonic-gate 	    /* Fill in default values */
420*0Sstevel@tonic-gate 	    ent->name = NULL; 				/* alias */
421*0Sstevel@tonic-gate 	    ent->entryno = 0;				/* Entry no. */
422*0Sstevel@tonic-gate 	    ent->comment = FALSE;			/* data rec */
423*0Sstevel@tonic-gate 	    ent->dataspace = NULL;			/* string */
424*0Sstevel@tonic-gate 	    ent->membership = NULL;			/* attr list */
425*0Sstevel@tonic-gate 
426*0Sstevel@tonic-gate 	    /* Fill in the device-group name */
427*0Sstevel@tonic-gate 	    if (ent->name = malloc(strlen(dgroup)+1)) {
428*0Sstevel@tonic-gate 		(void) strcpy(ent->name, dgroup);
429*0Sstevel@tonic-gate 
430*0Sstevel@tonic-gate 		/* Add membership to the structure */
431*0Sstevel@tonic-gate 		prev = NULL;
432*0Sstevel@tonic-gate 		if ((pp = members) != NULL)
433*0Sstevel@tonic-gate 		    while (*pp && noerr) {
434*0Sstevel@tonic-gate 
435*0Sstevel@tonic-gate 		    if (member = malloc(sizeof (struct member))) {
436*0Sstevel@tonic-gate 
437*0Sstevel@tonic-gate 			if (member->name = malloc(strlen(*pp)+1)) {
438*0Sstevel@tonic-gate 			    (void) strcpy(member->name, *pp);
439*0Sstevel@tonic-gate 			    if (prev) prev->next = member;
440*0Sstevel@tonic-gate 			    else ent->membership = member;
441*0Sstevel@tonic-gate 			    member->next = NULL;
442*0Sstevel@tonic-gate 			    prev = member;
443*0Sstevel@tonic-gate 			} else {
444*0Sstevel@tonic-gate 			    noerr = FALSE;
445*0Sstevel@tonic-gate 			    free(member);
446*0Sstevel@tonic-gate 			}
447*0Sstevel@tonic-gate 		    } else noerr = FALSE;
448*0Sstevel@tonic-gate 		    pp++;
449*0Sstevel@tonic-gate 		}   /* End membership processing loop */
450*0Sstevel@tonic-gate 
451*0Sstevel@tonic-gate 	    } else noerr = FALSE;	/* malloc() failed */
452*0Sstevel@tonic-gate 
453*0Sstevel@tonic-gate 		/*
454*0Sstevel@tonic-gate 		 * If there was a problem, clean up the mess we've made
455*0Sstevel@tonic-gate 		 */
456*0Sstevel@tonic-gate 
457*0Sstevel@tonic-gate 	    if (!noerr) {
458*0Sstevel@tonic-gate 
459*0Sstevel@tonic-gate 		_freedgrptabent(ent);
460*0Sstevel@tonic-gate 		ent = NULL;
461*0Sstevel@tonic-gate 
462*0Sstevel@tonic-gate 	    }   /* if (noerr) */
463*0Sstevel@tonic-gate 
464*0Sstevel@tonic-gate 	} else noerr = FALSE;   /* if (malloc(dgrptabent space)) */
465*0Sstevel@tonic-gate 
466*0Sstevel@tonic-gate 	/* Finished */
467*0Sstevel@tonic-gate 	return (ent);
468*0Sstevel@tonic-gate }
469*0Sstevel@tonic-gate 
470*0Sstevel@tonic-gate /*
471*0Sstevel@tonic-gate  * int _putdgrptabrec(stream, rec)
472*0Sstevel@tonic-gate  *	FILE		       *stream
473*0Sstevel@tonic-gate  *	struct dgrptabent      *rec
474*0Sstevel@tonic-gate  *
475*0Sstevel@tonic-gate  *	Write a device-group table record containing the information in the
476*0Sstevel@tonic-gate  *	struct dgrptab structure <rec> to the current position of the
477*0Sstevel@tonic-gate  *	standard I/O stream <stream>.
478*0Sstevel@tonic-gate  *
479*0Sstevel@tonic-gate  *  Arguments:
480*0Sstevel@tonic-gate  *	stream		The stream to write to
481*0Sstevel@tonic-gate  *	rec		The structure containing the information to write
482*0Sstevel@tonic-gate  *
483*0Sstevel@tonic-gate  *  Returns:  int
484*0Sstevel@tonic-gate  *	The number of characters written or EOF if there was some error.
485*0Sstevel@tonic-gate  */
486*0Sstevel@tonic-gate 
487*0Sstevel@tonic-gate int
_putdgrptabrec(FILE * stream,struct dgrptabent * rec)488*0Sstevel@tonic-gate _putdgrptabrec(
489*0Sstevel@tonic-gate 	FILE			*stream,	/* Stream to write to */
490*0Sstevel@tonic-gate 	struct dgrptabent	*rec)		/* Record to write */
491*0Sstevel@tonic-gate {
492*0Sstevel@tonic-gate 	/* Automatic Data */
493*0Sstevel@tonic-gate 	struct member		*mem;		/* Ptr to attr/val pair */
494*0Sstevel@tonic-gate 	char			*buf;		/* Allocated buffer */
495*0Sstevel@tonic-gate 	char			*p;		/* Temp char pointer */
496*0Sstevel@tonic-gate 	char			*q;		/* Temp char pointer */
497*0Sstevel@tonic-gate 	int			count;		/* Number of chars written */
498*0Sstevel@tonic-gate 	int			size;		/* Size of needed buffer */
499*0Sstevel@tonic-gate 
500*0Sstevel@tonic-gate 
501*0Sstevel@tonic-gate 	/* Comment or data record? */
502*0Sstevel@tonic-gate 	if (rec->comment) count = fputs(rec->dataspace, stream);
503*0Sstevel@tonic-gate 	else {
504*0Sstevel@tonic-gate 
505*0Sstevel@tonic-gate 	/*
506*0Sstevel@tonic-gate 	 * Record is a data record
507*0Sstevel@tonic-gate 	 */
508*0Sstevel@tonic-gate 
509*0Sstevel@tonic-gate 	    /* Figure out the amount of space the record needs */
510*0Sstevel@tonic-gate 	    size = (int)strlen(rec->name) + 1;	    /* "name:" */
511*0Sstevel@tonic-gate 	    if ((mem = rec->membership) != NULL)
512*0Sstevel@tonic-gate 		do {	    /* members */
513*0Sstevel@tonic-gate 		    /* "membername " or "membername\n" */
514*0Sstevel@tonic-gate 		    size += (int)strlen(mem->name) + 1;
515*0Sstevel@tonic-gate 		} while ((mem = mem->next) != NULL);	/* Next attr/val */
516*0Sstevel@tonic-gate 	    else
517*0Sstevel@tonic-gate 		size++;		/* Count trailing '\n' if empty grp */
518*0Sstevel@tonic-gate 
519*0Sstevel@tonic-gate 
520*0Sstevel@tonic-gate 	    /* Alloc space for the record */
521*0Sstevel@tonic-gate 	    if (buf = malloc((size_t) size+1)) {
522*0Sstevel@tonic-gate 
523*0Sstevel@tonic-gate 		/* Initializations */
524*0Sstevel@tonic-gate 		p = buf;
525*0Sstevel@tonic-gate 
526*0Sstevel@tonic-gate 		/* Write the device-group name */
527*0Sstevel@tonic-gate 		q = rec->name;
528*0Sstevel@tonic-gate 		while (*q) *p++ = *q++;
529*0Sstevel@tonic-gate 		*p++ = ':';
530*0Sstevel@tonic-gate 
531*0Sstevel@tonic-gate 		/* Write the membership list */
532*0Sstevel@tonic-gate 		if ((mem = rec->membership) != NULL) do {
533*0Sstevel@tonic-gate 		    q = mem->name;
534*0Sstevel@tonic-gate 		    while (*q) *p++ = *q++;
535*0Sstevel@tonic-gate 		    if ((mem = mem->next) != NULL) *p++ = ',';
536*0Sstevel@tonic-gate 		} while (mem);
537*0Sstevel@tonic-gate 
538*0Sstevel@tonic-gate 		/* Terminate the record */
539*0Sstevel@tonic-gate 		*p++ = '\n';
540*0Sstevel@tonic-gate 		*p = '\0';
541*0Sstevel@tonic-gate 
542*0Sstevel@tonic-gate 		/* Write the record */
543*0Sstevel@tonic-gate 		count = fputs(buf, stream);
544*0Sstevel@tonic-gate 		free(buf);
545*0Sstevel@tonic-gate 	    } else
546*0Sstevel@tonic-gate 		count = EOF;  /* malloc() failed */
547*0Sstevel@tonic-gate 	}
548*0Sstevel@tonic-gate 
549*0Sstevel@tonic-gate 	/* Finished */
550*0Sstevel@tonic-gate 	return (count);
551*0Sstevel@tonic-gate }
552*0Sstevel@tonic-gate 
553*0Sstevel@tonic-gate /*
554*0Sstevel@tonic-gate  *  int _adddgrptabrec(dgrp, members)
555*0Sstevel@tonic-gate  *	char   *dgrp
556*0Sstevel@tonic-gate  *	char  **members
557*0Sstevel@tonic-gate  *
558*0Sstevel@tonic-gate  *	If <dgrp> doesn't exist, this function adds a record to the
559*0Sstevel@tonic-gate  *	device-group table for that device-group.  That record will
560*0Sstevel@tonic-gate  *	have the name <dgrp> and will have a membership described in
561*0Sstevel@tonic-gate  *	the list referenced by <members>.  The record is added to the
562*0Sstevel@tonic-gate  *	end of the table.
563*0Sstevel@tonic-gate  *
564*0Sstevel@tonic-gate  *	If <dgrp> already exists in the table, the function adds the
565*0Sstevel@tonic-gate  *	members in the <members> list to the group's membership.
566*0Sstevel@tonic-gate  *
567*0Sstevel@tonic-gate  *  Arguments:
568*0Sstevel@tonic-gate  *	dgrp		The name of the device-group being added to the
569*0Sstevel@tonic-gate  *			device-group table.
570*0Sstevel@tonic-gate  *	members		A pointer to the first item of the list of members
571*0Sstevel@tonic-gate  *			in the device-group being added to the table.
572*0Sstevel@tonic-gate  *			(This value may be (char **) NULL).
573*0Sstevel@tonic-gate  *
574*0Sstevel@tonic-gate  *  Returns:  int
575*0Sstevel@tonic-gate  *	TRUE if successful, FALSE with "errno" set otherwise.
576*0Sstevel@tonic-gate  */
577*0Sstevel@tonic-gate 
578*0Sstevel@tonic-gate int
_adddgrptabrec(char * dgrp,char ** members)579*0Sstevel@tonic-gate _adddgrptabrec(
580*0Sstevel@tonic-gate 	char   *dgrp,			/* Devgrp to add to the table */
581*0Sstevel@tonic-gate 	char  **members)		/* Members for that devgrp */
582*0Sstevel@tonic-gate {
583*0Sstevel@tonic-gate 	/* Automatic data */
584*0Sstevel@tonic-gate 	struct dgrptabent	*ent;		/* Ptr to dev tab entry */
585*0Sstevel@tonic-gate 	struct dgrptabent	*new;		/* Ptr to new dev tab info */
586*0Sstevel@tonic-gate 	struct dgrptabent	*p;		/* Temp ptr to dev tab info */
587*0Sstevel@tonic-gate 	struct member		*pm, *qm, *rm;	/* Tmp ptrs to struct member */
588*0Sstevel@tonic-gate 	FILE			*fd;		/* File descr, temp file */
589*0Sstevel@tonic-gate 	char			*path;		/* Ptr to new devtab name */
590*0Sstevel@tonic-gate 	int			olderrno;	/* Errno on entry */
591*0Sstevel@tonic-gate 	int			noerr;		/* FLAG, TRUE if all's well */
592*0Sstevel@tonic-gate 
593*0Sstevel@tonic-gate 
594*0Sstevel@tonic-gate 	/* Make a structure describing the new information */
595*0Sstevel@tonic-gate 	if ((new = mkdgrptabent(dgrp, members)) == NULL)
596*0Sstevel@tonic-gate 	    return (FALSE);
597*0Sstevel@tonic-gate 
598*0Sstevel@tonic-gate 	/*
599*0Sstevel@tonic-gate 	 * Lock the device-group table.  This only returns if the
600*0Sstevel@tonic-gate 	 * table is locked or some error occurred.  It waits until the
601*0Sstevel@tonic-gate 	 * table is available.
602*0Sstevel@tonic-gate 	 */
603*0Sstevel@tonic-gate 	if (!lkdgrptab("a+", F_WRLCK)) {
604*0Sstevel@tonic-gate 	    _freedgrptabent(new);
605*0Sstevel@tonic-gate 	    return (FALSE);
606*0Sstevel@tonic-gate 	}
607*0Sstevel@tonic-gate 
608*0Sstevel@tonic-gate 	/*
609*0Sstevel@tonic-gate 	 * If the device-group is already in the table, add
610*0Sstevel@tonic-gate 	 * the specified members
611*0Sstevel@tonic-gate 	 */
612*0Sstevel@tonic-gate 
613*0Sstevel@tonic-gate 	noerr = TRUE;
614*0Sstevel@tonic-gate 	olderrno = errno;
615*0Sstevel@tonic-gate 	if (ent = _getdgrprec(dgrp)) {
616*0Sstevel@tonic-gate 
617*0Sstevel@tonic-gate 	    /* Any members to add?  If not, do nothing. */
618*0Sstevel@tonic-gate 	    if (new->membership) {
619*0Sstevel@tonic-gate 
620*0Sstevel@tonic-gate 		/* Any existing members? */
621*0Sstevel@tonic-gate 		if ((pm = ent->membership) != NULL) {
622*0Sstevel@tonic-gate 
623*0Sstevel@tonic-gate 		    /* Find the end of the existing membership list */
624*0Sstevel@tonic-gate 		    while (pm->next) pm = pm->next;
625*0Sstevel@tonic-gate 
626*0Sstevel@tonic-gate 		    /* Append the new members to the membership list */
627*0Sstevel@tonic-gate 		    pm->next = new->membership;
628*0Sstevel@tonic-gate 
629*0Sstevel@tonic-gate 		    /* Remove any duplicates */
630*0Sstevel@tonic-gate 		    for (pm = ent->membership; pm; pm = pm->next) {
631*0Sstevel@tonic-gate 			qm = pm;
632*0Sstevel@tonic-gate 			while ((rm = qm->next) != NULL) {
633*0Sstevel@tonic-gate 			    if (strcmp(pm->name, rm->name) == 0) {
634*0Sstevel@tonic-gate 				qm->next = rm->next;
635*0Sstevel@tonic-gate 				free(rm->name);
636*0Sstevel@tonic-gate 				free(rm);
637*0Sstevel@tonic-gate 			    } else qm = rm;
638*0Sstevel@tonic-gate 			}
639*0Sstevel@tonic-gate 		    }
640*0Sstevel@tonic-gate 		} else ent->membership = new->membership;
641*0Sstevel@tonic-gate 
642*0Sstevel@tonic-gate 		/* No members in the new list any more */
643*0Sstevel@tonic-gate 		new->membership = NULL;
644*0Sstevel@tonic-gate 
645*0Sstevel@tonic-gate 		/*
646*0Sstevel@tonic-gate 		 * Make a new device-group table, replacing the
647*0Sstevel@tonic-gate 		 * record for the specified device-group
648*0Sstevel@tonic-gate 		 */
649*0Sstevel@tonic-gate 
650*0Sstevel@tonic-gate 		_setdgrptab();	/* Rewind existing table */
651*0Sstevel@tonic-gate 
652*0Sstevel@tonic-gate 		/* Open a temp file */
653*0Sstevel@tonic-gate 		if (fd = opennewdgrptab(&path)) {
654*0Sstevel@tonic-gate 
655*0Sstevel@tonic-gate 		    /* While there's more records and no error ... */
656*0Sstevel@tonic-gate 		    while (((p = _getdgrptabent()) != NULL) && noerr) {
657*0Sstevel@tonic-gate 
658*0Sstevel@tonic-gate 			/*
659*0Sstevel@tonic-gate 			 * If this isn't the record we're replacing,
660*0Sstevel@tonic-gate 			 * write it to the temporary file.  Otherwise,
661*0Sstevel@tonic-gate 			 * write the updated record
662*0Sstevel@tonic-gate 			 */
663*0Sstevel@tonic-gate 
664*0Sstevel@tonic-gate 			if (ent->entryno != p->entryno)
665*0Sstevel@tonic-gate 				noerr = _putdgrptabrec(fd, p) != EOF;
666*0Sstevel@tonic-gate 			else noerr = _putdgrptabrec(fd, ent) != EOF;
667*0Sstevel@tonic-gate 			_freedgrptabent(p);
668*0Sstevel@tonic-gate 		    }
669*0Sstevel@tonic-gate 
670*0Sstevel@tonic-gate 		    /* Fix the files */
671*0Sstevel@tonic-gate 		    if (noerr) {
672*0Sstevel@tonic-gate 			(void) fclose(fd);
673*0Sstevel@tonic-gate 			noerr = mknewdgrptab(path);
674*0Sstevel@tonic-gate 		    } else {
675*0Sstevel@tonic-gate 			(void) fclose(fd);
676*0Sstevel@tonic-gate 			(void) rmnewdgrptab(path);
677*0Sstevel@tonic-gate 		    }
678*0Sstevel@tonic-gate 		}   /* if (opennewdgrptab()) */
679*0Sstevel@tonic-gate 
680*0Sstevel@tonic-gate 	    }   /* If there's members to add */
681*0Sstevel@tonic-gate 
682*0Sstevel@tonic-gate 	    /* Free the memory associated with the updated entry */
683*0Sstevel@tonic-gate 	    _freedgrptabent(ent);
684*0Sstevel@tonic-gate 	}
685*0Sstevel@tonic-gate 
686*0Sstevel@tonic-gate 	/*
687*0Sstevel@tonic-gate 	 * Otherwise, add the device-group to the end of the table
688*0Sstevel@tonic-gate 	 */
689*0Sstevel@tonic-gate 
690*0Sstevel@tonic-gate 	else if (errno == EINVAL) {
691*0Sstevel@tonic-gate 	    errno = olderrno;
692*0Sstevel@tonic-gate 	    if (fseek(oam_dgroup, 0, SEEK_END) == 0)
693*0Sstevel@tonic-gate 		noerr = (_putdgrptabrec(oam_dgroup, new) != EOF);
694*0Sstevel@tonic-gate 	} else noerr = FALSE;
695*0Sstevel@tonic-gate 
696*0Sstevel@tonic-gate 	/* Finished */
697*0Sstevel@tonic-gate 	(void) unlkdgrptab();		/* Unlock the file */
698*0Sstevel@tonic-gate 	_freedgrptabent(new);		/* Free the new dgrptab info struct */
699*0Sstevel@tonic-gate 	return (noerr);			/* Return with success indicator */
700*0Sstevel@tonic-gate }
701*0Sstevel@tonic-gate 
702*0Sstevel@tonic-gate /*
703*0Sstevel@tonic-gate  * int _rmdgrptabrec(dgrp)
704*0Sstevel@tonic-gate  *	char   *dgrp
705*0Sstevel@tonic-gate  *
706*0Sstevel@tonic-gate  *	This function removes the record in the device-group table
707*0Sstevel@tonic-gate  *	for the specified device-group.
708*0Sstevel@tonic-gate  *
709*0Sstevel@tonic-gate  *  Arguments:
710*0Sstevel@tonic-gate  *	dgrp	The device-group to be removed
711*0Sstevel@tonic-gate  *
712*0Sstevel@tonic-gate  *  Returns:  int
713*0Sstevel@tonic-gate  *	Success indicator:  TRUE if successful, FALSE with errno set otherwise.
714*0Sstevel@tonic-gate  */
715*0Sstevel@tonic-gate 
716*0Sstevel@tonic-gate int
_rmdgrptabrec(char * dgrp)717*0Sstevel@tonic-gate _rmdgrptabrec(char *dgrp)		/* Device-group to remove */
718*0Sstevel@tonic-gate {
719*0Sstevel@tonic-gate 	/* Automatic data */
720*0Sstevel@tonic-gate 	struct dgrptabent	*ent;	/* Entry to remove */
721*0Sstevel@tonic-gate 	struct dgrptabent	*p;	/* Entry being copied */
722*0Sstevel@tonic-gate 	FILE			*fd;	/* Temp file's file descriptor */
723*0Sstevel@tonic-gate 	char			*path;	/* Pathname of temp file */
724*0Sstevel@tonic-gate 	int			noerr;	/* FLAG, TRUE if all's well */
725*0Sstevel@tonic-gate 
726*0Sstevel@tonic-gate 	noerr = TRUE;
727*0Sstevel@tonic-gate 	if (!lkdgrptab("r", F_WRLCK))
728*0Sstevel@tonic-gate 		return (FALSE);
729*0Sstevel@tonic-gate 	if (ent = _getdgrprec(dgrp)) {
730*0Sstevel@tonic-gate 	    _setdgrptab();
731*0Sstevel@tonic-gate 	    if (fd = opennewdgrptab(&path)) {
732*0Sstevel@tonic-gate 		while (((p = _getdgrptabent()) != NULL) && noerr) {
733*0Sstevel@tonic-gate 		    if (ent->entryno != p->entryno)
734*0Sstevel@tonic-gate 			noerr = _putdgrptabrec(fd, p) != EOF;
735*0Sstevel@tonic-gate 		    _freedgrptabent(p);
736*0Sstevel@tonic-gate 		}
737*0Sstevel@tonic-gate 		if (noerr) {
738*0Sstevel@tonic-gate 		    (void) fclose(fd);
739*0Sstevel@tonic-gate 		    noerr = mknewdgrptab(path);
740*0Sstevel@tonic-gate 		} else {
741*0Sstevel@tonic-gate 		    (void) fclose(fd);
742*0Sstevel@tonic-gate 		    (void) rmnewdgrptab(path);
743*0Sstevel@tonic-gate 		}
744*0Sstevel@tonic-gate 	    } else noerr = FALSE;
745*0Sstevel@tonic-gate 	    _freedgrptabent(ent);
746*0Sstevel@tonic-gate 	} else noerr = FALSE;
747*0Sstevel@tonic-gate 	(void) unlkdgrptab();
748*0Sstevel@tonic-gate 	return (noerr);
749*0Sstevel@tonic-gate }
750*0Sstevel@tonic-gate 
751*0Sstevel@tonic-gate /*
752*0Sstevel@tonic-gate  * int _rmdgrpmems(dgrp, mems, notfounds)
753*0Sstevel@tonic-gate  *	char   *dgrp
754*0Sstevel@tonic-gate  *	char  **mems
755*0Sstevel@tonic-gate  *	char ***notfounds
756*0Sstevel@tonic-gate  *
757*0Sstevel@tonic-gate  *	Remove the specified members from the membership of the specified
758*0Sstevel@tonic-gate  *	device-group.  Any members not found in that device-group are
759*0Sstevel@tonic-gate  *	returned in the list referenced by <notfounds>.
760*0Sstevel@tonic-gate  *
761*0Sstevel@tonic-gate  *  Arguments:
762*0Sstevel@tonic-gate  *	dgrp		The device-group from which members are to be removed
763*0Sstevel@tonic-gate  *	mems		The address of the first element in the list of
764*0Sstevel@tonic-gate  *			members to remove.  This list is terminated by
765*0Sstevel@tonic-gate  *			(char *) NULL.
766*0Sstevel@tonic-gate  *	notfounds	The place to put the address of the list of addresses
767*0Sstevel@tonic-gate  *			referencing the requested members that were not
768*0Sstevel@tonic-gate  *			members of the specified device-group
769*0Sstevel@tonic-gate  *
770*0Sstevel@tonic-gate  *  Returns: int
771*0Sstevel@tonic-gate  *	TRUE if successful, FALSE with errno set otherwise.
772*0Sstevel@tonic-gate  */
773*0Sstevel@tonic-gate 
774*0Sstevel@tonic-gate int
_rmdgrpmems(char * dgrp,char ** mems,char *** notfounds)775*0Sstevel@tonic-gate _rmdgrpmems(
776*0Sstevel@tonic-gate 	char   *dgrp,			/* Device-group to modify */
777*0Sstevel@tonic-gate 	char  **mems,			/* Members to remove */
778*0Sstevel@tonic-gate 	char ***notfounds)		/* Members req'd but not found */
779*0Sstevel@tonic-gate {
780*0Sstevel@tonic-gate 	/* Automatic data */
781*0Sstevel@tonic-gate 	struct dgrptabent	*ent;	/* Entry to modify */
782*0Sstevel@tonic-gate 	struct dgrptabent	*p;	/* Entry being copied */
783*0Sstevel@tonic-gate 	struct member		*pm;	/* Ptr to member being examined */
784*0Sstevel@tonic-gate 	struct member		*prev;	/* Ptr to previous member */
785*0Sstevel@tonic-gate 	char			**nflst; /* Ptr to not-found list */
786*0Sstevel@tonic-gate 	char			**pnf;	/* Ptr into not-found list */
787*0Sstevel@tonic-gate 	char			**pp;	/* Ptr into members-to-rm list */
788*0Sstevel@tonic-gate 	FILE			*fd;	/* Temp file's file descriptor */
789*0Sstevel@tonic-gate 	char			*path;	/* Pathname of temp file */
790*0Sstevel@tonic-gate 	int			noerr;	/* TRUE if all's well */
791*0Sstevel@tonic-gate 	int			found;	/* TRUE if member is in membership */
792*0Sstevel@tonic-gate 	int			i;	/* Temp counter */
793*0Sstevel@tonic-gate 
794*0Sstevel@tonic-gate 	noerr = TRUE;
795*0Sstevel@tonic-gate 
796*0Sstevel@tonic-gate 	/* Lock the device-group table */
797*0Sstevel@tonic-gate 	if (!lkdgrptab("r", F_WRLCK))
798*0Sstevel@tonic-gate 		return (FALSE);
799*0Sstevel@tonic-gate 
800*0Sstevel@tonic-gate 	/* Nothing is "not found" yet */
801*0Sstevel@tonic-gate 	*notfounds = NULL;
802*0Sstevel@tonic-gate 
803*0Sstevel@tonic-gate 	/* Get the entry we're to modify */
804*0Sstevel@tonic-gate 	if (ent = _getdgrprec(dgrp)) {
805*0Sstevel@tonic-gate 
806*0Sstevel@tonic-gate 	    /* Allocate space for the not-found list */
807*0Sstevel@tonic-gate 	    i = 1;
808*0Sstevel@tonic-gate 	    if (mems)
809*0Sstevel@tonic-gate 		for (pp = mems; *pp; pp++)
810*0Sstevel@tonic-gate 			i++;
811*0Sstevel@tonic-gate 	    if (nflst = malloc(i*sizeof (char *))) {
812*0Sstevel@tonic-gate 		pnf = nflst;
813*0Sstevel@tonic-gate 		*pnf = NULL;
814*0Sstevel@tonic-gate 
815*0Sstevel@tonic-gate 		/* For each member to remove ... (if any) */
816*0Sstevel@tonic-gate 		if (mems)
817*0Sstevel@tonic-gate 		    for (pp = mems; *pp; pp++) {
818*0Sstevel@tonic-gate 
819*0Sstevel@tonic-gate 		    found = FALSE;
820*0Sstevel@tonic-gate 
821*0Sstevel@tonic-gate 		    /* Compare against each member in the membership list */
822*0Sstevel@tonic-gate 		    pm = ent->membership;
823*0Sstevel@tonic-gate 		    prev = NULL;
824*0Sstevel@tonic-gate 		    while (pm && !found) {
825*0Sstevel@tonic-gate 
826*0Sstevel@tonic-gate 			if (strcmp(*pp, pm->name) == 0) {
827*0Sstevel@tonic-gate 
828*0Sstevel@tonic-gate 			    /* Found.  Remove from linked list */
829*0Sstevel@tonic-gate 			    if (prev) prev->next = pm->next;
830*0Sstevel@tonic-gate 			    else ent->membership = pm->next;
831*0Sstevel@tonic-gate 			    if (pm->name) free(pm->name);
832*0Sstevel@tonic-gate 			    free(pm);
833*0Sstevel@tonic-gate 			    found = TRUE;
834*0Sstevel@tonic-gate 
835*0Sstevel@tonic-gate 			} else {
836*0Sstevel@tonic-gate 
837*0Sstevel@tonic-gate 			    /* Bump to the next member */
838*0Sstevel@tonic-gate 			    prev = pm;
839*0Sstevel@tonic-gate 			    pm = pm->next;
840*0Sstevel@tonic-gate 
841*0Sstevel@tonic-gate 			}
842*0Sstevel@tonic-gate 
843*0Sstevel@tonic-gate 		    }   /* For each member in the group */
844*0Sstevel@tonic-gate 
845*0Sstevel@tonic-gate 		/*
846*0Sstevel@tonic-gate 		 * If the requested member-to-remove wasn't found,
847*0Sstevel@tonic-gate 		 * add it to the list of not-found members
848*0Sstevel@tonic-gate 		 */
849*0Sstevel@tonic-gate 		    if (!found) {
850*0Sstevel@tonic-gate 			if (*pnf = malloc(strlen(*pp)+1)) {
851*0Sstevel@tonic-gate 			    (void) strcpy(*pnf++, *pp);
852*0Sstevel@tonic-gate 			    *pnf = NULL;
853*0Sstevel@tonic-gate 			} else noerr = FALSE;
854*0Sstevel@tonic-gate 		    }
855*0Sstevel@tonic-gate 
856*0Sstevel@tonic-gate 		}   /* for (each requested member to remove */
857*0Sstevel@tonic-gate 
858*0Sstevel@tonic-gate 		_setdgrptab();		/* Rewind existing table */
859*0Sstevel@tonic-gate 
860*0Sstevel@tonic-gate 		if (fd = opennewdgrptab(&path)) {
861*0Sstevel@tonic-gate 		    while (((p = _getdgrptabent()) != NULL) && noerr) {
862*0Sstevel@tonic-gate 			if (ent->entryno != p->entryno)
863*0Sstevel@tonic-gate 			    noerr = _putdgrptabrec(fd, p) != EOF;
864*0Sstevel@tonic-gate 			else noerr = _putdgrptabrec(fd, ent) != EOF;
865*0Sstevel@tonic-gate 			_freedgrptabent(p);
866*0Sstevel@tonic-gate 		    }
867*0Sstevel@tonic-gate 		    if (noerr) {
868*0Sstevel@tonic-gate 			(void) fclose(fd);
869*0Sstevel@tonic-gate 			noerr = mknewdgrptab(path);
870*0Sstevel@tonic-gate 		    } else {
871*0Sstevel@tonic-gate 			(void) fclose(fd);
872*0Sstevel@tonic-gate 			(void) rmnewdgrptab(path);
873*0Sstevel@tonic-gate 		    }
874*0Sstevel@tonic-gate 		} else noerr = FALSE;   /* if (opennewdgrptab()) */
875*0Sstevel@tonic-gate 
876*0Sstevel@tonic-gate 		/*
877*0Sstevel@tonic-gate 		 * If there was no error but there was requested members
878*0Sstevel@tonic-gate 		 * that weren't found, set the not-found list and the error
879*0Sstevel@tonic-gate 		 * information.  Otherwise, free the not-found list
880*0Sstevel@tonic-gate 		 */
881*0Sstevel@tonic-gate 
882*0Sstevel@tonic-gate 		if (noerr && (pnf != nflst)) {
883*0Sstevel@tonic-gate 		    *notfounds = nflst;
884*0Sstevel@tonic-gate 		    errno = ENODEV;
885*0Sstevel@tonic-gate 		    noerr = FALSE;
886*0Sstevel@tonic-gate 		} else {
887*0Sstevel@tonic-gate 		    for (pnf = nflst; *pnf; pnf++) free(*pnf);
888*0Sstevel@tonic-gate 		    free(nflst);
889*0Sstevel@tonic-gate 		    if (!noerr) *notfounds = NULL;
890*0Sstevel@tonic-gate 		}
891*0Sstevel@tonic-gate 	    } else noerr = FALSE;
892*0Sstevel@tonic-gate 
893*0Sstevel@tonic-gate 	    /* Free the description of the modified device group */
894*0Sstevel@tonic-gate 	    _freedgrptabent(ent);
895*0Sstevel@tonic-gate 
896*0Sstevel@tonic-gate 	} else noerr = FALSE;    /* _getdgrprec() failed */
897*0Sstevel@tonic-gate 
898*0Sstevel@tonic-gate 	/* Unlock the original device-group table */
899*0Sstevel@tonic-gate 	(void) unlkdgrptab();
900*0Sstevel@tonic-gate 	return (noerr);
901*0Sstevel@tonic-gate }
902