2 * Copyright 2004 Apache Software Foundation
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
21 #include <sys/types.h>
22 #include <sys/socket.h>
26 /* ignore MSVC++ warnings that are annoying and hard to remove:
27 4115 named type definition in parentheses
28 4127 conditional expression is constant
29 4514 unreferenced inline function removed
31 #pragma warning( disable : 4115 4127 4514 )
41 /* Dec 13 2001 jm: added safe full-read and full-write functions. These
42 * can cope with networks etc., where a write or read may not read all
43 * the data that's there, in one call.
45 /* Aug 14, 2002 bj: EINTR and EAGAIN aren't fatal, are they? */
46 /* Aug 14, 2002 bj: moved these to utils.c */
47 /* Jan 13, 2003 ym: added timeout functionality */
48 /* Apr 24, 2003 sjf: made full_read and full_write void* params */
50 /* -------------------------------------------------------------------------- */
52 typedef void sigfunc(int); /* for signal handlers */
54 sigfunc *sig_catch(int sig, void (*f) (int))
56 struct sigaction act, oact;
59 sigemptyset(&act.sa_mask);
60 sigaction(sig, &act, &oact);
61 return oact.sa_handler;
64 static void catch_alrm(int x)
70 int fd_timeout_read(int fd, char fdflag, void *buf, size_t nbytes)
77 sig = sig_catch(SIGALRM, catch_alrm);
78 if (libspamc_timeout > 0) {
79 alarm(libspamc_timeout);
85 nred = (int)read(fd, buf, nbytes);
89 nred = (int)recv(fd, buf, nbytes, 0);
93 origerr = WSAGetLastError();
96 } while (nred < 0 && origerr == EWOULDBLOCK);
99 if (nred < 0 && origerr == EINTR)
102 if (libspamc_timeout > 0) {
106 /* restore old signal handler */
107 sig_catch(SIGALRM, sig);
113 int ssl_timeout_read(SSL * ssl, void *buf, int nbytes)
120 sig = sig_catch(SIGALRM, catch_alrm);
121 if (libspamc_timeout > 0) {
122 alarm(libspamc_timeout);
129 nred = SSL_read(ssl, buf, nbytes);
131 UNUSED_VARIABLE(ssl);
132 UNUSED_VARIABLE(buf);
133 UNUSED_VARIABLE(nbytes);
134 nred = 0; /* never used */
137 } while (nred < 0 && errno == EWOULDBLOCK);
140 if (nred < 0 && errno == EINTR)
143 if (libspamc_timeout > 0) {
147 /* restore old signal handler */
148 sig_catch(SIGALRM, sig);
154 /* -------------------------------------------------------------------------- */
156 int full_read(int fd, char fdflag, void *vbuf, int min, int len)
158 unsigned char *buf = (unsigned char *) vbuf;
162 for (total = 0; total < min;) {
163 thistime = fd_timeout_read(fd, fdflag, buf + total, len - total);
167 /* error, but we read *some*. return what we've read
168 * so far and next read (if there is one) will return -1. */
174 else if (thistime == 0) {
175 /* EOF, but we didn't read the minimum. return what we've read
176 * so far and next read (if there is one) will return 0. */
185 int full_read_ssl(SSL * ssl, unsigned char *buf, int min, int len)
190 for (total = 0; total < min;) {
191 thistime = ssl_timeout_read(ssl, buf + total, len - total);
195 /* error, but we read *some*. return what we've read
196 * so far and next read (if there is one) will return -1. */
202 else if (thistime == 0) {
203 /* EOF, but we didn't read the minimum. return what we've read
204 * so far and next read (if there is one) will return 0. */
213 int full_write(int fd, char fdflag, const void *vbuf, int len)
215 const char *buf = (const char *) vbuf;
220 for (total = 0; total < len;) {
222 thistime = write(fd, buf + total, len - total);
226 thistime = send(fd, buf + total, len - total, 0);
230 origerr = WSAGetLastError();
234 if (EINTR == origerr || EWOULDBLOCK == origerr)
236 return thistime; /* always an error for writes */