140266059SGregory Neil Shapiro /* 2b6bacd31SGregory Neil Shapiro * Copyright (c) 2000-2002, 2004 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> 164e4196cbSGregory Neil Shapiro SM_RCSID("@(#)$Id: fclose.c,v 1.44 2005/06/14 23:07:20 ca Exp $") 1740266059SGregory Neil Shapiro #include <errno.h> 1840266059SGregory Neil Shapiro #include <stdlib.h> 194e4196cbSGregory Neil Shapiro #include <sm/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 29b6bacd31SGregory Neil Shapiro static void closealrm __P((int)); 3040266059SGregory Neil Shapiro static jmp_buf CloseTimeOut; 3140266059SGregory Neil Shapiro 3240266059SGregory Neil Shapiro /* 3340266059SGregory Neil Shapiro ** CLOSEALRM -- handler when timeout activated for sm_io_close() 3440266059SGregory Neil Shapiro ** 3540266059SGregory Neil Shapiro ** Returns flow of control to where setjmp(CloseTimeOut) was set. 3640266059SGregory Neil Shapiro ** 3740266059SGregory Neil Shapiro ** Parameters: 3840266059SGregory Neil Shapiro ** sig -- unused 3940266059SGregory Neil Shapiro ** 4040266059SGregory Neil Shapiro ** Returns: 4140266059SGregory Neil Shapiro ** does not return 4240266059SGregory Neil Shapiro ** 4340266059SGregory Neil Shapiro ** Side Effects: 4440266059SGregory Neil Shapiro ** returns flow of control to setjmp(CloseTimeOut). 4540266059SGregory Neil Shapiro ** 4640266059SGregory Neil Shapiro ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD 4740266059SGregory Neil Shapiro ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE 4840266059SGregory Neil Shapiro ** DOING. 4940266059SGregory Neil Shapiro */ 5040266059SGregory Neil Shapiro 5140266059SGregory Neil Shapiro /* ARGSUSED0 */ 5240266059SGregory Neil Shapiro static void 5340266059SGregory Neil Shapiro closealrm(sig) 5440266059SGregory Neil Shapiro int sig; 5540266059SGregory Neil Shapiro { 5640266059SGregory Neil Shapiro longjmp(CloseTimeOut, 1); 5740266059SGregory Neil Shapiro } 5840266059SGregory Neil Shapiro 5940266059SGregory Neil Shapiro /* 6040266059SGregory Neil Shapiro ** SM_IO_CLOSE -- close a file handle/pointer 6140266059SGregory Neil Shapiro ** 6240266059SGregory Neil Shapiro ** Parameters: 6340266059SGregory Neil Shapiro ** fp -- file pointer to be closed 6440266059SGregory Neil Shapiro ** timeout -- maximum time allowed to perform the close (millisecs) 6540266059SGregory Neil Shapiro ** 6640266059SGregory Neil Shapiro ** Returns: 6740266059SGregory Neil Shapiro ** 0 on success 6840266059SGregory Neil Shapiro ** -1 on failure and sets errno 6940266059SGregory Neil Shapiro ** 7040266059SGregory Neil Shapiro ** Side Effects: 7140266059SGregory Neil Shapiro ** file pointer 'fp' will no longer be valid. 7240266059SGregory Neil Shapiro */ 7340266059SGregory Neil Shapiro 7440266059SGregory Neil Shapiro int 7540266059SGregory Neil Shapiro sm_io_close(fp, timeout) 7640266059SGregory Neil Shapiro register SM_FILE_T *fp; 7740266059SGregory Neil Shapiro int SM_NONVOLATILE timeout; 7840266059SGregory Neil Shapiro { 7940266059SGregory Neil Shapiro register int SM_NONVOLATILE r; 8040266059SGregory Neil Shapiro SM_EVENT *evt = NULL; 8140266059SGregory Neil Shapiro 8240266059SGregory Neil Shapiro if (fp == NULL) 8340266059SGregory Neil Shapiro { 8440266059SGregory Neil Shapiro errno = EBADF; 8540266059SGregory Neil Shapiro return SM_IO_EOF; 8640266059SGregory Neil Shapiro } 8740266059SGregory Neil Shapiro 8840266059SGregory Neil Shapiro SM_REQUIRE_ISA(fp, SmFileMagic); 8940266059SGregory Neil Shapiro 90605302a5SGregory Neil Shapiro /* XXX this won't be reached if above macro is active */ 9140266059SGregory Neil Shapiro if (fp->sm_magic == NULL) 9240266059SGregory Neil Shapiro { 9340266059SGregory Neil Shapiro /* not open! */ 9440266059SGregory Neil Shapiro errno = EBADF; 9540266059SGregory Neil Shapiro return SM_IO_EOF; 9640266059SGregory Neil Shapiro } 9740266059SGregory Neil Shapiro if (fp->f_close == NULL) 9840266059SGregory Neil Shapiro { 9940266059SGregory Neil Shapiro /* no close function! */ 10040266059SGregory Neil Shapiro errno = ENODEV; 10140266059SGregory Neil Shapiro return SM_IO_EOF; 10240266059SGregory Neil Shapiro } 10340266059SGregory Neil Shapiro if (fp->f_dup_cnt > 0) 10440266059SGregory Neil Shapiro { 10540266059SGregory Neil Shapiro /* decrement file pointer open count */ 10640266059SGregory Neil Shapiro fp->f_dup_cnt--; 10740266059SGregory Neil Shapiro return 0; 10840266059SGregory Neil Shapiro } 10940266059SGregory Neil Shapiro 11040266059SGregory Neil Shapiro /* Okay, this is where we set the timeout. */ 11140266059SGregory Neil Shapiro if (timeout == SM_TIME_DEFAULT) 11240266059SGregory Neil Shapiro timeout = fp->f_timeout; 11340266059SGregory Neil Shapiro if (timeout == SM_TIME_IMMEDIATE) 11440266059SGregory Neil Shapiro { 11540266059SGregory Neil Shapiro errno = EAGAIN; 11640266059SGregory Neil Shapiro return -1; 11740266059SGregory Neil Shapiro } 11840266059SGregory Neil Shapiro 11940266059SGregory Neil Shapiro /* No more duplicates of file pointer. Flush buffer and close */ 12040266059SGregory Neil Shapiro r = fp->f_flags & SMWR ? sm_flush(fp, (int *) &timeout) : 0; 12140266059SGregory Neil Shapiro 12240266059SGregory Neil Shapiro /* sm_flush() has updated to.it_value for the time it's used */ 12340266059SGregory Neil Shapiro if (timeout != SM_TIME_FOREVER) 12440266059SGregory Neil Shapiro { 12540266059SGregory Neil Shapiro if (setjmp(CloseTimeOut) != 0) 12640266059SGregory Neil Shapiro { 12740266059SGregory Neil Shapiro errno = EAGAIN; 12840266059SGregory Neil Shapiro return SM_IO_EOF; 12940266059SGregory Neil Shapiro } 13040266059SGregory Neil Shapiro evt = sm_seteventm(timeout, closealrm, 0); 13140266059SGregory Neil Shapiro } 13240266059SGregory Neil Shapiro if ((*fp->f_close)(fp) < 0) 13340266059SGregory Neil Shapiro r = SM_IO_EOF; 13440266059SGregory Neil Shapiro 13540266059SGregory Neil Shapiro /* We're back. So undo our timeout and handler */ 13640266059SGregory Neil Shapiro if (evt != NULL) 13740266059SGregory Neil Shapiro sm_clrevent(evt); 13840266059SGregory Neil Shapiro if (fp->f_flags & SMMBF) 13940266059SGregory Neil Shapiro { 14040266059SGregory Neil Shapiro sm_free((char *)fp->f_bf.smb_base); 14140266059SGregory Neil Shapiro fp->f_bf.smb_base = NULL; 14240266059SGregory Neil Shapiro } 14340266059SGregory Neil Shapiro if (HASUB(fp)) 14440266059SGregory Neil Shapiro FREEUB(fp); 14540266059SGregory Neil Shapiro fp->f_flags = 0; /* clear flags */ 14640266059SGregory Neil Shapiro fp->sm_magic = NULL; /* Release this SM_FILE_T for reuse. */ 14740266059SGregory Neil Shapiro fp->f_r = fp->f_w = 0; /* Mess up if reaccessed. */ 14840266059SGregory Neil Shapiro return r; 14940266059SGregory Neil Shapiro } 150