X-Git-Url: https://diplodocus.org/git/nmh/blobdiff_plain/a9bb157da7d3cee576e8944eaf8fab2bdbc4be8d..248c3a452003bc95088d9a1c4dec988696be2d7d:/uip/mhstoresbr.c diff --git a/uip/mhstoresbr.c b/uip/mhstoresbr.c index d707fb8e..131650be 100644 --- a/uip/mhstoresbr.c +++ b/uip/mhstoresbr.c @@ -5,17 +5,31 @@ * complete copyright information. */ -#include +#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 -#include -#include -#include -#include -#include -#include -#include +#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_mktemp.h" +#include "sbr/m_maildir.h" +#include "sbr/m_mktemp.h" enum clobber_policy_t { NMH_CLOBBER_ALWAYS = 0, @@ -25,7 +39,7 @@ enum clobber_policy_t { NMH_CLOBBER_NEVER }; -static enum clobber_policy_t clobber_policy (const char *); +static enum clobber_policy_t clobber_policy (const char *) PURE; struct mhstoreinfo { CT *cts; /* Top-level list of contents to store. */ @@ -44,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); @@ -60,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; } @@ -79,11 +96,6 @@ mhstoreinfo_files_not_clobbered (const mhstoreinfo_t info) { typedef int (*qsort_comp) (const void *, const void *); -/* mhmisc.c */ -int part_ok (CT); -int type_ok (CT, int); -void flush_errors (void); - /* * static prototypes */ @@ -92,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); /* @@ -166,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); @@ -208,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); } @@ -231,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 */ @@ -244,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; } } @@ -271,7 +279,7 @@ store_application (CT ct, mhstoreinfo_t info) } } - return store_content (ct, NULL, info); + return store_content (ct, info); } @@ -308,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". */ @@ -462,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 = add (p->c_storage, NULL); - - /* record the folder name */ - if (p->c_folder) { - ct->c_folder = mh_xstrdup(p->c_folder); - } - } - goto got_filename; - } - } - /* * Get storage formatting string. * @@ -569,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); @@ -628,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) @@ -643,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; @@ -689,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; @@ -749,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: @@ -785,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) { @@ -818,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; @@ -840,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; @@ -901,13 +669,12 @@ output_content_folder (char *folder, char *filename) struct msgs *mp; /* Read the folder. */ - if ((mp = folder_read (folder, 0))) { - /* Link file into folder */ - msgnum = folder_addmsg (&mp, filename, 0, 0, 0, 0, NULL); - } else { + if (!(mp = folder_read(folder, 0))) { inform("unable to read folder %s", folder); return NOTOK; } + /* Link file into folder */ + msgnum = folder_addmsg(&mp, filename, 0, 0, 0, 0, NULL); /* free folder structure */ folder_free (mp); @@ -1074,7 +841,7 @@ get_storeproc (CT ct) free(cp); return; } - mh_xfree(cp); + free(cp); } /* @@ -1088,45 +855,16 @@ get_storeproc (CT ct) ct->c_storeproc = mh_xstrdup(cp); } - mh_xfree(cp); + free(cp); } -/* - * 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; } @@ -1143,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; @@ -1209,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 @@ -1221,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; @@ -1248,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: @@ -1295,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; @@ -1314,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; } } @@ -1341,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. */