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