#include <unistd.h>
#include <errno.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>
#include <stdio.h>
#include "utils.h"
typedef void sigfunc(int);
sigfunc* sig_catch(int sig, void (*f)(int))
{
struct sigaction act, oact;
act.sa_handler = f;
act.sa_flags = 0;
sigemptyset(&act.sa_mask);
sigaction(sig, &act, &oact);
return oact.sa_handler;
}
static void catch_alrm(int x) {
UNUSED_VARIABLE(x);
}
ssize_t
fd_timeout_read (int fd, void *buf, size_t nbytes)
{
ssize_t nred;
sigfunc* sig;
sig = sig_catch(SIGALRM, catch_alrm);
if (libspamc_timeout > 0) {
alarm(libspamc_timeout);
}
do {
nred = read (fd, buf, nbytes);
} while(nred < 0 && errno == EAGAIN);
if(nred < 0 && errno == EINTR)
errno = ETIMEDOUT;
if (libspamc_timeout > 0) {
alarm(0);
}
sig_catch(SIGALRM, sig);
return nred;
}
int
ssl_timeout_read (SSL *ssl, void *buf, int nbytes)
{
int nred;
sigfunc* sig;
#ifndef SPAMC_SSL
UNUSED_VARIABLE(ssl);
UNUSED_VARIABLE(buf);
UNUSED_VARIABLE(nbytes);
#endif
sig = sig_catch(SIGALRM, catch_alrm);
if (libspamc_timeout > 0) {
alarm(libspamc_timeout);
}
do {
#ifdef SPAMC_SSL
nred = SSL_read (ssl, buf, nbytes);
#else
nred = 0;
#endif
} while(nred < 0 && errno == EAGAIN);
if(nred < 0 && errno == EINTR)
errno = ETIMEDOUT;
if (libspamc_timeout > 0) {
alarm(0);
}
sig_catch(SIGALRM, sig);
return nred;
}
int
full_read (int fd, void *vbuf, int min, int len)
{
unsigned char *buf = (unsigned char *)vbuf;
int total;
int thistime;
for (total = 0; total < min; ) {
thistime = fd_timeout_read (fd, buf+total, len-total);
if (thistime < 0) {
return -1;
} else if (thistime == 0) {
return total;
}
total += thistime;
}
return total;
}
int
full_read_ssl (SSL *ssl, unsigned char *buf, int min, int len)
{
int total;
int thistime;
for (total = 0; total < min; ) {
thistime = ssl_timeout_read (ssl, buf+total, len-total);
if (thistime < 0) {
return -1;
} else if (thistime == 0) {
return total;
}
total += thistime;
}
return total;
}
int
full_write (int fd, const void *vbuf, int len)
{
const unsigned char *buf = (const unsigned char *)vbuf;
int total;
int thistime;
for (total = 0; total < len; ) {
thistime = write (fd, buf+total, len-total);
if (thistime < 0) {
if(EINTR == errno || EAGAIN == errno) continue;
return thistime;
}
total += thistime;
}
return total;
}