Hi [2019-08-31 12:16] Philipp Takacs <phil...@bureaucracy.de> > As Markus mentioned in the other mail we plan to implement a wrapper > around m_getfld2(). I have started with one called getfields() and > following interface: > > [...] > > So next step is clean up the error messages a bit. I have only copied > them so they maybe not that good. Test the filter system. then implement > getflieds on all tools.
I have now tested my filter implementation with whom. Today I will work on replacing m_getfld() calls with getfields(). New version is attached. Still based on my pick patch. Philipp
From 710511ce7310e2b850f64243cd8c2c9c0cc41d59 Mon Sep 17 00:00:00 2001 From: Philipp Takacs <phil...@bureaucracy.de> Date: Wed, 28 Aug 2019 16:50:37 +0200 Subject: [PATCH 1/4] add EOH2 to m_getfld2 return if you only intrested in the header you don't need to read the first body line. This is also required for getfields. --- h/mh.h | 1 + sbr/m_getfld2.c | 5 ++++- sbr/readconfig.c | 1 + sbr/seq_read.c | 1 + uip/distsbr.c | 4 ++++ uip/mhbuild.c | 2 ++ uip/mhl.c | 2 ++ uip/mhparse.c | 2 ++ uip/new.c | 1 + uip/pick.c | 4 +++- uip/prompter.c | 2 ++ uip/rcvdist.c | 1 + uip/repl.c | 1 + uip/scansbr.c | 3 ++- uip/slocal.c | 1 + uip/spost.c | 2 ++ uip/whom.c | 1 + 17 files changed, 31 insertions(+), 3 deletions(-) diff --git a/h/mh.h b/h/mh.h index 6337a0ca..1aa58655 100644 --- a/h/mh.h +++ b/h/mh.h @@ -219,6 +219,7 @@ enum state { FMTERR2 = -3, /* Format error in message */ IOERR2 = -1, /* Read error */ FLD2 = 0, /* Header field returned */ + EOH2, /* End of Header */ BODY2, /* Body line returned */ FILEEOF2 /* Reached end of input file */ }; diff --git a/sbr/m_getfld2.c b/sbr/m_getfld2.c index b9a618d1..7cc8689c 100644 --- a/sbr/m_getfld2.c +++ b/sbr/m_getfld2.c @@ -74,7 +74,7 @@ m_getfld2(enum state s, struct field *f, FILE *msg) if (ret == FLD2 && is_separator(tmpline)) { /* header/body separator found */ free(tmpline); - return m_getfld2(BODY2, f, msg); + return EOH2; } f->namelen = copyname(f->name, tmpline); @@ -129,6 +129,9 @@ m_getfld2(enum state s, struct field *f, FILE *msg) free(tmpline); return ret; + case EOH2: + ret = BODY2; + /* FALL */ case BODY2: *f->name = '\0'; f->namelen = 0; diff --git a/sbr/readconfig.c b/sbr/readconfig.c index 91d2b4ed..431530ef 100644 --- a/sbr/readconfig.c +++ b/sbr/readconfig.c @@ -75,6 +75,7 @@ readconfig(struct node **npp, FILE *ib, char *file, int ctx) advise(NULL, "%s is poorly formatted", file); state = FLD2; continue; + case EOH2: case BODY2: adios(EX_CONFIG, NULL, "no blank lines are permitted in %s", file); diff --git a/sbr/seq_read.c b/sbr/seq_read.c index 041f6327..ce56ebca 100644 --- a/sbr/seq_read.c +++ b/sbr/seq_read.c @@ -83,6 +83,7 @@ seq_public(struct msgs *mp) seq_init(mp, mh_xstrdup(f.name), trimcpy(f.value)); continue; + case EOH2: case BODY2: adios(EX_CONFIG, NULL, "no blank lines are permitted in %s", seqfile); diff --git a/uip/distsbr.c b/uip/distsbr.c index 2662c02d..913ade01 100644 --- a/uip/distsbr.c +++ b/uip/distsbr.c @@ -67,6 +67,8 @@ distout(char *drft, char *msgnam, char *backup) fprintf(ofp, "%s: %s", f.name, f.value); break; + case EOH2: + continue; case BODY2: for (dp = f.value; *dp; dp++) { if (!isspace(*dp)) { @@ -171,6 +173,8 @@ ready_msg(char *msgnam) fprintf(ofp, "%s: %s", f.name, f.value); break; + case EOH2: + continue; case BODY2: fclose(ofp); diff --git a/uip/mhbuild.c b/uip/mhbuild.c index a233c685..13dc8510 100644 --- a/uip/mhbuild.c +++ b/uip/mhbuild.c @@ -376,6 +376,8 @@ build_mime(char *infile) continue; + case EOH2: + continue; case BODY2: fseek(in, (long) (-strlen(f.value)), SEEK_CUR); break; diff --git a/uip/mhl.c b/uip/mhl.c index fa83602d..a09cd28b 100644 --- a/uip/mhl.c +++ b/uip/mhl.c @@ -683,6 +683,8 @@ mhlfile(FILE *fp, char *mname, int ofilen, int ofilec) } continue; + case EOH2: + continue; case BODY2: case FILEEOF2: column = 0; diff --git a/uip/mhparse.c b/uip/mhparse.c index 2b72e7bc..2d8e8ead 100644 --- a/uip/mhparse.c +++ b/uip/mhparse.c @@ -275,6 +275,8 @@ get_content(FILE *in, char *file, int toplevel) ct->c_begin = ftell(in) + 1; continue; + case EOH2: + continue; case BODY2: ct->c_begin = ftell(in) - strlen(f.value); break; diff --git a/uip/new.c b/uip/new.c index 21435b34..cd206e18 100644 --- a/uip/new.c +++ b/uip/new.c @@ -137,6 +137,7 @@ get_msgnums(char *folder, char *sequences[]) } continue; + case EOH2: case BODY2: adios(EX_DATAERR, NULL, "no blank lines are permitted in %s", seqfile); /* FALL */ diff --git a/uip/pick.c b/uip/pick.c index 8f28f354..a2a03cfb 100644 --- a/uip/pick.c +++ b/uip/pick.c @@ -865,7 +865,7 @@ pmatches(FILE *fp, int msgnum) nexus_debug(head, 0); } - while (s == FLD2 || s == BODY2) { + while (s == FLD2 || s == BODY2 || s == EOH2) { switch (s = m_getfld2(s, &f, fp)) { case LENERR2: s = FLD2; @@ -873,6 +873,8 @@ pmatches(FILE *fp, int msgnum) case FLD2: nexus_match(&f, msgnum, head); break; + case EOH2: + continue; case BODY2: if (!body) { return head->match; diff --git a/uip/prompter.c b/uip/prompter.c index 7f71e028..c565b2a5 100644 --- a/uip/prompter.c +++ b/uip/prompter.c @@ -185,6 +185,8 @@ abort: } continue; + case EOH2: + continue; case BODY2: case FILEEOF2: fprintf(out, "--------\n"); diff --git a/uip/rcvdist.c b/uip/rcvdist.c index af3fc10d..b89c1906 100644 --- a/uip/rcvdist.c +++ b/uip/rcvdist.c @@ -216,6 +216,7 @@ rcvdistout(FILE *inb, char *form, char *addrs) case LENERR2: case FMTERR2: case IOERR2: + case EOH2: case BODY2: case FILEEOF2: goto finished; diff --git a/uip/repl.c b/uip/repl.c index b2adebfe..d982a8f3 100644 --- a/uip/repl.c +++ b/uip/repl.c @@ -476,6 +476,7 @@ replout(FILE *inb, char *drft, struct msgs *mp, case LENERR2: case FMTERR2: case IOERR2: + case EOH2: case BODY2: case FILEEOF2: goto finished; diff --git a/uip/scansbr.c b/uip/scansbr.c index 48837d76..739bf375 100644 --- a/uip/scansbr.c +++ b/uip/scansbr.c @@ -144,7 +144,8 @@ scan(FILE *inb, int innum, int outnum, char *fmtstr, int width, int curflg, } while ((cptr = cptr->c_next)); } break; - + case EOH2: + continue; case BODY2: compnum = -1; if (scanfolder) { diff --git a/uip/slocal.c b/uip/slocal.c index df0dc7f6..69c7c773 100644 --- a/uip/slocal.c +++ b/uip/slocal.c @@ -794,6 +794,7 @@ parse(int fd) } continue; + case EOH2: case BODY2: case FILEEOF2: break; diff --git a/uip/spost.c b/uip/spost.c index fd0cbcc9..b98687d5 100644 --- a/uip/spost.c +++ b/uip/spost.c @@ -241,6 +241,8 @@ main(int argc, char **argv) putfmt(f.name, f.value, out); continue; + case EOH2: + continue; case BODY2: finish_headers(out); fprintf(out, "\n%s", f.value); diff --git a/uip/whom.c b/uip/whom.c index ef0b684d..5222fc68 100644 --- a/uip/whom.c +++ b/uip/whom.c @@ -232,6 +232,7 @@ process(char *file) proc_hdr(f.name, f.value); continue; + case EOH2: case BODY2: case FILEEOF2: break; -- 2.20.1
From 09dfda7195fa22687ed95ae31d25bce41727997c Mon Sep 17 00:00:00 2001 From: Philipp Takacs <phil...@bureaucracy.de> Date: Wed, 28 Aug 2019 16:53:12 +0200 Subject: [PATCH 2/4] add getfliedlds not finished --- h/prototypes.h | 1 + sbr/Makefile.in | 2 +- sbr/getfields.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++ sbr/utils.c | 13 +++++++++ 4 files changed, 85 insertions(+), 1 deletion(-) create mode 100644 sbr/getfields.c diff --git a/h/prototypes.h b/h/prototypes.h index fad1af4f..63c03459 100644 --- a/h/prototypes.h +++ b/h/prototypes.h @@ -54,6 +54,7 @@ int gans(char *, struct swit *); char **getans(char *, struct swit *); int getanswer(char *); char **getarguments(char *, int, char **, int); +ssize_t getfields(FILE **, struct field **, size_t *, const char *, const char * const *); char *get_charset(); char *getcurfol(void); char *getdeffol(void); diff --git a/sbr/Makefile.in b/sbr/Makefile.in index f2310fb8..7e772332 100644 --- a/sbr/Makefile.in +++ b/sbr/Makefile.in @@ -56,7 +56,7 @@ SRCS = addrsbr.c ambigsw.c brkstring.c \ error.c execprog.c ext_hook.c folder_addmsg.c folder_delmsgs.c \ folder_free.c folder_read.c \ folder_realloc.c gans.c getans.c getanswer.c \ - getarguments.c \ + getarguments.c getfields.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_getfld2.c m_gmprot.c \ diff --git a/sbr/getfields.c b/sbr/getfields.c new file mode 100644 index 00000000..43f1ebd0 --- /dev/null +++ b/sbr/getfields.c @@ -0,0 +1,70 @@ +#include <h/mh.h> +#include <h/utils.h> +#include <stdio.h> +#include <sysexits.h> + +static boolean use_name(const char * const *filter, const char *name) +{ + size_t i; + + if (!filter) { + return TRUE; + } + for (i = 0; filter[i]; i++) { + if (strcasecmp(filter[i], name)==0) { + return TRUE; + } + } + return FALSE; +} + +ssize_t getfields(FILE **file, struct field **fields, size_t *n, const char *filename, const char * const * filter) +{ + enum state s = FLD2; + size_t i = 0; + + if (!*file) { + *file = fopen(filename, "r"); + } + if (!*file) { + return -1; + } + if (!(*fields && *n > 0)) { + *fields = mh_xcalloc(32, sizeof(**fields)); + *n = 32; + } + + while (s == FLD2) { + if (i >= *n) { + *fields = mh_xrealloc(*fields, 2*(*n)*sizeof(**fields)); + *n = 2*(*n); + } + (*fields)[i].value = NULL; + (*fields)[i].alloclen = 0; + switch (s = m_getfld2(s, (*fields)+i, *file)) { + case LENERR2: + s = FLD2; + /* FALL */ + case FLD2: + if (!use_name(filter, (*fields)[i].name)) { + mh_free0(&(*fields)[i].value); + (*fields)[i].alloclen = 0; + break; + } + i++; + break; + case FILEEOF2: + case EOH2: + return i; + case FMTERR2: + advise(NULL, "Format error in message"); + return -1; + case IOERR2: + advise(NULL, "IOERROR"); + return -1; + default: + adios(EX_SOFTWARE, "m_getfld2", "returned unknown state %d at message %d", s, filename); + } + } + return i; +} diff --git a/sbr/utils.c b/sbr/utils.c index 50060ae7..4e8dce7f 100644 --- a/sbr/utils.c +++ b/sbr/utils.c @@ -76,6 +76,19 @@ mh_free0(void * ptr) *p = NULL; } +/* +** Free a array of Fields and set it to NULL +*/ +void +fieldsfree(struct fields **f, size_t n) +{ + size_t i; + for (i = 0; i < n; i++) { + free((*f)[i].value); + } + mh_free0(f); +} + /* ** Return the present working directory, if the current directory does not ** exist, or is too long, make / the pwd. -- 2.20.1
From e11224e4b2eec3b3f7480675eceb4c371dbbf762 Mon Sep 17 00:00:00 2001 From: Philipp Takacs <phil...@bureaucracy.de> Date: Sat, 31 Aug 2019 10:59:00 +0200 Subject: [PATCH 3/4] use getfields in uip/pick.c --- uip/pick.c | 52 +++++++++++++++++++++++++--------------------------- 1 file changed, 25 insertions(+), 27 deletions(-) diff --git a/uip/pick.c b/uip/pick.c index a2a03cfb..af893bd0 100644 --- a/uip/pick.c +++ b/uip/pick.c @@ -853,9 +853,13 @@ static void nexus_clear(struct nexus *n) static int pmatches(FILE *fp, int msgnum) { - struct field f = {{0}}; - enum state s = FLD2; - + static struct field *fields = NULL; + static size_t alloc = 0; + ssize_t field_n; + size_t i; + enum state s; + char tmp[BUFSIZ]; + snprintf(tmp, BUFSIZ-1, "%d", msgnum); if (!head) return 1; @@ -865,31 +869,25 @@ pmatches(FILE *fp, int msgnum) nexus_debug(head, 0); } - while (s == FLD2 || s == BODY2 || s == EOH2) { - switch (s = m_getfld2(s, &f, fp)) { - case LENERR2: - s = FLD2; - /* FALL */ - case FLD2: - nexus_match(&f, msgnum, head); - break; - case EOH2: - continue; - case BODY2: - if (!body) { - return head->match; - } - nexus_match(&f, msgnum, head); - break; - case IOERR2: - advise(NULL, "IOERR in message %d\n", msgnum); - return FALSE; - case FILEEOF2: - break; - default: - adios(EX_SOFTWARE, "m_getfld2", "returned unknown state %d at message %d", s, msgnum); - } + field_n = getfields(&fp, &fields, &alloc, tmp, NULL); + + if (field_n < 0) { + advise("getfields", "returned -1 at message %d", s, msgnum); + return FALSE; + } + + for (i = 0; i < field_n; i++) { + nexus_match(fields+i, msgnum, head); + } + s = feof(fp) ? FILEEOF2 : BODY2; + if (!body) { + mh_free0(&fields); + return head->match; + } + while (m_getfld2(s, fields, fp) == BODY2) { + nexus_match(fields, msgnum, head); } + mh_free0(&fields); return head->match; } -- 2.20.1
From 0387baa6c524002a252beae8304589bf19c876d6 Mon Sep 17 00:00:00 2001 From: Philipp Takacs <phil...@bureaucracy.de> Date: Sun, 8 Sep 2019 01:23:34 +0200 Subject: [PATCH 4/4] use getfields in whom --- test/tests/whom/multible-files | 16 +++++++++ uip/whom.c | 64 +++++++++++++--------------------- 2 files changed, 41 insertions(+), 39 deletions(-) create mode 100644 test/tests/whom/multible-files diff --git a/test/tests/whom/multible-files b/test/tests/whom/multible-files new file mode 100644 index 00000000..079f37be --- /dev/null +++ b/test/tests/whom/multible-files @@ -0,0 +1,16 @@ +# test whom + +. "$MH_TEST_COMMON" + +runandcheck 'whom a' <<! +u...@example.com +u...@example.com +u...@example.com +u...@example.com +u...@example.com +u...@example.com +u...@example.com +u...@example.com +u...@example.com +u...@example.com +! diff --git a/uip/whom.c b/uip/whom.c index 5222fc68..f8cd4028 100644 --- a/uip/whom.c +++ b/uip/whom.c @@ -60,12 +60,22 @@ static int alisw = 1; /* expand aliases on rcpt addrs */ static char *dccsep = "\t==DCC=="; static char *bccsep = "\t==BCC=="; - +static const char * const fields[] = { + "to", + "cc", + "bcc", + "dcc", + "resent-to", + "resent-cc", + "resent-bcc", + "resent-dcc", + NULL, +}; /* ** static prototypes */ -static int process(char *); +static void process(char *); static void proc_hdr(char *, char *); static int print(void); static int printdcc(void); @@ -210,48 +220,24 @@ main(int argc, char **argv) } -static int +static void process(char *file) { - enum state state; - struct field f = {{0}}; - int compnum; - FILE *in; + FILE *in = NULL; + static struct field *f = NULL; + static size_t alloc = 0; + ssize_t num; + size_t i; - - if ((in = fopen(file, "r")) == NULL) { - adios(EX_IOERR, file, "unable to open"); + num = getfields(&in, &f, &alloc, file, fields); + fclose(in); + if (num < 0) { + advise("getflieds", "Can not process mail %s", file); + return; } - - for (compnum=1, state=FLD2;; compnum++) { - switch (state = m_getfld2(state, &f, in)) { - case LENERR2: - state = FLD2; - /* FALL */ - case FLD2: - proc_hdr(f.name, f.value); - continue; - - case EOH2: - case BODY2: - case FILEEOF2: - break; - - case FMTERR2: - advise(NULL, "message format error in component #%d", compnum); - continue; - - case IOERR2: - adios(EX_DATAERR, NULL, "message format error in component #%d", - compnum); - - default: - adios(EX_SOFTWARE, NULL, "getfld() returned %d", state); - } - break; + for (i = 0; i < num; i++) { + proc_hdr(f[i].name, f[i].value); } - fclose(in); - return 0; } -- 2.20.1