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