xref: /illumos-gate/usr/src/lib/libadm/common/putdgrp.c (revision 4656d474)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate /*
237c478bd9Sstevel@tonic-gate  * Copyright (c) 1996-1997, by Sun Microsystems, Inc.
247c478bd9Sstevel@tonic-gate  * All Rights reserved.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
277c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
287c478bd9Sstevel@tonic-gate 
29*4656d474SGarrett D'Amore /*
30*4656d474SGarrett D'Amore  * Copyright 2010 Nexenta Systems, Inc.  All rights reserved.
31*4656d474SGarrett D'Amore  */
327c478bd9Sstevel@tonic-gate 
337c478bd9Sstevel@tonic-gate /* LINTLIBRARY */
347c478bd9Sstevel@tonic-gate 
357c478bd9Sstevel@tonic-gate /*
367c478bd9Sstevel@tonic-gate  * putdgrp.c
377c478bd9Sstevel@tonic-gate  *
387c478bd9Sstevel@tonic-gate  * Global Definitions:
397c478bd9Sstevel@tonic-gate  *	_putdgrptabrec()	Write a device-group record to a stream
407c478bd9Sstevel@tonic-gate  *	_rmdgrptabrec()		Remove a device-group table record
417c478bd9Sstevel@tonic-gate  *	_rmdgrpmems()		Remove specific members from a device group
427c478bd9Sstevel@tonic-gate  *	_adddgrptabrec()	Add a device-group record to the table
437c478bd9Sstevel@tonic-gate  */
447c478bd9Sstevel@tonic-gate 
457c478bd9Sstevel@tonic-gate /*
467c478bd9Sstevel@tonic-gate  *  G L O B A L   R E F E R E N C E S
477c478bd9Sstevel@tonic-gate  *
487c478bd9Sstevel@tonic-gate  *	Header Files
497c478bd9Sstevel@tonic-gate  *	Externals Referenced
507c478bd9Sstevel@tonic-gate  */
517c478bd9Sstevel@tonic-gate 
527c478bd9Sstevel@tonic-gate /*
537c478bd9Sstevel@tonic-gate  * Header Files
547c478bd9Sstevel@tonic-gate  *	<sys/types.h>		UNIX System Data Types
557c478bd9Sstevel@tonic-gate  *	<stdio.h>		Standard I/O definitions
567c478bd9Sstevel@tonic-gate  *	<fcntl.h>		Definitions for file control
577c478bd9Sstevel@tonic-gate  *	<errno.h>		Error handling definitions
587c478bd9Sstevel@tonic-gate  *	<string.h>		String Handling Definitions
597c478bd9Sstevel@tonic-gate  *	<unistd.h>		Standard UNIX(r) Definitions
607c478bd9Sstevel@tonic-gate  *	<devmgmt.h>		Device Management Definitions
617c478bd9Sstevel@tonic-gate  *	"devtab.h"		Local Device Management Definitions
627c478bd9Sstevel@tonic-gate  */
637c478bd9Sstevel@tonic-gate 
647c478bd9Sstevel@tonic-gate #include	<sys/types.h>
657c478bd9Sstevel@tonic-gate #include	<sys/stat.h>
667c478bd9Sstevel@tonic-gate #include	<stdio.h>
677c478bd9Sstevel@tonic-gate #include	<fcntl.h>
687c478bd9Sstevel@tonic-gate #include	<errno.h>
697c478bd9Sstevel@tonic-gate #include	<string.h>
707c478bd9Sstevel@tonic-gate #include	<unistd.h>
717c478bd9Sstevel@tonic-gate #include	<stdlib.h>
727c478bd9Sstevel@tonic-gate #include	<devmgmt.h>
737c478bd9Sstevel@tonic-gate #include	"devtab.h"
747c478bd9Sstevel@tonic-gate 
757c478bd9Sstevel@tonic-gate /*
767c478bd9Sstevel@tonic-gate  *  L O C A L   D E F I N I T I O N S
777c478bd9Sstevel@tonic-gate  *	TDGTABNM	Name of the temporary device-group table (in the
787c478bd9Sstevel@tonic-gate  *			directory of the existing table)
797c478bd9Sstevel@tonic-gate  */
807c478bd9Sstevel@tonic-gate 
817c478bd9Sstevel@tonic-gate #define	TDGTABNM	"%sdgroup.%6.6d"
827c478bd9Sstevel@tonic-gate 
837c478bd9Sstevel@tonic-gate 
847c478bd9Sstevel@tonic-gate /*
857c478bd9Sstevel@tonic-gate  * Static functions
867c478bd9Sstevel@tonic-gate  *	lkdgrptab	Locks the device-group table
877c478bd9Sstevel@tonic-gate  *	unlkdgrptab	Unlocks the device-group table
887c478bd9Sstevel@tonic-gate  *	mkdgrptabent	Builds a device-group table entry from the alias and the
897c478bd9Sstevel@tonic-gate  *			list of attr=val pairs given
907c478bd9Sstevel@tonic-gate  *	opennewdgrptab	Opens a new device-group table (as a temp file)
917c478bd9Sstevel@tonic-gate  *	mknewdgrptab	Makes the temp device-group table the new dgrptab
927c478bd9Sstevel@tonic-gate  *	rmnewdgrptab	Remove the temporary device-group table and free space
937c478bd9Sstevel@tonic-gate  *			allocated to the filename of that file.
947c478bd9Sstevel@tonic-gate  */
957c478bd9Sstevel@tonic-gate 
967c478bd9Sstevel@tonic-gate static	int			lkdgrptab(char *o_mode, short lktype);
977c478bd9Sstevel@tonic-gate static	int			unlkdgrptab(void);
987c478bd9Sstevel@tonic-gate static	struct dgrptabent	*mkdgrptabent(char *dgroup, char **members);
997c478bd9Sstevel@tonic-gate static	FILE			*opennewdgrptab(char **pname);
1007c478bd9Sstevel@tonic-gate static	int			mknewdgrptab(char *tempname);
1017c478bd9Sstevel@tonic-gate static	int			rmnewdgrptab(char *tempname);
1027c478bd9Sstevel@tonic-gate 
1037c478bd9Sstevel@tonic-gate /*
1047c478bd9Sstevel@tonic-gate  * FILE *opennewdgrptab(pname)
1057c478bd9Sstevel@tonic-gate  *	char   **pname
1067c478bd9Sstevel@tonic-gate  *
1077c478bd9Sstevel@tonic-gate  *	Generates a temporary device-group table name from the existing
1087c478bd9Sstevel@tonic-gate  *	device-group table name (in the same directory) and opens that
1097c478bd9Sstevel@tonic-gate  *	file for writing.  It puts a pointer to the malloc()ed space
1107c478bd9Sstevel@tonic-gate  *	containing the temp device-group table's name at the place
1117c478bd9Sstevel@tonic-gate  *	referenced by <pname>.
1127c478bd9Sstevel@tonic-gate  *
1137c478bd9Sstevel@tonic-gate  *  Arguments:
1147c478bd9Sstevel@tonic-gate  *	pname	Pointer to the char * to contain the address of the name
1157c478bd9Sstevel@tonic-gate  *		of the temporary file
1167c478bd9Sstevel@tonic-gate  *
1177c478bd9Sstevel@tonic-gate  *  Returns:  FILE *
1187c478bd9Sstevel@tonic-gate  *	A pointer to the opened stream or (FILE *) NULL if an error occurred.
1197c478bd9Sstevel@tonic-gate  *	If an error occurred, "errno" will be set to reflect the problem.
1207c478bd9Sstevel@tonic-gate  */
1217c478bd9Sstevel@tonic-gate 
1227c478bd9Sstevel@tonic-gate static FILE *
opennewdgrptab(char ** pname)1237c478bd9Sstevel@tonic-gate opennewdgrptab(char **pname)	 /* A(ptr to temp filename's path) */
1247c478bd9Sstevel@tonic-gate {
1257c478bd9Sstevel@tonic-gate 	char   *oldname;		/* Ptr to the dgrptab name */
1267c478bd9Sstevel@tonic-gate 	char   *buf;			/* Ptr to the temp file's name */
1277c478bd9Sstevel@tonic-gate 	char   *dirname;		/* Directory containing dgrptab */
1287c478bd9Sstevel@tonic-gate 	char   *p;			/* Ptr to last '/' in dgrptab name */
1297c478bd9Sstevel@tonic-gate 	int    fd;			/* Opened file descriptor */
1307c478bd9Sstevel@tonic-gate 	FILE   *fp;			/* Opened file pointer */
1317c478bd9Sstevel@tonic-gate 	struct stat64	sbuf;		/* stat buf for old dgrptab file */
1327c478bd9Sstevel@tonic-gate 
1337c478bd9Sstevel@tonic-gate 
1347c478bd9Sstevel@tonic-gate 	/* Initializations */
1357c478bd9Sstevel@tonic-gate 	fp = NULL;
1367c478bd9Sstevel@tonic-gate 
1377c478bd9Sstevel@tonic-gate 	/* Get the name of the device-group table */
1387c478bd9Sstevel@tonic-gate 	if (oldname = _dgrptabpath()) {
139*4656d474SGarrett D'Amore 		/*
140*4656d474SGarrett D'Amore 		 * It is possible for us to have sufficient
141*4656d474SGarrett D'Amore 		 * permissions to create the new file without having
142*4656d474SGarrett D'Amore 		 * sufficient permissions to write the original
143*4656d474SGarrett D'Amore 		 * dgrptab file.  For consistency with the operations
144*4656d474SGarrett D'Amore 		 * which modify the original file by writing it
145*4656d474SGarrett D'Amore 		 * directly we require write permissions for the
146*4656d474SGarrett D'Amore 		 * original file in order to make a new one.
147*4656d474SGarrett D'Amore 		 */
148*4656d474SGarrett D'Amore 		if ((fd = open(oldname, O_WRONLY)) == -1)
149*4656d474SGarrett D'Amore 			return (NULL);
1507c478bd9Sstevel@tonic-gate 
151*4656d474SGarrett D'Amore 		if (fstat64(fd, &sbuf) == -1) {
152*4656d474SGarrett D'Amore 			(void) close(fd);
153*4656d474SGarrett D'Amore 			return (NULL);
154*4656d474SGarrett D'Amore 		}
1557c478bd9Sstevel@tonic-gate 		(void) close(fd);
1567c478bd9Sstevel@tonic-gate 
157*4656d474SGarrett D'Amore 		/* Get the directory that the device-group table lives in */
158*4656d474SGarrett D'Amore 		if (p = strrchr(oldname, '/')) {
159*4656d474SGarrett D'Amore 			*(p+1) = '\0';
160*4656d474SGarrett D'Amore 			dirname = oldname;
161*4656d474SGarrett D'Amore 		} else
162*4656d474SGarrett D'Amore 			dirname = "./";
163*4656d474SGarrett D'Amore 
164*4656d474SGarrett D'Amore 		/* Get space for the temp dgrptab pathname */
165*4656d474SGarrett D'Amore 		if (asprintf(&buf, TDGTABNM, dirname, getpid()) >= 0) {
166*4656d474SGarrett D'Amore 			/*
167*4656d474SGarrett D'Amore 			 * Build the name of the temp dgrptab and open
168*4656d474SGarrett D'Amore 			 * the file.  We must reset the owner, group
169*4656d474SGarrett D'Amore 			 * and perms to those of the original dgrptab
170*4656d474SGarrett D'Amore 			 * file.
171*4656d474SGarrett D'Amore 			 */
172*4656d474SGarrett D'Amore 			if (fp = fopen(buf, "w")) {
173*4656d474SGarrett D'Amore 				*pname = buf;
174*4656d474SGarrett D'Amore 				(void) fchmod(fileno(fp), sbuf.st_mode & 0777);
175*4656d474SGarrett D'Amore 				(void) fchown(fileno(fp), sbuf.st_uid,
176*4656d474SGarrett D'Amore 				    sbuf.st_gid);
177*4656d474SGarrett D'Amore 			} else {
178*4656d474SGarrett D'Amore 				free(buf);
179*4656d474SGarrett D'Amore 			}
1807c478bd9Sstevel@tonic-gate 		}
1817c478bd9Sstevel@tonic-gate 
182*4656d474SGarrett D'Amore 		/* Free the space containing the dgrptab's name */
183*4656d474SGarrett D'Amore 		free(oldname);
1847c478bd9Sstevel@tonic-gate 	}
1857c478bd9Sstevel@tonic-gate 
1867c478bd9Sstevel@tonic-gate 	/* Finished.  Return what we've got */
1877c478bd9Sstevel@tonic-gate 	return (fp);
1887c478bd9Sstevel@tonic-gate }
1897c478bd9Sstevel@tonic-gate 
1907c478bd9Sstevel@tonic-gate /*
1917c478bd9Sstevel@tonic-gate  *  int rmnewdgrptab(tempname)
1927c478bd9Sstevel@tonic-gate  *	char   *tempname
1937c478bd9Sstevel@tonic-gate  *
1947c478bd9Sstevel@tonic-gate  *	Unlink the temp dgrptab and free the memory allocated to
1957c478bd9Sstevel@tonic-gate  *	contain the name of that file
1967c478bd9Sstevel@tonic-gate  *
1977c478bd9Sstevel@tonic-gate  *  Arguments:
1987c478bd9Sstevel@tonic-gate  *	tempname	Name of the temporary file
1997c478bd9Sstevel@tonic-gate  *
2007c478bd9Sstevel@tonic-gate  *  Returns: int
2017c478bd9Sstevel@tonic-gate  *	TRUE if successful, FALSE otherwise
2027c478bd9Sstevel@tonic-gate  */
2037c478bd9Sstevel@tonic-gate 
2047c478bd9Sstevel@tonic-gate static int
rmnewdgrptab(char * tempname)2057c478bd9Sstevel@tonic-gate rmnewdgrptab(char *tempname)
2067c478bd9Sstevel@tonic-gate {
2077c478bd9Sstevel@tonic-gate 	/* Automatic data */
2087c478bd9Sstevel@tonic-gate 	int	noerr;
2097c478bd9Sstevel@tonic-gate 
2107c478bd9Sstevel@tonic-gate 	/* Unlink the temporary file */
2117c478bd9Sstevel@tonic-gate 	noerr = (unlink(tempname) == 0);
2127c478bd9Sstevel@tonic-gate 	free(tempname);
2137c478bd9Sstevel@tonic-gate 
2147c478bd9Sstevel@tonic-gate 	/* Finished */
2157c478bd9Sstevel@tonic-gate 	return (noerr);
2167c478bd9Sstevel@tonic-gate }
2177c478bd9Sstevel@tonic-gate 
2187c478bd9Sstevel@tonic-gate /*
2197c478bd9Sstevel@tonic-gate  *  int mknewdgrptab(tempname)
2207c478bd9Sstevel@tonic-gate  *	char   *tempname
2217c478bd9Sstevel@tonic-gate  *
2227c478bd9Sstevel@tonic-gate  *	Make the temporary device-group table the new system
2237c478bd9Sstevel@tonic-gate  *	device-group table
2247c478bd9Sstevel@tonic-gate  *
2257c478bd9Sstevel@tonic-gate  *  Arguments:
2267c478bd9Sstevel@tonic-gate  *	tempname	Name of the temporary file
2277c478bd9Sstevel@tonic-gate  *
2287c478bd9Sstevel@tonic-gate  *  Returns:  int
2297c478bd9Sstevel@tonic-gate  *	TRUE if successful, FALSE otherwise
2307c478bd9Sstevel@tonic-gate  *
2317c478bd9Sstevel@tonic-gate  *  Notes:
2327c478bd9Sstevel@tonic-gate  *	- Need to use rename() someday instead of link()/unlink()
2337c478bd9Sstevel@tonic-gate  *	- This code is somewhat ineffecient in that asks for the name
2347c478bd9Sstevel@tonic-gate  *	  of the device-group table more than once.  Done so that we don't
2357c478bd9Sstevel@tonic-gate  *	  have to manage that space, but this may be somewhat lazy.
2367c478bd9Sstevel@tonic-gate  */
2377c478bd9Sstevel@tonic-gate 
2387c478bd9Sstevel@tonic-gate static int
mknewdgrptab(char * tempname)2397c478bd9Sstevel@tonic-gate mknewdgrptab(char *tempname)		/* Ptr to name of temp dgrp tab */
2407c478bd9Sstevel@tonic-gate {
2417c478bd9Sstevel@tonic-gate 	char   *dgrpname;		/* Ptr to the dgrptab's name */
2427c478bd9Sstevel@tonic-gate 	int	noerr;			/* FLAG, TRUE if all's well */
2437c478bd9Sstevel@tonic-gate 
2447c478bd9Sstevel@tonic-gate 	/* Get the dgrptab's pathname */
2457c478bd9Sstevel@tonic-gate 	if (dgrpname = _dgrptabpath()) {
2467c478bd9Sstevel@tonic-gate 
247*4656d474SGarrett D'Amore 		/* Unlink the existing file */
248*4656d474SGarrett D'Amore 		if (unlink(dgrpname) == 0) {
2497c478bd9Sstevel@tonic-gate 
250*4656d474SGarrett D'Amore 			/* Make the temp file the real device-group table */
251*4656d474SGarrett D'Amore 			noerr = (link(tempname, dgrpname) == 0) ? TRUE : FALSE;
2527c478bd9Sstevel@tonic-gate 
253*4656d474SGarrett D'Amore 			/* Remove the temp file */
254*4656d474SGarrett D'Amore 			if (noerr)
255*4656d474SGarrett D'Amore 				noerr = rmnewdgrptab(tempname);
2567c478bd9Sstevel@tonic-gate 
257*4656d474SGarrett D'Amore 		} else {
258*4656d474SGarrett D'Amore 			noerr = FALSE;	/* unlink() failed */
259*4656d474SGarrett D'Amore 		}
2607c478bd9Sstevel@tonic-gate 
261*4656d474SGarrett D'Amore 		/* Free the dgrptab's name */
262*4656d474SGarrett D'Amore 		free(dgrpname);
2637c478bd9Sstevel@tonic-gate 
264*4656d474SGarrett D'Amore 	} else {
265*4656d474SGarrett D'Amore 		noerr = FALSE; 	/* dgrptabpath() failed */
266*4656d474SGarrett D'Amore 	}
2677c478bd9Sstevel@tonic-gate 
2687c478bd9Sstevel@tonic-gate 	/* Finished.  Return success indicator */
2697c478bd9Sstevel@tonic-gate 	return (noerr);
2707c478bd9Sstevel@tonic-gate }
2717c478bd9Sstevel@tonic-gate 
2727c478bd9Sstevel@tonic-gate /*
2737c478bd9Sstevel@tonic-gate  * int lkdgrptab(o_mode, lktype)
2747c478bd9Sstevel@tonic-gate  *	char   *o_mode
2757c478bd9Sstevel@tonic-gate  *	short	lktype
2767c478bd9Sstevel@tonic-gate  *
2777c478bd9Sstevel@tonic-gate  *	Lock the device-group table for writing.  If it isn't available, it
2787c478bd9Sstevel@tonic-gate  *	waits until it is.
2797c478bd9Sstevel@tonic-gate  *
2807c478bd9Sstevel@tonic-gate  *  Arguments:
2817c478bd9Sstevel@tonic-gate  *	o_mode	The open() mode to use when opening the device-group table
2827c478bd9Sstevel@tonic-gate  *	lktype	The type of lock to apply
2837c478bd9Sstevel@tonic-gate  *
2847c478bd9Sstevel@tonic-gate  *  Returns:  int
2857c478bd9Sstevel@tonic-gate  *	TRUE if successful, FALSE with errno set otherwise
2867c478bd9Sstevel@tonic-gate  */
2877c478bd9Sstevel@tonic-gate 
2887c478bd9Sstevel@tonic-gate static int
lkdgrptab(char * o_mode,short lktype)2897c478bd9Sstevel@tonic-gate lkdgrptab(
2907c478bd9Sstevel@tonic-gate 	char   *o_mode,				/* Open mode */
2917c478bd9Sstevel@tonic-gate 	short	lktype)				/* Lock type */
2927c478bd9Sstevel@tonic-gate {
2937c478bd9Sstevel@tonic-gate 	/* Automatic data */
2947c478bd9Sstevel@tonic-gate 	struct flock	lockinfo;		/* File locking structure */
2957c478bd9Sstevel@tonic-gate 	int		noerr;			/* FLAG, TRUE if no error */
2967c478bd9Sstevel@tonic-gate 	int		olderrno;		/* Former value of errno */
2977c478bd9Sstevel@tonic-gate 
2987c478bd9Sstevel@tonic-gate 
2997c478bd9Sstevel@tonic-gate 	/* Close the device-group table (if it's open) */
3007c478bd9Sstevel@tonic-gate 	_enddgrptab();
3017c478bd9Sstevel@tonic-gate 
3027c478bd9Sstevel@tonic-gate 	/* Open the device-group table for read/append */
3037c478bd9Sstevel@tonic-gate 	noerr = TRUE;
3047c478bd9Sstevel@tonic-gate 	if (_opendgrptab(o_mode)) {
3057c478bd9Sstevel@tonic-gate 
3067c478bd9Sstevel@tonic-gate 		/*
307*4656d474SGarrett D'Amore 		 * Lock the device-group table (for writing).  If it's not
308*4656d474SGarrett D'Amore 		 * available, wait until it is, then close and open the
309*4656d474SGarrett D'Amore 		 * table (modify and delete change the table!) and try
310*4656d474SGarrett D'Amore 		 * to lock it again
3117c478bd9Sstevel@tonic-gate 		 */
3127c478bd9Sstevel@tonic-gate 
313*4656d474SGarrett D'Amore 		/* Build the locking structure */
314*4656d474SGarrett D'Amore 		lockinfo.l_type = lktype;
315*4656d474SGarrett D'Amore 		lockinfo.l_whence = 0;
316*4656d474SGarrett D'Amore 		lockinfo.l_start = 0L;
317*4656d474SGarrett D'Amore 		lockinfo.l_len = 0L;
318*4656d474SGarrett D'Amore 		olderrno = errno;
319*4656d474SGarrett D'Amore 
320*4656d474SGarrett D'Amore 		/* Keep on going until we lock the file or an error happens */
321*4656d474SGarrett D'Amore 		while ((fcntl(fileno(oam_dgroup), F_SETLK, &lockinfo) == -1) &&
322*4656d474SGarrett D'Amore 		    !noerr) {
323*4656d474SGarrett D'Amore 
324*4656d474SGarrett D'Amore 			/*
325*4656d474SGarrett D'Amore 			 * fcntl() failed.  If errno=EACCES, it's
326*4656d474SGarrett D'Amore 			 * because the file's locked by someone else.
327*4656d474SGarrett D'Amore 			 * Wait for the file to be unlocked, then
328*4656d474SGarrett D'Amore 			 * close and reopen the file and try the lock
329*4656d474SGarrett D'Amore 			 * again.
330*4656d474SGarrett D'Amore 			 */
331*4656d474SGarrett D'Amore 
332*4656d474SGarrett D'Amore 			if (errno == EACCES) {
333*4656d474SGarrett D'Amore 				if (fcntl(fileno(oam_dgroup), F_SETLKW,
334*4656d474SGarrett D'Amore 				    &lockinfo) == -1)
335*4656d474SGarrett D'Amore 					noerr = FALSE;
336*4656d474SGarrett D'Amore 				else {
337*4656d474SGarrett D'Amore 					_enddgrptab();
338*4656d474SGarrett D'Amore 					if (!_opendgrptab(o_mode))
339*4656d474SGarrett D'Amore 						noerr = FALSE;
340*4656d474SGarrett D'Amore 					else
341*4656d474SGarrett D'Amore 						errno = olderrno;
342*4656d474SGarrett D'Amore 				}
343*4656d474SGarrett D'Amore 
344*4656d474SGarrett D'Amore 			} else
345*4656d474SGarrett D'Amore 				noerr = FALSE;  /* fcntl() failed hard */
346*4656d474SGarrett D'Amore 
347*4656d474SGarrett D'Amore 		}   /* End while (fcntl() && !noerr) */
348*4656d474SGarrett D'Amore 
349*4656d474SGarrett D'Amore 		/* Don't keep file open if an error happened */
350*4656d474SGarrett D'Amore 		if (!noerr) _enddgrptab();
351*4656d474SGarrett D'Amore 
352*4656d474SGarrett D'Amore 	} else
353*4656d474SGarrett D'Amore 		noerr = FALSE;	/* _opendgrptab() failed */
3547c478bd9Sstevel@tonic-gate 
3557c478bd9Sstevel@tonic-gate 	/* Done */
3567c478bd9Sstevel@tonic-gate 	return (noerr);
3577c478bd9Sstevel@tonic-gate }
3587c478bd9Sstevel@tonic-gate 
3597c478bd9Sstevel@tonic-gate /*
3607c478bd9Sstevel@tonic-gate  * int unlkdgrptab()
3617c478bd9Sstevel@tonic-gate  *
3627c478bd9Sstevel@tonic-gate  *	Unlock the locked device-group table.
3637c478bd9Sstevel@tonic-gate  *
3647c478bd9Sstevel@tonic-gate  *  Arguments:  None
3657c478bd9Sstevel@tonic-gate  *
3667c478bd9Sstevel@tonic-gate  *  Returns:  int
3677c478bd9Sstevel@tonic-gate  *	Whatever fcntl() returns...
3687c478bd9Sstevel@tonic-gate  */
3697c478bd9Sstevel@tonic-gate 
3707c478bd9Sstevel@tonic-gate static int
unlkdgrptab(void)3717c478bd9Sstevel@tonic-gate unlkdgrptab(void)
3727c478bd9Sstevel@tonic-gate {
3737c478bd9Sstevel@tonic-gate 	/* Automatic data */
3747c478bd9Sstevel@tonic-gate 	struct flock	lockinfo;		/* Locking structure */
3757c478bd9Sstevel@tonic-gate 	int		noerr;			/* FLAG, TRUE if all's well */
3767c478bd9Sstevel@tonic-gate 
3777c478bd9Sstevel@tonic-gate 	/* Build the locking structure */
3787c478bd9Sstevel@tonic-gate 	lockinfo.l_type = F_UNLCK;		/* Lock type */
3797c478bd9Sstevel@tonic-gate 	lockinfo.l_whence = 0;			/* Count from top of file */
3807c478bd9Sstevel@tonic-gate 	lockinfo.l_start = 0L;			/* From beginning */
3817c478bd9Sstevel@tonic-gate 	lockinfo.l_len = 0L;			/* Length of locked data */
3827c478bd9Sstevel@tonic-gate 
3837c478bd9Sstevel@tonic-gate 	/* Unlock it */
3847c478bd9Sstevel@tonic-gate 	noerr = (fcntl(fileno(oam_dgroup), F_SETLK, &lockinfo) != -1);
3857c478bd9Sstevel@tonic-gate 	_enddgrptab();
3867c478bd9Sstevel@tonic-gate 
3877c478bd9Sstevel@tonic-gate 	/* Finished */
3887c478bd9Sstevel@tonic-gate 	return (noerr);
3897c478bd9Sstevel@tonic-gate }
3907c478bd9Sstevel@tonic-gate 
3917c478bd9Sstevel@tonic-gate /*
3927c478bd9Sstevel@tonic-gate  * struct dgrptabent *mkdgrptabent(dgroup, members)
3937c478bd9Sstevel@tonic-gate  *	char   *dgroup
3947c478bd9Sstevel@tonic-gate  *	char  **members
3957c478bd9Sstevel@tonic-gate  *
3967c478bd9Sstevel@tonic-gate  *	This function builds a struct dgrptabent structure describing the
3977c478bd9Sstevel@tonic-gate  *	device-group <dgroup> so that it contains the members in the
3987c478bd9Sstevel@tonic-gate  *	membership list <members>.
3997c478bd9Sstevel@tonic-gate  *
4007c478bd9Sstevel@tonic-gate  *  Arguments:
4017c478bd9Sstevel@tonic-gate  *	dgroup		The device-group being added to the device-group table
4027c478bd9Sstevel@tonic-gate  *	members		The members of the device-group
4037c478bd9Sstevel@tonic-gate  *
4047c478bd9Sstevel@tonic-gate  *  Returns:  struct dgrptabent *
4057c478bd9Sstevel@tonic-gate  *	A completed struct dgrptabent structure containing the description
4067c478bd9Sstevel@tonic-gate  *	of the device group.  The structure, and all of the data in the
4077c478bd9Sstevel@tonic-gate  *	structure are each in space allocated using the malloc() function
4087c478bd9Sstevel@tonic-gate  *	and should be freed using the free() function (or the _freedgrptabent()
4097c478bd9Sstevel@tonic-gate  *	function.
4107c478bd9Sstevel@tonic-gate  */
4117c478bd9Sstevel@tonic-gate 
4127c478bd9Sstevel@tonic-gate static struct dgrptabent *
mkdgrptabent(char * dgroup,char ** members)4137c478bd9Sstevel@tonic-gate mkdgrptabent(
4147c478bd9Sstevel@tonic-gate 	char   *dgroup,		/* Device-group being created (or modified) */
4157c478bd9Sstevel@tonic-gate 	char  **members)	/* Members to add to that entry */
4167c478bd9Sstevel@tonic-gate {
4177c478bd9Sstevel@tonic-gate 	/* Automatic data */
4187c478bd9Sstevel@tonic-gate 	struct dgrptabent	*ent;	/* Ptr to struct we're making */
4197c478bd9Sstevel@tonic-gate 	struct member		*prev;	/* Ptr to prev attr/val struct */
4207c478bd9Sstevel@tonic-gate 	struct member		*member;	/* Ptr to current struct */
4217c478bd9Sstevel@tonic-gate 	char			**pp;	/* Ptr into list of ptrs */
4227c478bd9Sstevel@tonic-gate 	int			noerr;	/* TRUE if all's well */
4237c478bd9Sstevel@tonic-gate 
4247c478bd9Sstevel@tonic-gate 
4257c478bd9Sstevel@tonic-gate 	/* No problems (yet) */
4267c478bd9Sstevel@tonic-gate 	noerr = TRUE;
4277c478bd9Sstevel@tonic-gate 
4287c478bd9Sstevel@tonic-gate 	/* Get space for the structure */
4297c478bd9Sstevel@tonic-gate 	if (ent = malloc(sizeof (struct dgrptabent))) {
4307c478bd9Sstevel@tonic-gate 
4317c478bd9Sstevel@tonic-gate 	    /* Fill in default values */
4327c478bd9Sstevel@tonic-gate 	    ent->name = NULL; 				/* alias */
4337c478bd9Sstevel@tonic-gate 	    ent->entryno = 0;				/* Entry no. */
4347c478bd9Sstevel@tonic-gate 	    ent->comment = FALSE;			/* data rec */
4357c478bd9Sstevel@tonic-gate 	    ent->dataspace = NULL;			/* string */
4367c478bd9Sstevel@tonic-gate 	    ent->membership = NULL;			/* attr list */
4377c478bd9Sstevel@tonic-gate 
4387c478bd9Sstevel@tonic-gate 	    /* Fill in the device-group name */
4397c478bd9Sstevel@tonic-gate 	    if (ent->name = malloc(strlen(dgroup)+1)) {
4407c478bd9Sstevel@tonic-gate 		(void) strcpy(ent->name, dgroup);
4417c478bd9Sstevel@tonic-gate 
4427c478bd9Sstevel@tonic-gate 		/* Add membership to the structure */
4437c478bd9Sstevel@tonic-gate 		prev = NULL;
4447c478bd9Sstevel@tonic-gate 		if ((pp = members) != NULL)
4457c478bd9Sstevel@tonic-gate 		    while (*pp && noerr) {
4467c478bd9Sstevel@tonic-gate 
4477c478bd9Sstevel@tonic-gate 		    if (member = malloc(sizeof (struct member))) {
4487c478bd9Sstevel@tonic-gate 
4497c478bd9Sstevel@tonic-gate 			if (member->name = malloc(strlen(*pp)+1)) {
4507c478bd9Sstevel@tonic-gate 			    (void) strcpy(member->name, *pp);
4517c478bd9Sstevel@tonic-gate 			    if (prev) prev->next = member;
4527c478bd9Sstevel@tonic-gate 			    else ent->membership = member;
4537c478bd9Sstevel@tonic-gate 			    member->next = NULL;
4547c478bd9Sstevel@tonic-gate 			    prev = member;
4557c478bd9Sstevel@tonic-gate 			} else {
4567c478bd9Sstevel@tonic-gate 			    noerr = FALSE;
4577c478bd9Sstevel@tonic-gate 			    free(member);
4587c478bd9Sstevel@tonic-gate 			}
4597c478bd9Sstevel@tonic-gate 		    } else noerr = FALSE;
4607c478bd9Sstevel@tonic-gate 		    pp++;
4617c478bd9Sstevel@tonic-gate 		}   /* End membership processing loop */
4627c478bd9Sstevel@tonic-gate 
4637c478bd9Sstevel@tonic-gate 	    } else noerr = FALSE;	/* malloc() failed */
4647c478bd9Sstevel@tonic-gate 
4657c478bd9Sstevel@tonic-gate 		/*
4667c478bd9Sstevel@tonic-gate 		 * If there was a problem, clean up the mess we've made
4677c478bd9Sstevel@tonic-gate 		 */
4687c478bd9Sstevel@tonic-gate 
4697c478bd9Sstevel@tonic-gate 	    if (!noerr) {
4707c478bd9Sstevel@tonic-gate 
4717c478bd9Sstevel@tonic-gate 		_freedgrptabent(ent);
4727c478bd9Sstevel@tonic-gate 		ent = NULL;
4737c478bd9Sstevel@tonic-gate 
4747c478bd9Sstevel@tonic-gate 	    }   /* if (noerr) */
4757c478bd9Sstevel@tonic-gate 
4767c478bd9Sstevel@tonic-gate 	} else noerr = FALSE;   /* if (malloc(dgrptabent space)) */
4777c478bd9Sstevel@tonic-gate 
4787c478bd9Sstevel@tonic-gate 	/* Finished */
4797c478bd9Sstevel@tonic-gate 	return (ent);
4807c478bd9Sstevel@tonic-gate }
4817c478bd9Sstevel@tonic-gate 
4827c478bd9Sstevel@tonic-gate /*
4837c478bd9Sstevel@tonic-gate  * int _putdgrptabrec(stream, rec)
4847c478bd9Sstevel@tonic-gate  *	FILE		       *stream
4857c478bd9Sstevel@tonic-gate  *	struct dgrptabent      *rec
4867c478bd9Sstevel@tonic-gate  *
4877c478bd9Sstevel@tonic-gate  *	Write a device-group table record containing the information in the
4887c478bd9Sstevel@tonic-gate  *	struct dgrptab structure <rec> to the current position of the
4897c478bd9Sstevel@tonic-gate  *	standard I/O stream <stream>.
4907c478bd9Sstevel@tonic-gate  *
4917c478bd9Sstevel@tonic-gate  *  Arguments:
4927c478bd9Sstevel@tonic-gate  *	stream		The stream to write to
4937c478bd9Sstevel@tonic-gate  *	rec		The structure containing the information to write
4947c478bd9Sstevel@tonic-gate  *
4957c478bd9Sstevel@tonic-gate  *  Returns:  int
4967c478bd9Sstevel@tonic-gate  *	The number of characters written or EOF if there was some error.
4977c478bd9Sstevel@tonic-gate  */
4987c478bd9Sstevel@tonic-gate 
4997c478bd9Sstevel@tonic-gate int
_putdgrptabrec(FILE * stream,struct dgrptabent * rec)5007c478bd9Sstevel@tonic-gate _putdgrptabrec(
5017c478bd9Sstevel@tonic-gate 	FILE			*stream,	/* Stream to write to */
5027c478bd9Sstevel@tonic-gate 	struct dgrptabent	*rec)		/* Record to write */
5037c478bd9Sstevel@tonic-gate {
5047c478bd9Sstevel@tonic-gate 	/* Automatic Data */
5057c478bd9Sstevel@tonic-gate 	struct member		*mem;		/* Ptr to attr/val pair */
5067c478bd9Sstevel@tonic-gate 	char			*buf;		/* Allocated buffer */
5077c478bd9Sstevel@tonic-gate 	char			*p;		/* Temp char pointer */
5087c478bd9Sstevel@tonic-gate 	char			*q;		/* Temp char pointer */
5097c478bd9Sstevel@tonic-gate 	int			count;		/* Number of chars written */
5107c478bd9Sstevel@tonic-gate 	int			size;		/* Size of needed buffer */
5117c478bd9Sstevel@tonic-gate 
5127c478bd9Sstevel@tonic-gate 
5137c478bd9Sstevel@tonic-gate 	/* Comment or data record? */
514*4656d474SGarrett D'Amore 	if (rec->comment)
515*4656d474SGarrett D'Amore 		count = fputs(rec->dataspace, stream);
5167c478bd9Sstevel@tonic-gate 	else {
5177c478bd9Sstevel@tonic-gate 
5187c478bd9Sstevel@tonic-gate 	/*
5197c478bd9Sstevel@tonic-gate 	 * Record is a data record
5207c478bd9Sstevel@tonic-gate 	 */
5217c478bd9Sstevel@tonic-gate 
5227c478bd9Sstevel@tonic-gate 	    /* Figure out the amount of space the record needs */
5237c478bd9Sstevel@tonic-gate 	    size = (int)strlen(rec->name) + 1;	    /* "name:" */
5247c478bd9Sstevel@tonic-gate 	    if ((mem = rec->membership) != NULL)
5257c478bd9Sstevel@tonic-gate 		do {	    /* members */
5267c478bd9Sstevel@tonic-gate 		    /* "membername " or "membername\n" */
5277c478bd9Sstevel@tonic-gate 		    size += (int)strlen(mem->name) + 1;
5287c478bd9Sstevel@tonic-gate 		} while ((mem = mem->next) != NULL);	/* Next attr/val */
5297c478bd9Sstevel@tonic-gate 	    else
5307c478bd9Sstevel@tonic-gate 		size++;		/* Count trailing '\n' if empty grp */
5317c478bd9Sstevel@tonic-gate 
5327c478bd9Sstevel@tonic-gate 
5337c478bd9Sstevel@tonic-gate 	    /* Alloc space for the record */
5347c478bd9Sstevel@tonic-gate 	    if (buf = malloc((size_t) size+1)) {
5357c478bd9Sstevel@tonic-gate 
5367c478bd9Sstevel@tonic-gate 		/* Initializations */
5377c478bd9Sstevel@tonic-gate 		p = buf;
5387c478bd9Sstevel@tonic-gate 
5397c478bd9Sstevel@tonic-gate 		/* Write the device-group name */
5407c478bd9Sstevel@tonic-gate 		q = rec->name;
5417c478bd9Sstevel@tonic-gate 		while (*q) *p++ = *q++;
5427c478bd9Sstevel@tonic-gate 		*p++ = ':';
5437c478bd9Sstevel@tonic-gate 
5447c478bd9Sstevel@tonic-gate 		/* Write the membership list */
5457c478bd9Sstevel@tonic-gate 		if ((mem = rec->membership) != NULL) do {
5467c478bd9Sstevel@tonic-gate 		    q = mem->name;
5477c478bd9Sstevel@tonic-gate 		    while (*q) *p++ = *q++;
5487c478bd9Sstevel@tonic-gate 		    if ((mem = mem->next) != NULL) *p++ = ',';
5497c478bd9Sstevel@tonic-gate 		} while (mem);
5507c478bd9Sstevel@tonic-gate 
5517c478bd9Sstevel@tonic-gate 		/* Terminate the record */
5527c478bd9Sstevel@tonic-gate 		*p++ = '\n';
5537c478bd9Sstevel@tonic-gate 		*p = '\0';
5547c478bd9Sstevel@tonic-gate 
5557c478bd9Sstevel@tonic-gate 		/* Write the record */
5567c478bd9Sstevel@tonic-gate 		count = fputs(buf, stream);
5577c478bd9Sstevel@tonic-gate 		free(buf);
5587c478bd9Sstevel@tonic-gate 	    } else
5597c478bd9Sstevel@tonic-gate 		count = EOF;  /* malloc() failed */
5607c478bd9Sstevel@tonic-gate 	}
5617c478bd9Sstevel@tonic-gate 
5627c478bd9Sstevel@tonic-gate 	/* Finished */
5637c478bd9Sstevel@tonic-gate 	return (count);
5647c478bd9Sstevel@tonic-gate }
5657c478bd9Sstevel@tonic-gate 
5667c478bd9Sstevel@tonic-gate /*
5677c478bd9Sstevel@tonic-gate  *  int _adddgrptabrec(dgrp, members)
5687c478bd9Sstevel@tonic-gate  *	char   *dgrp
5697c478bd9Sstevel@tonic-gate  *	char  **members
5707c478bd9Sstevel@tonic-gate  *
5717c478bd9Sstevel@tonic-gate  *	If <dgrp> doesn't exist, this function adds a record to the
5727c478bd9Sstevel@tonic-gate  *	device-group table for that device-group.  That record will
5737c478bd9Sstevel@tonic-gate  *	have the name <dgrp> and will have a membership described in
5747c478bd9Sstevel@tonic-gate  *	the list referenced by <members>.  The record is added to the
5757c478bd9Sstevel@tonic-gate  *	end of the table.
5767c478bd9Sstevel@tonic-gate  *
5777c478bd9Sstevel@tonic-gate  *	If <dgrp> already exists in the table, the function adds the
5787c478bd9Sstevel@tonic-gate  *	members in the <members> list to the group's membership.
5797c478bd9Sstevel@tonic-gate  *
5807c478bd9Sstevel@tonic-gate  *  Arguments:
5817c478bd9Sstevel@tonic-gate  *	dgrp		The name of the device-group being added to the
5827c478bd9Sstevel@tonic-gate  *			device-group table.
5837c478bd9Sstevel@tonic-gate  *	members		A pointer to the first item of the list of members
5847c478bd9Sstevel@tonic-gate  *			in the device-group being added to the table.
5857c478bd9Sstevel@tonic-gate  *			(This value may be (char **) NULL).
5867c478bd9Sstevel@tonic-gate  *
5877c478bd9Sstevel@tonic-gate  *  Returns:  int
5887c478bd9Sstevel@tonic-gate  *	TRUE if successful, FALSE with "errno" set otherwise.
5897c478bd9Sstevel@tonic-gate  */
5907c478bd9Sstevel@tonic-gate 
5917c478bd9Sstevel@tonic-gate int
_adddgrptabrec(char * dgrp,char ** members)5927c478bd9Sstevel@tonic-gate _adddgrptabrec(
5937c478bd9Sstevel@tonic-gate 	char   *dgrp,			/* Devgrp to add to the table */
5947c478bd9Sstevel@tonic-gate 	char  **members)		/* Members for that devgrp */
5957c478bd9Sstevel@tonic-gate {
5967c478bd9Sstevel@tonic-gate 	/* Automatic data */
5977c478bd9Sstevel@tonic-gate 	struct dgrptabent	*ent;		/* Ptr to dev tab entry */
5987c478bd9Sstevel@tonic-gate 	struct dgrptabent	*new;		/* Ptr to new dev tab info */
5997c478bd9Sstevel@tonic-gate 	struct dgrptabent	*p;		/* Temp ptr to dev tab info */
6007c478bd9Sstevel@tonic-gate 	struct member		*pm, *qm, *rm;	/* Tmp ptrs to struct member */
6017c478bd9Sstevel@tonic-gate 	FILE			*fd;		/* File descr, temp file */
6027c478bd9Sstevel@tonic-gate 	char			*path;		/* Ptr to new devtab name */
6037c478bd9Sstevel@tonic-gate 	int			olderrno;	/* Errno on entry */
6047c478bd9Sstevel@tonic-gate 	int			noerr;		/* FLAG, TRUE if all's well */
6057c478bd9Sstevel@tonic-gate 
6067c478bd9Sstevel@tonic-gate 
6077c478bd9Sstevel@tonic-gate 	/* Make a structure describing the new information */
6087c478bd9Sstevel@tonic-gate 	if ((new = mkdgrptabent(dgrp, members)) == NULL)
6097c478bd9Sstevel@tonic-gate 	    return (FALSE);
6107c478bd9Sstevel@tonic-gate 
6117c478bd9Sstevel@tonic-gate 	/*
6127c478bd9Sstevel@tonic-gate 	 * Lock the device-group table.  This only returns if the
6137c478bd9Sstevel@tonic-gate 	 * table is locked or some error occurred.  It waits until the
6147c478bd9Sstevel@tonic-gate 	 * table is available.
6157c478bd9Sstevel@tonic-gate 	 */
6167c478bd9Sstevel@tonic-gate 	if (!lkdgrptab("a+", F_WRLCK)) {
6177c478bd9Sstevel@tonic-gate 	    _freedgrptabent(new);
6187c478bd9Sstevel@tonic-gate 	    return (FALSE);
6197c478bd9Sstevel@tonic-gate 	}
6207c478bd9Sstevel@tonic-gate 
6217c478bd9Sstevel@tonic-gate 	/*
6227c478bd9Sstevel@tonic-gate 	 * If the device-group is already in the table, add
6237c478bd9Sstevel@tonic-gate 	 * the specified members
6247c478bd9Sstevel@tonic-gate 	 */
6257c478bd9Sstevel@tonic-gate 
6267c478bd9Sstevel@tonic-gate 	noerr = TRUE;
6277c478bd9Sstevel@tonic-gate 	olderrno = errno;
6287c478bd9Sstevel@tonic-gate 	if (ent = _getdgrprec(dgrp)) {
6297c478bd9Sstevel@tonic-gate 
6307c478bd9Sstevel@tonic-gate 	    /* Any members to add?  If not, do nothing. */
6317c478bd9Sstevel@tonic-gate 	    if (new->membership) {
6327c478bd9Sstevel@tonic-gate 
6337c478bd9Sstevel@tonic-gate 		/* Any existing members? */
6347c478bd9Sstevel@tonic-gate 		if ((pm = ent->membership) != NULL) {
6357c478bd9Sstevel@tonic-gate 
6367c478bd9Sstevel@tonic-gate 		    /* Find the end of the existing membership list */
6377c478bd9Sstevel@tonic-gate 		    while (pm->next) pm = pm->next;
6387c478bd9Sstevel@tonic-gate 
6397c478bd9Sstevel@tonic-gate 		    /* Append the new members to the membership list */
6407c478bd9Sstevel@tonic-gate 		    pm->next = new->membership;
6417c478bd9Sstevel@tonic-gate 
6427c478bd9Sstevel@tonic-gate 		    /* Remove any duplicates */
6437c478bd9Sstevel@tonic-gate 		    for (pm = ent->membership; pm; pm = pm->next) {
6447c478bd9Sstevel@tonic-gate 			qm = pm;
6457c478bd9Sstevel@tonic-gate 			while ((rm = qm->next) != NULL) {
6467c478bd9Sstevel@tonic-gate 			    if (strcmp(pm->name, rm->name) == 0) {
6477c478bd9Sstevel@tonic-gate 				qm->next = rm->next;
6487c478bd9Sstevel@tonic-gate 				free(rm->name);
6497c478bd9Sstevel@tonic-gate 				free(rm);
6507c478bd9Sstevel@tonic-gate 			    } else qm = rm;
6517c478bd9Sstevel@tonic-gate 			}
6527c478bd9Sstevel@tonic-gate 		    }
6537c478bd9Sstevel@tonic-gate 		} else ent->membership = new->membership;
6547c478bd9Sstevel@tonic-gate 
6557c478bd9Sstevel@tonic-gate 		/* No members in the new list any more */
6567c478bd9Sstevel@tonic-gate 		new->membership = NULL;
6577c478bd9Sstevel@tonic-gate 
6587c478bd9Sstevel@tonic-gate 		/*
6597c478bd9Sstevel@tonic-gate 		 * Make a new device-group table, replacing the
6607c478bd9Sstevel@tonic-gate 		 * record for the specified device-group
6617c478bd9Sstevel@tonic-gate 		 */
6627c478bd9Sstevel@tonic-gate 
6637c478bd9Sstevel@tonic-gate 		_setdgrptab();	/* Rewind existing table */
6647c478bd9Sstevel@tonic-gate 
6657c478bd9Sstevel@tonic-gate 		/* Open a temp file */
6667c478bd9Sstevel@tonic-gate 		if (fd = opennewdgrptab(&path)) {
6677c478bd9Sstevel@tonic-gate 
6687c478bd9Sstevel@tonic-gate 		    /* While there's more records and no error ... */
6697c478bd9Sstevel@tonic-gate 		    while (((p = _getdgrptabent()) != NULL) && noerr) {
6707c478bd9Sstevel@tonic-gate 
6717c478bd9Sstevel@tonic-gate 			/*
6727c478bd9Sstevel@tonic-gate 			 * If this isn't the record we're replacing,
6737c478bd9Sstevel@tonic-gate 			 * write it to the temporary file.  Otherwise,
6747c478bd9Sstevel@tonic-gate 			 * write the updated record
6757c478bd9Sstevel@tonic-gate 			 */
6767c478bd9Sstevel@tonic-gate 
6777c478bd9Sstevel@tonic-gate 			if (ent->entryno != p->entryno)
6787c478bd9Sstevel@tonic-gate 				noerr = _putdgrptabrec(fd, p) != EOF;
6797c478bd9Sstevel@tonic-gate 			else noerr = _putdgrptabrec(fd, ent) != EOF;
6807c478bd9Sstevel@tonic-gate 			_freedgrptabent(p);
6817c478bd9Sstevel@tonic-gate 		    }
6827c478bd9Sstevel@tonic-gate 
6837c478bd9Sstevel@tonic-gate 		    /* Fix the files */
6847c478bd9Sstevel@tonic-gate 		    if (noerr) {
6857c478bd9Sstevel@tonic-gate 			(void) fclose(fd);
6867c478bd9Sstevel@tonic-gate 			noerr = mknewdgrptab(path);
6877c478bd9Sstevel@tonic-gate 		    } else {
6887c478bd9Sstevel@tonic-gate 			(void) fclose(fd);
6897c478bd9Sstevel@tonic-gate 			(void) rmnewdgrptab(path);
6907c478bd9Sstevel@tonic-gate 		    }
6917c478bd9Sstevel@tonic-gate 		}   /* if (opennewdgrptab()) */
6927c478bd9Sstevel@tonic-gate 
6937c478bd9Sstevel@tonic-gate 	    }   /* If there's members to add */
6947c478bd9Sstevel@tonic-gate 
6957c478bd9Sstevel@tonic-gate 	    /* Free the memory associated with the updated entry */
6967c478bd9Sstevel@tonic-gate 	    _freedgrptabent(ent);
6977c478bd9Sstevel@tonic-gate 	}
6987c478bd9Sstevel@tonic-gate 
6997c478bd9Sstevel@tonic-gate 	/*
7007c478bd9Sstevel@tonic-gate 	 * Otherwise, add the device-group to the end of the table
7017c478bd9Sstevel@tonic-gate 	 */
7027c478bd9Sstevel@tonic-gate 
7037c478bd9Sstevel@tonic-gate 	else if (errno == EINVAL) {
7047c478bd9Sstevel@tonic-gate 	    errno = olderrno;
7057c478bd9Sstevel@tonic-gate 	    if (fseek(oam_dgroup, 0, SEEK_END) == 0)
7067c478bd9Sstevel@tonic-gate 		noerr = (_putdgrptabrec(oam_dgroup, new) != EOF);
7077c478bd9Sstevel@tonic-gate 	} else noerr = FALSE;
7087c478bd9Sstevel@tonic-gate 
7097c478bd9Sstevel@tonic-gate 	/* Finished */
7107c478bd9Sstevel@tonic-gate 	(void) unlkdgrptab();		/* Unlock the file */
7117c478bd9Sstevel@tonic-gate 	_freedgrptabent(new);		/* Free the new dgrptab info struct */
7127c478bd9Sstevel@tonic-gate 	return (noerr);			/* Return with success indicator */
7137c478bd9Sstevel@tonic-gate }
7147c478bd9Sstevel@tonic-gate 
7157c478bd9Sstevel@tonic-gate /*
7167c478bd9Sstevel@tonic-gate  * int _rmdgrptabrec(dgrp)
7177c478bd9Sstevel@tonic-gate  *	char   *dgrp
7187c478bd9Sstevel@tonic-gate  *
7197c478bd9Sstevel@tonic-gate  *	This function removes the record in the device-group table
7207c478bd9Sstevel@tonic-gate  *	for the specified device-group.
7217c478bd9Sstevel@tonic-gate  *
7227c478bd9Sstevel@tonic-gate  *  Arguments:
7237c478bd9Sstevel@tonic-gate  *	dgrp	The device-group to be removed
7247c478bd9Sstevel@tonic-gate  *
7257c478bd9Sstevel@tonic-gate  *  Returns:  int
7267c478bd9Sstevel@tonic-gate  *	Success indicator:  TRUE if successful, FALSE with errno set otherwise.
7277c478bd9Sstevel@tonic-gate  */
7287c478bd9Sstevel@tonic-gate 
7297c478bd9Sstevel@tonic-gate int
_rmdgrptabrec(char * dgrp)7307c478bd9Sstevel@tonic-gate _rmdgrptabrec(char *dgrp)		/* Device-group to remove */
7317c478bd9Sstevel@tonic-gate {
7327c478bd9Sstevel@tonic-gate 	/* Automatic data */
7337c478bd9Sstevel@tonic-gate 	struct dgrptabent	*ent;	/* Entry to remove */
7347c478bd9Sstevel@tonic-gate 	struct dgrptabent	*p;	/* Entry being copied */
7357c478bd9Sstevel@tonic-gate 	FILE			*fd;	/* Temp file's file descriptor */
7367c478bd9Sstevel@tonic-gate 	char			*path;	/* Pathname of temp file */
7377c478bd9Sstevel@tonic-gate 	int			noerr;	/* FLAG, TRUE if all's well */
7387c478bd9Sstevel@tonic-gate 
7397c478bd9Sstevel@tonic-gate 	noerr = TRUE;
7407c478bd9Sstevel@tonic-gate 	if (!lkdgrptab("r", F_WRLCK))
7417c478bd9Sstevel@tonic-gate 		return (FALSE);
7427c478bd9Sstevel@tonic-gate 	if (ent = _getdgrprec(dgrp)) {
7437c478bd9Sstevel@tonic-gate 	    _setdgrptab();
7447c478bd9Sstevel@tonic-gate 	    if (fd = opennewdgrptab(&path)) {
7457c478bd9Sstevel@tonic-gate 		while (((p = _getdgrptabent()) != NULL) && noerr) {
7467c478bd9Sstevel@tonic-gate 		    if (ent->entryno != p->entryno)
7477c478bd9Sstevel@tonic-gate 			noerr = _putdgrptabrec(fd, p) != EOF;
7487c478bd9Sstevel@tonic-gate 		    _freedgrptabent(p);
7497c478bd9Sstevel@tonic-gate 		}
7507c478bd9Sstevel@tonic-gate 		if (noerr) {
7517c478bd9Sstevel@tonic-gate 		    (void) fclose(fd);
7527c478bd9Sstevel@tonic-gate 		    noerr = mknewdgrptab(path);
7537c478bd9Sstevel@tonic-gate 		} else {
7547c478bd9Sstevel@tonic-gate 		    (void) fclose(fd);
7557c478bd9Sstevel@tonic-gate 		    (void) rmnewdgrptab(path);
7567c478bd9Sstevel@tonic-gate 		}
7577c478bd9Sstevel@tonic-gate 	    } else noerr = FALSE;
7587c478bd9Sstevel@tonic-gate 	    _freedgrptabent(ent);
7597c478bd9Sstevel@tonic-gate 	} else noerr = FALSE;
7607c478bd9Sstevel@tonic-gate 	(void) unlkdgrptab();
7617c478bd9Sstevel@tonic-gate 	return (noerr);
7627c478bd9Sstevel@tonic-gate }
7637c478bd9Sstevel@tonic-gate 
7647c478bd9Sstevel@tonic-gate /*
7657c478bd9Sstevel@tonic-gate  * int _rmdgrpmems(dgrp, mems, notfounds)
7667c478bd9Sstevel@tonic-gate  *	char   *dgrp
7677c478bd9Sstevel@tonic-gate  *	char  **mems
7687c478bd9Sstevel@tonic-gate  *	char ***notfounds
7697c478bd9Sstevel@tonic-gate  *
7707c478bd9Sstevel@tonic-gate  *	Remove the specified members from the membership of the specified
7717c478bd9Sstevel@tonic-gate  *	device-group.  Any members not found in that device-group are
7727c478bd9Sstevel@tonic-gate  *	returned in the list referenced by <notfounds>.
7737c478bd9Sstevel@tonic-gate  *
7747c478bd9Sstevel@tonic-gate  *  Arguments:
7757c478bd9Sstevel@tonic-gate  *	dgrp		The device-group from which members are to be removed
7767c478bd9Sstevel@tonic-gate  *	mems		The address of the first element in the list of
7777c478bd9Sstevel@tonic-gate  *			members to remove.  This list is terminated by
7787c478bd9Sstevel@tonic-gate  *			(char *) NULL.
7797c478bd9Sstevel@tonic-gate  *	notfounds	The place to put the address of the list of addresses
7807c478bd9Sstevel@tonic-gate  *			referencing the requested members that were not
7817c478bd9Sstevel@tonic-gate  *			members of the specified device-group
7827c478bd9Sstevel@tonic-gate  *
7837c478bd9Sstevel@tonic-gate  *  Returns: int
7847c478bd9Sstevel@tonic-gate  *	TRUE if successful, FALSE with errno set otherwise.
7857c478bd9Sstevel@tonic-gate  */
7867c478bd9Sstevel@tonic-gate 
7877c478bd9Sstevel@tonic-gate int
_rmdgrpmems(char * dgrp,char ** mems,char *** notfounds)7887c478bd9Sstevel@tonic-gate _rmdgrpmems(
7897c478bd9Sstevel@tonic-gate 	char   *dgrp,			/* Device-group to modify */
7907c478bd9Sstevel@tonic-gate 	char  **mems,			/* Members to remove */
7917c478bd9Sstevel@tonic-gate 	char ***notfounds)		/* Members req'd but not found */
7927c478bd9Sstevel@tonic-gate {
7937c478bd9Sstevel@tonic-gate 	/* Automatic data */
7947c478bd9Sstevel@tonic-gate 	struct dgrptabent	*ent;	/* Entry to modify */
7957c478bd9Sstevel@tonic-gate 	struct dgrptabent	*p;	/* Entry being copied */
7967c478bd9Sstevel@tonic-gate 	struct member		*pm;	/* Ptr to member being examined */
7977c478bd9Sstevel@tonic-gate 	struct member		*prev;	/* Ptr to previous member */
7987c478bd9Sstevel@tonic-gate 	char			**nflst; /* Ptr to not-found list */
7997c478bd9Sstevel@tonic-gate 	char			**pnf;	/* Ptr into not-found list */
8007c478bd9Sstevel@tonic-gate 	char			**pp;	/* Ptr into members-to-rm list */
8017c478bd9Sstevel@tonic-gate 	FILE			*fd;	/* Temp file's file descriptor */
8027c478bd9Sstevel@tonic-gate 	char			*path;	/* Pathname of temp file */
8037c478bd9Sstevel@tonic-gate 	int			noerr;	/* TRUE if all's well */
8047c478bd9Sstevel@tonic-gate 	int			found;	/* TRUE if member is in membership */
8057c478bd9Sstevel@tonic-gate 	int			i;	/* Temp counter */
8067c478bd9Sstevel@tonic-gate 
8077c478bd9Sstevel@tonic-gate 	noerr = TRUE;
8087c478bd9Sstevel@tonic-gate 
8097c478bd9Sstevel@tonic-gate 	/* Lock the device-group table */
8107c478bd9Sstevel@tonic-gate 	if (!lkdgrptab("r", F_WRLCK))
8117c478bd9Sstevel@tonic-gate 		return (FALSE);
8127c478bd9Sstevel@tonic-gate 
8137c478bd9Sstevel@tonic-gate 	/* Nothing is "not found" yet */
8147c478bd9Sstevel@tonic-gate 	*notfounds = NULL;
8157c478bd9Sstevel@tonic-gate 
8167c478bd9Sstevel@tonic-gate 	/* Get the entry we're to modify */
8177c478bd9Sstevel@tonic-gate 	if (ent = _getdgrprec(dgrp)) {
8187c478bd9Sstevel@tonic-gate 
8197c478bd9Sstevel@tonic-gate 	    /* Allocate space for the not-found list */
8207c478bd9Sstevel@tonic-gate 	    i = 1;
8217c478bd9Sstevel@tonic-gate 	    if (mems)
8227c478bd9Sstevel@tonic-gate 		for (pp = mems; *pp; pp++)
8237c478bd9Sstevel@tonic-gate 			i++;
8247c478bd9Sstevel@tonic-gate 	    if (nflst = malloc(i*sizeof (char *))) {
8257c478bd9Sstevel@tonic-gate 		pnf = nflst;
8267c478bd9Sstevel@tonic-gate 		*pnf = NULL;
8277c478bd9Sstevel@tonic-gate 
8287c478bd9Sstevel@tonic-gate 		/* For each member to remove ... (if any) */
8297c478bd9Sstevel@tonic-gate 		if (mems)
8307c478bd9Sstevel@tonic-gate 		    for (pp = mems; *pp; pp++) {
8317c478bd9Sstevel@tonic-gate 
8327c478bd9Sstevel@tonic-gate 		    found = FALSE;
8337c478bd9Sstevel@tonic-gate 
8347c478bd9Sstevel@tonic-gate 		    /* Compare against each member in the membership list */
8357c478bd9Sstevel@tonic-gate 		    pm = ent->membership;
8367c478bd9Sstevel@tonic-gate 		    prev = NULL;
8377c478bd9Sstevel@tonic-gate 		    while (pm && !found) {
8387c478bd9Sstevel@tonic-gate 
8397c478bd9Sstevel@tonic-gate 			if (strcmp(*pp, pm->name) == 0) {
8407c478bd9Sstevel@tonic-gate 
8417c478bd9Sstevel@tonic-gate 			    /* Found.  Remove from linked list */
8427c478bd9Sstevel@tonic-gate 			    if (prev) prev->next = pm->next;
8437c478bd9Sstevel@tonic-gate 			    else ent->membership = pm->next;
8447c478bd9Sstevel@tonic-gate 			    if (pm->name) free(pm->name);
8457c478bd9Sstevel@tonic-gate 			    free(pm);
8467c478bd9Sstevel@tonic-gate 			    found = TRUE;
8477c478bd9Sstevel@tonic-gate 
8487c478bd9Sstevel@tonic-gate 			} else {
8497c478bd9Sstevel@tonic-gate 
8507c478bd9Sstevel@tonic-gate 			    /* Bump to the next member */
8517c478bd9Sstevel@tonic-gate 			    prev = pm;
8527c478bd9Sstevel@tonic-gate 			    pm = pm->next;
8537c478bd9Sstevel@tonic-gate 
8547c478bd9Sstevel@tonic-gate 			}
8557c478bd9Sstevel@tonic-gate 
8567c478bd9Sstevel@tonic-gate 		    }   /* For each member in the group */
8577c478bd9Sstevel@tonic-gate 
8587c478bd9Sstevel@tonic-gate 		/*
8597c478bd9Sstevel@tonic-gate 		 * If the requested member-to-remove wasn't found,
8607c478bd9Sstevel@tonic-gate 		 * add it to the list of not-found members
8617c478bd9Sstevel@tonic-gate 		 */
8627c478bd9Sstevel@tonic-gate 		    if (!found) {
8637c478bd9Sstevel@tonic-gate 			if (*pnf = malloc(strlen(*pp)+1)) {
8647c478bd9Sstevel@tonic-gate 			    (void) strcpy(*pnf++, *pp);
8657c478bd9Sstevel@tonic-gate 			    *pnf = NULL;
8667c478bd9Sstevel@tonic-gate 			} else noerr = FALSE;
8677c478bd9Sstevel@tonic-gate 		    }
8687c478bd9Sstevel@tonic-gate 
8697c478bd9Sstevel@tonic-gate 		}   /* for (each requested member to remove */
8707c478bd9Sstevel@tonic-gate 
8717c478bd9Sstevel@tonic-gate 		_setdgrptab();		/* Rewind existing table */
8727c478bd9Sstevel@tonic-gate 
8737c478bd9Sstevel@tonic-gate 		if (fd = opennewdgrptab(&path)) {
8747c478bd9Sstevel@tonic-gate 		    while (((p = _getdgrptabent()) != NULL) && noerr) {
8757c478bd9Sstevel@tonic-gate 			if (ent->entryno != p->entryno)
8767c478bd9Sstevel@tonic-gate 			    noerr = _putdgrptabrec(fd, p) != EOF;
8777c478bd9Sstevel@tonic-gate 			else noerr = _putdgrptabrec(fd, ent) != EOF;
8787c478bd9Sstevel@tonic-gate 			_freedgrptabent(p);
8797c478bd9Sstevel@tonic-gate 		    }
8807c478bd9Sstevel@tonic-gate 		    if (noerr) {
8817c478bd9Sstevel@tonic-gate 			(void) fclose(fd);
8827c478bd9Sstevel@tonic-gate 			noerr = mknewdgrptab(path);
8837c478bd9Sstevel@tonic-gate 		    } else {
8847c478bd9Sstevel@tonic-gate 			(void) fclose(fd);
8857c478bd9Sstevel@tonic-gate 			(void) rmnewdgrptab(path);
8867c478bd9Sstevel@tonic-gate 		    }
8877c478bd9Sstevel@tonic-gate 		} else noerr = FALSE;   /* if (opennewdgrptab()) */
8887c478bd9Sstevel@tonic-gate 
8897c478bd9Sstevel@tonic-gate 		/*
8907c478bd9Sstevel@tonic-gate 		 * If there was no error but there was requested members
8917c478bd9Sstevel@tonic-gate 		 * that weren't found, set the not-found list and the error
8927c478bd9Sstevel@tonic-gate 		 * information.  Otherwise, free the not-found list
8937c478bd9Sstevel@tonic-gate 		 */
8947c478bd9Sstevel@tonic-gate 
8957c478bd9Sstevel@tonic-gate 		if (noerr && (pnf != nflst)) {
8967c478bd9Sstevel@tonic-gate 		    *notfounds = nflst;
8977c478bd9Sstevel@tonic-gate 		    errno = ENODEV;
8987c478bd9Sstevel@tonic-gate 		    noerr = FALSE;
8997c478bd9Sstevel@tonic-gate 		} else {
9007c478bd9Sstevel@tonic-gate 		    for (pnf = nflst; *pnf; pnf++) free(*pnf);
9017c478bd9Sstevel@tonic-gate 		    free(nflst);
9027c478bd9Sstevel@tonic-gate 		    if (!noerr) *notfounds = NULL;
9037c478bd9Sstevel@tonic-gate 		}
9047c478bd9Sstevel@tonic-gate 	    } else noerr = FALSE;
9057c478bd9Sstevel@tonic-gate 
9067c478bd9Sstevel@tonic-gate 	    /* Free the description of the modified device group */
9077c478bd9Sstevel@tonic-gate 	    _freedgrptabent(ent);
9087c478bd9Sstevel@tonic-gate 
9097c478bd9Sstevel@tonic-gate 	} else noerr = FALSE;    /* _getdgrprec() failed */
9107c478bd9Sstevel@tonic-gate 
9117c478bd9Sstevel@tonic-gate 	/* Unlock the original device-group table */
9127c478bd9Sstevel@tonic-gate 	(void) unlkdgrptab();
9137c478bd9Sstevel@tonic-gate 	return (noerr);
9147c478bd9Sstevel@tonic-gate }
915