]> git.ipfire.org Git - people/ms/dma.git/commitdiff
read_remote: rewrite for better readability
authorSimon Schubert <2@0x2c.org>
Wed, 30 Jun 2010 22:00:39 +0000 (00:00 +0200)
committerSimon Schubert <2@0x2c.org>
Wed, 30 Jun 2010 22:39:25 +0000 (00:39 +0200)
net.c

diff --git a/net.c b/net.c
index 3d4f5d7fecaa3a9404e1527c1cfaf49e201d938c..79f5a2bffc4e079b920935b84fe426893e095f52 100644 (file)
--- a/net.c
+++ b/net.c
@@ -46,6 +46,7 @@
 #include <openssl/ssl.h>
 #include <openssl/err.h>
 
+#include <ctype.h>
 #include <err.h>
 #include <errno.h>
 #include <netdb.h>
@@ -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);
 }
 
 /*