From f5e0b65756bd1f791c91935b0eeba0352a2d95f9 Mon Sep 17 00:00:00 2001 From: Karl Berry Date: Fri, 16 Jun 2006 23:53:26 +0000 Subject: allow pipes as input or output files; from Taco git-svn-id: svn://tug.org/texlive/trunk@1688 c570f23f-e606-0410-a88d-b1316a301751 --- Build/source/texk/web2c/cpascal.h | 3 +- Build/source/texk/web2c/lib/openclose.c | 2 +- Build/source/texk/web2c/lib/texmfmp.c | 110 ++++++++++++++++++++++++++++++++ Build/source/texk/web2c/texmfmp.h | 19 ++++++ 4 files changed, 132 insertions(+), 2 deletions(-) diff --git a/Build/source/texk/web2c/cpascal.h b/Build/source/texk/web2c/cpascal.h index f9493690d3b..efe830359dd 100644 --- a/Build/source/texk/web2c/cpascal.h +++ b/Build/source/texk/web2c/cpascal.h @@ -134,6 +134,7 @@ typedef FILE *text; needs to know what path to use. Used by BibTeX, MF, TeX. */ #define aopenin(f,p) open_input (&(f), p, FOPEN_RBIN_MODE) #define aopenout(f) open_output (&(f), FOPEN_W_MODE) +#define aclose close_file /* For faking arrays in tftopl. */ typedef unsigned char *pointertobyte; @@ -266,7 +267,7 @@ extern TEXDLL void mainbody P1H(void); /* generated by web2c */ /* openclose.c */ extern boolean open_input P3H(FILE **, int, const_string fopen_mode); extern boolean open_output P2H(FILE **, const_string fopen_mode); -extern void aclose P1H(FILE *); +extern void close_file P1H(FILE *); extern void recorder_change_filename P1H(string); extern boolean recorder_enabled; extern string output_directory; diff --git a/Build/source/texk/web2c/lib/openclose.c b/Build/source/texk/web2c/lib/openclose.c index 6e542d247fa..a4ac21495b8 100644 --- a/Build/source/texk/web2c/lib/openclose.c +++ b/Build/source/texk/web2c/lib/openclose.c @@ -234,7 +234,7 @@ open_output P2C(FILE **, f_ptr, const_string, fopen_mode) /* Close F. */ void -aclose P1C(FILE *, f) +close_file P1C(FILE *, f) { /* If F is null, just return. bad_pool might close a file that has never been opened. */ diff --git a/Build/source/texk/web2c/lib/texmfmp.c b/Build/source/texk/web2c/lib/texmfmp.c index ff69d12df4f..d876e075170 100644 --- a/Build/source/texk/web2c/lib/texmfmp.c +++ b/Build/source/texk/web2c/lib/texmfmp.c @@ -1192,6 +1192,116 @@ boolean openoutnameok P1C(const_string, fname) /* For output, default to paranoid. */ return opennameok (fname, "openout_any", "p", ok_writing); } +/* + piped I/O + */ + +/* The code that implements popen() needs an array for tracking + possible pipe file pointers, because these need to be + closed using pclose(). +*/ + +#if defined(pdfTeX) || defined(pdfeTeX) + +static FILE *pipes [] = {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, + NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL}; + +boolean +open_in_or_pipe P3C(FILE **, f_ptr, int, filefmt, const_string, fopen_mode) +{ + string fname = NULL; + int i; /* iterator */ + + /* opening a read pipe is straightforward, only have to + skip past the pipe symbol in the file name. filename + quoting is assumed to happen elsewhere (it does :-)) */ + + if (shellenabledp && *(nameoffile+1) == '|') { + /* the user requested a pipe */ + *f_ptr = NULL; + fname = (string)xmalloc(strlen(nameoffile+1)); + strcpy(fname,nameoffile+1); + *f_ptr = popen(fname+1,"r"); + free(fname); + for (i=0; i<=15; i++) { + if (pipes[i]==NULL) { + pipes[i] = *f_ptr; + break; + } + } + if (*f_ptr) + setvbuf (*f_ptr,(char *)NULL,_IOLBF,0); + + return *f_ptr != NULL; + } + + return open_input(f_ptr,filefmt,fopen_mode) ; +} + + +boolean +open_out_or_pipe P2C(FILE **, f_ptr, const_string, fopen_mode) +{ + string fname; + int i; /* iterator */ + + /* opening a write pipe takes a little bit more work, because TeX + will perhaps have appended ".tex". To avoid user confusion as + much as possible, this extension is stripped only when the command + is a bare word. Some small string trickery is needed to make + sure the correct number of bytes is free()-d afterwards */ + + if (shellenabledp && *(nameoffile+1) == '|') { + /* the user requested a pipe */ + fname = (string)xmalloc(strlen(nameoffile+1)); + strcpy(fname,nameoffile+1); + if (strchr (fname,' ')==NULL && strchr(fname,'>')==NULL) { + /* mp and mf currently do not use this code, but it + is better to be prepared */ + if (STREQ((fname+strlen(fname)-3),"tex")) + *(fname+strlen(fname)-4) = 0; + *f_ptr = popen(fname+1,"w"); + *(fname+strlen(fname)) = '.'; + } else { + *f_ptr = popen(fname+1,"w"); + } + free(fname); + + for (i=0; i<=15; i++) { + if (pipes[i]==NULL) { + pipes[i] = *f_ptr; + break; + } + } + + if (*f_ptr) + setvbuf(*f_ptr,(char *)NULL,_IOLBF,0); + + return *f_ptr != NULL; + } + + return open_output(f_ptr,fopen_mode); +} + + +void +close_file_or_pipe P1C(FILE *, f) +{ + int i; /* iterator */ + + if (shellenabledp) { + /* if this file was a pipe, pclose() it and return */ + for (i=0; i<=15; i++) { + if (pipes[i] == f) { + pclose (f); + pipes[i] = NULL; + return; + } + } + } + close_file(f); +} +#endif /* All our interrupt handler has to do is set TeX's or Metafont's global variable `interrupt'; then they will do everything needed. */ diff --git a/Build/source/texk/web2c/texmfmp.h b/Build/source/texk/web2c/texmfmp.h index 45fca14d140..d000afc7cd7 100644 --- a/Build/source/texk/web2c/texmfmp.h +++ b/Build/source/texk/web2c/texmfmp.h @@ -89,6 +89,13 @@ extern int tfmtemp, texinputtype; extern boolean openinnameok P1H(const_string); extern boolean openoutnameok P1H(const_string); +/* pdfTeX uses these for pipe support */ +#if defined(pdfTeX) || defined(pdfeTeX) +extern boolean open_in_or_pipe P3H(FILE **, int, const_string fopen_mode); +extern boolean open_out_or_pipe P2H(FILE **, const_string fopen_mode); +extern void close_file_or_pipe P1H(FILE *); +#endif + /* All but the Omega family use this. */ #if !defined(Omega) && !defined(eOmega) && !defined(Aleph) extern void readtcxfile P1H(void); @@ -171,6 +178,18 @@ extern void topenin P1H(void); /* Set an array size from texmf.cnf. */ extern void setupboundvariable P3H(integer *, const_string, integer); +/* These defines reroute the file i/o calls to the new pipe-enabled + functions in texmfmp.c*/ + +#if defined(pdfTeX) || defined(pdfeTeX) +#undef aopenin +#undef aopenout +#undef aclose +#define aopenin(f,p) open_in_or_pipe(&(f),p,FOPEN_RBIN_MODE) +#define aopenout(f) open_out_or_pipe(&(f),FOPEN_W_MODE) +#define aclose(f) close_file_or_pipe(f) +#endif + /* `bopenin' (and out) is used only for reading (and writing) .tfm files; `wopenin' (and out) only for dump files. The filenames are passed in as a global variable, `nameoffile'. */ -- cgit v1.2.3