X-Git-Url: https://diplodocus.org/git/nmh/blobdiff_plain/d6b2ae5fa68b9a82ffc006c233aef64c5cdb3bd2..fc8e02dc2074ce73276afc6f48919b9ecb32a409:/uip/mhstoresbr.c diff --git a/uip/mhstoresbr.c b/uip/mhstoresbr.c index ae835fbf..131650be 100644 --- a/uip/mhstoresbr.c +++ b/uip/mhstoresbr.c @@ -1,21 +1,35 @@ - -/* - * mhstoresbr.c -- routines to save/store the contents of MIME messages +/* mhstoresbr.c -- routines to save/store the contents of MIME messages * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * 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_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. */ @@ -41,10 +55,14 @@ struct mhstoreinfo { enum clobber_policy_t clobber_policy; /* -clobber selection */ }; +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_t info = mh_xmalloc (sizeof *info); +mhstoreinfo_create (CT *ct, char *pwd, const char *csw, int asw, int vsw) +{ + mhstoreinfo_t info; + NEW(info); info->cts = ct; info->cwd = pwd; info->autosw = asw; @@ -57,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; } @@ -76,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); -int type_ok (CT, int); -void flush_errors (void); - /* * static prototypes */ @@ -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); /* @@ -116,7 +128,7 @@ store_all_messages (mhstoreinfo_t info) * store any contents. */ if ((cp = context_find (nmhstorage)) && *cp) - info->dir = getcpy (cp); + info->dir = mh_xstrdup(cp); else info->dir = getcpy (info->cwd); @@ -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); } @@ -287,12 +298,12 @@ store_multi (CT ct, mhstoreinfo_t info) for (part = m->mp_parts; part; part = part->mp_next) { CT p = part->mp_part; - if (part_ok (p, 1) && type_ok (p, 1)) { + if (part_ok (p) && type_ok (p, 1)) { if (ct->c_storage) { /* Support mhstore -outfile. The MIME parser doesn't load c_storage, so we know that p->c_storage is NULL here. */ - p->c_storage = add (ct->c_storage, NULL); + p->c_storage = mh_xstrdup(ct->c_storage); } result = store_switch (p, info); @@ -305,113 +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) { - advise (NULL, "missing (at least) last part of multipart message"); - return NOTOK; - } - - if ((base = (CT *) mh_xcalloc ((size_t) (i + 1), sizeof(*base))) == NULL) - adios (NULL, "out of memory"); - - 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) { - if (pm->pm_marked == cur - 1) { - admonish (NULL, - "duplicate part %d of %d part multipart message", - pm->pm_marked, hi); - continue; - } - -missing_part: - advise (NULL, - "missing %spart %d of %d part multipart message", - cur != hi ? "(at least) " : "", cur, hi); - goto losing; - } - else - cur++; - } - 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 ((char *) base); - return NOTOK; - } - - for (; *ctq; ctq++) { - p = *ctq; - if (store_content (p, ct, info) == NOTOK) - goto losing; - } - - free ((char *) base); - return OK; -} - - /* * Store content from a message of type "message/external". */ @@ -433,16 +337,11 @@ store_external (CT ct, mhstoreinfo_t info) if (info->autosw) { char *cp; - if ((cp = e->eb_name) - && *cp != '/' - && *cp != '.' - && *cp != '|' - && *cp != '!' - && !strchr (cp, '%')) { + if ((cp = e->eb_name) && use_param_as_filename(cp)) { if (!ct->c_storeproc) - ct->c_storeproc = add (cp, NULL); + ct->c_storeproc = mh_xstrdup(cp); if (!p->c_storeproc) - p->c_storeproc = add (cp, NULL); + p->c_storeproc = mh_xstrdup(cp); } } @@ -458,7 +357,7 @@ store_external (CT ct, mhstoreinfo_t info) if (ct->c_storage) { /* Support mhstore -outfile. The MIME parser doesn't load c_storage, so we know that p->c_storage is NULL here. */ - p->c_storage = add (ct->c_storage, NULL); + p->c_storage = mh_xstrdup(ct->c_storage); } result = store_switch (p, info); @@ -467,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 = add (p->c_folder, NULL); - } - } - goto got_filename; - } - } - /* * Get storage formatting string. * @@ -574,10 +407,10 @@ 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 = add (tmpfilenam, NULL); + ct->c_storage = mh_xstrdup(tmpfilenam); /* Get the folder name */ if (cp[1]) @@ -589,7 +422,7 @@ store_content (CT ct, CT p, mhstoreinfo_t info) create_folder(m_mailpath(folder), 0, exit); /* Record the folder name */ - ct->c_folder = add (folder, NULL); + ct->c_folder = mh_xstrdup(folder); if (cp[1]) free (folder); @@ -611,7 +444,7 @@ store_content (CT ct, CT p, mhstoreinfo_t info) return show_content_aux (ct, 0, buffer + 1, info->dir, NULL); /* record the filename */ - if ((ct->c_storage = clobber_check (add (buffer, NULL), info)) == + if ((ct->c_storage = clobber_check (mh_xstrdup(buffer), info)) == NULL) { return NOTOK; } @@ -633,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) @@ -648,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) - fprintf (stderr, "%s", ct->c_file); - 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", - strncmp (ct->c_storage, info->cwd, cwdlen) - || 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; @@ -694,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; @@ -711,7 +530,7 @@ output_content_file (CT ct, int appending) int cc, fd; if (!ct->c_ceopenfnx) { - advise (NULL, "don't know how to decode part %s of message %s", + inform("don't know how to decode part %s of message %s", ct->c_partno, ct->c_file); return NOTOK; } @@ -754,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: @@ -790,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) { @@ -823,21 +631,7 @@ 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) - 1, ct->c_fp)) { + while (fgets (buffer, sizeof buffer, ct->c_fp)) { if ((pos += strlen (buffer)) > last) { int diff; @@ -845,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; @@ -906,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, (char *)0); - } else { - advise (NULL, "unable to read folder %s", folder); + 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); @@ -955,7 +717,9 @@ parse_format_string (CT ct, char *cp, char *buffer, int buflen, char *dir) * appropriate directory. */ if (*cp != '/' && *cp != '|' && *cp != '!') { - snprintf (bp, buflen, "%s/", dir[1] ? dir : ""); + if (!strcmp(dir, "/")) + dir = ""; /* Don't start with "//". */ + snprintf (bp, buflen, "%s/", dir); len = strlen (bp); bp += len; buflen -= len; @@ -976,7 +740,8 @@ parse_format_string (CT ct, char *cp, char *buffer, int buflen, char *dir) *bp = '\0'; buflen--; continue; - } else { + } + { PM pm; char *s = ""; @@ -1003,7 +768,7 @@ parse_format_string (CT ct, char *cp, char *buffer, int buflen, char *dir) break; case 'p': - /* insert part number withouth leading dot */ + /* insert part number without leading dot */ if (ct->c_partno) strncpy (bp, ct->c_partno, buflen); break; @@ -1070,18 +835,13 @@ get_storeproc (CT ct) * use that (RFC-2183). */ if (ct->c_dispo) { - if ((cp = get_param(ct->c_dispo_first, "filename", '_', 0)) - && *cp != '/' - && *cp != '.' - && *cp != '|' - && *cp != '!' - && !strchr (cp, '%')) { - ct->c_storeproc = add (cp, NULL); + if ((cp = get_param(ct->c_dispo_first, "filename", '_', 0)) && + use_param_as_filename(cp)) { + ct->c_storeproc = mh_xstrdup(cp); free(cp); return; } - if (cp) - free(cp); + free(cp); } /* @@ -1090,74 +850,44 @@ get_storeproc (CT ct) * the storeproc. */ ci = &ct->c_ctinfo; - if ((cp = get_param(ci->ci_first_pm, "name", '_', 0)) - && *cp != '/' - && *cp != '.' - && *cp != '|' - && *cp != '!' - && !strchr (cp, '%')) { - ct->c_storeproc = add (cp, NULL); + if ((cp = get_param(ci->ci_first_pm, "name", '_', 0)) && + use_param_as_filename(cp)) { + ct->c_storeproc = mh_xstrdup(cp); } - if (cp) - free(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")) { - } else if (! strcasecmp (value, "auto")) { + return NMH_CLOBBER_ALWAYS; + } + if (! strcasecmp (value, "auto")) { return NMH_CLOBBER_AUTO; - } else if (! strcasecmp (value, "suffix")) { + } + if (! strcasecmp (value, "suffix")) { return NMH_CLOBBER_SUFFIX; - } else if (! strcasecmp (value, "ask")) { + } + if (! strcasecmp (value, "ask")) { return NMH_CLOBBER_ASK; - } else if (! strcasecmp (value, "never")) { + } + if (! strcasecmp (value, "never")) { return NMH_CLOBBER_NEVER; - } else { - adios (NULL, "invalid argument, %s, to clobber", value); } - return NMH_CLOBBER_ALWAYS; + 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; @@ -1187,7 +917,7 @@ next_version (char *file, enum clobber_policy_t clobber_policy) { default: /* Should never get here. */ - advise (NULL, "will not overwrite %s, invalid clobber policy", buffer); + inform("will not overwrite %s, invalid clobber policy", buffer); free (buffer); return NULL; } @@ -1208,7 +938,7 @@ next_version (char *file, enum clobber_policy_t clobber_policy) { free (file); if (version >= max_versions) { - advise (NULL, "will not overwrite %s, too many versions", buffer); + inform("will not overwrite %s, too many versions", buffer); free (buffer); buffer = NULL; } @@ -1218,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 @@ -1230,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; @@ -1240,7 +971,7 @@ clobber_check (char *original_file, mhstoreinfo_t info) { /* Save cwd for possible use in loop below. */ char *slash; - cwd = add (original_file, NULL); + cwd = mh_xstrdup(original_file); slash = strrchr (cwd, '/'); if (slash) { @@ -1257,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: @@ -1286,11 +1017,11 @@ clobber_check (char *original_file, mhstoreinfo_t info) { if (isatty (fileno (stdin))) { char *prompt = concat ("Overwrite \"", file, "\" [y/n/rename]? ", NULL); - ans = getans (prompt, answer); + ans = read_switch_multiword (prompt, answer); free (prompt); } else { /* Overwrite, that's what nmh used to do. And warn. */ - advise (NULL, "-clobber ask but no tty, so overwrite %s", file); + inform("-clobber ask but no tty, so overwrite %s", file); break; } @@ -1304,29 +1035,26 @@ 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; ++info->files_not_clobbered; } else { - char *newline = strchr (buf, '\n'); - if (newline) { - *newline = '\0'; - } + trim_suffix_c(buf, '\n'); } free (file); if (buf[0] == '/') { /* Full path, use it. */ - file = add (buf, NULL); + file = mh_xstrdup(buf); } else { /* Relative path. */ - file = cwd ? concat (cwd, "/", buf, NULL) : add (buf, NULL); + file = cwd ? concat (cwd, "/", buf, NULL) : mh_xstrdup(buf); } - check_again = 1; + check_again = true; break; } } @@ -1337,7 +1065,7 @@ clobber_check (char *original_file, mhstoreinfo_t info) { if (stat (file, &st) == OK) { /* Keep count of files that would have been clobbered, and return that as process exit status. */ - advise (NULL, "will not overwrite %s with -clobber never", file); + inform("will not overwrite %s with -clobber never", file); free (file); file = NULL; ++info->files_not_clobbered; @@ -1353,5 +1081,13 @@ clobber_check (char *original_file, mhstoreinfo_t info) { return file; } +static bool +use_param_as_filename(const char *p) +{ + /* Preserve result of original test that considered an empty string + * OK. */ + return !*p || (!strchr("/.|!", *p) && !strchr(p, '%')); +} + /* -clobber support */ /******************************************************************************/