xref: /titanic_50/usr/src/lib/libadm/common/putdev.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright (c) 1996-1997, by Sun Microsystems, Inc.
24*7c478bd9Sstevel@tonic-gate  * All Rights reserved.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
27*7c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate 
30*7c478bd9Sstevel@tonic-gate #pragma	ident	"%Z%%M%	%I%	%E% SMI"	/* SVr4.0 1.2 */
31*7c478bd9Sstevel@tonic-gate /* LINTLIBRARY */
32*7c478bd9Sstevel@tonic-gate 
33*7c478bd9Sstevel@tonic-gate /*
34*7c478bd9Sstevel@tonic-gate  * putdev.c
35*7c478bd9Sstevel@tonic-gate  *
36*7c478bd9Sstevel@tonic-gate  * Global Definitions:
37*7c478bd9Sstevel@tonic-gate  *	_adddevtabrec()		Add a record to the device table
38*7c478bd9Sstevel@tonic-gate  *	_putdevtabrec()		Write a record to the device table
39*7c478bd9Sstevel@tonic-gate  *	_moddevtabrec()		Modify a device-table record
40*7c478bd9Sstevel@tonic-gate  *	_rmdevtabrec()		Remove a device-table record
41*7c478bd9Sstevel@tonic-gate  *	_rmdevtabattrs()	Remove attributes from a device-table record
42*7c478bd9Sstevel@tonic-gate  *	oam_devtab		File descriptor of the open device table
43*7c478bd9Sstevel@tonic-gate  */
44*7c478bd9Sstevel@tonic-gate 
45*7c478bd9Sstevel@tonic-gate /*
46*7c478bd9Sstevel@tonic-gate  *  G L O B A L   R E F E R E N C E S
47*7c478bd9Sstevel@tonic-gate  *
48*7c478bd9Sstevel@tonic-gate  *	Header Files
49*7c478bd9Sstevel@tonic-gate  *	Externals Referenced
50*7c478bd9Sstevel@tonic-gate  */
51*7c478bd9Sstevel@tonic-gate 
52*7c478bd9Sstevel@tonic-gate /*
53*7c478bd9Sstevel@tonic-gate  * Header Files
54*7c478bd9Sstevel@tonic-gate  *	<sys/types.h>		UNIX(r) Data Types
55*7c478bd9Sstevel@tonic-gate  *	<sys/stat.h>
56*7c478bd9Sstevel@tonic-gate  *	<stdio.h>		Standard I/O definitions
57*7c478bd9Sstevel@tonic-gate  *	<fcntl.h>		Definitions for file control
58*7c478bd9Sstevel@tonic-gate  *	<errno.h>		Error handling definitions
59*7c478bd9Sstevel@tonic-gate  *	<string.h>		String Handling Definitions
60*7c478bd9Sstevel@tonic-gate  *	<devmgmt.h>		Device Management Definitions
61*7c478bd9Sstevel@tonic-gate  *	<unistd.h>		Get UNIX(r) Standard Definitions
62*7c478bd9Sstevel@tonic-gate  *	"devtab.h"		Local Device Management Definitions
63*7c478bd9Sstevel@tonic-gate  */
64*7c478bd9Sstevel@tonic-gate 
65*7c478bd9Sstevel@tonic-gate #include	<sys/types.h>
66*7c478bd9Sstevel@tonic-gate #include	<sys/stat.h>
67*7c478bd9Sstevel@tonic-gate #include	<stdio.h>
68*7c478bd9Sstevel@tonic-gate #include	<fcntl.h>
69*7c478bd9Sstevel@tonic-gate #include	<errno.h>
70*7c478bd9Sstevel@tonic-gate #include	<string.h>
71*7c478bd9Sstevel@tonic-gate #include	<devmgmt.h>
72*7c478bd9Sstevel@tonic-gate #include	<unistd.h>
73*7c478bd9Sstevel@tonic-gate #include	<stdlib.h>
74*7c478bd9Sstevel@tonic-gate #include	"devtab.h"
75*7c478bd9Sstevel@tonic-gate 
76*7c478bd9Sstevel@tonic-gate /*
77*7c478bd9Sstevel@tonic-gate  *  L O C A L   D E F I N I T I O N S
78*7c478bd9Sstevel@tonic-gate  *
79*7c478bd9Sstevel@tonic-gate  *	TDTABNM		Name of the temporary device table (in the
80*7c478bd9Sstevel@tonic-gate  *			directory of the existing table)
81*7c478bd9Sstevel@tonic-gate  *	TDTABNMLN	Number of characters added to the directory
82*7c478bd9Sstevel@tonic-gate  *			name -- the length of the device table temp name
83*7c478bd9Sstevel@tonic-gate  */
84*7c478bd9Sstevel@tonic-gate 
85*7c478bd9Sstevel@tonic-gate #define	TDTABNM		"%sdevtab.%6.6d"
86*7c478bd9Sstevel@tonic-gate #define	TDTABNMLN	13
87*7c478bd9Sstevel@tonic-gate 
88*7c478bd9Sstevel@tonic-gate 
89*7c478bd9Sstevel@tonic-gate /*
90*7c478bd9Sstevel@tonic-gate  * Static functions
91*7c478bd9Sstevel@tonic-gate  *	strcatesc	Copies a character-string from one place to another
92*7c478bd9Sstevel@tonic-gate  *			escaping the appropriate characters
93*7c478bd9Sstevel@tonic-gate  *	lkdevtab	Locks the device table
94*7c478bd9Sstevel@tonic-gate  *	unlkdevtab	Unlocks the device table
95*7c478bd9Sstevel@tonic-gate  *	mkdevtabent	Builds a device-table entry from the alias and the
96*7c478bd9Sstevel@tonic-gate  *			list of attr=val pairs given
97*7c478bd9Sstevel@tonic-gate  *	opennewdevtab	Opens a new device table (as a temp file)
98*7c478bd9Sstevel@tonic-gate  *	mknewdevtab	Makes the temp device table the new devtab
99*7c478bd9Sstevel@tonic-gate  *	rmnewdevtab	Remove the temporary device table and free space
100*7c478bd9Sstevel@tonic-gate  *			allocated to the filename of that file.
101*7c478bd9Sstevel@tonic-gate  */
102*7c478bd9Sstevel@tonic-gate 
103*7c478bd9Sstevel@tonic-gate static	char			*strcatesc(char *, char *);
104*7c478bd9Sstevel@tonic-gate static	int			lkdevtab(char *, short);
105*7c478bd9Sstevel@tonic-gate static	int			unlkdevtab(void);
106*7c478bd9Sstevel@tonic-gate static	struct devtabent	*mkdevtabent(char *, char **);
107*7c478bd9Sstevel@tonic-gate static	FILE			*opennewdevtab(char **);
108*7c478bd9Sstevel@tonic-gate static	int			mknewdevtab(char *);
109*7c478bd9Sstevel@tonic-gate static	int			rmnewdevtab(char *);
110*7c478bd9Sstevel@tonic-gate 
111*7c478bd9Sstevel@tonic-gate /*
112*7c478bd9Sstevel@tonic-gate  * char *strcatesc(p, q)
113*7c478bd9Sstevel@tonic-gate  *	char   *p
114*7c478bd9Sstevel@tonic-gate  *	char   *q
115*7c478bd9Sstevel@tonic-gate  *
116*7c478bd9Sstevel@tonic-gate  *	Write the character-string pointed to by "q" to the place
117*7c478bd9Sstevel@tonic-gate  *	pointed to by "p", escaping those characters in "q" found in the
118*7c478bd9Sstevel@tonic-gate  *	string "DTAB_ESCS" by preceding them with '\\'.  Return a pointer to
119*7c478bd9Sstevel@tonic-gate  *	the byte beyond the last character written to "p".
120*7c478bd9Sstevel@tonic-gate  *
121*7c478bd9Sstevel@tonic-gate  *  Arguments:
122*7c478bd9Sstevel@tonic-gate  *	p		The place to begin writing to
123*7c478bd9Sstevel@tonic-gate  *	q		The string to write
124*7c478bd9Sstevel@tonic-gate  *
125*7c478bd9Sstevel@tonic-gate  *  Returns:  char *
126*7c478bd9Sstevel@tonic-gate  *	The address of the byte beyond the last character written into "p"
127*7c478bd9Sstevel@tonic-gate  */
128*7c478bd9Sstevel@tonic-gate 
129*7c478bd9Sstevel@tonic-gate static char *
130*7c478bd9Sstevel@tonic-gate strcatesc(
131*7c478bd9Sstevel@tonic-gate 	char   *p,		/* Place to write to */
132*7c478bd9Sstevel@tonic-gate 	char   *q)		/* Thing to write */
133*7c478bd9Sstevel@tonic-gate {
134*7c478bd9Sstevel@tonic-gate 	while (*q) {
135*7c478bd9Sstevel@tonic-gate 	    if (strchr(DTAB_ESCS, *q)) *p++ = '\\';
136*7c478bd9Sstevel@tonic-gate 	    *p++ = *q++;
137*7c478bd9Sstevel@tonic-gate 	}
138*7c478bd9Sstevel@tonic-gate 	return (p);
139*7c478bd9Sstevel@tonic-gate }
140*7c478bd9Sstevel@tonic-gate 
141*7c478bd9Sstevel@tonic-gate /*
142*7c478bd9Sstevel@tonic-gate  * FILE *opennewdevtab(pname)
143*7c478bd9Sstevel@tonic-gate  *	char   **pname
144*7c478bd9Sstevel@tonic-gate  *
145*7c478bd9Sstevel@tonic-gate  *	Generates a temporary device-table name from the existing
146*7c478bd9Sstevel@tonic-gate  *	device table name (in the same directory) and opens that
147*7c478bd9Sstevel@tonic-gate  *	file for writing.  It puts a pointer to the malloc()ed space
148*7c478bd9Sstevel@tonic-gate  *	containing the temp device table's name at the place referenced
149*7c478bd9Sstevel@tonic-gate  *	by <pname>.
150*7c478bd9Sstevel@tonic-gate  *
151*7c478bd9Sstevel@tonic-gate  *  Arguments:
152*7c478bd9Sstevel@tonic-gate  *	pname	Pointer to the char * to contain the address of the name
153*7c478bd9Sstevel@tonic-gate  *		of the temporary file
154*7c478bd9Sstevel@tonic-gate  *
155*7c478bd9Sstevel@tonic-gate  *  Returns:  FILE *
156*7c478bd9Sstevel@tonic-gate  *	A pointer to the opened stream or (FILE *) NULL if an error occurred.
157*7c478bd9Sstevel@tonic-gate  *	If an error occurred, "errno" will be set to reflect the problem.
158*7c478bd9Sstevel@tonic-gate  */
159*7c478bd9Sstevel@tonic-gate 
160*7c478bd9Sstevel@tonic-gate static FILE *
161*7c478bd9Sstevel@tonic-gate opennewdevtab(char  **pname)		/* A(ptr to temp filename's path) */
162*7c478bd9Sstevel@tonic-gate {
163*7c478bd9Sstevel@tonic-gate 	char   *oldname;		/* Ptr to the device-table's name */
164*7c478bd9Sstevel@tonic-gate 	char   *buf;			/* Ptr to the temp file's name */
165*7c478bd9Sstevel@tonic-gate 	char   *dirname;		/* Directory containing devtab */
166*7c478bd9Sstevel@tonic-gate 	char   *p;			/* Ptr to last '/' in devtab name */
167*7c478bd9Sstevel@tonic-gate 	int    fd;			/* Opened file descriptor */
168*7c478bd9Sstevel@tonic-gate 	FILE   *fp;			/* Opened file pointer */
169*7c478bd9Sstevel@tonic-gate 	struct stat64	sbuf;		/* stat buf for old devtab file */
170*7c478bd9Sstevel@tonic-gate 
171*7c478bd9Sstevel@tonic-gate 	fp = NULL;
172*7c478bd9Sstevel@tonic-gate 	if (oldname = _devtabpath()) {
173*7c478bd9Sstevel@tonic-gate 	/*
174*7c478bd9Sstevel@tonic-gate 	 * It is possible for us to have sufficient permissions to create
175*7c478bd9Sstevel@tonic-gate 	 * the new file without having sufficient permissions to write the
176*7c478bd9Sstevel@tonic-gate 	 * original devtab file.  For consistency with the operations which
177*7c478bd9Sstevel@tonic-gate 	 * modify the original file by writing it directly we require write
178*7c478bd9Sstevel@tonic-gate 	 * permissions for the original file in order to make a new one.
179*7c478bd9Sstevel@tonic-gate 	 */
180*7c478bd9Sstevel@tonic-gate 	    if ((fd = open(oldname, O_WRONLY)) == -1)
181*7c478bd9Sstevel@tonic-gate 		return (NULL);
182*7c478bd9Sstevel@tonic-gate 
183*7c478bd9Sstevel@tonic-gate 	    if (fstat64(fd, &sbuf) == -1) {
184*7c478bd9Sstevel@tonic-gate 		(void) close(fd);
185*7c478bd9Sstevel@tonic-gate 		return (NULL);
186*7c478bd9Sstevel@tonic-gate 	    }
187*7c478bd9Sstevel@tonic-gate 	    (void) close(fd);
188*7c478bd9Sstevel@tonic-gate 
189*7c478bd9Sstevel@tonic-gate 	    if (p = strrchr(oldname, '/')) {
190*7c478bd9Sstevel@tonic-gate 		*(p+1) = '\0';
191*7c478bd9Sstevel@tonic-gate 		dirname = oldname;
192*7c478bd9Sstevel@tonic-gate 	    } else dirname = "./";
193*7c478bd9Sstevel@tonic-gate 	    if (buf = malloc(TDTABNMLN + strlen(dirname) + 1)) {
194*7c478bd9Sstevel@tonic-gate 
195*7c478bd9Sstevel@tonic-gate 		/*
196*7c478bd9Sstevel@tonic-gate 		 * Build the name of the temp device table and open the
197*7c478bd9Sstevel@tonic-gate 		 * file.  We must reset the owner, group and perms to those
198*7c478bd9Sstevel@tonic-gate 		 * of the original devtab file.
199*7c478bd9Sstevel@tonic-gate 		 */
200*7c478bd9Sstevel@tonic-gate 		(void) sprintf(buf, TDTABNM, dirname, getpid());
201*7c478bd9Sstevel@tonic-gate 		if (fp = fopen(buf, "w")) {
202*7c478bd9Sstevel@tonic-gate 			*pname = buf;
203*7c478bd9Sstevel@tonic-gate 			(void) fchmod(fileno(fp), sbuf.st_mode & 0777);
204*7c478bd9Sstevel@tonic-gate 			(void) fchown(fileno(fp), sbuf.st_uid, sbuf.st_gid);
205*7c478bd9Sstevel@tonic-gate 		} else {
206*7c478bd9Sstevel@tonic-gate 			free(buf);
207*7c478bd9Sstevel@tonic-gate 		}
208*7c478bd9Sstevel@tonic-gate 	    }
209*7c478bd9Sstevel@tonic-gate 
210*7c478bd9Sstevel@tonic-gate 	/*
211*7c478bd9Sstevel@tonic-gate 	 *
212*7c478bd9Sstevel@tonic-gate 	 * Free the space containing the device table's name.
213*7c478bd9Sstevel@tonic-gate 	 */
214*7c478bd9Sstevel@tonic-gate 	    free(oldname);
215*7c478bd9Sstevel@tonic-gate 	}
216*7c478bd9Sstevel@tonic-gate 
217*7c478bd9Sstevel@tonic-gate 	/* Finished.  Return what we've got */
218*7c478bd9Sstevel@tonic-gate 	return (fp);
219*7c478bd9Sstevel@tonic-gate }
220*7c478bd9Sstevel@tonic-gate 
221*7c478bd9Sstevel@tonic-gate /*
222*7c478bd9Sstevel@tonic-gate  *  int rmnewdevtab(tempname)
223*7c478bd9Sstevel@tonic-gate  *	char   *tempname
224*7c478bd9Sstevel@tonic-gate  *
225*7c478bd9Sstevel@tonic-gate  *	Unlink the temp device table and free the memory allocated to
226*7c478bd9Sstevel@tonic-gate  *	contain the name of that file
227*7c478bd9Sstevel@tonic-gate  *
228*7c478bd9Sstevel@tonic-gate  *  Arguments:
229*7c478bd9Sstevel@tonic-gate  *	tempname	Name of the temporary file
230*7c478bd9Sstevel@tonic-gate  *
231*7c478bd9Sstevel@tonic-gate  *  Returns: int
232*7c478bd9Sstevel@tonic-gate  *	TRUE if successful, FALSE otherwise
233*7c478bd9Sstevel@tonic-gate  */
234*7c478bd9Sstevel@tonic-gate 
235*7c478bd9Sstevel@tonic-gate static int
236*7c478bd9Sstevel@tonic-gate rmnewdevtab(char *tempname)	/* Filename of new device table */
237*7c478bd9Sstevel@tonic-gate {
238*7c478bd9Sstevel@tonic-gate 	int	noerr;		/* Flag, TRUE if no error, FALSE otherwise */
239*7c478bd9Sstevel@tonic-gate 
240*7c478bd9Sstevel@tonic-gate 	/* Unlink the file */
241*7c478bd9Sstevel@tonic-gate 	noerr = (unlink(tempname) == 0);
242*7c478bd9Sstevel@tonic-gate 
243*7c478bd9Sstevel@tonic-gate 	/* Free the space allocated to the filename */
244*7c478bd9Sstevel@tonic-gate 	free(tempname);
245*7c478bd9Sstevel@tonic-gate 
246*7c478bd9Sstevel@tonic-gate 	/* Return success indicator */
247*7c478bd9Sstevel@tonic-gate 	return (noerr);
248*7c478bd9Sstevel@tonic-gate }
249*7c478bd9Sstevel@tonic-gate 
250*7c478bd9Sstevel@tonic-gate /*
251*7c478bd9Sstevel@tonic-gate  *  int mknewdevtab(tempname)
252*7c478bd9Sstevel@tonic-gate  *	char   *tempname
253*7c478bd9Sstevel@tonic-gate  *
254*7c478bd9Sstevel@tonic-gate  *	Make the temporary device-table the new system device table
255*7c478bd9Sstevel@tonic-gate  *
256*7c478bd9Sstevel@tonic-gate  *  Arguments:
257*7c478bd9Sstevel@tonic-gate  *	tempname	Name of the temporary file
258*7c478bd9Sstevel@tonic-gate  *
259*7c478bd9Sstevel@tonic-gate  *  Returns:  int
260*7c478bd9Sstevel@tonic-gate  *	TRUE if successful, FALSE otherwise
261*7c478bd9Sstevel@tonic-gate  *
262*7c478bd9Sstevel@tonic-gate  *  Notes:
263*7c478bd9Sstevel@tonic-gate  *	- Need to use rename() someday instead of link()/unlink()
264*7c478bd9Sstevel@tonic-gate  *	- This code is somewhat ineffecient in that asks for the name
265*7c478bd9Sstevel@tonic-gate  *	  of the device-table more than once.  Done so that we don't
266*7c478bd9Sstevel@tonic-gate  *	  have to manage that space, but this may be somewhat lazy.
267*7c478bd9Sstevel@tonic-gate  */
268*7c478bd9Sstevel@tonic-gate 
269*7c478bd9Sstevel@tonic-gate static int
270*7c478bd9Sstevel@tonic-gate mknewdevtab(char   *tempname)		/* Ptr to name of temp dev tab */
271*7c478bd9Sstevel@tonic-gate {
272*7c478bd9Sstevel@tonic-gate 	char   *devtabname;		/* Ptr to the device table's name */
273*7c478bd9Sstevel@tonic-gate 	int	noerr;			/* FLAG, TRUE if all's well */
274*7c478bd9Sstevel@tonic-gate 
275*7c478bd9Sstevel@tonic-gate 	/* Get the device table's pathname */
276*7c478bd9Sstevel@tonic-gate 	if (devtabname = _devtabpath()) {
277*7c478bd9Sstevel@tonic-gate 
278*7c478bd9Sstevel@tonic-gate 	    /* Unlink the existing file */
279*7c478bd9Sstevel@tonic-gate 	    if (unlink(devtabname) == 0) {
280*7c478bd9Sstevel@tonic-gate 
281*7c478bd9Sstevel@tonic-gate 		/* Make the temp file the real device table */
282*7c478bd9Sstevel@tonic-gate 		noerr = (link(tempname, devtabname) == 0) ? TRUE : FALSE;
283*7c478bd9Sstevel@tonic-gate 
284*7c478bd9Sstevel@tonic-gate 		/* Remove the temp file (and resources) */
285*7c478bd9Sstevel@tonic-gate 		if (noerr) (void) rmnewdevtab(tempname);
286*7c478bd9Sstevel@tonic-gate 
287*7c478bd9Sstevel@tonic-gate 	    } else noerr = FALSE;	/* unlink() failed */
288*7c478bd9Sstevel@tonic-gate 
289*7c478bd9Sstevel@tonic-gate 	    /* Free the device table's name */
290*7c478bd9Sstevel@tonic-gate 	    free(devtabname);
291*7c478bd9Sstevel@tonic-gate 
292*7c478bd9Sstevel@tonic-gate 	} else noerr = FALSE; 	/* devtabpath() failed */
293*7c478bd9Sstevel@tonic-gate 
294*7c478bd9Sstevel@tonic-gate 	/* Finished.  Return success indicator */
295*7c478bd9Sstevel@tonic-gate 	return (noerr);
296*7c478bd9Sstevel@tonic-gate }
297*7c478bd9Sstevel@tonic-gate 
298*7c478bd9Sstevel@tonic-gate /*
299*7c478bd9Sstevel@tonic-gate  * static int lkdevtab(o_mode, lktype)
300*7c478bd9Sstevel@tonic-gate  *	char   *o_mode
301*7c478bd9Sstevel@tonic-gate  *	short	lktype
302*7c478bd9Sstevel@tonic-gate  *
303*7c478bd9Sstevel@tonic-gate  *	Lock the device table for writing.  If it isn't available, it waits
304*7c478bd9Sstevel@tonic-gate  *	until it is.
305*7c478bd9Sstevel@tonic-gate  *
306*7c478bd9Sstevel@tonic-gate  *  Arguments:
307*7c478bd9Sstevel@tonic-gate  *	o_mode	The open() mode to use when opening the device table
308*7c478bd9Sstevel@tonic-gate  *	lktype	The type of lock to apply
309*7c478bd9Sstevel@tonic-gate  *
310*7c478bd9Sstevel@tonic-gate  *  Returns:  int
311*7c478bd9Sstevel@tonic-gate  *	TRUE if successful, FALSE with errno set otherwise
312*7c478bd9Sstevel@tonic-gate  */
313*7c478bd9Sstevel@tonic-gate 
314*7c478bd9Sstevel@tonic-gate static int
315*7c478bd9Sstevel@tonic-gate lkdevtab(
316*7c478bd9Sstevel@tonic-gate 	char   *o_mode,				/* Open mode */
317*7c478bd9Sstevel@tonic-gate 	short	lktype)				/* Lock type */
318*7c478bd9Sstevel@tonic-gate {
319*7c478bd9Sstevel@tonic-gate 	/* Automatic data */
320*7c478bd9Sstevel@tonic-gate 	struct flock	lockinfo;		/* File locking structure */
321*7c478bd9Sstevel@tonic-gate 	int		noerr;			/* FLAG, TRUE if no error */
322*7c478bd9Sstevel@tonic-gate 	int		olderrno;		/* Old value of "errno" */
323*7c478bd9Sstevel@tonic-gate 
324*7c478bd9Sstevel@tonic-gate 
325*7c478bd9Sstevel@tonic-gate 	/* Close the device table (if it's open) */
326*7c478bd9Sstevel@tonic-gate 	_enddevtab();
327*7c478bd9Sstevel@tonic-gate 
328*7c478bd9Sstevel@tonic-gate 	/* Open the device table for read/append */
329*7c478bd9Sstevel@tonic-gate 	noerr = TRUE;
330*7c478bd9Sstevel@tonic-gate 	if (_opendevtab(o_mode)) {
331*7c478bd9Sstevel@tonic-gate 
332*7c478bd9Sstevel@tonic-gate 	/*
333*7c478bd9Sstevel@tonic-gate 	 * Lock the device table (for writing).  If it's not
334*7c478bd9Sstevel@tonic-gate 	 * available, wait until it is, then close and open the
335*7c478bd9Sstevel@tonic-gate 	 * table (modify and delete change the table!) and try
336*7c478bd9Sstevel@tonic-gate 	 * to lock it again
337*7c478bd9Sstevel@tonic-gate 	 */
338*7c478bd9Sstevel@tonic-gate 
339*7c478bd9Sstevel@tonic-gate 	    /* Build the locking structure */
340*7c478bd9Sstevel@tonic-gate 	    lockinfo.l_type = lktype;
341*7c478bd9Sstevel@tonic-gate 	    lockinfo.l_whence = 0;
342*7c478bd9Sstevel@tonic-gate 	    lockinfo.l_start = 0L;
343*7c478bd9Sstevel@tonic-gate 	    lockinfo.l_len = 0L;
344*7c478bd9Sstevel@tonic-gate 	    olderrno = errno;
345*7c478bd9Sstevel@tonic-gate 
346*7c478bd9Sstevel@tonic-gate 	    /* Keep on going until we lock the file or an error happens */
347*7c478bd9Sstevel@tonic-gate 	    while ((fcntl(fileno(oam_devtab), F_SETLK, &lockinfo) == -1) &&
348*7c478bd9Sstevel@tonic-gate 		!noerr) {
349*7c478bd9Sstevel@tonic-gate 		if (errno == EACCES) {
350*7c478bd9Sstevel@tonic-gate 		    if (fcntl(fileno(oam_devtab), F_SETLKW, &lockinfo) == -1)
351*7c478bd9Sstevel@tonic-gate 			noerr = FALSE;
352*7c478bd9Sstevel@tonic-gate 		    else {
353*7c478bd9Sstevel@tonic-gate 			/* Reopen the file (maybe it's moved?) */
354*7c478bd9Sstevel@tonic-gate 			_enddevtab();
355*7c478bd9Sstevel@tonic-gate 			if (!_opendevtab(o_mode)) noerr = FALSE;
356*7c478bd9Sstevel@tonic-gate 			else errno = olderrno;
357*7c478bd9Sstevel@tonic-gate 		    }
358*7c478bd9Sstevel@tonic-gate 		} else noerr = FALSE;
359*7c478bd9Sstevel@tonic-gate 	    }
360*7c478bd9Sstevel@tonic-gate 
361*7c478bd9Sstevel@tonic-gate 	    if (!noerr) _enddevtab();  /* Don't keep open if in error */
362*7c478bd9Sstevel@tonic-gate 
363*7c478bd9Sstevel@tonic-gate 	} else noerr = FALSE;
364*7c478bd9Sstevel@tonic-gate 
365*7c478bd9Sstevel@tonic-gate 	/* Done */
366*7c478bd9Sstevel@tonic-gate 	return (noerr);
367*7c478bd9Sstevel@tonic-gate }
368*7c478bd9Sstevel@tonic-gate 
369*7c478bd9Sstevel@tonic-gate /*
370*7c478bd9Sstevel@tonic-gate  * int unlkdevtab()
371*7c478bd9Sstevel@tonic-gate  *
372*7c478bd9Sstevel@tonic-gate  *	Unlock the locked device table.
373*7c478bd9Sstevel@tonic-gate  *
374*7c478bd9Sstevel@tonic-gate  *  Arguments:  None
375*7c478bd9Sstevel@tonic-gate  *
376*7c478bd9Sstevel@tonic-gate  *  Returns:  int
377*7c478bd9Sstevel@tonic-gate  *	Whatever fcntl() returns...
378*7c478bd9Sstevel@tonic-gate  */
379*7c478bd9Sstevel@tonic-gate 
380*7c478bd9Sstevel@tonic-gate static int
381*7c478bd9Sstevel@tonic-gate unlkdevtab(void)
382*7c478bd9Sstevel@tonic-gate {
383*7c478bd9Sstevel@tonic-gate 	/* Automatic data */
384*7c478bd9Sstevel@tonic-gate 	struct flock	lockinfo;		/* Locking structure */
385*7c478bd9Sstevel@tonic-gate 	int		noerr;			/* FLAG, TRUE if all's well */
386*7c478bd9Sstevel@tonic-gate 
387*7c478bd9Sstevel@tonic-gate 	/* Build the locking structure */
388*7c478bd9Sstevel@tonic-gate 	lockinfo.l_type = F_UNLCK;		/* Lock type */
389*7c478bd9Sstevel@tonic-gate 	lockinfo.l_whence = 0;			/* Count from top of file */
390*7c478bd9Sstevel@tonic-gate 	lockinfo.l_start = 0L;			/* From beginning */
391*7c478bd9Sstevel@tonic-gate 	lockinfo.l_len = 0L;			/* Length of locked data */
392*7c478bd9Sstevel@tonic-gate 
393*7c478bd9Sstevel@tonic-gate 	/* Unlock it */
394*7c478bd9Sstevel@tonic-gate 	noerr = (fcntl(fileno(oam_devtab), F_SETLK, &lockinfo) != -1);
395*7c478bd9Sstevel@tonic-gate 	_enddevtab();
396*7c478bd9Sstevel@tonic-gate 
397*7c478bd9Sstevel@tonic-gate 	/* Finished */
398*7c478bd9Sstevel@tonic-gate 	return (noerr);
399*7c478bd9Sstevel@tonic-gate }
400*7c478bd9Sstevel@tonic-gate 
401*7c478bd9Sstevel@tonic-gate /*
402*7c478bd9Sstevel@tonic-gate  * struct devtabent *mkdevtabent(alias, attrlist)
403*7c478bd9Sstevel@tonic-gate  *	char   *alias
404*7c478bd9Sstevel@tonic-gate  *	char  **attrlist
405*7c478bd9Sstevel@tonic-gate  *
406*7c478bd9Sstevel@tonic-gate  *	This function builds a struct devtabent structure describing the
407*7c478bd9Sstevel@tonic-gate  *	alias <alias> using the information in the attribute list <attrlist>.
408*7c478bd9Sstevel@tonic-gate  *	The <attrlist> contains data of the form attr=value where attr is
409*7c478bd9Sstevel@tonic-gate  *	the name of an attribute and value is the value of that attribute.
410*7c478bd9Sstevel@tonic-gate  *
411*7c478bd9Sstevel@tonic-gate  *  Arguments:
412*7c478bd9Sstevel@tonic-gate  *	alias		The alias being added to the device table
413*7c478bd9Sstevel@tonic-gate  *	attrlist	The attributes and values for that alias
414*7c478bd9Sstevel@tonic-gate  *
415*7c478bd9Sstevel@tonic-gate  *  Returns:  struct devtabent *
416*7c478bd9Sstevel@tonic-gate  *	A completed struct devtabent structure containing the description
417*7c478bd9Sstevel@tonic-gate  *	of the alias.  The structure, and all of the data in the structure
418*7c478bd9Sstevel@tonic-gate  *	are each in space allocated using the malloc() function and should
419*7c478bd9Sstevel@tonic-gate  *	be freed using the free() function (or the _freedevtabent() function).
420*7c478bd9Sstevel@tonic-gate  *
421*7c478bd9Sstevel@tonic-gate  *  Errors:
422*7c478bd9Sstevel@tonic-gate  *	EINVAL	If "alias" is used as an attribute in an attr=val pair
423*7c478bd9Sstevel@tonic-gate  *	EAGAIN	If an attribute is specified more than once
424*7c478bd9Sstevel@tonic-gate  */
425*7c478bd9Sstevel@tonic-gate 
426*7c478bd9Sstevel@tonic-gate static struct devtabent *
427*7c478bd9Sstevel@tonic-gate mkdevtabent(
428*7c478bd9Sstevel@tonic-gate 	char   *alias,		/* Alias of entry */
429*7c478bd9Sstevel@tonic-gate 	char  **attrlist)	/* Attributes of new entry */
430*7c478bd9Sstevel@tonic-gate {
431*7c478bd9Sstevel@tonic-gate 	/* Automatic data */
432*7c478bd9Sstevel@tonic-gate 	struct devtabent	*devtabent;	/* * to struct we're making */
433*7c478bd9Sstevel@tonic-gate 	struct attrval		*prevattrval;	/* * to prev attr/val struct */
434*7c478bd9Sstevel@tonic-gate 	struct attrval		*attrval;	/* * to current struct */
435*7c478bd9Sstevel@tonic-gate 	char			**pp;		/* Ptr into list of ptrs */
436*7c478bd9Sstevel@tonic-gate 	char			*peq;		/* Ptr to '=' in string */
437*7c478bd9Sstevel@tonic-gate 	char			*val;		/* Ptr to space for value */
438*7c478bd9Sstevel@tonic-gate 	char			*name;		/* Ptr to space for name */
439*7c478bd9Sstevel@tonic-gate 	ssize_t			len;		/* Length of name */
440*7c478bd9Sstevel@tonic-gate 	int			noerr;		/* TRUE if all's well */
441*7c478bd9Sstevel@tonic-gate 	int			found;		/* TRUE the attr is found */
442*7c478bd9Sstevel@tonic-gate 
443*7c478bd9Sstevel@tonic-gate 
444*7c478bd9Sstevel@tonic-gate 	/* No problems (yet) */
445*7c478bd9Sstevel@tonic-gate 	noerr = TRUE;
446*7c478bd9Sstevel@tonic-gate 
447*7c478bd9Sstevel@tonic-gate 	/* Get space for the structure */
448*7c478bd9Sstevel@tonic-gate 	if (devtabent = malloc(sizeof (struct devtabent))) {
449*7c478bd9Sstevel@tonic-gate 
450*7c478bd9Sstevel@tonic-gate 	    /* Fill in default values */
451*7c478bd9Sstevel@tonic-gate 	    if (devtabent->alias = malloc(strlen(alias)+1)) {
452*7c478bd9Sstevel@tonic-gate 
453*7c478bd9Sstevel@tonic-gate 		(void) strcpy(devtabent->alias, alias);		/* alias */
454*7c478bd9Sstevel@tonic-gate 		devtabent->comment = FALSE;			/* data rec */
455*7c478bd9Sstevel@tonic-gate 		devtabent->cdevice = NULL;			/* cdevice */
456*7c478bd9Sstevel@tonic-gate 		devtabent->bdevice = NULL;			/* bdevice */
457*7c478bd9Sstevel@tonic-gate 		devtabent->pathname = NULL;			/* pathname */
458*7c478bd9Sstevel@tonic-gate 		devtabent->attrstr = NULL;			/* string */
459*7c478bd9Sstevel@tonic-gate 		devtabent->attrlist = NULL;			/* attr list */
460*7c478bd9Sstevel@tonic-gate 
461*7c478bd9Sstevel@tonic-gate 		/* Add attributes to the structure */
462*7c478bd9Sstevel@tonic-gate 		prevattrval = NULL;
463*7c478bd9Sstevel@tonic-gate 		if ((pp = attrlist) != NULL)
464*7c478bd9Sstevel@tonic-gate 		    while (*pp && noerr) {
465*7c478bd9Sstevel@tonic-gate 
466*7c478bd9Sstevel@tonic-gate 		    /* Valid attr=value pair? */
467*7c478bd9Sstevel@tonic-gate 		    if (((peq = strchr(*pp, '=')) != NULL) &&
468*7c478bd9Sstevel@tonic-gate 			((len = peq - *pp) > 0)) {
469*7c478bd9Sstevel@tonic-gate 
470*7c478bd9Sstevel@tonic-gate 			/* Get space for the value */
471*7c478bd9Sstevel@tonic-gate 			if (val = malloc(strlen(peq))) {
472*7c478bd9Sstevel@tonic-gate 			    (void) strcpy(val, peq+1);		/* Copy it */
473*7c478bd9Sstevel@tonic-gate 
474*7c478bd9Sstevel@tonic-gate 			    /* Get space for attribute name */
475*7c478bd9Sstevel@tonic-gate 			    if (name = malloc((size_t)(len + 1))) {
476*7c478bd9Sstevel@tonic-gate 				(void) strncpy(name, *pp, (size_t)len);
477*7c478bd9Sstevel@tonic-gate 				*(name+len) = '\0';
478*7c478bd9Sstevel@tonic-gate 
479*7c478bd9Sstevel@tonic-gate 				/* Specifying the alias?  If so, ERROR */
480*7c478bd9Sstevel@tonic-gate 				if (strcmp(name, DTAB_ALIAS) == 0) {
481*7c478bd9Sstevel@tonic-gate 				    noerr = FALSE;
482*7c478bd9Sstevel@tonic-gate 				    free(name);
483*7c478bd9Sstevel@tonic-gate 				    free(val);
484*7c478bd9Sstevel@tonic-gate 				    errno = EINVAL;
485*7c478bd9Sstevel@tonic-gate 				}
486*7c478bd9Sstevel@tonic-gate 
487*7c478bd9Sstevel@tonic-gate 				/* Specifying the char device path? */
488*7c478bd9Sstevel@tonic-gate 				else if (strcmp(name, DTAB_CDEVICE) == 0) {
489*7c478bd9Sstevel@tonic-gate 				    if (!devtabent->cdevice) {
490*7c478bd9Sstevel@tonic-gate 					if (val[0] != '/') {
491*7c478bd9Sstevel@tonic-gate 						noerr = FALSE;
492*7c478bd9Sstevel@tonic-gate 						free(name);
493*7c478bd9Sstevel@tonic-gate 						free(val);
494*7c478bd9Sstevel@tonic-gate 						errno = ENXIO;
495*7c478bd9Sstevel@tonic-gate 					} else {
496*7c478bd9Sstevel@tonic-gate 						devtabent->cdevice = val;
497*7c478bd9Sstevel@tonic-gate 						free(name);
498*7c478bd9Sstevel@tonic-gate 					}
499*7c478bd9Sstevel@tonic-gate 				    } else {
500*7c478bd9Sstevel@tonic-gate 					noerr = FALSE;
501*7c478bd9Sstevel@tonic-gate 					free(name);
502*7c478bd9Sstevel@tonic-gate 					free(val);
503*7c478bd9Sstevel@tonic-gate 					errno = EAGAIN;
504*7c478bd9Sstevel@tonic-gate 				    }
505*7c478bd9Sstevel@tonic-gate 				}
506*7c478bd9Sstevel@tonic-gate 
507*7c478bd9Sstevel@tonic-gate 				/* Specifying the block device path? */
508*7c478bd9Sstevel@tonic-gate 				else if (strcmp(name, DTAB_BDEVICE) == 0) {
509*7c478bd9Sstevel@tonic-gate 				    if (!devtabent->bdevice) {
510*7c478bd9Sstevel@tonic-gate 					if (val[0] != '/') {
511*7c478bd9Sstevel@tonic-gate 						noerr = FALSE;
512*7c478bd9Sstevel@tonic-gate 						free(name);
513*7c478bd9Sstevel@tonic-gate 						free(val);
514*7c478bd9Sstevel@tonic-gate 						errno = ENXIO;
515*7c478bd9Sstevel@tonic-gate 					} else {
516*7c478bd9Sstevel@tonic-gate 						devtabent->bdevice = val;
517*7c478bd9Sstevel@tonic-gate 						free(name);
518*7c478bd9Sstevel@tonic-gate 					}
519*7c478bd9Sstevel@tonic-gate 				    } else {
520*7c478bd9Sstevel@tonic-gate 					noerr = FALSE;
521*7c478bd9Sstevel@tonic-gate 					free(name);
522*7c478bd9Sstevel@tonic-gate 					free(val);
523*7c478bd9Sstevel@tonic-gate 					errno = EAGAIN;
524*7c478bd9Sstevel@tonic-gate 				    }
525*7c478bd9Sstevel@tonic-gate 				}
526*7c478bd9Sstevel@tonic-gate 
527*7c478bd9Sstevel@tonic-gate 				/* Specifying the pathname (generic)? */
528*7c478bd9Sstevel@tonic-gate 				else if (strcmp(name, DTAB_PATHNAME) == 0) {
529*7c478bd9Sstevel@tonic-gate 				    if (!devtabent->pathname) {
530*7c478bd9Sstevel@tonic-gate 					if (val[0] != '/') {
531*7c478bd9Sstevel@tonic-gate 						noerr = FALSE;
532*7c478bd9Sstevel@tonic-gate 						free(name);
533*7c478bd9Sstevel@tonic-gate 						free(val);
534*7c478bd9Sstevel@tonic-gate 						errno = ENXIO;
535*7c478bd9Sstevel@tonic-gate 					} else {
536*7c478bd9Sstevel@tonic-gate 						devtabent->pathname = val;
537*7c478bd9Sstevel@tonic-gate 						free(name);
538*7c478bd9Sstevel@tonic-gate 					}
539*7c478bd9Sstevel@tonic-gate 				    } else {
540*7c478bd9Sstevel@tonic-gate 					noerr = FALSE;
541*7c478bd9Sstevel@tonic-gate 					free(name);
542*7c478bd9Sstevel@tonic-gate 					free(val);
543*7c478bd9Sstevel@tonic-gate 					errno = EAGAIN;
544*7c478bd9Sstevel@tonic-gate 				    }
545*7c478bd9Sstevel@tonic-gate 				}
546*7c478bd9Sstevel@tonic-gate 
547*7c478bd9Sstevel@tonic-gate 				/* Some other attribute */
548*7c478bd9Sstevel@tonic-gate 				else {
549*7c478bd9Sstevel@tonic-gate 				    found = FALSE;
550*7c478bd9Sstevel@tonic-gate 				    if ((attrval = devtabent->attrlist) != NULL)
551*7c478bd9Sstevel@tonic-gate 					do {
552*7c478bd9Sstevel@tonic-gate 					    if (strcmp(attrval->attr,
553*7c478bd9Sstevel@tonic-gate 						name) == 0) {
554*7c478bd9Sstevel@tonic-gate 
555*7c478bd9Sstevel@tonic-gate 						noerr = FALSE;
556*7c478bd9Sstevel@tonic-gate 						free(name);
557*7c478bd9Sstevel@tonic-gate 						free(val);
558*7c478bd9Sstevel@tonic-gate 						errno = EAGAIN;
559*7c478bd9Sstevel@tonic-gate 					    }
560*7c478bd9Sstevel@tonic-gate 					} while (!found && noerr &&
561*7c478bd9Sstevel@tonic-gate 					    (attrval = attrval->next));
562*7c478bd9Sstevel@tonic-gate 
563*7c478bd9Sstevel@tonic-gate 				    if (!found && noerr) {
564*7c478bd9Sstevel@tonic-gate 
565*7c478bd9Sstevel@tonic-gate 					/* Get space for attr/val structure */
566*7c478bd9Sstevel@tonic-gate 					if (attrval =
567*7c478bd9Sstevel@tonic-gate 					    malloc(sizeof (struct attrval))) {
568*7c478bd9Sstevel@tonic-gate 
569*7c478bd9Sstevel@tonic-gate 					    /* Fill attr/val structure */
570*7c478bd9Sstevel@tonic-gate 					    attrval->attr = name;
571*7c478bd9Sstevel@tonic-gate 					    attrval->val = val;
572*7c478bd9Sstevel@tonic-gate 					    attrval->next = NULL;
573*7c478bd9Sstevel@tonic-gate 
574*7c478bd9Sstevel@tonic-gate 					/*
575*7c478bd9Sstevel@tonic-gate 					 * Link into the list of attributes
576*7c478bd9Sstevel@tonic-gate 					 */
577*7c478bd9Sstevel@tonic-gate 					    if (prevattrval)
578*7c478bd9Sstevel@tonic-gate 						prevattrval->next = attrval;
579*7c478bd9Sstevel@tonic-gate 					    else devtabent->attrlist = attrval;
580*7c478bd9Sstevel@tonic-gate 					    prevattrval = attrval;
581*7c478bd9Sstevel@tonic-gate 
582*7c478bd9Sstevel@tonic-gate 					} else {
583*7c478bd9Sstevel@tonic-gate 					    /* malloc() for attrval failed */
584*7c478bd9Sstevel@tonic-gate 					    noerr = FALSE;
585*7c478bd9Sstevel@tonic-gate 					    free(name);
586*7c478bd9Sstevel@tonic-gate 					    free(val);
587*7c478bd9Sstevel@tonic-gate 					}
588*7c478bd9Sstevel@tonic-gate 				    }
589*7c478bd9Sstevel@tonic-gate 				}   /* End else (some other attribute) */
590*7c478bd9Sstevel@tonic-gate 
591*7c478bd9Sstevel@tonic-gate 			    } else { 	/* malloc() for attribute name failed */
592*7c478bd9Sstevel@tonic-gate 				noerr = FALSE;
593*7c478bd9Sstevel@tonic-gate 				free(val);
594*7c478bd9Sstevel@tonic-gate 			    }
595*7c478bd9Sstevel@tonic-gate 
596*7c478bd9Sstevel@tonic-gate 			} else noerr = FALSE;	/* Malloc() for "val" failed */
597*7c478bd9Sstevel@tonic-gate 
598*7c478bd9Sstevel@tonic-gate 			/* If we saw an error, free structure, returning NULL */
599*7c478bd9Sstevel@tonic-gate 			if (!noerr) {
600*7c478bd9Sstevel@tonic-gate 			    _freedevtabent(devtabent);
601*7c478bd9Sstevel@tonic-gate 			    devtabent = NULL;
602*7c478bd9Sstevel@tonic-gate 			}
603*7c478bd9Sstevel@tonic-gate 
604*7c478bd9Sstevel@tonic-gate 		    } 	/* Ignore invalid attr=val pair */
605*7c478bd9Sstevel@tonic-gate 
606*7c478bd9Sstevel@tonic-gate 		    if (noerr) pp++;
607*7c478bd9Sstevel@tonic-gate 
608*7c478bd9Sstevel@tonic-gate 		}   /* End attribute processing loop */
609*7c478bd9Sstevel@tonic-gate 
610*7c478bd9Sstevel@tonic-gate 	    } else {	/* malloc() failed */
611*7c478bd9Sstevel@tonic-gate 		free(devtabent);
612*7c478bd9Sstevel@tonic-gate 		devtabent = NULL;
613*7c478bd9Sstevel@tonic-gate 	    }
614*7c478bd9Sstevel@tonic-gate 	}
615*7c478bd9Sstevel@tonic-gate 
616*7c478bd9Sstevel@tonic-gate 	/* Finished */
617*7c478bd9Sstevel@tonic-gate 	return (devtabent);
618*7c478bd9Sstevel@tonic-gate }
619*7c478bd9Sstevel@tonic-gate 
620*7c478bd9Sstevel@tonic-gate /*
621*7c478bd9Sstevel@tonic-gate  * int _putdevtabrec(stream, rec)
622*7c478bd9Sstevel@tonic-gate  *	FILE		       *stream
623*7c478bd9Sstevel@tonic-gate  *	struct devtabent       *rec
624*7c478bd9Sstevel@tonic-gate  *
625*7c478bd9Sstevel@tonic-gate  *	Write a device table record containing the information in the struct
626*7c478bd9Sstevel@tonic-gate  *	devtab structure <rec> to the current position of the standard I/O
627*7c478bd9Sstevel@tonic-gate  *	stream <stream>.
628*7c478bd9Sstevel@tonic-gate  *
629*7c478bd9Sstevel@tonic-gate  *  Arguments:
630*7c478bd9Sstevel@tonic-gate  *	stream		The stream to write to
631*7c478bd9Sstevel@tonic-gate  *	rec		The structure containing the information to write
632*7c478bd9Sstevel@tonic-gate  *
633*7c478bd9Sstevel@tonic-gate  *  Returns:  int
634*7c478bd9Sstevel@tonic-gate  *	The number of characters written or EOF if there was some error.
635*7c478bd9Sstevel@tonic-gate  */
636*7c478bd9Sstevel@tonic-gate 
637*7c478bd9Sstevel@tonic-gate int
638*7c478bd9Sstevel@tonic-gate _putdevtabrec(
639*7c478bd9Sstevel@tonic-gate 	FILE			*stream,	/* Stream to which to write */
640*7c478bd9Sstevel@tonic-gate 	struct devtabent	*rec)		/* Record to write */
641*7c478bd9Sstevel@tonic-gate {
642*7c478bd9Sstevel@tonic-gate 	/* Automatic Data */
643*7c478bd9Sstevel@tonic-gate 	struct attrval		*attrval;	/* Ptr to attr/val pair */
644*7c478bd9Sstevel@tonic-gate 	char			*buf;		/* Allocated buffer */
645*7c478bd9Sstevel@tonic-gate 	char			*p;		/* Temp char pointer */
646*7c478bd9Sstevel@tonic-gate 	int			count;		/* Number of chars written */
647*7c478bd9Sstevel@tonic-gate 	size_t			size = 0;	/* Size of needed buffer */
648*7c478bd9Sstevel@tonic-gate 
649*7c478bd9Sstevel@tonic-gate 
650*7c478bd9Sstevel@tonic-gate 	/* Comment or data record? */
651*7c478bd9Sstevel@tonic-gate 	if (rec->comment) {
652*7c478bd9Sstevel@tonic-gate 
653*7c478bd9Sstevel@tonic-gate 	/*
654*7c478bd9Sstevel@tonic-gate 	 * Record is a comment
655*7c478bd9Sstevel@tonic-gate 	 */
656*7c478bd9Sstevel@tonic-gate 
657*7c478bd9Sstevel@tonic-gate 	    /* Copy (escaping chars) record into temp buffer */
658*7c478bd9Sstevel@tonic-gate 	    size = (strlen(rec->attrstr)*2)+1;		/* Max rec size */
659*7c478bd9Sstevel@tonic-gate 	    if (buf = malloc(size+1)) {
660*7c478bd9Sstevel@tonic-gate 		/* Alloc space */
661*7c478bd9Sstevel@tonic-gate 		p = strcatesc(buf, rec->attrstr);	/* Copy "escaped" */
662*7c478bd9Sstevel@tonic-gate 		*(p-2) = '\n';				/* Unescape last \n */
663*7c478bd9Sstevel@tonic-gate 		*(p-1) = '\0';				/* Terminate string */
664*7c478bd9Sstevel@tonic-gate 
665*7c478bd9Sstevel@tonic-gate 		/* Write the record */
666*7c478bd9Sstevel@tonic-gate 		count = fputs(buf, stream);
667*7c478bd9Sstevel@tonic-gate 		free(buf);
668*7c478bd9Sstevel@tonic-gate 
669*7c478bd9Sstevel@tonic-gate 	    } else count = EOF;  /* malloc() failed */
670*7c478bd9Sstevel@tonic-gate 	}
671*7c478bd9Sstevel@tonic-gate 
672*7c478bd9Sstevel@tonic-gate 	else {
673*7c478bd9Sstevel@tonic-gate 
674*7c478bd9Sstevel@tonic-gate 		/*
675*7c478bd9Sstevel@tonic-gate 		 * Record is a data record
676*7c478bd9Sstevel@tonic-gate 		 */
677*7c478bd9Sstevel@tonic-gate 
678*7c478bd9Sstevel@tonic-gate 		/*
679*7c478bd9Sstevel@tonic-gate 		 * Figure out maximum amount of space you're going to need.
680*7c478bd9Sstevel@tonic-gate 		 * (Assume every escapable character is escaped to determine the
681*7c478bd9Sstevel@tonic-gate 		 * maximum size needed)
682*7c478bd9Sstevel@tonic-gate 		 */
683*7c478bd9Sstevel@tonic-gate 
684*7c478bd9Sstevel@tonic-gate 	    if (rec->cdevice)
685*7c478bd9Sstevel@tonic-gate 		size += (strlen(rec->cdevice)*2) + 1;	/* cdevice: */
686*7c478bd9Sstevel@tonic-gate 	    if (rec->bdevice)
687*7c478bd9Sstevel@tonic-gate 		size += (strlen(rec->bdevice)*2) + 1;	/* bdevice: */
688*7c478bd9Sstevel@tonic-gate 	    if (rec->pathname)
689*7c478bd9Sstevel@tonic-gate 		size += (strlen(rec->pathname)*2) + 1;	/* pathname: */
690*7c478bd9Sstevel@tonic-gate 	    if ((attrval = rec->attrlist) != NULL) do {	/* Attributes */
691*7c478bd9Sstevel@tonic-gate 		if (attrval->attr)
692*7c478bd9Sstevel@tonic-gate 			size += (strlen(attrval->attr)*2);	    /* attr */
693*7c478bd9Sstevel@tonic-gate 		if (attrval->val) {
694*7c478bd9Sstevel@tonic-gate 			/* val & '="" ' or val & '=""\n' */
695*7c478bd9Sstevel@tonic-gate 			size += (strlen(attrval->val)*2) +4;
696*7c478bd9Sstevel@tonic-gate 		}
697*7c478bd9Sstevel@tonic-gate 	    } while ((attrval = attrval->next) != NULL);    /* Next attr/val */
698*7c478bd9Sstevel@tonic-gate 	    else size++;		/* Else make room for trailing '\n' */
699*7c478bd9Sstevel@tonic-gate 
700*7c478bd9Sstevel@tonic-gate 	    /* Alloc space for "escaped" record */
701*7c478bd9Sstevel@tonic-gate 	    if (buf = malloc(size+1)) {
702*7c478bd9Sstevel@tonic-gate 
703*7c478bd9Sstevel@tonic-gate 		/* Initializations */
704*7c478bd9Sstevel@tonic-gate 		p = buf;
705*7c478bd9Sstevel@tonic-gate 
706*7c478bd9Sstevel@tonic-gate 		/* Write the alias ("alias" attribute) */
707*7c478bd9Sstevel@tonic-gate 		p = strcatesc(p, rec->alias);
708*7c478bd9Sstevel@tonic-gate 		*p++ = ':';
709*7c478bd9Sstevel@tonic-gate 
710*7c478bd9Sstevel@tonic-gate 		/* Write the character device ("cdevice" attribute) */
711*7c478bd9Sstevel@tonic-gate 		if (rec->cdevice) p = strcatesc(p, rec->cdevice);
712*7c478bd9Sstevel@tonic-gate 		*p++ = ':';
713*7c478bd9Sstevel@tonic-gate 
714*7c478bd9Sstevel@tonic-gate 		/* Write the block device ("bdevice" attribute) */
715*7c478bd9Sstevel@tonic-gate 		if (rec->bdevice) p = strcatesc(p, rec->bdevice);
716*7c478bd9Sstevel@tonic-gate 		*p++ = ':';
717*7c478bd9Sstevel@tonic-gate 
718*7c478bd9Sstevel@tonic-gate 		/* Write the pathname ("pathname" attribute) */
719*7c478bd9Sstevel@tonic-gate 		if (rec->pathname) p = strcatesc(p, rec->pathname);
720*7c478bd9Sstevel@tonic-gate 		*p++ = ':';
721*7c478bd9Sstevel@tonic-gate 
722*7c478bd9Sstevel@tonic-gate 		/* Write the rest of the attributes */
723*7c478bd9Sstevel@tonic-gate 		if ((attrval = rec->attrlist) != NULL)
724*7c478bd9Sstevel@tonic-gate 		    do {
725*7c478bd9Sstevel@tonic-gate 			p = strcatesc(p, attrval->attr);
726*7c478bd9Sstevel@tonic-gate 			*p++ = '=';
727*7c478bd9Sstevel@tonic-gate 			*p++ = '"';
728*7c478bd9Sstevel@tonic-gate 			p = strcatesc(p, attrval->val);
729*7c478bd9Sstevel@tonic-gate 			*p++ = '"';
730*7c478bd9Sstevel@tonic-gate 			if ((attrval = attrval->next) != NULL)
731*7c478bd9Sstevel@tonic-gate 			    *p++ = ' ';
732*7c478bd9Sstevel@tonic-gate 		    } while (attrval);
733*7c478bd9Sstevel@tonic-gate 
734*7c478bd9Sstevel@tonic-gate 		/* Terminate the record */
735*7c478bd9Sstevel@tonic-gate 		*p++ = '\n';
736*7c478bd9Sstevel@tonic-gate 		*p = '\0';
737*7c478bd9Sstevel@tonic-gate 
738*7c478bd9Sstevel@tonic-gate 		/* Write the record */
739*7c478bd9Sstevel@tonic-gate 		count = fputs(buf, stream);
740*7c478bd9Sstevel@tonic-gate 		free(buf);
741*7c478bd9Sstevel@tonic-gate 	    } else count = EOF;  /* malloc() failed */
742*7c478bd9Sstevel@tonic-gate 	}
743*7c478bd9Sstevel@tonic-gate 
744*7c478bd9Sstevel@tonic-gate 	/* Finished */
745*7c478bd9Sstevel@tonic-gate 	return (count);
746*7c478bd9Sstevel@tonic-gate }
747*7c478bd9Sstevel@tonic-gate 
748*7c478bd9Sstevel@tonic-gate /*
749*7c478bd9Sstevel@tonic-gate  *  int _adddevtabrec(alias, attrval)
750*7c478bd9Sstevel@tonic-gate  *	char   *alias
751*7c478bd9Sstevel@tonic-gate  *	char  **attrval
752*7c478bd9Sstevel@tonic-gate  *
753*7c478bd9Sstevel@tonic-gate  *	This function adds a record to the device table.  That record will
754*7c478bd9Sstevel@tonic-gate  *	have the alias <alias> and will have the attributes described in
755*7c478bd9Sstevel@tonic-gate  *	the list referenced by <attrval>.
756*7c478bd9Sstevel@tonic-gate  *
757*7c478bd9Sstevel@tonic-gate  *	It always adds the record to the end of the table.
758*7c478bd9Sstevel@tonic-gate  *
759*7c478bd9Sstevel@tonic-gate  *  Arguments:
760*7c478bd9Sstevel@tonic-gate  *	alias		The alias of the device whose description is being
761*7c478bd9Sstevel@tonic-gate  *			added to the device table.
762*7c478bd9Sstevel@tonic-gate  *	attrval		The pointer to the first item of a list of attributes
763*7c478bd9Sstevel@tonic-gate  *			defining the device whose description is being added.
764*7c478bd9Sstevel@tonic-gate  *			(This value may be (char **) NULL).
765*7c478bd9Sstevel@tonic-gate  *
766*7c478bd9Sstevel@tonic-gate  *  Returns:  int
767*7c478bd9Sstevel@tonic-gate  *	TRUE if successful, FALSE with errno set otherwise.
768*7c478bd9Sstevel@tonic-gate  */
769*7c478bd9Sstevel@tonic-gate 
770*7c478bd9Sstevel@tonic-gate int
771*7c478bd9Sstevel@tonic-gate _adddevtabrec(
772*7c478bd9Sstevel@tonic-gate 	char   *alias,			/* Alias to add to the device table */
773*7c478bd9Sstevel@tonic-gate 	char  **attrval)		/* Attributes for that device */
774*7c478bd9Sstevel@tonic-gate {
775*7c478bd9Sstevel@tonic-gate 	/* Automatic data */
776*7c478bd9Sstevel@tonic-gate 	struct devtabent	*devtabent;	/* Ptr to dev tab entry */
777*7c478bd9Sstevel@tonic-gate 	int			olderrno;	/* Errno on entry */
778*7c478bd9Sstevel@tonic-gate 	int			noerr;		/* FLAG, TRUE if all's well */
779*7c478bd9Sstevel@tonic-gate 
780*7c478bd9Sstevel@tonic-gate 	/* Validate the device alias.  Error (EINVAL) if it's not valid */
781*7c478bd9Sstevel@tonic-gate 	if (!_validalias(alias)) {
782*7c478bd9Sstevel@tonic-gate 	    errno = EINVAL;
783*7c478bd9Sstevel@tonic-gate 	    return (FALSE);
784*7c478bd9Sstevel@tonic-gate 	}
785*7c478bd9Sstevel@tonic-gate 
786*7c478bd9Sstevel@tonic-gate 	/*
787*7c478bd9Sstevel@tonic-gate 	 * Lock the device table.  This only returns if the table is locked or
788*7c478bd9Sstevel@tonic-gate 	 * some error occurred.  It waits until the table is available.
789*7c478bd9Sstevel@tonic-gate 	 */
790*7c478bd9Sstevel@tonic-gate 	if (!lkdevtab("a+", F_WRLCK))
791*7c478bd9Sstevel@tonic-gate 		return (FALSE);
792*7c478bd9Sstevel@tonic-gate 
793*7c478bd9Sstevel@tonic-gate 	/* Make sure that the alias isn't already in the table */
794*7c478bd9Sstevel@tonic-gate 	noerr = TRUE;
795*7c478bd9Sstevel@tonic-gate 	olderrno = errno;
796*7c478bd9Sstevel@tonic-gate 	if (devtabent = _getdevrec(alias)) {
797*7c478bd9Sstevel@tonic-gate 
798*7c478bd9Sstevel@tonic-gate 	    /* The alias is already in the table */
799*7c478bd9Sstevel@tonic-gate 	    _freedevtabent(devtabent);		/* Free device table info */
800*7c478bd9Sstevel@tonic-gate 	    errno = EEXIST;			/* Set errno, entry exists */
801*7c478bd9Sstevel@tonic-gate 	    noerr = FALSE;			/* All's not well */
802*7c478bd9Sstevel@tonic-gate 	} else if ((errno == ENOENT) || (errno == ENODEV)) {
803*7c478bd9Sstevel@tonic-gate 
804*7c478bd9Sstevel@tonic-gate 	    /* The alias wasn't in the table or there wasn't a table. */
805*7c478bd9Sstevel@tonic-gate 
806*7c478bd9Sstevel@tonic-gate 	    errno = olderrno;			/* Reset errno */
807*7c478bd9Sstevel@tonic-gate 
808*7c478bd9Sstevel@tonic-gate 	    /* Build a struct devtabent that describes the new alias */
809*7c478bd9Sstevel@tonic-gate 	    if (devtabent = mkdevtabent(alias, attrval)) {
810*7c478bd9Sstevel@tonic-gate 
811*7c478bd9Sstevel@tonic-gate 		/* Position to the end of the existing table */
812*7c478bd9Sstevel@tonic-gate 		if (fseek(oam_devtab, 0, SEEK_END) == 0)
813*7c478bd9Sstevel@tonic-gate 
814*7c478bd9Sstevel@tonic-gate 		    /* Write the new entry */
815*7c478bd9Sstevel@tonic-gate 		    noerr = (_putdevtabrec(oam_devtab, devtabent) != EOF);
816*7c478bd9Sstevel@tonic-gate 
817*7c478bd9Sstevel@tonic-gate 		/* Free the info we just wrote */
818*7c478bd9Sstevel@tonic-gate 		_freedevtabent(devtabent);
819*7c478bd9Sstevel@tonic-gate 
820*7c478bd9Sstevel@tonic-gate 	    } else noerr = FALSE;	/* mkdevtabent() failed */
821*7c478bd9Sstevel@tonic-gate 	} else noerr = FALSE;		/* Some odd error, _devtab */
822*7c478bd9Sstevel@tonic-gate 
823*7c478bd9Sstevel@tonic-gate 	/* Unlock and close the device table */
824*7c478bd9Sstevel@tonic-gate 	(void) unlkdevtab();
825*7c478bd9Sstevel@tonic-gate 
826*7c478bd9Sstevel@tonic-gate 	/* Fini */
827*7c478bd9Sstevel@tonic-gate 	return (noerr);
828*7c478bd9Sstevel@tonic-gate }
829*7c478bd9Sstevel@tonic-gate 
830*7c478bd9Sstevel@tonic-gate /*
831*7c478bd9Sstevel@tonic-gate  * int _moddevtabrec(device, attrval)
832*7c478bd9Sstevel@tonic-gate  *	char   *device
833*7c478bd9Sstevel@tonic-gate  *	char  **attrval
834*7c478bd9Sstevel@tonic-gate  *
835*7c478bd9Sstevel@tonic-gate  *	This function modifies the description for the specified device
836*7c478bd9Sstevel@tonic-gate  *	so that it has the attributes and values as specified in the
837*7c478bd9Sstevel@tonic-gate  *	given list.
838*7c478bd9Sstevel@tonic-gate  *
839*7c478bd9Sstevel@tonic-gate  *  Arguments:
840*7c478bd9Sstevel@tonic-gate  *	device		The name of the device whose description
841*7c478bd9Sstevel@tonic-gate  *			is being modified
842*7c478bd9Sstevel@tonic-gate  *	attrval		The first attr/val value in the list (attr=val) of
843*7c478bd9Sstevel@tonic-gate  *			the attributes that are to change
844*7c478bd9Sstevel@tonic-gate  *
845*7c478bd9Sstevel@tonic-gate  *  Returns:  int
846*7c478bd9Sstevel@tonic-gate  *	TRUE if all went well, FALSE with errno set otherwise
847*7c478bd9Sstevel@tonic-gate  */
848*7c478bd9Sstevel@tonic-gate 
849*7c478bd9Sstevel@tonic-gate int
850*7c478bd9Sstevel@tonic-gate _moddevtabrec(
851*7c478bd9Sstevel@tonic-gate 	char   *device,			/* Device to modify */
852*7c478bd9Sstevel@tonic-gate 	char  **attrval)		/* Attributes to add or change */
853*7c478bd9Sstevel@tonic-gate {
854*7c478bd9Sstevel@tonic-gate 	/* Automatic data */
855*7c478bd9Sstevel@tonic-gate 	FILE			*fd;	/* File ptr, new device table */
856*7c478bd9Sstevel@tonic-gate 	struct devtabent	*ent;	/* Device's current description */
857*7c478bd9Sstevel@tonic-gate 	struct devtabent	*chg;	/* Changes to make to description */
858*7c478bd9Sstevel@tonic-gate 	struct attrval		*new;	/* New attribute/value desc */
859*7c478bd9Sstevel@tonic-gate 	struct attrval		*old;	/* Old attribute/value desc */
860*7c478bd9Sstevel@tonic-gate 	struct attrval		*newnew; /* Next "new" value to look at */
861*7c478bd9Sstevel@tonic-gate 	struct attrval		*prevnew; /* Previous item in the 'new' list */
862*7c478bd9Sstevel@tonic-gate 	char			*tname;	/* name of temp devtab file */
863*7c478bd9Sstevel@tonic-gate 	int			noerr;	/* FLAG, TRUE if all's well */
864*7c478bd9Sstevel@tonic-gate 	int			found;	/* FLAG, TRUE if attr found for dev */
865*7c478bd9Sstevel@tonic-gate 
866*7c478bd9Sstevel@tonic-gate 	/* Lock the device table */
867*7c478bd9Sstevel@tonic-gate 	if (!lkdevtab("r", F_WRLCK))
868*7c478bd9Sstevel@tonic-gate 		return (FALSE);
869*7c478bd9Sstevel@tonic-gate 
870*7c478bd9Sstevel@tonic-gate 	/* No problems (so far) */
871*7c478bd9Sstevel@tonic-gate 	noerr = TRUE;
872*7c478bd9Sstevel@tonic-gate 
873*7c478bd9Sstevel@tonic-gate 	/* Get the entry to modify */
874*7c478bd9Sstevel@tonic-gate 	if (ent = _getdevrec(device)) {
875*7c478bd9Sstevel@tonic-gate 
876*7c478bd9Sstevel@tonic-gate 	    /* Build a structure describing the changes */
877*7c478bd9Sstevel@tonic-gate 	    if (chg = mkdevtabent(device, attrval)) {
878*7c478bd9Sstevel@tonic-gate 
879*7c478bd9Sstevel@tonic-gate 		/* If the "cdevice" field is specified, change it */
880*7c478bd9Sstevel@tonic-gate 		if (chg->cdevice) {
881*7c478bd9Sstevel@tonic-gate 		    if (ent->cdevice) free(ent->cdevice);
882*7c478bd9Sstevel@tonic-gate 		    ent->cdevice = chg->cdevice;
883*7c478bd9Sstevel@tonic-gate 		    chg->cdevice = NULL;
884*7c478bd9Sstevel@tonic-gate 		}
885*7c478bd9Sstevel@tonic-gate 
886*7c478bd9Sstevel@tonic-gate 		/* If the "bdevice" field is specified, change it */
887*7c478bd9Sstevel@tonic-gate 		if (chg->bdevice) {
888*7c478bd9Sstevel@tonic-gate 		    if (ent->bdevice) free(ent->bdevice);
889*7c478bd9Sstevel@tonic-gate 		    ent->bdevice = chg->bdevice;
890*7c478bd9Sstevel@tonic-gate 		    chg->bdevice = NULL;
891*7c478bd9Sstevel@tonic-gate 		}
892*7c478bd9Sstevel@tonic-gate 
893*7c478bd9Sstevel@tonic-gate 		/* If the "pathname" field is specified, change it */
894*7c478bd9Sstevel@tonic-gate 		if (chg->pathname) {
895*7c478bd9Sstevel@tonic-gate 		    if (ent->pathname) free(ent->pathname);
896*7c478bd9Sstevel@tonic-gate 		    ent->pathname = chg->pathname;
897*7c478bd9Sstevel@tonic-gate 		    chg->pathname = NULL;
898*7c478bd9Sstevel@tonic-gate 		}
899*7c478bd9Sstevel@tonic-gate 
900*7c478bd9Sstevel@tonic-gate 		/* Change the other attributes (if any) */
901*7c478bd9Sstevel@tonic-gate 		if (ent->attrlist) {
902*7c478bd9Sstevel@tonic-gate 		    prevnew = NULL;
903*7c478bd9Sstevel@tonic-gate 		    if ((new = chg->attrlist) != NULL) do {
904*7c478bd9Sstevel@tonic-gate 
905*7c478bd9Sstevel@tonic-gate 			found = FALSE;
906*7c478bd9Sstevel@tonic-gate 			for (old = ent->attrlist; !found && old;
907*7c478bd9Sstevel@tonic-gate 			    old = old->next) {
908*7c478bd9Sstevel@tonic-gate 			    if (strcmp(old->attr, new->attr) == 0) {
909*7c478bd9Sstevel@tonic-gate 				found = TRUE;
910*7c478bd9Sstevel@tonic-gate 				free(old->val);
911*7c478bd9Sstevel@tonic-gate 				old->val = new->val;
912*7c478bd9Sstevel@tonic-gate 				new->val = NULL;
913*7c478bd9Sstevel@tonic-gate 			    }
914*7c478bd9Sstevel@tonic-gate 			}   /* Loop through the existing attribute list */
915*7c478bd9Sstevel@tonic-gate 
916*7c478bd9Sstevel@tonic-gate 			/*
917*7c478bd9Sstevel@tonic-gate 			 * If the attribute wasn't found, add it to the list
918*7c478bd9Sstevel@tonic-gate 			 * of attributes for the device.  If it was found, just
919*7c478bd9Sstevel@tonic-gate 			 * bump to the next one and look for it
920*7c478bd9Sstevel@tonic-gate 			 */
921*7c478bd9Sstevel@tonic-gate 
922*7c478bd9Sstevel@tonic-gate 			if (!found) {
923*7c478bd9Sstevel@tonic-gate 
924*7c478bd9Sstevel@tonic-gate 			/*
925*7c478bd9Sstevel@tonic-gate 			 * Not found.  Move attr/val description to the
926*7c478bd9Sstevel@tonic-gate 			 * device's list of attributes
927*7c478bd9Sstevel@tonic-gate 			 */
928*7c478bd9Sstevel@tonic-gate 
929*7c478bd9Sstevel@tonic-gate 			    if (prevnew) prevnew->next = new->next;
930*7c478bd9Sstevel@tonic-gate 			    else chg->attrlist = new->next;
931*7c478bd9Sstevel@tonic-gate 			    newnew = new->next;
932*7c478bd9Sstevel@tonic-gate 			    new->next = ent->attrlist;
933*7c478bd9Sstevel@tonic-gate 			    ent->attrlist = new;
934*7c478bd9Sstevel@tonic-gate 			    new = newnew;
935*7c478bd9Sstevel@tonic-gate 			} else {
936*7c478bd9Sstevel@tonic-gate 
937*7c478bd9Sstevel@tonic-gate 			    /* Attribute changed, bump to the next one */
938*7c478bd9Sstevel@tonic-gate 			    prevnew = new;
939*7c478bd9Sstevel@tonic-gate 			    new = new->next;
940*7c478bd9Sstevel@tonic-gate 			}
941*7c478bd9Sstevel@tonic-gate 		    } while (new);  /* Loop for each attr to add or modify */
942*7c478bd9Sstevel@tonic-gate 
943*7c478bd9Sstevel@tonic-gate 		} else {
944*7c478bd9Sstevel@tonic-gate 
945*7c478bd9Sstevel@tonic-gate 		    /* Device had no attributes -- add entire list */
946*7c478bd9Sstevel@tonic-gate 		    ent->attrlist = chg->attrlist;
947*7c478bd9Sstevel@tonic-gate 		    chg->attrlist = NULL;
948*7c478bd9Sstevel@tonic-gate 		}
949*7c478bd9Sstevel@tonic-gate 
950*7c478bd9Sstevel@tonic-gate 		/* Free the structure containing the changes */
951*7c478bd9Sstevel@tonic-gate 		_freedevtabent(chg);
952*7c478bd9Sstevel@tonic-gate 
953*7c478bd9Sstevel@tonic-gate 	    } else noerr = FALSE;   /* Couldn't build changes struct */
954*7c478bd9Sstevel@tonic-gate 
955*7c478bd9Sstevel@tonic-gate 	    /* If there hasn't been an error (so far), write the new record */
956*7c478bd9Sstevel@tonic-gate 	    if (noerr) {
957*7c478bd9Sstevel@tonic-gate 
958*7c478bd9Sstevel@tonic-gate 		/* Open the new device table */
959*7c478bd9Sstevel@tonic-gate 		if (fd = opennewdevtab(&tname)) {
960*7c478bd9Sstevel@tonic-gate 
961*7c478bd9Sstevel@tonic-gate 		/*
962*7c478bd9Sstevel@tonic-gate 		 * For each entry in the existing table, write that entry
963*7c478bd9Sstevel@tonic-gate 		 * to the new table.  If the entry is the one being
964*7c478bd9Sstevel@tonic-gate 		 * modified, write the modified entry instead of the
965*7c478bd9Sstevel@tonic-gate 		 * original entry.
966*7c478bd9Sstevel@tonic-gate 		 */
967*7c478bd9Sstevel@tonic-gate 
968*7c478bd9Sstevel@tonic-gate 		    _setdevtab();		/* Rewind existing table */
969*7c478bd9Sstevel@tonic-gate 		    chg = ent;			/* Remember new record */
970*7c478bd9Sstevel@tonic-gate 		    while (((ent = _getdevtabent()) != NULL) && noerr) {
971*7c478bd9Sstevel@tonic-gate 			if (ent->entryno != chg->entryno)
972*7c478bd9Sstevel@tonic-gate 			    noerr = _putdevtabrec(fd, ent) != EOF;
973*7c478bd9Sstevel@tonic-gate 			else noerr = _putdevtabrec(fd, chg) != EOF;
974*7c478bd9Sstevel@tonic-gate 			_freedevtabent(ent);
975*7c478bd9Sstevel@tonic-gate 		    }
976*7c478bd9Sstevel@tonic-gate 
977*7c478bd9Sstevel@tonic-gate 		/*
978*7c478bd9Sstevel@tonic-gate 		 * If we successfully generated the new table, make it the
979*7c478bd9Sstevel@tonic-gate 		 * new system device table.  Otherwise, just remove the
980*7c478bd9Sstevel@tonic-gate 		 * temporary file we've created.
981*7c478bd9Sstevel@tonic-gate 		 */
982*7c478bd9Sstevel@tonic-gate 
983*7c478bd9Sstevel@tonic-gate 		    if (noerr) {
984*7c478bd9Sstevel@tonic-gate 			(void) fclose(fd);
985*7c478bd9Sstevel@tonic-gate 			noerr = mknewdevtab(tname);
986*7c478bd9Sstevel@tonic-gate 		    } else {
987*7c478bd9Sstevel@tonic-gate 			(void) fclose(fd);
988*7c478bd9Sstevel@tonic-gate 			(void) rmnewdevtab(tname);
989*7c478bd9Sstevel@tonic-gate 		    }
990*7c478bd9Sstevel@tonic-gate 
991*7c478bd9Sstevel@tonic-gate 		    /* Free the changed device structure */
992*7c478bd9Sstevel@tonic-gate 		    _freedevtabent(chg);
993*7c478bd9Sstevel@tonic-gate 
994*7c478bd9Sstevel@tonic-gate 		}   /* if (_opennewdevtab()) */
995*7c478bd9Sstevel@tonic-gate 		else noerr = FALSE;
996*7c478bd9Sstevel@tonic-gate 
997*7c478bd9Sstevel@tonic-gate 	    } else _freedevtabent(ent);  /* if (noerr) */
998*7c478bd9Sstevel@tonic-gate 
999*7c478bd9Sstevel@tonic-gate 	} else noerr = FALSE;	/* Device not found? */
1000*7c478bd9Sstevel@tonic-gate 
1001*7c478bd9Sstevel@tonic-gate 	/* Finished.  Unlock the device table and quit */
1002*7c478bd9Sstevel@tonic-gate 	(void) unlkdevtab();
1003*7c478bd9Sstevel@tonic-gate 	return (noerr);
1004*7c478bd9Sstevel@tonic-gate }
1005*7c478bd9Sstevel@tonic-gate 
1006*7c478bd9Sstevel@tonic-gate /*
1007*7c478bd9Sstevel@tonic-gate  * int _rmdevtabrec(device)
1008*7c478bd9Sstevel@tonic-gate  *	char   *device
1009*7c478bd9Sstevel@tonic-gate  *
1010*7c478bd9Sstevel@tonic-gate  *	This function removes the record in the device table for the specified
1011*7c478bd9Sstevel@tonic-gate  *	device.
1012*7c478bd9Sstevel@tonic-gate  *
1013*7c478bd9Sstevel@tonic-gate  *  Arguments:
1014*7c478bd9Sstevel@tonic-gate  *	device	The device (alias, cdevice, bdevice, pathname, or link to one)
1015*7c478bd9Sstevel@tonic-gate  *		whose entry is to be removed
1016*7c478bd9Sstevel@tonic-gate  *
1017*7c478bd9Sstevel@tonic-gate  *  Returns:  int
1018*7c478bd9Sstevel@tonic-gate  *	Success indicator:  TRUE if successful, FALSE with errno set otherwise.
1019*7c478bd9Sstevel@tonic-gate  */
1020*7c478bd9Sstevel@tonic-gate 
1021*7c478bd9Sstevel@tonic-gate int
1022*7c478bd9Sstevel@tonic-gate _rmdevtabrec(char *device)		/* Device to remove */
1023*7c478bd9Sstevel@tonic-gate {
1024*7c478bd9Sstevel@tonic-gate 	struct devtabent	*rment;
1025*7c478bd9Sstevel@tonic-gate 	struct devtabent	*devtabent;
1026*7c478bd9Sstevel@tonic-gate 	char			*tempname;
1027*7c478bd9Sstevel@tonic-gate 	FILE			*fd;
1028*7c478bd9Sstevel@tonic-gate 	int			noerr;
1029*7c478bd9Sstevel@tonic-gate 
1030*7c478bd9Sstevel@tonic-gate 	if (!lkdevtab("r", F_WRLCK))
1031*7c478bd9Sstevel@tonic-gate 		return (FALSE);
1032*7c478bd9Sstevel@tonic-gate 	noerr = TRUE;
1033*7c478bd9Sstevel@tonic-gate 	if (rment = _getdevrec(device)) {
1034*7c478bd9Sstevel@tonic-gate 	    if (fd = opennewdevtab(&tempname)) {
1035*7c478bd9Sstevel@tonic-gate 		_setdevtab();
1036*7c478bd9Sstevel@tonic-gate 		while (((devtabent = _getdevtabent()) != NULL) && noerr) {
1037*7c478bd9Sstevel@tonic-gate 		    if (devtabent->entryno != rment->entryno)
1038*7c478bd9Sstevel@tonic-gate 			noerr = _putdevtabrec(fd, devtabent) != EOF;
1039*7c478bd9Sstevel@tonic-gate 		    _freedevtabent(devtabent);
1040*7c478bd9Sstevel@tonic-gate 		}
1041*7c478bd9Sstevel@tonic-gate 		if (noerr) {
1042*7c478bd9Sstevel@tonic-gate 		    (void) fclose(fd);
1043*7c478bd9Sstevel@tonic-gate 		    noerr = mknewdevtab(tempname);
1044*7c478bd9Sstevel@tonic-gate 		} else {
1045*7c478bd9Sstevel@tonic-gate 		    (void) fclose(fd);
1046*7c478bd9Sstevel@tonic-gate 		    (void) rmnewdevtab(tempname);
1047*7c478bd9Sstevel@tonic-gate 		}
1048*7c478bd9Sstevel@tonic-gate 	    } else noerr = FALSE;
1049*7c478bd9Sstevel@tonic-gate 	    _freedevtabent(rment);
1050*7c478bd9Sstevel@tonic-gate 	} else noerr = FALSE;
1051*7c478bd9Sstevel@tonic-gate 	(void) unlkdevtab();
1052*7c478bd9Sstevel@tonic-gate 	return (noerr);
1053*7c478bd9Sstevel@tonic-gate }
1054*7c478bd9Sstevel@tonic-gate 
1055*7c478bd9Sstevel@tonic-gate /*
1056*7c478bd9Sstevel@tonic-gate  * int _rmdevtabattrs(device, attributes, notfounds)
1057*7c478bd9Sstevel@tonic-gate  *	char   *device
1058*7c478bd9Sstevel@tonic-gate  *	char  **attributes
1059*7c478bd9Sstevel@tonic-gate  *	char ***notfounds
1060*7c478bd9Sstevel@tonic-gate  *
1061*7c478bd9Sstevel@tonic-gate  *	Remove the specified attributes from the specified device.  The
1062*7c478bd9Sstevel@tonic-gate  *	device is specified by <device>, <attributes> is the address of
1063*7c478bd9Sstevel@tonic-gate  *	the first char * in the list of char * pointing to the attributes
1064*7c478bd9Sstevel@tonic-gate  *	to remove from the device, and <notfounds> is the address of a
1065*7c478bd9Sstevel@tonic-gate  *	char ** to put the address of the first element in the malloc()ed
1066*7c478bd9Sstevel@tonic-gate  *	list of (char *) pointing to requested attributes that were not
1067*7c478bd9Sstevel@tonic-gate  *	defined for the device <device>.
1068*7c478bd9Sstevel@tonic-gate  *
1069*7c478bd9Sstevel@tonic-gate  *  Arguments:
1070*7c478bd9Sstevel@tonic-gate  *	device		The device from which attributes are to be removed
1071*7c478bd9Sstevel@tonic-gate  *	attributes	The address of the first element in the list of
1072*7c478bd9Sstevel@tonic-gate  *			attributes to remove.  This list is terminated by
1073*7c478bd9Sstevel@tonic-gate  *			(char *) NULL.
1074*7c478bd9Sstevel@tonic-gate  *	notfounds	The place to put the address of the list of addresses
1075*7c478bd9Sstevel@tonic-gate  *			referencing the requested attributes that are not
1076*7c478bd9Sstevel@tonic-gate  *			defined for the specified device.
1077*7c478bd9Sstevel@tonic-gate  *
1078*7c478bd9Sstevel@tonic-gate  *  Returns: int
1079*7c478bd9Sstevel@tonic-gate  *	TRUE if successful, FALSE with errno set otherwise.
1080*7c478bd9Sstevel@tonic-gate  *
1081*7c478bd9Sstevel@tonic-gate  *  Notes:
1082*7c478bd9Sstevel@tonic-gate  *    -	"alias" may not be undefined
1083*7c478bd9Sstevel@tonic-gate  *    - "cdevice", "bdevice", and "pathname" are made "null", not really
1084*7c478bd9Sstevel@tonic-gate  *	undefined
1085*7c478bd9Sstevel@tonic-gate  */
1086*7c478bd9Sstevel@tonic-gate 
1087*7c478bd9Sstevel@tonic-gate int
1088*7c478bd9Sstevel@tonic-gate _rmdevtabattrs(
1089*7c478bd9Sstevel@tonic-gate 	char   *device,			/* Device to modify */
1090*7c478bd9Sstevel@tonic-gate 	char  **attributes,		/* Attributes to remove */
1091*7c478bd9Sstevel@tonic-gate 	char ***notfounds)		/* Attributes req'd but not found */
1092*7c478bd9Sstevel@tonic-gate {
1093*7c478bd9Sstevel@tonic-gate 	/* Automatics */
1094*7c478bd9Sstevel@tonic-gate 	char			**pnxt;		/* Ptr to next attribute */
1095*7c478bd9Sstevel@tonic-gate 	char			**pp;		/* Ptr to current attr name */
1096*7c478bd9Sstevel@tonic-gate 	struct devtabent	*modent;	/* Entry being modified */
1097*7c478bd9Sstevel@tonic-gate 	struct devtabent	*devtabent;	/* Entry being copied */
1098*7c478bd9Sstevel@tonic-gate 	struct attrval		*attrval;	/* Ptr to attr/val desc */
1099*7c478bd9Sstevel@tonic-gate 	struct attrval		*prevattrval;	/* Ptr to prev attr/val */
1100*7c478bd9Sstevel@tonic-gate 	FILE			*fd;		/* File desc, temp file */
1101*7c478bd9Sstevel@tonic-gate 	char			*tempname;	/* Name of temp file */
1102*7c478bd9Sstevel@tonic-gate 	int			nattrs;		/* Number of attrs to remove */
1103*7c478bd9Sstevel@tonic-gate 	int			nobaderr;	/* TRUE if no fatal error */
1104*7c478bd9Sstevel@tonic-gate 	int			noerr;		/* TRUE if no non-fatal error */
1105*7c478bd9Sstevel@tonic-gate 	int			found;		/* TRUE if attribute found */
1106*7c478bd9Sstevel@tonic-gate 	int			nonotfounds;	/* TRUE if no attrs not fount */
1107*7c478bd9Sstevel@tonic-gate 
1108*7c478bd9Sstevel@tonic-gate 
1109*7c478bd9Sstevel@tonic-gate 	/* Initializations */
1110*7c478bd9Sstevel@tonic-gate 	nobaderr = TRUE;
1111*7c478bd9Sstevel@tonic-gate 	noerr = TRUE;
1112*7c478bd9Sstevel@tonic-gate 
1113*7c478bd9Sstevel@tonic-gate 	/* Count attributes to remove -- make sure "alias" isn't specified */
1114*7c478bd9Sstevel@tonic-gate 	for (pp = attributes, nattrs = 0; *pp; pp++, nattrs++)
1115*7c478bd9Sstevel@tonic-gate 	    if (strcmp(*pp, DTAB_ALIAS) == 0) {
1116*7c478bd9Sstevel@tonic-gate 		*notfounds = NULL;
1117*7c478bd9Sstevel@tonic-gate 		errno = EINVAL;
1118*7c478bd9Sstevel@tonic-gate 		return (FALSE);
1119*7c478bd9Sstevel@tonic-gate 	    }
1120*7c478bd9Sstevel@tonic-gate 
1121*7c478bd9Sstevel@tonic-gate 	/* Lock the device table */
1122*7c478bd9Sstevel@tonic-gate 	if (!lkdevtab("r", F_WRLCK))
1123*7c478bd9Sstevel@tonic-gate 		return (FALSE);
1124*7c478bd9Sstevel@tonic-gate 
1125*7c478bd9Sstevel@tonic-gate 	/* Is there a record for the requested device? */
1126*7c478bd9Sstevel@tonic-gate 	if (modent = _getdevrec(device)) {
1127*7c478bd9Sstevel@tonic-gate 
1128*7c478bd9Sstevel@tonic-gate 	    /* Record found.  Try to modify it */
1129*7c478bd9Sstevel@tonic-gate 	    nonotfounds = TRUE;
1130*7c478bd9Sstevel@tonic-gate 
1131*7c478bd9Sstevel@tonic-gate 	    /* For each of the attributes in the attribute list ... */
1132*7c478bd9Sstevel@tonic-gate 	    for (pp = attributes; nobaderr && *pp; pp++) {
1133*7c478bd9Sstevel@tonic-gate 
1134*7c478bd9Sstevel@tonic-gate 		/*
1135*7c478bd9Sstevel@tonic-gate 		 * Modify the device description, removing the requested
1136*7c478bd9Sstevel@tonic-gate 		 * attributes from the structure
1137*7c478bd9Sstevel@tonic-gate 		 */
1138*7c478bd9Sstevel@tonic-gate 
1139*7c478bd9Sstevel@tonic-gate 		found = FALSE;				/* Not found yet */
1140*7c478bd9Sstevel@tonic-gate 
1141*7c478bd9Sstevel@tonic-gate 		/* If it's the "cdevice" attribute, make it a null-string */
1142*7c478bd9Sstevel@tonic-gate 		if (strcmp(*pp, DTAB_CDEVICE) == 0) {
1143*7c478bd9Sstevel@tonic-gate 		    if (modent->cdevice) {
1144*7c478bd9Sstevel@tonic-gate 			free(modent->cdevice);
1145*7c478bd9Sstevel@tonic-gate 			modent->cdevice = NULL;
1146*7c478bd9Sstevel@tonic-gate 		    }
1147*7c478bd9Sstevel@tonic-gate 		    found = TRUE;
1148*7c478bd9Sstevel@tonic-gate 		}
1149*7c478bd9Sstevel@tonic-gate 
1150*7c478bd9Sstevel@tonic-gate 		/* If it's the "bdevice" attribute, make it a null-string */
1151*7c478bd9Sstevel@tonic-gate 		else if (strcmp(*pp, DTAB_BDEVICE) == 0) {
1152*7c478bd9Sstevel@tonic-gate 		    if (modent->bdevice) {
1153*7c478bd9Sstevel@tonic-gate 			free(modent->bdevice);
1154*7c478bd9Sstevel@tonic-gate 			modent->bdevice = NULL;
1155*7c478bd9Sstevel@tonic-gate 		    }
1156*7c478bd9Sstevel@tonic-gate 		    found = TRUE;
1157*7c478bd9Sstevel@tonic-gate 		}
1158*7c478bd9Sstevel@tonic-gate 
1159*7c478bd9Sstevel@tonic-gate 		/* If it's the "pathname" attribute, make it a null-string */
1160*7c478bd9Sstevel@tonic-gate 		else if (strcmp(*pp, DTAB_PATHNAME) == 0) {
1161*7c478bd9Sstevel@tonic-gate 		    if (modent->pathname) {
1162*7c478bd9Sstevel@tonic-gate 			free(modent->pathname);
1163*7c478bd9Sstevel@tonic-gate 			modent->pathname = NULL;
1164*7c478bd9Sstevel@tonic-gate 		    }
1165*7c478bd9Sstevel@tonic-gate 		    found = TRUE;
1166*7c478bd9Sstevel@tonic-gate 		}
1167*7c478bd9Sstevel@tonic-gate 
1168*7c478bd9Sstevel@tonic-gate 		/* Must be one of the other "auxilliary" attributes */
1169*7c478bd9Sstevel@tonic-gate 		else {
1170*7c478bd9Sstevel@tonic-gate 
1171*7c478bd9Sstevel@tonic-gate 		    /* Search the attribute list for the attribute */
1172*7c478bd9Sstevel@tonic-gate 		    prevattrval = NULL;
1173*7c478bd9Sstevel@tonic-gate 		    if ((attrval = modent->attrlist) != NULL) do {
1174*7c478bd9Sstevel@tonic-gate 			if (strcmp(*pp, attrval->attr) == 0) {
1175*7c478bd9Sstevel@tonic-gate 
1176*7c478bd9Sstevel@tonic-gate 			    /* Found.  Remove from attribute list */
1177*7c478bd9Sstevel@tonic-gate 			    found = TRUE;
1178*7c478bd9Sstevel@tonic-gate 			    free(attrval->attr);
1179*7c478bd9Sstevel@tonic-gate 			    free(attrval->val);
1180*7c478bd9Sstevel@tonic-gate 			    if (prevattrval) {
1181*7c478bd9Sstevel@tonic-gate 				prevattrval->next = attrval->next;
1182*7c478bd9Sstevel@tonic-gate 				free(attrval);
1183*7c478bd9Sstevel@tonic-gate 				attrval = prevattrval->next;
1184*7c478bd9Sstevel@tonic-gate 			    } else {
1185*7c478bd9Sstevel@tonic-gate 				modent->attrlist = attrval->next;
1186*7c478bd9Sstevel@tonic-gate 				free(attrval);
1187*7c478bd9Sstevel@tonic-gate 				attrval = modent->attrlist;
1188*7c478bd9Sstevel@tonic-gate 			    }
1189*7c478bd9Sstevel@tonic-gate 			} else {
1190*7c478bd9Sstevel@tonic-gate 			    prevattrval = attrval;	/* Advance to next */
1191*7c478bd9Sstevel@tonic-gate 			    attrval = attrval->next;
1192*7c478bd9Sstevel@tonic-gate 			}
1193*7c478bd9Sstevel@tonic-gate 		    } while (!found && attrval);
1194*7c478bd9Sstevel@tonic-gate 
1195*7c478bd9Sstevel@tonic-gate 		}   /* End attribute search loop */
1196*7c478bd9Sstevel@tonic-gate 
1197*7c478bd9Sstevel@tonic-gate 		/*
1198*7c478bd9Sstevel@tonic-gate 		 * If the requested attribute wasn't defined for the device,
1199*7c478bd9Sstevel@tonic-gate 		 * put it in the list of attributes not found
1200*7c478bd9Sstevel@tonic-gate 		 */
1201*7c478bd9Sstevel@tonic-gate 
1202*7c478bd9Sstevel@tonic-gate 		if (!found) {
1203*7c478bd9Sstevel@tonic-gate 
1204*7c478bd9Sstevel@tonic-gate 			/*
1205*7c478bd9Sstevel@tonic-gate 			 * If there's no list (yet), alloc enough space for
1206*7c478bd9Sstevel@tonic-gate 			 * the list
1207*7c478bd9Sstevel@tonic-gate 			 */
1208*7c478bd9Sstevel@tonic-gate 
1209*7c478bd9Sstevel@tonic-gate 		    if (nonotfounds)
1210*7c478bd9Sstevel@tonic-gate 			if (*notfounds = malloc(sizeof (char **)*(nattrs+1))) {
1211*7c478bd9Sstevel@tonic-gate 
1212*7c478bd9Sstevel@tonic-gate 			    /* List allocated -- put in the first entry */
1213*7c478bd9Sstevel@tonic-gate 			    nonotfounds = FALSE;
1214*7c478bd9Sstevel@tonic-gate 			    pnxt = *notfounds;
1215*7c478bd9Sstevel@tonic-gate 			    if (*pnxt = malloc(strlen(*pp)+1)) {
1216*7c478bd9Sstevel@tonic-gate 				errno = EINVAL;
1217*7c478bd9Sstevel@tonic-gate 				noerr = FALSE;
1218*7c478bd9Sstevel@tonic-gate 				(void) strcpy(*pnxt++, *pp);
1219*7c478bd9Sstevel@tonic-gate 			    } else {
1220*7c478bd9Sstevel@tonic-gate 				/* malloc() failed, free list */
1221*7c478bd9Sstevel@tonic-gate 				free(*notfounds);
1222*7c478bd9Sstevel@tonic-gate 				*notfounds = NULL;
1223*7c478bd9Sstevel@tonic-gate 				nonotfounds = TRUE;
1224*7c478bd9Sstevel@tonic-gate 				nobaderr = FALSE;
1225*7c478bd9Sstevel@tonic-gate 			    }
1226*7c478bd9Sstevel@tonic-gate 
1227*7c478bd9Sstevel@tonic-gate 			} else nobaderr = FALSE;  /* malloc() failed */
1228*7c478bd9Sstevel@tonic-gate 
1229*7c478bd9Sstevel@tonic-gate 		    else {
1230*7c478bd9Sstevel@tonic-gate 			/* Already a list, add this attribute to it */
1231*7c478bd9Sstevel@tonic-gate 			if (*pnxt = malloc(strlen(*pp)+1))
1232*7c478bd9Sstevel@tonic-gate 			    (void) strcpy(*pnxt++, *pp);
1233*7c478bd9Sstevel@tonic-gate 			else {
1234*7c478bd9Sstevel@tonic-gate 			    /* Out of memory, clean up */
1235*7c478bd9Sstevel@tonic-gate 			    for (pnxt = *notfounds; *pnxt; pnxt++)
1236*7c478bd9Sstevel@tonic-gate 				free(*pnxt);
1237*7c478bd9Sstevel@tonic-gate 			    free(*notfounds);
1238*7c478bd9Sstevel@tonic-gate 			    *notfounds = NULL;
1239*7c478bd9Sstevel@tonic-gate 			    nonotfounds = TRUE;
1240*7c478bd9Sstevel@tonic-gate 			    nobaderr = FALSE;
1241*7c478bd9Sstevel@tonic-gate 			}
1242*7c478bd9Sstevel@tonic-gate 		    }
1243*7c478bd9Sstevel@tonic-gate 
1244*7c478bd9Sstevel@tonic-gate 		}    /* end if (!found) */
1245*7c478bd9Sstevel@tonic-gate 
1246*7c478bd9Sstevel@tonic-gate 		/* Terminate the not-found list */
1247*7c478bd9Sstevel@tonic-gate 		if (!nonotfounds) *pnxt = NULL;
1248*7c478bd9Sstevel@tonic-gate 
1249*7c478bd9Sstevel@tonic-gate 	    }	/* end (for each attribute in attribute list) loop */
1250*7c478bd9Sstevel@tonic-gate 
1251*7c478bd9Sstevel@tonic-gate 
1252*7c478bd9Sstevel@tonic-gate 		/*
1253*7c478bd9Sstevel@tonic-gate 		 * If we haven't seen any problems so far,
1254*7c478bd9Sstevel@tonic-gate 		 * write the new device table
1255*7c478bd9Sstevel@tonic-gate 		 */
1256*7c478bd9Sstevel@tonic-gate 
1257*7c478bd9Sstevel@tonic-gate 	    if (nobaderr) {
1258*7c478bd9Sstevel@tonic-gate 
1259*7c478bd9Sstevel@tonic-gate 		/* Open the new device table */
1260*7c478bd9Sstevel@tonic-gate 		if (fd = opennewdevtab(&tempname)) {
1261*7c478bd9Sstevel@tonic-gate 
1262*7c478bd9Sstevel@tonic-gate 		/*
1263*7c478bd9Sstevel@tonic-gate 		 * For each entry in the existing table, write that entry
1264*7c478bd9Sstevel@tonic-gate 		 * to the new table.  If the entry is the one being
1265*7c478bd9Sstevel@tonic-gate 		 * modified, write the modified entry instead of the
1266*7c478bd9Sstevel@tonic-gate 		 * original entry.
1267*7c478bd9Sstevel@tonic-gate 		 */
1268*7c478bd9Sstevel@tonic-gate 
1269*7c478bd9Sstevel@tonic-gate 		    _setdevtab();		/* Rewind existing table */
1270*7c478bd9Sstevel@tonic-gate 		    while (((devtabent = _getdevtabent()) != NULL) &&
1271*7c478bd9Sstevel@tonic-gate 			nobaderr) {
1272*7c478bd9Sstevel@tonic-gate 
1273*7c478bd9Sstevel@tonic-gate 			if (devtabent->entryno != modent->entryno)
1274*7c478bd9Sstevel@tonic-gate 			    nobaderr = _putdevtabrec(fd, devtabent) != EOF;
1275*7c478bd9Sstevel@tonic-gate 			else nobaderr = _putdevtabrec(fd, modent) != EOF;
1276*7c478bd9Sstevel@tonic-gate 			_freedevtabent(devtabent);
1277*7c478bd9Sstevel@tonic-gate 		    }
1278*7c478bd9Sstevel@tonic-gate 
1279*7c478bd9Sstevel@tonic-gate 		/*
1280*7c478bd9Sstevel@tonic-gate 		 * If we successfully generated the new table, make it the
1281*7c478bd9Sstevel@tonic-gate 		 * new system device table.  Otherwise, just remove the
1282*7c478bd9Sstevel@tonic-gate 		 * temporary file we've created.
1283*7c478bd9Sstevel@tonic-gate 		 */
1284*7c478bd9Sstevel@tonic-gate 
1285*7c478bd9Sstevel@tonic-gate 		    if (nobaderr) {
1286*7c478bd9Sstevel@tonic-gate 			(void) fclose(fd);
1287*7c478bd9Sstevel@tonic-gate 			nobaderr = mknewdevtab(tempname);
1288*7c478bd9Sstevel@tonic-gate 		    } else {
1289*7c478bd9Sstevel@tonic-gate 			(void) fclose(fd);
1290*7c478bd9Sstevel@tonic-gate 			(void) rmnewdevtab(tempname);
1291*7c478bd9Sstevel@tonic-gate 		    }
1292*7c478bd9Sstevel@tonic-gate 
1293*7c478bd9Sstevel@tonic-gate 		}   /* if (_opennewdevtab()) */
1294*7c478bd9Sstevel@tonic-gate 		else nobaderr = FALSE;
1295*7c478bd9Sstevel@tonic-gate 
1296*7c478bd9Sstevel@tonic-gate 		/*
1297*7c478bd9Sstevel@tonic-gate 		 * If there was some error, we need to clean up
1298*7c478bd9Sstevel@tonic-gate 		 * allocated resources
1299*7c478bd9Sstevel@tonic-gate 		 */
1300*7c478bd9Sstevel@tonic-gate 		if (!nobaderr && !nonotfounds) {
1301*7c478bd9Sstevel@tonic-gate 		    for (pnxt = *notfounds; *pnxt; pnxt++)
1302*7c478bd9Sstevel@tonic-gate 			free(*pnxt);
1303*7c478bd9Sstevel@tonic-gate 		    free(*notfounds);
1304*7c478bd9Sstevel@tonic-gate 		    *notfounds = NULL;
1305*7c478bd9Sstevel@tonic-gate 		    nonotfounds = TRUE;
1306*7c478bd9Sstevel@tonic-gate 		}
1307*7c478bd9Sstevel@tonic-gate 
1308*7c478bd9Sstevel@tonic-gate 	    }	/* if (nobaderr) */
1309*7c478bd9Sstevel@tonic-gate 
1310*7c478bd9Sstevel@tonic-gate 	    /* Free the resources alloc'ed for <device>'s entry */
1311*7c478bd9Sstevel@tonic-gate 	    _freedevtabent(modent);
1312*7c478bd9Sstevel@tonic-gate 
1313*7c478bd9Sstevel@tonic-gate 	} else {
1314*7c478bd9Sstevel@tonic-gate 	    /* _getdevrec(device) failed */
1315*7c478bd9Sstevel@tonic-gate 	    nobaderr = FALSE;
1316*7c478bd9Sstevel@tonic-gate 	    *notfounds = NULL;
1317*7c478bd9Sstevel@tonic-gate 	}
1318*7c478bd9Sstevel@tonic-gate 
1319*7c478bd9Sstevel@tonic-gate 	/* Unlock the device table */
1320*7c478bd9Sstevel@tonic-gate 	(void) unlkdevtab();
1321*7c478bd9Sstevel@tonic-gate 
1322*7c478bd9Sstevel@tonic-gate 	/* We're finished */
1323*7c478bd9Sstevel@tonic-gate 	return (noerr && nobaderr);
1324*7c478bd9Sstevel@tonic-gate }
1325