summaryrefslogtreecommitdiff
path: root/common/spio.c
diff options
context:
space:
mode:
Diffstat (limited to 'common/spio.c')
-rw-r--r--common/spio.c216
1 files changed, 132 insertions, 84 deletions
diff --git a/common/spio.c b/common/spio.c
index 36b495e..ff5a473 100644
--- a/common/spio.c
+++ b/common/spio.c
@@ -53,11 +53,15 @@
#include <fcntl.h>
#include <syslog.h>
#include <errno.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <errno.h>
+#include <err.h>
#include "usuals.h"
#include "sock_any.h"
-#include "clamsmtpd.h"
-#include "util.h"
+#include "stringx.h"
+#include "sppriv.h"
#define MAX_LOG_LINE 79
#define GET_IO_NAME(io) ((io)->name ? (io)->name : "??? ")
@@ -70,7 +74,7 @@ static void close_raw(int* fd)
*fd = -1;
}
-static void log_io_data(clamsmtp_context_t* ctx, clio_t* io, const char* data, int read)
+static void log_io_data(spctx_t* ctx, spio_t* io, const char* data, int read)
{
char buf[MAX_LOG_LINE + 1];
int pos, len;
@@ -90,14 +94,14 @@ static void log_io_data(clamsmtp_context_t* ctx, clio_t* io, const char* data, i
memcpy(buf, data, len);
buf[len] = 0;
- messagex(ctx, LOG_DEBUG, "%s%s%s", GET_IO_NAME(io),
+ sp_messagex(ctx, LOG_DEBUG, "%s%s%s", GET_IO_NAME(io),
read ? " < " : " > ", buf);
data += pos;
}
}
-void clio_init(clio_t* io, const char* name)
+void spio_init(spio_t* io, const char* name)
{
ASSERT(io && name);
memset(io, 0, sizeof(*io));
@@ -105,7 +109,7 @@ void clio_init(clio_t* io, const char* name)
io->fd = -1;
}
-int clio_connect(clamsmtp_context_t* ctx, clio_t* io, const struct sockaddr_any* sany,
+int spio_connect(spctx_t* ctx, spio_t* io, const struct sockaddr_any* sany,
const char* addrname)
{
int ret = 0;
@@ -116,9 +120,9 @@ int clio_connect(clamsmtp_context_t* ctx, clio_t* io, const struct sockaddr_any*
if((io->fd = socket(SANY_TYPE(*sany), SOCK_STREAM, 0)) == -1)
RETURN(-1);
- if(setsockopt(io->fd, SOL_SOCKET, SO_RCVTIMEO, &(g_state->timeout), sizeof(g_state->timeout)) == -1 ||
- setsockopt(io->fd, SOL_SOCKET, SO_SNDTIMEO, &(g_state->timeout), sizeof(g_state->timeout)) == -1)
- messagex(ctx, LOG_WARNING, "couldn't set timeouts on connection");
+ if(setsockopt(io->fd, SOL_SOCKET, SO_RCVTIMEO, &(g_state.timeout), sizeof(g_state.timeout)) == -1 ||
+ setsockopt(io->fd, SOL_SOCKET, SO_SNDTIMEO, &(g_state.timeout), sizeof(g_state.timeout)) == -1)
+ sp_messagex(ctx, LOG_WARNING, "couldn't set timeouts on connection");
if(connect(io->fd, &SANY_ADDR(*sany), SANY_LEN(*sany)) == -1)
RETURN(-1);
@@ -129,89 +133,95 @@ cleanup:
if(io->fd != -1)
close(io->fd);
- message(ctx, LOG_ERR, "couldn't connect to: %s", addrname);
+ sp_message(ctx, LOG_ERR, "couldn't connect to: %s", addrname);
return -1;
}
ASSERT(io->fd != -1);
- messagex(ctx, LOG_DEBUG, "%s connected to: %s", GET_IO_NAME(io), addrname);
+ sp_messagex(ctx, LOG_DEBUG, "%s connected to: %s", GET_IO_NAME(io), addrname);
return 0;
}
-void clio_disconnect(clamsmtp_context_t* ctx, clio_t* io)
+void spio_disconnect(spctx_t* ctx, spio_t* io)
{
ASSERT(ctx && io);
- if(clio_valid(io))
+ if(spio_valid(io))
{
close_raw(&(io->fd));
- messagex(ctx, LOG_DEBUG, "%s connection closed", GET_IO_NAME(io));
+ sp_messagex(ctx, LOG_DEBUG, "%s connection closed", GET_IO_NAME(io));
}
}
-int clio_select(clamsmtp_context_t* ctx, clio_t** io)
+unsigned int spio_select(spctx_t* ctx, ...)
{
fd_set mask;
+ spio_t* io;
+ int ret = 0;
+ int i = 0;
+ va_list ap;
- ASSERT(ctx && io);
+ ASSERT(ctx);
FD_ZERO(&mask);
- *io = NULL;
- /* First check if buffers have any data */
+ va_start(ap, ctx);
- if(clio_valid(&(ctx->server)))
+ while((io = va_arg(ap, spio_t*)) != NULL)
{
- if(ctx->server.buflen > 0)
- {
- *io = &(ctx->server);
- return 0;
- }
+ /* We can't handle more than 31 args */
+ if(i > (sizeof(int) * 8) - 2)
+ break;
- FD_SET(ctx->server.fd, &mask);
- }
+ /* Check if the buffer has something in it */
+ if(io->_ln > 0)
+ ret |= (1 << i);
- if(clio_valid(&(ctx->client)))
- {
- if(ctx->client.buflen > 0)
- {
- *io = &(ctx->client);
- return 0;
- }
+ /* Mark for select */
+ FD_SET(io->fd, &mask);
- FD_SET(ctx->client.fd, &mask);
+ i++;
}
- /* Select on the above */
+ va_end(ap);
+
+ /* If any buffers had something present, then return */
+ if(ret != 0)
+ return ret;
- switch(select(FD_SETSIZE, &mask, NULL, NULL, (struct timeval*)&(g_state->timeout)))
+ /* Otherwise wait on more data */
+ switch(select(FD_SETSIZE, &mask, NULL, NULL,
+ (struct timeval*)&(g_state.timeout)))
{
case 0:
- messagex(ctx, LOG_ERR, "network operation timed out");
- return -1;
+ sp_messagex(ctx, LOG_ERR, "network operation timed out");
+ return ~0;
case -1:
- message(ctx, LOG_ERR, "couldn't select on sockets");
- return -1;
+ sp_message(ctx, LOG_ERR, "couldn't select on sockets");
+ return ~0;
};
/* See what came in */
+ i = 0;
- if(FD_ISSET(ctx->server.fd, &mask))
- {
- *io = &(ctx->server);
- return 0;
- }
+ va_start(ap, ctx);
- if(FD_ISSET(ctx->client.fd, &mask))
+ while((io = va_arg(ap, spio_t*)) != NULL)
{
- *io = &(ctx->client);
- return 0;
+ /* We can't handle more than 31 args */
+ if(i > (sizeof(int) * 8) - 2)
+ break;
+
+ /* Check if the buffer has something in it */
+ if(FD_ISSET(io->fd, &mask))
+ ret |= (1 << i);
+
+ i++;
}
- ASSERT(0 && "invalid result from select");
- return -1;
+ return ret;
}
-int clio_read_line(clamsmtp_context_t* ctx, clio_t* io, int opts)
+int spio_read_line(spctx_t* ctx, spio_t* io, int opts)
{
int l, x;
char* t;
@@ -219,32 +229,32 @@ int clio_read_line(clamsmtp_context_t* ctx, clio_t* io, int opts)
ASSERT(ctx && io);
- if(!clio_valid(io))
+ if(!spio_valid(io))
{
- messagex(ctx, LOG_WARNING, "tried to read from a closed connection");
+ sp_messagex(ctx, LOG_WARNING, "tried to read from a closed connection");
return 0;
}
ctx->line[0] = 0;
t = ctx->line;
- l = LINE_LENGTH - 1;
+ l = SP_LINE_LENGTH - 1;
for(;;)
{
/* refil buffer if necessary */
- if(io->buflen == 0)
+ if(io->_ln == 0)
{
ASSERT(io->fd != -1);
- io->buflen = read(io->fd, io->buf, sizeof(char) * BUF_LEN);
+ io->_ln = read(io->fd, io->_bf, sizeof(char) * SPIO_BUFLEN);
- if(io->buflen == -1)
+ if(io->_ln == -1)
{
- io->buflen = 0;
+ io->_ln = 0;
if(errno == EINTR)
{
/* When the application is quiting */
- if(g_state->quit)
+ if(sp_is_quit())
return -1;
/* For any other signal we go again */
@@ -252,11 +262,11 @@ int clio_read_line(clamsmtp_context_t* ctx, clio_t* io, int opts)
}
if(errno == ECONNRESET) /* Not usually a big deal so supresse the error */
- messagex(ctx, LOG_DEBUG, "connection disconnected by peer: %s", GET_IO_NAME(io));
+ sp_messagex(ctx, LOG_DEBUG, "connection disconnected by peer: %s", GET_IO_NAME(io));
else if(errno == EAGAIN)
- messagex(ctx, LOG_WARNING, "network read operation timed out: %s", GET_IO_NAME(io));
+ sp_messagex(ctx, LOG_WARNING, "network read operation timed out: %s", GET_IO_NAME(io));
else
- message(ctx, LOG_ERR, "couldn't read data from socket: %s", GET_IO_NAME(io));
+ sp_message(ctx, LOG_ERR, "couldn't read data from socket: %s", GET_IO_NAME(io));
/*
* The basic logic here is that if we've had a fatal error
@@ -270,50 +280,50 @@ int clio_read_line(clamsmtp_context_t* ctx, clio_t* io, int opts)
}
/* End of data */
- if(io->buflen == 0)
+ if(io->_ln == 0)
break;
/* Check for a new line */
- p = (unsigned char*)memchr(io->buf, '\n', io->buflen);
+ p = (unsigned char*)memchr(io->_bf, '\n', io->_ln);
if(p != NULL)
{
- x = (p - io->buf) + 1;
- io->buflen -= x;
+ x = (p - io->_bf) + 1;
+ io->_ln -= x;
}
else
{
- x = io->buflen;
- io->buflen = 0;
+ x = io->_ln;
+ io->_ln = 0;
}
if(x > l)
x = l;
/* Copy from buffer line */
- memcpy(t, io->buf, x);
+ memcpy(t, io->_bf, x);
t += x;
l -= x;
/* Move whatever we have in the buffer to the front */
- if(io->buflen > 0)
- memmove(io->buf, io->buf + x, io->buflen);
+ if(io->_ln > 0)
+ memmove(io->_bf, io->_bf + x, io->_ln);
/* Found a new line, done */
if(p != NULL)
break;
/* If discarding then don't break when full */
- if(!(opts && CLIO_DISCARD) && l == 0)
+ if(!(opts && SPIO_DISCARD) && l == 0)
break;
}
- ctx->linelen = (LINE_LENGTH - l) - 1;
- ASSERT(ctx->linelen < LINE_LENGTH);
+ ctx->linelen = (SP_LINE_LENGTH - l) - 1;
+ ASSERT(ctx->linelen < SP_LINE_LENGTH);
ctx->line[ctx->linelen] = 0;
- if(opts & CLIO_TRIM && ctx->linelen > 0)
+ if(opts & SPIO_TRIM && ctx->linelen > 0)
{
t = ctx->line;
@@ -335,28 +345,28 @@ int clio_read_line(clamsmtp_context_t* ctx, clio_t* io, int opts)
}
}
- if(!(opts & CLIO_QUIET))
+ if(!(opts & SPIO_QUIET))
log_io_data(ctx, io, ctx->line, 1);
return ctx->linelen;
}
-int clio_write_data(clamsmtp_context_t* ctx, clio_t* io, const char* data)
+int spio_write_data(spctx_t* ctx, spio_t* io, const char* data)
{
int len = strlen(data);
ASSERT(ctx && io && data);
- if(!clio_valid(io))
+ if(!spio_valid(io))
{
- message(ctx, LOG_ERR, "connection closed. can't write data.");
+ sp_message(ctx, LOG_ERR, "connection closed. can't write data.");
return -1;
}
log_io_data(ctx, io, data, 0);
- return clio_write_data_raw(ctx, io, (unsigned char*)data, len);
+ return spio_write_data_raw(ctx, io, (unsigned char*)data, len);
}
-int clio_write_data_raw(clamsmtp_context_t* ctx, clio_t* io, unsigned char* buf, int len)
+int spio_write_data_raw(spctx_t* ctx, spio_t* io, unsigned char* buf, int len)
{
int r;
@@ -380,7 +390,7 @@ int clio_write_data_raw(clamsmtp_context_t* ctx, clio_t* io, unsigned char* buf,
if(errno == EINTR)
{
/* When the application is quiting */
- if(g_state->quit)
+ if(sp_is_quit())
return -1;
/* For any other signal we go again */
@@ -395,9 +405,9 @@ int clio_write_data_raw(clamsmtp_context_t* ctx, clio_t* io, unsigned char* buf,
close_raw(&(io->fd));
if(errno == EAGAIN)
- messagex(ctx, LOG_WARNING, "network write operation timed out: %s", GET_IO_NAME(io));
+ sp_messagex(ctx, LOG_WARNING, "network write operation timed out: %s", GET_IO_NAME(io));
else
- message(ctx, LOG_ERR, "couldn't write data to socket: %s", GET_IO_NAME(io));
+ sp_message(ctx, LOG_ERR, "couldn't write data to socket: %s", GET_IO_NAME(io));
return -1;
}
@@ -405,3 +415,41 @@ int clio_write_data_raw(clamsmtp_context_t* ctx, clio_t* io, unsigned char* buf,
return 0;
}
+
+void spio_read_junk(spctx_t* ctx, spio_t* io)
+{
+ char buf[16];
+ const char* t;
+ int said = 0;
+ int l;
+
+ ASSERT(ctx);
+ ASSERT(io);
+
+ /* Truncate any data in buffer */
+ io->_ln = 0;
+
+ if(!spio_valid(io))
+ return;
+
+ /* Make it non blocking */
+ fcntl(io->fd, F_SETFL, fcntl(io->fd, F_GETFL, 0) | O_NONBLOCK);
+
+ for(;;)
+ {
+ l = read(io->fd, buf, sizeof(buf) - 1);
+ if(l <= 0)
+ break;
+
+ buf[l] = 0;
+ t = trim_start(buf);
+
+ if(!said && *t)
+ {
+ sp_messagex(ctx, LOG_DEBUG, "received junk data from daemon");
+ said = 1;
+ }
+ }
+
+ fcntl(io->fd, F_SETFL, fcntl(io->fd, F_GETFL, 0) & ~O_NONBLOCK);
+}