support image/x-eps format via pdf_viewer
[claws.git] / src / plugins / spamassassin / utils.c
blob136524e532c9c4f3541f125f7110228c5152e83b
1 /* <@LICENSE>
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:
8 *
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.
16 * </@LICENSE>
19 #include "config.h"
21 #ifndef _WIN32
22 #include <unistd.h>
23 #include <sys/uio.h>
24 #include <sys/types.h>
25 #include <sys/socket.h>
26 #else
28 #ifdef _MSC_VER
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 )
36 #endif
38 #include <io.h>
39 #endif
40 #include <errno.h>
41 #include <signal.h>
42 #include <stdio.h>
43 #include "utils.h"
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 /* -------------------------------------------------------------------------- */
55 #ifndef _WIN32
56 typedef void sigfunc(int); /* for signal handlers */
58 sigfunc *sig_catch(int sig, void (*f) (int))
60 struct sigaction act, oact;
61 act.sa_handler = f;
62 act.sa_flags = 0;
63 sigemptyset(&act.sa_mask);
64 sigaction(sig, &act, &oact);
65 return oact.sa_handler;
68 static void catch_alrm(int x)
70 UNUSED_VARIABLE(x);
72 #endif
74 int timeout_connect (int sockfd, const struct sockaddr *serv_addr, size_t addrlen)
76 int ret;
78 #ifndef _WIN32
79 sigfunc* sig;
81 sig = sig_catch(SIGALRM, catch_alrm);
82 if (libspamc_connect_timeout > 0) {
83 alarm(libspamc_connect_timeout);
85 #endif
87 ret = connect(sockfd, serv_addr, addrlen);
89 #ifndef _WIN32
90 if (libspamc_connect_timeout > 0) {
91 alarm(0);
94 /* restore old signal handler */
95 sig_catch(SIGALRM, sig);
96 #endif
98 return ret;
101 int fd_timeout_read(int fd, char fdflag, void *buf, size_t nbytes)
103 int nred;
104 int origerr;
105 #ifndef _WIN32
106 sigfunc *sig;
108 sig = sig_catch(SIGALRM, catch_alrm);
109 if (libspamc_timeout > 0) {
110 alarm(libspamc_timeout);
112 #endif
114 do {
115 if (fdflag) {
116 nred = (int)read(fd, buf, nbytes);
117 origerr = errno;
119 else {
120 nred = (int)recv(fd, buf, nbytes, 0);
121 #ifndef _WIN32
122 origerr = errno;
123 #else
124 origerr = WSAGetLastError();
125 #endif
127 } while (nred < 0 && origerr == EWOULDBLOCK);
129 #ifndef _WIN32
130 if (nred < 0 && origerr == EINTR)
131 errno = ETIMEDOUT;
133 if (libspamc_timeout > 0) {
134 alarm(0);
137 /* restore old signal handler */
138 sig_catch(SIGALRM, sig);
139 #endif
141 return nred;
144 int ssl_timeout_read(SSL * ssl, void *buf, int nbytes)
146 int nred;
148 #ifndef _WIN32
149 sigfunc *sig;
151 sig = sig_catch(SIGALRM, catch_alrm);
152 if (libspamc_timeout > 0) {
153 alarm(libspamc_timeout);
155 #endif
157 do {
159 #ifdef SPAMC_SSL
160 nred = SSL_read(ssl, buf, nbytes);
161 #else
162 UNUSED_VARIABLE(ssl);
163 UNUSED_VARIABLE(buf);
164 UNUSED_VARIABLE(nbytes);
165 nred = 0; /* never used */
166 #endif
168 } while (nred < 0 && errno == EWOULDBLOCK);
170 #ifndef _WIN32
171 if (nred < 0 && errno == EINTR)
172 errno = ETIMEDOUT;
174 if (libspamc_timeout > 0) {
175 alarm(0);
178 /* restore old signal handler */
179 sig_catch(SIGALRM, sig);
180 #endif
182 return nred;
185 /* -------------------------------------------------------------------------- */
187 int full_read(int fd, char fdflag, void *vbuf, int min, int len)
189 unsigned char *buf = (unsigned char *) vbuf;
190 int total;
191 int thistime;
193 for (total = 0; total < min;) {
194 thistime = fd_timeout_read(fd, fdflag, buf + total, len - total);
196 if (thistime < 0) {
197 if (total >= min) {
198 /* error, but we read *some*. return what we've read
199 * so far and next read (if there is one) will return -1. */
200 return total;
201 } else {
202 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. */
208 return total;
211 total += thistime;
213 return total;
216 int full_read_ssl(SSL * ssl, unsigned char *buf, int min, int len)
218 int total;
219 int thistime;
221 for (total = 0; total < min;) {
222 thistime = ssl_timeout_read(ssl, buf + total, len - total);
224 if (thistime < 0) {
225 if (total >= min) {
226 /* error, but we read *some*. return what we've read
227 * so far and next read (if there is one) will return -1. */
228 return total;
229 } else {
230 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. */
236 return total;
239 total += thistime;
241 return total;
244 int full_write(int fd, char fdflag, const void *vbuf, int len)
246 const char *buf = (const char *) vbuf;
247 int total;
248 int thistime;
249 int origerr;
251 for (total = 0; total < len;) {
252 if (fdflag) {
253 thistime = write(fd, buf + total, len - total);
254 origerr = errno;
256 else {
257 thistime = send(fd, buf + total, len - total, 0);
258 #ifndef _WIN32
259 origerr = errno;
260 #else
261 origerr = WSAGetLastError();
262 #endif
264 if (thistime < 0) {
265 if (EINTR == origerr || EWOULDBLOCK == origerr)
266 continue;
267 return thistime; /* always an error for writes */
269 total += thistime;
271 return total;