xref: /freebsd/contrib/sendmail/libsm/fclose.c (revision 605302a5c9939b7eeda0a31f38901d9a8348e8cb)
140266059SGregory Neil Shapiro /*
2605302a5SGregory Neil Shapiro  * Copyright (c) 2000-2002 Sendmail, Inc. and its suppliers.
340266059SGregory Neil Shapiro  *      All rights reserved.
440266059SGregory Neil Shapiro  * Copyright (c) 1990, 1993
540266059SGregory Neil Shapiro  *	The Regents of the University of California.  All rights reserved.
640266059SGregory Neil Shapiro  *
740266059SGregory Neil Shapiro  * This code is derived from software contributed to Berkeley by
840266059SGregory Neil Shapiro  * Chris Torek.
940266059SGregory Neil Shapiro  *
1040266059SGregory Neil Shapiro  * By using this file, you agree to the terms and conditions set
1140266059SGregory Neil Shapiro  * forth in the LICENSE file which can be found at the top level of
1240266059SGregory Neil Shapiro  * the sendmail distribution.
1340266059SGregory Neil Shapiro  */
1440266059SGregory Neil Shapiro 
1540266059SGregory Neil Shapiro #include <sm/gen.h>
16605302a5SGregory Neil Shapiro SM_RCSID("@(#)$Id: fclose.c,v 1.42 2002/02/01 02:28:00 ca Exp $")
1740266059SGregory Neil Shapiro #include <errno.h>
1840266059SGregory Neil Shapiro #include <stdlib.h>
1940266059SGregory Neil Shapiro #include <sys/time.h>
2040266059SGregory Neil Shapiro #include <setjmp.h>
2140266059SGregory Neil Shapiro #include <sm/io.h>
2240266059SGregory Neil Shapiro #include <sm/assert.h>
2340266059SGregory Neil Shapiro #include <sm/heap.h>
2440266059SGregory Neil Shapiro #include <sm/signal.h>
2540266059SGregory Neil Shapiro #include <sm/conf.h>
2640266059SGregory Neil Shapiro #include <sm/clock.h>
2740266059SGregory Neil Shapiro #include "local.h"
2840266059SGregory Neil Shapiro 
2940266059SGregory Neil Shapiro static jmp_buf CloseTimeOut;
3040266059SGregory Neil Shapiro 
3140266059SGregory Neil Shapiro /*
3240266059SGregory Neil Shapiro **  CLOSEALRM -- handler when timeout activated for sm_io_close()
3340266059SGregory Neil Shapiro **
3440266059SGregory Neil Shapiro **	Returns flow of control to where setjmp(CloseTimeOut) was set.
3540266059SGregory Neil Shapiro **
3640266059SGregory Neil Shapiro **	Parameters:
3740266059SGregory Neil Shapiro **		sig -- unused
3840266059SGregory Neil Shapiro **
3940266059SGregory Neil Shapiro **	Returns:
4040266059SGregory Neil Shapiro **		does not return
4140266059SGregory Neil Shapiro **
4240266059SGregory Neil Shapiro **	Side Effects:
4340266059SGregory Neil Shapiro **		returns flow of control to setjmp(CloseTimeOut).
4440266059SGregory Neil Shapiro **
4540266059SGregory Neil Shapiro **	NOTE:	THIS CAN BE CALLED FROM A SIGNAL HANDLER.  DO NOT ADD
4640266059SGregory Neil Shapiro **		ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE
4740266059SGregory Neil Shapiro **		DOING.
4840266059SGregory Neil Shapiro */
4940266059SGregory Neil Shapiro 
5040266059SGregory Neil Shapiro /* ARGSUSED0 */
5140266059SGregory Neil Shapiro static void
5240266059SGregory Neil Shapiro closealrm(sig)
5340266059SGregory Neil Shapiro 	int sig;
5440266059SGregory Neil Shapiro {
5540266059SGregory Neil Shapiro 	longjmp(CloseTimeOut, 1);
5640266059SGregory Neil Shapiro }
5740266059SGregory Neil Shapiro 
5840266059SGregory Neil Shapiro /*
5940266059SGregory Neil Shapiro **  SM_IO_CLOSE -- close a file handle/pointer
6040266059SGregory Neil Shapiro **
6140266059SGregory Neil Shapiro **	Parameters:
6240266059SGregory Neil Shapiro **		fp -- file pointer to be closed
6340266059SGregory Neil Shapiro **		timeout -- maximum time allowed to perform the close (millisecs)
6440266059SGregory Neil Shapiro **
6540266059SGregory Neil Shapiro **	Returns:
6640266059SGregory Neil Shapiro **		0 on success
6740266059SGregory Neil Shapiro **		-1 on failure and sets errno
6840266059SGregory Neil Shapiro **
6940266059SGregory Neil Shapiro **	Side Effects:
7040266059SGregory Neil Shapiro **		file pointer 'fp' will no longer be valid.
7140266059SGregory Neil Shapiro */
7240266059SGregory Neil Shapiro 
7340266059SGregory Neil Shapiro int
7440266059SGregory Neil Shapiro sm_io_close(fp, timeout)
7540266059SGregory Neil Shapiro 	register SM_FILE_T *fp;
7640266059SGregory Neil Shapiro 	int SM_NONVOLATILE timeout;
7740266059SGregory Neil Shapiro {
7840266059SGregory Neil Shapiro 	register int SM_NONVOLATILE r;
7940266059SGregory Neil Shapiro 	SM_EVENT *evt = NULL;
8040266059SGregory Neil Shapiro 
8140266059SGregory Neil Shapiro 	if (fp == NULL)
8240266059SGregory Neil Shapiro 	{
8340266059SGregory Neil Shapiro 		errno = EBADF;
8440266059SGregory Neil Shapiro 		return SM_IO_EOF;
8540266059SGregory Neil Shapiro 	}
8640266059SGregory Neil Shapiro 
8740266059SGregory Neil Shapiro 	SM_REQUIRE_ISA(fp, SmFileMagic);
8840266059SGregory Neil Shapiro 
89605302a5SGregory Neil Shapiro 	/* XXX this won't be reached if above macro is active */
9040266059SGregory Neil Shapiro 	if (fp->sm_magic == NULL)
9140266059SGregory Neil Shapiro 	{
9240266059SGregory Neil Shapiro 		/* not open! */
9340266059SGregory Neil Shapiro 		errno = EBADF;
9440266059SGregory Neil Shapiro 		return SM_IO_EOF;
9540266059SGregory Neil Shapiro 	}
9640266059SGregory Neil Shapiro 	if (fp->f_close == NULL)
9740266059SGregory Neil Shapiro 	{
9840266059SGregory Neil Shapiro 		/* no close function! */
9940266059SGregory Neil Shapiro 		errno = ENODEV;
10040266059SGregory Neil Shapiro 		return SM_IO_EOF;
10140266059SGregory Neil Shapiro 	}
10240266059SGregory Neil Shapiro 	if (fp->f_dup_cnt > 0)
10340266059SGregory Neil Shapiro 	{
10440266059SGregory Neil Shapiro 		/* decrement file pointer open count */
10540266059SGregory Neil Shapiro 		fp->f_dup_cnt--;
10640266059SGregory Neil Shapiro 		return 0;
10740266059SGregory Neil Shapiro 	}
10840266059SGregory Neil Shapiro 
10940266059SGregory Neil Shapiro 	/*  Okay, this is where we set the timeout.  */
11040266059SGregory Neil Shapiro 	if (timeout == SM_TIME_DEFAULT)
11140266059SGregory Neil Shapiro 		timeout = fp->f_timeout;
11240266059SGregory Neil Shapiro 	if (timeout == SM_TIME_IMMEDIATE)
11340266059SGregory Neil Shapiro 	{
11440266059SGregory Neil Shapiro 		errno = EAGAIN;
11540266059SGregory Neil Shapiro 		return -1;
11640266059SGregory Neil Shapiro 	}
11740266059SGregory Neil Shapiro 
11840266059SGregory Neil Shapiro 	/* No more duplicates of file pointer. Flush buffer and close */
11940266059SGregory Neil Shapiro 	r = fp->f_flags & SMWR ? sm_flush(fp, (int *) &timeout) : 0;
12040266059SGregory Neil Shapiro 
12140266059SGregory Neil Shapiro 	/* sm_flush() has updated to.it_value for the time it's used */
12240266059SGregory Neil Shapiro 	if (timeout != SM_TIME_FOREVER)
12340266059SGregory Neil Shapiro 	{
12440266059SGregory Neil Shapiro 		if (setjmp(CloseTimeOut) != 0)
12540266059SGregory Neil Shapiro 		{
12640266059SGregory Neil Shapiro 			errno = EAGAIN;
12740266059SGregory Neil Shapiro 			return SM_IO_EOF;
12840266059SGregory Neil Shapiro 		}
12940266059SGregory Neil Shapiro 		evt = sm_seteventm(timeout, closealrm, 0);
13040266059SGregory Neil Shapiro 	}
13140266059SGregory Neil Shapiro 	if ((*fp->f_close)(fp) < 0)
13240266059SGregory Neil Shapiro 		r = SM_IO_EOF;
13340266059SGregory Neil Shapiro 
13440266059SGregory Neil Shapiro 	/*  We're back. So undo our timeout and handler */
13540266059SGregory Neil Shapiro 	if (evt != NULL)
13640266059SGregory Neil Shapiro 		sm_clrevent(evt);
13740266059SGregory Neil Shapiro 	if (fp->f_flags & SMMBF)
13840266059SGregory Neil Shapiro 	{
13940266059SGregory Neil Shapiro 		sm_free((char *)fp->f_bf.smb_base);
14040266059SGregory Neil Shapiro 		fp->f_bf.smb_base = NULL;
14140266059SGregory Neil Shapiro 	}
14240266059SGregory Neil Shapiro 	if (HASUB(fp))
14340266059SGregory Neil Shapiro 		FREEUB(fp);
14440266059SGregory Neil Shapiro 	fp->f_flags = 0;	/* clear flags */
14540266059SGregory Neil Shapiro 	fp->sm_magic = NULL;	/* Release this SM_FILE_T for reuse. */
14640266059SGregory Neil Shapiro 	fp->f_r = fp->f_w = 0;	/* Mess up if reaccessed. */
14740266059SGregory Neil Shapiro 	return r;
14840266059SGregory Neil Shapiro }
149