1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * Copyright (c) 2000-2001 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: fflush.c,v 1.41 2001/05/15 16:55:27 ca Exp $") 19*7c478bd9Sstevel@tonic-gate #include <unistd.h> 20*7c478bd9Sstevel@tonic-gate #include <errno.h> 21*7c478bd9Sstevel@tonic-gate #include <sys/time.h> 22*7c478bd9Sstevel@tonic-gate #include <signal.h> 23*7c478bd9Sstevel@tonic-gate #include <fcntl.h> 24*7c478bd9Sstevel@tonic-gate #include <string.h> 25*7c478bd9Sstevel@tonic-gate #include <sm/io.h> 26*7c478bd9Sstevel@tonic-gate #include <sm/assert.h> 27*7c478bd9Sstevel@tonic-gate #include <sm/setjmp.h> 28*7c478bd9Sstevel@tonic-gate #include "local.h" 29*7c478bd9Sstevel@tonic-gate #include <sm/conf.h> 30*7c478bd9Sstevel@tonic-gate 31*7c478bd9Sstevel@tonic-gate /* 32*7c478bd9Sstevel@tonic-gate ** SM_IO_FLUSH -- flush the buffer for a 'fp' to the "file" 33*7c478bd9Sstevel@tonic-gate ** 34*7c478bd9Sstevel@tonic-gate ** Flush a single file. We don't allow this function to flush 35*7c478bd9Sstevel@tonic-gate ** all open files when fp==NULL any longer. 36*7c478bd9Sstevel@tonic-gate ** 37*7c478bd9Sstevel@tonic-gate ** Parameters: 38*7c478bd9Sstevel@tonic-gate ** fp -- the file pointer buffer to flush 39*7c478bd9Sstevel@tonic-gate ** timeout -- time to complete the flush 40*7c478bd9Sstevel@tonic-gate ** 41*7c478bd9Sstevel@tonic-gate ** Results: 42*7c478bd9Sstevel@tonic-gate ** Failure: SM_IO_EOF and sets errno 43*7c478bd9Sstevel@tonic-gate ** Success: 0 (zero) 44*7c478bd9Sstevel@tonic-gate */ 45*7c478bd9Sstevel@tonic-gate 46*7c478bd9Sstevel@tonic-gate int 47*7c478bd9Sstevel@tonic-gate sm_io_flush(fp, timeout) 48*7c478bd9Sstevel@tonic-gate register SM_FILE_T *fp; 49*7c478bd9Sstevel@tonic-gate int SM_NONVOLATILE timeout; 50*7c478bd9Sstevel@tonic-gate { 51*7c478bd9Sstevel@tonic-gate int fd; 52*7c478bd9Sstevel@tonic-gate struct timeval to; 53*7c478bd9Sstevel@tonic-gate 54*7c478bd9Sstevel@tonic-gate SM_REQUIRE_ISA(fp, SmFileMagic); 55*7c478bd9Sstevel@tonic-gate 56*7c478bd9Sstevel@tonic-gate if ((fp->f_flags & (SMWR | SMRW)) == 0) 57*7c478bd9Sstevel@tonic-gate { 58*7c478bd9Sstevel@tonic-gate /* 59*7c478bd9Sstevel@tonic-gate ** The file is not opened for writing, so it cannot be flushed 60*7c478bd9Sstevel@tonic-gate ** (writable means SMWR [write] or SMRW [read/write]. 61*7c478bd9Sstevel@tonic-gate */ 62*7c478bd9Sstevel@tonic-gate 63*7c478bd9Sstevel@tonic-gate errno = EBADF; 64*7c478bd9Sstevel@tonic-gate return SM_IO_EOF; 65*7c478bd9Sstevel@tonic-gate } 66*7c478bd9Sstevel@tonic-gate 67*7c478bd9Sstevel@tonic-gate SM_CONVERT_TIME(fp, fd, timeout, &to); 68*7c478bd9Sstevel@tonic-gate 69*7c478bd9Sstevel@tonic-gate /* Now do the flush */ 70*7c478bd9Sstevel@tonic-gate return sm_flush(fp, (int *) &timeout); 71*7c478bd9Sstevel@tonic-gate } 72*7c478bd9Sstevel@tonic-gate 73*7c478bd9Sstevel@tonic-gate /* 74*7c478bd9Sstevel@tonic-gate ** SM_FLUSH -- perform the actual flush 75*7c478bd9Sstevel@tonic-gate ** 76*7c478bd9Sstevel@tonic-gate ** Assumes that 'fp' has been validated before this function called. 77*7c478bd9Sstevel@tonic-gate ** 78*7c478bd9Sstevel@tonic-gate ** Parameters: 79*7c478bd9Sstevel@tonic-gate ** fp -- file pointer to be flushed 80*7c478bd9Sstevel@tonic-gate ** timeout -- max time allowed for flush (milliseconds) 81*7c478bd9Sstevel@tonic-gate ** 82*7c478bd9Sstevel@tonic-gate ** Results: 83*7c478bd9Sstevel@tonic-gate ** Success: 0 (zero) 84*7c478bd9Sstevel@tonic-gate ** Failure: SM_IO_EOF and errno set 85*7c478bd9Sstevel@tonic-gate ** 86*7c478bd9Sstevel@tonic-gate ** Side Effects: 87*7c478bd9Sstevel@tonic-gate ** timeout will get updated with the time remaining (if any) 88*7c478bd9Sstevel@tonic-gate */ 89*7c478bd9Sstevel@tonic-gate 90*7c478bd9Sstevel@tonic-gate int 91*7c478bd9Sstevel@tonic-gate sm_flush(fp, timeout) 92*7c478bd9Sstevel@tonic-gate register SM_FILE_T *fp; 93*7c478bd9Sstevel@tonic-gate int *timeout; 94*7c478bd9Sstevel@tonic-gate { 95*7c478bd9Sstevel@tonic-gate register unsigned char *p; 96*7c478bd9Sstevel@tonic-gate register int n, t; 97*7c478bd9Sstevel@tonic-gate int fd; 98*7c478bd9Sstevel@tonic-gate 99*7c478bd9Sstevel@tonic-gate SM_REQUIRE_ISA(fp, SmFileMagic); 100*7c478bd9Sstevel@tonic-gate 101*7c478bd9Sstevel@tonic-gate t = fp->f_flags; 102*7c478bd9Sstevel@tonic-gate if ((t & SMWR) == 0) 103*7c478bd9Sstevel@tonic-gate return 0; 104*7c478bd9Sstevel@tonic-gate 105*7c478bd9Sstevel@tonic-gate if (t & SMSTR) 106*7c478bd9Sstevel@tonic-gate { 107*7c478bd9Sstevel@tonic-gate *fp->f_p = '\0'; 108*7c478bd9Sstevel@tonic-gate return 0; 109*7c478bd9Sstevel@tonic-gate } 110*7c478bd9Sstevel@tonic-gate 111*7c478bd9Sstevel@tonic-gate if ((p = fp->f_bf.smb_base) == NULL) 112*7c478bd9Sstevel@tonic-gate return 0; 113*7c478bd9Sstevel@tonic-gate 114*7c478bd9Sstevel@tonic-gate n = fp->f_p - p; /* write this much */ 115*7c478bd9Sstevel@tonic-gate 116*7c478bd9Sstevel@tonic-gate if ((fd = sm_io_getinfo(fp, SM_IO_WHAT_FD, NULL)) == -1) 117*7c478bd9Sstevel@tonic-gate { 118*7c478bd9Sstevel@tonic-gate /* can't get an fd, likely internal 'fake' fp */ 119*7c478bd9Sstevel@tonic-gate errno = 0; 120*7c478bd9Sstevel@tonic-gate fd = -1; 121*7c478bd9Sstevel@tonic-gate } 122*7c478bd9Sstevel@tonic-gate 123*7c478bd9Sstevel@tonic-gate /* 124*7c478bd9Sstevel@tonic-gate ** Set these immediately to avoid problems with longjmp and to allow 125*7c478bd9Sstevel@tonic-gate ** exchange buffering (via setvbuf) in user write function. 126*7c478bd9Sstevel@tonic-gate */ 127*7c478bd9Sstevel@tonic-gate 128*7c478bd9Sstevel@tonic-gate fp->f_p = p; 129*7c478bd9Sstevel@tonic-gate fp->f_w = t & (SMLBF|SMNBF) ? 0 : fp->f_bf.smb_size; /* implies SMFBF */ 130*7c478bd9Sstevel@tonic-gate 131*7c478bd9Sstevel@tonic-gate for (; n > 0; n -= t, p += t) 132*7c478bd9Sstevel@tonic-gate { 133*7c478bd9Sstevel@tonic-gate errno = 0; /* needed to ensure EOF correctly found */ 134*7c478bd9Sstevel@tonic-gate 135*7c478bd9Sstevel@tonic-gate /* Call the file type's write function */ 136*7c478bd9Sstevel@tonic-gate t = (*fp->f_write)(fp, (char *)p, n); 137*7c478bd9Sstevel@tonic-gate if (t <= 0) 138*7c478bd9Sstevel@tonic-gate { 139*7c478bd9Sstevel@tonic-gate if (t == 0 && errno == 0) 140*7c478bd9Sstevel@tonic-gate break; /* EOF found */ 141*7c478bd9Sstevel@tonic-gate 142*7c478bd9Sstevel@tonic-gate if (IS_IO_ERROR(fd, t, *timeout)) 143*7c478bd9Sstevel@tonic-gate { 144*7c478bd9Sstevel@tonic-gate fp->f_flags |= SMERR; 145*7c478bd9Sstevel@tonic-gate 146*7c478bd9Sstevel@tonic-gate /* errno set by fp->f_write */ 147*7c478bd9Sstevel@tonic-gate return SM_IO_EOF; 148*7c478bd9Sstevel@tonic-gate } 149*7c478bd9Sstevel@tonic-gate SM_IO_WR_TIMEOUT(fp, fd, *timeout); 150*7c478bd9Sstevel@tonic-gate } 151*7c478bd9Sstevel@tonic-gate } 152*7c478bd9Sstevel@tonic-gate return 0; 153*7c478bd9Sstevel@tonic-gate } 154