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