xref: /titanic_41/usr/src/cmd/sendmail/libsm/fclose.c (revision 49218d4f8e4d84d1c08aeb267bcf6e451f2056dc)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * Copyright (c) 2000-2002, 2004 Sendmail, Inc. and its suppliers.
37c478bd9Sstevel@tonic-gate  *      All rights reserved.
47c478bd9Sstevel@tonic-gate  * Copyright (c) 1990, 1993
57c478bd9Sstevel@tonic-gate  *	The Regents of the University of California.  All rights reserved.
67c478bd9Sstevel@tonic-gate  *
77c478bd9Sstevel@tonic-gate  * This code is derived from software contributed to Berkeley by
87c478bd9Sstevel@tonic-gate  * Chris Torek.
97c478bd9Sstevel@tonic-gate  *
107c478bd9Sstevel@tonic-gate  * By using this file, you agree to the terms and conditions set
117c478bd9Sstevel@tonic-gate  * forth in the LICENSE file which can be found at the top level of
127c478bd9Sstevel@tonic-gate  * the sendmail distribution.
137c478bd9Sstevel@tonic-gate  */
147c478bd9Sstevel@tonic-gate 
157c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
167c478bd9Sstevel@tonic-gate 
177c478bd9Sstevel@tonic-gate #include <sm/gen.h>
18*49218d4fSjbeck SM_RCSID("@(#)$Id: fclose.c,v 1.44 2005/06/14 23:07:20 ca Exp $")
197c478bd9Sstevel@tonic-gate #include <errno.h>
207c478bd9Sstevel@tonic-gate #include <stdlib.h>
21*49218d4fSjbeck #include <sm/time.h>
227c478bd9Sstevel@tonic-gate #include <setjmp.h>
237c478bd9Sstevel@tonic-gate #include <sm/io.h>
247c478bd9Sstevel@tonic-gate #include <sm/assert.h>
257c478bd9Sstevel@tonic-gate #include <sm/heap.h>
267c478bd9Sstevel@tonic-gate #include <sm/signal.h>
277c478bd9Sstevel@tonic-gate #include <sm/conf.h>
287c478bd9Sstevel@tonic-gate #include <sm/clock.h>
297c478bd9Sstevel@tonic-gate #include "local.h"
307c478bd9Sstevel@tonic-gate 
317c478bd9Sstevel@tonic-gate static void	closealrm __P((int));
327c478bd9Sstevel@tonic-gate static jmp_buf CloseTimeOut;
337c478bd9Sstevel@tonic-gate 
347c478bd9Sstevel@tonic-gate /*
357c478bd9Sstevel@tonic-gate **  CLOSEALRM -- handler when timeout activated for sm_io_close()
367c478bd9Sstevel@tonic-gate **
377c478bd9Sstevel@tonic-gate **	Returns flow of control to where setjmp(CloseTimeOut) was set.
387c478bd9Sstevel@tonic-gate **
397c478bd9Sstevel@tonic-gate **	Parameters:
407c478bd9Sstevel@tonic-gate **		sig -- unused
417c478bd9Sstevel@tonic-gate **
427c478bd9Sstevel@tonic-gate **	Returns:
437c478bd9Sstevel@tonic-gate **		does not return
447c478bd9Sstevel@tonic-gate **
457c478bd9Sstevel@tonic-gate **	Side Effects:
467c478bd9Sstevel@tonic-gate **		returns flow of control to setjmp(CloseTimeOut).
477c478bd9Sstevel@tonic-gate **
487c478bd9Sstevel@tonic-gate **	NOTE:	THIS CAN BE CALLED FROM A SIGNAL HANDLER.  DO NOT ADD
497c478bd9Sstevel@tonic-gate **		ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE
507c478bd9Sstevel@tonic-gate **		DOING.
517c478bd9Sstevel@tonic-gate */
527c478bd9Sstevel@tonic-gate 
537c478bd9Sstevel@tonic-gate /* ARGSUSED0 */
547c478bd9Sstevel@tonic-gate static void
closealrm(sig)557c478bd9Sstevel@tonic-gate closealrm(sig)
567c478bd9Sstevel@tonic-gate 	int sig;
577c478bd9Sstevel@tonic-gate {
587c478bd9Sstevel@tonic-gate 	longjmp(CloseTimeOut, 1);
597c478bd9Sstevel@tonic-gate }
607c478bd9Sstevel@tonic-gate 
617c478bd9Sstevel@tonic-gate /*
627c478bd9Sstevel@tonic-gate **  SM_IO_CLOSE -- close a file handle/pointer
637c478bd9Sstevel@tonic-gate **
647c478bd9Sstevel@tonic-gate **	Parameters:
657c478bd9Sstevel@tonic-gate **		fp -- file pointer to be closed
667c478bd9Sstevel@tonic-gate **		timeout -- maximum time allowed to perform the close (millisecs)
677c478bd9Sstevel@tonic-gate **
687c478bd9Sstevel@tonic-gate **	Returns:
697c478bd9Sstevel@tonic-gate **		0 on success
707c478bd9Sstevel@tonic-gate **		-1 on failure and sets errno
717c478bd9Sstevel@tonic-gate **
727c478bd9Sstevel@tonic-gate **	Side Effects:
737c478bd9Sstevel@tonic-gate **		file pointer 'fp' will no longer be valid.
747c478bd9Sstevel@tonic-gate */
757c478bd9Sstevel@tonic-gate 
767c478bd9Sstevel@tonic-gate int
sm_io_close(fp,timeout)777c478bd9Sstevel@tonic-gate sm_io_close(fp, timeout)
787c478bd9Sstevel@tonic-gate 	register SM_FILE_T *fp;
797c478bd9Sstevel@tonic-gate 	int SM_NONVOLATILE timeout;
807c478bd9Sstevel@tonic-gate {
817c478bd9Sstevel@tonic-gate 	register int SM_NONVOLATILE r;
827c478bd9Sstevel@tonic-gate 	SM_EVENT *evt = NULL;
837c478bd9Sstevel@tonic-gate 
847c478bd9Sstevel@tonic-gate 	if (fp == NULL)
857c478bd9Sstevel@tonic-gate 	{
867c478bd9Sstevel@tonic-gate 		errno = EBADF;
877c478bd9Sstevel@tonic-gate 		return SM_IO_EOF;
887c478bd9Sstevel@tonic-gate 	}
897c478bd9Sstevel@tonic-gate 
907c478bd9Sstevel@tonic-gate 	SM_REQUIRE_ISA(fp, SmFileMagic);
917c478bd9Sstevel@tonic-gate 
927c478bd9Sstevel@tonic-gate 	/* XXX this won't be reached if above macro is active */
937c478bd9Sstevel@tonic-gate 	if (fp->sm_magic == NULL)
947c478bd9Sstevel@tonic-gate 	{
957c478bd9Sstevel@tonic-gate 		/* not open! */
967c478bd9Sstevel@tonic-gate 		errno = EBADF;
977c478bd9Sstevel@tonic-gate 		return SM_IO_EOF;
987c478bd9Sstevel@tonic-gate 	}
997c478bd9Sstevel@tonic-gate 	if (fp->f_close == NULL)
1007c478bd9Sstevel@tonic-gate 	{
1017c478bd9Sstevel@tonic-gate 		/* no close function! */
1027c478bd9Sstevel@tonic-gate 		errno = ENODEV;
1037c478bd9Sstevel@tonic-gate 		return SM_IO_EOF;
1047c478bd9Sstevel@tonic-gate 	}
1057c478bd9Sstevel@tonic-gate 	if (fp->f_dup_cnt > 0)
1067c478bd9Sstevel@tonic-gate 	{
1077c478bd9Sstevel@tonic-gate 		/* decrement file pointer open count */
1087c478bd9Sstevel@tonic-gate 		fp->f_dup_cnt--;
1097c478bd9Sstevel@tonic-gate 		return 0;
1107c478bd9Sstevel@tonic-gate 	}
1117c478bd9Sstevel@tonic-gate 
1127c478bd9Sstevel@tonic-gate 	/*  Okay, this is where we set the timeout.  */
1137c478bd9Sstevel@tonic-gate 	if (timeout == SM_TIME_DEFAULT)
1147c478bd9Sstevel@tonic-gate 		timeout = fp->f_timeout;
1157c478bd9Sstevel@tonic-gate 	if (timeout == SM_TIME_IMMEDIATE)
1167c478bd9Sstevel@tonic-gate 	{
1177c478bd9Sstevel@tonic-gate 		errno = EAGAIN;
1187c478bd9Sstevel@tonic-gate 		return -1;
1197c478bd9Sstevel@tonic-gate 	}
1207c478bd9Sstevel@tonic-gate 
1217c478bd9Sstevel@tonic-gate 	/* No more duplicates of file pointer. Flush buffer and close */
1227c478bd9Sstevel@tonic-gate 	r = fp->f_flags & SMWR ? sm_flush(fp, (int *) &timeout) : 0;
1237c478bd9Sstevel@tonic-gate 
1247c478bd9Sstevel@tonic-gate 	/* sm_flush() has updated to.it_value for the time it's used */
1257c478bd9Sstevel@tonic-gate 	if (timeout != SM_TIME_FOREVER)
1267c478bd9Sstevel@tonic-gate 	{
1277c478bd9Sstevel@tonic-gate 		if (setjmp(CloseTimeOut) != 0)
1287c478bd9Sstevel@tonic-gate 		{
1297c478bd9Sstevel@tonic-gate 			errno = EAGAIN;
1307c478bd9Sstevel@tonic-gate 			return SM_IO_EOF;
1317c478bd9Sstevel@tonic-gate 		}
1327c478bd9Sstevel@tonic-gate 		evt = sm_seteventm(timeout, closealrm, 0);
1337c478bd9Sstevel@tonic-gate 	}
1347c478bd9Sstevel@tonic-gate 	if ((*fp->f_close)(fp) < 0)
1357c478bd9Sstevel@tonic-gate 		r = SM_IO_EOF;
1367c478bd9Sstevel@tonic-gate 
1377c478bd9Sstevel@tonic-gate 	/*  We're back. So undo our timeout and handler */
1387c478bd9Sstevel@tonic-gate 	if (evt != NULL)
1397c478bd9Sstevel@tonic-gate 		sm_clrevent(evt);
1407c478bd9Sstevel@tonic-gate 	if (fp->f_flags & SMMBF)
1417c478bd9Sstevel@tonic-gate 	{
1427c478bd9Sstevel@tonic-gate 		sm_free((char *)fp->f_bf.smb_base);
1437c478bd9Sstevel@tonic-gate 		fp->f_bf.smb_base = NULL;
1447c478bd9Sstevel@tonic-gate 	}
1457c478bd9Sstevel@tonic-gate 	if (HASUB(fp))
1467c478bd9Sstevel@tonic-gate 		FREEUB(fp);
1477c478bd9Sstevel@tonic-gate 	fp->f_flags = 0;	/* clear flags */
1487c478bd9Sstevel@tonic-gate 	fp->sm_magic = NULL;	/* Release this SM_FILE_T for reuse. */
1497c478bd9Sstevel@tonic-gate 	fp->f_r = fp->f_w = 0;	/* Mess up if reaccessed. */
1507c478bd9Sstevel@tonic-gate 	return r;
1517c478bd9Sstevel@tonic-gate }
152