From 4e6362c1749f16f1b09fb04d5951a03c1d9aa9cd Mon Sep 17 00:00:00 2001 From: markus schnalke Date: Mon, 9 Nov 2015 22:03:40 +0100 Subject: [PATCH] Add new implementation m_getfld2() This is mainly Philipp Takacs work. --- h/mh.h | 17 ++++++ h/prototypes.h | 1 + sbr/Makefile.in | 2 +- sbr/m_getfld2.c | 177 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 196 insertions(+), 1 deletion(-) create mode 100644 sbr/m_getfld2.c diff --git a/h/mh.h b/h/mh.h index 33b38ee..a93d9a9 100644 --- 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 */ diff --git a/h/prototypes.h b/h/prototypes.h index 8575b22..b48946b 100644 --- a/h/prototypes.h +++ b/h/prototypes.h @@ -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 *); diff --git a/sbr/Makefile.in b/sbr/Makefile.in index 51049c7..981945e 100644 --- a/sbr/Makefile.in +++ b/sbr/Makefile.in @@ -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 index 0000000..6eb0ef8 --- /dev/null +++ b/sbr/m_getfld2.c @@ -0,0 +1,177 @@ +/* +** m_getfld2 -- replacement for m_getfld() +** read an RFC 822 message +*/ + +#define _WITH_GETLINE +#define _POSIX_C_SOURCE 200809L + +#include +#include +#include +#include + + +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); +} -- 1.7.10.4