1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright (c) 1999 by Sun Microsystems, Inc.
24*7c478bd9Sstevel@tonic-gate  * All rights reserved.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
28*7c478bd9Sstevel@tonic-gate #include <sys/stat.h>
29*7c478bd9Sstevel@tonic-gate #include <errno.h>
30*7c478bd9Sstevel@tonic-gate #include <syslog.h>
31*7c478bd9Sstevel@tonic-gate #include <libintl.h>
32*7c478bd9Sstevel@tonic-gate #include <unistd.h>
33*7c478bd9Sstevel@tonic-gate #include <strings.h>
34*7c478bd9Sstevel@tonic-gate #include <string.h>
35*7c478bd9Sstevel@tonic-gate #include <assert.h>
36*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
37*7c478bd9Sstevel@tonic-gate #include "nfslogd.h"
38*7c478bd9Sstevel@tonic-gate #include "../lib/nfslogtab.h"
39*7c478bd9Sstevel@tonic-gate #include "buffer_list.h"
40*7c478bd9Sstevel@tonic-gate 
41*7c478bd9Sstevel@tonic-gate static int buildbuffer_list(struct buffer_ent **, timestruc_t *);
42*7c478bd9Sstevel@tonic-gate static void free_buffer_ent(struct buffer_ent *);
43*7c478bd9Sstevel@tonic-gate static struct buffer_ent *findbuffer(struct buffer_ent *, char *);
44*7c478bd9Sstevel@tonic-gate static void free_sharepnt_list(struct sharepnt_ent *);
45*7c478bd9Sstevel@tonic-gate static void free_sharepnt_ent(struct sharepnt_ent *);
46*7c478bd9Sstevel@tonic-gate #ifdef	DEBUG
47*7c478bd9Sstevel@tonic-gate static void print_sharepnt_list(struct sharepnt_ent *);
48*7c478bd9Sstevel@tonic-gate #endif
49*7c478bd9Sstevel@tonic-gate static struct sharepnt_ent *findsharepnt(struct sharepnt_ent *, char *,
50*7c478bd9Sstevel@tonic-gate 	struct sharepnt_ent **);
51*7c478bd9Sstevel@tonic-gate 
52*7c478bd9Sstevel@tonic-gate /*
53*7c478bd9Sstevel@tonic-gate  * Builds the buffer list from NFSLOGTAB and returns it in *listpp.
54*7c478bd9Sstevel@tonic-gate  * Returns 0 on success, non-zero error code otherwise.
55*7c478bd9Sstevel@tonic-gate  */
56*7c478bd9Sstevel@tonic-gate int
getbuffer_list(struct buffer_ent ** listpp,timestruc_t * lu)57*7c478bd9Sstevel@tonic-gate getbuffer_list(struct buffer_ent **listpp, timestruc_t *lu)
58*7c478bd9Sstevel@tonic-gate {
59*7c478bd9Sstevel@tonic-gate 	*listpp = NULL;
60*7c478bd9Sstevel@tonic-gate 	return (buildbuffer_list(listpp, lu));
61*7c478bd9Sstevel@tonic-gate }
62*7c478bd9Sstevel@tonic-gate 
63*7c478bd9Sstevel@tonic-gate /*
64*7c478bd9Sstevel@tonic-gate  * If NFSLOGTAB has not been modified since the last time we read it,
65*7c478bd9Sstevel@tonic-gate  * it simply returns the same buffer list, otherwise it re-reads NFSLOGTAB
66*7c478bd9Sstevel@tonic-gate  * and rebuilds the list.
67*7c478bd9Sstevel@tonic-gate  * No NFSLOGTAB is not treated as an error.
68*7c478bd9Sstevel@tonic-gate  * Returns 0 on success, non-zero error code otherwise
69*7c478bd9Sstevel@tonic-gate  */
70*7c478bd9Sstevel@tonic-gate int
checkbuffer_list(struct buffer_ent ** listpp,timestruc_t * lu)71*7c478bd9Sstevel@tonic-gate checkbuffer_list(struct buffer_ent **listpp, timestruc_t *lu)
72*7c478bd9Sstevel@tonic-gate {
73*7c478bd9Sstevel@tonic-gate 	struct stat st;
74*7c478bd9Sstevel@tonic-gate 	int error = 0;
75*7c478bd9Sstevel@tonic-gate 
76*7c478bd9Sstevel@tonic-gate 	if (stat(NFSLOGTAB, &st) == -1) {
77*7c478bd9Sstevel@tonic-gate 		error = errno;
78*7c478bd9Sstevel@tonic-gate 		if (error != ENOENT) {
79*7c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR, gettext("Can't stat %s - %s"),
80*7c478bd9Sstevel@tonic-gate 				NFSLOGTAB, strerror(error));
81*7c478bd9Sstevel@tonic-gate 			error = 0;
82*7c478bd9Sstevel@tonic-gate 		}
83*7c478bd9Sstevel@tonic-gate 		return (error);
84*7c478bd9Sstevel@tonic-gate 	}
85*7c478bd9Sstevel@tonic-gate 
86*7c478bd9Sstevel@tonic-gate 	if (lu->tv_sec == st.st_mtim.tv_sec &&
87*7c478bd9Sstevel@tonic-gate 	    lu->tv_nsec == st.st_mtim.tv_nsec)
88*7c478bd9Sstevel@tonic-gate 		return (0);
89*7c478bd9Sstevel@tonic-gate 
90*7c478bd9Sstevel@tonic-gate 	free_buffer_list(listpp);	/* free existing list first */
91*7c478bd9Sstevel@tonic-gate 	return (buildbuffer_list(listpp, lu));
92*7c478bd9Sstevel@tonic-gate }
93*7c478bd9Sstevel@tonic-gate 
94*7c478bd9Sstevel@tonic-gate /*
95*7c478bd9Sstevel@tonic-gate  * Does the actual work of reading NFSLOGTAB, and building the
96*7c478bd9Sstevel@tonic-gate  * buffer list. If *be_head already contains entries, it will
97*7c478bd9Sstevel@tonic-gate  * update the list with new information.
98*7c478bd9Sstevel@tonic-gate  * Returns 0 on success, non-zero error code otherwise.
99*7c478bd9Sstevel@tonic-gate  */
100*7c478bd9Sstevel@tonic-gate static int
buildbuffer_list(struct buffer_ent ** be_head,timestruc_t * lu)101*7c478bd9Sstevel@tonic-gate buildbuffer_list(struct buffer_ent **be_head, timestruc_t *lu)
102*7c478bd9Sstevel@tonic-gate {
103*7c478bd9Sstevel@tonic-gate 	FILE *fd;
104*7c478bd9Sstevel@tonic-gate 	struct buffer_ent *be_tail = NULL, *bep;
105*7c478bd9Sstevel@tonic-gate 	struct sharepnt_ent *se_tail = NULL, *sep;
106*7c478bd9Sstevel@tonic-gate 	struct logtab_ent *lep;
107*7c478bd9Sstevel@tonic-gate 	struct stat st;
108*7c478bd9Sstevel@tonic-gate 	int error = 0, res;
109*7c478bd9Sstevel@tonic-gate 
110*7c478bd9Sstevel@tonic-gate 	if ((fd = fopen(NFSLOGTAB, "r+")) == NULL) {
111*7c478bd9Sstevel@tonic-gate 		error = errno;
112*7c478bd9Sstevel@tonic-gate 		if (error != ENOENT) {
113*7c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR, gettext("%s - %s\n"), NFSLOGTAB,
114*7c478bd9Sstevel@tonic-gate 				strerror(error));
115*7c478bd9Sstevel@tonic-gate 			error = 0;
116*7c478bd9Sstevel@tonic-gate 		}
117*7c478bd9Sstevel@tonic-gate 		return (error);
118*7c478bd9Sstevel@tonic-gate 	}
119*7c478bd9Sstevel@tonic-gate 
120*7c478bd9Sstevel@tonic-gate 	if (lockf(fileno(fd), F_LOCK, 0L) < 0) {
121*7c478bd9Sstevel@tonic-gate 		error = errno;
122*7c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR, gettext("cannot lock %s - %s\n"), NFSLOGTAB,
123*7c478bd9Sstevel@tonic-gate 			strerror(error));
124*7c478bd9Sstevel@tonic-gate 		(void) fclose(fd);
125*7c478bd9Sstevel@tonic-gate 		return (error);
126*7c478bd9Sstevel@tonic-gate 	}
127*7c478bd9Sstevel@tonic-gate 
128*7c478bd9Sstevel@tonic-gate 	assert(*be_head == NULL);
129*7c478bd9Sstevel@tonic-gate 	while ((res = logtab_getent(fd, &lep)) > 0) {
130*7c478bd9Sstevel@tonic-gate 		if (bep = findbuffer(*be_head, lep->le_buffer)) {
131*7c478bd9Sstevel@tonic-gate 			/*
132*7c478bd9Sstevel@tonic-gate 			 * Add sharepnt to buffer list
133*7c478bd9Sstevel@tonic-gate 			 */
134*7c478bd9Sstevel@tonic-gate 			if (sep = findsharepnt(bep->be_sharepnt,
135*7c478bd9Sstevel@tonic-gate 			    lep->le_path, &se_tail)) {
136*7c478bd9Sstevel@tonic-gate 				/*
137*7c478bd9Sstevel@tonic-gate 				 * Sharepoint already in list,
138*7c478bd9Sstevel@tonic-gate 				 * update its state.
139*7c478bd9Sstevel@tonic-gate 				 */
140*7c478bd9Sstevel@tonic-gate 				sep->se_state = lep->le_state;
141*7c478bd9Sstevel@tonic-gate 			} else {
142*7c478bd9Sstevel@tonic-gate 				/*
143*7c478bd9Sstevel@tonic-gate 				 * Need to add to sharepoint list
144*7c478bd9Sstevel@tonic-gate 				 */
145*7c478bd9Sstevel@tonic-gate 				sep = (struct sharepnt_ent *)
146*7c478bd9Sstevel@tonic-gate 					malloc(sizeof (*sep));
147*7c478bd9Sstevel@tonic-gate 				if (sep == NULL) {
148*7c478bd9Sstevel@tonic-gate 					error = ENOMEM;
149*7c478bd9Sstevel@tonic-gate 					goto errout;
150*7c478bd9Sstevel@tonic-gate 				}
151*7c478bd9Sstevel@tonic-gate 				(void) memset(sep, 0, sizeof (*sep));
152*7c478bd9Sstevel@tonic-gate 
153*7c478bd9Sstevel@tonic-gate 				sep->se_name = strdup(lep->le_path);
154*7c478bd9Sstevel@tonic-gate 				if (sep->se_name == NULL) {
155*7c478bd9Sstevel@tonic-gate 					error = ENOMEM;
156*7c478bd9Sstevel@tonic-gate 					goto errout;
157*7c478bd9Sstevel@tonic-gate 				}
158*7c478bd9Sstevel@tonic-gate 				sep->se_state = lep->le_state;
159*7c478bd9Sstevel@tonic-gate 
160*7c478bd9Sstevel@tonic-gate 				assert(se_tail != NULL);
161*7c478bd9Sstevel@tonic-gate 				assert(se_tail->se_next == NULL);
162*7c478bd9Sstevel@tonic-gate 				se_tail->se_next = sep;
163*7c478bd9Sstevel@tonic-gate 			}
164*7c478bd9Sstevel@tonic-gate 		} else {
165*7c478bd9Sstevel@tonic-gate 			/*
166*7c478bd9Sstevel@tonic-gate 			 * Add new buffer to list
167*7c478bd9Sstevel@tonic-gate 			 */
168*7c478bd9Sstevel@tonic-gate 			bep = (struct buffer_ent *)malloc(sizeof (*bep));
169*7c478bd9Sstevel@tonic-gate 			if (bep == NULL) {
170*7c478bd9Sstevel@tonic-gate 				error = ENOMEM;
171*7c478bd9Sstevel@tonic-gate 				goto errout;
172*7c478bd9Sstevel@tonic-gate 			}
173*7c478bd9Sstevel@tonic-gate 			(void) memset(bep, 0, sizeof (*bep));
174*7c478bd9Sstevel@tonic-gate 
175*7c478bd9Sstevel@tonic-gate 			bep->be_name = strdup(lep->le_buffer);
176*7c478bd9Sstevel@tonic-gate 			if (bep->be_name == NULL) {
177*7c478bd9Sstevel@tonic-gate 				error = ENOMEM;
178*7c478bd9Sstevel@tonic-gate 				goto errout;
179*7c478bd9Sstevel@tonic-gate 			}
180*7c478bd9Sstevel@tonic-gate 
181*7c478bd9Sstevel@tonic-gate 			if (*be_head == NULL)
182*7c478bd9Sstevel@tonic-gate 				*be_head = bep;
183*7c478bd9Sstevel@tonic-gate 			else
184*7c478bd9Sstevel@tonic-gate 				be_tail->be_next = bep;
185*7c478bd9Sstevel@tonic-gate 			be_tail = bep;
186*7c478bd9Sstevel@tonic-gate 
187*7c478bd9Sstevel@tonic-gate 			bep->be_sharepnt = (struct sharepnt_ent *)
188*7c478bd9Sstevel@tonic-gate 				malloc(sizeof (*(bep->be_sharepnt)));
189*7c478bd9Sstevel@tonic-gate 			(void) memset(bep->be_sharepnt, 0,
190*7c478bd9Sstevel@tonic-gate 				sizeof (*(bep->be_sharepnt)));
191*7c478bd9Sstevel@tonic-gate 
192*7c478bd9Sstevel@tonic-gate 			if (bep->be_sharepnt == NULL) {
193*7c478bd9Sstevel@tonic-gate 				error = ENOMEM;
194*7c478bd9Sstevel@tonic-gate 				goto errout;
195*7c478bd9Sstevel@tonic-gate 			}
196*7c478bd9Sstevel@tonic-gate 			bep->be_sharepnt->se_name = strdup(lep->le_path);
197*7c478bd9Sstevel@tonic-gate 			if (bep->be_sharepnt->se_name == NULL) {
198*7c478bd9Sstevel@tonic-gate 				error = ENOMEM;
199*7c478bd9Sstevel@tonic-gate 				goto errout;
200*7c478bd9Sstevel@tonic-gate 			}
201*7c478bd9Sstevel@tonic-gate 			bep->be_sharepnt->se_state = lep->le_state;
202*7c478bd9Sstevel@tonic-gate 		}
203*7c478bd9Sstevel@tonic-gate 	}
204*7c478bd9Sstevel@tonic-gate 
205*7c478bd9Sstevel@tonic-gate 	if (res < 0) {
206*7c478bd9Sstevel@tonic-gate 		error = EIO;
207*7c478bd9Sstevel@tonic-gate 		goto errout;
208*7c478bd9Sstevel@tonic-gate 	}
209*7c478bd9Sstevel@tonic-gate 
210*7c478bd9Sstevel@tonic-gate 	/*
211*7c478bd9Sstevel@tonic-gate 	 * Get modification time while we have the file locked.
212*7c478bd9Sstevel@tonic-gate 	 */
213*7c478bd9Sstevel@tonic-gate 	if (lu) {
214*7c478bd9Sstevel@tonic-gate 		if ((error = fstat(fileno(fd), &st)) == -1) {
215*7c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR, gettext("Can't stat %s"), NFSLOGTAB);
216*7c478bd9Sstevel@tonic-gate 			goto errout;
217*7c478bd9Sstevel@tonic-gate 		}
218*7c478bd9Sstevel@tonic-gate 		*lu = st.st_mtim;
219*7c478bd9Sstevel@tonic-gate 	}
220*7c478bd9Sstevel@tonic-gate 
221*7c478bd9Sstevel@tonic-gate 	(void) fclose(fd);
222*7c478bd9Sstevel@tonic-gate 	return (error);
223*7c478bd9Sstevel@tonic-gate 
224*7c478bd9Sstevel@tonic-gate errout:
225*7c478bd9Sstevel@tonic-gate 	(void) fclose(fd);
226*7c478bd9Sstevel@tonic-gate 	if (lep)
227*7c478bd9Sstevel@tonic-gate 		logtab_ent_free(lep);
228*7c478bd9Sstevel@tonic-gate 	free_buffer_list(be_head);
229*7c478bd9Sstevel@tonic-gate 	assert(*be_head == NULL);
230*7c478bd9Sstevel@tonic-gate 	syslog(LOG_ERR, gettext("cannot read %s: %s\n"), NFSLOGTAB,
231*7c478bd9Sstevel@tonic-gate 		strerror(error));
232*7c478bd9Sstevel@tonic-gate 
233*7c478bd9Sstevel@tonic-gate 	return (error);
234*7c478bd9Sstevel@tonic-gate }
235*7c478bd9Sstevel@tonic-gate 
236*7c478bd9Sstevel@tonic-gate /*
237*7c478bd9Sstevel@tonic-gate  * Removes the entry from the buffer list and frees it.
238*7c478bd9Sstevel@tonic-gate  */
239*7c478bd9Sstevel@tonic-gate void
remove_buffer_ent(struct buffer_ent ** be_listpp,struct buffer_ent * bep)240*7c478bd9Sstevel@tonic-gate remove_buffer_ent(struct buffer_ent **be_listpp, struct buffer_ent *bep)
241*7c478bd9Sstevel@tonic-gate {
242*7c478bd9Sstevel@tonic-gate 	struct buffer_ent *p, *prev;
243*7c478bd9Sstevel@tonic-gate 
244*7c478bd9Sstevel@tonic-gate 	for (p = prev = *be_listpp; p != NULL; p = p->be_next) {
245*7c478bd9Sstevel@tonic-gate 		if (p == bep) {
246*7c478bd9Sstevel@tonic-gate 			if (p == *be_listpp)
247*7c478bd9Sstevel@tonic-gate 				*be_listpp = (*be_listpp)->be_next;
248*7c478bd9Sstevel@tonic-gate 			else
249*7c478bd9Sstevel@tonic-gate 				prev->be_next = bep->be_next;
250*7c478bd9Sstevel@tonic-gate 			free_buffer_ent(bep);
251*7c478bd9Sstevel@tonic-gate 			break;
252*7c478bd9Sstevel@tonic-gate 		}
253*7c478bd9Sstevel@tonic-gate 		prev = p;
254*7c478bd9Sstevel@tonic-gate 	}
255*7c478bd9Sstevel@tonic-gate }
256*7c478bd9Sstevel@tonic-gate 
257*7c478bd9Sstevel@tonic-gate /*
258*7c478bd9Sstevel@tonic-gate  * Frees the buffer list.
259*7c478bd9Sstevel@tonic-gate  */
260*7c478bd9Sstevel@tonic-gate void
free_buffer_list(struct buffer_ent ** be_listpp)261*7c478bd9Sstevel@tonic-gate free_buffer_list(struct buffer_ent **be_listpp)
262*7c478bd9Sstevel@tonic-gate {
263*7c478bd9Sstevel@tonic-gate 	struct buffer_ent *bep, *nextp;
264*7c478bd9Sstevel@tonic-gate 
265*7c478bd9Sstevel@tonic-gate 	for (bep = *be_listpp; bep != NULL; bep = nextp) {
266*7c478bd9Sstevel@tonic-gate 		nextp = bep->be_next;
267*7c478bd9Sstevel@tonic-gate 		free_buffer_ent(bep);
268*7c478bd9Sstevel@tonic-gate 	}
269*7c478bd9Sstevel@tonic-gate 	*be_listpp = NULL;
270*7c478bd9Sstevel@tonic-gate }
271*7c478bd9Sstevel@tonic-gate 
272*7c478bd9Sstevel@tonic-gate static void
free_buffer_ent(struct buffer_ent * bep)273*7c478bd9Sstevel@tonic-gate free_buffer_ent(struct buffer_ent *bep)
274*7c478bd9Sstevel@tonic-gate {
275*7c478bd9Sstevel@tonic-gate 	assert(bep != NULL);
276*7c478bd9Sstevel@tonic-gate 	if (debug)
277*7c478bd9Sstevel@tonic-gate 		(void) printf("freeing %s\n", bep->be_name);
278*7c478bd9Sstevel@tonic-gate 	if (bep->be_name != NULL)
279*7c478bd9Sstevel@tonic-gate 		free(bep->be_name);
280*7c478bd9Sstevel@tonic-gate 	if (bep->be_sharepnt != NULL)
281*7c478bd9Sstevel@tonic-gate 		free_sharepnt_list(bep->be_sharepnt);
282*7c478bd9Sstevel@tonic-gate 	free(bep);
283*7c478bd9Sstevel@tonic-gate }
284*7c478bd9Sstevel@tonic-gate 
285*7c478bd9Sstevel@tonic-gate static void
free_sharepnt_list(struct sharepnt_ent * sep_listp)286*7c478bd9Sstevel@tonic-gate free_sharepnt_list(struct sharepnt_ent *sep_listp)
287*7c478bd9Sstevel@tonic-gate {
288*7c478bd9Sstevel@tonic-gate 	struct sharepnt_ent *nextp;
289*7c478bd9Sstevel@tonic-gate 
290*7c478bd9Sstevel@tonic-gate 	for (; sep_listp != NULL; sep_listp = nextp) {
291*7c478bd9Sstevel@tonic-gate 		nextp = sep_listp->se_next;
292*7c478bd9Sstevel@tonic-gate 		free_sharepnt_ent(sep_listp);
293*7c478bd9Sstevel@tonic-gate 	}
294*7c478bd9Sstevel@tonic-gate 	free(sep_listp);
295*7c478bd9Sstevel@tonic-gate }
296*7c478bd9Sstevel@tonic-gate 
297*7c478bd9Sstevel@tonic-gate /*
298*7c478bd9Sstevel@tonic-gate  * Removes the entry from the sharepnt list and frees it.
299*7c478bd9Sstevel@tonic-gate  */
300*7c478bd9Sstevel@tonic-gate void
remove_sharepnt_ent(struct sharepnt_ent ** se_listpp,struct sharepnt_ent * sep)301*7c478bd9Sstevel@tonic-gate remove_sharepnt_ent(struct sharepnt_ent **se_listpp, struct sharepnt_ent *sep)
302*7c478bd9Sstevel@tonic-gate {
303*7c478bd9Sstevel@tonic-gate 	struct sharepnt_ent *p, *prev;
304*7c478bd9Sstevel@tonic-gate 
305*7c478bd9Sstevel@tonic-gate 	for (p = prev = *se_listpp; p != NULL; p = p->se_next) {
306*7c478bd9Sstevel@tonic-gate 		if (p == sep) {
307*7c478bd9Sstevel@tonic-gate 			if (p == *se_listpp)
308*7c478bd9Sstevel@tonic-gate 				*se_listpp = (*se_listpp)->se_next;
309*7c478bd9Sstevel@tonic-gate 			else
310*7c478bd9Sstevel@tonic-gate 				prev->se_next = sep->se_next;
311*7c478bd9Sstevel@tonic-gate 			free_sharepnt_ent(sep);
312*7c478bd9Sstevel@tonic-gate 			break;
313*7c478bd9Sstevel@tonic-gate 		}
314*7c478bd9Sstevel@tonic-gate 		prev = p;
315*7c478bd9Sstevel@tonic-gate 	}
316*7c478bd9Sstevel@tonic-gate }
317*7c478bd9Sstevel@tonic-gate 
318*7c478bd9Sstevel@tonic-gate static void
free_sharepnt_ent(struct sharepnt_ent * sep)319*7c478bd9Sstevel@tonic-gate free_sharepnt_ent(struct sharepnt_ent *sep)
320*7c478bd9Sstevel@tonic-gate {
321*7c478bd9Sstevel@tonic-gate 	assert(sep != NULL);
322*7c478bd9Sstevel@tonic-gate 	if (debug)
323*7c478bd9Sstevel@tonic-gate 		(void) printf("freeing %s\n", sep->se_name);
324*7c478bd9Sstevel@tonic-gate 	if (sep->se_name != NULL)
325*7c478bd9Sstevel@tonic-gate 		free(sep->se_name);
326*7c478bd9Sstevel@tonic-gate 	free(sep);
327*7c478bd9Sstevel@tonic-gate }
328*7c478bd9Sstevel@tonic-gate 
329*7c478bd9Sstevel@tonic-gate #ifdef DEBUG
330*7c478bd9Sstevel@tonic-gate void
printbuffer_list(struct buffer_ent * bep)331*7c478bd9Sstevel@tonic-gate printbuffer_list(struct buffer_ent *bep)
332*7c478bd9Sstevel@tonic-gate {
333*7c478bd9Sstevel@tonic-gate 	for (; bep != NULL; bep = bep->be_next) {
334*7c478bd9Sstevel@tonic-gate 		(void) printf("%s\n", bep->be_name);
335*7c478bd9Sstevel@tonic-gate 		if (bep->be_sharepnt != NULL)
336*7c478bd9Sstevel@tonic-gate 			print_sharepnt_list(bep->be_sharepnt);
337*7c478bd9Sstevel@tonic-gate 	}
338*7c478bd9Sstevel@tonic-gate }
339*7c478bd9Sstevel@tonic-gate 
340*7c478bd9Sstevel@tonic-gate static void
print_sharepnt_list(struct sharepnt_ent * sep)341*7c478bd9Sstevel@tonic-gate print_sharepnt_list(struct sharepnt_ent *sep)
342*7c478bd9Sstevel@tonic-gate {
343*7c478bd9Sstevel@tonic-gate 	for (; sep != NULL; sep = sep->se_next)
344*7c478bd9Sstevel@tonic-gate 		(void) printf("\t(%d) %s\n", sep->se_state, sep->se_name);
345*7c478bd9Sstevel@tonic-gate }
346*7c478bd9Sstevel@tonic-gate #endif
347*7c478bd9Sstevel@tonic-gate 
348*7c478bd9Sstevel@tonic-gate /*
349*7c478bd9Sstevel@tonic-gate  * Returns a pointer to the buffer matching 'name', NULL otherwise.
350*7c478bd9Sstevel@tonic-gate  */
351*7c478bd9Sstevel@tonic-gate static struct buffer_ent *
findbuffer(struct buffer_ent * bep,char * name)352*7c478bd9Sstevel@tonic-gate findbuffer(struct buffer_ent *bep, char *name)
353*7c478bd9Sstevel@tonic-gate {
354*7c478bd9Sstevel@tonic-gate 	for (; bep != NULL; bep = bep->be_next) {
355*7c478bd9Sstevel@tonic-gate 		if (strcmp(bep->be_name, name) == 0)
356*7c478bd9Sstevel@tonic-gate 			return (bep);
357*7c478bd9Sstevel@tonic-gate 	}
358*7c478bd9Sstevel@tonic-gate 	return (NULL);
359*7c478bd9Sstevel@tonic-gate }
360*7c478bd9Sstevel@tonic-gate 
361*7c478bd9Sstevel@tonic-gate /*
362*7c478bd9Sstevel@tonic-gate  * Returns a pointer the sharepoint entry matching 'name'.
363*7c478bd9Sstevel@tonic-gate  * Otherwise, it sets '*se_tail' to the last element of the list
364*7c478bd9Sstevel@tonic-gate  * to make insertion of new element easier, and returns NULL.
365*7c478bd9Sstevel@tonic-gate  */
366*7c478bd9Sstevel@tonic-gate static struct sharepnt_ent *
findsharepnt(struct sharepnt_ent * sep,char * name,struct sharepnt_ent ** se_tail)367*7c478bd9Sstevel@tonic-gate findsharepnt(
368*7c478bd9Sstevel@tonic-gate 	struct sharepnt_ent *sep,
369*7c478bd9Sstevel@tonic-gate 	char *name,
370*7c478bd9Sstevel@tonic-gate 	struct sharepnt_ent **se_tail)
371*7c478bd9Sstevel@tonic-gate {
372*7c478bd9Sstevel@tonic-gate 	struct sharepnt_ent *tail;
373*7c478bd9Sstevel@tonic-gate 
374*7c478bd9Sstevel@tonic-gate 	for (; sep != NULL; sep = sep->se_next) {
375*7c478bd9Sstevel@tonic-gate 		if (strcmp(sep->se_name, name) == 0)
376*7c478bd9Sstevel@tonic-gate 			return (sep);
377*7c478bd9Sstevel@tonic-gate 		tail = sep;
378*7c478bd9Sstevel@tonic-gate 	}
379*7c478bd9Sstevel@tonic-gate 	*se_tail = tail;
380*7c478bd9Sstevel@tonic-gate 	return (NULL);
381*7c478bd9Sstevel@tonic-gate }
382