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> 16 SM_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 27 static 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 */ 49 static void 50 tellalrm(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 68 long 69 sm_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 147 clean: 148 /* We're back. So undo our timeout and handler */ 149 if (evt != NULL) 150 sm_clrevent(evt); 151 return pos; 152 } 153