Add new implementation m_getfld2()
authormarkus schnalke <meillo@marmaro.de>
Mon, 9 Nov 2015 21:03:40 +0000 (22:03 +0100)
committermarkus schnalke <meillo@marmaro.de>
Mon, 9 Nov 2015 21:03:40 +0000 (22:03 +0100)
This is mainly Philipp Takacs work.

h/mh.h
h/prototypes.h
sbr/Makefile.in
sbr/m_getfld2.c [new file with mode: 0644]

diff --git a/h/mh.h b/h/mh.h
index 33b38ee..a93d9a9 100644 (file)
--- a/h/mh.h
+++ b/h/mh.h
@@ -203,6 +203,23 @@ struct msgs {
                            ** terminating NULL.
                            */
 
+struct field {
+       char name[NAMESZ];
+       size_t namelen;
+       char *value;
+       size_t valuelen;
+       size_t alloclen;
+};
+
+enum state {
+       LENERR2 = -2,
+       FMTERR2 = -3,
+       ERR2 = -1,
+       FLD2 = 0,
+       BODY2,
+       FILEEOF2,
+};
+
 #define LENERR   (-2)      /* Name too long error from getfld  */
 #define FMTERR   (-3)      /* Message Format error             */
 #define FLD      0         /* Field returned                   */
index 8575b22..b48946b 100644 (file)
@@ -67,6 +67,7 @@ char *m_backup(char *);
 int m_convert(struct msgs *, char *);
 char *m_draft(char *);
 int m_getfld(int, unsigned char *, unsigned char *, int, FILE *);
+enum state m_getfld2(enum state, struct field *, FILE *);
 int m_gmprot(void);
 char *m_name(int);
 int m_putenv(char *, char *);
index 51049c7..981945e 100644 (file)
@@ -57,7 +57,7 @@ SRCS = addrsbr.c ambigsw.c brkstring.c  \
        getarguments.c getcpy.c \
        fmt_addr.c fmt_compile.c fmt_new.c fmt_rfc2047.c  \
        fmt_scan.c lock_file.c m_atoi.c \
-       m_convert.c m_draft.c m_getfld.c m_gmprot.c  \
+       m_convert.c m_draft.c m_getfld.c m_getfld2.c m_gmprot.c  \
        m_name.c \
        makedir.c mts.c norm_charmap.c  \
        path.c pidwait.c pidstatus.c  \
diff --git a/sbr/m_getfld2.c b/sbr/m_getfld2.c
new file mode 100644 (file)
index 0000000..6eb0ef8
--- /dev/null
@@ -0,0 +1,177 @@
+/*
+** m_getfld2 -- replacement for m_getfld()
+**              read an RFC 822 message
+*/
+
+#define _WITH_GETLINE
+#define _POSIX_C_SOURCE 200809L
+
+#include <h/mh.h>
+#include <h/utils.h>
+#include <stdio.h>
+#include <ctype.h>
+
+
+enum threestate {
+       B_TRUE = 1,
+       B_FALSE = 0,
+       FAIL = -1,
+};
+
+/*
+** static prototypes
+*/
+static enum threestate is_falted(FILE *);
+static size_t copyname(char *, char *);
+
+
+/*
+** For the states FLD2, BODY2 memory is allocated for f->value.
+** For the states LENERR2, FMTERR2, ERR2 and FILEEOF2 no memory is allocated.
+*/
+enum state
+m_getfld2(enum state s, struct field *f, FILE *msg)
+{
+       char *tmpline = NULL;
+       size_t len = 0;
+       ssize_t nchars;
+       enum threestate falted;
+
+       nchars = getline(&tmpline, &len, msg);
+       if (nchars == -1) {
+               if (feof(msg)) {
+                       return FILEEOF2;
+               } else {
+                       return ERR2;
+               }
+       }
+
+       if (nchars >= NAMESZ) {
+               free(tmpline);
+               return LENERR2;
+       }
+
+       switch (s) {
+       case FLD2:
+               if (*(tmpline + nchars - 1) != '\n') {
+                       free(tmpline);
+                       return FMTERR2;
+               }
+
+               if (nchars > 0 && (*tmpline == '\n' || *tmpline == '-')) {
+                       /* header/body separator found */
+                       free(tmpline);
+                       return m_getfld2(BODY2, f, msg);
+               }
+
+               f->namelen = copyname(f->name, tmpline);
+               if (f->namelen < 1) {
+                       free(tmpline);
+                       return FMTERR2;
+               }
+
+               /* copy the field's value */
+               if (f->alloclen <= nchars - f->namelen) {
+                       f->value = mh_xrealloc(f->value, f->alloclen + len);
+                       f->alloclen += len;
+               }
+               strcpy(f->value, tmpline + f->namelen + 1);
+               f->valuelen = nchars - f->namelen - 1;
+
+               while ((falted = is_falted(msg)) == B_TRUE) {
+                       nchars = getline(&tmpline, &len, msg);
+                       if (nchars <= 0) {
+                               free(tmpline);
+                               return ERR2;
+                       }
+
+                       if (nchars >= NAMESZ) {
+                               free(tmpline);
+                               return LENERR2;
+                       }
+
+                       if (*(tmpline + nchars - 1) != '\n') {
+                               free(tmpline);
+                               return FMTERR2;
+                       }
+
+                       if (f->alloclen - f->valuelen <= nchars) {
+                               f->value = mh_xrealloc(f->value,
+                                               f->alloclen + len);
+                               f->alloclen += len;
+                       }
+                       strcpy(f->value + f->valuelen, tmpline);
+                       f->valuelen += nchars;
+
+               }
+
+               if (falted == FAIL) {
+                       free(tmpline);
+                       return ERR2;
+               }
+
+               free(tmpline);
+               return FLD2;
+
+       case BODY2:
+               *f->name = '\0';
+               f->namelen = 0;
+               if (f->value) {
+                       free(f->value);
+               }
+               f->value = tmpline;
+               f->valuelen = nchars;
+               f->alloclen = len;
+               return BODY2;
+
+       default:
+               /* give error states back as received */
+               return s;
+       }
+}
+
+static enum threestate
+is_falted(FILE *msg)
+{
+       enum threestate ret;
+       int c;
+
+       if ((c = getc(msg)) < 0) {
+               if (feof(msg)) {
+                       clearerr(msg);
+                       return B_FALSE;
+               } else {
+                       return FAIL;
+               }
+       }
+       if (isblank(c)) {
+               ret = B_TRUE;
+       } else {
+               ret = B_FALSE;
+       }
+       if (ungetc(c, msg) != c) {
+               return FAIL;
+       }
+       return ret;
+}
+
+static size_t
+copyname(char *dst, char *src)
+{
+       size_t len;
+       char *sep = strchr(src, ':');
+
+       if (!sep) {
+               return 0;
+       }
+
+       len = sep - src;
+       if (len >= NAMESZ) {
+               return 0;
+       }
+
+       src[len] = '\0';
+       strcpy(dst, src);
+
+       return strlen(dst);
+}