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