From 2fe9dbf53e97d3aeb0653947cdc0b515e79b454e Mon Sep 17 00:00:00 2001 From: "Steffen (Daode) Nurpmeso" Date: Thu, 6 Jul 2017 16:51:21 +0200 Subject: [PATCH] FIX [62358d22] (More `alternates' processing: a 2nd "pure"..run).. Bummer! On a fuzzy afternoon [62358d22] (More `alternates' processing: a 2nd "pure", non-extended run) added more stripping but for one counts non-`alternate's as if they were `alternate's, and second does not terminate the tail of a newly relinked list! What a terrible mess! The approach as such was brain damaged. Instead simply mark all messages which refer to an `alternate' in order to finally (!) remove all such marked messages (instead of possibly one). That shall be it. --- cc-test.sh | 16 ++++----- nail.h | 57 +++++++++++++++---------------- nam-a-grp.c | 110 ++++++++++++++++++++++++++---------------------------------- 3 files changed, 82 insertions(+), 101 deletions(-) diff --git a/cc-test.sh b/cc-test.sh index 559ea3e2..60915284 100755 --- a/cc-test.sh +++ b/cc-test.sh @@ -2806,10 +2806,6 @@ t_behave_compose_hooks() { # TODO monster: "tests" also `alternates', at least read ver echo t_ocs call t_header - if [ "$t_remove" != "" ] - echo "~^ header insert to -"; read es;\ - call xerr "$es" "reinstantiate of a To:" - end call t_attach } define t_oce { @@ -2852,7 +2848,7 @@ t_behave_compose_hooks() { # TODO monster: "tests" also `alternates', at least } wysh set on-compose-splice=t_ocs \ on-compose-enter=t_oce on-compose-leave=t_ocl \ - on-compose-cleanup=t_occ + on-compose-cleanup=t_occ __EOT__ # @@ -2863,15 +2859,15 @@ __EOT__ -X'source ./.trc' -Smta=./.tsendmail.sh \ >./.tall 2>&1 ${cat} ./.tall >> "${MBOX}" - check behave:compose_hooks-1 0 "${MBOX}" '207648214 10083' + check behave:compose_hooks-1 0 "${MBOX}" '3667291468 10101' ${rm} -f "${MBOX}" - printf 'm -\nbody\n!.\n' | + printf 'm this-goes@nowhere\nbody\n!.\n' | ${MAILX} ${ARGS} -Snomemdebug -Sescape=! -Sstealthmua=noagent \ -St_remove=1 -X'source ./.trc' -Smta=./.tsendmail.sh \ - > "${MBOX}" 2>./.terr - ${cat} ./.terr >> "${MBOX}" - check behave:compose_hooks-2 0 "${MBOX}" '217089054 12397' + >./.tall 2>&1 + ${cat} ./.tall >> "${MBOX}" + check behave:compose_hooks-2 0 "${MBOX}" '1746765053 12535' # Some state machine stress, shell compose hook, localopts for hook, etc. # readctl in child. ~r as HERE document diff --git a/nail.h b/nail.h index 3d286a10..3a5ebab0 100644 --- a/nail.h +++ b/nail.h @@ -2381,31 +2381,32 @@ struct header { /* Handling of namelist nodes used in processing the recipients of mail and * aliases, inspection of mail-addresses and all that kind of stuff */ enum nameflags { - NAME_NAME_SALLOC = 1<< 0, /* .n_name is doped */ - NAME_FULLNAME_SALLOC = 1<< 1, /* .n_fullname is doped */ - NAME_SKINNED = 1<< 2, /* Is actually skin()ned */ - NAME_IDNA = 1<< 3, /* IDNA was applied */ - - NAME_ADDRSPEC_CHECKED = 1<< 4, /* Address has been .. and */ - NAME_ADDRSPEC_ISFILE = 1<< 5, /* ..is a file path */ - NAME_ADDRSPEC_ISPIPE = 1<< 6, /* ..is a command for piping */ + NAME_NAME_SALLOC = 1u<<0, /* .n_name is doped */ + NAME_FULLNAME_SALLOC = 1u<<1, /* .n_fullname is doped */ + NAME_SKINNED = 1u<<2, /* Is actually skin()ned */ + NAME_IDNA = 1u<<3, /* IDNA was applied */ + + NAME_ADDRSPEC_CHECKED = 1u<<4, /* Address has been .. and */ + NAME_ADDRSPEC_ISFILE = 1u<<5, /* ..is a file path */ + NAME_ADDRSPEC_ISPIPE = 1u<<6, /* ..is a command for piping */ NAME_ADDRSPEC_ISFILEORPIPE = NAME_ADDRSPEC_ISFILE | NAME_ADDRSPEC_ISPIPE, - NAME_ADDRSPEC_ISNAME = 1<< 7, /* ..is an alias name */ - NAME_ADDRSPEC_ISADDR = 1<< 8, /* ..is a mail network address */ - - NAME_ADDRSPEC_ERR_EMPTY = 1<< 9, /* An empty string (or NULL) */ - NAME_ADDRSPEC_ERR_ATSEQ = 1<<10, /* Weird @ sequence */ - NAME_ADDRSPEC_ERR_CHAR = 1<<11, /* Invalid character */ - NAME_ADDRSPEC_ERR_IDNA = 1<<12, /* IDNA convertion failed */ - NAME_ADDRSPEC_ERR_NAME = 1<<13, /* Alias with invalid content */ - NAME_ADDRSPEC_INVALID = NAME_ADDRSPEC_ERR_EMPTY | + NAME_ADDRSPEC_ISNAME = 1u<<7, /* ..is an alias name */ + NAME_ADDRSPEC_ISADDR = 1u<<8, /* ..is a mail network address */ + + NAME_ADDRSPEC_ERR_EMPTY = 1u<<9, /* An empty string (or NULL) */ + NAME_ADDRSPEC_ERR_ATSEQ = 1u<<10, /* Weird @ sequence */ + NAME_ADDRSPEC_ERR_CHAR = 1u<<11, /* Invalid character */ + NAME_ADDRSPEC_ERR_IDNA = 1u<<12, /* IDNA convertion failed */ + NAME_ADDRSPEC_ERR_NAME = 1u<<13, /* Alias with invalid content */ + NAME_ADDRSPEC_INVALID = NAME_ADDRSPEC_ERR_EMPTY | NAME_ADDRSPEC_ERR_ATSEQ | NAME_ADDRSPEC_ERR_CHAR | NAME_ADDRSPEC_ERR_IDNA | NAME_ADDRSPEC_ERR_NAME, /* Error storage (we must fit in 31-bit) */ - _NAME_SHIFTWC = 14, - _NAME_MAXWC = 0x1FFFF, - _NAME_MASKWC = _NAME_MAXWC << _NAME_SHIFTWC + _NAME_SHIFTWC = 14, + _NAME_MAXWC = 0x1FFFF, + _NAME_MASKWC = _NAME_MAXWC << _NAME_SHIFTWC + /* Bit 31 (32) == SI32_MIN temporarily used */ }; /* In the !_ERR_EMPTY case, the failing character can be queried */ @@ -2417,14 +2418,14 @@ do {\ (E) | (((unsigned int)(WC) & _NAME_MAXWC) << _NAME_SHIFTWC);\ } while (0) -struct name { - struct name *n_flink; /* Forward link in list. */ - struct name *n_blink; /* Backward list link */ - enum gfield n_type; /* From which list it came */ - enum nameflags n_flags; /* enum nameflags */ - char *n_name; /* This fella's address */ - char *n_fullname; /* Ditto, unless GFULL including comment */ - char *n_fullextra; /* GFULL, without address */ +struct name{ + struct name *n_flink; /* Forward link in list. */ + struct name *n_blink; /* Backward list link */ + enum gfield n_type; /* From which list it came */ + ui32_t n_flags; /* enum nameflags */ + char *n_name; /* This fella's address */ + char *n_fullname; /* Ditto, unless GFULL including comment */ + char *n_fullextra; /* GFULL, without address */ }; struct n_addrguts{ diff --git a/nam-a-grp.c b/nam-a-grp.c index 9a914287..f9aedffe 100644 --- a/nam-a-grp.c +++ b/nam-a-grp.c @@ -159,9 +159,8 @@ static struct group *_filetype_heads[HSHSIZE]; /* Same name, while taking care for *allnet*? */ static bool_t a_nag_is_same_name(char const *n1, char const *n2); -/* Delete the given name from a namelist, unless keep_single and only one */ -static struct name *a_nag_namelist_del_cp(struct name *np, char const *name, - bool_t keep_single); +/* Mark all nodes with the given name */ +static struct name *a_nag_namelist_mark_name(struct name *np, char const *name); /* Grab a single name (liberal name) */ static char const * yankname(char const *ap, char *wbuf, @@ -254,23 +253,15 @@ a_nag_is_same_name(char const *n1, char const *n2){ } static struct name * -a_nag_namelist_del_cp(struct name *np, char const *name, bool_t keep_single){ +a_nag_namelist_mark_name(struct name *np, char const *name){ struct name *p; NYD2_ENTER; for(p = np; p != NULL; p = p->n_flink) - if(a_nag_is_same_name(p->n_name, name)){ - if(keep_single && np == p && np->n_flink == NULL) - break; - if(p->n_blink == NULL){ - if((np = p->n_flink) != NULL) - np->n_blink = NULL; - }else if(p->n_flink == NULL) - p->n_blink->n_flink = NULL; - else{ - p->n_blink->n_flink = p->n_flink; - p->n_flink->n_blink = p->n_blink; - } + if(!(p->n_type & GDEL) && !(p->n_flags & (ui32_t)SI32_MIN) && + a_nag_is_same_name(p->n_name, name)){ + p->n_flags |= (ui32_t)SI32_MIN; + break; } NYD2_LEAVE; return np; @@ -1441,9 +1432,9 @@ elide(struct name *names) np = names; ++i; } - if(nlist == NULL || i == 1) goto jleave; + np->n_flink = NULL; /* Create a temporay array and sort that */ nparr = n_lofi_alloc(sizeof(*nparr) * i); @@ -1568,67 +1559,60 @@ c_alternates(void *v){ /* TODO use a hashmap!! */ FL struct name * n_alternates_remove(struct name *np, bool_t keep_single){ - struct name *xp; + struct name *xp, *newnp; NYD_ENTER; - /* Throw away all deleted nodes: we may not allow to remove a lonely - * addressee if that matches an alternate, so ensure we do not need to - * fiddle around with GDEL; _namelist_del_cp() will fully del, too */ - /* C99 */{ - struct name *newnp; - - for(xp = newnp = NULL; np != NULL; np = np->n_flink) - if(!(np->n_type & GDEL)){ - np->n_blink = xp; - if(xp != NULL) - xp->n_flink = np; - else - newnp = np; - xp = np; - } - np = newnp; - } + /* Delete the temporary bit from all */ + for(xp = np; xp != NULL; xp = xp->n_flink) + xp->n_flags &= ~(ui32_t)SI32_MIN; - if(np == NULL) - goto jleave; - if(keep_single && np->n_flink == NULL) - goto jleave; + /* Mark all possible alternate names (xxx sic) */ if(a_nag_altnames != NULL){ struct n_strlist *slp; - for(slp = a_nag_altnames; slp != NULL; slp = slp->sl_next){ - np = a_nag_namelist_del_cp(np, slp->sl_dat, keep_single); - if(np == NULL || (keep_single && np->n_flink == NULL)) - goto jleave; - } + for(slp = a_nag_altnames; slp != NULL; slp = slp->sl_next) + np = a_nag_namelist_mark_name(np, slp->sl_dat); } - np = a_nag_namelist_del_cp(np, ok_vlook(LOGNAME), keep_single); - if(np == NULL || (keep_single && np->n_flink == NULL)) - goto jleave; + np = a_nag_namelist_mark_name(np, ok_vlook(LOGNAME)); for(xp = lextract(ok_vlook(from), GEXTRA | GSKIN); xp != NULL; - xp = xp->n_flink){ - np = a_nag_namelist_del_cp(np, xp->n_name, keep_single); - if(np == NULL || (keep_single && np->n_flink == NULL)) - goto jleave; - } + xp = xp->n_flink) + np = a_nag_namelist_mark_name(np, xp->n_name); for(xp = extract(ok_vlook(sender), GEXTRA | GSKIN); xp != NULL; - xp = xp->n_flink){ - np = a_nag_namelist_del_cp(np, xp->n_name, keep_single); - if(np == NULL || (keep_single && np->n_flink == NULL)) - goto jleave; - } + xp = xp->n_flink) + np = a_nag_namelist_mark_name(np, xp->n_name); for(xp = lextract(ok_vlook(replyto), GEXTRA | GSKIN); xp != NULL; - xp = xp->n_flink){ - np = a_nag_namelist_del_cp(np, xp->n_name, keep_single); - if(np == NULL || (keep_single && np->n_flink == NULL)) - goto jleave; - } -jleave: + xp = xp->n_flink) + np = a_nag_namelist_mark_name(np, xp->n_name); + + /* GDEL all (but a single) marked node(s) */ + for(xp = np; xp != NULL; xp = xp->n_flink) + if(xp->n_flags & (ui32_t)SI32_MIN){ + if(!keep_single) + xp->n_type |= GDEL; + keep_single = FAL0; + } + + /* Clean the list by throwing away all deleted nodes */ + for(xp = newnp = NULL; np != NULL; np = np->n_flink) + if(!(np->n_type & GDEL)){ + np->n_blink = xp; + if(xp != NULL) + xp->n_flink = np; + else + newnp = np; + xp = np; + } + np = newnp; + + /* Delete the temporary bit from all remaining (again) */ + for(xp = np; xp != NULL; xp = xp->n_flink) + xp->n_flags &= ~(ui32_t)SI32_MIN; + NYD_LEAVE; return np; } -- 2.11.4.GIT