From 223a68cbc78401d514b5bd0f39d0d1d5e758a38d Mon Sep 17 00:00:00 2001 From: shinwell Date: Thu, 1 Jun 2006 10:30:51 +0000 Subject: 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@114302 138bc75d-0d04-0410-961f-82ee72b054a4 --- libiberty/pex-win32.c | 113 +++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 102 insertions(+), 11 deletions(-) (limited to 'libiberty/pex-win32.c') diff --git a/libiberty/pex-win32.c b/libiberty/pex-win32.c index 046f393c6d9..45725457b6a 100644 --- a/libiberty/pex-win32.c +++ b/libiberty/pex-win32.c @@ -36,12 +36,14 @@ Boston, MA 02110-1301, USA. */ #include #endif +#include #include #include #include #include #include #include +#include /* 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 -- cgit v1.2.1