summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Shinwell <shinwell@codesourcery.com>2006-09-28 20:41:10 +0000
committerMark Shinwell <shinwell@codesourcery.com>2006-09-28 20:41:10 +0000
commit8b641d414553eff5f9f6948cfa01bb5820899b93 (patch)
tree12c38f398f8d6cac4a661eb9385b6a1462846018
parent29c3dd9be3ab490cfeef2caab8555dd99cf57004 (diff)
downloadbinutils-redhat-8b641d414553eff5f9f6948cfa01bb5820899b93.tar.gz
* libiberty.h: Declare pex_run_in_environment. libiberty/ * pex-common.c: New function pex_run_in_environment. * pex-common.h: Add environment parameter to exec_child. * pex-msdos.c: Add environment parameter to pex_msdos_exec_child. * pex-djgpp.c: Add environment parameter to pex_djgpp_exec_child. (pex_djgpp_exec_child): Pass environment to child process. * pex-unix.c: Add environment parameter to pex_unix_exec_child. (pex_unix_exec_child): Pass environment to child process. * pex-win32.c: Add environment parameter to pex_win32_exec_child. New function env_compare for comparing VAR=VALUE pairs. (win32_spawn): Assemble environment block and pass to CreateProcess. (spawn_script): Pass environment through to win32_spawn. (pex_win32_exec_child): Pass environment through to spawn_script and win32_spawn. * functions.texi: Regenerate. * pexecute.txh: Document pex_run_in_environment.
-rw-r--r--ChangeLog.csl22
-rw-r--r--include/libiberty.h17
-rw-r--r--libiberty/functions.texi32
-rw-r--r--libiberty/pex-common.c26
-rw-r--r--libiberty/pex-common.h1
-rw-r--r--libiberty/pex-djgpp.c14
-rw-r--r--libiberty/pex-msdos.c6
-rw-r--r--libiberty/pex-unix.c14
-rw-r--r--libiberty/pex-win32.c113
-rw-r--r--libiberty/pexecute.txh13
10 files changed, 222 insertions, 36 deletions
diff --git a/ChangeLog.csl b/ChangeLog.csl
index cf7b0ba8d3..8fcce895bb 100644
--- a/ChangeLog.csl
+++ b/ChangeLog.csl
@@ -1,3 +1,25 @@
+2006-09-28 Mark Shinwell <shinwell@codesourcery.com>
+
+ include/
+ * libiberty.h: Declare pex_run_in_environment.
+
+ libiberty/
+ * pex-common.c: New function pex_run_in_environment.
+ * pex-common.h: Add environment parameter to exec_child.
+ * pex-msdos.c: Add environment parameter to pex_msdos_exec_child.
+ * pex-djgpp.c: Add environment parameter to pex_djgpp_exec_child.
+ (pex_djgpp_exec_child): Pass environment to child process.
+ * pex-unix.c: Add environment parameter to pex_unix_exec_child.
+ (pex_unix_exec_child): Pass environment to child process.
+ * pex-win32.c: Add environment parameter to pex_win32_exec_child.
+ New function env_compare for comparing VAR=VALUE pairs.
+ (win32_spawn): Assemble environment block and pass to CreateProcess.
+ (spawn_script): Pass environment through to win32_spawn.
+ (pex_win32_exec_child): Pass environment through to spawn_script and
+ win32_spawn.
+ * functions.texi: Regenerate.
+ * pexecute.txh: Document pex_run_in_environment.
+
2006-09-19 Mark Shinwell <shinwell@codesourcery.com>
Joseph Myers <joseph@codesourcery.com>
Ian Lance Taylor <ian@wasabisystems.com>
diff --git a/include/libiberty.h b/include/libiberty.h
index 6bd318e0fe..1328d3eb14 100644
--- a/include/libiberty.h
+++ b/include/libiberty.h
@@ -448,6 +448,23 @@ extern const char *pex_run (struct pex_obj *obj, int flags,
const char *outname, const char *errname,
int *err);
+/* As for pex_run (), but takes an extra parameter to enable the
+ environment for the child process to be specified.
+
+ ENV The environment for the child process, specified as
+ an array of character pointers. Each element of the
+ array should point to a string of the form VAR=VALUE,
+ with the exception of the last element which must be
+ a null pointer.
+*/
+
+extern const char *pex_run_in_environment (struct pex_obj *obj, int flags,
+ const char *executable,
+ char * const *argv,
+ char * const *env,
+ const char *outname,
+ const char *errname, int *err);
+
/* Return a `FILE' pointer FP for the standard input of the first
program in the pipeline; FP is opened for writing. You must have
passed `PEX_USE_PIPES' to the `pex_init' call that returned OBJ.
diff --git a/libiberty/functions.texi b/libiberty/functions.texi
index 9696df3f2e..d10a4a0928 100644
--- a/libiberty/functions.texi
+++ b/libiberty/functions.texi
@@ -668,14 +668,14 @@ reading and writing.
@end deftypefn
-@c pexecute.txh:259
+@c pexecute.txh:272
@deftypefn Extension void pex_free (struct pex_obj @var{obj})
Clean up and free all data associated with @var{obj}.
@end deftypefn
-@c pexecute.txh:234
+@c pexecute.txh:247
@deftypefn Extension int pex_get_status (struct pex_obj *@var{obj}, int @var{count}, int *@var{vector})
Returns the exit status of all programs run using @var{obj}.
@@ -685,7 +685,7 @@ to @code{pex_run}. Returns 0 on error, 1 on success.
@end deftypefn
-@c pexecute.txh:243
+@c pexecute.txh:256
@deftypefn Extension int pex_get_times (struct pex_obj *@var{obj}, int @var{count}, struct pex_time *@var{vector})
Returns the process execution times of all programs run using
@@ -734,7 +734,7 @@ temporary files; it may be @code{NULL} to use a randomly chosen name.
@end deftypefn
-@c pexecute.txh:161
+@c pexecute.txh:174
@deftypefn Extension {FILE *} pex_input_file (struct pex_obj *@var{obj}, int @var{flags}, const char *@var{in_name})
Return a stream for a temporary file to pass to the first program in
@@ -752,7 +752,7 @@ binary mode; otherwise, open it in the default mode. Including
@code{PEX_BINARY_OUTPUT} in @var{flags} has no effect on Unix.
@end deftypefn
-@c pexecute.txh:178
+@c pexecute.txh:191
@deftypefn Extension {FILE *} pex_input_pipe (struct pex_obj *@var{obj}, int @var{binary})
Return a stream @var{fp} for a pipe connected to the standard input of
@@ -797,7 +797,7 @@ the output pipe is you, but you are blocked on the input pipe.
@end deftypefn
-@c pexecute.txh:265
+@c pexecute.txh:278
@deftypefn Extension {const char *} pex_one (int @var{flags}, const char *@var{executable}, char * const *@var{argv}, const char *@var{pname}, const char *@var{outname}, const char *@var{errname}, int *@var{status}, int *@var{err})
An interface to permit the easy execution of a
@@ -810,7 +810,7 @@ be set to the exit status of the program.
@end deftypefn
-@c pexecute.txh:222
+@c pexecute.txh:235
@deftypefn Extension {FILE *} pex_read_output (struct pex_obj *@var{obj}, int @var{binary})
Returns a @code{FILE} pointer which may be used to read the standard
@@ -924,6 +924,20 @@ value, or to 0 if there is no relevant @code{errno}.
@end deftypefn
+@c pexecute.txh:161
+@deftypefn Extension {const char *} pex_run_in_environment (struct pex_obj *@var{obj}, int @var{flags}, const char *@var{executable}, char * const *@var{argv}, char * const *@var{env}, int @var{env_size}, const char *@var{outname}, const char *@var{errname}, int *@var{err})
+
+Execute one program in a pipeline, permitting the environment for the
+program to be specified. Behaviour and parameters not listed below are
+as for @code{pex_run}.
+
+@var{env} is the environment for the child process, specified as an array of
+character pointers. Each element of the array should point to a string of the
+form @code{VAR=VALUE}, with the exception of the last element that must be
+@code{NULL}.
+
+@end deftypefn
+
@c pexecute.txh:133
@deftypefn Extension {FILE *} pex_write_input (struct pex_obj *@var{obj}, int @var{binary})
@@ -953,7 +967,7 @@ the output pipe is you, but you are blocked on the input pipe.
@end deftypefn
-@c pexecute.txh:277
+@c pexecute.txh:290
@deftypefn Extension int pexecute (const char *@var{program}, char * const *@var{argv}, const char *@var{this_pname}, const char *@var{temp_base}, char **@var{errmsg_fmt}, char **@var{errmsg_arg}, int flags)
This is the old interface to execute one or more programs. It is
@@ -981,7 +995,7 @@ name is unset/removed.
@end deftypefn
-@c pexecute.txh:285
+@c pexecute.txh:298
@deftypefn Extension int pwait (int @var{pid}, int *@var{status}, int @var{flags})
Another part of the old execution interface.
diff --git a/libiberty/pex-common.c b/libiberty/pex-common.c
index bce2c3b428..e4c063dc69 100644
--- a/libiberty/pex-common.c
+++ b/libiberty/pex-common.c
@@ -142,12 +142,15 @@ temp_file (struct pex_obj *obj, int flags, char *name)
return name;
}
-/* Run a program. */
+
+/* As for pex_run (), but permits the environment for the child process
+ to be specified. */
const char *
-pex_run (struct pex_obj *obj, int flags, const char *executable,
- char * const * argv, const char *orig_outname, const char *errname,
- int *err)
+pex_run_in_environment (struct pex_obj *obj, int flags, const char *executable,
+ char * const * argv, char * const * env,
+ const char *orig_outname, const char *errname,
+ int *err)
{
const char *errmsg;
int in, out, errdes;
@@ -298,8 +301,8 @@ pex_run (struct pex_obj *obj, int flags, const char *executable,
/* Run the program. */
- pid = obj->funcs->exec_child (obj, flags, executable, argv, in, out, errdes,
- &errmsg, err);
+ pid = obj->funcs->exec_child (obj, flags, executable, argv, env,
+ in, out, errdes, &errmsg, err);
if (p[WRITE_PORT] != -1)
obj->funcs->close (obj, p[WRITE_PORT]);
if (pid < 0)
@@ -369,6 +372,17 @@ pex_write_input (struct pex_obj *obj, int binary)
return NULL;
}
+/* Run a program. */
+
+const char *
+pex_run (struct pex_obj *obj, int flags, const char *executable,
+ char * const * argv, const char *orig_outname, const char *errname,
+ int *err)
+{
+ return pex_run_in_environment (obj, flags, executable, argv, NULL,
+ orig_outname, errname, err);
+}
+
/* Return a FILE pointer for a temporary file to fill with input for
the pipeline. */
FILE *
diff --git a/libiberty/pex-common.h b/libiberty/pex-common.h
index 8ded138148..520f26a260 100644
--- a/libiberty/pex-common.h
+++ b/libiberty/pex-common.h
@@ -104,6 +104,7 @@ struct pex_funcs
error and set *ERRMSG and *ERR. */
long (*exec_child) (struct pex_obj *, int /* flags */,
const char */* executable */, char * const * /* argv */,
+ char * const * /* env */,
int /* in */, int /* out */, int /* errdes */,
const char **/* errmsg */, int */* err */);
/* Close a descriptor. Return 0 on success, -1 on error. */
diff --git a/libiberty/pex-djgpp.c b/libiberty/pex-djgpp.c
index 17fbf2cc7e..acaa4c43fd 100644
--- a/libiberty/pex-djgpp.c
+++ b/libiberty/pex-djgpp.c
@@ -45,7 +45,8 @@ extern int errno;
static int pex_djgpp_open_read (struct pex_obj *, const char *, int);
static int pex_djgpp_open_write (struct pex_obj *, const char *, int);
static long pex_djgpp_exec_child (struct pex_obj *, int, const char *,
- char * const *, int, int, int,
+ char * const *, char * const *,
+ int, int, int,
const char **, int *);
static int pex_djgpp_close (struct pex_obj *, int);
static int pex_djgpp_wait (struct pex_obj *, long, int *, struct pex_time *,
@@ -111,7 +112,8 @@ pex_djgpp_close (struct pex_obj *obj ATTRIBUTE_UNUSED, int fd)
static long
pex_djgpp_exec_child (struct pex_obj *obj, int flags, const char *executable,
- char * const * argv, int in, int out, int errdes,
+ char * const * argv, char * const * env,
+ int in, int out, int errdes,
const char **errmsg, int *err)
{
int org_in, org_out, org_errdes;
@@ -196,8 +198,12 @@ pex_djgpp_exec_child (struct pex_obj *obj, int flags, const char *executable,
}
}
- status = (((flags & PEX_SEARCH) != 0 ? spawnvp : spawnv)
- (P_WAIT, executable, (char * const *) argv));
+ if (env)
+ status = (((flags & PEX_SEARCH) != 0 ? spawnvpe : spawnve)
+ (P_WAIT, executable, argv, env));
+ else
+ status = (((flags & PEX_SEARCH) != 0 ? spawnvp : spawnv)
+ (P_WAIT, executable, argv));
if (status == -1)
{
diff --git a/libiberty/pex-msdos.c b/libiberty/pex-msdos.c
index db22337aa2..bcad93dbe2 100644
--- a/libiberty/pex-msdos.c
+++ b/libiberty/pex-msdos.c
@@ -55,8 +55,8 @@ static int pex_msdos_open (struct pex_obj *, const char *, int);
static int pex_msdos_open (struct pex_obj *, const char *, int);
static int pex_msdos_fdindex (struct pex_msdos *, int);
static long pex_msdos_exec_child (struct pex_obj *, int, const char *,
- char * const *, int, int, int,
- const char **, int *);
+ char * const *, char * const *,
+ int, int, int, const char **, int *);
static int pex_msdos_close (struct pex_obj *, int);
static int pex_msdos_wait (struct pex_obj *, long, int *, struct pex_time *,
int, const char **, int *);
@@ -153,7 +153,7 @@ pex_msdos_close (struct pex_obj *obj, int fd)
static long
pex_msdos_exec_child (struct pex_obj *obj, int flags, const char *executable,
- char * const * argv, int in, int out,
+ char * const * argv, char * const * env, int in, int out,
int errdes ATTRIBUTE_UNUSED, const char **errmsg,
int *err)
{
diff --git a/libiberty/pex-unix.c b/libiberty/pex-unix.c
index c92a429797..91619af1e2 100644
--- a/libiberty/pex-unix.c
+++ b/libiberty/pex-unix.c
@@ -270,8 +270,8 @@ static void pex_child_error (struct pex_obj *, const char *, const char *, int)
static int pex_unix_open_read (struct pex_obj *, const char *, int);
static int pex_unix_open_write (struct pex_obj *, const char *, int);
static long pex_unix_exec_child (struct pex_obj *, int, const char *,
- char * const *, int, int, int,
- const char **, int *);
+ char * const *, char * const *,
+ int, int, int, const char **, int *);
static int pex_unix_close (struct pex_obj *, int);
static int pex_unix_wait (struct pex_obj *, long, int *, struct pex_time *,
int, const char **, int *);
@@ -352,12 +352,16 @@ pex_child_error (struct pex_obj *obj, const char *executable,
/* Execute a child. */
+extern char **environ;
+
static long
pex_unix_exec_child (struct pex_obj *obj, int flags, const char *executable,
- char * const * argv, int in, int out, int errdes,
+ char * const * argv, char * const * env,
+ int in, int out, int errdes,
const char **errmsg, int *err)
{
pid_t pid;
+
/* We declare these to be volatile to avoid warnings from gcc about
them being clobbered by vfork. */
volatile int sleep_interval;
@@ -409,6 +413,10 @@ pex_unix_exec_child (struct pex_obj *obj, int flags, const char *executable,
if (dup2 (STDOUT_FILE_NO, STDERR_FILE_NO) < 0)
pex_child_error (obj, executable, "dup2", errno);
}
+
+ if (env)
+ environ = env;
+
if ((flags & PEX_SEARCH) != 0)
{
execvp (executable, argv);
diff --git a/libiberty/pex-win32.c b/libiberty/pex-win32.c
index 046f393c6d..45725457b6 100644
--- a/libiberty/pex-win32.c
+++ b/libiberty/pex-win32.c
@@ -36,12 +36,14 @@ Boston, MA 02110-1301, USA. */
#include <sys/wait.h>
#endif
+#include <assert.h>
#include <process.h>
#include <io.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/stat.h>
#include <errno.h>
+#include <ctype.h>
/* mingw32 headers may not define the following. */
@@ -59,6 +61,8 @@ Boston, MA 02110-1301, USA. */
#define MINGW_NAME "Minimalist GNU for Windows"
#define MINGW_NAME_LEN (sizeof(MINGW_NAME) - 1)
+extern char *stpcpy (char *dst, const char *src);
+
/* Ensure that the executable pathname uses Win32 backslashes. This
is not necessary on NT, but on W9x, forward slashes causes
failure of spawn* and exec* functions (and probably any function
@@ -76,7 +80,8 @@ backslashify (char *s)
static int pex_win32_open_read (struct pex_obj *, const char *, int);
static int pex_win32_open_write (struct pex_obj *, const char *, int);
static long pex_win32_exec_child (struct pex_obj *, int, const char *,
- char * const *, int, int, int,
+ char * const *, char * const *,
+ int, int, int,
const char **, int *);
static int pex_win32_close (struct pex_obj *, int);
static int pex_win32_wait (struct pex_obj *, long, int *,
@@ -478,22 +483,96 @@ find_executable (const char *program, BOOL search)
return full_executable;
}
-/* Low-level process creation function. */
+/* Low-level process creation function and helper. */
+
+static int
+env_compare (const void *a_ptr, const void *b_ptr)
+{
+ const char *a;
+ const char *b;
+ unsigned char c1;
+ unsigned char c2;
+
+ a = *(const char **) a_ptr;
+ b = *(const char **) b_ptr;
+
+ /* a and b will be of the form: VAR=VALUE
+ We compare only the variable name part here using a case-insensitive
+ comparison algorithm. It might appear that in fact strcasecmp () can
+ take the place of this whole function, and indeed it could, save for
+ the fact that it would fail in cases such as comparing A1=foo and
+ A=bar (because 1 is less than = in the ASCII character set).
+ (Environment variables containing no numbers would work in such a
+ scenario.) */
+
+ do
+ {
+ c1 = (unsigned char) tolower (*a++);
+ c2 = (unsigned char) tolower (*b++);
+
+ if (c1 == '=')
+ c1 = '\0';
+
+ if (c2 == '=')
+ c2 = '\0';
+ }
+ while (c1 == c2 && c1 != '\0');
+
+ return c1 - c2;
+}
static long
win32_spawn (const char *executable,
BOOL search,
char *const *argv,
+ char *const *env, /* array of strings of the form: VAR=VALUE */
DWORD dwCreationFlags,
LPSTARTUPINFO si,
LPPROCESS_INFORMATION pi)
{
char *full_executable;
char *cmdline;
+ char **env_copy;
+ char *env_block = NULL;
full_executable = NULL;
cmdline = NULL;
+ if (env)
+ {
+ int env_size;
+
+ /* Count the number of environment bindings supplied. */
+ for (env_size = 0; env[env_size]; env_size++)
+ continue;
+
+ /* Assemble an environment block, if required. This consists of
+ VAR=VALUE strings juxtaposed (with one null character between each
+ pair) and an additional null at the end. */
+ if (env_size > 0)
+ {
+ int var;
+ int total_size = 1; /* 1 is for the final null. */
+ char *bufptr;
+
+ /* Windows needs the members of the block to be sorted by variable
+ name. */
+ env_copy = alloca (sizeof (char *) * env_size);
+ memcpy (env_copy, env, sizeof (char *) * env_size);
+ qsort (env_copy, env_size, sizeof (char *), env_compare);
+
+ for (var = 0; var < env_size; var++)
+ total_size += strlen (env[var]) + 1;
+
+ env_block = malloc (total_size);
+ bufptr = env_block;
+ for (var = 0; var < env_size; var++)
+ bufptr = stpcpy (bufptr, env_copy[var]) + 1;
+
+ *bufptr = '\0';
+ }
+ }
+
full_executable = find_executable (executable, search);
if (!full_executable)
goto error;
@@ -507,31 +586,41 @@ win32_spawn (const char *executable,
/*lpThreadAttributes=*/NULL,
/*bInheritHandles=*/TRUE,
dwCreationFlags,
- /*lpEnvironment=*/NULL,
+ (LPVOID) env_block,
/*lpCurrentDirectory=*/NULL,
si,
pi))
{
+ if (env_block)
+ free (env_block);
+
free (full_executable);
+
return -1;
}
/* Clean up. */
CloseHandle (pi->hThread);
free (full_executable);
+ if (env_block)
+ free (env_block);
return (long) pi->hProcess;
error:
+ if (env_block)
+ free (env_block);
if (cmdline)
free (cmdline);
if (full_executable)
free (full_executable);
+
return -1;
}
static long
spawn_script (const char *executable, char *const *argv,
+ char* const *env,
DWORD dwCreationFlags,
LPSTARTUPINFO si,
LPPROCESS_INFORMATION pi)
@@ -566,20 +655,20 @@ spawn_script (const char *executable, char *const *argv,
executable = strrchr (executable1, '\\') + 1;
if (!executable)
executable = executable1;
- pid = win32_spawn (executable, TRUE, argv,
+ pid = win32_spawn (executable, TRUE, argv, env,
dwCreationFlags, si, pi);
#else
if (strchr (executable1, '\\') == NULL)
- pid = win32_spawn (executable1, TRUE, argv,
+ pid = win32_spawn (executable1, TRUE, argv, env,
dwCreationFlags, si, pi);
else if (executable1[0] != '\\')
- pid = win32_spawn (executable1, FALSE, argv,
+ pid = win32_spawn (executable1, FALSE, argv, env,
dwCreationFlags, si, pi);
else
{
const char *newex = mingw_rootify (executable1);
*avhere = newex;
- pid = win32_spawn (newex, FALSE, argv,
+ pid = win32_spawn (newex, FALSE, argv, env,
dwCreationFlags, si, pi);
if (executable1 != newex)
free ((char *) newex);
@@ -589,7 +678,7 @@ spawn_script (const char *executable, char *const *argv,
if (newex != executable1)
{
*avhere = newex;
- pid = win32_spawn (newex, FALSE, argv,
+ pid = win32_spawn (newex, FALSE, argv, env,
dwCreationFlags, si, pi);
free ((char *) newex);
}
@@ -609,6 +698,7 @@ spawn_script (const char *executable, char *const *argv,
static long
pex_win32_exec_child (struct pex_obj *obj ATTRIBUTE_UNUSED, int flags,
const char *executable, char * const * argv,
+ char* const* env,
int in, int out, int errdes, const char **errmsg,
int *err)
{
@@ -686,9 +776,10 @@ pex_win32_exec_child (struct pex_obj *obj ATTRIBUTE_UNUSED, int flags,
/* Create the child process. */
pid = win32_spawn (executable, (flags & PEX_SEARCH) != 0,
- argv, dwCreationFlags, &si, &pi);
+ argv, env, dwCreationFlags, &si, &pi);
if (pid == -1)
- pid = spawn_script (executable, argv, dwCreationFlags, &si, &pi);
+ pid = spawn_script (executable, argv, env, dwCreationFlags,
+ &si, &pi);
if (pid == -1)
{
*err = ENOENT;
@@ -789,7 +880,7 @@ main (int argc ATTRIBUTE_UNUSED, char **argv)
char const *errmsg;
int err;
argv++;
- printf ("%ld\n", pex_win32_exec_child (NULL, PEX_SEARCH, argv[0], argv, 0, 1, 2, &errmsg, &err));
+ printf ("%ld\n", pex_win32_exec_child (NULL, PEX_SEARCH, argv[0], argv, NULL, 0, 0, 1, 2, &errmsg, &err));
exit (0);
}
#endif
diff --git a/libiberty/pexecute.txh b/libiberty/pexecute.txh
index e3f1248407..d7745f2122 100644
--- a/libiberty/pexecute.txh
+++ b/libiberty/pexecute.txh
@@ -158,6 +158,19 @@ the output pipe is you, but you are blocked on the input pipe.
@end deftypefn
+@deftypefn Extension {const char *} pex_run_in_environment (struct pex_obj *@var{obj}, int @var{flags}, const char *@var{executable}, char * const *@var{argv}, char * const *@var{env}, int @var{env_size}, const char *@var{outname}, const char *@var{errname}, int *@var{err})
+
+Execute one program in a pipeline, permitting the environment for the
+program to be specified. Behaviour and parameters not listed below are
+as for @code{pex_run}.
+
+@var{env} is the environment for the child process, specified as an array of
+character pointers. Each element of the array should point to a string of the
+form @code{VAR=VALUE}, with the exception of the last element that must be
+@code{NULL}.
+
+@end deftypefn
+
@deftypefn Extension {FILE *} pex_input_file (struct pex_obj *@var{obj}, int @var{flags}, const char *@var{in_name})
Return a stream for a temporary file to pass to the first program in