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: fclose.c,v 1.44 2005/06/14 23:07:20 ca Exp $")
24 #include <sm/assert.h>
26 #include <sm/signal.h>
31 static void closealrm
__P((int));
32 static jmp_buf CloseTimeOut
;
35 ** CLOSEALRM -- handler when timeout activated for sm_io_close()
37 ** Returns flow of control to where setjmp(CloseTimeOut) was set.
46 ** returns flow of control to setjmp(CloseTimeOut).
48 ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD
49 ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE
58 longjmp(CloseTimeOut
, 1);
62 ** SM_IO_CLOSE -- close a file handle/pointer
65 ** fp -- file pointer to be closed
66 ** timeout -- maximum time allowed to perform the close (millisecs)
70 ** -1 on failure and sets errno
73 ** file pointer 'fp' will no longer be valid.
77 sm_io_close(fp
, timeout
)
78 register SM_FILE_T
*fp
;
79 int SM_NONVOLATILE timeout
;
81 register int SM_NONVOLATILE r
;
90 SM_REQUIRE_ISA(fp
, SmFileMagic
);
92 /* XXX this won't be reached if above macro is active */
93 if (fp
->sm_magic
== NULL
)
99 if (fp
->f_close
== NULL
)
101 /* no close function! */
105 if (fp
->f_dup_cnt
> 0)
107 /* decrement file pointer open count */
112 /* Okay, this is where we set the timeout. */
113 if (timeout
== SM_TIME_DEFAULT
)
114 timeout
= fp
->f_timeout
;
115 if (timeout
== SM_TIME_IMMEDIATE
)
121 /* No more duplicates of file pointer. Flush buffer and close */
122 r
= fp
->f_flags
& SMWR
? sm_flush(fp
, (int *) &timeout
) : 0;
124 /* sm_flush() has updated to.it_value for the time it's used */
125 if (timeout
!= SM_TIME_FOREVER
)
127 if (setjmp(CloseTimeOut
) != 0)
132 evt
= sm_seteventm(timeout
, closealrm
, 0);
134 if ((*fp
->f_close
)(fp
) < 0)
137 /* We're back. So undo our timeout and handler */
140 if (fp
->f_flags
& SMMBF
)
142 sm_free((char *)fp
->f_bf
.smb_base
);
143 fp
->f_bf
.smb_base
= NULL
;
147 fp
->f_flags
= 0; /* clear flags */
148 fp
->sm_magic
= NULL
; /* Release this SM_FILE_T for reuse. */
149 fp
->f_r
= fp
->f_w
= 0; /* Mess up if reaccessed. */