aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2020-05-24 10:27:23 +0100
committerRon Yorston <rmy@pobox.com>2020-05-24 10:27:23 +0100
commit04129e0bde3c2d25ab676079e6e3b6fdcdeabe4f (patch)
tree4eae7fc3f111e4a0c15c6a4371fca751b2630e6f
parent184aa4b5d07d5f3fcc15dd4bb0d4636fba734de3 (diff)
downloadbusybox-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.c3
-rw-r--r--win32/process.c22
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
294static intptr_t 294static intptr_t
295mingw_spawn_interpreter(int mode, const char *prog, char *const *argv, char *const *envp) 295mingw_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)
401int 403int
402mingw_execve(const char *cmd, char *const *argv, char *const *envp) 404mingw_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;