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