xref: /illumos-gate/usr/src/cmd/sendmail/libsm/fpos.c (revision 2a8bcb4e)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * Copyright (c) 2000-2001, 2004 Sendmail, Inc. and its suppliers.
37c478bd9Sstevel@tonic-gate  *      All rights reserved.
47c478bd9Sstevel@tonic-gate  * Copyright (c) 1990, 1993
57c478bd9Sstevel@tonic-gate  *	The Regents of the University of California.  All rights reserved.
67c478bd9Sstevel@tonic-gate  *
77c478bd9Sstevel@tonic-gate  * This code is derived from software contributed to Berkeley by
87c478bd9Sstevel@tonic-gate  * Chris Torek.
97c478bd9Sstevel@tonic-gate  *
107c478bd9Sstevel@tonic-gate  * By using this file, you agree to the terms and conditions set
117c478bd9Sstevel@tonic-gate  * forth in the LICENSE file which can be found at the top level of
127c478bd9Sstevel@tonic-gate  * the sendmail distribution.
137c478bd9Sstevel@tonic-gate  */
147c478bd9Sstevel@tonic-gate 
157c478bd9Sstevel@tonic-gate #include <sm/gen.h>
16*49218d4fSjbeck SM_RCSID("@(#)$Id: fpos.c,v 1.39 2005/06/14 23:07:20 ca Exp $")
177c478bd9Sstevel@tonic-gate #include <errno.h>
187c478bd9Sstevel@tonic-gate #include <setjmp.h>
19*49218d4fSjbeck #include <sm/time.h>
207c478bd9Sstevel@tonic-gate #include <sm/heap.h>
217c478bd9Sstevel@tonic-gate #include <sm/signal.h>
227c478bd9Sstevel@tonic-gate #include <sm/clock.h>
237c478bd9Sstevel@tonic-gate #include <sm/io.h>
247c478bd9Sstevel@tonic-gate #include <sm/assert.h>
257c478bd9Sstevel@tonic-gate #include "local.h"
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate static void	tellalrm __P((int));
287c478bd9Sstevel@tonic-gate static jmp_buf TellTimeOut;
297c478bd9Sstevel@tonic-gate 
307c478bd9Sstevel@tonic-gate /*
317c478bd9Sstevel@tonic-gate **  TELLALRM -- handler when timeout activated for sm_io_tell()
327c478bd9Sstevel@tonic-gate **
337c478bd9Sstevel@tonic-gate **  Returns flow of control to where setjmp(TellTimeOut) was set.
347c478bd9Sstevel@tonic-gate **
357c478bd9Sstevel@tonic-gate **	Parameters:
367c478bd9Sstevel@tonic-gate **		sig -- unused
377c478bd9Sstevel@tonic-gate **
387c478bd9Sstevel@tonic-gate **	Returns:
397c478bd9Sstevel@tonic-gate **		does not return
407c478bd9Sstevel@tonic-gate **
417c478bd9Sstevel@tonic-gate **	Side Effects:
427c478bd9Sstevel@tonic-gate **		returns flow of control to setjmp(TellTimeOut).
437c478bd9Sstevel@tonic-gate **
447c478bd9Sstevel@tonic-gate **	NOTE:	THIS CAN BE CALLED FROM A SIGNAL HANDLER.  DO NOT ADD
457c478bd9Sstevel@tonic-gate **		ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE
467c478bd9Sstevel@tonic-gate **		DOING.
477c478bd9Sstevel@tonic-gate */
487c478bd9Sstevel@tonic-gate 
497c478bd9Sstevel@tonic-gate /* ARGSUSED0 */
507c478bd9Sstevel@tonic-gate static void
tellalrm(sig)517c478bd9Sstevel@tonic-gate tellalrm(sig)
527c478bd9Sstevel@tonic-gate 	int sig;
537c478bd9Sstevel@tonic-gate {
547c478bd9Sstevel@tonic-gate 	longjmp(TellTimeOut, 1);
557c478bd9Sstevel@tonic-gate }
567c478bd9Sstevel@tonic-gate 
577c478bd9Sstevel@tonic-gate /*
587c478bd9Sstevel@tonic-gate **  SM_IO_TELL -- position the file pointer
597c478bd9Sstevel@tonic-gate **
607c478bd9Sstevel@tonic-gate **	Paramters:
617c478bd9Sstevel@tonic-gate **		fp -- the file pointer to get repositioned
627c478bd9Sstevel@tonic-gate **		timeout -- time to complete the tell (milliseconds)
637c478bd9Sstevel@tonic-gate **
647c478bd9Sstevel@tonic-gate **	Returns:
657c478bd9Sstevel@tonic-gate **		Success -- the repositioned location.
667c478bd9Sstevel@tonic-gate **		Failure -- -1 (minus 1) and sets errno
677c478bd9Sstevel@tonic-gate */
687c478bd9Sstevel@tonic-gate 
697c478bd9Sstevel@tonic-gate long
sm_io_tell(fp,timeout)707c478bd9Sstevel@tonic-gate sm_io_tell(fp, timeout)
717c478bd9Sstevel@tonic-gate 	register SM_FILE_T *fp;
727c478bd9Sstevel@tonic-gate 	int SM_NONVOLATILE timeout;
737c478bd9Sstevel@tonic-gate {
747c478bd9Sstevel@tonic-gate 	register off_t pos;
757c478bd9Sstevel@tonic-gate 	SM_EVENT *evt = NULL;
767c478bd9Sstevel@tonic-gate 
777c478bd9Sstevel@tonic-gate 	SM_REQUIRE_ISA(fp, SmFileMagic);
787c478bd9Sstevel@tonic-gate 	if (fp->f_seek == NULL)
797c478bd9Sstevel@tonic-gate 	{
807c478bd9Sstevel@tonic-gate 		errno = ESPIPE;			/* historic practice */
817c478bd9Sstevel@tonic-gate 		return -1L;
827c478bd9Sstevel@tonic-gate 	}
837c478bd9Sstevel@tonic-gate 
847c478bd9Sstevel@tonic-gate 	if (timeout == SM_TIME_DEFAULT)
857c478bd9Sstevel@tonic-gate 		timeout = fp->f_timeout;
867c478bd9Sstevel@tonic-gate 	if (timeout == SM_TIME_IMMEDIATE)
877c478bd9Sstevel@tonic-gate 	{
887c478bd9Sstevel@tonic-gate 		/*
897c478bd9Sstevel@tonic-gate 		**  Filling the buffer will take time and we are wanted to
907c478bd9Sstevel@tonic-gate 		**  return immediately. So...
917c478bd9Sstevel@tonic-gate 		*/
927c478bd9Sstevel@tonic-gate 
937c478bd9Sstevel@tonic-gate 		errno = EAGAIN;
947c478bd9Sstevel@tonic-gate 		return -1L;
957c478bd9Sstevel@tonic-gate 	}
967c478bd9Sstevel@tonic-gate 
977c478bd9Sstevel@tonic-gate 	/*
987c478bd9Sstevel@tonic-gate 	**  Find offset of underlying I/O object, then adjust byte position
997c478bd9Sstevel@tonic-gate 	**  may adjust seek offset on append stream
1007c478bd9Sstevel@tonic-gate 	*/
1017c478bd9Sstevel@tonic-gate 
1027c478bd9Sstevel@tonic-gate 	(void) sm_flush(fp, (int *) &timeout);
1037c478bd9Sstevel@tonic-gate 
1047c478bd9Sstevel@tonic-gate 	/* This is where we start the timeout */
1057c478bd9Sstevel@tonic-gate 	if (timeout != SM_TIME_FOREVER)
1067c478bd9Sstevel@tonic-gate 	{
1077c478bd9Sstevel@tonic-gate 		if (setjmp(TellTimeOut) != 0)
1087c478bd9Sstevel@tonic-gate 		{
1097c478bd9Sstevel@tonic-gate 			errno = EAGAIN;
1107c478bd9Sstevel@tonic-gate 			return -1L;
1117c478bd9Sstevel@tonic-gate 		}
1127c478bd9Sstevel@tonic-gate 
1137c478bd9Sstevel@tonic-gate 		evt = sm_seteventm(timeout, tellalrm, 0);
1147c478bd9Sstevel@tonic-gate 	}
1157c478bd9Sstevel@tonic-gate 
1167c478bd9Sstevel@tonic-gate 	if (fp->f_flags & SMOFF)
1177c478bd9Sstevel@tonic-gate 		pos = fp->f_lseekoff;
1187c478bd9Sstevel@tonic-gate 	else
1197c478bd9Sstevel@tonic-gate 	{
1207c478bd9Sstevel@tonic-gate 		/* XXX only set the timeout here? */
1217c478bd9Sstevel@tonic-gate 		pos = (*fp->f_seek)(fp, (off_t) 0, SM_IO_SEEK_CUR);
1227c478bd9Sstevel@tonic-gate 		if (pos == -1L)
1237c478bd9Sstevel@tonic-gate 			goto clean;
1247c478bd9Sstevel@tonic-gate 	}
1257c478bd9Sstevel@tonic-gate 	if (fp->f_flags & SMRD)
1267c478bd9Sstevel@tonic-gate 	{
1277c478bd9Sstevel@tonic-gate 		/*
1287c478bd9Sstevel@tonic-gate 		**  Reading.  Any unread characters (including
1297c478bd9Sstevel@tonic-gate 		**  those from ungetc) cause the position to be
1307c478bd9Sstevel@tonic-gate 		**  smaller than that in the underlying object.
1317c478bd9Sstevel@tonic-gate 		*/
1327c478bd9Sstevel@tonic-gate 
1337c478bd9Sstevel@tonic-gate 		pos -= fp->f_r;
1347c478bd9Sstevel@tonic-gate 		if (HASUB(fp))
1357c478bd9Sstevel@tonic-gate 			pos -= fp->f_ur;
1367c478bd9Sstevel@tonic-gate 	}
1377c478bd9Sstevel@tonic-gate 	else if (fp->f_flags & SMWR && fp->f_p != NULL)
1387c478bd9Sstevel@tonic-gate 	{
1397c478bd9Sstevel@tonic-gate 		/*
1407c478bd9Sstevel@tonic-gate 		**  Writing.  Any buffered characters cause the
1417c478bd9Sstevel@tonic-gate 		**  position to be greater than that in the
1427c478bd9Sstevel@tonic-gate 		**  underlying object.
1437c478bd9Sstevel@tonic-gate 		*/
1447c478bd9Sstevel@tonic-gate 
1457c478bd9Sstevel@tonic-gate 		pos += fp->f_p - fp->f_bf.smb_base;
1467c478bd9Sstevel@tonic-gate 	}
1477c478bd9Sstevel@tonic-gate 
1487c478bd9Sstevel@tonic-gate clean:
1497c478bd9Sstevel@tonic-gate 	/*  We're back. So undo our timeout and handler */
1507c478bd9Sstevel@tonic-gate 	if (evt != NULL)
1517c478bd9Sstevel@tonic-gate 		sm_clrevent(evt);
1527c478bd9Sstevel@tonic-gate 	return pos;
1537c478bd9Sstevel@tonic-gate }
154