More minor IPI work.
[dragonfly/vkernel-mp.git] / contrib / sendmail-8.14 / libsm / fclose.c
blob82a7de4689e848cbd99784d6fb28a1478ae8aab5
1 /*
2 * Copyright (c) 2000-2002, 2004 Sendmail, Inc. and its suppliers.
3 * All rights reserved.
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
8 * Chris Torek.
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 #include <sm/gen.h>
16 SM_RCSID("@(#)$Id: fclose.c,v 1.44 2005/06/14 23:07:20 ca Exp $")
17 #include <errno.h>
18 #include <stdlib.h>
19 #include <sm/time.h>
20 #include <setjmp.h>
21 #include <sm/io.h>
22 #include <sm/assert.h>
23 #include <sm/heap.h>
24 #include <sm/signal.h>
25 #include <sm/conf.h>
26 #include <sm/clock.h>
27 #include "local.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.
37 ** Parameters:
38 ** sig -- unused
40 ** Returns:
41 ** does not return
43 ** Side Effects:
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
48 ** DOING.
51 /* ARGSUSED0 */
52 static void
53 closealrm(sig)
54 int sig;
56 longjmp(CloseTimeOut, 1);
60 ** SM_IO_CLOSE -- close a file handle/pointer
62 ** Parameters:
63 ** fp -- file pointer to be closed
64 ** timeout -- maximum time allowed to perform the close (millisecs)
66 ** Returns:
67 ** 0 on success
68 ** -1 on failure and sets errno
70 ** Side Effects:
71 ** file pointer 'fp' will no longer be valid.
74 int
75 sm_io_close(fp, timeout)
76 register SM_FILE_T *fp;
77 int SM_NONVOLATILE timeout;
79 register int SM_NONVOLATILE r;
80 SM_EVENT *evt = NULL;
82 if (fp == NULL)
84 errno = EBADF;
85 return SM_IO_EOF;
88 SM_REQUIRE_ISA(fp, SmFileMagic);
90 /* XXX this won't be reached if above macro is active */
91 if (fp->sm_magic == NULL)
93 /* not open! */
94 errno = EBADF;
95 return SM_IO_EOF;
97 if (fp->f_close == NULL)
99 /* no close function! */
100 errno = ENODEV;
101 return SM_IO_EOF;
103 if (fp->f_dup_cnt > 0)
105 /* decrement file pointer open count */
106 fp->f_dup_cnt--;
107 return 0;
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)
115 errno = EAGAIN;
116 return -1;
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)
127 errno = EAGAIN;
128 return SM_IO_EOF;
130 evt = sm_seteventm(timeout, closealrm, 0);
132 if ((*fp->f_close)(fp) < 0)
133 r = SM_IO_EOF;
135 /* We're back. So undo our timeout and handler */
136 if (evt != NULL)
137 sm_clrevent(evt);
138 if (fp->f_flags & SMMBF)
140 sm_free((char *)fp->f_bf.smb_base);
141 fp->f_bf.smb_base = NULL;
143 if (HASUB(fp))
144 FREEUB(fp);
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. */
148 return r;