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