From: Jon Steinhart Date: Fri, 23 Aug 2002 20:37:01 +0000 (+0000) Subject: Added external program hooks. X-Git-Tag: RELEASE_1_2~115 X-Git-Url: http://git.marmaro.de/?a=commitdiff_plain;h=a259594cc41e41bfbb90562d3977b8194d1446f5;p=mmh Added external program hooks. --- diff --git a/docs/README-ATTACHMENTS b/docs/README-ATTACHMENTS index ff9db2a..a996364 100644 --- a/docs/README-ATTACHMENTS +++ b/docs/README-ATTACHMENTS @@ -1,3 +1,5 @@ +$Id$ + Jon Steinhart's (jon@fourwinds.com) Attachment Handling Mods ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/docs/README-HOOKS b/docs/README-HOOKS new file mode 100644 index 0000000..bb5d6ee --- /dev/null +++ b/docs/README-HOOKS @@ -0,0 +1,111 @@ +$Id$ + +Jon Steinhart's (jon@fourwinds.com) External Program Hooks +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This blurb describes a changes to nmh that implement an interface +to external programs. This interface is different than the limited +interface provided by things like the rmmproc context entry. + + +Why Did I Do This? +~~~~~~~~~~~~~~~~~~ + +I'm working on a project (grokmail) that will get released via GPL sometime +soon. This project keeps a database synchronized with the messages in the +mail system. New functionality is built on top of this database. This +functionality allows fast searching, and searching based on interest +criteria. The latter can be used for spam filtering. + +The changes to nmh allow external programs to be run whenever a message is +added to a folder, removed from a folder, or refiled. The changes are +implemented in a general way so that it can be used for other purposes than +mine. + +What Are The Changes? +~~~~~~~~~~~~~~~~~~~~~ + +The changes add four new profile components: + +add-hook: This is the full pathname of a program that is invoked + whenever a message is added to a folder. The program + is passed one argument which is the full pathname of the + message file. The program is executed after the message + is written so that it can act upon that message. + +del-hook: This is the full pathname of a program that is invoked + whenever a message is deleted from a folder. The program + is passed one argument which is the full pathname of the + message file. The program is executed before the message + is written so that it can act upon that message. + +ref-hook: This is the full pathname of a program that is invoked + whenever a message is refiled. The program is passed two + arguments: the first is the full pathname of the original + message file, the second is the full pathname of the final + message file. The program is executed after the message + is written. + +msg-hook: This is a text message that is output if the execution of + one of the external hook programs fails. There is a built-in + default message if none is specified. + +The definition of refiling is a bit tricky. The refile hook is executed if a +message is moved from one place to another. So, for example, the command + + refile -link + +causes the add hook to be executed, not the refile hook, because a new message +is created, the old one isn't moved. + +These changes affect the following commands: + +burst: The add hook is executed for messages burst from a digest, and + for the table of contents if -inplace is specified. The delete + hook is executed for the original message if -inplace is + specified. The refile hook is executed for messages that are + moved. + +folder: The refile hook is executed for -pack. + +inc: The add hook is executed when messages are incorporated. + +refile: Either the add or refile hooks are executed. + +rmf: The delete hook is executed when messages are deleted. + +rmm: The delete hook is executed when messages are deleted. + +sortm: The refile hook is executed for each message moved. Note that + a magic temporary message number of 2147483647 is used to hold + messages as they are being shuffled. + + + +Did I Do This Correctly? +~~~~~~~~~~~~~~~~~~~~~~~~ + +Well, sort of. This all works, but I'm not really happy with it. The issue +is that an examination of the nmh code shows that message handling is scattered +all over the place. Although there are library routines such as folder_addmsg +and folder_delmsgs, they are not used consistently. Long term, I think that it +would be better to make all message handling go through the same choke points. + +Also, I added a function to run the external programs. This sort of stuff is +also scattered around the nmh code, for example in the code to run the rmmproc. +Again, I'd like to make this more consistent in the long term. + +What Files Did I Change? +~~~~~~~~~~~~~~~~~~~~~~~~ +uip/ + burst.c + inc.c + refile.c + rmf.c + sortm.c + +sbr/ + folder_addmsg.c + folder_delmsgs.c + folder_pack.c + ext_hook.c (new file) diff --git a/h/prototypes.h b/h/prototypes.h index 63ea87e..1b815bc 100644 --- a/h/prototypes.h +++ b/h/prototypes.h @@ -49,9 +49,10 @@ void cpydgst (int, int, char *, char *); int decode_rfc2047 (char *, char *); void discard (FILE *); int done (int); +int ext_hook(char *, char *, char *); int fdcompare (int, int); -int folder_addmsg (struct msgs **, char *, int, int, int); -int folder_delmsgs (struct msgs *, int); +int folder_addmsg (struct msgs **, char *, int, int, int, int); +int folder_delmsgs (struct msgs *, int, int); void folder_free (struct msgs *); int folder_pack (struct msgs **, int); struct msgs *folder_read (char *); diff --git a/sbr/Makefile.in b/sbr/Makefile.in index 882094e..b27b126 100644 --- a/sbr/Makefile.in +++ b/sbr/Makefile.in @@ -57,7 +57,7 @@ SRCS = add.c addrsbr.c ambigsw.c atooi.c brkstring.c \ context_find.c context_foil.c context_read.c \ context_replace.c context_save.c copy.c \ copyip.c cpydata.c cpydgst.c discard.c done.c dtime.c dtimep.c \ - error.c fdcompare.c folder_addmsg.c folder_delmsgs.c \ + error.c ext_hook.o fdcompare.c folder_addmsg.c folder_delmsgs.c \ folder_free.c folder_pack.c folder_read.c \ folder_realloc.c gans.c getans.c getanswer.c \ getarguments.c getcpy.c getfolder.c getpass.c \ diff --git a/sbr/folder_addmsg.c b/sbr/folder_addmsg.c index 16f4cc5..b3bc891 100644 --- a/sbr/folder_addmsg.c +++ b/sbr/folder_addmsg.c @@ -20,10 +20,12 @@ int folder_addmsg (struct msgs **mpp, char *msgfile, int selected, - int unseen, int preserve) + int unseen, int preserve, int deleting) { int infd, outfd, linkerr, first_time, msgnum; char *nmsg, newmsg[BUFSIZ]; + char oldmsg[BUFSIZ]; + struct msgs *op; struct msgs *mp; struct stat st1, st2; @@ -132,9 +134,23 @@ folder_addmsg (struct msgs **mpp, char *msgfile, int selected, snprintf (newmsg, sizeof(newmsg), "%s/%s", mp->foldpath, nmsg); /* - * Now try to link message into folder + * Now try to link message into folder. + * Then run the external hook on the message if one was specified in the context. + * Run the refile hook if we're moving the message from one place to another. + * We have to construct the from path name for this because it's not there. + * Run the add hook if the message is getting copied or lined somewhere else. */ if (link (msgfile, newmsg) != -1) { + + if (deleting) { + op = folder_read(getfolder(1)); + (void)snprintf(oldmsg, sizeof (oldmsg), "%s/%s", op->foldpath, msgfile); + folder_free(op); + (void)ext_hook("ref-hook", oldmsg, newmsg); + } + else + (void)ext_hook("add-hook", newmsg, (char *)0); + return msgnum; } else { linkerr = errno; @@ -183,6 +199,12 @@ folder_addmsg (struct msgs **mpp, char *msgfile, int selected, cpydata (infd, outfd, msgfile, newmsg); close (infd); close (outfd); + + if (deleting) + (void)ext_hook("ref-hook", newmsg, msgfile); + else + (void)ext_hook("add-hook", newmsg, (char *)0); + return msgnum; } } diff --git a/sbr/folder_delmsgs.c b/sbr/folder_delmsgs.c index 3d2e549..4567f6d 100644 --- a/sbr/folder_delmsgs.c +++ b/sbr/folder_delmsgs.c @@ -22,11 +22,12 @@ */ int -folder_delmsgs (struct msgs *mp, int unlink_msgs) +folder_delmsgs (struct msgs *mp, int unlink_msgs, int nohook) { pid_t pid; int msgnum, vecp, retval = 0; char buf[100], *dp, **vec; + char msgpath[BUFSIZ]; /* * If "rmmproc" is defined, exec it to remove messages. @@ -83,6 +84,19 @@ folder_delmsgs (struct msgs *mp, int unlink_msgs) unset_selected (mp, msgnum); mp->numsel--; + /* + * Run the external hook on the message if one was specified in the context. + * All we have is the message number; we have changed to the directory + * containing the message. So, we need to extract that directory to form + * the complete path. Note that the caller knows the directory, but has + * no way of passing that to us. + */ + + if (!nohook) { + (void)snprintf(msgpath, sizeof (msgpath), "%s/%d", getcwd(msgpath, sizeof (msgpath)), msgnum); + (void)ext_hook("del-hook", msgpath, (char *)0); + } + dp = m_name (msgnum); if (unlink_msgs) { diff --git a/sbr/folder_pack.c b/sbr/folder_pack.c index 7a661a5..bebc145 100644 --- a/sbr/folder_pack.c +++ b/sbr/folder_pack.c @@ -59,6 +59,14 @@ folder_pack (struct msgs **mpp, int verbose) return -1; } + /* + * Invoke the external refile hook for each message being renamed. + */ + + (void)snprintf(oldmsg, sizeof (oldmsg), "%s/%d", mp->foldpath, msgnum); + (void)snprintf(newmsg, sizeof (newmsg), "%s/%d", mp->foldpath, hole); + ext_hook("ref-hook", oldmsg, newmsg); + /* check if this is the current message */ if (msgnum == mp->curmsg) newcurrent = hole; diff --git a/sbr/m_convert.c b/sbr/m_convert.c index 8acfb1a..bbefc99 100644 --- a/sbr/m_convert.c +++ b/sbr/m_convert.c @@ -225,7 +225,7 @@ single: /* * Convert the various message names to - * there numeric value. + * their numeric values. * * n (integer) * prev diff --git a/uip/burst.c b/uip/burst.c index 6b9be83..908de0d 100644 --- a/uip/burst.c +++ b/uip/burst.c @@ -42,7 +42,7 @@ struct smsg { * static prototypes */ static int find_delim (int, struct smsg *); -static void burst (struct msgs **, int, struct smsg *, int, int, int); +static void burst (struct msgs **, int, struct smsg *, int, int, int, char *); static void cpybrst (FILE *, FILE *, char *, char *, int); @@ -156,7 +156,7 @@ main (int argc, char **argv) if (verbosw) printf ("%d message%s exploded from digest %d\n", numburst, numburst > 1 ? "s" : "", msgnum); - burst (&mp, msgnum, smsgs, numburst, inplace, verbosw); + burst (&mp, msgnum, smsgs, numburst, inplace, verbosw, maildir); } else { if (numburst == 0) { if (!quietsw) @@ -256,7 +256,7 @@ find_delim (int msgnum, struct smsg *smsgs) static void burst (struct msgs **mpp, int msgnum, struct smsg *smsgs, int numburst, - int inplace, int verbosw) + int inplace, int verbosw, char *maildir) { int i, j, mode; char *msgnam; @@ -296,6 +296,9 @@ burst (struct msgs **mpp, int msgnum, struct smsg *smsgs, int numburst, * If -inplace is given, renumber the messages after the * source message, to make room for each of the messages * contained within the digest. + * + * This is equivalent to refiling a message from the point + * of view of the external hooks. */ if (inplace) { for (i = mp->hghmsg; j > msgnum; i--, j--) { @@ -307,6 +310,11 @@ burst (struct msgs **mpp, int msgnum, struct smsg *smsgs, int numburst, if (rename (f2, f1) == NOTOK) admonish (f1, "unable to rename %s to", f2); + + (void)snprintf(f1, sizeof (f1), "%s/%d", maildir, i); + (void)snprintf(f2, sizeof (f2), "%s/%d", maildir, j); + ext_hook("ref-hook", f1, f2); + copy_msg_flags (mp, i, j); clear_msg_flags (mp, j); mp->msgflags |= SEQMOD; @@ -316,7 +324,25 @@ burst (struct msgs **mpp, int msgnum, struct smsg *smsgs, int numburst, unset_selected (mp, msgnum); - /* new hghmsg is hghmsg + numburst */ + /* new hghmsg is hghmsg + numburst + * + * At this point, there is an array of numburst smsgs, each element of + * which contains the starting and stopping offsets (seeks) of the message + * in the digest. The inplace flag is set if the original digest is replaced + * by a message containing the table of contents. smsgs[0] is that table of + * contents. Go through the message numbers in reverse order (high to low). + * + * Set f1 to the name of the destination message, f2 to the name of a scratch + * file. Extract a message from the digest to the scratch file. Move the + * original message to a backup file if the destination message number is the + * same as the number of the original message, which only happens if the + * inplace flag is set. Then move the scratch file to the destination message. + * + * Moving the original message to the backup file is equivalent to deleting the + * message from the point of view of the external hooks. And bursting each + * message is equivalent to adding a new message. + */ + i = inplace ? msgnum + numburst : mp->hghmsg; for (j = numburst; j >= (inplace ? 0 : 1); i--, j--) { strncpy (f1, m_name (i), sizeof(f1)); @@ -336,9 +362,16 @@ burst (struct msgs **mpp, int msgnum, struct smsg *smsgs, int numburst, strncpy (f3, m_backup (f1), sizeof(f3)); if (rename (f1, f3) == NOTOK) admonish (f3, "unable to rename %s to", f1); + + (void)snprintf(f3, sizeof (f3), "%s/%d", maildir, i); + ext_hook("del-hook", f3, (char *)0); } if (rename (f2, f1) == NOTOK) admonish (f1, "unable to rename %s to", f2); + + (void)snprintf(f3, sizeof (f3), "%s/%d", maildir, i); + ext_hook("add-hook", f3, (char *)0); + copy_msg_flags (mp, i, msgnum); mp->msgflags |= SEQMOD; } diff --git a/uip/inc.c b/uip/inc.c index 7886411..ec4f520 100644 --- a/uip/inc.c +++ b/uip/inc.c @@ -245,6 +245,7 @@ main (int argc, char **argv) struct msgs *mp; struct stat st, s1; FILE *aud = NULL; + char b[MAXPATHLEN + 1]; #ifdef POP int nmsgs, nbytes, p = 0; @@ -802,7 +803,6 @@ go_to_it: /* link message into folder */ newmsg = folder_addmsg(mp, tmpfilenam); #endif - /* create scanline for new message */ switch (i = scan (in, msgnum + 1, msgnum + 1, nfs, width, msgnum == hghnum && chgflag, 1, NULL, 0L, noisy)) { @@ -826,6 +826,13 @@ go_to_it: case SCNMSG: case SCNENC: + /* + * Run the external program hook on the message. + */ + + (void)snprintf(b, sizeof (b), "%s/%d", maildir, msgnum + 1); + (void)ext_hook("add-hook", b, (char *)0); + if (aud) fputs (scanl, aud); #ifdef MHE diff --git a/uip/mhstoresbr.c b/uip/mhstoresbr.c index d91b7b4..2e88df2 100644 --- a/uip/mhstoresbr.c +++ b/uip/mhstoresbr.c @@ -921,7 +921,7 @@ output_content_folder (char *folder, char *filename) /* Read the folder. */ if ((mp = folder_read (folder))) { /* Link file into folder */ - msgnum = folder_addmsg (&mp, filename, 0, 0, 0); + msgnum = folder_addmsg (&mp, filename, 0, 0, 0, 0); } else { advise (NULL, "unable to read folder %s", folder); return NOTOK; diff --git a/uip/rcvstore.c b/uip/rcvstore.c index ca8789f..8f6a6f8 100644 --- a/uip/rcvstore.c +++ b/uip/rcvstore.c @@ -203,7 +203,7 @@ main (int argc, char **argv) * Link message into folder, and possibly add * to the Unseen-Sequence's. */ - if ((msgnum = folder_addmsg (&mp, tmpfilenam, 0, unseensw, 0)) == -1) + if ((msgnum = folder_addmsg (&mp, tmpfilenam, 0, unseensw, 0, 0)) == -1) done (1); /* diff --git a/uip/refile.c b/uip/refile.c index 9e1ed20..663092b 100644 --- a/uip/refile.c +++ b/uip/refile.c @@ -66,7 +66,7 @@ struct st_fold { static void opnfolds (struct st_fold *, int); static void clsfolds (struct st_fold *, int); static void remove_files (int, char **); -static int m_file (char *, struct st_fold *, int, int); +static int m_file (char *, struct st_fold *, int, int, int); int @@ -213,7 +213,7 @@ main (int argc, char **argv) adios (NULL, "use -file or some messages, not both"); opnfolds (folders, foldp); for (i = 0; i < filep; i++) - if (m_file (files[i], folders, foldp, preserve)) + if (m_file (files[i], folders, foldp, preserve, 0)) done (1); /* If -nolink, then "remove" files */ if (!linkf) @@ -247,11 +247,16 @@ main (int argc, char **argv) /* create folder structures for each destination folder */ opnfolds (folders, foldp); - /* Link all the selected messages into destination folders */ + /* Link all the selected messages into destination folders. + * + * This causes the add hook to be run for messages that are + * linked into another folder. The refile hook is run for + * messages that are moved to another folder. + */ for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) { if (is_selected (mp, msgnum)) { cp = getcpy (m_name (msgnum)); - if (m_file (cp, folders, foldp, preserve)) + if (m_file (cp, folders, foldp, preserve, !linkf)) done (1); free (cp); } @@ -269,9 +274,13 @@ main (int argc, char **argv) fflush (stdout); } - /* If -nolink, then "remove" messages from source folder */ + /* If -nolink, then "remove" messages from source folder. + * + * Note that folder_delmsgs does not call the delete hook + * because the message has already been handled above. + */ if (!linkf) { - folder_delmsgs (mp, unlink_msgs); + folder_delmsgs (mp, unlink_msgs, 1); } clsfolds (folders, foldp); @@ -387,13 +396,13 @@ remove_files (int filep, char **files) */ static int -m_file (char *msgfile, struct st_fold *folders, int nfolders, int preserve) +m_file (char *msgfile, struct st_fold *folders, int nfolders, int preserve, int refile) { int msgnum; struct st_fold *fp, *ep; for (fp = folders, ep = folders + nfolders; fp < ep; fp++) { - if ((msgnum = folder_addmsg (&fp->f_mp, msgfile, 1, 0, preserve)) == -1) + if ((msgnum = folder_addmsg (&fp->f_mp, msgfile, 1, 0, preserve, nfolders == 1 && refile)) == -1) return 1; } return 0; diff --git a/uip/rmf.c b/uip/rmf.c index fccbb09..2909196 100644 --- a/uip/rmf.c +++ b/uip/rmf.c @@ -152,6 +152,12 @@ rmf (char *folder) adios (NULL, "unable to read folder +%s", folder); others = 0; + /* + * Run the external delete hook program. + */ + + (void)ext_hook("del-hook", maildir, (char *)0); + j = strlen(BACKUP_PREFIX); while ((dp = readdir (dd))) { switch (dp->d_name[0]) { diff --git a/uip/rmm.c b/uip/rmm.c index a18c278..072097a 100644 --- a/uip/rmm.c +++ b/uip/rmm.c @@ -145,7 +145,7 @@ main (int argc, char **argv) } /* "remove" the SELECTED messages */ - folder_delmsgs (mp, unlink_msgs); + folder_delmsgs (mp, unlink_msgs, 0); seq_save (mp); /* synchronize message sequences */ context_replace (pfolder, folder); /* update current folder */ diff --git a/uip/sortm.c b/uip/sortm.c index 4b348cf..5cff943 100644 --- a/uip/sortm.c +++ b/uip/sortm.c @@ -232,7 +232,7 @@ main (int argc, char **argv) if (verbose) { /* announce what we're doing */ if (subjsort) - printf ("sorting by %s-major %s-minor\n", + printf ("sorting by %s-major %s-minor\n", submajor ? subjsort : datesw, submajor ? datesw : subjsort); else @@ -240,7 +240,7 @@ main (int argc, char **argv) } /* first sort by date, or by subject-major, date-minor */ - qsort ((char *) dlist, nmsgs, sizeof(*dlist), + qsort ((char *) dlist, nmsgs, sizeof(*dlist), (qsort_comp) (submajor && subjsort ? txtsort : dsort)); /* @@ -292,7 +292,7 @@ main (int argc, char **argv) */ while (*s && (*s)->s_subj[0] && strcmp((*s)->s_subj, s[-1]->s_subj) == 0 && - (datelimit == 0 || + (datelimit == 0 || (*s)->s_clock - s[-1]->s_clock <= datelimit)) { il[(*s)->s_msg] = 0; *fp++ = *s++; @@ -303,6 +303,12 @@ main (int argc, char **argv) free (dlist); dlist = flist; } + + /* + * At this point, dlist is a sorted array of pointers to smsg structures, + * each of which contains a message number. + */ + rename_msgs (mp, dlist); context_replace (pfolder, folder); /* update current folder */ @@ -312,7 +318,7 @@ main (int argc, char **argv) return done (0); } -static int +static int read_hdrs (struct msgs *mp, char *datesw) { int msgnum; @@ -431,7 +437,7 @@ get_fields (char *datesw, int msg, struct smsg *smsg) /* * try to make the subject "canonical": delete * leading "re:", everything but letters & smash - * letters to lower case. + * letters to lower case. */ register char *cp, *cp2, c; @@ -472,7 +478,7 @@ get_fields (char *datesw, int msg, struct smsg *smsg) /* * sort on dates. */ -static int +static int dsort (struct smsg **a, struct smsg **b) { if ((*a)->s_clock < (*b)->s_clock) @@ -488,7 +494,7 @@ dsort (struct smsg **a, struct smsg **b) /* * sort on subjects. */ -static int +static int subsort (struct smsg **a, struct smsg **b) { register int i; @@ -499,7 +505,7 @@ subsort (struct smsg **a, struct smsg **b) return (dsort (a, b)); } -static int +static int txtsort (struct smsg **a, struct smsg **b) { register int i; @@ -517,6 +523,7 @@ rename_chain (struct msgs *mp, struct smsg **mlist, int msg, int endmsg) { int nxt, old, new; char *newname, oldname[BUFSIZ]; + char newbuf[MAXPATHLEN + 1]; for (;;) { nxt = mlist[msg] - smsgs; /* mlist[msg] is a ptr into smsgs */ @@ -531,11 +538,15 @@ rename_chain (struct msgs *mp, struct smsg **mlist, int msg, int endmsg) if (rename (oldname, newname) == NOTOK) adios (newname, "unable to rename %s to", oldname); + (void)snprintf(oldname, sizeof (oldname), "%s/%d", mp->foldpath, old); + (void)snprintf(newbuf, sizeof (newbuf), "%s/%d", mp->foldpath, new); + ext_hook("ref-hook", oldname, newbuf); + copy_msg_flags (mp, new, old); if (mp->curmsg == old) seq_setcur (mp, new); - if (nxt == endmsg) + if (nxt == endmsg) break; msg = nxt; @@ -550,12 +561,13 @@ rename_msgs (struct msgs *mp, struct smsg **mlist) int i, j, old, new; seqset_t tmpset; char f1[BUFSIZ], tmpfil[BUFSIZ]; + char newbuf[MAXPATHLEN + 1]; struct smsg *sp; strncpy (tmpfil, m_name (mp->hghmsg + 1), sizeof(tmpfil)); for (i = 0; i < nmsgs; i++) { - if (! (sp = mlist[i])) + if (! (sp = mlist[i])) continue; /* did this one */ j = sp - smsgs; @@ -576,12 +588,31 @@ rename_msgs (struct msgs *mp, struct smsg **mlist) if (rename (f1, tmpfil) == NOTOK) adios (tmpfil, "unable to rename %s to ", f1); + + /* + * Run the external hook to refile the old message as message + * number 2147483647. This is our way of making a temporary + * message number. I don't really like this. + */ + + (void)snprintf(f1, sizeof (f1), "%s/%d", mp->foldpath, old); + (void)snprintf(newbuf, sizeof (newbuf), "%s/2147483647", mp->foldpath); + ext_hook("ref-hook", f1, newbuf); + get_msg_flags (mp, &tmpset, old); rename_chain (mp, mlist, j, i); if (rename (tmpfil, m_name(new)) == NOTOK) adios (m_name(new), "unable to rename %s to", tmpfil); + /* + * Run the external hook to refile the temorary message number + * to the real place. + */ + + (void)snprintf(f1, sizeof (f1), "%s/%d", mp->foldpath, new); + ext_hook("ref-hook", newbuf, f1); + set_msg_flags (mp, &tmpset, new); mp->msgflags |= SEQMOD; }