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
12 #include <sys/types.h>
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.
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 /* Apr 24, 2003 sjf: made full_read and full_write void* params */
27 /* -------------------------------------------------------------------------- */
29 typedef void sigfunc(int); /* for signal handlers */
31 sigfunc* sig_catch(int sig, void (*f)(int))
33 struct sigaction act, oact;
36 sigemptyset(&act.sa_mask);
37 sigaction(sig, &act, &oact);
38 return oact.sa_handler;
41 static void catch_alrm(int x) {
46 fd_timeout_read (int fd, void *buf, size_t nbytes)
51 sig = sig_catch(SIGALRM, catch_alrm);
52 if (libspamc_timeout > 0) {
53 alarm(libspamc_timeout);
57 nred = read (fd, buf, nbytes);
58 } while(nred < 0 && errno == EAGAIN);
60 if(nred < 0 && errno == EINTR)
63 if (libspamc_timeout > 0) {
67 /* restore old signal handler */
68 sig_catch(SIGALRM, sig);
74 ssl_timeout_read (SSL *ssl, void *buf, int nbytes)
82 UNUSED_VARIABLE(nbytes);
85 sig = sig_catch(SIGALRM, catch_alrm);
86 if (libspamc_timeout > 0) {
87 alarm(libspamc_timeout);
92 nred = SSL_read (ssl, buf, nbytes);
94 nred = 0; /* never used */
96 } while(nred < 0 && errno == EAGAIN);
98 if(nred < 0 && errno == EINTR)
101 if (libspamc_timeout > 0) {
105 /* restore old signal handler */
106 sig_catch(SIGALRM, sig);
111 /* -------------------------------------------------------------------------- */
114 full_read (int fd, void *vbuf, int min, int len)
116 unsigned char *buf = (unsigned char *)vbuf;
120 for (total = 0; total < min; ) {
121 thistime = fd_timeout_read (fd, buf+total, len-total);
125 } else if (thistime == 0) {
126 /* EOF, but we didn't read the minimum. return what we've read
127 * so far and next read (if there is one) will return 0. */
137 full_read_ssl (SSL *ssl, unsigned char *buf, int min, int len)
142 for (total = 0; total < min; ) {
143 thistime = ssl_timeout_read (ssl, buf+total, len-total);
147 } else if (thistime == 0) {
148 /* EOF, but we didn't read the minimum. return what we've read
149 * so far and next read (if there is one) will return 0. */
159 full_write (int fd, const void *vbuf, int len)
161 const unsigned char *buf = (const unsigned char *)vbuf;
165 for (total = 0; total < len; ) {
166 thistime = write (fd, buf+total, len-total);
169 if(EINTR == errno || EAGAIN == errno) continue;
170 return thistime; /* always an error for writes */