diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2007-05-20 12:47:02 +0000 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2007-05-20 12:47:02 +0000 |
commit | d779018cf7e2ea8846ad9b305511f6b304c1ffc2 (patch) | |
tree | 3ee728440889331f68c651bfd4724b042baf0a39 /src | |
parent | 15fa734f152c87ccf302db330b5de79bee5f99da (diff) | |
download | mailfromd-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.l | 15 | ||||
-rw-r--r-- | src/mailfromd.h | 4 | ||||
-rw-r--r-- | src/pp.c | 146 |
3 files changed, 152 insertions, 13 deletions
@@ -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(); @@ -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); +} |