2 * Copyright (c) 2000-2002, 2004 Sendmail, Inc. and its suppliers.
4 * Copyright (c) 1990, 1993
5 * The Regents of the University of California. All rights reserved.
7 * This code is derived from software contributed to Berkeley by
10 * By using this file, you agree to the terms and conditions set
11 * forth in the LICENSE file which can be found at the top level of
12 * the sendmail distribution.
16 SM_RCSID("@(#)$Id: fopen.c,v 1.62 2005/06/14 23:07:20 ca Exp $")
21 #include <sm/signal.h>
22 #include <sm/assert.h>
27 static void openalrm
__P((int));
28 static void reopenalrm
__P((int));
29 extern int sm_io_fclose
__P((SM_FILE_T
*));
31 static jmp_buf OpenTimeOut
, ReopenTimeOut
;
34 ** OPENALRM -- handler when timeout activated for sm_io_open()
36 ** Returns flow of control to where setjmp(OpenTimeOut) was set.
45 ** returns flow of control to setjmp(OpenTimeOut).
47 ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD
48 ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE
57 longjmp(OpenTimeOut
, 1);
60 ** REOPENALRM -- handler when timeout activated for sm_io_reopen()
62 ** Returns flow of control to where setjmp(ReopenTimeOut) was set.
71 ** returns flow of control to setjmp(ReopenTimeOut).
73 ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD
74 ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE
83 longjmp(ReopenTimeOut
, 1);
87 ** SM_IO_OPEN -- open a file of a specific type
90 ** type -- type of file to open
91 ** timeout -- time to complete the open
92 ** info -- info describing what is to be opened (type dependant)
93 ** flags -- user selected flags
94 ** rpool -- pointer to rpool to be used for this open
97 ** Raises exception on heap exhaustion.
98 ** Aborts if type is invalid.
99 ** Returns NULL and sets errno
100 ** - when the type specific open fails
101 ** - when open vector errors
102 ** - when flags not set or invalid
103 ** Success returns a file pointer to the opened file type.
107 sm_io_open(type
, timeout
, info
, flags
, rpool
)
108 const SM_FILE_T
*type
;
109 int SM_NONVOLATILE timeout
; /* this is not the file type timeout */
114 register SM_FILE_T
*fp
;
116 SM_EVENT
*evt
= NULL
;
118 ioflags
= sm_flags(flags
);
122 /* must give some indication/intent */
127 if (timeout
== SM_TIME_DEFAULT
)
128 timeout
= SM_TIME_FOREVER
;
129 if (timeout
== SM_TIME_IMMEDIATE
)
135 fp
= sm_fp(type
, ioflags
, NULL
);
137 /* Okay, this is where we set the timeout. */
138 if (timeout
!= SM_TIME_FOREVER
)
140 if (setjmp(OpenTimeOut
) != 0)
145 evt
= sm_seteventm(timeout
, openalrm
, 0);
148 if ((*fp
->f_open
)(fp
, info
, flags
, rpool
) < 0)
150 fp
->f_flags
= 0; /* release */
151 fp
->sm_magic
= NULL
; /* release */
155 /* We're back. So undo our timeout and handler */
161 sm_rpool_attach_x(rpool
, sm_io_fclose
, fp
);
162 #endif /* SM_RPOOL */
167 ** SM_IO_DUP -- duplicate a file pointer
170 ** fp -- file pointer to duplicate
173 ** Success - the duplicated file pointer
174 ** Failure - NULL (was an invalid file pointer or too many open)
176 ** Increments the duplicate counter (dup_cnt) for the open file pointer.
177 ** The counter counts the number of duplicates. When the duplicate
178 ** counter is 0 (zero) then the file pointer is the only one left
179 ** (no duplicates, it is the only one).
187 SM_REQUIRE_ISA(fp
, SmFileMagic
);
188 if (fp
->sm_magic
!= SmFileMagic
)
193 if (fp
->f_dup_cnt
>= INT_MAX
- 1)
195 /* Can't let f_dup_cnt wrap! */
203 ** SM_IO_REOPEN -- open a new file using the old file pointer
206 ** type -- file type to be opened
207 ** timeout -- time to complete the reopen
208 ** info -- infomation about what is to be "re-opened" (type dep.)
209 ** flags -- user flags to map to internal flags
210 ** rpool -- rpool file to be associated with
211 ** fp -- the file pointer to reuse
214 ** Raises an exception on heap exhaustion.
215 ** Aborts if type is invalid.
216 ** Failure: returns NULL
217 ** Success: returns "reopened" file pointer
221 sm_io_reopen(type
, timeout
, info
, flags
, rpool
, fp
)
222 const SM_FILE_T
*type
;
223 int SM_NONVOLATILE timeout
;
231 SM_EVENT
*evt
= NULL
;
233 if ((ioflags
= sm_flags(flags
)) == 0)
235 (void) sm_io_close(fp
, timeout
);
242 if (timeout
== SM_TIME_DEFAULT
)
243 timeout
= SM_TIME_FOREVER
;
244 if (timeout
== SM_TIME_IMMEDIATE
)
247 ** Filling the buffer will take time and we are wanted to
248 ** return immediately. So...
254 /* Okay, this is where we set the timeout. */
255 if (timeout
!= SM_TIME_FOREVER
)
257 if (setjmp(ReopenTimeOut
) != 0)
263 evt
= sm_seteventm(timeout
, reopenalrm
, 0);
267 ** There are actually programs that depend on being able to "reopen"
268 ** descriptors that weren't originally open. Keep this from breaking.
269 ** Remember whether the stream was open to begin with, and which file
270 ** descriptor (if any) was associated with it. If it was attached to
271 ** a descriptor, defer closing it; reopen("/dev/stdin", "r", stdin)
272 ** should work. This is unnecessary if it was not a Unix file.
277 if (fp
->sm_magic
!= SmFileMagic
)
278 fp
->f_flags
= SMFEOF
; /* hold on to it */
281 /* flush the stream; ANSI doesn't require this. */
282 (void) sm_io_flush(fp
, SM_TIME_FOREVER
);
283 (void) sm_io_close(fp
, SM_TIME_FOREVER
);
287 fp2
= sm_fp(type
, ioflags
, fp
);
288 ret
= (*fp2
->f_open
)(fp2
, info
, flags
, rpool
);
290 /* We're back. So undo our timeout and handler */
296 fp2
->f_flags
= 0; /* release */
297 fp2
->sm_magic
= NULL
; /* release */
302 ** We're not preserving this logic (below) for sm_io because it is now
303 ** abstracted at least one "layer" away. By closing and reopening
304 ** the 1st fd used should be the just released one (when Unix
305 ** behavior followed). Old comment::
306 ** If reopening something that was open before on a real file, try
307 ** to maintain the descriptor. Various C library routines (perror)
308 ** assume stderr is always fd STDERR_FILENO, even if being reopen'd.
313 sm_rpool_attach_x(rpool
, sm_io_close
, fp2
);
314 #endif /* SM_RPOOL */
319 ** SM_IO_AUTOFLUSH -- link another file to this for auto-flushing
321 ** When a read occurs on fp, fp2 will be flushed iff there is no
322 ** data waiting on fp.
325 ** fp -- the file opened for reading.
326 ** fp2 -- the file opened for writing.
329 ** The old flush file pointer.
333 sm_io_autoflush(fp
, fp2
)
339 SM_REQUIRE_ISA(fp
, SmFileMagic
);
341 SM_REQUIRE_ISA(fp2
, SmFileMagic
);
343 savefp
= fp
->f_flushfp
;
348 ** SM_IO_AUTOMODE -- link another file to this for auto-moding
350 ** When the mode (blocking or non-blocking) changes for fp1 then
351 ** update fp2's mode at the same time. This is to be used when
352 ** a system dup() has generated a second file descriptor for
353 ** another sm_io_open() by file descriptor. The modes have been
354 ** linked in the system and this formalizes it for sm_io internally.
357 ** fp1 -- the first file
358 ** fp2 -- the second file
365 sm_io_automode(fp1
, fp2
)
369 SM_REQUIRE_ISA(fp1
, SmFileMagic
);
370 SM_REQUIRE_ISA(fp2
, SmFileMagic
);