190792Sgshapiro/* 2261363Sgshapiro * Copyright (c) 2000-2001, 2004 Proofpoint, Inc. and its suppliers. 390792Sgshapiro * All rights reserved. 490792Sgshapiro * Copyright (c) 1990, 1993 590792Sgshapiro * The Regents of the University of California. All rights reserved. 690792Sgshapiro * 790792Sgshapiro * This code is derived from software contributed to Berkeley by 890792Sgshapiro * Chris Torek. 990792Sgshapiro * 1090792Sgshapiro * By using this file, you agree to the terms and conditions set 1190792Sgshapiro * forth in the LICENSE file which can be found at the top level of 1290792Sgshapiro * the sendmail distribution. 1390792Sgshapiro */ 1490792Sgshapiro 1590792Sgshapiro#include <sm/gen.h> 16266692SgshapiroSM_RCSID("@(#)$Id: fpos.c,v 1.40 2013-11-22 20:51:42 ca Exp $") 1790792Sgshapiro#include <errno.h> 1890792Sgshapiro#include <setjmp.h> 19157001Sgshapiro#include <sm/time.h> 2090792Sgshapiro#include <sm/heap.h> 2190792Sgshapiro#include <sm/signal.h> 2290792Sgshapiro#include <sm/clock.h> 2390792Sgshapiro#include <sm/io.h> 2490792Sgshapiro#include <sm/assert.h> 2590792Sgshapiro#include "local.h" 2690792Sgshapiro 27141858Sgshapirostatic void tellalrm __P((int)); 2890792Sgshapirostatic jmp_buf TellTimeOut; 2990792Sgshapiro 3090792Sgshapiro/* 3190792Sgshapiro** TELLALRM -- handler when timeout activated for sm_io_tell() 3290792Sgshapiro** 3390792Sgshapiro** Returns flow of control to where setjmp(TellTimeOut) was set. 3490792Sgshapiro** 3590792Sgshapiro** Parameters: 3690792Sgshapiro** sig -- unused 3790792Sgshapiro** 3890792Sgshapiro** Returns: 3990792Sgshapiro** does not return 4090792Sgshapiro** 4190792Sgshapiro** Side Effects: 4290792Sgshapiro** returns flow of control to setjmp(TellTimeOut). 4390792Sgshapiro** 4490792Sgshapiro** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD 4590792Sgshapiro** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE 4690792Sgshapiro** DOING. 4790792Sgshapiro*/ 4890792Sgshapiro 4990792Sgshapiro/* ARGSUSED0 */ 5090792Sgshapirostatic void 5190792Sgshapirotellalrm(sig) 5290792Sgshapiro int sig; 5390792Sgshapiro{ 5490792Sgshapiro longjmp(TellTimeOut, 1); 5590792Sgshapiro} 5690792Sgshapiro 5790792Sgshapiro/* 5890792Sgshapiro** SM_IO_TELL -- position the file pointer 5990792Sgshapiro** 6090792Sgshapiro** Paramters: 6190792Sgshapiro** fp -- the file pointer to get repositioned 6290792Sgshapiro** timeout -- time to complete the tell (milliseconds) 6390792Sgshapiro** 6490792Sgshapiro** Returns: 6590792Sgshapiro** Success -- the repositioned location. 6690792Sgshapiro** Failure -- -1 (minus 1) and sets errno 6790792Sgshapiro*/ 6890792Sgshapiro 6990792Sgshapirolong 7090792Sgshapirosm_io_tell(fp, timeout) 7190792Sgshapiro register SM_FILE_T *fp; 7290792Sgshapiro int SM_NONVOLATILE timeout; 7390792Sgshapiro{ 7490792Sgshapiro register off_t pos; 7590792Sgshapiro SM_EVENT *evt = NULL; 7690792Sgshapiro 7790792Sgshapiro SM_REQUIRE_ISA(fp, SmFileMagic); 7890792Sgshapiro if (fp->f_seek == NULL) 7990792Sgshapiro { 8090792Sgshapiro errno = ESPIPE; /* historic practice */ 8190792Sgshapiro return -1L; 8290792Sgshapiro } 8390792Sgshapiro 8490792Sgshapiro if (timeout == SM_TIME_DEFAULT) 8590792Sgshapiro timeout = fp->f_timeout; 8690792Sgshapiro if (timeout == SM_TIME_IMMEDIATE) 8790792Sgshapiro { 8890792Sgshapiro /* 8990792Sgshapiro ** Filling the buffer will take time and we are wanted to 9090792Sgshapiro ** return immediately. So... 9190792Sgshapiro */ 9290792Sgshapiro 9390792Sgshapiro errno = EAGAIN; 9490792Sgshapiro return -1L; 9590792Sgshapiro } 9690792Sgshapiro 9790792Sgshapiro /* 9890792Sgshapiro ** Find offset of underlying I/O object, then adjust byte position 9990792Sgshapiro ** may adjust seek offset on append stream 10090792Sgshapiro */ 10190792Sgshapiro 10290792Sgshapiro (void) sm_flush(fp, (int *) &timeout); 10390792Sgshapiro 10490792Sgshapiro /* This is where we start the timeout */ 10590792Sgshapiro if (timeout != SM_TIME_FOREVER) 10690792Sgshapiro { 10790792Sgshapiro if (setjmp(TellTimeOut) != 0) 10890792Sgshapiro { 10990792Sgshapiro errno = EAGAIN; 11090792Sgshapiro return -1L; 11190792Sgshapiro } 11290792Sgshapiro 11390792Sgshapiro evt = sm_seteventm(timeout, tellalrm, 0); 11490792Sgshapiro } 11590792Sgshapiro 11690792Sgshapiro if (fp->f_flags & SMOFF) 11790792Sgshapiro pos = fp->f_lseekoff; 11890792Sgshapiro else 11990792Sgshapiro { 12090792Sgshapiro /* XXX only set the timeout here? */ 12190792Sgshapiro pos = (*fp->f_seek)(fp, (off_t) 0, SM_IO_SEEK_CUR); 12290792Sgshapiro if (pos == -1L) 12390792Sgshapiro goto clean; 12490792Sgshapiro } 12590792Sgshapiro if (fp->f_flags & SMRD) 12690792Sgshapiro { 12790792Sgshapiro /* 12890792Sgshapiro ** Reading. Any unread characters (including 12990792Sgshapiro ** those from ungetc) cause the position to be 13090792Sgshapiro ** smaller than that in the underlying object. 13190792Sgshapiro */ 13290792Sgshapiro 13390792Sgshapiro pos -= fp->f_r; 13490792Sgshapiro if (HASUB(fp)) 13590792Sgshapiro pos -= fp->f_ur; 13690792Sgshapiro } 13790792Sgshapiro else if (fp->f_flags & SMWR && fp->f_p != NULL) 13890792Sgshapiro { 13990792Sgshapiro /* 14090792Sgshapiro ** Writing. Any buffered characters cause the 14190792Sgshapiro ** position to be greater than that in the 14290792Sgshapiro ** underlying object. 14390792Sgshapiro */ 14490792Sgshapiro 14590792Sgshapiro pos += fp->f_p - fp->f_bf.smb_base; 14690792Sgshapiro } 14790792Sgshapiro 14890792Sgshapiroclean: 14990792Sgshapiro /* We're back. So undo our timeout and handler */ 15090792Sgshapiro if (evt != NULL) 15190792Sgshapiro sm_clrevent(evt); 15290792Sgshapiro return pos; 15390792Sgshapiro} 154