diff options
author | Ron Yorston <rmy@pobox.com> | 2024-06-12 12:34:08 +0100 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2024-06-12 12:43:39 +0100 |
commit | 2817c3d4f3fb60b6719782cde57a6b7347cf2898 (patch) | |
tree | 177dc25062b8eadddc988c638920f417c77bb2b1 | |
parent | a518a4f6023582744fa271ec279375dd3d51a4d4 (diff) | |
download | busybox-w32-path_search.tar.gz busybox-w32-path_search.tar.bz2 busybox-w32-path_search.zip |
win32: allow for trailing separator in PATHpath_search
In recent versions of Windows the PATH environment variable has
a trailing semicolon. This is insignificant to Windows because
it's ignored. busybox-w32 conforms to the POSIX interpretation
of PATH which treats an empty path element as denoting the current
directory. As result, on these versions of Windows executables
may by default be run from the current directory, contrary to
usual Unix practice.
Attempt to detect and remove the trailing semicolon on applet
start up. If the user insists, they can add a trailing semicolon
to the shell variable PATH and it will be respected in the
conventional manner.
Adds 88-112 bytes.
-rw-r--r-- | include/mingw.h | 1 | ||||
-rw-r--r-- | libbb/appletlib.c | 12 | ||||
-rw-r--r-- | shell/ash.c | 46 | ||||
-rw-r--r-- | win32/mingw.c | 26 |
4 files changed, 47 insertions, 38 deletions
diff --git a/include/mingw.h b/include/mingw.h index 2a6cae4ee..fae732332 100644 --- a/include/mingw.h +++ b/include/mingw.h | |||
@@ -638,3 +638,4 @@ char *get_user_name(void); | |||
638 | char *quote_arg(const char *arg); | 638 | char *quote_arg(const char *arg); |
639 | char *find_first_executable(const char *name); | 639 | char *find_first_executable(const char *name); |
640 | char *xappendword(const char *str, const char *word); | 640 | char *xappendword(const char *str, const char *word); |
641 | int windows_env(void); | ||
diff --git a/libbb/appletlib.c b/libbb/appletlib.c index 1232d97c9..1f9968f10 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c | |||
@@ -1410,6 +1410,18 @@ int main(int argc UNUSED_PARAM, char **argv) | |||
1410 | if (s) | 1410 | if (s) |
1411 | *s = '\0'; | 1411 | *s = '\0'; |
1412 | } | 1412 | } |
1413 | |||
1414 | if (windows_env()) { | ||
1415 | /* remove single trailing separator from PATH */ | ||
1416 | for (char **envp = environ; envp && *envp; envp++) { | ||
1417 | if (is_prefixed_with_case(*envp, "PATH=")) { | ||
1418 | char *end = last_char_is(*envp, ';'); | ||
1419 | if (end && end[-1] != ';') | ||
1420 | *end = '\0'; | ||
1421 | break; | ||
1422 | } | ||
1423 | } | ||
1424 | } | ||
1413 | # endif | 1425 | # endif |
1414 | applet_name = bb_basename(applet_name); | 1426 | applet_name = bb_basename(applet_name); |
1415 | 1427 | ||
diff --git a/shell/ash.c b/shell/ash.c index d2c88c4bc..ad77689e7 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -15885,30 +15885,6 @@ static void setvar_if_unset(const char *key, const char *value) | |||
15885 | } | 15885 | } |
15886 | #endif | 15886 | #endif |
15887 | 15887 | ||
15888 | #if ENABLE_PLATFORM_MINGW32 | ||
15889 | /* | ||
15890 | * Detect if the environment contains certain mixed-case names: | ||
15891 | * | ||
15892 | * Path is present in a standard Windows environment | ||
15893 | * ComSpec is present in WINE | ||
15894 | * ProgramData is present in Cygwin/MSYS2 | ||
15895 | */ | ||
15896 | static int mixed_case_special_name(const char *envp) | ||
15897 | { | ||
15898 | const char *names = "PATH=\0""COMSPEC=\0""PROGRAMDATA=\0"; | ||
15899 | const char *n; | ||
15900 | |||
15901 | for (n = names; *n; ) { | ||
15902 | if (is_prefixed_with_case(envp, n) && !is_prefixed_with(envp, n)) { | ||
15903 | return TRUE; | ||
15904 | } | ||
15905 | while (*n++) | ||
15906 | ; | ||
15907 | } | ||
15908 | return FALSE; | ||
15909 | } | ||
15910 | #endif | ||
15911 | |||
15912 | /* Don't inline: conserve stack of caller from having our locals too */ | 15888 | /* Don't inline: conserve stack of caller from having our locals too */ |
15913 | static NOINLINE void | 15889 | static NOINLINE void |
15914 | init(void) | 15890 | init(void) |
@@ -15941,26 +15917,20 @@ init(void) | |||
15941 | * We may end up having both Path and PATH. Then Path will be chosen | 15917 | * We may end up having both Path and PATH. Then Path will be chosen |
15942 | * because it appears first. | 15918 | * because it appears first. |
15943 | */ | 15919 | */ |
15944 | for (envp = environ; envp && *envp; envp++) { | 15920 | if (windows_env()) { |
15945 | if (mixed_case_special_name(*envp)) { | ||
15946 | /* mintty sets HOME: unset it */ | ||
15947 | const char *tty = getenv("TERM_PROGRAM"); | ||
15948 | if (tty && strcmp(tty, "mintty") == 0) { | ||
15949 | unsetenv("HOME"); | ||
15950 | } | ||
15951 | break; | ||
15952 | } | ||
15953 | } | ||
15954 | |||
15955 | if (envp && *envp) { | ||
15956 | /* | 15921 | /* |
15957 | * If we get here it's because the environment contains a path | 15922 | * If we get here it's because the environment suggests we |
15958 | * variable called something other than PATH. This suggests we | ||
15959 | * haven't been invoked from an earlier instance of BusyBox. | 15923 | * haven't been invoked from an earlier instance of BusyBox. |
15960 | */ | 15924 | */ |
15961 | char *start, *end; | 15925 | char *start, *end; |
15962 | struct passwd *pw; | 15926 | struct passwd *pw; |
15963 | 15927 | ||
15928 | /* mintty sets HOME: unset it */ | ||
15929 | const char *tty = getenv("TERM_PROGRAM"); | ||
15930 | if (tty && strcmp(tty, "mintty") == 0) { | ||
15931 | unsetenv("HOME"); | ||
15932 | } | ||
15933 | |||
15964 | import = VIMPORT; | 15934 | import = VIMPORT; |
15965 | for (envp = environ; envp && *envp; envp++) { | 15935 | for (envp = environ; envp && *envp; envp++) { |
15966 | if (!(end=strchr(*envp, '='))) | 15936 | if (!(end=strchr(*envp, '='))) |
diff --git a/win32/mingw.c b/win32/mingw.c index d3daf8315..f96b5b49a 100644 --- a/win32/mingw.c +++ b/win32/mingw.c | |||
@@ -2464,3 +2464,29 @@ char *xappendword(const char *str, const char *word) | |||
2464 | free((void *)str); | 2464 | free((void *)str); |
2465 | return newstr; | 2465 | return newstr; |
2466 | } | 2466 | } |
2467 | |||
2468 | /* | ||
2469 | * Detect if the environment contains certain mixed-case names: | ||
2470 | * | ||
2471 | * Path is present in a standard Windows environment | ||
2472 | * ComSpec is present in WINE | ||
2473 | * ProgramData is present in Cygwin/MSYS2 | ||
2474 | */ | ||
2475 | int | ||
2476 | windows_env(void) | ||
2477 | { | ||
2478 | const char *names = "PATH=\0""COMSPEC=\0""PROGRAMDATA=\0"; | ||
2479 | const char *n; | ||
2480 | |||
2481 | for (char **envp = environ; envp && *envp; envp++) { | ||
2482 | for (n = names; *n; ) { | ||
2483 | if (is_prefixed_with_case(*envp, n) && | ||
2484 | !is_prefixed_with(*envp, n)) { | ||
2485 | return TRUE; | ||
2486 | } | ||
2487 | while (*n++) | ||
2488 | ; | ||
2489 | } | ||
2490 | } | ||
2491 | return FALSE; | ||
2492 | } | ||