Finally, some support for mh-format when using forw(1). Still needs some
authorKen Hornstein <kenh@pobox.com>
Sun, 26 Feb 2012 05:09:52 +0000 (00:09 -0500)
committerKen Hornstein <kenh@pobox.com>
Sun, 26 Feb 2012 05:09:52 +0000 (00:09 -0500)
tests.

Makefile.am
etc/digestcomps
etc/forwcomps
h/prototypes.h
h/utils.h
sbr/utils.c
uip/comp.c
uip/forw.c
uip/forwsbr.c [new file with mode: 0755]

index 2d3342b..a219981 100644 (file)
@@ -145,6 +145,9 @@ dist_sysconf_DATA = etc/MailAliases etc/components etc/digestcomps \
 ##
 sysconf_DATA = etc/mhn.defaults etc/mts.conf
 
+##
+## Documentation that gets installed in docdir
+##
 dist_doc_DATA = COPYRIGHT VERSION docs/COMPLETION-BASH docs/COMPLETION-TCSH \
                docs/COMPLETION-ZSH docs/DIFFERENCES docs/FAQ \
                docs/MAIL.FILTERING docs/MAILING-LISTS docs/README-ATTACHMENTS \
@@ -223,7 +226,7 @@ uip_flist_SOURCES = uip/flist.c
 uip_folder_SOURCES = uip/folder.c
 
 uip_forw_SOURCES = uip/forw.c uip/whatnowproc.c uip/whatnowsbr.c uip/sendsbr.c \
-                  uip/annosbr.c uip/distsbr.c
+                  uip/annosbr.c uip/distsbr.c uip/forwsbr.c
 uip_forw_LDADD = $(LDADD) $(ICONVLIB)
 
 uip_inc_SOURCES = uip/inc.c uip/scansbr.c uip/dropsbr.c uip/termsbr.c \
@@ -547,6 +550,7 @@ rpm: dist
 cscope:
        echo "-I $(srcdir)/h -I $(srcdir)/sbr -I $(srcdir)/uip -I $(srcdir)/mts/smtp" > cscope.files
        find $(srcdir) \( -name \*.c -o -name \*.l \) -print | grep -v dtimep.c >> cscope.files
+.PHONY: cscope
 
 ##
 ## Rules to upload the distribution to savannah
index 7f5036d..fdb55f8 100644 (file)
@@ -3,7 +3,7 @@ To:       %{digest} Distribution: dist-%{digest};
 Subject:  %{digest} Digest V%(cur) #%(msg)
 Reply-To: %{digest}
 --------
-%{digest} Digest       %(weekday{date}), %2(mday{date}) %(month{date}) %(year{date})
+%{digest} Digest       %(weekday{nmh-date}), %2(mday{nmh-date}) %(month{nmh-date}) %(year{nmh-date})
                Volume %(cur) : Issue %(msg)
 
 Today's Topics:
index 7f255ea..fdfb23b 100644 (file)
@@ -1,5 +1,6 @@
-To:
-cc:
-Fcc: +outbox
-Subject:
+%<{nmh-from}%|%(void(localmbox))%>%(void(width))%(putaddr From: )
+%<{nmh-to}%(void(width))%(putaddr To: )%|To:%>
+%<{nmh-cc}%(void(width))%(putaddr cc: )%|cc:%>
+Fcc: %<{fcc}%(putstr)%|+outbox%>
+Subject:%<{nmh-subject} %(trim)%(putlit)%?{subject} %(trim)%(putlit) (fwd)%>
 --------
index 11db40d..ad9a87e 100644 (file)
@@ -146,6 +146,8 @@ void annopreserve(int);
 int distout (char *, char *, char *);
 void replout (FILE *, char *, char *, struct msgs *, int,
        int, char *, char *, char *);
+int build_form (char *, char *, int *, char *, char *, char *, char *,
+               char *, char *);
 int sendsbr (char **, int, char *, struct stat *, int, char *, int);
 int what_now (char *, int, int, char *, char *,
        int, struct msgs *, char *, int, char *);
index b9660a5..8142b2c 100644 (file)
--- a/h/utils.h
+++ b/h/utils.h
@@ -7,6 +7,7 @@ void *mh_xmalloc(size_t);
 void *mh_xrealloc(void *, size_t);
 char *pwd(void);
 char *add(char *, char *);
+char *addlist(char *, char *);
 int folder_exists(char *);
 void create_folder(char *, int, void (*)(int));
 int num_digits(int);
index 48969ab..cce7378 100644 (file)
@@ -123,6 +123,19 @@ add (char *s2, char *s1)
 }
 
 /*
+ * addlist
+ *     Append an item to a comma separated list
+ */
+char *
+addlist (char *list, char *item)
+{
+    if (list)
+       list = add (", ", list);
+
+    return add (item, list);
+}
+
+/*
  * folder_exists
  *      Check to see if a folder exists.
  */
index c8189d1..111a219 100644 (file)
@@ -79,12 +79,6 @@ static struct swit aqrul[] = {
     { NULL, 0 }
 };
 
-/*
- * Add an item to a comma seperated list
- */
-
-static char *addlist(char *, char *); 
-
 int
 main (int argc, char **argv)
 {
@@ -416,16 +410,3 @@ edit_it:
     done (1);
     return 1;
 }
-
-/*
- * Append an item to a comma separated list
- */
-
-static char *
-addlist (char *list, char *item)
-{
-    if (list)
-       list = add (", ", list);
-
-    return add (item, list);
-}
index 112b083..3c3e4f6 100644 (file)
@@ -9,7 +9,6 @@
 
 #include <h/mh.h>
 #include <fcntl.h>
-#include <h/fmt_scan.h>
 #include <h/tws.h>
 #include <h/utils.h>
 
@@ -70,7 +69,18 @@ static struct swit switches[] = {
     { "file file", 4 },                        /* interface from msh */
 #define        BILDSW                25
     { "build", 5 },                    /* interface from mhe */
-
+#define FROMSW                26
+    { "from address", 0 },
+#define TOSW                  27
+    { "to address", 0 },
+#define CCSW                  28
+    { "cc address", 0 },
+#define SUBJECTSW             29
+    { "subject text", 0 },
+#define FCCSW                 30
+    { "fcc mailbox", 0 },
+#define WIDTHSW               31
+    { "width columns", 0 },
     { NULL, 0 }
 };
 
@@ -112,7 +122,6 @@ static struct msgs *mp = NULL;              /* used a lot */
 static void mhl_draft (int, char *, int, int, char *, char *, int);
 static void copy_draft (int, char *, char *, int, int, int);
 static void copy_mime_draft (int);
-static int build_form (char *, char *, int, int);
 
 
 int
@@ -122,9 +131,12 @@ main (int argc, char **argv)
     int issue = 0, volume = 0, dashstuff = 0;
     int nedit = 0, nwhat = 0, i, in;
     int out, isdf = 0, msgnum;
+    int outputlinelen = OUTPUTLINELEN;
+    int dat[5];
     char *cp, *cwd, *maildir, *dfolder = NULL;
     char *dmsg = NULL, *digest = NULL, *ed = NULL;
-    char *file = NULL, *filter = NULL, *folder = NULL;
+    char *file = NULL, *filter = NULL, *folder = NULL, *fwdmsg = NULL;
+    char *from = NULL, *to = NULL, *cc = NULL, *subject = NULL, *fcc = NULL;
     char *form = NULL, buf[BUFSIZ], value[10];
     char **argp, **arguments, *msgs[MAXARGS];
     struct stat st;
@@ -228,8 +240,9 @@ main (int argc, char **argv)
                    continue;
 
                case DGSTSW: 
-                   if (!(digest = *argp++) || *digest == '-')
+                   if (!(cp = *argp++) || *cp == '-')
                        adios (NULL, "missing argument to %s", argp[-2]);
+                   digest = getcpy(cp);
                    mime = 0;
                    continue;
                case ISSUESW:
@@ -270,6 +283,39 @@ main (int argc, char **argv)
                case NBITSTUFFSW: 
                    dashstuff = -1;     /* trinary logic */
                    continue;
+
+               case FROMSW:
+                   if (!(cp = *argp++) || *cp == '-')
+                       adios (NULL, "missing argument to %s", argp[-2]);
+                   from = addlist(from, cp);
+                   continue;
+               case TOSW:
+                   if (!(cp = *argp++) || *cp == '-')
+                       adios (NULL, "missing argument to %s", argp[-2]);
+                   to = addlist(to, cp);
+                   continue;
+               case CCSW:
+                   if (!(cp = *argp++) || *cp == '-')
+                       adios (NULL, "missing argument to %s", argp[-2]);
+                   cc = addlist(cc, cp);
+                   continue;
+               case FCCSW:
+                   if (!(cp = *argp++) || *cp == '-')
+                       adios (NULL, "missing argument to %s", argp[-2]);
+                   fcc = addlist(fcc, cp);
+                   continue;
+               case SUBJECTSW:
+                   if (!(cp = *argp++) || *cp == '-')
+                       adios (NULL, "missing argument to %s", argp[-2]);
+                   subject = getcpy(cp);
+                   continue;
+
+               case WIDTHSW:
+                   if (!(cp = *argp++) || *cp == '-')
+                       adios (NULL, "missing argument to %s", argp[-2]);
+                   if ((outputlinelen = atoi(cp)) < 10)
+                       adios (NULL, "impossible width %d", outputlinelen);
+                   continue;
            }
        }
        if (*cp == '+' || *cp == '@') {
@@ -353,6 +399,20 @@ try_it_again:
            if (!m_convert (mp, msgs[msgnum]))
                done (1);
        seq_setprev (mp);       /* set the previous sequence */
+
+       /*
+        * Find the first message in our set and use it as the input
+        * for the component scanner
+        */
+
+       for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
+           if (is_selected (mp, msgnum)) {
+               fwdmsg = strdup(m_name(msgnum));
+               break;
+           }
+
+       if (! fwdmsg)
+           adios (NULL, "Unable to find input message");
     }
 
     if (filter && access (filter, R_OK) == NOTOK)
@@ -376,9 +436,19 @@ try_it_again:
            volume = 1;
        if (!form)
            form = digestcomps;
-       in = build_form (form, digest, volume, issue);
-    } else
-       in = open_form(&form, forwcomps);
+    } else {
+       form = forwcomps;
+    }
+
+    dat[0] = issue;
+    dat[1] = volume;
+    dat[2] = 0;
+    dat[3] = outputlinelen;
+    dat[4] = 0;
+
+
+    in = build_form (form, digest, dat, from, to, cc, fcc, subject,
+                    file ? file : fwdmsg);
 
     if ((out = creat (drft, m_gmprot ())) == NOTOK)
        adios (drft, "unable to create");
@@ -626,55 +696,3 @@ copy_mime_draft (int out)
        }
     write (out, "\n", 1);
 }
-
-
-static int
-build_form (char *form, char *digest, int volume, int issue)
-{
-    int        in;
-    int fmtsize;
-    register char *nfs;
-    char *line, tmpfil[BUFSIZ];
-    FILE *tmp;
-    register struct comp *cptr;
-    struct format *fmt;
-    int dat[5];
-    char *cp = NULL;
-
-    /* Get new format string */
-    nfs = new_fs (form, NULL, NULL);
-    fmtsize = strlen (nfs) + 256;
-
-    /* Compile format string */
-    fmt_compile (nfs, &fmt);
-
-    FINDCOMP (cptr, "digest");
-    if (cptr)
-       cptr->c_text = digest;
-    FINDCOMP (cptr, "date");
-    if (cptr)
-       cptr->c_text = getcpy(dtimenow (0));
-
-    dat[0] = issue;
-    dat[1] = volume;
-    dat[2] = 0;
-    dat[3] = fmtsize;
-    dat[4] = 0;
-
-    cp = m_mktemp2(NULL, invo_name, NULL, &tmp);
-    if (cp == NULL) adios("forw", "unable to create temporary file");
-    strncpy (tmpfil, cp, sizeof(tmpfil));
-    unlink (tmpfil);
-    if ((in = dup (fileno (tmp))) == NOTOK)
-       adios ("dup", "unable to");
-
-    line = mh_xmalloc ((unsigned) fmtsize);
-    fmt_scan (fmt, line, fmtsize, dat);
-    fputs (line, tmp);
-    free (line);
-    if (fclose (tmp))
-       adios (tmpfil, "error writing");
-
-    lseek (in, (off_t) 0, SEEK_SET);
-    return in;
-}
diff --git a/uip/forwsbr.c b/uip/forwsbr.c
new file mode 100755 (executable)
index 0000000..a3bc42e
--- /dev/null
@@ -0,0 +1,182 @@
+
+/*
+ * forwsbr.c -- subroutine to build a draft from a component file
+ *
+ * This code is Copyright (c) 2012, by the authors of nmh.  See the
+ * COPYRIGHT file in the root directory of the nmh distribution for
+ * complete copyright information.
+ */
+
+#include <h/mh.h>
+#include <fcntl.h>
+#include <h/fmt_scan.h>
+#include <h/tws.h>
+#include <h/utils.h>
+
+/*
+ * Take from replsbr.c - a buffer big enough to read in data header lines
+ * in reasonable chunks but not enough to slurp in the whole message
+ */
+
+static char msgbuf[256];
+#define COMPFREE(c) if (c->c_text) free(c->c_text)
+
+int
+build_form (char *form, char *digest, int *dat, char *from, char *to,
+           char *cc, char *fcc, char *subject, char *inputfile)
+{
+    int        in;
+    int i, fmtsize, ncomps, state, char_read = 0;
+    register char *nfs;
+    char *line, tmpfil[BUFSIZ], name[NAMESZ];
+    FILE *tmp;
+    register struct comp *cptr;
+    struct format *fmt;
+    char *cp = NULL;
+
+    /*
+     * Open the message we'll be scanning for components
+     */
+
+    if ((tmp = fopen(inputfile, "r")) == NULL)
+       adios (inputfile, "Unable to open");
+
+    /* Get new format string */
+    nfs = new_fs (form, NULL, NULL);
+    fmtsize = strlen (nfs) + 256;
+
+    /* Compile format string */
+    ncomps = fmt_compile (nfs, &fmt);
+
+    /*
+     * Process our message and save all relevant components
+     *
+     * A lot of this is taken from replsbr.c; should we try to merge
+     * these routines?
+     */
+
+    for (state = FLD;;) {
+       state = m_getfld(state, name, msgbuf, sizeof(msgbuf), tmp);
+       switch (state) {
+           case FLD:
+           case FLDPLUS:
+               /*
+                * If we find a component that we're interested in, save
+                * a copy.  We don't do all of that weird buffer switching
+                * that replout does.
+                */
+               if ((cptr = wantcomp[CHASH(name)]))
+                   do {
+                       if (mh_strcasecmp(name, cptr->c_name) == 0) {
+                           char_read += msg_count;
+                           if (! cptr->c_text) {
+                               i = strlen(cptr->c_text = strdup(msgbuf)) - 1;
+                               if (cptr->c_text[i] == '\n')
+                                   cptr->c_text[i] = '\0';
+                           } else {
+                               i = strlen(cptr->c_text) - 1;
+                               if (cptr->c_text[i] == '\n') {
+                                   if (cptr->c_type & CT_ADDR) {
+                                       cptr->c_text[i] = '\0';
+                                       cptr->c_text = add(",\n\t",
+                                                              cptr->c_text);
+                                   } else {
+                                       cptr->c_text = add ("\t", cptr->c_text);
+                                   }
+                               }
+                               cptr->c_text = add(msgbuf, cptr->c_text);
+                           }
+                           while (state == FLDPLUS) {
+                               state = m_getfld(state, name, msgbuf,
+                                                sizeof(msgbuf), tmp);
+                               cptr->c_text = add(msgbuf, cptr->c_text);
+                               char_read += msg_count;
+                           }
+                           break;
+                       }
+                   } while ((cptr = cptr->c_next));
+
+               while (state == FLDPLUS)
+                   state = m_getfld(state, name, msgbuf, sizeof(msgbuf), tmp);
+               break;
+
+           case LENERR:
+           case FMTERR:
+           case BODY:
+           case FILEEOF:
+               goto finished;
+
+           default:
+               adios(NULL, "m_getfld() returned %d", state);
+       }
+    }
+
+    /*
+     * Override any components just in case they were included in the
+     * input message.  Also include command-line components given here
+     */
+
+finished:
+
+    FINDCOMP (cptr, "digest");
+    if (cptr) {
+       COMPFREE(cptr);
+       cptr->c_text = digest;
+    }
+    FINDCOMP (cptr, "nmh-date");
+    if (cptr) {
+       COMPFREE(cptr);
+       cptr->c_text = getcpy(dtimenow (0));
+    }
+    FINDCOMP (cptr, "nmh-from");
+    if (cptr) {
+       COMPFREE(cptr);
+       cptr->c_text = from;
+    }
+    FINDCOMP (cptr, "nmh-to");
+    if (cptr) {
+       COMPFREE(cptr);
+       cptr->c_text = to;
+    }
+    FINDCOMP (cptr, "nmh-cc");
+    if (cptr) {
+       COMPFREE(cptr);
+       cptr->c_text = cc;
+    }
+    FINDCOMP (cptr, "nmh-subject");
+    if (cptr) {
+       COMPFREE(cptr);
+       cptr->c_text = subject;
+    }
+    FINDCOMP (cptr, "fcc");
+    if (cptr) {
+       COMPFREE(cptr);
+       cptr->c_text = fcc;
+    }
+
+    cp = m_mktemp2(NULL, invo_name, NULL, &tmp);
+    if (cp == NULL) adios("forw", "unable to create temporary file");
+    strncpy (tmpfil, cp, sizeof(tmpfil));
+    unlink (tmpfil);
+    if ((in = dup (fileno (tmp))) == NOTOK)
+       adios ("dup", "unable to");
+
+    line = mh_xmalloc ((unsigned) fmtsize);
+    fmt_scan (fmt, line, fmtsize, dat);
+    fputs (line, tmp);
+    free (line);
+    if (fclose (tmp))
+       adios (tmpfil, "error writing");
+
+    lseek (in, (off_t) 0, SEEK_SET);
+
+    /*
+     * Free any component buffers that we allocated
+     */
+
+    for (i = 0; i < (sizeof(wantcomp) / sizeof(struct comp)); i++)
+       for (cptr = wantcomp[i]; cptr != NULL; cptr = cptr->c_next)
+           COMPFREE(cptr);
+
+    return in;
+}