aboutsummaryrefslogtreecommitdiff
path: root/win32/process.c
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2022-05-06 08:26:55 +0100
committerRon Yorston <rmy@pobox.com>2022-05-06 09:30:43 +0100
commit26ba73098e714459e3294679228a1d54eed14799 (patch)
tree5e5dda2adbf6577276baf372626465213fd2f1b9 /win32/process.c
parent3b5042430fc4b82d44e0430f9ecc21a9228d1651 (diff)
downloadbusybox-w32-26ba73098e714459e3294679228a1d54eed14799.tar.gz
busybox-w32-26ba73098e714459e3294679228a1d54eed14799.tar.bz2
busybox-w32-26ba73098e714459e3294679228a1d54eed14799.zip
win32: search PATH for missing Unix-style executables
Commit 41ef232fc5 (win32: use built-in applets for non-existent binaries with Unix-style paths) alters what happens when trying to find an executable. If all of the following apply: - the pathname starts with one of the standard directories for Unix executables (/bin, /usr/bin, /sbin, /usr/sbin); - the file isn't found relative to the system root; - the basename matches an applet then the applet is run. Further extend the procedure so that if the first two conditions are met and either: - the PREFER_APPLETS and SH_STANDALONE features are enabled and the basename *doesn't* match an applet or - the PREFER_APPLETS and SH_STANDALONE features are disabled then PATH is searched for the basename. This affects: - how interpreters and binaries are spawned by mingw_spawn_interpreter() and mingw_spawnvp(); - how 'which' and the shell search for binaries. Special steps need to be taken in the shell to avoid treating shell built-ins and functions as applets. As a consequence of this change: - An executable that isn't an applet, say curl.exe, can be run as /usr/bin/curl so long as it's in a directory in PATH. It doesn't have to be in C:/usr/bin. - If the PREFER_APPLETS and SH_STANDALONE features are disabled binaries can be run using paths referring to standard Unix directories even if they're installed elsewhere in PATH.
Diffstat (limited to 'win32/process.c')
-rw-r--r--win32/process.c68
1 files changed, 39 insertions, 29 deletions
diff --git a/win32/process.c b/win32/process.c
index d4ab07ad8..6ab0d8735 100644
--- a/win32/process.c
+++ b/win32/process.c
@@ -297,12 +297,12 @@ static intptr_t
297mingw_spawn_interpreter(int mode, const char *prog, char *const *argv, 297mingw_spawn_interpreter(int mode, const char *prog, char *const *argv,
298 char *const *envp, int level) 298 char *const *envp, int level)
299{ 299{
300 intptr_t ret; 300 intptr_t ret = -1;
301 int nopts; 301 int nopts;
302 interp_t interp; 302 interp_t interp;
303 char **new_argv; 303 char **new_argv;
304 int argc; 304 int argc;
305 char *fullpath = NULL; 305 char *path = NULL;
306 306
307 if (!parse_interpreter(prog, &interp)) 307 if (!parse_interpreter(prog, &interp))
308 return spawnveq(mode, prog, argv, envp); 308 return spawnveq(mode, prog, argv, envp);
@@ -320,22 +320,33 @@ mingw_spawn_interpreter(int mode, const char *prog, char *const *argv,
320 memcpy(new_argv+nopts+2, argv+1, sizeof(*argv)*argc); 320 memcpy(new_argv+nopts+2, argv+1, sizeof(*argv)*argc);
321 321
322#if ENABLE_FEATURE_PREFER_APPLETS && NUM_APPLETS > 1 322#if ENABLE_FEATURE_PREFER_APPLETS && NUM_APPLETS > 1
323 if (find_applet_by_name(interp.name) >= 0) { 323 if (unix_path(interp.path) && find_applet_by_name(interp.name) >= 0) {
324 /* the fake path indicates the index of the script */ 324 /* the fake path indicates the index of the script */
325 new_argv[0] = fullpath = xasprintf("%d:/%s", nopts+1, interp.name); 325 new_argv[0] = path = xasprintf("%d:/%s", nopts+1, interp.name);
326 ret = mingw_spawn_applet(mode, new_argv, envp); 326 ret = mingw_spawn_applet(mode, new_argv, envp);
327 } else 327 goto done;
328 }
328#endif 329#endif
329 if ((fullpath = alloc_system_drive(interp.path)) && 330
330 (add_win32_extension(fullpath) || file_is_executable(fullpath))) { 331 path = alloc_system_drive(interp.path);
331 new_argv[0] = fullpath; 332 if ((add_win32_extension(path) || file_is_executable(path))) {
332 ret = mingw_spawn_interpreter(mode, new_argv[0], new_argv, envp, level); 333 new_argv[0] = path;
333 } else { 334 ret = mingw_spawn_interpreter(mode, path, new_argv, envp, level);
334 errno = ENOENT; 335 goto done;
335 ret = -1;
336 } 336 }
337 free(path);
338 path = NULL;
337 339
338 free(fullpath); 340 if (unix_path(interp.path)) {
341 if ((path = find_first_executable(interp.name)) != NULL) {
342 new_argv[0] = path;
343 ret = mingw_spawn_interpreter(mode, path, new_argv, envp, level);
344 goto done;
345 }
346 }
347 errno = ENOENT;
348 done:
349 free(path);
339 free(new_argv); 350 free(new_argv);
340 return ret; 351 return ret;
341} 352}
@@ -343,30 +354,29 @@ mingw_spawn_interpreter(int mode, const char *prog, char *const *argv,
343static intptr_t 354static intptr_t
344mingw_spawnvp(int mode, const char *cmd, char *const *argv) 355mingw_spawnvp(int mode, const char *cmd, char *const *argv)
345{ 356{
346 char *prog; 357 char *path;
347 intptr_t ret; 358 intptr_t ret;
348 359
349#if ENABLE_FEATURE_PREFER_APPLETS && NUM_APPLETS > 1 360#if ENABLE_FEATURE_PREFER_APPLETS && NUM_APPLETS > 1
350 if (find_applet_by_name(cmd) >= 0) 361 if ((!has_path(cmd) || unix_path(cmd)) &&
362 find_applet_by_name(bb_basename(cmd)) >= 0)
351 return mingw_spawn_applet(mode, argv, NULL); 363 return mingw_spawn_applet(mode, argv, NULL);
352 else
353#endif 364#endif
354 if (has_path(cmd)) { 365 if (has_path(cmd)) {
355 char *path = alloc_system_drive(cmd); 366 path = alloc_system_drive(cmd);
356 add_win32_extension(path); 367 if (add_win32_extension(path) || file_is_executable(path)) {
357 ret = mingw_spawn_interpreter(mode, path, argv, NULL, 0); 368 ret = mingw_spawn_interpreter(mode, path, argv, NULL, 0);
358 free(path); 369 free(path);
359#if ENABLE_FEATURE_PREFER_APPLETS && NUM_APPLETS > 1 370 return ret;
360 if (ret == -1 && unix_path(cmd) &&
361 find_applet_by_name(bb_basename(cmd)) >= 0) {
362 return mingw_spawn_applet(mode, argv, NULL);
363 } 371 }
364#endif 372 free(path);
365 return ret; 373 if (unix_path(cmd))
374 cmd = bb_basename(cmd);
366 } 375 }
367 else if ((prog=find_first_executable(cmd)) != NULL) { 376
368 ret = mingw_spawn_interpreter(mode, prog, argv, NULL, 0); 377 if ((path = find_first_executable(cmd)) != NULL) {
369 free(prog); 378 ret = mingw_spawn_interpreter(mode, path, argv, NULL, 0);
379 free(path);
370 return ret; 380 return ret;
371 } 381 }
372 382