# 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, "");
 }
 
 /*

Reply via email to