2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to you under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at:
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
24 #include <sys/types.h>
25 #include <sys/socket.h>
29 /* ignore MSVC++ warnings that are annoying and hard to remove:
30 4115 named type definition in parentheses
31 4127 conditional expression is constant
32 4514 unreferenced inline function removed
33 4996 deprecated "unsafe" functions
35 #pragma warning( disable : 4115 4127 4514 4996 )
45 /* Dec 13 2001 jm: added safe full-read and full-write functions. These
46 * can cope with networks etc., where a write or read may not read all
47 * the data that's there, in one call.
49 /* Aug 14, 2002 bj: EINTR and EAGAIN aren't fatal, are they? */
50 /* Aug 14, 2002 bj: moved these to utils.c */
51 /* Jan 13, 2003 ym: added timeout functionality */
52 /* Apr 24, 2003 sjf: made full_read and full_write void* params */
54 /* -------------------------------------------------------------------------- */
56 typedef void sigfunc(int); /* for signal handlers */
58 sigfunc
*sig_catch(int sig
, void (*f
) (int))
60 struct sigaction act
, oact
;
63 sigemptyset(&act
.sa_mask
);
64 sigaction(sig
, &act
, &oact
);
65 return oact
.sa_handler
;
68 static void catch_alrm(int x
)
74 int timeout_connect (int sockfd
, const struct sockaddr
*serv_addr
, size_t addrlen
)
81 sig
= sig_catch(SIGALRM
, catch_alrm
);
82 if (libspamc_connect_timeout
> 0) {
83 alarm(libspamc_connect_timeout
);
87 ret
= connect(sockfd
, serv_addr
, addrlen
);
90 if (libspamc_connect_timeout
> 0) {
94 /* restore old signal handler */
95 sig_catch(SIGALRM
, sig
);
101 int fd_timeout_read(int fd
, char fdflag
, void *buf
, size_t nbytes
)
108 sig
= sig_catch(SIGALRM
, catch_alrm
);
109 if (libspamc_timeout
> 0) {
110 alarm(libspamc_timeout
);
116 nred
= (int)read(fd
, buf
, nbytes
);
120 nred
= (int)recv(fd
, buf
, nbytes
, 0);
124 origerr
= WSAGetLastError();
127 } while (nred
< 0 && origerr
== EWOULDBLOCK
);
130 if (nred
< 0 && origerr
== EINTR
)
133 if (libspamc_timeout
> 0) {
137 /* restore old signal handler */
138 sig_catch(SIGALRM
, sig
);
144 int ssl_timeout_read(SSL
* ssl
, void *buf
, int nbytes
)
151 sig
= sig_catch(SIGALRM
, catch_alrm
);
152 if (libspamc_timeout
> 0) {
153 alarm(libspamc_timeout
);
160 nred
= SSL_read(ssl
, buf
, nbytes
);
162 UNUSED_VARIABLE(ssl
);
163 UNUSED_VARIABLE(buf
);
164 UNUSED_VARIABLE(nbytes
);
165 nred
= 0; /* never used */
168 } while (nred
< 0 && errno
== EWOULDBLOCK
);
171 if (nred
< 0 && errno
== EINTR
)
174 if (libspamc_timeout
> 0) {
178 /* restore old signal handler */
179 sig_catch(SIGALRM
, sig
);
185 /* -------------------------------------------------------------------------- */
187 int full_read(int fd
, char fdflag
, void *vbuf
, int min
, int len
)
189 unsigned char *buf
= (unsigned char *) vbuf
;
193 for (total
= 0; total
< min
;) {
194 thistime
= fd_timeout_read(fd
, fdflag
, buf
+ total
, len
- total
);
198 /* error, but we read *some*. return what we've read
199 * so far and next read (if there is one) will return -1. */
205 else if (thistime
== 0) {
206 /* EOF, but we didn't read the minimum. return what we've read
207 * so far and next read (if there is one) will return 0. */
216 int full_read_ssl(SSL
* ssl
, unsigned char *buf
, int min
, int len
)
221 for (total
= 0; total
< min
;) {
222 thistime
= ssl_timeout_read(ssl
, buf
+ total
, len
- total
);
226 /* error, but we read *some*. return what we've read
227 * so far and next read (if there is one) will return -1. */
233 else if (thistime
== 0) {
234 /* EOF, but we didn't read the minimum. return what we've read
235 * so far and next read (if there is one) will return 0. */
244 int full_write(int fd
, char fdflag
, const void *vbuf
, int len
)
246 const char *buf
= (const char *) vbuf
;
251 for (total
= 0; total
< len
;) {
253 thistime
= write(fd
, buf
+ total
, len
- total
);
257 thistime
= send(fd
, buf
+ total
, len
- total
, 0);
261 origerr
= WSAGetLastError();
265 if (EINTR
== origerr
|| EWOULDBLOCK
== origerr
)
267 return thistime
; /* always an error for writes */