Subject: [PATCH] for NETaa13787: %ENV=(); doesn't clear the environment
Perl maintains two representations of the environment:
(A) a hash named %ENV, used by the perl script
(B) a char** named environ, which is passed to child processes
Obviously, the intent is to keep tho two in sync.
This fails in two situations:
(1) A list assignment to %ENV clears (A) but not (B);
(2) Assigning to $0 has the side effect of deleting the key
NoNeSuCh form (B) but not from (A).
$ perl -e '%ENV=(); print "home\n" if exists $ENV{HOME}; exec "echo \$HOME";'
/Users/hansm
$ perl -e '$ENV{NoNeSuCh} = "foo"; $0 = "bar"; exec "echo \$NoNeSuCh";'
$ perl -e '$ENV{NoNeSuCh} = "foo"; exec "echo \$NoNeSuCh";'
foo
$
I've complained about rpoblem (1) before; and Larry assigned
it bug ID NETaa13787 when he entered it into DDTS.
The patch below attempts to remedy both problems, at least on
Unix platforms. I don't know how to handle the environment
on VMS and WIN32; my code simply calls DIE('unimplemented"),
which is honest but won't make users on those plaforms happy.
p5p-msgid:
199705292240.AAA01135@mail.euronet.nl
Signed-off-by: Peter Prymmer <pvhp@forte.com>
#define lshift_ass_amg Perl_lshift_ass_amg
#define lt_amg Perl_lt_amg
#define magic_clearenv Perl_magic_clearenv
+#define magic_clear_all_env Perl_magic_clear_all_env
#define magic_clearpack Perl_magic_clearpack
#define magic_clearsig Perl_magic_clearsig
#define magic_existspack Perl_magic_existspack
localize
looks_like_number
magic_clearenv
+magic_clearenviron
magic_clearpack
magic_clearsig
magic_existspack
}
int
+magic_clear_all_env()
+{
+#if defined(VMS) || defined(WIN32)
+ DIE("'%ENV = @list;' is not implemented on this machine");
+#else
+ I32 i;
+
+ if (environ == origenviron)
+ New(901, environ, 1, char*);
+ else
+ for (i = 0; environ[i]; i++)
+ Safefree(environ[i]);
+ environ[0] = Nullch;
+
+ return 0;
+#endif
+}
+
+int
magic_getsig(sv,mg)
SV* sv;
MAGIC* mg;
}
/* can grab env area too? */
if (origenviron && origenviron[0] == s + 1) {
- my_setenv("NoNeSuCh", Nullch);
+ my_setenv("NoNe SuCh", Nullch);
/* force copy of environment */
for (i = 0; origenviron[i]; i++)
if (origenviron[i] == s + 1)
magic_set,
magic_len,
0, 0};
-EXT MGVTBL vtbl_env = {0, 0, 0, 0, 0};
+EXT MGVTBL vtbl_env = {0, 0, 0, magic_clear_all_env,
+ 0};
EXT MGVTBL vtbl_envelem = {0, magic_setenv,
0, magic_clearenv,
0};
OP* localize _((OP* arg, I32 lexical));
I32 looks_like_number _((SV* sv));
int magic_clearenv _((SV* sv, MAGIC* mg));
+int magic_clear_all_env _((void));
int magic_clearpack _((SV* sv, MAGIC* mg));
int magic_clearsig _((SV* sv, MAGIC* mg));
int magic_existspack _((SV* sv, MAGIC* mg));
$Is_MSWin32 = ($^O eq 'MSWin32');
$PERL = ($Is_MSWin32 ? '.\perl' : './perl');
-print "1..28\n";
+print "1..30\n";
eval '$ENV{"foo"} = "hi there";'; # check that ENV is inited inside eval
if ($Is_MSWin32) { ok 1, `cmd /x /c set foo` eq "foo=hi there\n"; }
ok 26, $] >= 5.00319, $];
ok 27, $^O;
ok 28, $^T > 850000000, $^T;
+
+if ($Is_MSWin32) {
+ ok 29, 1;
+ ok 30, 1;
+}
+else {
+ %ENV = ();
+ ok 29, `echo \$foo` eq "\n";
+
+ $ENV{NoNeSuCh} = "foo";
+ $0 = "bar";
+ ok 30, `echo \$NoNeSuCh` eq "foo\n";
+}