diff options
Diffstat (limited to 'sendmail/libsm/fpos.c')
-rw-r--r-- | sendmail/libsm/fpos.c | 153 |
1 files changed, 153 insertions, 0 deletions
diff --git a/sendmail/libsm/fpos.c b/sendmail/libsm/fpos.c new file mode 100644 index 0000000..4fe22bf --- /dev/null +++ b/sendmail/libsm/fpos.c @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2000-2001, 2004 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + */ + +#include <sm/gen.h> +SM_RCSID("@(#)$Id: fpos.c,v 1.39 2005/06/14 23:07:20 ca Exp $") +#include <errno.h> +#include <setjmp.h> +#include <sm/time.h> +#include <sm/heap.h> +#include <sm/signal.h> +#include <sm/clock.h> +#include <sm/io.h> +#include <sm/assert.h> +#include "local.h" + +static void tellalrm __P((int)); +static jmp_buf TellTimeOut; + +/* +** TELLALRM -- handler when timeout activated for sm_io_tell() +** +** Returns flow of control to where setjmp(TellTimeOut) was set. +** +** Parameters: +** sig -- unused +** +** Returns: +** does not return +** +** Side Effects: +** returns flow of control to setjmp(TellTimeOut). +** +** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD +** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE +** DOING. +*/ + +/* ARGSUSED0 */ +static void +tellalrm(sig) + int sig; +{ + longjmp(TellTimeOut, 1); +} + +/* +** SM_IO_TELL -- position the file pointer +** +** Paramters: +** fp -- the file pointer to get repositioned +** timeout -- time to complete the tell (milliseconds) +** +** Returns: +** Success -- the repositioned location. +** Failure -- -1 (minus 1) and sets errno +*/ + +long +sm_io_tell(fp, timeout) + register SM_FILE_T *fp; + int SM_NONVOLATILE timeout; +{ + register off_t pos; + SM_EVENT *evt = NULL; + + SM_REQUIRE_ISA(fp, SmFileMagic); + if (fp->f_seek == NULL) + { + errno = ESPIPE; /* historic practice */ + return -1L; + } + + if (timeout == SM_TIME_DEFAULT) + timeout = fp->f_timeout; + if (timeout == SM_TIME_IMMEDIATE) + { + /* + ** Filling the buffer will take time and we are wanted to + ** return immediately. So... + */ + + errno = EAGAIN; + return -1L; + } + + /* + ** Find offset of underlying I/O object, then adjust byte position + ** may adjust seek offset on append stream + */ + + (void) sm_flush(fp, (int *) &timeout); + + /* This is where we start the timeout */ + if (timeout != SM_TIME_FOREVER) + { + if (setjmp(TellTimeOut) != 0) + { + errno = EAGAIN; + return -1L; + } + + evt = sm_seteventm(timeout, tellalrm, 0); + } + + if (fp->f_flags & SMOFF) + pos = fp->f_lseekoff; + else + { + /* XXX only set the timeout here? */ + pos = (*fp->f_seek)(fp, (off_t) 0, SM_IO_SEEK_CUR); + if (pos == -1L) + goto clean; + } + if (fp->f_flags & SMRD) + { + /* + ** Reading. Any unread characters (including + ** those from ungetc) cause the position to be + ** smaller than that in the underlying object. + */ + + pos -= fp->f_r; + if (HASUB(fp)) + pos -= fp->f_ur; + } + else if (fp->f_flags & SMWR && fp->f_p != NULL) + { + /* + ** Writing. Any buffered characters cause the + ** position to be greater than that in the + ** underlying object. + */ + + pos += fp->f_p - fp->f_bf.smb_base; + } + +clean: + /* We're back. So undo our timeout and handler */ + if (evt != NULL) + sm_clrevent(evt); + return pos; +} |