Patch to provide pex_run_in_environment.

* 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.

From-SVN: r114302
This commit is contained in:
Mark Shinwell 2006-06-01 10:30:51 +00:00 committed by Mark Shinwell
parent 7d6d782d02
commit ea60341e32
11 changed files with 222 additions and 36 deletions

View File

@ -1,3 +1,7 @@
2006-06-01 Mark Shinwell <shinwell@codesourcery.com>
* include/libiberty.h: Declare pex_run_in_environment.
2006-05-31 Asher Langton <langton2@llnl.gov>
* MAINTAINERS (Write After Approval): Add myself.

View File

@ -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.

View File

@ -1,3 +1,21 @@
2006-06-01 Mark Shinwell <shinwell@codesourcery.com>
* 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-05-28 Mark Shinwell <shinwell@codesourcery.com>
* mkstemps.c: Open temporary files in binary mode.

View File

@ -668,14 +668,14 @@ reading and writing.
@end deftypefn
@c pexecute.txh:231
@c pexecute.txh:244
@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:206
@c pexecute.txh:219
@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:215
@c pexecute.txh:228
@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:133
@c pexecute.txh:146
@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:150
@c pexecute.txh:163
@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:237
@c pexecute.txh:250
@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:194
@c pexecute.txh:207
@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,7 +924,21 @@ value, or to 0 if there is no relevant @code{errno}.
@end deftypefn
@c pexecute.txh:249
@c pexecute.txh:133
@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:262
@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
@ -952,7 +966,7 @@ name is unset/removed.
@end deftypefn
@c pexecute.txh:257
@c pexecute.txh:270
@deftypefn Extension int pwait (int @var{pid}, int *@var{status}, int @var{flags})
Another part of the old execution interface.

View File

@ -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;
@ -296,8 +299,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 (pid < 0)
goto error_exit;
@ -319,6 +322,17 @@ pex_run (struct pex_obj *obj, int flags, const char *executable,
return errmsg;
}
/* 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 *

View File

@ -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. */

View File

@ -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)
{

View File

@ -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)
{

View File

@ -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);

View File

@ -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

View File

@ -130,6 +130,19 @@ value, or to 0 if there is no relevant @code{errno}.
@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