aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2007-05-20 12:47:02 +0000
committerSergey Poznyakoff <gray@gnu.org.ua>2007-05-20 12:47:02 +0000
commitd779018cf7e2ea8846ad9b305511f6b304c1ffc2 (patch)
tree3ee728440889331f68c651bfd4724b042baf0a39 /src
parent15fa734f152c87ccf302db330b5de79bee5f99da (diff)
downloadmailfromd-d779018cf7e2ea8846ad9b305511f6b304c1ffc2.tar.gz
mailfromd-d779018cf7e2ea8846ad9b305511f6b304c1ffc2.tar.bz2
Improve external preprocessor usage
git-svn-id: file:///svnroot/mailfromd/trunk@1458 7a8a7f39-df28-0410-adc6-e0d955640f24
Diffstat (limited to 'src')
-rw-r--r--src/lex.l15
-rw-r--r--src/mailfromd.h4
-rw-r--r--src/pp.c146
3 files changed, 152 insertions, 13 deletions
diff --git a/src/lex.l b/src/lex.l
index e61dd08d..e65f87b1 100644
--- a/src/lex.l
+++ b/src/lex.l
@@ -703,6 +703,8 @@ parse_error_locus(const struct locus *loc, char *fmt, ...)
error_count++;
}
+static pid_t pp_pid;
+
int
source(char *name)
{
@@ -721,16 +723,7 @@ source(char *name)
close(fd);
pp_make_argcv(&argc, &argv);
- if (mu_argcv_string(argc, argv, &ppcmd)) {
- mu_error(_("Cannot build preprocessor command line: %s"),
- mu_strerror(errno));
- return EX_OSERR;
- }
-
- if (yy_flex_debug)
- __debug1("Running preprocessor: `%s'", ppcmd);
-
- yyin = popen(ppcmd, "r");
+ yyin = pp_extrn_start(argc, argv, &pp_pid);
if (!yyin) {
mu_error(_("Unable to start external preprocessor `%s': %s"),
ppcmd,
@@ -747,7 +740,7 @@ int
yywrap()
{
if (yyin)
- pclose(yyin);
+ pp_extrn_shutdown(pp_pid);
else
pp_done();
locus.file = NULL;
diff --git a/src/mailfromd.h b/src/mailfromd.h
index b041e33d..0693f818 100644
--- a/src/mailfromd.h
+++ b/src/mailfromd.h
@@ -660,6 +660,10 @@ size_t pp_fill_buffer(char *buf, size_t size);
int preprocess_input(char *);
int source(char *);
void pp_make_argcv(int *pargc, char ***pargv);
+FILE *pp_extrn_start(int argc, char **argv, pid_t *ppid);
+void pp_extrn_shutdown(pid_t pid);
+int pp_init(char *name);
+void pp_done(void);
/* Parser functions */
int yyparse();
diff --git a/src/pp.c b/src/pp.c
index 8ad18b28..d5aec559 100644
--- a/src/pp.c
+++ b/src/pp.c
@@ -600,7 +600,39 @@ pp_done()
free(putback_buffer);
}
-
+static void
+copy(FILE *infile, FILE *outfile)
+{
+ char *buf = NULL;
+ size_t bufsize;
+
+ fseek(infile, 0, SEEK_END);
+ bufsize = ftell(infile);
+ fseek(infile, 0, SEEK_SET);
+ if (bufsize == 0)
+ bufsize = BUFSIZ;
+ do {
+ buf = malloc(bufsize);
+ } while (buf == NULL && (bufsize /= 2) != 0);
+ if (!buf) {
+ mu_error("%s", mu_strerror(errno));
+ return;
+ }
+
+ while (1) {
+ size_t rsize = fread(buf, 1, bufsize, infile);
+ if (rsize == 0)
+ break;
+ while (rsize) {
+ size_t wsize = fwrite(buf, 1, rsize, outfile);
+ if (wsize == 0)
+ break;
+ rsize -= wsize;
+ }
+ }
+ free(buf);
+}
+
int
preprocess_input(char *extpp)
{
@@ -610,13 +642,32 @@ preprocess_input(char *extpp)
if (pp_init(script_file))
return EX_NOINPUT;
if (extpp) {
- FILE *outfile = popen(extpp, "w");
+ FILE *outfile;
+ char *setup_file;
+
+ debug1(1, "Running preprocessor: `%s'", extpp);
+ outfile = popen(extpp, "w");
if (!outfile) {
mu_error(_("Unable to start external preprocessor `%s': %s"),
extpp,
mu_strerror(errno));
return EX_OSFILE;
}
+
+ if (try_file("pp-setup", 1, &setup_file)) {
+ FILE *infile = fopen(setup_file, "r");
+ if (!infile)
+ mu_error(_("Cannot open preprocessor setup file `%s': %s"),
+ setup_file, mu_strerror(errno));
+ else {
+ debug1(1, "Using preprocessor setup file `%s'",
+ setup_file);
+ copy(infile, outfile);
+ fclose(infile);
+ }
+ free(setup_file);
+ }
+
while (i = pp_fill_buffer(buffer, sizeof buffer))
fwrite(buffer, 1, i, outfile);
pclose(outfile);
@@ -663,3 +714,94 @@ pp_make_argcv(int *pargc, char ***pargv)
*pargc = argc;
*pargv = argv;
}
+
+FILE *
+pp_extrn_start(int argc, char **argv, pid_t *ppid)
+{
+ int pout[2];
+ pid_t pid;
+ int i;
+ char *ppcmd = "unknown";
+ FILE *fp = NULL;
+
+ mu_argcv_string(argc, argv, &ppcmd);
+ debug1(1, "Running preprocessor: `%s'", ppcmd);
+
+ pipe(pout);
+ switch (pid = fork()) {
+ /* The child branch. */
+ case 0:
+ if (pout[1] != 1) {
+ close(1);
+ dup2(pout[1], 1);
+ }
+
+ /* Close unneded descripitors */
+ for (i = getmaxfd(); i > 2; i--)
+ close(i);
+
+ if (!log_to_stderr) {
+ int p[2];
+ char *buf = NULL;
+ size_t size = 0;
+ FILE *fp;
+
+ signal(SIGCHLD, SIG_DFL);
+ pipe(p);
+ switch (pid = fork()) {
+ /* Grandchild */
+ case 0:
+ if (p[1] != 2) {
+ close(2);
+ dup2(p[1], 2);
+ }
+ close(p[0]);
+
+ execvp(argv[0], argv);
+ exit(127);
+
+ case -1:
+ /* Fork failed */
+ log_setup(log_to_stderr);
+ mu_error("Cannot run `%s': %s",
+ ppcmd, mu_strerror(errno));
+ exit(127);
+
+ default:
+ /* Sub-master */
+ close(p[1]);
+ fp = fdopen(p[0], "r");
+ log_setup(log_to_stderr);
+ while (getline(&buf, &size, fp) > 0)
+ mu_error("%s", buf);
+ exit(0);
+ }
+ } else {
+ execvp(argv[0], argv);
+ log_setup(log_to_stderr);
+ mu_error("Cannot run `%s': %s",
+ ppcmd, mu_strerror(errno));
+ exit(127);
+ }
+
+ case -1:
+ /* Fork failed */
+ mu_error("Cannot run `%s': %s",
+ ppcmd, mu_strerror(errno));
+ break;
+
+ default:
+ close(pout[1]);
+ fp = fdopen(pout[0], "r");
+ break;
+ }
+ *ppid = pid;
+ return fp;
+}
+
+void
+pp_extrn_shutdown(pid_t pid)
+{
+ int status;
+ waitpid(pid, &status, 0);
+}

Return to:

Send suggestions and report system problems to the System administrator.