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);
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 *);
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 *, ...);
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;
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
*/
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 {
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);
}
}
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) {
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);
*/
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
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());
}
} 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);
* 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);
}
}
outfile = NULL;
}
+ fclose (*infp);
+ *infp = NULL;
free (input_filename);
return status;
* 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) {
status = NOTOK;
}
- close (out);
- close (in);
-
return status;
}
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());
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;
}
* 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 : "-");
} 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 ();