diff options
Diffstat (limited to 'sendmail/libsm/fclose.c')
-rw-r--r-- | sendmail/libsm/fclose.c | 149 |
1 files changed, 149 insertions, 0 deletions
diff --git a/sendmail/libsm/fclose.c b/sendmail/libsm/fclose.c new file mode 100644 index 0000000..82a7de4 --- /dev/null +++ b/sendmail/libsm/fclose.c @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2000-2002, 2004 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + */ + +#include <sm/gen.h> +SM_RCSID("@(#)$Id: fclose.c,v 1.44 2005/06/14 23:07:20 ca Exp $") +#include <errno.h> +#include <stdlib.h> +#include <sm/time.h> +#include <setjmp.h> +#include <sm/io.h> +#include <sm/assert.h> +#include <sm/heap.h> +#include <sm/signal.h> +#include <sm/conf.h> +#include <sm/clock.h> +#include "local.h" + +static void closealrm __P((int)); +static jmp_buf CloseTimeOut; + +/* +** CLOSEALRM -- handler when timeout activated for sm_io_close() +** +** Returns flow of control to where setjmp(CloseTimeOut) was set. +** +** Parameters: +** sig -- unused +** +** Returns: +** does not return +** +** Side Effects: +** returns flow of control to setjmp(CloseTimeOut). +** +** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD +** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE +** DOING. +*/ + +/* ARGSUSED0 */ +static void +closealrm(sig) + int sig; +{ + longjmp(CloseTimeOut, 1); +} + +/* +** SM_IO_CLOSE -- close a file handle/pointer +** +** Parameters: +** fp -- file pointer to be closed +** timeout -- maximum time allowed to perform the close (millisecs) +** +** Returns: +** 0 on success +** -1 on failure and sets errno +** +** Side Effects: +** file pointer 'fp' will no longer be valid. +*/ + +int +sm_io_close(fp, timeout) + register SM_FILE_T *fp; + int SM_NONVOLATILE timeout; +{ + register int SM_NONVOLATILE r; + SM_EVENT *evt = NULL; + + if (fp == NULL) + { + errno = EBADF; + return SM_IO_EOF; + } + + SM_REQUIRE_ISA(fp, SmFileMagic); + + /* XXX this won't be reached if above macro is active */ + if (fp->sm_magic == NULL) + { + /* not open! */ + errno = EBADF; + return SM_IO_EOF; + } + if (fp->f_close == NULL) + { + /* no close function! */ + errno = ENODEV; + return SM_IO_EOF; + } + if (fp->f_dup_cnt > 0) + { + /* decrement file pointer open count */ + fp->f_dup_cnt--; + return 0; + } + + /* Okay, this is where we set the timeout. */ + if (timeout == SM_TIME_DEFAULT) + timeout = fp->f_timeout; + if (timeout == SM_TIME_IMMEDIATE) + { + errno = EAGAIN; + return -1; + } + + /* No more duplicates of file pointer. Flush buffer and close */ + r = fp->f_flags & SMWR ? sm_flush(fp, (int *) &timeout) : 0; + + /* sm_flush() has updated to.it_value for the time it's used */ + if (timeout != SM_TIME_FOREVER) + { + if (setjmp(CloseTimeOut) != 0) + { + errno = EAGAIN; + return SM_IO_EOF; + } + evt = sm_seteventm(timeout, closealrm, 0); + } + if ((*fp->f_close)(fp) < 0) + r = SM_IO_EOF; + + /* We're back. So undo our timeout and handler */ + if (evt != NULL) + sm_clrevent(evt); + if (fp->f_flags & SMMBF) + { + sm_free((char *)fp->f_bf.smb_base); + fp->f_bf.smb_base = NULL; + } + if (HASUB(fp)) + FREEUB(fp); + fp->f_flags = 0; /* clear flags */ + fp->sm_magic = NULL; /* Release this SM_FILE_T for reuse. */ + fp->f_r = fp->f_w = 0; /* Mess up if reaccessed. */ + return r; +} |