X-Git-Url: https://diplodocus.org/git/nmh/blobdiff_plain/2194cc9557fbdf80841cd59c0497637ba8d932ec..55852a7a33e630d3d92368ee3242287f16ceeb78:/uip/mhfixmsg.c diff --git a/uip/mhfixmsg.c b/uip/mhfixmsg.c index 93d0b116..ff3e383a 100644 --- a/uip/mhfixmsg.c +++ b/uip/mhfixmsg.c @@ -63,7 +63,7 @@ extern int bogus_mp_content; /* flag from InitMultiPart */ extern int suppress_extraneous_trailing_semicolon_warning; /* mhoutsbr.c */ -int output_message (CT, char *); +int output_message_fp (CT, FILE *, char *); /* mhmisc.c */ void flush_errors (void); @@ -87,9 +87,10 @@ typedef struct fix_transformations { char *textcharset; } fix_transformations; -int mhfixmsgsbr (CT *, char *, const fix_transformations *, char *); +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 *); +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 *); @@ -121,7 +122,7 @@ static int convert_charsets (CT, char *, int *); static int fix_always (CT, int *); static int fix_filename_param (char *, char *, PM *, PM *); static int fix_filename_encoding (CT); -static int write_content (CT, const char *, char *, int, int); +static int write_content (CT, const char *, char *, FILE *, int, int); static void set_text_ctparams(CT, char *, int); static int remove_file (const char *); static void report (char *, char *, char *, char *, ...); @@ -137,7 +138,7 @@ main (int argc, char **argv) { struct msgs_array msgs = { 0, 0, NULL }; struct msgs *mp = NULL; CT *ctp; - FILE *fp; + FILE *fp, *infp = NULL, *outfp = NULL; int using_stdin = 0; int chgflag = 1; int status = OK; @@ -323,6 +324,16 @@ main (int argc, char **argv) { adios (NULL, "cannot specify msg and file at same time!"); } + if (outfile) { + /* Open the outfile now, so we don't have to risk opening it + after running out of fds. */ + if (strcmp (outfile, "-") == 0) { + outfp = stdout; + } else if ((outfp = fopen (outfile, "w")) == NULL) { + adios (outfile, "unable to open for writing"); + } + } + /* * check if message is coming from file */ @@ -364,14 +375,23 @@ main (int argc, char **argv) { advise (NULL, "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) != 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) { + advise (NULL, "unable to copy message to %s, " + "it might be lost\n", outfile); + } + + fclose (infp); + infp = NULL; } } } else { @@ -438,11 +458,21 @@ main (int argc, char **argv) { char *input_filename = concat (maildir, "/", msgnam, NULL); - if (copy_input_to_output (input_filename, outfile) != OK) { + 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) { advise (NULL, - "unable to copy message to %s, it might be lost\n", + "unable to copy message to %s, " + "it might be lost\n", outfile); } + + fclose (infp); + infp = NULL; free (input_filename); } } @@ -459,7 +489,7 @@ main (int argc, char **argv) { if (*cts) { for (ctp = cts; *ctp; ++ctp) { - status += mhfixmsgsbr (ctp, maildir, &fx, outfile); + status += mhfixmsgsbr (ctp, maildir, &fx, &infp, outfile, &outfp); free_content (*ctp); if (using_stdin) { @@ -478,6 +508,8 @@ main (int argc, char **argv) { 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); free (folder); @@ -493,7 +525,7 @@ main (int argc, char **argv) { */ int mhfixmsgsbr (CT *ctp, char *maildir, const fix_transformations *fx, - char *outfile) { + 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 @@ -503,12 +535,21 @@ 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; - if ((tempfile = m_mktemp2 (NULL, invo_name, NULL, NULL)) == NULL) { + /* 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", get_temp_dir()); } @@ -516,7 +557,7 @@ mhfixmsgsbr (CT *ctp, char *maildir, const fix_transformations *fx, } else { adios (NULL, "missing both input and output filenames\n"); } - } + } /* else *outfp was defined by caller */ reverse_alternative_parts (*ctp); status = fix_always (*ctp, &message_mods); @@ -558,14 +599,16 @@ mhfixmsgsbr (CT *ctp, char *maildir, const fix_transformations *fx, * Write the content to a file */ if (status == OK) { - status = write_content (*ctp, input_filename, outfile, modify_inplace, - message_mods); + status = write_content (*ctp, input_filename, outfile, *outfp, + modify_inplace, message_mods); } else if (! modify_inplace) { /* 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) != 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) { + advise (NULL, "unable to copy message to %s, it might be lost\n", + outfile); } } @@ -575,6 +618,8 @@ mhfixmsgsbr (CT *ctp, char *maildir, const fix_transformations *fx, outfile = NULL; } + fclose (*infp); + *infp = NULL; free (input_filename); return status; @@ -586,11 +631,10 @@ 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) { - int in = open (input_filename, O_RDONLY); - int out = strcmp (output_filename, "-") - ? open (output_filename, O_WRONLY | O_CREAT, m_gmprot ()) - : STDOUT_FILENO; +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; if (in != -1 && out != -1) { @@ -599,9 +643,6 @@ copy_input_to_output (const char *input_filename, const char *output_filename) { status = NOTOK; } - close (out); - close (in); - return status; } @@ -1449,6 +1490,7 @@ 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", get_temp_dir()); @@ -1574,18 +1616,22 @@ static int decode_part (CT ct) { char *tmp_decoded; int status; + FILE *file; char *tempfile; - if ((tempfile = m_mktemp2 (NULL, invo_name, NULL, NULL)) == NULL) { + if ((tempfile = m_mktemp2 (NULL, invo_name, NULL, &file)) == NULL) { adios (NULL, "unable to create temporary file in %s", get_temp_dir()); } tmp_decoded = mh_xstrdup (tempfile); /* The following call will load ct->c_cefile.ce_file with the tmp filename of the decoded content. tmp_decoded will contain the encoded output, get rid of that. */ - status = output_message (ct, tmp_decoded); + status = output_message_fp (ct, file, tmp_decoded); (void) m_unlink (tmp_decoded); free (tmp_decoded); + if (fclose (file)) { + admonish (NULL, "unable to close temporary file %s", tempfile); + } return status; } @@ -2631,13 +2677,13 @@ fix_filename_encoding (CT ct) { * Output content in input file to output file. */ static int -write_content (CT ct, const char *input_filename, char *outfile, int modify_inplace, - int message_mods) { +write_content (CT ct, const char *input_filename, char *outfile, FILE *outfp, + int modify_inplace, int message_mods) { int status = OK; if (modify_inplace) { if (message_mods > 0) { - if ((status = output_message (ct, outfile)) == OK) { + if ((status = output_message_fp (ct, outfp, outfile)) == OK) { char *infile = input_filename ? mh_xstrdup (input_filename) : mh_xstrdup (ct->c_file ? ct->c_file : "-"); @@ -2696,7 +2742,7 @@ write_content (CT ct, const char *input_filename, char *outfile, int modify_inpl } else { /* Output is going to some file. Produce it whether or not there were modifications. */ - status = output_message (ct, outfile); + status = output_message_fp (ct, outfp, outfile); } flush_errors ();