diff options
author | Ron Yorston <rmy@pobox.com> | 2022-05-05 15:14:10 +0100 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2022-05-05 15:14:10 +0100 |
commit | 3b5042430fc4b82d44e0430f9ecc21a9228d1651 (patch) | |
tree | 192bbe0db34239cbc927ddeece00162584bca2d4 | |
parent | 9e535b09a70a1ef7a2260e6d6955f7bbf291a08f (diff) | |
download | busybox-w32-3b5042430fc4b82d44e0430f9ecc21a9228d1651.tar.gz busybox-w32-3b5042430fc4b82d44e0430f9ecc21a9228d1651.tar.bz2 busybox-w32-3b5042430fc4b82d44e0430f9ecc21a9228d1651.zip |
win32: better fix for empty environment variables
It appears the CRT and OS each have a copy of the environment.
mingw_putenv() fools the CRT into accepting an empty environment
variable by calling _putenv("V=0") then truncating the new value
by hand. But _putenv() also updates the OS environment with the
fake 'V=0' value. Commit 5b48ca53b (win32: pass NULL to spawnve,
not environ) resulted in this fake value being used and hence empty
variables getting the value '0'.
- Add a call to SetEnvironmentVariable() in mingw_putenv() to update
the OS environment.
- Restore the use of NULL environment pointers in mingw_spawnvp().
- Add a test.
(GitHub issue #250)
-rwxr-xr-x | testsuite/env.tests | 67 | ||||
-rw-r--r-- | win32/env.c | 4 | ||||
-rw-r--r-- | win32/process.c | 13 |
3 files changed, 75 insertions, 9 deletions
diff --git a/testsuite/env.tests b/testsuite/env.tests new file mode 100755 index 000000000..456808728 --- /dev/null +++ b/testsuite/env.tests | |||
@@ -0,0 +1,67 @@ | |||
1 | #!/bin/sh | ||
2 | # Copyright 2022 by Ron Yorston | ||
3 | # Licensed under GPLv2, see file LICENSE in this source tree. | ||
4 | |||
5 | . ./testing.sh | ||
6 | |||
7 | # testing "test name" "commands" "expected result" "file input" "stdin" | ||
8 | |||
9 | # Not so much a test of 'env' as of whether environment variables | ||
10 | # (or the lack thereof) are correctly passed to child processes. | ||
11 | testing "environment variables 1a" \ | ||
12 | "V=set env sh -c 'env | grep ^V='" \ | ||
13 | "V=set | ||
14 | " "" "" | ||
15 | |||
16 | testing "environment variables 1b" \ | ||
17 | "V= env sh -c 'env | grep ^V='" \ | ||
18 | "V= | ||
19 | " "" "" | ||
20 | |||
21 | testing "environment variables 1c" \ | ||
22 | "env sh -c 'env | grep ^V='" \ | ||
23 | "" "" "" | ||
24 | |||
25 | testing "environment variables 2a" \ | ||
26 | "V=set sh -c 'env | grep ^V='" \ | ||
27 | "V=set | ||
28 | " "" "" | ||
29 | |||
30 | testing "environment variables 2b" \ | ||
31 | "V= sh -c 'env | grep ^V='" \ | ||
32 | "V= | ||
33 | " "" "" | ||
34 | |||
35 | testing "environment variables 2c" \ | ||
36 | "sh -c 'env | grep ^V='" \ | ||
37 | "" "" "" | ||
38 | |||
39 | testing "environment variables 3a" \ | ||
40 | "V=set env sh -c 'echo \${V-unset}'" \ | ||
41 | "set | ||
42 | " "" "" | ||
43 | |||
44 | testing "environment variables 3b" \ | ||
45 | "V= env sh -c 'echo \${V-unset}'" \ | ||
46 | " | ||
47 | " "" "" | ||
48 | |||
49 | testing "environment variables 3c" \ | ||
50 | "env sh -c 'echo \${V-unset}'" \ | ||
51 | "unset | ||
52 | " "" "" | ||
53 | |||
54 | testing "environment variables 4a" \ | ||
55 | "V=set sh -c 'echo \${V-unset}'" \ | ||
56 | "set | ||
57 | " "" "" | ||
58 | |||
59 | testing "environment variables 4b" \ | ||
60 | "V= sh -c 'echo \${V-unset}'" \ | ||
61 | " | ||
62 | " "" "" | ||
63 | |||
64 | testing "environment variables 4c" \ | ||
65 | "sh -c 'echo \${V-unset}'" \ | ||
66 | "unset | ||
67 | " "" "" | ||
diff --git a/win32/env.c b/win32/env.c index 4d4e9c8fd..8e54c4c5e 100644 --- a/win32/env.c +++ b/win32/env.c | |||
@@ -100,6 +100,10 @@ int mingw_putenv(const char *env) | |||
100 | break; | 100 | break; |
101 | } | 101 | } |
102 | } | 102 | } |
103 | |||
104 | /* tell the OS environment about the change */ | ||
105 | envstr[s - env] = '\0'; | ||
106 | SetEnvironmentVariable(envstr, ""); | ||
103 | free(envstr); | 107 | free(envstr); |
104 | } | 108 | } |
105 | 109 | ||
diff --git a/win32/process.c b/win32/process.c index 5978226f0..d4ab07ad8 100644 --- a/win32/process.c +++ b/win32/process.c | |||
@@ -345,32 +345,27 @@ mingw_spawnvp(int mode, const char *cmd, char *const *argv) | |||
345 | { | 345 | { |
346 | char *prog; | 346 | char *prog; |
347 | intptr_t ret; | 347 | intptr_t ret; |
348 | #if !defined(_UCRT) | ||
349 | char *const *envp = environ; | ||
350 | #else | ||
351 | char *const *envp = NULL; | ||
352 | #endif | ||
353 | 348 | ||
354 | #if ENABLE_FEATURE_PREFER_APPLETS && NUM_APPLETS > 1 | 349 | #if ENABLE_FEATURE_PREFER_APPLETS && NUM_APPLETS > 1 |
355 | if (find_applet_by_name(cmd) >= 0) | 350 | if (find_applet_by_name(cmd) >= 0) |
356 | return mingw_spawn_applet(mode, argv, envp); | 351 | return mingw_spawn_applet(mode, argv, NULL); |
357 | else | 352 | else |
358 | #endif | 353 | #endif |
359 | if (has_path(cmd)) { | 354 | if (has_path(cmd)) { |
360 | char *path = alloc_system_drive(cmd); | 355 | char *path = alloc_system_drive(cmd); |
361 | add_win32_extension(path); | 356 | add_win32_extension(path); |
362 | ret = mingw_spawn_interpreter(mode, path, argv, envp, 0); | 357 | ret = mingw_spawn_interpreter(mode, path, argv, NULL, 0); |
363 | free(path); | 358 | free(path); |
364 | #if ENABLE_FEATURE_PREFER_APPLETS && NUM_APPLETS > 1 | 359 | #if ENABLE_FEATURE_PREFER_APPLETS && NUM_APPLETS > 1 |
365 | if (ret == -1 && unix_path(cmd) && | 360 | if (ret == -1 && unix_path(cmd) && |
366 | find_applet_by_name(bb_basename(cmd)) >= 0) { | 361 | find_applet_by_name(bb_basename(cmd)) >= 0) { |
367 | return mingw_spawn_applet(mode, argv, envp); | 362 | return mingw_spawn_applet(mode, argv, NULL); |
368 | } | 363 | } |
369 | #endif | 364 | #endif |
370 | return ret; | 365 | return ret; |
371 | } | 366 | } |
372 | else if ((prog=find_first_executable(cmd)) != NULL) { | 367 | else if ((prog=find_first_executable(cmd)) != NULL) { |
373 | ret = mingw_spawn_interpreter(mode, prog, argv, envp, 0); | 368 | ret = mingw_spawn_interpreter(mode, prog, argv, NULL, 0); |
374 | free(prog); | 369 | free(prog); |
375 | return ret; | 370 | return ret; |
376 | } | 371 | } |