xref: /titanic_44/usr/src/cmd/sendmail/libsm/fopen.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * Copyright (c) 2000-2002, 2004 Sendmail, Inc. and its suppliers.
3*7c478bd9Sstevel@tonic-gate  *      All rights reserved.
4*7c478bd9Sstevel@tonic-gate  * Copyright (c) 1990, 1993
5*7c478bd9Sstevel@tonic-gate  *	The Regents of the University of California.  All rights reserved.
6*7c478bd9Sstevel@tonic-gate  *
7*7c478bd9Sstevel@tonic-gate  * This code is derived from software contributed to Berkeley by
8*7c478bd9Sstevel@tonic-gate  * Chris Torek.
9*7c478bd9Sstevel@tonic-gate  *
10*7c478bd9Sstevel@tonic-gate  * By using this file, you agree to the terms and conditions set
11*7c478bd9Sstevel@tonic-gate  * forth in the LICENSE file which can be found at the top level of
12*7c478bd9Sstevel@tonic-gate  * the sendmail distribution.
13*7c478bd9Sstevel@tonic-gate  */
14*7c478bd9Sstevel@tonic-gate 
15*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
16*7c478bd9Sstevel@tonic-gate 
17*7c478bd9Sstevel@tonic-gate #include <sm/gen.h>
18*7c478bd9Sstevel@tonic-gate SM_RCSID("@(#)$Id: fopen.c,v 1.61 2004/08/03 20:17:38 ca Exp $")
19*7c478bd9Sstevel@tonic-gate #include <errno.h>
20*7c478bd9Sstevel@tonic-gate #include <setjmp.h>
21*7c478bd9Sstevel@tonic-gate #include <sys/time.h>
22*7c478bd9Sstevel@tonic-gate #include <sm/heap.h>
23*7c478bd9Sstevel@tonic-gate #include <sm/signal.h>
24*7c478bd9Sstevel@tonic-gate #include <sm/assert.h>
25*7c478bd9Sstevel@tonic-gate #include <sm/io.h>
26*7c478bd9Sstevel@tonic-gate #include <sm/clock.h>
27*7c478bd9Sstevel@tonic-gate #include "local.h"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate static void	openalrm __P((int));
30*7c478bd9Sstevel@tonic-gate static void	reopenalrm __P((int));
31*7c478bd9Sstevel@tonic-gate extern int      sm_io_fclose __P((SM_FILE_T *));
32*7c478bd9Sstevel@tonic-gate 
33*7c478bd9Sstevel@tonic-gate static jmp_buf OpenTimeOut, ReopenTimeOut;
34*7c478bd9Sstevel@tonic-gate 
35*7c478bd9Sstevel@tonic-gate /*
36*7c478bd9Sstevel@tonic-gate **  OPENALRM -- handler when timeout activated for sm_io_open()
37*7c478bd9Sstevel@tonic-gate **
38*7c478bd9Sstevel@tonic-gate **  Returns flow of control to where setjmp(OpenTimeOut) was set.
39*7c478bd9Sstevel@tonic-gate **
40*7c478bd9Sstevel@tonic-gate **	Parameters:
41*7c478bd9Sstevel@tonic-gate **		sig -- unused
42*7c478bd9Sstevel@tonic-gate **
43*7c478bd9Sstevel@tonic-gate **	Returns:
44*7c478bd9Sstevel@tonic-gate **		does not return
45*7c478bd9Sstevel@tonic-gate **
46*7c478bd9Sstevel@tonic-gate **	Side Effects:
47*7c478bd9Sstevel@tonic-gate **		returns flow of control to setjmp(OpenTimeOut).
48*7c478bd9Sstevel@tonic-gate **
49*7c478bd9Sstevel@tonic-gate **	NOTE:	THIS CAN BE CALLED FROM A SIGNAL HANDLER.  DO NOT ADD
50*7c478bd9Sstevel@tonic-gate **		ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE
51*7c478bd9Sstevel@tonic-gate **		DOING.
52*7c478bd9Sstevel@tonic-gate */
53*7c478bd9Sstevel@tonic-gate 
54*7c478bd9Sstevel@tonic-gate /* ARGSUSED0 */
55*7c478bd9Sstevel@tonic-gate static void
56*7c478bd9Sstevel@tonic-gate openalrm(sig)
57*7c478bd9Sstevel@tonic-gate 	int sig;
58*7c478bd9Sstevel@tonic-gate {
59*7c478bd9Sstevel@tonic-gate 	longjmp(OpenTimeOut, 1);
60*7c478bd9Sstevel@tonic-gate }
61*7c478bd9Sstevel@tonic-gate /*
62*7c478bd9Sstevel@tonic-gate **  REOPENALRM -- handler when timeout activated for sm_io_reopen()
63*7c478bd9Sstevel@tonic-gate **
64*7c478bd9Sstevel@tonic-gate **  Returns flow of control to where setjmp(ReopenTimeOut) was set.
65*7c478bd9Sstevel@tonic-gate **
66*7c478bd9Sstevel@tonic-gate **	Parameters:
67*7c478bd9Sstevel@tonic-gate **		sig -- unused
68*7c478bd9Sstevel@tonic-gate **
69*7c478bd9Sstevel@tonic-gate **	Returns:
70*7c478bd9Sstevel@tonic-gate **		does not return
71*7c478bd9Sstevel@tonic-gate **
72*7c478bd9Sstevel@tonic-gate **	Side Effects:
73*7c478bd9Sstevel@tonic-gate **		returns flow of control to setjmp(ReopenTimeOut).
74*7c478bd9Sstevel@tonic-gate **
75*7c478bd9Sstevel@tonic-gate **	NOTE:	THIS CAN BE CALLED FROM A SIGNAL HANDLER.  DO NOT ADD
76*7c478bd9Sstevel@tonic-gate **		ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE
77*7c478bd9Sstevel@tonic-gate **		DOING.
78*7c478bd9Sstevel@tonic-gate */
79*7c478bd9Sstevel@tonic-gate 
80*7c478bd9Sstevel@tonic-gate /* ARGSUSED0 */
81*7c478bd9Sstevel@tonic-gate static void
82*7c478bd9Sstevel@tonic-gate reopenalrm(sig)
83*7c478bd9Sstevel@tonic-gate 	int sig;
84*7c478bd9Sstevel@tonic-gate {
85*7c478bd9Sstevel@tonic-gate 	longjmp(ReopenTimeOut, 1);
86*7c478bd9Sstevel@tonic-gate }
87*7c478bd9Sstevel@tonic-gate 
88*7c478bd9Sstevel@tonic-gate /*
89*7c478bd9Sstevel@tonic-gate **  SM_IO_OPEN -- open a file of a specific type
90*7c478bd9Sstevel@tonic-gate **
91*7c478bd9Sstevel@tonic-gate **	Parameters:
92*7c478bd9Sstevel@tonic-gate **		type -- type of file to open
93*7c478bd9Sstevel@tonic-gate **		timeout -- time to complete the open
94*7c478bd9Sstevel@tonic-gate **		info -- info describing what is to be opened (type dependant)
95*7c478bd9Sstevel@tonic-gate **		flags -- user selected flags
96*7c478bd9Sstevel@tonic-gate **		rpool -- pointer to rpool to be used for this open
97*7c478bd9Sstevel@tonic-gate **
98*7c478bd9Sstevel@tonic-gate **	Returns:
99*7c478bd9Sstevel@tonic-gate **		Raises exception on heap exhaustion.
100*7c478bd9Sstevel@tonic-gate **		Aborts if type is invalid.
101*7c478bd9Sstevel@tonic-gate **		Returns NULL and sets errno
102*7c478bd9Sstevel@tonic-gate **			- when the type specific open fails
103*7c478bd9Sstevel@tonic-gate **			- when open vector errors
104*7c478bd9Sstevel@tonic-gate **			- when flags not set or invalid
105*7c478bd9Sstevel@tonic-gate **		Success returns a file pointer to the opened file type.
106*7c478bd9Sstevel@tonic-gate */
107*7c478bd9Sstevel@tonic-gate 
108*7c478bd9Sstevel@tonic-gate SM_FILE_T *
109*7c478bd9Sstevel@tonic-gate sm_io_open(type, timeout, info, flags, rpool)
110*7c478bd9Sstevel@tonic-gate 	const SM_FILE_T *type;
111*7c478bd9Sstevel@tonic-gate 	int SM_NONVOLATILE timeout;	/* this is not the file type timeout */
112*7c478bd9Sstevel@tonic-gate 	const void *info;
113*7c478bd9Sstevel@tonic-gate 	int flags;
114*7c478bd9Sstevel@tonic-gate 	const void *rpool;
115*7c478bd9Sstevel@tonic-gate {
116*7c478bd9Sstevel@tonic-gate 	register SM_FILE_T *fp;
117*7c478bd9Sstevel@tonic-gate 	int ioflags;
118*7c478bd9Sstevel@tonic-gate 	SM_EVENT *evt = NULL;
119*7c478bd9Sstevel@tonic-gate 
120*7c478bd9Sstevel@tonic-gate 	ioflags = sm_flags(flags);
121*7c478bd9Sstevel@tonic-gate 
122*7c478bd9Sstevel@tonic-gate 	if (ioflags == 0)
123*7c478bd9Sstevel@tonic-gate 	{
124*7c478bd9Sstevel@tonic-gate 		/* must give some indication/intent */
125*7c478bd9Sstevel@tonic-gate 		errno = EINVAL;
126*7c478bd9Sstevel@tonic-gate 		return NULL;
127*7c478bd9Sstevel@tonic-gate 	}
128*7c478bd9Sstevel@tonic-gate 
129*7c478bd9Sstevel@tonic-gate 	if (timeout == SM_TIME_DEFAULT)
130*7c478bd9Sstevel@tonic-gate 		timeout = SM_TIME_FOREVER;
131*7c478bd9Sstevel@tonic-gate 	if (timeout == SM_TIME_IMMEDIATE)
132*7c478bd9Sstevel@tonic-gate 	{
133*7c478bd9Sstevel@tonic-gate 		errno = EAGAIN;
134*7c478bd9Sstevel@tonic-gate 		return NULL;
135*7c478bd9Sstevel@tonic-gate 	}
136*7c478bd9Sstevel@tonic-gate 
137*7c478bd9Sstevel@tonic-gate 	fp = sm_fp(type, ioflags, NULL);
138*7c478bd9Sstevel@tonic-gate 
139*7c478bd9Sstevel@tonic-gate 	/*  Okay, this is where we set the timeout.  */
140*7c478bd9Sstevel@tonic-gate 	if (timeout != SM_TIME_FOREVER)
141*7c478bd9Sstevel@tonic-gate 	{
142*7c478bd9Sstevel@tonic-gate 		if (setjmp(OpenTimeOut) != 0)
143*7c478bd9Sstevel@tonic-gate 		{
144*7c478bd9Sstevel@tonic-gate 			errno = EAGAIN;
145*7c478bd9Sstevel@tonic-gate 			return NULL;
146*7c478bd9Sstevel@tonic-gate 		}
147*7c478bd9Sstevel@tonic-gate 		evt = sm_seteventm(timeout, openalrm, 0);
148*7c478bd9Sstevel@tonic-gate 	}
149*7c478bd9Sstevel@tonic-gate 
150*7c478bd9Sstevel@tonic-gate 	if ((*fp->f_open)(fp, info, flags, rpool) < 0)
151*7c478bd9Sstevel@tonic-gate 	{
152*7c478bd9Sstevel@tonic-gate 		fp->f_flags = 0;	/* release */
153*7c478bd9Sstevel@tonic-gate 		fp->sm_magic = NULL;	/* release */
154*7c478bd9Sstevel@tonic-gate 		return NULL;
155*7c478bd9Sstevel@tonic-gate 	}
156*7c478bd9Sstevel@tonic-gate 
157*7c478bd9Sstevel@tonic-gate 	/*  We're back. So undo our timeout and handler */
158*7c478bd9Sstevel@tonic-gate 	if (evt != NULL)
159*7c478bd9Sstevel@tonic-gate 		sm_clrevent(evt);
160*7c478bd9Sstevel@tonic-gate 
161*7c478bd9Sstevel@tonic-gate #if SM_RPOOL
162*7c478bd9Sstevel@tonic-gate 	if (rpool != NULL)
163*7c478bd9Sstevel@tonic-gate 		sm_rpool_attach_x(rpool, sm_io_fclose, fp);
164*7c478bd9Sstevel@tonic-gate #endif /* SM_RPOOL */
165*7c478bd9Sstevel@tonic-gate 
166*7c478bd9Sstevel@tonic-gate 	return fp;
167*7c478bd9Sstevel@tonic-gate }
168*7c478bd9Sstevel@tonic-gate /*
169*7c478bd9Sstevel@tonic-gate **  SM_IO_DUP -- duplicate a file pointer
170*7c478bd9Sstevel@tonic-gate **
171*7c478bd9Sstevel@tonic-gate **	Parameters:
172*7c478bd9Sstevel@tonic-gate **		fp -- file pointer to duplicate
173*7c478bd9Sstevel@tonic-gate **
174*7c478bd9Sstevel@tonic-gate **	Returns:
175*7c478bd9Sstevel@tonic-gate **		Success - the duplicated file pointer
176*7c478bd9Sstevel@tonic-gate **		Failure - NULL (was an invalid file pointer or too many open)
177*7c478bd9Sstevel@tonic-gate **
178*7c478bd9Sstevel@tonic-gate **	Increments the duplicate counter (dup_cnt) for the open file pointer.
179*7c478bd9Sstevel@tonic-gate **	The counter counts the number of duplicates. When the duplicate
180*7c478bd9Sstevel@tonic-gate **	counter is 0 (zero) then the file pointer is the only one left
181*7c478bd9Sstevel@tonic-gate **	(no duplicates, it is the only one).
182*7c478bd9Sstevel@tonic-gate */
183*7c478bd9Sstevel@tonic-gate 
184*7c478bd9Sstevel@tonic-gate SM_FILE_T *
185*7c478bd9Sstevel@tonic-gate sm_io_dup(fp)
186*7c478bd9Sstevel@tonic-gate 	SM_FILE_T *fp;
187*7c478bd9Sstevel@tonic-gate {
188*7c478bd9Sstevel@tonic-gate 
189*7c478bd9Sstevel@tonic-gate 	SM_REQUIRE_ISA(fp, SmFileMagic);
190*7c478bd9Sstevel@tonic-gate 	if (fp->sm_magic != SmFileMagic)
191*7c478bd9Sstevel@tonic-gate 	{
192*7c478bd9Sstevel@tonic-gate 		errno = EBADF;
193*7c478bd9Sstevel@tonic-gate 		return NULL;
194*7c478bd9Sstevel@tonic-gate 	}
195*7c478bd9Sstevel@tonic-gate 	if (fp->f_dup_cnt >= INT_MAX - 1)
196*7c478bd9Sstevel@tonic-gate 	{
197*7c478bd9Sstevel@tonic-gate 		/* Can't let f_dup_cnt wrap! */
198*7c478bd9Sstevel@tonic-gate 		errno = EMFILE;
199*7c478bd9Sstevel@tonic-gate 		return NULL;
200*7c478bd9Sstevel@tonic-gate 	}
201*7c478bd9Sstevel@tonic-gate 	fp->f_dup_cnt++;
202*7c478bd9Sstevel@tonic-gate 	return fp;
203*7c478bd9Sstevel@tonic-gate }
204*7c478bd9Sstevel@tonic-gate /*
205*7c478bd9Sstevel@tonic-gate **  SM_IO_REOPEN -- open a new file using the old file pointer
206*7c478bd9Sstevel@tonic-gate **
207*7c478bd9Sstevel@tonic-gate **	Parameters:
208*7c478bd9Sstevel@tonic-gate **		type -- file type to be opened
209*7c478bd9Sstevel@tonic-gate **		timeout -- time to complete the reopen
210*7c478bd9Sstevel@tonic-gate **		info -- infomation about what is to be "re-opened" (type dep.)
211*7c478bd9Sstevel@tonic-gate **		flags -- user flags to map to internal flags
212*7c478bd9Sstevel@tonic-gate **		rpool -- rpool file to be associated with
213*7c478bd9Sstevel@tonic-gate **		fp -- the file pointer to reuse
214*7c478bd9Sstevel@tonic-gate **
215*7c478bd9Sstevel@tonic-gate **	Returns:
216*7c478bd9Sstevel@tonic-gate **		Raises an exception on heap exhaustion.
217*7c478bd9Sstevel@tonic-gate **		Aborts if type is invalid.
218*7c478bd9Sstevel@tonic-gate **		Failure: returns NULL
219*7c478bd9Sstevel@tonic-gate **		Success: returns "reopened" file pointer
220*7c478bd9Sstevel@tonic-gate */
221*7c478bd9Sstevel@tonic-gate 
222*7c478bd9Sstevel@tonic-gate SM_FILE_T *
223*7c478bd9Sstevel@tonic-gate sm_io_reopen(type, timeout, info, flags, rpool, fp)
224*7c478bd9Sstevel@tonic-gate 	const SM_FILE_T *type;
225*7c478bd9Sstevel@tonic-gate 	int SM_NONVOLATILE timeout;
226*7c478bd9Sstevel@tonic-gate 	const void *info;
227*7c478bd9Sstevel@tonic-gate 	int flags;
228*7c478bd9Sstevel@tonic-gate 	const void *rpool;
229*7c478bd9Sstevel@tonic-gate 	SM_FILE_T *fp;
230*7c478bd9Sstevel@tonic-gate {
231*7c478bd9Sstevel@tonic-gate 	int ioflags, ret;
232*7c478bd9Sstevel@tonic-gate 	SM_FILE_T *fp2;
233*7c478bd9Sstevel@tonic-gate 	SM_EVENT *evt = NULL;
234*7c478bd9Sstevel@tonic-gate 
235*7c478bd9Sstevel@tonic-gate 	if ((ioflags = sm_flags(flags)) == 0)
236*7c478bd9Sstevel@tonic-gate 	{
237*7c478bd9Sstevel@tonic-gate 		(void) sm_io_close(fp, timeout);
238*7c478bd9Sstevel@tonic-gate 		return NULL;
239*7c478bd9Sstevel@tonic-gate 	}
240*7c478bd9Sstevel@tonic-gate 
241*7c478bd9Sstevel@tonic-gate 	if (!Sm_IO_DidInit)
242*7c478bd9Sstevel@tonic-gate 		sm_init();
243*7c478bd9Sstevel@tonic-gate 
244*7c478bd9Sstevel@tonic-gate 	if (timeout == SM_TIME_DEFAULT)
245*7c478bd9Sstevel@tonic-gate 		timeout = SM_TIME_FOREVER;
246*7c478bd9Sstevel@tonic-gate 	if (timeout == SM_TIME_IMMEDIATE)
247*7c478bd9Sstevel@tonic-gate 	{
248*7c478bd9Sstevel@tonic-gate 		/*
249*7c478bd9Sstevel@tonic-gate 		**  Filling the buffer will take time and we are wanted to
250*7c478bd9Sstevel@tonic-gate 		**  return immediately. So...
251*7c478bd9Sstevel@tonic-gate 		*/
252*7c478bd9Sstevel@tonic-gate 
253*7c478bd9Sstevel@tonic-gate 		errno = EAGAIN;
254*7c478bd9Sstevel@tonic-gate 		return NULL;
255*7c478bd9Sstevel@tonic-gate 	}
256*7c478bd9Sstevel@tonic-gate 	/*  Okay, this is where we set the timeout.  */
257*7c478bd9Sstevel@tonic-gate 	if (timeout != SM_TIME_FOREVER)
258*7c478bd9Sstevel@tonic-gate 	{
259*7c478bd9Sstevel@tonic-gate 		if (setjmp(ReopenTimeOut) != 0)
260*7c478bd9Sstevel@tonic-gate 		{
261*7c478bd9Sstevel@tonic-gate 			errno = EAGAIN;
262*7c478bd9Sstevel@tonic-gate 			return NULL;
263*7c478bd9Sstevel@tonic-gate 		}
264*7c478bd9Sstevel@tonic-gate 
265*7c478bd9Sstevel@tonic-gate 		evt = sm_seteventm(timeout, reopenalrm, 0);
266*7c478bd9Sstevel@tonic-gate 	}
267*7c478bd9Sstevel@tonic-gate 
268*7c478bd9Sstevel@tonic-gate 	/*
269*7c478bd9Sstevel@tonic-gate 	**  There are actually programs that depend on being able to "reopen"
270*7c478bd9Sstevel@tonic-gate 	**  descriptors that weren't originally open.  Keep this from breaking.
271*7c478bd9Sstevel@tonic-gate 	**  Remember whether the stream was open to begin with, and which file
272*7c478bd9Sstevel@tonic-gate 	**  descriptor (if any) was associated with it.  If it was attached to
273*7c478bd9Sstevel@tonic-gate 	**  a descriptor, defer closing it; reopen("/dev/stdin", "r", stdin)
274*7c478bd9Sstevel@tonic-gate 	**  should work.  This is unnecessary if it was not a Unix file.
275*7c478bd9Sstevel@tonic-gate 	*/
276*7c478bd9Sstevel@tonic-gate 
277*7c478bd9Sstevel@tonic-gate 	if (fp != NULL)
278*7c478bd9Sstevel@tonic-gate 	{
279*7c478bd9Sstevel@tonic-gate 		if (fp->sm_magic != SmFileMagic)
280*7c478bd9Sstevel@tonic-gate 			fp->f_flags = SMFEOF;	/* hold on to it */
281*7c478bd9Sstevel@tonic-gate 		else
282*7c478bd9Sstevel@tonic-gate 		{
283*7c478bd9Sstevel@tonic-gate 			/* flush the stream; ANSI doesn't require this. */
284*7c478bd9Sstevel@tonic-gate 			(void) sm_io_flush(fp, SM_TIME_FOREVER);
285*7c478bd9Sstevel@tonic-gate 			(void) sm_io_close(fp, SM_TIME_FOREVER);
286*7c478bd9Sstevel@tonic-gate 		}
287*7c478bd9Sstevel@tonic-gate 	}
288*7c478bd9Sstevel@tonic-gate 
289*7c478bd9Sstevel@tonic-gate 	fp2 = sm_fp(type, ioflags, fp);
290*7c478bd9Sstevel@tonic-gate 	ret = (*fp2->f_open)(fp2, info, flags, rpool);
291*7c478bd9Sstevel@tonic-gate 
292*7c478bd9Sstevel@tonic-gate 	/*  We're back. So undo our timeout and handler */
293*7c478bd9Sstevel@tonic-gate 	if (evt != NULL)
294*7c478bd9Sstevel@tonic-gate 		sm_clrevent(evt);
295*7c478bd9Sstevel@tonic-gate 
296*7c478bd9Sstevel@tonic-gate 	if (ret < 0)
297*7c478bd9Sstevel@tonic-gate 	{
298*7c478bd9Sstevel@tonic-gate 		fp2->f_flags = 0;	/* release */
299*7c478bd9Sstevel@tonic-gate 		fp2->sm_magic = NULL;	/* release */
300*7c478bd9Sstevel@tonic-gate 		return NULL;
301*7c478bd9Sstevel@tonic-gate 	}
302*7c478bd9Sstevel@tonic-gate 
303*7c478bd9Sstevel@tonic-gate 	/*
304*7c478bd9Sstevel@tonic-gate 	**  We're not preserving this logic (below) for sm_io because it is now
305*7c478bd9Sstevel@tonic-gate 	**  abstracted at least one "layer" away. By closing and reopening
306*7c478bd9Sstevel@tonic-gate 	**  the 1st fd used should be the just released one (when Unix
307*7c478bd9Sstevel@tonic-gate 	**  behavior followed). Old comment::
308*7c478bd9Sstevel@tonic-gate 	**  If reopening something that was open before on a real file, try
309*7c478bd9Sstevel@tonic-gate 	**  to maintain the descriptor.  Various C library routines (perror)
310*7c478bd9Sstevel@tonic-gate 	**  assume stderr is always fd STDERR_FILENO, even if being reopen'd.
311*7c478bd9Sstevel@tonic-gate 	*/
312*7c478bd9Sstevel@tonic-gate 
313*7c478bd9Sstevel@tonic-gate #if SM_RPOOL
314*7c478bd9Sstevel@tonic-gate 	if (rpool != NULL)
315*7c478bd9Sstevel@tonic-gate 		sm_rpool_attach_x(rpool, sm_io_close, fp2);
316*7c478bd9Sstevel@tonic-gate #endif /* SM_RPOOL */
317*7c478bd9Sstevel@tonic-gate 
318*7c478bd9Sstevel@tonic-gate 	return fp2;
319*7c478bd9Sstevel@tonic-gate }
320*7c478bd9Sstevel@tonic-gate /*
321*7c478bd9Sstevel@tonic-gate **  SM_IO_AUTOFLUSH -- link another file to this for auto-flushing
322*7c478bd9Sstevel@tonic-gate **
323*7c478bd9Sstevel@tonic-gate **	When a read occurs on fp, fp2 will be flushed iff there is no
324*7c478bd9Sstevel@tonic-gate **	data waiting on fp.
325*7c478bd9Sstevel@tonic-gate **
326*7c478bd9Sstevel@tonic-gate **	Parameters:
327*7c478bd9Sstevel@tonic-gate **		fp -- the file opened for reading.
328*7c478bd9Sstevel@tonic-gate **		fp2 -- the file opened for writing.
329*7c478bd9Sstevel@tonic-gate **
330*7c478bd9Sstevel@tonic-gate **	Returns:
331*7c478bd9Sstevel@tonic-gate **		The old flush file pointer.
332*7c478bd9Sstevel@tonic-gate */
333*7c478bd9Sstevel@tonic-gate 
334*7c478bd9Sstevel@tonic-gate SM_FILE_T *
335*7c478bd9Sstevel@tonic-gate sm_io_autoflush(fp, fp2)
336*7c478bd9Sstevel@tonic-gate 	SM_FILE_T *fp;
337*7c478bd9Sstevel@tonic-gate 	SM_FILE_T *fp2;
338*7c478bd9Sstevel@tonic-gate {
339*7c478bd9Sstevel@tonic-gate 	SM_FILE_T *savefp;
340*7c478bd9Sstevel@tonic-gate 
341*7c478bd9Sstevel@tonic-gate 	SM_REQUIRE_ISA(fp, SmFileMagic);
342*7c478bd9Sstevel@tonic-gate 	if (fp2 != NULL)
343*7c478bd9Sstevel@tonic-gate 		SM_REQUIRE_ISA(fp2, SmFileMagic);
344*7c478bd9Sstevel@tonic-gate 
345*7c478bd9Sstevel@tonic-gate 	savefp = fp->f_flushfp;
346*7c478bd9Sstevel@tonic-gate 	fp->f_flushfp = fp2;
347*7c478bd9Sstevel@tonic-gate 	return savefp;
348*7c478bd9Sstevel@tonic-gate }
349*7c478bd9Sstevel@tonic-gate /*
350*7c478bd9Sstevel@tonic-gate **  SM_IO_AUTOMODE -- link another file to this for auto-moding
351*7c478bd9Sstevel@tonic-gate **
352*7c478bd9Sstevel@tonic-gate **	When the mode (blocking or non-blocking) changes for fp1 then
353*7c478bd9Sstevel@tonic-gate **	update fp2's mode at the same time. This is to be used when
354*7c478bd9Sstevel@tonic-gate **	a system dup() has generated a second file descriptor for
355*7c478bd9Sstevel@tonic-gate **	another sm_io_open() by file descriptor. The modes have been
356*7c478bd9Sstevel@tonic-gate **	linked in the system and this formalizes it for sm_io internally.
357*7c478bd9Sstevel@tonic-gate **
358*7c478bd9Sstevel@tonic-gate **	Parameters:
359*7c478bd9Sstevel@tonic-gate **		fp1 -- the first file
360*7c478bd9Sstevel@tonic-gate **		fp2 -- the second file
361*7c478bd9Sstevel@tonic-gate **
362*7c478bd9Sstevel@tonic-gate **	Returns:
363*7c478bd9Sstevel@tonic-gate **		nothing
364*7c478bd9Sstevel@tonic-gate */
365*7c478bd9Sstevel@tonic-gate 
366*7c478bd9Sstevel@tonic-gate void
367*7c478bd9Sstevel@tonic-gate sm_io_automode(fp1, fp2)
368*7c478bd9Sstevel@tonic-gate 	SM_FILE_T *fp1;
369*7c478bd9Sstevel@tonic-gate 	SM_FILE_T *fp2;
370*7c478bd9Sstevel@tonic-gate {
371*7c478bd9Sstevel@tonic-gate 	SM_REQUIRE_ISA(fp1, SmFileMagic);
372*7c478bd9Sstevel@tonic-gate 	SM_REQUIRE_ISA(fp2, SmFileMagic);
373*7c478bd9Sstevel@tonic-gate 
374*7c478bd9Sstevel@tonic-gate 	fp1->f_modefp = fp2;
375*7c478bd9Sstevel@tonic-gate 	fp2->f_modefp = fp1;
376*7c478bd9Sstevel@tonic-gate }
377