]> diplodocus.org Git - nmh/blobdiff - uip/mhstoresbr.c
Include proper header without READLINE_SUPPORT.
[nmh] / uip / mhstoresbr.c
index 0e9b94cd112d0e68f9eb25bf481d46a874889443..131650be59d9128d463fe730f878d310c17bd787 100644 (file)
@@ -5,15 +5,27 @@
  * complete copyright information.
  */
 
-#include <h/mh.h>
+#include "h/mh.h"
+#include "sbr/read_switch_multiword.h"
+#include "sbr/concat.h"
+#include "sbr/smatch.h"
+#include "sbr/r1bindex.h"
+#include "sbr/uprf.h"
+#include "sbr/getcpy.h"
+#include "sbr/getfolder.h"
+#include "sbr/folder_read.h"
+#include "sbr/folder_free.h"
+#include "sbr/folder_addmsg.h"
+#include "sbr/context_find.h"
+#include "sbr/path.h"
+#include "sbr/error.h"
 #include <fcntl.h>
-#include <h/md5.h>
-#include <h/mts.h>
-#include <h/tws.h>
-#include <h/fmt_scan.h>
-#include <h/mime.h>
-#include <h/mhparse.h>
-#include <h/utils.h>
+#include "h/mts.h"
+#include "h/tws.h"
+#include "h/fmt_scan.h"
+#include "h/mime.h"
+#include "h/mhparse.h"
+#include "h/utils.h"
 #include "mhmisc.h"
 #include "mhshowsbr.h"
 #include "sbr/m_maildir.h"
@@ -46,7 +58,8 @@ struct mhstoreinfo {
 static bool use_param_as_filename(const char *p);
 
 mhstoreinfo_t
-mhstoreinfo_create (CT *ct, char *pwd, const char *csw, int asw, int vsw) {
+mhstoreinfo_create (CT *ct, char *pwd, const char *csw, int asw, int vsw)
+{
     mhstoreinfo_t info;
 
     NEW(info);
@@ -62,14 +75,16 @@ mhstoreinfo_create (CT *ct, char *pwd, const char *csw, int asw, int vsw) {
 }
 
 void
-mhstoreinfo_free (mhstoreinfo_t info) {
+mhstoreinfo_free (mhstoreinfo_t info)
+{
     free (info->cwd);
     free (info->dir);
     free (info);
 }
 
 int
-mhstoreinfo_files_not_clobbered (const mhstoreinfo_t info) {
+mhstoreinfo_files_not_clobbered (const mhstoreinfo_t info)
+{
     return info->files_not_clobbered;
 }
 
@@ -89,15 +104,12 @@ static int store_switch (CT, mhstoreinfo_t);
 static int store_generic (CT, mhstoreinfo_t);
 static int store_application (CT, mhstoreinfo_t);
 static int store_multi (CT, mhstoreinfo_t);
-static int store_partial (CT, mhstoreinfo_t);
 static int store_external (CT, mhstoreinfo_t);
-static int ct_compar (CT *, CT *);
-static int store_content (CT, CT, mhstoreinfo_t);
+static int store_content (CT, mhstoreinfo_t);
 static int output_content_file (CT, int);
 static int output_content_folder (char *, char *);
 static int parse_format_string (CT, char *, char *, int, char *);
 static void get_storeproc (CT);
-static int copy_some_headers (FILE *, CT);
 static char *clobber_check (char *, mhstoreinfo_t);
 
 /*
@@ -163,9 +175,6 @@ store_switch (CT ct, mhstoreinfo_t info)
 
        case CT_MESSAGE:
            switch (ct->c_subtype) {
-               case MESSAGE_PARTIAL:
-                   return store_partial (ct, info);
-
                case MESSAGE_EXTERNAL:
                    return store_external (ct, info);
 
@@ -205,7 +214,7 @@ store_generic (CT ct, mhstoreinfo_t info)
     if (info->autosw && ct->c_type != CT_MESSAGE)
        get_storeproc (ct);
 
-    return store_content (ct, NULL, info);
+    return store_content (ct, info);
 }
 
 
@@ -228,12 +237,14 @@ store_application (CT ct, mhstoreinfo_t info)
      * attribute/value pairs which specify if this a tar file.
      */
     if (!ct->c_storeproc && ct->c_subtype == APPLICATION_OCTETS) {
-       int tarP = 0, zP = 0, gzP = 0;
+       bool tarP = false;
+        bool zP = false;
+        bool gzP = false;
        char *cp;
 
        if ((cp = get_param(ci->ci_first_pm, "type", ' ', 1))) {
            if (strcasecmp (cp, "tar") == 0)
-               tarP = 1;
+               tarP = true;
        }
 
        /* check for "conversions=compress" attribute */
@@ -241,11 +252,11 @@ store_application (CT ct, mhstoreinfo_t info)
            (cp = get_param(ci->ci_first_pm, "x-conversions", ' ', 1))) {
            if (strcasecmp (cp, "compress") == 0 ||
                    strcasecmp (cp, "x-compress") == 0) {
-               zP = 1;
+               zP = true;
            }
            if (strcasecmp (cp, "gzip") == 0 ||
                    strcasecmp (cp, "x-gzip") == 0) {
-               gzP = 1;
+               gzP = true;
            }
        }
 
@@ -268,7 +279,7 @@ store_application (CT ct, mhstoreinfo_t info)
        }
     }
 
-    return store_content (ct, NULL, info);
+    return store_content (ct, info);
 }
 
 
@@ -305,110 +316,6 @@ store_multi (CT ct, mhstoreinfo_t info)
 }
 
 
-/*
- * Reassemble and store the contents of a collection
- * of messages of type "message/partial".
- */
-
-static int
-store_partial (CT ct, mhstoreinfo_t info)
-{
-    int        cur, hi, i;
-    CT p, *ctp, *ctq;
-    CT *base;
-    struct partial *pm, *qm;
-
-    qm = (struct partial *) ct->c_ctparams;
-    if (qm->pm_stored)
-       return OK;
-
-    hi = i = 0;
-    for (ctp = info->cts; *ctp; ctp++) {
-       p = *ctp;
-       if (p->c_type == CT_MESSAGE && p->c_subtype == ct->c_subtype) {
-           pm = (struct partial *) p->c_ctparams;
-           if (!pm->pm_stored
-                   && strcmp (qm->pm_partid, pm->pm_partid) == 0) {
-               pm->pm_marked = pm->pm_partno;
-               if (pm->pm_maxno)
-                   hi = pm->pm_maxno;
-               pm->pm_stored = 1;
-               i++;
-           }
-           else
-               pm->pm_marked = 0;
-       }
-    }
-
-    if (hi == 0) {
-       inform("missing (at least) last part of multipart message");
-       return NOTOK;
-    }
-
-    base = mh_xcalloc(i + 1, sizeof *base);
-    ctq = base;
-    for (ctp = info->cts; *ctp; ctp++) {
-       p = *ctp;
-       if (p->c_type == CT_MESSAGE && p->c_subtype == ct->c_subtype) {
-           pm = (struct partial *) p->c_ctparams;
-           if (pm->pm_marked)
-               *ctq++ = p;
-       }
-    }
-    *ctq = NULL;
-
-    if (i > 1)
-       qsort ((char *) base, i, sizeof(*base), (qsort_comp) ct_compar);
-
-    cur = 1;
-    for (ctq = base; *ctq; ctq++) {
-       p = *ctq;
-       pm = (struct partial *) p->c_ctparams;
-       if (pm->pm_marked == cur) {
-           cur++;
-            continue;
-        }
-
-        if (pm->pm_marked == cur - 1) {
-            inform("duplicate part %d of %d part multipart message, continuing...",
-                      pm->pm_marked, hi);
-            continue;
-        }
-
-missing_part:
-        inform("missing %spart %d of %d part multipart message",
-            cur != hi ? "(at least) " : "", cur, hi);
-        goto losing;
-    }
-    if (hi != --cur) {
-       cur = hi;
-       goto missing_part;
-    }
-
-    /*
-     * Now cycle through the sorted list of messages of type
-     * "message/partial" and save/append them to a file.
-     */
-
-    ctq = base;
-    ct = *ctq++;
-    if (store_content (ct, NULL, info) == NOTOK) {
-losing:
-       free(base);
-       return NOTOK;
-    }
-
-    for (; *ctq; ctq++) {
-       p = *ctq;
-       if (store_content (p, ct, info) == NOTOK)
-           goto losing;
-    }
-
-    free(base);
-    return OK;
-}
-
-
 /*
  * Store content from a message of type "message/external".
  */
@@ -459,85 +366,19 @@ store_external (CT ct, mhstoreinfo_t info)
 }
 
 
-/*
- * Compare the numbering from two different
- * message/partials (needed for sorting).
- */
-
-static int
-ct_compar (CT *a, CT *b)
-{
-    struct partial *am = (struct partial *) ((*a)->c_ctparams);
-    struct partial *bm = (struct partial *) ((*b)->c_ctparams);
-
-    return (am->pm_marked - bm->pm_marked);
-}
-
-
 /*
  * Store contents of a message or message part to
  * a folder, a file, the standard output, or pass
  * the contents to a command.
- *
- * If the current content to be saved is a followup part
- * to a collection of messages of type "message/partial",
- * then field "p" is a pointer to the Content structure
- * to the first message/partial in the group.
  */
 
 static int
-store_content (CT ct, CT p, mhstoreinfo_t info)
+store_content (CT ct, mhstoreinfo_t info)
 {
-    int appending = 0, msgnum = 0;
-    int is_partial = 0, first_partial = 0;
-    int last_partial = 0;
+    bool appending = false;
+    int msgnum = 0;
     char *cp, buffer[BUFSIZ];
 
-    /*
-     * Do special processing for messages of
-     * type "message/partial".
-     *
-     * We first check if this content is of type
-     * "message/partial".  If it is, then we need to check
-     * whether it is the first and/or last in the group.
-     *
-     * Then if "p" is a valid pointer, it points to the Content
-     * structure of the first partial in the group.  So we copy
-     * the file name and/or folder name from that message.  In
-     * this case, we also note that we will be appending.
-     */
-    if (ct->c_type == CT_MESSAGE && ct->c_subtype == MESSAGE_PARTIAL) {
-       struct partial *pm = (struct partial *) ct->c_ctparams;
-
-       /* Yep, it's a message/partial */
-       is_partial = 1;
-
-       /* But is it the first and/or last in the collection? */
-       if (pm->pm_partno == 1)
-           first_partial = 1;
-       if (pm->pm_maxno && pm->pm_partno == pm->pm_maxno)
-           last_partial = 1;
-
-       /*
-        * If "p" is a valid pointer, then it points to the
-        * Content structure for the first message in the group.
-        * So we just copy the filename or foldername information
-        * from the previous iteration of this function.
-        */
-       if (p) {
-           appending = 1;
-            if (! ct->c_storage) {
-               ct->c_storage = mh_xstrdup(FENDNULL(p->c_storage));
-
-               /* record the folder name */
-               if (p->c_folder) {
-                   ct->c_folder = mh_xstrdup(p->c_folder);
-               }
-           }
-           goto got_filename;
-       }
-    }
-
     /*
      * Get storage formatting string.
      *
@@ -566,7 +407,7 @@ store_content (CT ct, CT p, mhstoreinfo_t info)
 
            /* Store content in temporary file for now */
            if ((tmpfilenam = m_mktemp(invo_name, NULL, NULL)) == NULL) {
-               adios(NULL, "unable to create temporary file in %s",
+               die("unable to create temporary file in %s",
                      get_temp_dir());
            }
            ct->c_storage = mh_xstrdup(tmpfilenam);
@@ -625,10 +466,9 @@ got_filename:
 
     /*
      * If necessary, link the file into a folder and remove
-     * the temporary file.  If this message is a partial,
-     * then only do this if it is the last one in the group.
+     * the temporary file.
      */
-    if (ct->c_folder && (!is_partial || last_partial)) {
+    if (ct->c_folder) {
        msgnum = output_content_folder (ct->c_folder, ct->c_storage);
        (void) m_unlink (ct->c_storage);
        if (msgnum == NOTOK)
@@ -640,39 +480,27 @@ got_filename:
          * Now print out the name/number of the message
          * that we are storing.
          */
-        if (is_partial) {
-            if (first_partial)
-                fprintf (stderr, "reassembling partials ");
-            if (last_partial)
-                fputs(ct->c_file, stderr);
-            else
-                fprintf (stderr, "%s,", ct->c_file);
-        } else {
-            fprintf (stderr, "storing message %s", ct->c_file);
-            if (ct->c_partno)
-                fprintf (stderr, " part %s", ct->c_partno);
-        }
+       fprintf (stderr, "storing message %s", ct->c_file);
+       if (ct->c_partno)
+           fprintf (stderr, " part %s", ct->c_partno);
 
         /*
-         * Unless we are in the "middle" of group of message/partials,
-         * we now print the name of the file, folder, and/or message
+         * We now print the name of the file, folder, and/or message
          * to which we are storing the content.
          */
-        if (!is_partial || last_partial) {
-            if (ct->c_folder) {
-                fprintf (stderr, " to folder %s as message %d\n", ct->c_folder,
-                         msgnum);
-            } else if (!strcmp(ct->c_storage, "-")) {
-                fprintf (stderr, " to stdout\n");
-            } else {
-                int cwdlen = strlen (info->cwd);
-
-                fprintf (stderr, " as file %s\n",
-                         !has_prefix(ct->c_storage, info->cwd)
-                         || ct->c_storage[cwdlen] != '/'
-                         ? ct->c_storage : ct->c_storage + cwdlen + 1);
+       if (ct->c_folder) {
+           fprintf (stderr, " to folder %s as message %d\n", ct->c_folder,
+                   msgnum);
+       } else if (!strcmp(ct->c_storage, "-")) {
+           fprintf (stderr, " to stdout\n");
+       } else {
+           int cwdlen = strlen (info->cwd);
+
+           fprintf (stderr, " as file %s\n",
+                   !has_prefix(ct->c_storage, info->cwd)
+                   || ct->c_storage[cwdlen] != '/'
+                   ? ct->c_storage : ct->c_storage + cwdlen + 1);
             }
-        }
     }
 
     return OK;
@@ -686,7 +514,6 @@ got_filename:
 static int
 output_content_file (CT ct, int appending)
 {
-    int filterstate;
     char *file, buffer[BUFSIZ];
     long pos, last;
     FILE *fp;
@@ -746,17 +573,6 @@ losing:
            }
        }
 
-       /*
-        * Filter the header fields of the initial enclosing
-        * message/partial into the file.
-        */
-       if (ct->c_type == CT_MESSAGE && ct->c_subtype == MESSAGE_PARTIAL) {
-           struct partial *pm = (struct partial *) ct->c_ctparams;
-
-           if (pm->pm_partno == 1)
-               copy_some_headers (fp, ct);
-       }
-
        for (;;) {
            switch (cc = read (fd, buffer, sizeof(buffer))) {
                case NOTOK:
@@ -782,7 +598,7 @@ losing:
 
        fclose (fp);
 
-       return (cc != NOTOK ? OK : NOTOK);
+        return cc == NOTOK ? NOTOK : OK;
     }
 
     if (!ct->c_fp && (ct->c_fp = fopen (ct->c_file, "r")) == NULL) {
@@ -815,20 +631,6 @@ losing:
        }
     }
 
-    /*
-     * Copy a few of the header fields of the initial
-     * enclosing message/partial into the file.
-     */
-    filterstate = 0;
-    if (ct->c_type == CT_MESSAGE && ct->c_subtype == MESSAGE_PARTIAL) {
-       struct partial *pm = (struct partial *) ct->c_ctparams;
-
-       if (pm->pm_partno == 1) {
-           copy_some_headers (fp, ct);
-           filterstate = 1;
-       }
-    }
-
     while (fgets (buffer, sizeof buffer, ct->c_fp)) {
        if ((pos += strlen (buffer)) > last) {
            int diff;
@@ -837,37 +639,6 @@ losing:
            if (diff >= 0)
                buffer[diff] = '\0';
        }
-       /*
-        * If this is the first content of a group of
-        * message/partial contents, then we only copy a few
-        * of the header fields of the enclosed message.
-        */
-       if (filterstate) {
-           switch (buffer[0]) {
-               case ' ':
-               case '\t':
-                   if (filterstate < 0)
-                       buffer[0] = 0;
-                   break;
-
-               case '\n':
-                   filterstate = 0;
-                   break;
-
-               default:
-                   if (!uprf (buffer, XXX_FIELD_PRF)
-                           && !uprf (buffer, VRSN_FIELD)
-                           && !uprf (buffer, "Subject:")
-                           && !uprf (buffer, "Encrypted:")
-                           && !uprf (buffer, "Message-ID:")) {
-                       filterstate = -1;
-                       buffer[0] = 0;
-                       break;
-                   }
-                   filterstate = 1;
-                   break;
-           }
-       }
        fputs (buffer, fp);
        if (pos >= last)
            break;
@@ -1088,41 +859,12 @@ get_storeproc (CT ct)
 }
 
 
-/*
- * Copy some of the header fields of the initial message/partial
- * message into the header of the reassembled message.
- */
-
-static int
-copy_some_headers (FILE *out, CT ct)
-{
-    HF hp;
-
-    hp = ct->c_first_hf;       /* start at first header field */
-
-    while (hp) {
-       /*
-        * A few of the header fields of the enclosing
-        * messages are not copied.
-        */
-       if (!uprf (hp->name, XXX_FIELD_PRF)
-               && strcasecmp (hp->name, VRSN_FIELD)
-               && strcasecmp (hp->name, "Subject")
-               && strcasecmp (hp->name, "Encrypted")
-               && strcasecmp (hp->name, "Message-ID"))
-           fprintf (out, "%s:%s", hp->name, hp->value);
-       hp = hp->next;  /* next header field */
-    }
-
-    return OK;
-}
-
 /******************************************************************************/
 /* -clobber support */
 
-static
-enum clobber_policy_t
-clobber_policy (const char *value) {
+static enum clobber_policy_t
+clobber_policy (const char *value)
+{
   if (value == NULL  ||  ! strcasecmp (value, "always")) {
     return NMH_CLOBBER_ALWAYS;
   }
@@ -1139,12 +881,13 @@ clobber_policy (const char *value) {
     return NMH_CLOBBER_NEVER;
   }
 
-  adios (NULL, "invalid argument, %s, to clobber", value);
+  die("invalid argument, %s, to clobber", value);
 }
 
 
 static char *
-next_version (char *file, enum clobber_policy_t clobber_policy) {
+next_version (char *file, enum clobber_policy_t clobber_policy)
+{
   const size_t max_versions = 1000000;
   /* 8 = log max_versions  +  one for - or .  +  one for null terminator */
   const size_t buflen = strlen (file) + 8;
@@ -1205,7 +948,8 @@ next_version (char *file, enum clobber_policy_t clobber_policy) {
 
 
 static char *
-clobber_check (char *original_file, mhstoreinfo_t info) {
+clobber_check (char *original_file, mhstoreinfo_t info)
+{
   /* clobber policy        return value
    * --------------        ------------
    *   -always             original_file
@@ -1217,7 +961,7 @@ clobber_check (char *original_file, mhstoreinfo_t info) {
 
   char *file;
   char *cwd = NULL;
-  int check_again;
+  bool check_again;
 
   if (! strcmp (original_file, "-")) {
       return original_file;
@@ -1244,7 +988,7 @@ clobber_check (char *original_file, mhstoreinfo_t info) {
     struct stat st;
 
     file = original_file;
-    check_again = 0;
+    check_again = false;
 
     switch (info->clobber_policy) {
       case NMH_CLOBBER_ALWAYS:
@@ -1291,7 +1035,7 @@ clobber_check (char *original_file, mhstoreinfo_t info) {
               break;
             case NMH_RENAME: {
               char buf[PATH_MAX];
-              printf ("Enter filename or full path of the new file: ");
+              fputs("Enter filename or full path of the new file: ", stdout);
               if (fgets (buf, sizeof buf, stdin) == NULL  ||
                   buf[0] == '\0') {
                 file = NULL;
@@ -1310,7 +1054,7 @@ clobber_check (char *original_file, mhstoreinfo_t info) {
                 file = cwd  ?  concat (cwd, "/", buf, NULL)  :  mh_xstrdup(buf);
               }
 
-              check_again = 1;
+              check_again = true;
               break;
             }
           }
@@ -1337,7 +1081,8 @@ clobber_check (char *original_file, mhstoreinfo_t info) {
   return file;
 }
 
-static bool use_param_as_filename(const char *p)
+static bool
+use_param_as_filename(const char *p)
 {
     /* Preserve result of original test that considered an empty string
      * OK. */