xref: /titanic_44/usr/src/cmd/sendmail/libsm/fopen.c (revision 49218d4f8e4d84d1c08aeb267bcf6e451f2056dc)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * Copyright (c) 2000-2002, 2004 Sendmail, Inc. and its suppliers.
37c478bd9Sstevel@tonic-gate  *      All rights reserved.
47c478bd9Sstevel@tonic-gate  * Copyright (c) 1990, 1993
57c478bd9Sstevel@tonic-gate  *	The Regents of the University of California.  All rights reserved.
67c478bd9Sstevel@tonic-gate  *
77c478bd9Sstevel@tonic-gate  * This code is derived from software contributed to Berkeley by
87c478bd9Sstevel@tonic-gate  * Chris Torek.
97c478bd9Sstevel@tonic-gate  *
107c478bd9Sstevel@tonic-gate  * By using this file, you agree to the terms and conditions set
117c478bd9Sstevel@tonic-gate  * forth in the LICENSE file which can be found at the top level of
127c478bd9Sstevel@tonic-gate  * the sendmail distribution.
137c478bd9Sstevel@tonic-gate  */
147c478bd9Sstevel@tonic-gate 
157c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
167c478bd9Sstevel@tonic-gate 
177c478bd9Sstevel@tonic-gate #include <sm/gen.h>
18*49218d4fSjbeck SM_RCSID("@(#)$Id: fopen.c,v 1.62 2005/06/14 23:07:20 ca Exp $")
197c478bd9Sstevel@tonic-gate #include <errno.h>
207c478bd9Sstevel@tonic-gate #include <setjmp.h>
21*49218d4fSjbeck #include <sm/time.h>
227c478bd9Sstevel@tonic-gate #include <sm/heap.h>
237c478bd9Sstevel@tonic-gate #include <sm/signal.h>
247c478bd9Sstevel@tonic-gate #include <sm/assert.h>
257c478bd9Sstevel@tonic-gate #include <sm/io.h>
267c478bd9Sstevel@tonic-gate #include <sm/clock.h>
277c478bd9Sstevel@tonic-gate #include "local.h"
287c478bd9Sstevel@tonic-gate 
297c478bd9Sstevel@tonic-gate static void	openalrm __P((int));
307c478bd9Sstevel@tonic-gate static void	reopenalrm __P((int));
317c478bd9Sstevel@tonic-gate extern int      sm_io_fclose __P((SM_FILE_T *));
327c478bd9Sstevel@tonic-gate 
337c478bd9Sstevel@tonic-gate static jmp_buf OpenTimeOut, ReopenTimeOut;
347c478bd9Sstevel@tonic-gate 
357c478bd9Sstevel@tonic-gate /*
367c478bd9Sstevel@tonic-gate **  OPENALRM -- handler when timeout activated for sm_io_open()
377c478bd9Sstevel@tonic-gate **
387c478bd9Sstevel@tonic-gate **  Returns flow of control to where setjmp(OpenTimeOut) was set.
397c478bd9Sstevel@tonic-gate **
407c478bd9Sstevel@tonic-gate **	Parameters:
417c478bd9Sstevel@tonic-gate **		sig -- unused
427c478bd9Sstevel@tonic-gate **
437c478bd9Sstevel@tonic-gate **	Returns:
447c478bd9Sstevel@tonic-gate **		does not return
457c478bd9Sstevel@tonic-gate **
467c478bd9Sstevel@tonic-gate **	Side Effects:
477c478bd9Sstevel@tonic-gate **		returns flow of control to setjmp(OpenTimeOut).
487c478bd9Sstevel@tonic-gate **
497c478bd9Sstevel@tonic-gate **	NOTE:	THIS CAN BE CALLED FROM A SIGNAL HANDLER.  DO NOT ADD
507c478bd9Sstevel@tonic-gate **		ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE
517c478bd9Sstevel@tonic-gate **		DOING.
527c478bd9Sstevel@tonic-gate */
537c478bd9Sstevel@tonic-gate 
547c478bd9Sstevel@tonic-gate /* ARGSUSED0 */
557c478bd9Sstevel@tonic-gate static void
openalrm(sig)567c478bd9Sstevel@tonic-gate openalrm(sig)
577c478bd9Sstevel@tonic-gate 	int sig;
587c478bd9Sstevel@tonic-gate {
597c478bd9Sstevel@tonic-gate 	longjmp(OpenTimeOut, 1);
607c478bd9Sstevel@tonic-gate }
617c478bd9Sstevel@tonic-gate /*
627c478bd9Sstevel@tonic-gate **  REOPENALRM -- handler when timeout activated for sm_io_reopen()
637c478bd9Sstevel@tonic-gate **
647c478bd9Sstevel@tonic-gate **  Returns flow of control to where setjmp(ReopenTimeOut) was set.
657c478bd9Sstevel@tonic-gate **
667c478bd9Sstevel@tonic-gate **	Parameters:
677c478bd9Sstevel@tonic-gate **		sig -- unused
687c478bd9Sstevel@tonic-gate **
697c478bd9Sstevel@tonic-gate **	Returns:
707c478bd9Sstevel@tonic-gate **		does not return
717c478bd9Sstevel@tonic-gate **
727c478bd9Sstevel@tonic-gate **	Side Effects:
737c478bd9Sstevel@tonic-gate **		returns flow of control to setjmp(ReopenTimeOut).
747c478bd9Sstevel@tonic-gate **
757c478bd9Sstevel@tonic-gate **	NOTE:	THIS CAN BE CALLED FROM A SIGNAL HANDLER.  DO NOT ADD
767c478bd9Sstevel@tonic-gate **		ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE
777c478bd9Sstevel@tonic-gate **		DOING.
787c478bd9Sstevel@tonic-gate */
797c478bd9Sstevel@tonic-gate 
807c478bd9Sstevel@tonic-gate /* ARGSUSED0 */
817c478bd9Sstevel@tonic-gate static void
reopenalrm(sig)827c478bd9Sstevel@tonic-gate reopenalrm(sig)
837c478bd9Sstevel@tonic-gate 	int sig;
847c478bd9Sstevel@tonic-gate {
857c478bd9Sstevel@tonic-gate 	longjmp(ReopenTimeOut, 1);
867c478bd9Sstevel@tonic-gate }
877c478bd9Sstevel@tonic-gate 
887c478bd9Sstevel@tonic-gate /*
897c478bd9Sstevel@tonic-gate **  SM_IO_OPEN -- open a file of a specific type
907c478bd9Sstevel@tonic-gate **
917c478bd9Sstevel@tonic-gate **	Parameters:
927c478bd9Sstevel@tonic-gate **		type -- type of file to open
937c478bd9Sstevel@tonic-gate **		timeout -- time to complete the open
947c478bd9Sstevel@tonic-gate **		info -- info describing what is to be opened (type dependant)
957c478bd9Sstevel@tonic-gate **		flags -- user selected flags
967c478bd9Sstevel@tonic-gate **		rpool -- pointer to rpool to be used for this open
977c478bd9Sstevel@tonic-gate **
987c478bd9Sstevel@tonic-gate **	Returns:
997c478bd9Sstevel@tonic-gate **		Raises exception on heap exhaustion.
1007c478bd9Sstevel@tonic-gate **		Aborts if type is invalid.
1017c478bd9Sstevel@tonic-gate **		Returns NULL and sets errno
1027c478bd9Sstevel@tonic-gate **			- when the type specific open fails
1037c478bd9Sstevel@tonic-gate **			- when open vector errors
1047c478bd9Sstevel@tonic-gate **			- when flags not set or invalid
1057c478bd9Sstevel@tonic-gate **		Success returns a file pointer to the opened file type.
1067c478bd9Sstevel@tonic-gate */
1077c478bd9Sstevel@tonic-gate 
1087c478bd9Sstevel@tonic-gate SM_FILE_T *
sm_io_open(type,timeout,info,flags,rpool)1097c478bd9Sstevel@tonic-gate sm_io_open(type, timeout, info, flags, rpool)
1107c478bd9Sstevel@tonic-gate 	const SM_FILE_T *type;
1117c478bd9Sstevel@tonic-gate 	int SM_NONVOLATILE timeout;	/* this is not the file type timeout */
1127c478bd9Sstevel@tonic-gate 	const void *info;
1137c478bd9Sstevel@tonic-gate 	int flags;
1147c478bd9Sstevel@tonic-gate 	const void *rpool;
1157c478bd9Sstevel@tonic-gate {
1167c478bd9Sstevel@tonic-gate 	register SM_FILE_T *fp;
1177c478bd9Sstevel@tonic-gate 	int ioflags;
1187c478bd9Sstevel@tonic-gate 	SM_EVENT *evt = NULL;
1197c478bd9Sstevel@tonic-gate 
1207c478bd9Sstevel@tonic-gate 	ioflags = sm_flags(flags);
1217c478bd9Sstevel@tonic-gate 
1227c478bd9Sstevel@tonic-gate 	if (ioflags == 0)
1237c478bd9Sstevel@tonic-gate 	{
1247c478bd9Sstevel@tonic-gate 		/* must give some indication/intent */
1257c478bd9Sstevel@tonic-gate 		errno = EINVAL;
1267c478bd9Sstevel@tonic-gate 		return NULL;
1277c478bd9Sstevel@tonic-gate 	}
1287c478bd9Sstevel@tonic-gate 
1297c478bd9Sstevel@tonic-gate 	if (timeout == SM_TIME_DEFAULT)
1307c478bd9Sstevel@tonic-gate 		timeout = SM_TIME_FOREVER;
1317c478bd9Sstevel@tonic-gate 	if (timeout == SM_TIME_IMMEDIATE)
1327c478bd9Sstevel@tonic-gate 	{
1337c478bd9Sstevel@tonic-gate 		errno = EAGAIN;
1347c478bd9Sstevel@tonic-gate 		return NULL;
1357c478bd9Sstevel@tonic-gate 	}
1367c478bd9Sstevel@tonic-gate 
1377c478bd9Sstevel@tonic-gate 	fp = sm_fp(type, ioflags, NULL);
1387c478bd9Sstevel@tonic-gate 
1397c478bd9Sstevel@tonic-gate 	/*  Okay, this is where we set the timeout.  */
1407c478bd9Sstevel@tonic-gate 	if (timeout != SM_TIME_FOREVER)
1417c478bd9Sstevel@tonic-gate 	{
1427c478bd9Sstevel@tonic-gate 		if (setjmp(OpenTimeOut) != 0)
1437c478bd9Sstevel@tonic-gate 		{
1447c478bd9Sstevel@tonic-gate 			errno = EAGAIN;
1457c478bd9Sstevel@tonic-gate 			return NULL;
1467c478bd9Sstevel@tonic-gate 		}
1477c478bd9Sstevel@tonic-gate 		evt = sm_seteventm(timeout, openalrm, 0);
1487c478bd9Sstevel@tonic-gate 	}
1497c478bd9Sstevel@tonic-gate 
1507c478bd9Sstevel@tonic-gate 	if ((*fp->f_open)(fp, info, flags, rpool) < 0)
1517c478bd9Sstevel@tonic-gate 	{
1527c478bd9Sstevel@tonic-gate 		fp->f_flags = 0;	/* release */
1537c478bd9Sstevel@tonic-gate 		fp->sm_magic = NULL;	/* release */
1547c478bd9Sstevel@tonic-gate 		return NULL;
1557c478bd9Sstevel@tonic-gate 	}
1567c478bd9Sstevel@tonic-gate 
1577c478bd9Sstevel@tonic-gate 	/*  We're back. So undo our timeout and handler */
1587c478bd9Sstevel@tonic-gate 	if (evt != NULL)
1597c478bd9Sstevel@tonic-gate 		sm_clrevent(evt);
1607c478bd9Sstevel@tonic-gate 
1617c478bd9Sstevel@tonic-gate #if SM_RPOOL
1627c478bd9Sstevel@tonic-gate 	if (rpool != NULL)
1637c478bd9Sstevel@tonic-gate 		sm_rpool_attach_x(rpool, sm_io_fclose, fp);
1647c478bd9Sstevel@tonic-gate #endif /* SM_RPOOL */
1657c478bd9Sstevel@tonic-gate 
1667c478bd9Sstevel@tonic-gate 	return fp;
1677c478bd9Sstevel@tonic-gate }
1687c478bd9Sstevel@tonic-gate /*
1697c478bd9Sstevel@tonic-gate **  SM_IO_DUP -- duplicate a file pointer
1707c478bd9Sstevel@tonic-gate **
1717c478bd9Sstevel@tonic-gate **	Parameters:
1727c478bd9Sstevel@tonic-gate **		fp -- file pointer to duplicate
1737c478bd9Sstevel@tonic-gate **
1747c478bd9Sstevel@tonic-gate **	Returns:
1757c478bd9Sstevel@tonic-gate **		Success - the duplicated file pointer
1767c478bd9Sstevel@tonic-gate **		Failure - NULL (was an invalid file pointer or too many open)
1777c478bd9Sstevel@tonic-gate **
1787c478bd9Sstevel@tonic-gate **	Increments the duplicate counter (dup_cnt) for the open file pointer.
1797c478bd9Sstevel@tonic-gate **	The counter counts the number of duplicates. When the duplicate
1807c478bd9Sstevel@tonic-gate **	counter is 0 (zero) then the file pointer is the only one left
1817c478bd9Sstevel@tonic-gate **	(no duplicates, it is the only one).
1827c478bd9Sstevel@tonic-gate */
1837c478bd9Sstevel@tonic-gate 
1847c478bd9Sstevel@tonic-gate SM_FILE_T *
sm_io_dup(fp)1857c478bd9Sstevel@tonic-gate sm_io_dup(fp)
1867c478bd9Sstevel@tonic-gate 	SM_FILE_T *fp;
1877c478bd9Sstevel@tonic-gate {
1887c478bd9Sstevel@tonic-gate 
1897c478bd9Sstevel@tonic-gate 	SM_REQUIRE_ISA(fp, SmFileMagic);
1907c478bd9Sstevel@tonic-gate 	if (fp->sm_magic != SmFileMagic)
1917c478bd9Sstevel@tonic-gate 	{
1927c478bd9Sstevel@tonic-gate 		errno = EBADF;
1937c478bd9Sstevel@tonic-gate 		return NULL;
1947c478bd9Sstevel@tonic-gate 	}
1957c478bd9Sstevel@tonic-gate 	if (fp->f_dup_cnt >= INT_MAX - 1)
1967c478bd9Sstevel@tonic-gate 	{
1977c478bd9Sstevel@tonic-gate 		/* Can't let f_dup_cnt wrap! */
1987c478bd9Sstevel@tonic-gate 		errno = EMFILE;
1997c478bd9Sstevel@tonic-gate 		return NULL;
2007c478bd9Sstevel@tonic-gate 	}
2017c478bd9Sstevel@tonic-gate 	fp->f_dup_cnt++;
2027c478bd9Sstevel@tonic-gate 	return fp;
2037c478bd9Sstevel@tonic-gate }
2047c478bd9Sstevel@tonic-gate /*
2057c478bd9Sstevel@tonic-gate **  SM_IO_REOPEN -- open a new file using the old file pointer
2067c478bd9Sstevel@tonic-gate **
2077c478bd9Sstevel@tonic-gate **	Parameters:
2087c478bd9Sstevel@tonic-gate **		type -- file type to be opened
2097c478bd9Sstevel@tonic-gate **		timeout -- time to complete the reopen
2107c478bd9Sstevel@tonic-gate **		info -- infomation about what is to be "re-opened" (type dep.)
2117c478bd9Sstevel@tonic-gate **		flags -- user flags to map to internal flags
2127c478bd9Sstevel@tonic-gate **		rpool -- rpool file to be associated with
2137c478bd9Sstevel@tonic-gate **		fp -- the file pointer to reuse
2147c478bd9Sstevel@tonic-gate **
2157c478bd9Sstevel@tonic-gate **	Returns:
2167c478bd9Sstevel@tonic-gate **		Raises an exception on heap exhaustion.
2177c478bd9Sstevel@tonic-gate **		Aborts if type is invalid.
2187c478bd9Sstevel@tonic-gate **		Failure: returns NULL
2197c478bd9Sstevel@tonic-gate **		Success: returns "reopened" file pointer
2207c478bd9Sstevel@tonic-gate */
2217c478bd9Sstevel@tonic-gate 
2227c478bd9Sstevel@tonic-gate SM_FILE_T *
sm_io_reopen(type,timeout,info,flags,rpool,fp)2237c478bd9Sstevel@tonic-gate sm_io_reopen(type, timeout, info, flags, rpool, fp)
2247c478bd9Sstevel@tonic-gate 	const SM_FILE_T *type;
2257c478bd9Sstevel@tonic-gate 	int SM_NONVOLATILE timeout;
2267c478bd9Sstevel@tonic-gate 	const void *info;
2277c478bd9Sstevel@tonic-gate 	int flags;
2287c478bd9Sstevel@tonic-gate 	const void *rpool;
2297c478bd9Sstevel@tonic-gate 	SM_FILE_T *fp;
2307c478bd9Sstevel@tonic-gate {
2317c478bd9Sstevel@tonic-gate 	int ioflags, ret;
2327c478bd9Sstevel@tonic-gate 	SM_FILE_T *fp2;
2337c478bd9Sstevel@tonic-gate 	SM_EVENT *evt = NULL;
2347c478bd9Sstevel@tonic-gate 
2357c478bd9Sstevel@tonic-gate 	if ((ioflags = sm_flags(flags)) == 0)
2367c478bd9Sstevel@tonic-gate 	{
2377c478bd9Sstevel@tonic-gate 		(void) sm_io_close(fp, timeout);
2387c478bd9Sstevel@tonic-gate 		return NULL;
2397c478bd9Sstevel@tonic-gate 	}
2407c478bd9Sstevel@tonic-gate 
2417c478bd9Sstevel@tonic-gate 	if (!Sm_IO_DidInit)
2427c478bd9Sstevel@tonic-gate 		sm_init();
2437c478bd9Sstevel@tonic-gate 
2447c478bd9Sstevel@tonic-gate 	if (timeout == SM_TIME_DEFAULT)
2457c478bd9Sstevel@tonic-gate 		timeout = SM_TIME_FOREVER;
2467c478bd9Sstevel@tonic-gate 	if (timeout == SM_TIME_IMMEDIATE)
2477c478bd9Sstevel@tonic-gate 	{
2487c478bd9Sstevel@tonic-gate 		/*
2497c478bd9Sstevel@tonic-gate 		**  Filling the buffer will take time and we are wanted to
2507c478bd9Sstevel@tonic-gate 		**  return immediately. So...
2517c478bd9Sstevel@tonic-gate 		*/
2527c478bd9Sstevel@tonic-gate 
2537c478bd9Sstevel@tonic-gate 		errno = EAGAIN;
2547c478bd9Sstevel@tonic-gate 		return NULL;
2557c478bd9Sstevel@tonic-gate 	}
2567c478bd9Sstevel@tonic-gate 	/*  Okay, this is where we set the timeout.  */
2577c478bd9Sstevel@tonic-gate 	if (timeout != SM_TIME_FOREVER)
2587c478bd9Sstevel@tonic-gate 	{
2597c478bd9Sstevel@tonic-gate 		if (setjmp(ReopenTimeOut) != 0)
2607c478bd9Sstevel@tonic-gate 		{
2617c478bd9Sstevel@tonic-gate 			errno = EAGAIN;
2627c478bd9Sstevel@tonic-gate 			return NULL;
2637c478bd9Sstevel@tonic-gate 		}
2647c478bd9Sstevel@tonic-gate 
2657c478bd9Sstevel@tonic-gate 		evt = sm_seteventm(timeout, reopenalrm, 0);
2667c478bd9Sstevel@tonic-gate 	}
2677c478bd9Sstevel@tonic-gate 
2687c478bd9Sstevel@tonic-gate 	/*
2697c478bd9Sstevel@tonic-gate 	**  There are actually programs that depend on being able to "reopen"
2707c478bd9Sstevel@tonic-gate 	**  descriptors that weren't originally open.  Keep this from breaking.
2717c478bd9Sstevel@tonic-gate 	**  Remember whether the stream was open to begin with, and which file
2727c478bd9Sstevel@tonic-gate 	**  descriptor (if any) was associated with it.  If it was attached to
2737c478bd9Sstevel@tonic-gate 	**  a descriptor, defer closing it; reopen("/dev/stdin", "r", stdin)
2747c478bd9Sstevel@tonic-gate 	**  should work.  This is unnecessary if it was not a Unix file.
2757c478bd9Sstevel@tonic-gate 	*/
2767c478bd9Sstevel@tonic-gate 
2777c478bd9Sstevel@tonic-gate 	if (fp != NULL)
2787c478bd9Sstevel@tonic-gate 	{
2797c478bd9Sstevel@tonic-gate 		if (fp->sm_magic != SmFileMagic)
2807c478bd9Sstevel@tonic-gate 			fp->f_flags = SMFEOF;	/* hold on to it */
2817c478bd9Sstevel@tonic-gate 		else
2827c478bd9Sstevel@tonic-gate 		{
2837c478bd9Sstevel@tonic-gate 			/* flush the stream; ANSI doesn't require this. */
2847c478bd9Sstevel@tonic-gate 			(void) sm_io_flush(fp, SM_TIME_FOREVER);
2857c478bd9Sstevel@tonic-gate 			(void) sm_io_close(fp, SM_TIME_FOREVER);
2867c478bd9Sstevel@tonic-gate 		}
2877c478bd9Sstevel@tonic-gate 	}
2887c478bd9Sstevel@tonic-gate 
2897c478bd9Sstevel@tonic-gate 	fp2 = sm_fp(type, ioflags, fp);
2907c478bd9Sstevel@tonic-gate 	ret = (*fp2->f_open)(fp2, info, flags, rpool);
2917c478bd9Sstevel@tonic-gate 
2927c478bd9Sstevel@tonic-gate 	/*  We're back. So undo our timeout and handler */
2937c478bd9Sstevel@tonic-gate 	if (evt != NULL)
2947c478bd9Sstevel@tonic-gate 		sm_clrevent(evt);
2957c478bd9Sstevel@tonic-gate 
2967c478bd9Sstevel@tonic-gate 	if (ret < 0)
2977c478bd9Sstevel@tonic-gate 	{
2987c478bd9Sstevel@tonic-gate 		fp2->f_flags = 0;	/* release */
2997c478bd9Sstevel@tonic-gate 		fp2->sm_magic = NULL;	/* release */
3007c478bd9Sstevel@tonic-gate 		return NULL;
3017c478bd9Sstevel@tonic-gate 	}
3027c478bd9Sstevel@tonic-gate 
3037c478bd9Sstevel@tonic-gate 	/*
3047c478bd9Sstevel@tonic-gate 	**  We're not preserving this logic (below) for sm_io because it is now
3057c478bd9Sstevel@tonic-gate 	**  abstracted at least one "layer" away. By closing and reopening
3067c478bd9Sstevel@tonic-gate 	**  the 1st fd used should be the just released one (when Unix
3077c478bd9Sstevel@tonic-gate 	**  behavior followed). Old comment::
3087c478bd9Sstevel@tonic-gate 	**  If reopening something that was open before on a real file, try
3097c478bd9Sstevel@tonic-gate 	**  to maintain the descriptor.  Various C library routines (perror)
3107c478bd9Sstevel@tonic-gate 	**  assume stderr is always fd STDERR_FILENO, even if being reopen'd.
3117c478bd9Sstevel@tonic-gate 	*/
3127c478bd9Sstevel@tonic-gate 
3137c478bd9Sstevel@tonic-gate #if SM_RPOOL
3147c478bd9Sstevel@tonic-gate 	if (rpool != NULL)
3157c478bd9Sstevel@tonic-gate 		sm_rpool_attach_x(rpool, sm_io_close, fp2);
3167c478bd9Sstevel@tonic-gate #endif /* SM_RPOOL */
3177c478bd9Sstevel@tonic-gate 
3187c478bd9Sstevel@tonic-gate 	return fp2;
3197c478bd9Sstevel@tonic-gate }
3207c478bd9Sstevel@tonic-gate /*
3217c478bd9Sstevel@tonic-gate **  SM_IO_AUTOFLUSH -- link another file to this for auto-flushing
3227c478bd9Sstevel@tonic-gate **
3237c478bd9Sstevel@tonic-gate **	When a read occurs on fp, fp2 will be flushed iff there is no
3247c478bd9Sstevel@tonic-gate **	data waiting on fp.
3257c478bd9Sstevel@tonic-gate **
3267c478bd9Sstevel@tonic-gate **	Parameters:
3277c478bd9Sstevel@tonic-gate **		fp -- the file opened for reading.
3287c478bd9Sstevel@tonic-gate **		fp2 -- the file opened for writing.
3297c478bd9Sstevel@tonic-gate **
3307c478bd9Sstevel@tonic-gate **	Returns:
3317c478bd9Sstevel@tonic-gate **		The old flush file pointer.
3327c478bd9Sstevel@tonic-gate */
3337c478bd9Sstevel@tonic-gate 
3347c478bd9Sstevel@tonic-gate SM_FILE_T *
sm_io_autoflush(fp,fp2)3357c478bd9Sstevel@tonic-gate sm_io_autoflush(fp, fp2)
3367c478bd9Sstevel@tonic-gate 	SM_FILE_T *fp;
3377c478bd9Sstevel@tonic-gate 	SM_FILE_T *fp2;
3387c478bd9Sstevel@tonic-gate {
3397c478bd9Sstevel@tonic-gate 	SM_FILE_T *savefp;
3407c478bd9Sstevel@tonic-gate 
3417c478bd9Sstevel@tonic-gate 	SM_REQUIRE_ISA(fp, SmFileMagic);
3427c478bd9Sstevel@tonic-gate 	if (fp2 != NULL)
3437c478bd9Sstevel@tonic-gate 		SM_REQUIRE_ISA(fp2, SmFileMagic);
3447c478bd9Sstevel@tonic-gate 
3457c478bd9Sstevel@tonic-gate 	savefp = fp->f_flushfp;
3467c478bd9Sstevel@tonic-gate 	fp->f_flushfp = fp2;
3477c478bd9Sstevel@tonic-gate 	return savefp;
3487c478bd9Sstevel@tonic-gate }
3497c478bd9Sstevel@tonic-gate /*
3507c478bd9Sstevel@tonic-gate **  SM_IO_AUTOMODE -- link another file to this for auto-moding
3517c478bd9Sstevel@tonic-gate **
3527c478bd9Sstevel@tonic-gate **	When the mode (blocking or non-blocking) changes for fp1 then
3537c478bd9Sstevel@tonic-gate **	update fp2's mode at the same time. This is to be used when
3547c478bd9Sstevel@tonic-gate **	a system dup() has generated a second file descriptor for
3557c478bd9Sstevel@tonic-gate **	another sm_io_open() by file descriptor. The modes have been
3567c478bd9Sstevel@tonic-gate **	linked in the system and this formalizes it for sm_io internally.
3577c478bd9Sstevel@tonic-gate **
3587c478bd9Sstevel@tonic-gate **	Parameters:
3597c478bd9Sstevel@tonic-gate **		fp1 -- the first file
3607c478bd9Sstevel@tonic-gate **		fp2 -- the second file
3617c478bd9Sstevel@tonic-gate **
3627c478bd9Sstevel@tonic-gate **	Returns:
3637c478bd9Sstevel@tonic-gate **		nothing
3647c478bd9Sstevel@tonic-gate */
3657c478bd9Sstevel@tonic-gate 
3667c478bd9Sstevel@tonic-gate void
sm_io_automode(fp1,fp2)3677c478bd9Sstevel@tonic-gate sm_io_automode(fp1, fp2)
3687c478bd9Sstevel@tonic-gate 	SM_FILE_T *fp1;
3697c478bd9Sstevel@tonic-gate 	SM_FILE_T *fp2;
3707c478bd9Sstevel@tonic-gate {
3717c478bd9Sstevel@tonic-gate 	SM_REQUIRE_ISA(fp1, SmFileMagic);
3727c478bd9Sstevel@tonic-gate 	SM_REQUIRE_ISA(fp2, SmFileMagic);
3737c478bd9Sstevel@tonic-gate 
3747c478bd9Sstevel@tonic-gate 	fp1->f_modefp = fp2;
3757c478bd9Sstevel@tonic-gate 	fp2->f_modefp = fp1;
3767c478bd9Sstevel@tonic-gate }
377