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