# New Ticket Created by Ron Blaschke
# Please include the string: [perl #43235]
# in the subject line of all future correspondence about this issue.
# <URL: http://rt.perl.org/rt3/Ticket/Display.html?id=43235 >
Attached patch should take care of tickets #37301 and #40972.
Windows XP - Visual C++ 8
$ runtests -v t\pmc\env.t
t\pmc\env......
1..12
ok 1 - all Envs are ident
ok 2 - getenv
ok 3 - setenv/getenv
ok 4 - envs are all the same
ok 5 - gone/delete
ok 6 - iterate
ok 7 - exists/delete
ok 8 - check whether interface is done
ok 9 - get_integer()
ok 10 - get_number()
ok 11 - getenv - null key
ok 12 - setenv/getenv - PMC key
ok
All tests successful.
Files=1, Tests=12, 1 wallclock secs ( 0.00 cusr + 0.00 csys = 0.00 CPU)
Windows XP - MinGW (GCC)
$ runtests -v t\pmc\env.t
t\pmc\env......
1..12
ok 1 - all Envs are ident
ok 2 - getenv
ok 3 - setenv/getenv
ok 4 - envs are all the same
ok 5 - gone/delete
ok 6 - iterate
ok 7 - exists/delete
ok 8 - check whether interface is done
ok 9 - get_integer()
ok 10 - get_number()
ok 11 - getenv - null key
ok 12 - setenv/getenv - PMC key
ok
All tests successful.
Files=1, Tests=12, 2 wallclock secs ( 0.00 cusr + 0.00 csys = 0.00 CPU)
Ron
Index: t/pmc/env.t
===================================================================
--- t/pmc/env.t (revision 19066)
+++ t/pmc/env.t (working copy)
@@ -92,11 +92,7 @@
ok 2
OUT
-SKIP:
-{
- skip 'iterator not available on win32' => 1
- if 'MSWin32' eq $^O;
- pasm_output_is( <<'CODE', <<OUT, "iterate" );
+pasm_output_is( <<'CODE', <<OUT, "iterate" );
new P0, .Env
set P0["PARROT_1"], "hello"
set P0["PARROT_2"], "polly"
@@ -121,10 +117,8 @@
CODE
ok
OUT
-}
SKIP: {
-
# This will not work on our unsetenv implementation
skip( "no native unsetenv", 1 ) unless $PConfig{"unsetenv"};
pasm_output_is( <<'CODE', <<OUT, "exists/delete" );
@@ -173,10 +167,7 @@
0
OUTPUT
-SKIP: {
- skip 'not changing environment on windows', 2 if $^O eq 'MSWin32';
-
- pir_output_is( << 'CODE', << 'OUTPUT', "get_integer()" );
+pir_output_is( << 'CODE', << 'OUTPUT', "get_integer()" );
.sub main
.local pmc env
.local int num_before, num_after, num_diff
@@ -197,7 +188,7 @@
3
OUTPUT
- pir_output_is( << 'CODE', << 'OUTPUT', "get_number()" );
+pir_output_is( << 'CODE', << 'OUTPUT', "get_number()" );
.sub main
.local pmc env
.local num num_before, num_after, num_diff
@@ -217,7 +208,6 @@
CODE
3.000000
OUTPUT
-}
pasm_output_is( <<'CODE', <<OUT, "getenv - null key" );
new P0, .Env
Index: config/gen/platform/win32/env.c
===================================================================
--- config/gen/platform/win32/env.c (revision 19066)
+++ config/gen/platform/win32/env.c (working copy)
@@ -1,14 +1,59 @@
/*
+ On Windows there are two ways to access the environment. Either through the
+ Windows environment block, using GetEnvironmentVariable,
+ SetEnvironmentVariable and GetEnvironmentStrings, or the C runtime using
+ _getenv, _putenv and _environ.
+
+ Changes through the C runtime are reflected in the environment block, but
+ changes in the environment block are NOT reflected in the C runtime!
+
+ To keep both in sync we always update environment variables through the C
+ runtime. Getting an environment variable can be done either way,
+ whichever is more convenient.
+*/
+
+/*
** Parrot_setenv()
*/
void
Parrot_setenv(const char *name, const char *value)
{
- SetEnvironmentVariable(name, value);
+ assert(name != NULL);
+ assert(value != NULL);
+
+ {
+ const int name_len = strlen(name );
+ const int value_len = strlen(value);
+
+ {
+ char * const envstring = malloc(
+ name_len /* name */
+ + 1 /* '=' */
+ + value_len /* value */
+ + 1 /* string terminator */
+ );
+ if (envstring == NULL) {
+ /* TODO: Shouldn't we tell anyone that we failed? */
+ return;
+ }
+
+ /* Save a bit of time, by using the fact we already have the
+ lengths, avoiding strcat */
+ strcpy(envstring, name );
+ strcpy(envstring + name_len, "=" );
+ strcpy(envstring + name_len + 1, value);
+
+ if (_putenv(envstring) == 0) {
+ /* success */
+ } else {
+ /* TODO: Shouldn't we tell anyone that we failed? */
+ }
+ free(envstring);
+ }
+ }
}
-
char *
Parrot_getenv(const char *name, int *free_it)
{
@@ -25,10 +70,15 @@
return buffer;
}
+
void
Parrot_unsetenv(const char *name)
{
- SetEnvironmentVariable(name, NULL);
+/* You can remove a variable from the environment by specifying an empty
+ string -- in other words, by specifying only varname=.
+ -- _putenv, _wputenv (CRT) documentation
+*/
+ Parrot_setenv(name, "");
}
/*