make m_getfld2() called with an error state a noop
[mmh] / sbr / m_getfld2.c
index 5920425..970a3f0 100644 (file)
@@ -23,11 +23,22 @@ enum threestate {
 */
 static enum threestate is_falted(FILE *);
 static size_t copyname(char *, char *);
+static int is_separator(char *);
 
 
 /*
-** For the states FLD2, BODY2 and FMTERR2 memory is allocated for f->value.
-** For the states LENERR2, IOERR2 and FILEEOF2 no memory is allocated.
+** FLD2:       We read a (complete) header field
+** BODY2:      We read a body line
+** LENERR2:    Line is too long (>998, as defined by RFC 822)
+** FMTERR2:    Header field invalid
+** IOERR2:     Failure to read
+** FILEEOF2:   We're at the end of the file
+**
+** f->name is only filled in FLD2.
+**
+** In FLD2, f->value contains the field's (complete) value only;
+** in BODY2, LENERR2 and FMTERR2 f->value contains the whole line;
+** in IOERR2 and FILEEOF2 f->value is not set.
 */
 enum state
 m_getfld2(enum state s, struct field *f, FILE *msg)
@@ -37,25 +48,29 @@ m_getfld2(enum state s, struct field *f, FILE *msg)
        ssize_t nchars;
        enum threestate falted;
 
-       nchars = getline(&tmpline, &len, msg);
-       if (nchars == -1) {
-               if (feof(msg)) {
-                       return FILEEOF2;
-               } else {
-                       return IOERR2;
+       switch (s) {
+       case FLD2:
+               nchars = getline(&tmpline, &len, msg);
+               if (nchars < 1) {
+                       if (feof(msg)) {
+                               return FILEEOF2;
+                       } else {
+                               return IOERR2;
+                       }
                }
-       }
 
-       if (nchars >= NAMESZ) {
-               free(tmpline);
-               return LENERR2;
-       }
+               *f->name = '\0';
+               f->namelen = 0;
 
-       *f->name = '\0';
-       f->namelen = 0;
+               if (nchars >= NAMESZ) {
+                       if (f->value) {
+                               free(f->value);
+                       }
+                       f->value = tmpline;
+                       f->valuelen = nchars;
+                       return LENERR2;
+               }
 
-       switch (s) {
-       case FLD2:
                if (*(tmpline + nchars - 1) != '\n') {
                        if (f->value) {
                                free(f->value);
@@ -66,7 +81,7 @@ m_getfld2(enum state s, struct field *f, FILE *msg)
                        return FMTERR2;
                }
 
-               if (nchars > 0 && (*tmpline == '\n' || *tmpline == '-')) {
+               if (is_separator(tmpline)) {
                        /* header/body separator found */
                        free(tmpline);
                        return m_getfld2(BODY2, f, msg);
@@ -99,7 +114,11 @@ m_getfld2(enum state s, struct field *f, FILE *msg)
                        }
 
                        if (nchars >= NAMESZ) {
-                               free(tmpline);
+                               if (f->value) {
+                                       free(f->value);
+                               }
+                               f->value = tmpline;
+                               f->valuelen = nchars;
                                return LENERR2;
                        }
 
@@ -132,6 +151,26 @@ m_getfld2(enum state s, struct field *f, FILE *msg)
                return FLD2;
 
        case BODY2:
+               nchars = getline(&tmpline, &len, msg);
+               if (nchars < 1) {
+                       if (feof(msg)) {
+                               return FILEEOF2;
+                       } else {
+                               return IOERR2;
+                       }
+               }
+
+               *f->name = '\0';
+               f->namelen = 0;
+
+               if (nchars >= NAMESZ) {
+                       if (f->value) {
+                               free(f->value);
+                       }
+                       f->value = tmpline;
+                       f->valuelen = nchars;
+                       return LENERR2;
+               }
                if (f->value) {
                        free(f->value);
                }
@@ -197,3 +236,19 @@ copyname(char *dst, char *src)
 
        return strlen(dst);
 }
+
+static int
+is_separator(char *line)
+{
+       /*
+       ** In MH, lines that are consists of dashes only are
+       ** separators as well ... not so in RFC 822.
+       */
+       while (*line == '-') {
+               line++;
+       }
+       if (strcmp("\n", line)==0) {
+               return 1;
+       }
+       return 0;
+}