diff options
author | Ron Yorston <rmy@pobox.com> | 2020-05-24 10:27:23 +0100 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2020-05-24 10:27:23 +0100 |
commit | 04129e0bde3c2d25ab676079e6e3b6fdcdeabe4f (patch) | |
tree | 4eae7fc3f111e4a0c15c6a4371fca751b2630e6f | |
parent | 184aa4b5d07d5f3fcc15dd4bb0d4636fba734de3 (diff) | |
download | busybox-w32-04129e0bde3c2d25ab676079e6e3b6fdcdeabe4f.tar.gz busybox-w32-04129e0bde3c2d25ab676079e6e3b6fdcdeabe4f.tar.bz2 busybox-w32-04129e0bde3c2d25ab676079e6e3b6fdcdeabe4f.zip |
win32: changes to '#!' support
Since the earliest days of busybox-w32 '#!' has searched PATH for
the interpreter. This doesn't seem to be supported by precedent.
In testing I also found that additional code was needed for the case
where PATH has been altered in the current shell or is modified on
the command line: PATH has to be extracted from envp rather than
getenv("PATH"). Drop this non-standard feature.
*NIX implementations disagree on whether the interpreter can itself
be a script. Follow Linux and allow this with a limit of four levels
of nesting.
-rw-r--r-- | shell/ash.c | 3 | ||||
-rw-r--r-- | win32/process.c | 22 |
2 files changed, 13 insertions, 12 deletions
diff --git a/shell/ash.c b/shell/ash.c index 4f1fe005b..c6f64e202 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -22,8 +22,7 @@ | |||
22 | * - Environment variables from Windows will all be turned to uppercase. | 22 | * - Environment variables from Windows will all be turned to uppercase. |
23 | * - PATH accepts both ; and : as separator, but can't be mixed | 23 | * - PATH accepts both ; and : as separator, but can't be mixed |
24 | * - command without ".exe" extension is still understood as executable | 24 | * - command without ".exe" extension is still understood as executable |
25 | * - shell scripts on the path are detected by the presence of '#!'; | 25 | * - shell scripts on the path are detected by the presence of '#!' |
26 | * the path to the interpreter is ignored, PATH is searched to find it | ||
27 | * - both / and \ are supported in PATH. Usually you must use / | 26 | * - both / and \ are supported in PATH. Usually you must use / |
28 | * - trap/job does not work | 27 | * - trap/job does not work |
29 | * - /dev/null is supported for redirection | 28 | * - /dev/null is supported for redirection |
diff --git a/win32/process.c b/win32/process.c index 28df33c23..d33f06405 100644 --- a/win32/process.c +++ b/win32/process.c | |||
@@ -292,7 +292,8 @@ mingw_spawn_applet(int mode, | |||
292 | #endif | 292 | #endif |
293 | 293 | ||
294 | static intptr_t | 294 | static intptr_t |
295 | mingw_spawn_interpreter(int mode, const char *prog, char *const *argv, char *const *envp) | 295 | mingw_spawn_interpreter(int mode, const char *prog, char *const *argv, |
296 | char *const *envp, int level) | ||
296 | { | 297 | { |
297 | intptr_t ret; | 298 | intptr_t ret; |
298 | int nopts; | 299 | int nopts; |
@@ -304,6 +305,11 @@ mingw_spawn_interpreter(int mode, const char *prog, char *const *argv, char *con | |||
304 | if (!parse_interpreter(prog, &interp)) | 305 | if (!parse_interpreter(prog, &interp)) |
305 | return spawnveq(mode, prog, argv, envp); | 306 | return spawnveq(mode, prog, argv, envp); |
306 | 307 | ||
308 | if (++level > 4) { | ||
309 | errno = ELOOP; | ||
310 | return -1; | ||
311 | } | ||
312 | |||
307 | nopts = interp.opts != NULL; | 313 | nopts = interp.opts != NULL; |
308 | argc = string_array_len((char **)argv); | 314 | argc = string_array_len((char **)argv); |
309 | new_argv = xmalloc(sizeof(*argv)*(argc+nopts+2)); | 315 | new_argv = xmalloc(sizeof(*argv)*(argc+nopts+2)); |
@@ -314,7 +320,7 @@ mingw_spawn_interpreter(int mode, const char *prog, char *const *argv, char *con | |||
314 | if ((fullpath=alloc_win32_extension(interp.path)) != NULL || | 320 | if ((fullpath=alloc_win32_extension(interp.path)) != NULL || |
315 | file_is_executable(interp.path)) { | 321 | file_is_executable(interp.path)) { |
316 | new_argv[0] = fullpath ? fullpath : interp.path; | 322 | new_argv[0] = fullpath ? fullpath : interp.path; |
317 | ret = spawnveq(mode, new_argv[0], new_argv, envp); | 323 | ret = mingw_spawn_interpreter(mode, new_argv[0], new_argv, envp, level); |
318 | } else | 324 | } else |
319 | #if ENABLE_FEATURE_PREFER_APPLETS || ENABLE_FEATURE_SH_STANDALONE | 325 | #if ENABLE_FEATURE_PREFER_APPLETS || ENABLE_FEATURE_SH_STANDALONE |
320 | if (find_applet_by_name(interp.name) >= 0) { | 326 | if (find_applet_by_name(interp.name) >= 0) { |
@@ -323,11 +329,7 @@ mingw_spawn_interpreter(int mode, const char *prog, char *const *argv, char *con | |||
323 | ret = mingw_spawn_applet(mode, new_argv, envp); | 329 | ret = mingw_spawn_applet(mode, new_argv, envp); |
324 | } else | 330 | } else |
325 | #endif | 331 | #endif |
326 | if ((fullpath=find_first_executable(interp.name)) != NULL) { | 332 | { |
327 | new_argv[0] = fullpath; | ||
328 | ret = spawnveq(mode, fullpath, new_argv, envp); | ||
329 | } | ||
330 | else { | ||
331 | errno = ENOENT; | 333 | errno = ENOENT; |
332 | ret = -1; | 334 | ret = -1; |
333 | } | 335 | } |
@@ -349,10 +351,10 @@ mingw_spawn_1(int mode, const char *cmd, char *const *argv, char *const *envp) | |||
349 | #endif | 351 | #endif |
350 | if (strchr(cmd, '/') || strchr(cmd, '\\') || has_dos_drive_prefix(cmd)) { | 352 | if (strchr(cmd, '/') || strchr(cmd, '\\') || has_dos_drive_prefix(cmd)) { |
351 | const char *path = auto_win32_extension(cmd); | 353 | const char *path = auto_win32_extension(cmd); |
352 | return mingw_spawn_interpreter(mode, path ? path : cmd, argv, envp); | 354 | return mingw_spawn_interpreter(mode, path ? path : cmd, argv, envp, 0); |
353 | } | 355 | } |
354 | else if ((prog=find_first_executable(cmd)) != NULL) { | 356 | else if ((prog=find_first_executable(cmd)) != NULL) { |
355 | intptr_t ret = mingw_spawn_interpreter(mode, prog, argv, envp); | 357 | intptr_t ret = mingw_spawn_interpreter(mode, prog, argv, envp, 0); |
356 | free(prog); | 358 | free(prog); |
357 | return ret; | 359 | return ret; |
358 | } | 360 | } |
@@ -401,7 +403,7 @@ mingw_execvp(const char *cmd, char *const *argv) | |||
401 | int | 403 | int |
402 | mingw_execve(const char *cmd, char *const *argv, char *const *envp) | 404 | mingw_execve(const char *cmd, char *const *argv, char *const *envp) |
403 | { | 405 | { |
404 | int ret = (int)mingw_spawn_interpreter(P_WAIT, cmd, argv, envp); | 406 | int ret = (int)mingw_spawn_interpreter(P_WAIT, cmd, argv, envp, 0); |
405 | if (ret != -1) | 407 | if (ret != -1) |
406 | exit(ret); | 408 | exit(ret); |
407 | return ret; | 409 | return ret; |