xref: /titanic_51/usr/src/cmd/sendmail/libsm/fpos.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * Copyright (c) 2000-2001, 2004 Sendmail, Inc. and its suppliers.
3*7c478bd9Sstevel@tonic-gate  *      All rights reserved.
4*7c478bd9Sstevel@tonic-gate  * Copyright (c) 1990, 1993
5*7c478bd9Sstevel@tonic-gate  *	The Regents of the University of California.  All rights reserved.
6*7c478bd9Sstevel@tonic-gate  *
7*7c478bd9Sstevel@tonic-gate  * This code is derived from software contributed to Berkeley by
8*7c478bd9Sstevel@tonic-gate  * Chris Torek.
9*7c478bd9Sstevel@tonic-gate  *
10*7c478bd9Sstevel@tonic-gate  * By using this file, you agree to the terms and conditions set
11*7c478bd9Sstevel@tonic-gate  * forth in the LICENSE file which can be found at the top level of
12*7c478bd9Sstevel@tonic-gate  * the sendmail distribution.
13*7c478bd9Sstevel@tonic-gate  */
14*7c478bd9Sstevel@tonic-gate 
15*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
16*7c478bd9Sstevel@tonic-gate 
17*7c478bd9Sstevel@tonic-gate #include <sm/gen.h>
18*7c478bd9Sstevel@tonic-gate SM_RCSID("@(#)$Id: fpos.c,v 1.38 2004/08/03 20:17:38 ca Exp $")
19*7c478bd9Sstevel@tonic-gate #include <errno.h>
20*7c478bd9Sstevel@tonic-gate #include <setjmp.h>
21*7c478bd9Sstevel@tonic-gate #include <sys/time.h>
22*7c478bd9Sstevel@tonic-gate #include <sm/heap.h>
23*7c478bd9Sstevel@tonic-gate #include <sm/signal.h>
24*7c478bd9Sstevel@tonic-gate #include <sm/clock.h>
25*7c478bd9Sstevel@tonic-gate #include <sm/io.h>
26*7c478bd9Sstevel@tonic-gate #include <sm/assert.h>
27*7c478bd9Sstevel@tonic-gate #include "local.h"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate static void	tellalrm __P((int));
30*7c478bd9Sstevel@tonic-gate static jmp_buf TellTimeOut;
31*7c478bd9Sstevel@tonic-gate 
32*7c478bd9Sstevel@tonic-gate /*
33*7c478bd9Sstevel@tonic-gate **  TELLALRM -- handler when timeout activated for sm_io_tell()
34*7c478bd9Sstevel@tonic-gate **
35*7c478bd9Sstevel@tonic-gate **  Returns flow of control to where setjmp(TellTimeOut) was set.
36*7c478bd9Sstevel@tonic-gate **
37*7c478bd9Sstevel@tonic-gate **	Parameters:
38*7c478bd9Sstevel@tonic-gate **		sig -- unused
39*7c478bd9Sstevel@tonic-gate **
40*7c478bd9Sstevel@tonic-gate **	Returns:
41*7c478bd9Sstevel@tonic-gate **		does not return
42*7c478bd9Sstevel@tonic-gate **
43*7c478bd9Sstevel@tonic-gate **	Side Effects:
44*7c478bd9Sstevel@tonic-gate **		returns flow of control to setjmp(TellTimeOut).
45*7c478bd9Sstevel@tonic-gate **
46*7c478bd9Sstevel@tonic-gate **	NOTE:	THIS CAN BE CALLED FROM A SIGNAL HANDLER.  DO NOT ADD
47*7c478bd9Sstevel@tonic-gate **		ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE
48*7c478bd9Sstevel@tonic-gate **		DOING.
49*7c478bd9Sstevel@tonic-gate */
50*7c478bd9Sstevel@tonic-gate 
51*7c478bd9Sstevel@tonic-gate /* ARGSUSED0 */
52*7c478bd9Sstevel@tonic-gate static void
53*7c478bd9Sstevel@tonic-gate tellalrm(sig)
54*7c478bd9Sstevel@tonic-gate 	int sig;
55*7c478bd9Sstevel@tonic-gate {
56*7c478bd9Sstevel@tonic-gate 	longjmp(TellTimeOut, 1);
57*7c478bd9Sstevel@tonic-gate }
58*7c478bd9Sstevel@tonic-gate 
59*7c478bd9Sstevel@tonic-gate /*
60*7c478bd9Sstevel@tonic-gate **  SM_IO_TELL -- position the file pointer
61*7c478bd9Sstevel@tonic-gate **
62*7c478bd9Sstevel@tonic-gate **	Paramters:
63*7c478bd9Sstevel@tonic-gate **		fp -- the file pointer to get repositioned
64*7c478bd9Sstevel@tonic-gate **		timeout -- time to complete the tell (milliseconds)
65*7c478bd9Sstevel@tonic-gate **
66*7c478bd9Sstevel@tonic-gate **	Returns:
67*7c478bd9Sstevel@tonic-gate **		Success -- the repositioned location.
68*7c478bd9Sstevel@tonic-gate **		Failure -- -1 (minus 1) and sets errno
69*7c478bd9Sstevel@tonic-gate */
70*7c478bd9Sstevel@tonic-gate 
71*7c478bd9Sstevel@tonic-gate long
72*7c478bd9Sstevel@tonic-gate sm_io_tell(fp, timeout)
73*7c478bd9Sstevel@tonic-gate 	register SM_FILE_T *fp;
74*7c478bd9Sstevel@tonic-gate 	int SM_NONVOLATILE timeout;
75*7c478bd9Sstevel@tonic-gate {
76*7c478bd9Sstevel@tonic-gate 	register off_t pos;
77*7c478bd9Sstevel@tonic-gate 	SM_EVENT *evt = NULL;
78*7c478bd9Sstevel@tonic-gate 
79*7c478bd9Sstevel@tonic-gate 	SM_REQUIRE_ISA(fp, SmFileMagic);
80*7c478bd9Sstevel@tonic-gate 	if (fp->f_seek == NULL)
81*7c478bd9Sstevel@tonic-gate 	{
82*7c478bd9Sstevel@tonic-gate 		errno = ESPIPE;			/* historic practice */
83*7c478bd9Sstevel@tonic-gate 		return -1L;
84*7c478bd9Sstevel@tonic-gate 	}
85*7c478bd9Sstevel@tonic-gate 
86*7c478bd9Sstevel@tonic-gate 	if (timeout == SM_TIME_DEFAULT)
87*7c478bd9Sstevel@tonic-gate 		timeout = fp->f_timeout;
88*7c478bd9Sstevel@tonic-gate 	if (timeout == SM_TIME_IMMEDIATE)
89*7c478bd9Sstevel@tonic-gate 	{
90*7c478bd9Sstevel@tonic-gate 		/*
91*7c478bd9Sstevel@tonic-gate 		**  Filling the buffer will take time and we are wanted to
92*7c478bd9Sstevel@tonic-gate 		**  return immediately. So...
93*7c478bd9Sstevel@tonic-gate 		*/
94*7c478bd9Sstevel@tonic-gate 
95*7c478bd9Sstevel@tonic-gate 		errno = EAGAIN;
96*7c478bd9Sstevel@tonic-gate 		return -1L;
97*7c478bd9Sstevel@tonic-gate 	}
98*7c478bd9Sstevel@tonic-gate 
99*7c478bd9Sstevel@tonic-gate 	/*
100*7c478bd9Sstevel@tonic-gate 	**  Find offset of underlying I/O object, then adjust byte position
101*7c478bd9Sstevel@tonic-gate 	**  may adjust seek offset on append stream
102*7c478bd9Sstevel@tonic-gate 	*/
103*7c478bd9Sstevel@tonic-gate 
104*7c478bd9Sstevel@tonic-gate 	(void) sm_flush(fp, (int *) &timeout);
105*7c478bd9Sstevel@tonic-gate 
106*7c478bd9Sstevel@tonic-gate 	/* This is where we start the timeout */
107*7c478bd9Sstevel@tonic-gate 	if (timeout != SM_TIME_FOREVER)
108*7c478bd9Sstevel@tonic-gate 	{
109*7c478bd9Sstevel@tonic-gate 		if (setjmp(TellTimeOut) != 0)
110*7c478bd9Sstevel@tonic-gate 		{
111*7c478bd9Sstevel@tonic-gate 			errno = EAGAIN;
112*7c478bd9Sstevel@tonic-gate 			return -1L;
113*7c478bd9Sstevel@tonic-gate 		}
114*7c478bd9Sstevel@tonic-gate 
115*7c478bd9Sstevel@tonic-gate 		evt = sm_seteventm(timeout, tellalrm, 0);
116*7c478bd9Sstevel@tonic-gate 	}
117*7c478bd9Sstevel@tonic-gate 
118*7c478bd9Sstevel@tonic-gate 	if (fp->f_flags & SMOFF)
119*7c478bd9Sstevel@tonic-gate 		pos = fp->f_lseekoff;
120*7c478bd9Sstevel@tonic-gate 	else
121*7c478bd9Sstevel@tonic-gate 	{
122*7c478bd9Sstevel@tonic-gate 		/* XXX only set the timeout here? */
123*7c478bd9Sstevel@tonic-gate 		pos = (*fp->f_seek)(fp, (off_t) 0, SM_IO_SEEK_CUR);
124*7c478bd9Sstevel@tonic-gate 		if (pos == -1L)
125*7c478bd9Sstevel@tonic-gate 			goto clean;
126*7c478bd9Sstevel@tonic-gate 	}
127*7c478bd9Sstevel@tonic-gate 	if (fp->f_flags & SMRD)
128*7c478bd9Sstevel@tonic-gate 	{
129*7c478bd9Sstevel@tonic-gate 		/*
130*7c478bd9Sstevel@tonic-gate 		**  Reading.  Any unread characters (including
131*7c478bd9Sstevel@tonic-gate 		**  those from ungetc) cause the position to be
132*7c478bd9Sstevel@tonic-gate 		**  smaller than that in the underlying object.
133*7c478bd9Sstevel@tonic-gate 		*/
134*7c478bd9Sstevel@tonic-gate 
135*7c478bd9Sstevel@tonic-gate 		pos -= fp->f_r;
136*7c478bd9Sstevel@tonic-gate 		if (HASUB(fp))
137*7c478bd9Sstevel@tonic-gate 			pos -= fp->f_ur;
138*7c478bd9Sstevel@tonic-gate 	}
139*7c478bd9Sstevel@tonic-gate 	else if (fp->f_flags & SMWR && fp->f_p != NULL)
140*7c478bd9Sstevel@tonic-gate 	{
141*7c478bd9Sstevel@tonic-gate 		/*
142*7c478bd9Sstevel@tonic-gate 		**  Writing.  Any buffered characters cause the
143*7c478bd9Sstevel@tonic-gate 		**  position to be greater than that in the
144*7c478bd9Sstevel@tonic-gate 		**  underlying object.
145*7c478bd9Sstevel@tonic-gate 		*/
146*7c478bd9Sstevel@tonic-gate 
147*7c478bd9Sstevel@tonic-gate 		pos += fp->f_p - fp->f_bf.smb_base;
148*7c478bd9Sstevel@tonic-gate 	}
149*7c478bd9Sstevel@tonic-gate 
150*7c478bd9Sstevel@tonic-gate clean:
151*7c478bd9Sstevel@tonic-gate 	/*  We're back. So undo our timeout and handler */
152*7c478bd9Sstevel@tonic-gate 	if (evt != NULL)
153*7c478bd9Sstevel@tonic-gate 		sm_clrevent(evt);
154*7c478bd9Sstevel@tonic-gate 	return pos;
155*7c478bd9Sstevel@tonic-gate }
156