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.
15 #pragma ident "%Z%%M% %I% %E% SMI"
18 SM_RCSID("@(#)$Id: fopen.c,v 1.62 2005/06/14 23:07:20 ca Exp $")
23 #include <sm/signal.h>
24 #include <sm/assert.h>
29 static void openalrm
__P((int));
30 static void reopenalrm
__P((int));
31 extern int sm_io_fclose
__P((SM_FILE_T
*));
33 static jmp_buf OpenTimeOut
, ReopenTimeOut
;
36 ** OPENALRM -- handler when timeout activated for sm_io_open()
38 ** Returns flow of control to where setjmp(OpenTimeOut) was set.
47 ** returns flow of control to setjmp(OpenTimeOut).
49 ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD
50 ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE
59 longjmp(OpenTimeOut
, 1);
62 ** REOPENALRM -- handler when timeout activated for sm_io_reopen()
64 ** Returns flow of control to where setjmp(ReopenTimeOut) was set.
73 ** returns flow of control to setjmp(ReopenTimeOut).
75 ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD
76 ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE
85 longjmp(ReopenTimeOut
, 1);
89 ** SM_IO_OPEN -- open a file of a specific type
92 ** type -- type of file to open
93 ** timeout -- time to complete the open
94 ** info -- info describing what is to be opened (type dependant)
95 ** flags -- user selected flags
96 ** rpool -- pointer to rpool to be used for this open
99 ** Raises exception on heap exhaustion.
100 ** Aborts if type is invalid.
101 ** Returns NULL and sets errno
102 ** - when the type specific open fails
103 ** - when open vector errors
104 ** - when flags not set or invalid
105 ** Success returns a file pointer to the opened file type.
109 sm_io_open(type
, timeout
, info
, flags
, rpool
)
110 const SM_FILE_T
*type
;
111 int SM_NONVOLATILE timeout
; /* this is not the file type timeout */
116 register SM_FILE_T
*fp
;
118 SM_EVENT
*evt
= NULL
;
120 ioflags
= sm_flags(flags
);
124 /* must give some indication/intent */
129 if (timeout
== SM_TIME_DEFAULT
)
130 timeout
= SM_TIME_FOREVER
;
131 if (timeout
== SM_TIME_IMMEDIATE
)
137 fp
= sm_fp(type
, ioflags
, NULL
);
139 /* Okay, this is where we set the timeout. */
140 if (timeout
!= SM_TIME_FOREVER
)
142 if (setjmp(OpenTimeOut
) != 0)
147 evt
= sm_seteventm(timeout
, openalrm
, 0);
150 if ((*fp
->f_open
)(fp
, info
, flags
, rpool
) < 0)
152 fp
->f_flags
= 0; /* release */
153 fp
->sm_magic
= NULL
; /* release */
157 /* We're back. So undo our timeout and handler */
163 sm_rpool_attach_x(rpool
, sm_io_fclose
, fp
);
164 #endif /* SM_RPOOL */
169 ** SM_IO_DUP -- duplicate a file pointer
172 ** fp -- file pointer to duplicate
175 ** Success - the duplicated file pointer
176 ** Failure - NULL (was an invalid file pointer or too many open)
178 ** Increments the duplicate counter (dup_cnt) for the open file pointer.
179 ** The counter counts the number of duplicates. When the duplicate
180 ** counter is 0 (zero) then the file pointer is the only one left
181 ** (no duplicates, it is the only one).
189 SM_REQUIRE_ISA(fp
, SmFileMagic
);
190 if (fp
->sm_magic
!= SmFileMagic
)
195 if (fp
->f_dup_cnt
>= INT_MAX
- 1)
197 /* Can't let f_dup_cnt wrap! */
205 ** SM_IO_REOPEN -- open a new file using the old file pointer
208 ** type -- file type to be opened
209 ** timeout -- time to complete the reopen
210 ** info -- infomation about what is to be "re-opened" (type dep.)
211 ** flags -- user flags to map to internal flags
212 ** rpool -- rpool file to be associated with
213 ** fp -- the file pointer to reuse
216 ** Raises an exception on heap exhaustion.
217 ** Aborts if type is invalid.
218 ** Failure: returns NULL
219 ** Success: returns "reopened" file pointer
223 sm_io_reopen(type
, timeout
, info
, flags
, rpool
, fp
)
224 const SM_FILE_T
*type
;
225 int SM_NONVOLATILE timeout
;
233 SM_EVENT
*evt
= NULL
;
235 if ((ioflags
= sm_flags(flags
)) == 0)
237 (void) sm_io_close(fp
, timeout
);
244 if (timeout
== SM_TIME_DEFAULT
)
245 timeout
= SM_TIME_FOREVER
;
246 if (timeout
== SM_TIME_IMMEDIATE
)
249 ** Filling the buffer will take time and we are wanted to
250 ** return immediately. So...
256 /* Okay, this is where we set the timeout. */
257 if (timeout
!= SM_TIME_FOREVER
)
259 if (setjmp(ReopenTimeOut
) != 0)
265 evt
= sm_seteventm(timeout
, reopenalrm
, 0);
269 ** There are actually programs that depend on being able to "reopen"
270 ** descriptors that weren't originally open. Keep this from breaking.
271 ** Remember whether the stream was open to begin with, and which file
272 ** descriptor (if any) was associated with it. If it was attached to
273 ** a descriptor, defer closing it; reopen("/dev/stdin", "r", stdin)
274 ** should work. This is unnecessary if it was not a Unix file.
279 if (fp
->sm_magic
!= SmFileMagic
)
280 fp
->f_flags
= SMFEOF
; /* hold on to it */
283 /* flush the stream; ANSI doesn't require this. */
284 (void) sm_io_flush(fp
, SM_TIME_FOREVER
);
285 (void) sm_io_close(fp
, SM_TIME_FOREVER
);
289 fp2
= sm_fp(type
, ioflags
, fp
);
290 ret
= (*fp2
->f_open
)(fp2
, info
, flags
, rpool
);
292 /* We're back. So undo our timeout and handler */
298 fp2
->f_flags
= 0; /* release */
299 fp2
->sm_magic
= NULL
; /* release */
304 ** We're not preserving this logic (below) for sm_io because it is now
305 ** abstracted at least one "layer" away. By closing and reopening
306 ** the 1st fd used should be the just released one (when Unix
307 ** behavior followed). Old comment::
308 ** If reopening something that was open before on a real file, try
309 ** to maintain the descriptor. Various C library routines (perror)
310 ** assume stderr is always fd STDERR_FILENO, even if being reopen'd.
315 sm_rpool_attach_x(rpool
, sm_io_close
, fp2
);
316 #endif /* SM_RPOOL */
321 ** SM_IO_AUTOFLUSH -- link another file to this for auto-flushing
323 ** When a read occurs on fp, fp2 will be flushed iff there is no
324 ** data waiting on fp.
327 ** fp -- the file opened for reading.
328 ** fp2 -- the file opened for writing.
331 ** The old flush file pointer.
335 sm_io_autoflush(fp
, fp2
)
341 SM_REQUIRE_ISA(fp
, SmFileMagic
);
343 SM_REQUIRE_ISA(fp2
, SmFileMagic
);
345 savefp
= fp
->f_flushfp
;
350 ** SM_IO_AUTOMODE -- link another file to this for auto-moding
352 ** When the mode (blocking or non-blocking) changes for fp1 then
353 ** update fp2's mode at the same time. This is to be used when
354 ** a system dup() has generated a second file descriptor for
355 ** another sm_io_open() by file descriptor. The modes have been
356 ** linked in the system and this formalizes it for sm_io internally.
359 ** fp1 -- the first file
360 ** fp2 -- the second file
367 sm_io_automode(fp1
, fp2
)
371 SM_REQUIRE_ISA(fp1
, SmFileMagic
);
372 SM_REQUIRE_ISA(fp2
, SmFileMagic
);