Debianization.
[libspamc] / utils.c
CommitLineData
f5352ff0 1/*
2 * This code is copyright 2001 by Craig Hughes
3 * Portions copyright 2002 by Brad Jorsch
4 * It is licensed under the same license as Perl itself. The text of this
5 * license is included in the SpamAssassin distribution in the file named
6 * "License".
7 */
8
9#include <unistd.h>
10#include <errno.h>
11#include <signal.h>
12#include <sys/types.h>
13#include <sys/uio.h>
14#include <unistd.h>
15#include <stdio.h>
16#include "utils.h"
17
18/* Dec 13 2001 jm: added safe full-read and full-write functions. These
19 * can cope with networks etc., where a write or read may not read all
20 * the data that's there, in one call.
21 */
22/* Aug 14, 2002 bj: EINTR and EAGAIN aren't fatal, are they? */
23/* Aug 14, 2002 bj: moved these to utils.c */
24/* Jan 13, 2003 ym: added timeout functionality */
25
26/* -------------------------------------------------------------------------- */
27
28typedef void sigfunc(int); /* for signal handlers */
29
30sigfunc* sig_catch(int sig, void (*f)(int))
31{
32 struct sigaction act, oact;
33 act.sa_handler = f;
34 act.sa_flags = 0;
35 sigemptyset(&act.sa_mask);
36 sigaction(sig, &act, &oact);
37 return oact.sa_handler;
38}
39
40static void catch_alrm(int x) {
41 /* dummy */
42}
43
44ssize_t
45fd_timeout_read (int fd, void *buf, size_t nbytes)
46{
47 ssize_t nred;
48 sigfunc* sig;
49
50 sig = sig_catch(SIGALRM, catch_alrm);
51 if (libspamc_timeout > 0) {
52 alarm(libspamc_timeout);
53 }
54
55 do {
56 nred = read (fd, buf, nbytes);
57 } while(nred < 0 && errno == EAGAIN);
58
59 if(nred < 0 && errno == EINTR)
60 errno = ETIMEDOUT;
61
62 if (libspamc_timeout > 0) {
63 alarm(0);
64 }
65
66 /* restore old signal handler */
67 sig_catch(SIGALRM, sig);
68
69 return nred;
70}
71
72int
73ssl_timeout_read (SSL *ssl, void *buf, int nbytes)
74{
75 int nred;
76 sigfunc* sig;
77
78 sig = sig_catch(SIGALRM, catch_alrm);
79 if (libspamc_timeout > 0) {
80 alarm(libspamc_timeout);
81 }
82
83 do {
84#ifdef SPAMC_SSL
85 nred = SSL_read (ssl, buf, nbytes);
86#else
87 nred = 0; /* never used */
88#endif
89 } while(nred < 0 && errno == EAGAIN);
90
91 if(nred < 0 && errno == EINTR)
92 errno = ETIMEDOUT;
93
94 if (libspamc_timeout > 0) {
95 alarm(0);
96 }
97
98 /* restore old signal handler */
99 sig_catch(SIGALRM, sig);
100
101 return nred;
102}
103
104/* -------------------------------------------------------------------------- */
105
106int
107full_read (int fd, unsigned char *buf, int min, int len)
108{
109 int total;
110 int thistime;
111
112 for (total = 0; total < min; ) {
113 thistime = fd_timeout_read (fd, buf+total, len-total);
114
115 if (thistime < 0) {
116 return -1;
117 } else if (thistime == 0) {
118 /* EOF, but we didn't read the minimum. return what we've read
119 * so far and next read (if there is one) will return 0. */
120 return total;
121 }
122
123 total += thistime;
124 }
125 return total;
126}
127
128int
129full_write (int fd, const unsigned char *buf, int len)
130{
131 int total;
132 int thistime;
133
134 for (total = 0; total < len; ) {
135 thistime = write (fd, buf+total, len-total);
136
137 if (thistime < 0) {
138 if(EINTR == errno || EAGAIN == errno) continue;
139 return thistime; /* always an error for writes */
140 }
141 total += thistime;
142 }
143 return total;
144}