From: Simon Schubert <2@0x2c.org> Date: Wed, 30 Jun 2010 22:00:39 +0000 (+0200) Subject: read_remote: rewrite for better readability X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8a6f2a491fe161e65202455be8fb97e3b1c11299;p=people%2Fms%2Fdma.git read_remote: rewrite for better readability --- diff --git a/net.c b/net.c index 3d4f5d7..79f5a2b 100644 --- a/net.c +++ b/net.c @@ -46,6 +46,7 @@ #include #include +#include #include #include #include @@ -56,7 +57,6 @@ #include "dma.h" -static jmp_buf timeout_alarm; char neterr[BUF_SIZE]; char * @@ -71,13 +71,6 @@ ssl_errstr(void) 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, ...) { @@ -127,26 +120,25 @@ int 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)) { @@ -155,18 +147,22 @@ read_remote(int fd, int extbufsize, char *extbuf) 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 @@ -174,8 +170,7 @@ read_remote(int fd, int extbufsize, char *extbuf) * 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; @@ -183,32 +178,68 @@ read_remote(int fd, int extbufsize, char *extbuf) 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); } /*