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