X-Git-Url: https://diplodocus.org/git/nmh/blobdiff_plain/cb264ca67270e08ee6e629bf0f183054b63c6f07..ec68c7d9fca00e976df02842dc2c9d5a523567af:/uip/mhfixmsg.c diff --git a/uip/mhfixmsg.c b/uip/mhfixmsg.c index 24d1ac33..e1057887 100644 --- a/uip/mhfixmsg.c +++ b/uip/mhfixmsg.c @@ -1,5 +1,4 @@ -/* - * mhfixmsg.c -- rewrite a message with various transformations +/* mhfixmsg.c -- rewrite a message with various transformations * * This code is Copyright (c) 2002 and 2013, by the authors of nmh. * See the COPYRIGHT file in the root directory of the nmh @@ -87,9 +86,10 @@ typedef struct fix_transformations { char *textcharset; } fix_transformations; -int mhfixmsgsbr (CT *, char *, const fix_transformations *, char *, FILE **); +int mhfixmsgsbr (CT *, char *, const fix_transformations *, FILE **, char *, + FILE **); static int fix_boundary (CT *, int *); -static int copy_input_to_output (const char *, const char *, FILE *); +static int copy_input_to_output (const char *, FILE *, const char *, FILE *); static int get_multipart_boundary (CT, char **); static int replace_boundary (CT, char *, char *); static int fix_types (CT, svector_t, int *); @@ -137,7 +137,7 @@ main (int argc, char **argv) { struct msgs_array msgs = { 0, 0, NULL }; struct msgs *mp = NULL; CT *ctp; - FILE *fp, *outfp = NULL; + FILE *fp, *infp = NULL, *outfp = NULL; int using_stdin = 0; int chgflag = 1; int status = OK; @@ -371,17 +371,26 @@ main (int argc, char **argv) { set_text_ctparams(ct, fx.decodetypes, fx.lf_line_endings); *ctp++ = ct; } else { - advise (NULL, "unable to parse message from file %s", file); + inform("unable to parse message from file %s", file); status = NOTOK; - /* If there's an outfile, pass the input message unchanged, so the message won't - get dropped from a pipeline. */ + /* If there's an outfile, pass the input message unchanged, so the + message won't get dropped from a pipeline. */ if (outfile) { - /* Something went wrong. Output might be expected, such as if this were run - as a filter. Just copy the input to the output. */ - if (copy_input_to_output (file, outfile, outfp) != OK) { - advise (NULL, "unable to copy message to %s, it might be lost\n", outfile); + /* Something went wrong. Output might be expected, such as if + this were run as a filter. Just copy the input to the + output. */ + if ((infp = fopen (file, "r")) == NULL) { + adios (file, "unable to open for reading"); + } + + if (copy_input_to_output (file, infp, outfile, outfp) != OK) { + inform("unable to copy message to %s, " + "it might be lost\n", outfile); } + + fclose (infp); + infp = NULL; } } } else { @@ -396,7 +405,7 @@ main (int argc, char **argv) { if (! folder) { folder = getfolder (1); } - maildir = m_maildir (folder); + maildir = mh_xstrdup(m_maildir (folder)); /* chdir so that error messages, esp. from MIME parser, just refer to the message and not its path. */ @@ -432,7 +441,7 @@ main (int argc, char **argv) { set_text_ctparams(ct, fx.decodetypes, fx.lf_line_endings); *ctp++ = ct; } else { - advise (NULL, "unable to parse message %s", msgnam); + inform("unable to parse message %s", msgnam); status = NOTOK; /* If there's an outfile, pass the input message @@ -448,13 +457,19 @@ main (int argc, char **argv) { char *input_filename = concat (maildir, "/", msgnam, NULL); - if (copy_input_to_output (input_filename, outfile, - outfp) != OK) { - advise (NULL, - "unable to copy message to %s, " - "it might be lost\n", - outfile); + if ((infp = fopen (input_filename, "r")) == NULL) { + adios (input_filename, + "unable to open for reading"); + } + + if (copy_input_to_output (input_filename, infp, + outfile, outfp) != OK) { + inform("unable to copy message to %s, " + "it might be lost\n", outfile); } + + fclose (infp); + infp = NULL; free (input_filename); } } @@ -471,7 +486,7 @@ main (int argc, char **argv) { if (*cts) { for (ctp = cts; *ctp; ++ctp) { - status += mhfixmsgsbr (ctp, maildir, &fx, outfile, &outfp); + status += mhfixmsgsbr (ctp, maildir, &fx, &infp, outfile, &outfp); free_content (*ctp); if (using_stdin) { @@ -487,9 +502,11 @@ main (int argc, char **argv) { status = 1; } + mh_xfree(maildir); free (cts); if (fx.fixtypes != NULL) { svector_free (fx.fixtypes); } + if (infp) { fclose (infp); } /* even if stdin */ if (outfp) { fclose (outfp); } /* even if stdout */ free (outfile); free (file); @@ -506,7 +523,7 @@ main (int argc, char **argv) { */ int mhfixmsgsbr (CT *ctp, char *maildir, const fix_transformations *fx, - char *outfile, FILE **outfp) { + FILE **infp, char *outfile, FILE **outfp) { /* Store input filename in case one of the transformations, i.e., fix_boundary(), rewrites to a tmp file. */ char *input_filename = maildir @@ -516,11 +533,19 @@ mhfixmsgsbr (CT *ctp, char *maildir, const fix_transformations *fx, int message_mods = 0; int status = OK; + /* Though the input file won't need to be opened if everything goes + well, do it here just in case there's a failure, and that failure is + running out of file descriptors. */ + if ((*infp = fopen (input_filename, "r")) == NULL) { + adios (input_filename, "unable to open for reading"); + } + if (outfile == NULL) { modify_inplace = 1; if ((*ctp)->c_file) { char *tempfile; + /* outfp will be closed by the caller */ if ((tempfile = m_mktemp2 (NULL, invo_name, NULL, outfp)) == NULL) { adios (NULL, "unable to create temporary file in %s", @@ -578,8 +603,10 @@ mhfixmsgsbr (CT *ctp, char *maildir, const fix_transformations *fx, /* Something went wrong. Output might be expected, such as if this were run as a filter. Just copy the input to the output. */ - if (copy_input_to_output (input_filename, outfile, *outfp) != OK) { - advise (NULL, "unable to copy message to %s, it might be lost\n", outfile); + if (copy_input_to_output (input_filename, *infp, outfile, + *outfp) != OK) { + inform("unable to copy message to %s, it might be lost\n", + outfile); } } @@ -589,6 +616,8 @@ mhfixmsgsbr (CT *ctp, char *maildir, const fix_transformations *fx, outfile = NULL; } + fclose (*infp); + *infp = NULL; free (input_filename); return status; @@ -600,9 +629,9 @@ mhfixmsgsbr (CT *ctp, char *maildir, const fix_transformations *fx, * might be running as part of a pipeline. */ static int -copy_input_to_output (const char *input_filename, const char *output_filename, - FILE *outfp) { - int in = open (input_filename, O_RDONLY); +copy_input_to_output (const char *input_filename, FILE *infp, + const char *output_filename, FILE *outfp) { + int in = fileno (infp); int out = fileno (outfp); int status = OK; @@ -612,8 +641,6 @@ copy_input_to_output (const char *input_filename, const char *output_filename, status = NOTOK; } - close (in); - return status; } @@ -662,16 +689,16 @@ fix_boundary (CT *ct, int *message_mods) { } } else { *ct = NULL; - advise (NULL, "unable to parse fixed part"); + inform("unable to parse fixed part"); status = NOTOK; } free (filename); } else { - advise (NULL, "unable to replace broken boundary"); + inform("unable to replace broken boundary"); status = NOTOK; } } else { - advise (NULL, "unable to create temporary file in %s", + inform("unable to create temporary file in %s", get_temp_dir()); status = NOTOK; } @@ -796,7 +823,7 @@ replace_boundary (CT ct, char *file, char *boundary) { int status = OK; if (ct->c_file == NULL) { - advise (NULL, "missing input filename"); + inform("missing input filename"); return NOTOK; } @@ -868,12 +895,12 @@ replace_boundary (CT ct, char *file, char *boundary) { case LENERR: case FMTERR: - advise (NULL, "message format error in component #%d", compnum); + inform("message format error in component #%d", compnum); status = NOTOK; break; default: - advise (NULL, "getfld() returned %d", state); + inform("getfld() returned %d", state); status = NOTOK; break; } @@ -955,7 +982,7 @@ fix_types (CT ct, svector_t fixtypes, int *message_mods) { *cp = '\0'; ct_subtype = mh_xstrdup(++cp); } else { - advise (NULL, "missing / in MIME type of %s %s", + inform("missing / in MIME type of %s %s", ct->c_file, ct->c_partno); free (ct_type); return NOTOK; @@ -970,7 +997,7 @@ fix_types (CT ct, svector_t fixtypes, int *message_mods) { ct->c_ctinfo.ci_subtype = ct_subtype; if (! replace_substring (&ct->c_ctline, type, ct_type_subtype)) { - advise (NULL, "did not find %s in %s", + inform("did not find %s in %s", type, ct->c_ctline); } @@ -988,7 +1015,7 @@ fix_types (CT ct, svector_t fixtypes, int *message_mods) { } break; } else { - advise (NULL, "did not find %s in %s", + inform("did not find %s in %s", type, hf->value); } } @@ -1307,9 +1334,8 @@ ensure_text_plain (CT *ct, CT parent, int *message_mods, int replacetextplain) { parent->c_ctinfo.ci_subtype = mh_xstrdup("alternative"); if (! replace_substring (&parent->c_ctline, "/related", "/alternative")) { - advise (NULL, - "did not find multipart/related in %s", - parent->c_ctline); + inform("did not find multipart/related in %s", + parent->c_ctline); } /* Update Content-Type header field. */ @@ -1329,7 +1355,7 @@ ensure_text_plain (CT *ct, CT parent, int *message_mods, int replacetextplain) { remove_parameter (hf->value, "type"); break; } else { - advise (NULL, "did not find multipart/" + inform("did not find multipart/" "related in header %s", hf->value); } @@ -1461,8 +1487,9 @@ build_text_plain_part (CT encoded_part) { be unlinked by free_content (). */ char *tempfile; + /* This m_mktemp2() call closes the temp file. */ if ((tempfile = m_mktemp2 (NULL, invo_name, NULL, NULL)) == NULL) { - advise (NULL, "unable to create temporary file in %s", + inform("unable to create temporary file in %s", get_temp_dir()); } else { tmp_plain_file = mh_xstrdup (tempfile); @@ -1599,6 +1626,9 @@ decode_part (CT ct) { status = output_message_fp (ct, file, tmp_decoded); (void) m_unlink (tmp_decoded); free (tmp_decoded); + if (fclose (file)) { + inform("unable to close temporary file %s, continuing...", tempfile); + } return status; } @@ -1624,14 +1654,14 @@ reformat_part (CT ct, char *file, char *type, char *subtype, int c_type) { /* Check for invo_name-format-type/subtype. */ if ((cf = context_find_by_type ("format", type, subtype)) == NULL) { if (verbosw) { - advise (NULL, "Don't know how to convert %s, there is no " + inform("Don't know how to convert %s, there is no " "%s-format-%s/%s profile entry", ct->c_file, invo_name, type, subtype); } return NOTOK; } if (strchr (cf, '>')) { - advise (NULL, "'>' prohibited in \"%s\",\nplease fix your " + inform("'>' prohibited in \"%s\",\nplease fix your " "%s-format-%s/%s profile entry", cf, invo_name, type, subtype ? subtype : ""); @@ -1756,7 +1786,7 @@ build_multipart_alt (CT first_alt, CT new_part, int type, int subtype) { } if (found_boundary) { - advise (NULL, "giving up trying to find a unique boundary"); + inform("giving up trying to find a unique boundary"); free_content (ct); return NULL; } @@ -2270,7 +2300,7 @@ strip_crs (CT ct, int *message_mods) { } if (close (fd)) { - admonish (NULL, "unable to write temporary file %s", + inform("unable to write temporary file %s, continuing...", stripped_content_file); (void) m_unlink (stripped_content_file); status = NOTOK; @@ -2556,7 +2586,7 @@ static int fix_filename_param (char *name, char *value, PM *first_pm, PM *last_pm) { int fixed = 0; - if (HasPrefix(value, "=?") && HasSuffix(value, "?=")) { + if (has_prefix(value, "=?") && has_suffix(value, "?=")) { /* Looks like an RFC 2047 encoded parameter. */ char decoded[PATH_MAX + 1]; @@ -2565,7 +2595,7 @@ fix_filename_param (char *name, char *value, PM *first_pm, PM *last_pm) { replace_param (first_pm, last_pm, name, decoded, 0); fixed = 1; } else { - advise (NULL, "failed to decode %s parameter %s", name, value); + inform("failed to decode %s parameter %s", name, value); } } @@ -2630,7 +2660,7 @@ fix_filename_encoding (CT ct) { free((void *)new_params); /* Cast away const. Sigh. */ free((void *)params); } else { - advise (NULL, "did not find semicolon in %s:%s\n", + inform("did not find semicolon in %s:%s\n", hf->name, hf->value); } } @@ -2685,15 +2715,15 @@ write_content (CT ct, const char *input_filename, char *outfile, FILE *outfp, expand filename to absolute path. */ int file = ct->c_file && ct->c_file[0] == '/'; - admonish (NULL, "unable to rename %s %s to %s", + inform("unable to rename %s %s to %s, continuing...", file ? "file" : "message", outfile, infile); status = NOTOK; } } } else { - admonish (NULL, "unable to remove input file %s, " - "not modifying it", infile); + inform("unable to remove input file %s, " + "not modifying it, continuing...", infile); (void) m_unlink (outfile); status = NOTOK; }