From 03d6fe120a36c805008cc611ad140e2a222dc8b0 Mon Sep 17 00:00:00 2001 From: Ray Donnelly Date: Sun, 10 Apr 2016 21:47:41 +0100 Subject: [PATCH] environ.cc: New facility/environment variable MSYS2_ENV_CONV_EXCL Works very much like MSYS2_ARG_CONV_EXCL. In fact it uses the same function, arg_heuristic_with_exclusions (). Also refactors parsing the env. variables to use new function, string_split_delimited (). The env. that is searched through is the merged (POSIX + Windows) one. It remains to be seen if this should be made an option or not. This feature was prompted because the R language (Windows exe) calls bash to run configure.win, which then calls back into R to read its config variables (LOCAL_SOFT) and when this happens, msys2-runtime converts R_ARCH from "/x64" to an absolute Windows path and appends it to another absolute path, R_HOME, forming an invalid path. --- winsup/cygwin/environ.cc | 34 +++++++++++++++++------- winsup/cygwin/local_includes/miscfuncs.h | 2 ++ winsup/cygwin/miscfuncs.cc | 20 ++++++++++++++ winsup/cygwin/path.cc | 1 - winsup/cygwin/spawn.cc | 12 ++------- 5 files changed, 48 insertions(+), 21 deletions(-) diff --git a/winsup/cygwin/environ.cc b/winsup/cygwin/environ.cc index 117531367e..a9cce9645a 100644 --- a/winsup/cygwin/environ.cc +++ b/winsup/cygwin/environ.cc @@ -1173,6 +1173,10 @@ build_env (const char * const *envp, PWCHAR &envblock, int &envc, int tl = 0; char **pass_dstp; +#ifdef __MSYS__ + char *msys2_env_conv_excl_env = NULL; + size_t msys2_env_conv_excl_count = 0; +#endif char **pass_env = (char **) alloca (sizeof (char *) * (n + winnum + SPENVS_SIZE + 1)); /* Iterate over input list, generating a new environment list and refreshing @@ -1181,16 +1185,25 @@ build_env (const char * const *envp, PWCHAR &envblock, int &envc, { bool calc_tl = !no_envblock; #ifdef __MSYS__ - /* Don't pass timezone environment to non-msys applications */ - if (!keep_posix && ascii_strncasematch(*srcp, "TZ=", 3)) + if (!keep_posix) { - const char *v = *srcp + 3; - if (*v == ':') - goto next1; - for (; *v; v++) - if (!isalpha(*v) && !isdigit(*v) && - *v != '-' && *v != '+' && *v != ':') - goto next1; + /* Don't pass timezone environment to non-msys applications */ + if (ascii_strncasematch(*srcp, "TZ=", 3)) + { + const char *v = *srcp + 3; + if (*v == ':') + goto next1; + for (; *v; v++) + if (!isalpha(*v) && !isdigit(*v) && + *v != '-' && *v != '+' && *v != ':') + goto next1; + } + else if (ascii_strncasematch(*srcp, "MSYS2_ENV_CONV_EXCL=", 20)) + { + msys2_env_conv_excl_env = (char*)alloca (strlen(&(*srcp)[20])+1); + strcpy (msys2_env_conv_excl_env, &(*srcp)[20]); + msys2_env_conv_excl_count = string_split_delimited (msys2_env_conv_excl_env, ';'); + } } #endif /* Look for entries that require special attention */ @@ -1315,7 +1328,8 @@ build_env (const char * const *envp, PWCHAR &envblock, int &envc, } #ifdef __MSYS__ else if (!keep_posix) { - char *win_arg = arg_heuristic(*srcp); + char *win_arg = arg_heuristic_with_exclusions + (*srcp, msys2_env_conv_excl_env, msys2_env_conv_excl_count); debug_printf("WIN32_PATH is %s", win_arg); p = cstrdup1(win_arg); if (win_arg != *srcp) diff --git a/winsup/cygwin/local_includes/miscfuncs.h b/winsup/cygwin/local_includes/miscfuncs.h index d52debad1a..c4dbe0235b 100644 --- a/winsup/cygwin/local_includes/miscfuncs.h +++ b/winsup/cygwin/local_includes/miscfuncs.h @@ -81,6 +81,8 @@ void backslashify (const char *, char *, bool); void slashify (const char *, char *, bool); #define isslash(c) ((c) == '/') +size_t string_split_delimited (char * string, char delimiter); + extern void transform_chars (PWCHAR, PWCHAR); extern inline void transform_chars (PUNICODE_STRING upath, USHORT start_idx) diff --git a/winsup/cygwin/miscfuncs.cc b/winsup/cygwin/miscfuncs.cc index 767384faa9..160c996116 100644 --- a/winsup/cygwin/miscfuncs.cc +++ b/winsup/cygwin/miscfuncs.cc @@ -311,6 +311,26 @@ NT_readline::gets () } } +/* Searches through string for delimiter replacing each instance with '\0' + and returning the number of such delimited substrings. This function + Will return 0 for the NULL string and at least 1 otherwise. */ + +size_t +string_split_delimited (char * string, char delimiter) +{ + if ( string == NULL ) + return 0; + size_t count = 1; + string = strchr ( string, delimiter ); + while (string) + { + *string = '\0'; + ++count; + string = strchr ( string + 1, delimiter ); + } + return count; +} + /* Signal the thread name to any attached debugger (See "How to: Set a Thread Name in Native Code" diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc index b1a088a9fd..39819dc694 100644 --- a/winsup/cygwin/path.cc +++ b/winsup/cygwin/path.cc @@ -4051,7 +4051,6 @@ arg_heuristic_with_exclusions (char const * const arg, char const * exclusions, return arg_result; } - debug_printf("Input value: (%s)", arg); for (size_t excl = 0; excl < exclusions_count; ++excl) { /* Since we've got regex linked we should maybe switch to that, but diff --git a/winsup/cygwin/spawn.cc b/winsup/cygwin/spawn.cc index ace43db0a7..57231b3c2e 100644 --- a/winsup/cygwin/spawn.cc +++ b/winsup/cygwin/spawn.cc @@ -293,8 +293,7 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv, int res = -1; /* Environment variable MSYS2_ARG_CONV_EXCL contains a list - of ';' separated argument prefixes to pass un-modified.. - It isn't applied to env. variables; only spawn arguments. + of ';' separated argument prefixes to pass un-modified. A value of * means don't convert any arguments. */ char* msys2_arg_conv_excl_env = getenv("MSYS2_ARG_CONV_EXCL"); char* msys2_arg_conv_excl = NULL; @@ -303,14 +302,7 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv, { msys2_arg_conv_excl = (char*)alloca (strlen(msys2_arg_conv_excl_env)+1); strcpy (msys2_arg_conv_excl, msys2_arg_conv_excl_env); - msys2_arg_conv_excl_count = 1; - msys2_arg_conv_excl_env = strchr ( msys2_arg_conv_excl, ';' ); - while (msys2_arg_conv_excl_env) - { - *msys2_arg_conv_excl_env = '\0'; - ++msys2_arg_conv_excl_count; - msys2_arg_conv_excl_env = strchr ( msys2_arg_conv_excl_env + 1, ';' ); - } + msys2_arg_conv_excl_count = string_split_delimited (msys2_arg_conv_excl, ';'); } /* Check if we have been called from exec{lv}p or spawn{lv}p and mask