I wrote: > The new tests/test-spawn-pipe-script.c test reveals that create_pipe_in > returns an odd errno value when the program is an executable script without > '#!' marker. This patch fixes it.
That patch fixed only the case when the program base name does not contain a '.'. When it does contain a '.', 'find_in_given_path' succeeds, and CreateProcess fails with error ERROR_BAD_EXE_FORMAT, which the Gnulib code maps to EINVAL, which makes the test-spawn-pipe-script.c test fail. This patch fixes it. 2020-12-24 Bruno Haible <br...@clisp.org> windows-spawn: Improve errno upon failure on native Windows. * lib/windows-spawn.c (spawnpvech): Map the CreateProcess errors ERROR_BAD_FORMAT and ERROR_BAD_EXE_FORMAT to ENOEXEC. * tests/executable-script.sh: New file. * tests/test-posix_spawn-script.c (main): Also try executing executable-script.sh. * tests/test-posix_spawnp-script.c (main): Likewise. * tests/test-execute-script.c (main): Likewise. * tests/test-spawn-pipe-script.c (main): Likewise. * modules/posix_spawn-tests (Files): Add tests/executable-script.sh. * modules/posix_spawnp-tests (Files): Likewise. * modules/execute-tests (Files): Likewise. * modules/spawn-pipe-tests (Files): Likewise. (diff -w) diff --git a/lib/windows-spawn.c b/lib/windows-spawn.c index 19251ae..0385b1c 100644 --- a/lib/windows-spawn.c +++ b/lib/windows-spawn.c @@ -482,6 +482,11 @@ spawnpvech (int mode, errno = ENAMETOOLONG; break; + case ERROR_BAD_FORMAT: + case ERROR_BAD_EXE_FORMAT: + errno = ENOEXEC; + break; + default: errno = EINVAL; break; diff --git a/modules/execute-tests b/modules/execute-tests index 2213a32..422c1ab 100644 --- a/modules/execute-tests +++ b/modules/execute-tests @@ -4,6 +4,7 @@ tests/test-execute-main.c tests/test-execute-child.c tests/test-execute-script.c tests/executable-script +tests/executable-script.sh tests/executable-shell-script tests/macros.h diff --git a/modules/posix_spawn-tests b/modules/posix_spawn-tests index 451dbd1..06a8434 100644 --- a/modules/posix_spawn-tests +++ b/modules/posix_spawn-tests @@ -5,6 +5,7 @@ tests/test-posix_spawn-inherit0.c tests/test-posix_spawn-inherit1.c tests/test-posix_spawn-script.c tests/executable-script +tests/executable-script.sh tests/executable-shell-script tests/signature.h diff --git a/modules/posix_spawnp-tests b/modules/posix_spawnp-tests index 04ccdbb..887569c 100644 --- a/modules/posix_spawnp-tests +++ b/modules/posix_spawnp-tests @@ -5,6 +5,7 @@ tests/test-posix_spawn-dup2-stdin.c tests/test-posix_spawn-dup2-stdin.in.sh tests/test-posix_spawnp-script.c tests/executable-script +tests/executable-script.sh tests/executable-shell-script tests/signature.h diff --git a/modules/spawn-pipe-tests b/modules/spawn-pipe-tests index 80614a9..5dbd28d 100644 --- a/modules/spawn-pipe-tests +++ b/modules/spawn-pipe-tests @@ -4,6 +4,7 @@ tests/test-spawn-pipe-main.c tests/test-spawn-pipe-child.c tests/test-spawn-pipe-script.c tests/executable-script +tests/executable-script.sh tests/executable-shell-script tests/macros.h diff --git a/tests/executable-script.sh b/tests/executable-script.sh new file mode 100755 index 0000000..993f41c --- /dev/null +++ b/tests/executable-script.sh @@ -0,0 +1,4 @@ +printf 'Halle ' +printf "Potta" +# This script is intentionally not immediately recognizable as a shell script. +# Don't add a #! header in the first line. diff --git a/tests/test-execute-script.c b/tests/test-execute-script.c index 060f0c5..aff9236 100644 --- a/tests/test-execute-script.c +++ b/tests/test-execute-script.c @@ -48,14 +48,21 @@ main () ASSERT (fp != NULL); { - const char *progname = "executable-script"; - const char *prog_path = SRCDIR "executable-script"; + size_t i; + + for (i = 0; i < 2; i++) + { + const char *progname = + (i == 0 ? "executable-script" : "executable-script.sh"); + const char *prog_path = + (i == 0 ? SRCDIR "executable-script" : SRCDIR "executable-script.sh"); const char *prog_argv[2] = { prog_path, NULL }; int ret = execute (progname, prog_argv[0], prog_argv, NULL, false, false, false, false, true, false, NULL); ASSERT (ret == 127); } + } #if defined _WIN32 && !defined __CYGWIN__ /* On native Windows, scripts - even with '#!' marker - are not executable. diff --git a/tests/test-posix_spawn-script.c b/tests/test-posix_spawn-script.c index a632841..e17c3b8 100644 --- a/tests/test-posix_spawn-script.c +++ b/tests/test-posix_spawn-script.c @@ -52,7 +52,12 @@ main () == 0); { - const char *prog_path = SRCDIR "executable-script"; + size_t i; + + for (i = 0; i < 2; i++) + { + const char *prog_path = + (i == 0 ? SRCDIR "executable-script" : SRCDIR "executable-script.sh"); const char *prog_argv[2] = { prog_path, NULL }; int err = posix_spawn (&child, prog_path, &actions, NULL, @@ -83,6 +88,7 @@ main () } } } + } { const char *prog_path = SRCDIR "executable-shell-script"; diff --git a/tests/test-posix_spawnp-script.c b/tests/test-posix_spawnp-script.c index 04bf496..b48e791 100644 --- a/tests/test-posix_spawnp-script.c +++ b/tests/test-posix_spawnp-script.c @@ -52,7 +52,12 @@ main () == 0); { - const char *prog_path = SRCDIR "executable-script"; + size_t i; + + for (i = 0; i < 2; i++) + { + const char *prog_path = + (i == 0 ? SRCDIR "executable-script" : SRCDIR "executable-script.sh"); const char *prog_argv[2] = { prog_path, NULL }; int err = posix_spawnp (&child, prog_path, &actions, NULL, @@ -83,6 +88,7 @@ main () } } } + } { const char *prog_path = SRCDIR "executable-shell-script"; diff --git a/tests/test-spawn-pipe-script.c b/tests/test-spawn-pipe-script.c index dbd28ed..1bde5c1 100644 --- a/tests/test-spawn-pipe-script.c +++ b/tests/test-spawn-pipe-script.c @@ -41,8 +41,14 @@ main () pid_t pid; { - const char *progname = "executable-script"; - const char *prog_path = SRCDIR "executable-script"; + size_t i; + + for (i = 0; i < 2; i++) + { + const char *progname = + (i == 0 ? "executable-script" : "executable-script.sh"); + const char *prog_path = + (i == 0 ? SRCDIR "executable-script" : SRCDIR "executable-script.sh"); const char *prog_argv[2] = { prog_path, NULL }; pid = create_pipe_in (progname, prog_argv[0], prog_argv, NULL, @@ -50,7 +56,8 @@ main () if (pid >= 0) { /* Wait for child. */ - ASSERT (wait_subprocess (pid, progname, true, true, true, false, NULL) + ASSERT (wait_subprocess (pid, progname, true, true, true, false, + NULL) == 127); } else @@ -59,6 +66,7 @@ main () ASSERT (errno == ENOEXEC); } } + } #if defined _WIN32 && !defined __CYGWIN__ /* On native Windows, scripts - even with '#!' marker - are not executable.