xref: /titanic_53/usr/src/cmd/sendmail/libsm/fclose.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * Copyright (c) 2000-2002, 2004 Sendmail, Inc. and its suppliers.
3*7c478bd9Sstevel@tonic-gate  *      All rights reserved.
4*7c478bd9Sstevel@tonic-gate  * Copyright (c) 1990, 1993
5*7c478bd9Sstevel@tonic-gate  *	The Regents of the University of California.  All rights reserved.
6*7c478bd9Sstevel@tonic-gate  *
7*7c478bd9Sstevel@tonic-gate  * This code is derived from software contributed to Berkeley by
8*7c478bd9Sstevel@tonic-gate  * Chris Torek.
9*7c478bd9Sstevel@tonic-gate  *
10*7c478bd9Sstevel@tonic-gate  * By using this file, you agree to the terms and conditions set
11*7c478bd9Sstevel@tonic-gate  * forth in the LICENSE file which can be found at the top level of
12*7c478bd9Sstevel@tonic-gate  * the sendmail distribution.
13*7c478bd9Sstevel@tonic-gate  */
14*7c478bd9Sstevel@tonic-gate 
15*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
16*7c478bd9Sstevel@tonic-gate 
17*7c478bd9Sstevel@tonic-gate #include <sm/gen.h>
18*7c478bd9Sstevel@tonic-gate SM_RCSID("@(#)$Id: fclose.c,v 1.43 2004/08/03 20:17:38 ca Exp $")
19*7c478bd9Sstevel@tonic-gate #include <errno.h>
20*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
21*7c478bd9Sstevel@tonic-gate #include <sys/time.h>
22*7c478bd9Sstevel@tonic-gate #include <setjmp.h>
23*7c478bd9Sstevel@tonic-gate #include <sm/io.h>
24*7c478bd9Sstevel@tonic-gate #include <sm/assert.h>
25*7c478bd9Sstevel@tonic-gate #include <sm/heap.h>
26*7c478bd9Sstevel@tonic-gate #include <sm/signal.h>
27*7c478bd9Sstevel@tonic-gate #include <sm/conf.h>
28*7c478bd9Sstevel@tonic-gate #include <sm/clock.h>
29*7c478bd9Sstevel@tonic-gate #include "local.h"
30*7c478bd9Sstevel@tonic-gate 
31*7c478bd9Sstevel@tonic-gate static void	closealrm __P((int));
32*7c478bd9Sstevel@tonic-gate static jmp_buf CloseTimeOut;
33*7c478bd9Sstevel@tonic-gate 
34*7c478bd9Sstevel@tonic-gate /*
35*7c478bd9Sstevel@tonic-gate **  CLOSEALRM -- handler when timeout activated for sm_io_close()
36*7c478bd9Sstevel@tonic-gate **
37*7c478bd9Sstevel@tonic-gate **	Returns flow of control to where setjmp(CloseTimeOut) was set.
38*7c478bd9Sstevel@tonic-gate **
39*7c478bd9Sstevel@tonic-gate **	Parameters:
40*7c478bd9Sstevel@tonic-gate **		sig -- unused
41*7c478bd9Sstevel@tonic-gate **
42*7c478bd9Sstevel@tonic-gate **	Returns:
43*7c478bd9Sstevel@tonic-gate **		does not return
44*7c478bd9Sstevel@tonic-gate **
45*7c478bd9Sstevel@tonic-gate **	Side Effects:
46*7c478bd9Sstevel@tonic-gate **		returns flow of control to setjmp(CloseTimeOut).
47*7c478bd9Sstevel@tonic-gate **
48*7c478bd9Sstevel@tonic-gate **	NOTE:	THIS CAN BE CALLED FROM A SIGNAL HANDLER.  DO NOT ADD
49*7c478bd9Sstevel@tonic-gate **		ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE
50*7c478bd9Sstevel@tonic-gate **		DOING.
51*7c478bd9Sstevel@tonic-gate */
52*7c478bd9Sstevel@tonic-gate 
53*7c478bd9Sstevel@tonic-gate /* ARGSUSED0 */
54*7c478bd9Sstevel@tonic-gate static void
55*7c478bd9Sstevel@tonic-gate closealrm(sig)
56*7c478bd9Sstevel@tonic-gate 	int sig;
57*7c478bd9Sstevel@tonic-gate {
58*7c478bd9Sstevel@tonic-gate 	longjmp(CloseTimeOut, 1);
59*7c478bd9Sstevel@tonic-gate }
60*7c478bd9Sstevel@tonic-gate 
61*7c478bd9Sstevel@tonic-gate /*
62*7c478bd9Sstevel@tonic-gate **  SM_IO_CLOSE -- close a file handle/pointer
63*7c478bd9Sstevel@tonic-gate **
64*7c478bd9Sstevel@tonic-gate **	Parameters:
65*7c478bd9Sstevel@tonic-gate **		fp -- file pointer to be closed
66*7c478bd9Sstevel@tonic-gate **		timeout -- maximum time allowed to perform the close (millisecs)
67*7c478bd9Sstevel@tonic-gate **
68*7c478bd9Sstevel@tonic-gate **	Returns:
69*7c478bd9Sstevel@tonic-gate **		0 on success
70*7c478bd9Sstevel@tonic-gate **		-1 on failure and sets errno
71*7c478bd9Sstevel@tonic-gate **
72*7c478bd9Sstevel@tonic-gate **	Side Effects:
73*7c478bd9Sstevel@tonic-gate **		file pointer 'fp' will no longer be valid.
74*7c478bd9Sstevel@tonic-gate */
75*7c478bd9Sstevel@tonic-gate 
76*7c478bd9Sstevel@tonic-gate int
77*7c478bd9Sstevel@tonic-gate sm_io_close(fp, timeout)
78*7c478bd9Sstevel@tonic-gate 	register SM_FILE_T *fp;
79*7c478bd9Sstevel@tonic-gate 	int SM_NONVOLATILE timeout;
80*7c478bd9Sstevel@tonic-gate {
81*7c478bd9Sstevel@tonic-gate 	register int SM_NONVOLATILE r;
82*7c478bd9Sstevel@tonic-gate 	SM_EVENT *evt = NULL;
83*7c478bd9Sstevel@tonic-gate 
84*7c478bd9Sstevel@tonic-gate 	if (fp == NULL)
85*7c478bd9Sstevel@tonic-gate 	{
86*7c478bd9Sstevel@tonic-gate 		errno = EBADF;
87*7c478bd9Sstevel@tonic-gate 		return SM_IO_EOF;
88*7c478bd9Sstevel@tonic-gate 	}
89*7c478bd9Sstevel@tonic-gate 
90*7c478bd9Sstevel@tonic-gate 	SM_REQUIRE_ISA(fp, SmFileMagic);
91*7c478bd9Sstevel@tonic-gate 
92*7c478bd9Sstevel@tonic-gate 	/* XXX this won't be reached if above macro is active */
93*7c478bd9Sstevel@tonic-gate 	if (fp->sm_magic == NULL)
94*7c478bd9Sstevel@tonic-gate 	{
95*7c478bd9Sstevel@tonic-gate 		/* not open! */
96*7c478bd9Sstevel@tonic-gate 		errno = EBADF;
97*7c478bd9Sstevel@tonic-gate 		return SM_IO_EOF;
98*7c478bd9Sstevel@tonic-gate 	}
99*7c478bd9Sstevel@tonic-gate 	if (fp->f_close == NULL)
100*7c478bd9Sstevel@tonic-gate 	{
101*7c478bd9Sstevel@tonic-gate 		/* no close function! */
102*7c478bd9Sstevel@tonic-gate 		errno = ENODEV;
103*7c478bd9Sstevel@tonic-gate 		return SM_IO_EOF;
104*7c478bd9Sstevel@tonic-gate 	}
105*7c478bd9Sstevel@tonic-gate 	if (fp->f_dup_cnt > 0)
106*7c478bd9Sstevel@tonic-gate 	{
107*7c478bd9Sstevel@tonic-gate 		/* decrement file pointer open count */
108*7c478bd9Sstevel@tonic-gate 		fp->f_dup_cnt--;
109*7c478bd9Sstevel@tonic-gate 		return 0;
110*7c478bd9Sstevel@tonic-gate 	}
111*7c478bd9Sstevel@tonic-gate 
112*7c478bd9Sstevel@tonic-gate 	/*  Okay, this is where we set the timeout.  */
113*7c478bd9Sstevel@tonic-gate 	if (timeout == SM_TIME_DEFAULT)
114*7c478bd9Sstevel@tonic-gate 		timeout = fp->f_timeout;
115*7c478bd9Sstevel@tonic-gate 	if (timeout == SM_TIME_IMMEDIATE)
116*7c478bd9Sstevel@tonic-gate 	{
117*7c478bd9Sstevel@tonic-gate 		errno = EAGAIN;
118*7c478bd9Sstevel@tonic-gate 		return -1;
119*7c478bd9Sstevel@tonic-gate 	}
120*7c478bd9Sstevel@tonic-gate 
121*7c478bd9Sstevel@tonic-gate 	/* No more duplicates of file pointer. Flush buffer and close */
122*7c478bd9Sstevel@tonic-gate 	r = fp->f_flags & SMWR ? sm_flush(fp, (int *) &timeout) : 0;
123*7c478bd9Sstevel@tonic-gate 
124*7c478bd9Sstevel@tonic-gate 	/* sm_flush() has updated to.it_value for the time it's used */
125*7c478bd9Sstevel@tonic-gate 	if (timeout != SM_TIME_FOREVER)
126*7c478bd9Sstevel@tonic-gate 	{
127*7c478bd9Sstevel@tonic-gate 		if (setjmp(CloseTimeOut) != 0)
128*7c478bd9Sstevel@tonic-gate 		{
129*7c478bd9Sstevel@tonic-gate 			errno = EAGAIN;
130*7c478bd9Sstevel@tonic-gate 			return SM_IO_EOF;
131*7c478bd9Sstevel@tonic-gate 		}
132*7c478bd9Sstevel@tonic-gate 		evt = sm_seteventm(timeout, closealrm, 0);
133*7c478bd9Sstevel@tonic-gate 	}
134*7c478bd9Sstevel@tonic-gate 	if ((*fp->f_close)(fp) < 0)
135*7c478bd9Sstevel@tonic-gate 		r = SM_IO_EOF;
136*7c478bd9Sstevel@tonic-gate 
137*7c478bd9Sstevel@tonic-gate 	/*  We're back. So undo our timeout and handler */
138*7c478bd9Sstevel@tonic-gate 	if (evt != NULL)
139*7c478bd9Sstevel@tonic-gate 		sm_clrevent(evt);
140*7c478bd9Sstevel@tonic-gate 	if (fp->f_flags & SMMBF)
141*7c478bd9Sstevel@tonic-gate 	{
142*7c478bd9Sstevel@tonic-gate 		sm_free((char *)fp->f_bf.smb_base);
143*7c478bd9Sstevel@tonic-gate 		fp->f_bf.smb_base = NULL;
144*7c478bd9Sstevel@tonic-gate 	}
145*7c478bd9Sstevel@tonic-gate 	if (HASUB(fp))
146*7c478bd9Sstevel@tonic-gate 		FREEUB(fp);
147*7c478bd9Sstevel@tonic-gate 	fp->f_flags = 0;	/* clear flags */
148*7c478bd9Sstevel@tonic-gate 	fp->sm_magic = NULL;	/* Release this SM_FILE_T for reuse. */
149*7c478bd9Sstevel@tonic-gate 	fp->f_r = fp->f_w = 0;	/* Mess up if reaccessed. */
150*7c478bd9Sstevel@tonic-gate 	return r;
151*7c478bd9Sstevel@tonic-gate }
152