Debianization.
[libspamc] / utils.c
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
28 typedef void sigfunc(int); /* for signal handlers */
29
30 sigfunc* 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
40 static void catch_alrm(int x) {
41 /* dummy */
42 }
43
44 ssize_t
45 fd_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
72 int
73 ssl_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
106 int
107 full_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
128 int
129 full_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 }