#include <openssl/ssl.h>
#include <openssl/err.h>
+#include <ctype.h>
#include <err.h>
#include <errno.h>
#include <netdb.h>
#include "dma.h"
-static jmp_buf timeout_alarm;
char neterr[BUF_SIZE];
char *
return (ERR_error_string(oerr, NULL));
}
-static void
-sig_alarm(int signo)
-{
- (void)signo; /* so that gcc doesn't complain */
- longjmp(timeout_alarm, 1);
-}
-
ssize_t
send_remote_command(int fd, const char* fmt, ...)
{
read_remote(int fd, int extbufsize, char *extbuf)
{
ssize_t rlen = 0;
- size_t pos, len;
+ size_t pos, len, copysize;
char buff[BUF_SIZE];
- int done = 0, status = 0, extbufpos = 0;
+ int done = 0, status = 0, status_running = 0, extbufpos = 0;
+ enum { parse_status, parse_spacedash, parse_rest } parsestate;
- if (signal(SIGALRM, sig_alarm) == SIG_ERR) {
- snprintf(neterr, sizeof(neterr), "SIGALRM error: %s",
- strerror(errno));
- return (-1);
- }
- if (setjmp(timeout_alarm) != 0) {
+ if (do_timeout(CON_TIMEOUT, 1) != 0) {
snprintf(neterr, sizeof(neterr), "Timeout reached");
return (-1);
}
- alarm(CON_TIMEOUT);
/*
* Remote reading code from femail.c written by Henning Brauer of
* OpenBSD and released under a BSD style license.
*/
- for (len = pos = 0; !done; ) {
+ len = 0;
+ pos = 0;
+ parsestate = parse_status;
+ neterr[0] = 0;
+ while (!(done && parsestate == parse_status)) {
rlen = 0;
if (pos == 0 ||
(pos > 0 && memchr(buff + pos, '\n', len - pos) == NULL)) {
pos = 0;
if (((config.features & SECURETRANS) != 0) &&
(config.features & NOSSL) == 0) {
- if ((rlen = SSL_read(config.ssl, buff + len,
- sizeof(buff) - len)) == -1) {
+ if ((rlen = SSL_read(config.ssl, buff + len, sizeof(buff) - len)) == -1) {
strncpy(neterr, ssl_errstr(), sizeof(neterr));
- return (-1);
+ goto error;
}
} else {
if ((rlen = read(fd, buff + len, sizeof(buff) - len)) == -1) {
strncpy(neterr, strerror(errno), sizeof(neterr));
- return (-1);
+ goto error;
}
}
len += rlen;
+
+ copysize = sizeof(neterr) - strlen(neterr) - 1;
+ if (copysize > len)
+ copysize = len;
+ strncat(neterr, buff, copysize);
}
/*
* If there is an external buffer with a size bigger than zero
* there are new characters read from the mailserver
* copy them to the external buffer
*/
- if (extbufpos <= (extbufsize - 1) && rlen && extbufsize > 0
- && extbuf != NULL) {
+ if (extbufpos <= (extbufsize - 1) && rlen > 0 && extbufsize > 0 && extbuf != NULL) {
/* do not write over the bounds of the buffer */
if(extbufpos + rlen > (extbufsize - 1)) {
rlen = extbufsize - extbufpos;
memcpy(extbuf + extbufpos, buff + len - rlen, rlen);
extbufpos += rlen;
}
- for (; pos < len && buff[pos] >= '0' && buff[pos] <= '9'; pos++)
- ; /* Do nothing */
if (pos == len)
- return (0);
+ continue;
+
+ switch (parsestate) {
+ case parse_status:
+ for (; pos < len; pos++) {
+ if (isdigit(buff[pos])) {
+ status_running = status_running * 10 + (buff[pos] - '0');
+ } else {
+ status = status_running;
+ status_running = 0;
+ parsestate = parse_spacedash;
+ break;
+ }
+ }
+ continue;
+
+ case parse_spacedash:
+ switch (buff[pos]) {
+ case ' ':
+ done = 1;
+ break;
+
+ case '-':
+ /* ignore */
+ /* XXX read capabilities */
+ break;
+
+ default:
+ strcpy(neterr, "invalid syntax in reply from server");
+ goto error;
+ }
- if (buff[pos] == ' ') {
- done = 1;
- } else if (buff[pos] != '-') {
- strcpy(neterr, "invalid syntax in reply from server");
- return (-1);
+ pos++;
+ parsestate = parse_rest;
+ continue;
+
+ case parse_rest:
+ /* skip up to \n */
+ for (; pos < len; pos++) {
+ if (buff[pos] == '\n') {
+ pos++;
+ parsestate = parse_status;
+ break;
+ }
+ }
}
- /* skip up to \n */
- for (; pos < len && buff[pos - 1] != '\n'; pos++)
- ; /* Do nothing */
-
}
- alarm(0);
- buff[len] = '\0';
- while (len > 0 && (buff[len - 1] == '\r' || buff[len - 1] == '\n'))
- buff[--len] = '\0';
- snprintf(neterr, sizeof(neterr), "%s", buff);
- status = atoi(buff);
+ do_timeout(0, 0);
+
+ /* chop off trailing newlines */
+ while (neterr[0] != 0 && strchr("\r\n", neterr[strlen(neterr) - 1]) != 0)
+ neterr[strlen(neterr) - 1] = 0;
+
return (status/100);
+
+error:
+ do_timeout(0, 0);
+ return (-1);
}
/*