source: trunk/third/sendmail/libsm/fclose.c @ 19204

Revision 19204, 3.1 KB checked in by zacheiss, 21 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r19203, which included commits to RCS files with non-trunk default branches.
Line 
1/*
2 * Copyright (c) 2000-2002 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.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Chris Torek.
9 *
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.
13 */
14
15#include <sm/gen.h>
16SM_RCSID("@(#)$Id: fclose.c,v 1.1.1.1 2003-04-08 15:06:55 zacheiss Exp $")
17#include <errno.h>
18#include <stdlib.h>
19#include <sys/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"
28
29static jmp_buf CloseTimeOut;
30
31/*
32**  CLOSEALRM -- handler when timeout activated for sm_io_close()
33**
34**      Returns flow of control to where setjmp(CloseTimeOut) was set.
35**
36**      Parameters:
37**              sig -- unused
38**
39**      Returns:
40**              does not return
41**
42**      Side Effects:
43**              returns flow of control to setjmp(CloseTimeOut).
44**
45**      NOTE:   THIS CAN BE CALLED FROM A SIGNAL HANDLER.  DO NOT ADD
46**              ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE
47**              DOING.
48*/
49
50/* ARGSUSED0 */
51static void
52closealrm(sig)
53        int sig;
54{
55        longjmp(CloseTimeOut, 1);
56}
57
58/*
59**  SM_IO_CLOSE -- close a file handle/pointer
60**
61**      Parameters:
62**              fp -- file pointer to be closed
63**              timeout -- maximum time allowed to perform the close (millisecs)
64**
65**      Returns:
66**              0 on success
67**              -1 on failure and sets errno
68**
69**      Side Effects:
70**              file pointer 'fp' will no longer be valid.
71*/
72
73int
74sm_io_close(fp, timeout)
75        register SM_FILE_T *fp;
76        int SM_NONVOLATILE timeout;
77{
78        register int SM_NONVOLATILE r;
79        SM_EVENT *evt = NULL;
80
81        if (fp == NULL)
82        {
83                errno = EBADF;
84                return SM_IO_EOF;
85        }
86
87        SM_REQUIRE_ISA(fp, SmFileMagic);
88
89        /* XXX this won't be reached if above macro is active */
90        if (fp->sm_magic == NULL)
91        {
92                /* not open! */
93                errno = EBADF;
94                return SM_IO_EOF;
95        }
96        if (fp->f_close == NULL)
97        {
98                /* no close function! */
99                errno = ENODEV;
100                return SM_IO_EOF;
101        }
102        if (fp->f_dup_cnt > 0)
103        {
104                /* decrement file pointer open count */
105                fp->f_dup_cnt--;
106                return 0;
107        }
108
109        /*  Okay, this is where we set the timeout.  */
110        if (timeout == SM_TIME_DEFAULT)
111                timeout = fp->f_timeout;
112        if (timeout == SM_TIME_IMMEDIATE)
113        {
114                errno = EAGAIN;
115                return -1;
116        }
117
118        /* No more duplicates of file pointer. Flush buffer and close */
119        r = fp->f_flags & SMWR ? sm_flush(fp, (int *) &timeout) : 0;
120
121        /* sm_flush() has updated to.it_value for the time it's used */
122        if (timeout != SM_TIME_FOREVER)
123        {
124                if (setjmp(CloseTimeOut) != 0)
125                {
126                        errno = EAGAIN;
127                        return SM_IO_EOF;
128                }
129                evt = sm_seteventm(timeout, closealrm, 0);
130        }
131        if ((*fp->f_close)(fp) < 0)
132                r = SM_IO_EOF;
133
134        /*  We're back. So undo our timeout and handler */
135        if (evt != NULL)
136                sm_clrevent(evt);
137        if (fp->f_flags & SMMBF)
138        {
139                sm_free((char *)fp->f_bf.smb_base);
140                fp->f_bf.smb_base = NULL;
141        }
142        if (HASUB(fp))
143                FREEUB(fp);
144        fp->f_flags = 0;        /* clear flags */
145        fp->sm_magic = NULL;    /* Release this SM_FILE_T for reuse. */
146        fp->f_r = fp->f_w = 0;  /* Mess up if reaccessed. */
147        return r;
148}
Note: See TracBrowser for help on using the repository browser.