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: fclose.c,v 1.44 2005/06/14 23:07:20 ca Exp $")
22 #include <sm/assert.h>
24 #include <sm/signal.h>
29 static void closealrm
__P((int));
30 static jmp_buf CloseTimeOut
;
33 ** CLOSEALRM -- handler when timeout activated for sm_io_close()
35 ** Returns flow of control to where setjmp(CloseTimeOut) was set.
44 ** returns flow of control to setjmp(CloseTimeOut).
46 ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD
47 ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE
56 longjmp(CloseTimeOut
, 1);
60 ** SM_IO_CLOSE -- close a file handle/pointer
63 ** fp -- file pointer to be closed
64 ** timeout -- maximum time allowed to perform the close (millisecs)
68 ** -1 on failure and sets errno
71 ** file pointer 'fp' will no longer be valid.
75 sm_io_close(fp
, timeout
)
76 register SM_FILE_T
*fp
;
77 int SM_NONVOLATILE timeout
;
79 register int SM_NONVOLATILE r
;
88 SM_REQUIRE_ISA(fp
, SmFileMagic
);
90 /* XXX this won't be reached if above macro is active */
91 if (fp
->sm_magic
== NULL
)
97 if (fp
->f_close
== NULL
)
99 /* no close function! */
103 if (fp
->f_dup_cnt
> 0)
105 /* decrement file pointer open count */
110 /* Okay, this is where we set the timeout. */
111 if (timeout
== SM_TIME_DEFAULT
)
112 timeout
= fp
->f_timeout
;
113 if (timeout
== SM_TIME_IMMEDIATE
)
119 /* No more duplicates of file pointer. Flush buffer and close */
120 r
= fp
->f_flags
& SMWR
? sm_flush(fp
, (int *) &timeout
) : 0;
122 /* sm_flush() has updated to.it_value for the time it's used */
123 if (timeout
!= SM_TIME_FOREVER
)
125 if (setjmp(CloseTimeOut
) != 0)
130 evt
= sm_seteventm(timeout
, closealrm
, 0);
132 if ((*fp
->f_close
)(fp
) < 0)
135 /* We're back. So undo our timeout and handler */
138 if (fp
->f_flags
& SMMBF
)
140 sm_free((char *)fp
->f_bf
.smb_base
);
141 fp
->f_bf
.smb_base
= NULL
;
145 fp
->f_flags
= 0; /* clear flags */
146 fp
->sm_magic
= NULL
; /* Release this SM_FILE_T for reuse. */
147 fp
->f_r
= fp
->f_w
= 0; /* Mess up if reaccessed. */