fpos.c revision 90792
1/* 2 * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. 3 * All rights reserved. 4 * Copyright (c) 1990, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * Chris Torek. 9 * 10 * By using this file, you agree to the terms and conditions set 11 * forth in the LICENSE file which can be found at the top level of 12 * the sendmail distribution. 13 */ 14 15#include <sm/gen.h> 16SM_RCSID("@(#)$Id: fpos.c,v 1.37 2001/09/11 04:04:48 gshapiro Exp $") 17#include <errno.h> 18#include <setjmp.h> 19#include <sys/time.h> 20#include <sm/heap.h> 21#include <sm/signal.h> 22#include <sm/clock.h> 23#include <sm/io.h> 24#include <sm/assert.h> 25#include "local.h" 26 27static jmp_buf TellTimeOut; 28 29/* 30** TELLALRM -- handler when timeout activated for sm_io_tell() 31** 32** Returns flow of control to where setjmp(TellTimeOut) was set. 33** 34** Parameters: 35** sig -- unused 36** 37** Returns: 38** does not return 39** 40** Side Effects: 41** returns flow of control to setjmp(TellTimeOut). 42** 43** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD 44** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE 45** DOING. 46*/ 47 48/* ARGSUSED0 */ 49static void 50tellalrm(sig) 51 int sig; 52{ 53 longjmp(TellTimeOut, 1); 54} 55 56/* 57** SM_IO_TELL -- position the file pointer 58** 59** Paramters: 60** fp -- the file pointer to get repositioned 61** timeout -- time to complete the tell (milliseconds) 62** 63** Returns: 64** Success -- the repositioned location. 65** Failure -- -1 (minus 1) and sets errno 66*/ 67 68long 69sm_io_tell(fp, timeout) 70 register SM_FILE_T *fp; 71 int SM_NONVOLATILE timeout; 72{ 73 register off_t pos; 74 SM_EVENT *evt = NULL; 75 76 SM_REQUIRE_ISA(fp, SmFileMagic); 77 if (fp->f_seek == NULL) 78 { 79 errno = ESPIPE; /* historic practice */ 80 return -1L; 81 } 82 83 if (timeout == SM_TIME_DEFAULT) 84 timeout = fp->f_timeout; 85 if (timeout == SM_TIME_IMMEDIATE) 86 { 87 /* 88 ** Filling the buffer will take time and we are wanted to 89 ** return immediately. So... 90 */ 91 92 errno = EAGAIN; 93 return -1L; 94 } 95 96 /* 97 ** Find offset of underlying I/O object, then adjust byte position 98 ** may adjust seek offset on append stream 99 */ 100 101 (void) sm_flush(fp, (int *) &timeout); 102 103 /* This is where we start the timeout */ 104 if (timeout != SM_TIME_FOREVER) 105 { 106 if (setjmp(TellTimeOut) != 0) 107 { 108 errno = EAGAIN; 109 return -1L; 110 } 111 112 evt = sm_seteventm(timeout, tellalrm, 0); 113 } 114 115 if (fp->f_flags & SMOFF) 116 pos = fp->f_lseekoff; 117 else 118 { 119 /* XXX only set the timeout here? */ 120 pos = (*fp->f_seek)(fp, (off_t) 0, SM_IO_SEEK_CUR); 121 if (pos == -1L) 122 goto clean; 123 } 124 if (fp->f_flags & SMRD) 125 { 126 /* 127 ** Reading. Any unread characters (including 128 ** those from ungetc) cause the position to be 129 ** smaller than that in the underlying object. 130 */ 131 132 pos -= fp->f_r; 133 if (HASUB(fp)) 134 pos -= fp->f_ur; 135 } 136 else if (fp->f_flags & SMWR && fp->f_p != NULL) 137 { 138 /* 139 ** Writing. Any buffered characters cause the 140 ** position to be greater than that in the 141 ** underlying object. 142 */ 143 144 pos += fp->f_p - fp->f_bf.smb_base; 145 } 146 147clean: 148 /* We're back. So undo our timeout and handler */ 149 if (evt != NULL) 150 sm_clrevent(evt); 151 return pos; 152} 153