summaryrefslogtreecommitdiff
path: root/win32/win32.c
diff options
context:
space:
mode:
authorPhil Monsen <philip.monsen@pobox.com>2011-07-18 22:16:55 -0500
committerFather Chrysostomos <sprout@cpan.org>2011-07-18 21:58:13 -0700
commit1fcb0052e32fe8c260e83b2ece033e2ca2f30a92 (patch)
treedfcda30a0ccb54fa4f2946bf529af84f664801c5 /win32/win32.c
parentcd197e1e6cdf55043b0cf56f5dbe8fc0c5426002 (diff)
downloadperl-1fcb0052e32fe8c260e83b2ece033e2ca2f30a92.tar.gz
Fixes to allow win32 Perl to properly handle PERL5LIB.
On Windows Vista, 7 and 2008, the win32 API call GetEnvironmentVariableA() does not return environment values with string length of greater than 32766, even though such variables are supported in the environment. This consequently caused @INC not to be populated for such values of PERL5LIB on those OSes, as reported in RT #87322. This commit reworks the code so that GetEnvironmentStrings() is called if GetEnvironmentVariableA() indicates the requested value is set in the environmtn. The old fallback of consulting the registry for variables beginning with "PERL" is retained, but as a last-ditch fallback rather than the only recourse. A new test file, t/win32/runenv.t has been added to validate that the new behavior is working properly, as well as that general environment variable handling is in accordance with expectations, since t/run/runenv.t does not run on Win* platforms. The new test file is essentially a non-forking clone of t/run/runenv.t, with modifications to test cases to run properly on Win* platforms, and with a new test case to test the new behavior.
Diffstat (limited to 'win32/win32.c')
-rw-r--r--win32/win32.c36
1 files changed, 32 insertions, 4 deletions
diff --git a/win32/win32.c b/win32/win32.c
index cffd2b5bca..e67a7352be 100644
--- a/win32/win32.c
+++ b/win32/win32.c
@@ -1693,6 +1693,7 @@ win32_getenv(const char *name)
dTHX;
DWORD needlen;
SV *curitem = NULL;
+ DWORD last_err;
needlen = GetEnvironmentVariableA(name,NULL,0);
if (needlen != 0) {
@@ -1705,10 +1706,37 @@ win32_getenv(const char *name)
SvCUR_set(curitem, needlen);
}
else {
- /* allow any environment variables that begin with 'PERL'
- to be stored in the registry */
- if (strncmp(name, "PERL", 4) == 0)
- (void)get_regstr(name, &curitem);
+ last_err = GetLastError();
+ if (last_err == ERROR_NOT_ENOUGH_MEMORY) {
+ /* It appears the variable is in the env, but the Win32 API
+ doesn't have a canned way of getting it. So we fall back to
+ grabbing the whole env and pulling this value out if possible */
+ char *envv = GetEnvironmentStrings();
+ char *cur = envv;
+ STRLEN len;
+ while (*cur) {
+ char *end = strchr(cur,'=');
+ if (end && end != cur) {
+ *end = '\0';
+ if (!strcmp(cur,name)) {
+ curitem = sv_2mortal(newSVpv(end+1,0));
+ *end = '=';
+ break;
+ }
+ *end = '=';
+ cur = end + strlen(end+1)+2;
+ }
+ else if ((len = strlen(cur)))
+ cur += len+1;
+ }
+ FreeEnvironmentStrings(envv);
+ }
+ else {
+ /* last ditch: allow any environment variables that begin with 'PERL'
+ to be obtained from the registry, if found there */
+ if (strncmp(name, "PERL", 4) == 0)
+ (void)get_regstr(name, &curitem);
+ }
}
if (curitem && SvCUR(curitem))
return SvPVX(curitem);