The posix_spawn implementation in gnulib comes from glibc as of 2008.
But in 2011 an important change was done in glibc: Remove the ability
to specify a script that does not start with a '#!' marker as executable.
Previously this file was /_assumed_/ to be a shell script.

Here are 3 patches:
  - Change gnulib's posix_spawn to match what glibc does.
  - Add unit tests.
  - Fix the resulting test failures on many platforms (from GNU/Hurd [1] to
    Solaris 11).

[1] https://lists.gnu.org/archive/html/bug-hurd/2020-12/msg00071.html


2020-12-23  Bruno Haible  <br...@clisp.org>

        posix_spawn, posix_spawnp: Fix execution of scripts.
        * m4/posix_spawn.m4 (gl_POSIX_SPAWN_SECURE): New macro.
        (gl_POSIX_SPAWN_BODY): Invoke it. Set REPLACE_POSIX_SPAWN if posix_spawn
        or posix_spawnp allows unsecure execution of scripts.
        * doc/posix-functions/posix_spawn.texi: Document the script execution
        problem.
        * doc/posix-functions/posix_spawnp.texi: Likewise.

2020-12-23  Bruno Haible  <br...@clisp.org>

        Add unit tests regarding execution of scripts.
        * tests/executable-script: New file.
        * tests/executable-shell-script: New file.
        * tests/test-posix_spawn-script.c: New file.
        * tests/test-posix_spawnp-script.c: New file.
        * tests/test-execute-script.c: New file.
        * tests/test-spawn-pipe-script.c: New file.
        * modules/posix_spawn-tests (Files): Add
        tests/test-posix_spawn-script.c, tests/executable-script,
        tests/executable-shell-script.
        (Makefile.am): Compile and run test-posix_spawn-script.
        * modules/posix_spawnp-tests (Files): Add
        tests/test-posix_spawnp-script.c, tests/executable-script,
        tests/executable-shell-script.
        (Makefile.am): Compile and run test-posix_spawnp-script.
        * modules/execute-tests (Files): Add tests/test-execute-script.c,
        tests/executable-script, tests/executable-shell-script.
        (Makefile.am): Compile and run test-execute-script.
        * modules/spawn-pipe-tests (Files): Add tests/test-spawn-pipe-script.c,
        tests/executable-script, tests/executable-shell-script.
        (Makefile.am): Compile and run test-spawn-pipe-script.

2020-12-23  Bruno Haible  <br...@clisp.org>

        Don't execute scripts without '#!' marker through /bin/sh.
        This reflects the change done in glibc through
        <https://sourceware.org/bugzilla/show_bug.cgi?id=13134> and
        
<https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=d96de9634a334af16c0ac711074c15ac1762b23c>.
        * lib/spawni.c (internal_function): Remove macro.
        (script_execute): Remove function.
        (__spawni): Don't invoke script_execute.
        * lib/execute.c (execute): Disable the ENOEXEC handling.
        * lib/spawn-pipe.c (create_pipe): Likewise.
        * NEWS: Mention the change.

>From 9042e0456ac72d9333e2d48970c7f2835acfbf79 Mon Sep 17 00:00:00 2001
From: Bruno Haible <br...@clisp.org>
Date: Wed, 23 Dec 2020 23:58:17 +0100
Subject: [PATCH 1/3] Don't execute scripts without '#!' marker through
 /bin/sh.

This reflects the change done in glibc through
<https://sourceware.org/bugzilla/show_bug.cgi?id=13134> and
<https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=d96de9634a334af16c0ac711074c15ac1762b23c>.

* lib/spawni.c (internal_function): Remove macro.
(script_execute): Remove function.
(__spawni): Don't invoke script_execute.
* lib/execute.c (execute): Disable the ENOEXEC handling.
* lib/spawn-pipe.c (create_pipe): Likewise.
* NEWS: Mention the change.
---
 ChangeLog        | 13 +++++++++++++
 NEWS             |  7 +++++++
 lib/execute.c    |  2 ++
 lib/spawn-pipe.c |  4 ++++
 lib/spawni.c     | 39 ---------------------------------------
 5 files changed, 26 insertions(+), 39 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 7d38a83..b0d67da 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,18 @@
 2020-12-23  Bruno Haible  <br...@clisp.org>
 
+	Don't execute scripts without '#!' marker through /bin/sh.
+	This reflects the change done in glibc through
+	<https://sourceware.org/bugzilla/show_bug.cgi?id=13134> and
+	<https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=d96de9634a334af16c0ac711074c15ac1762b23c>.
+	* lib/spawni.c (internal_function): Remove macro.
+	(script_execute): Remove function.
+	(__spawni): Don't invoke script_execute.
+	* lib/execute.c (execute): Disable the ENOEXEC handling.
+	* lib/spawn-pipe.c (create_pipe): Likewise.
+	* NEWS: Mention the change.
+
+2020-12-23  Bruno Haible  <br...@clisp.org>
+
 	posix_spawn[p]: Fix compilation error on Windows (regr. 2020-12-14).
 	Reported by Adrian Ebeling <d...@adrian-ebeling.de> in
 	<https://lists.gnu.org/archive/html/bug-gnulib/2020-12/msg00189.html>.
diff --git a/NEWS b/NEWS
index 7679be0..c347ecd 100644
--- a/NEWS
+++ b/NEWS
@@ -60,6 +60,13 @@ User visible incompatible changes
 
 Date        Modules         Changes
 
+2020-12-23  execute         These functions no longer execute scripts without
+            spawn-pipe      '#!' marker through /bin/sh. To execute such a
+            posix_spawn     script as a shell script, either add a '#!/bin/sh'
+            posix_spawnp    marker in the first line, or specify "/bin/sh" as
+                            the program to execute and the script as its first
+                            argument.
+
 2020-12-18  free            This module, obsoleted in 2008, is gone.
 
 2020-12-14  findprog-in     The function 'find_in_given_path' now takes a 3rd
diff --git a/lib/execute.c b/lib/execute.c
index 41a2239..38dd07b 100644
--- a/lib/execute.c
+++ b/lib/execute.c
@@ -191,6 +191,7 @@ execute (const char *progname,
       exitcode = spawnpvech (P_WAIT, prog_path, argv + 1,
                              (const char * const *) environ, directory,
                              stdin_handle, stdout_handle, stderr_handle);
+# if 0 /* Executing arbitrary files as shell scripts is unsecure.  */
       if (exitcode == -1 && errno == ENOEXEC)
         {
           /* prog is not a native executable.  Try to execute it as a
@@ -201,6 +202,7 @@ execute (const char *progname,
                                  (const char * const *) environ, directory,
                                  stdin_handle, stdout_handle, stderr_handle);
         }
+# endif
     }
   if (exitcode == -1)
     saved_errno = errno;
diff --git a/lib/spawn-pipe.c b/lib/spawn-pipe.c
index d483520..aedbcb2 100644
--- a/lib/spawn-pipe.c
+++ b/lib/spawn-pipe.c
@@ -287,6 +287,7 @@ create_pipe (const char *progname,
       child = spawnpvech (P_NOWAIT, prog_path, argv + 1,
                           (const char * const *) environ, directory,
                           stdin_handle, stdout_handle, stderr_handle);
+#  if 0 /* Executing arbitrary files as shell scripts is unsecure.  */
       if (child == -1 && errno == ENOEXEC)
         {
           /* prog is not a native executable.  Try to execute it as a
@@ -297,6 +298,7 @@ create_pipe (const char *progname,
                               (const char * const *) environ, directory,
                               stdin_handle, stdout_handle, stderr_handle);
         }
+#  endif
     }
  failed:
   if (child == -1)
@@ -374,6 +376,7 @@ create_pipe (const char *progname,
     {
       child = _spawnvpe (P_NOWAIT, prog_path, argv + 1,
                          (const char **) environ);
+#  if 0 /* Executing arbitrary files as shell scripts is unsecure.  */
       if (child == -1 && errno == ENOEXEC)
         {
           /* prog is not a native executable.  Try to execute it as a
@@ -382,6 +385,7 @@ create_pipe (const char *progname,
           child = _spawnvpe (P_NOWAIT, argv[0], argv,
                              (const char **) environ);
         }
+#  endif
     }
   if (child == -1)
     saved_errno = errno;
diff --git a/lib/spawni.c b/lib/spawni.c
index 06d98b4..182d13f 100644
--- a/lib/spawni.c
+++ b/lib/spawni.c
@@ -75,9 +75,6 @@
 # define sigprocmask __sigprocmask
 # define strchrnul __strchrnul
 # define vfork __vfork
-#else
-# undef internal_function
-# define internal_function /* empty */
 #endif
 
 
@@ -105,36 +102,6 @@ __spawni (pid_t *pid, const char *file,
 #else
 
 
-/* The file is accessible but it is not an executable file.  Invoke
-   the shell to interpret it as a script.  */
-static void
-internal_function
-script_execute (const char *file, const char *const argv[],
-                const char *const envp[])
-{
-  /* Count the arguments.  */
-  int argc = 0;
-  while (argv[argc++])
-    ;
-
-  /* Construct an argument list for the shell.  */
-  {
-    const char **new_argv =
-      (const char **) alloca ((argc + 1) * sizeof (const char *));
-    new_argv[0] = _PATH_BSHELL;
-    new_argv[1] = file;
-    while (argc > 1)
-      {
-        new_argv[argc] = argv[argc - 1];
-        --argc;
-      }
-
-    /* Execute the shell.  */
-    execve (new_argv[0], (char * const *) new_argv, (char * const *) envp);
-  }
-}
-
-
 /* Spawn a new process executing PATH with the attributes describes in *ATTRP.
    Before running the process perform the actions described in FILE-ACTIONS. */
 int
@@ -307,9 +274,6 @@ __spawni (pid_t *pid, const char *file,
       /* The FILE parameter is actually a path.  */
       execve (file, (char * const *) argv, (char * const *) envp);
 
-      if (errno == ENOEXEC)
-        script_execute (file, argv, envp);
-
       /* Oh, oh.  'execve' returns.  This is bad.  */
       _exit (SPAWN_ERROR);
     }
@@ -358,9 +322,6 @@ __spawni (pid_t *pid, const char *file,
       /* Try to execute this name.  If it works, execv will not return.  */
       execve (startp, (char * const *) argv, (char * const *) envp);
 
-      if (errno == ENOEXEC)
-        script_execute (startp, argv, envp);
-
       switch (errno)
         {
         case EACCES:
-- 
2.7.4

>From 7e9ecfe3790f40ea5b9b18cbfdbb11d0277d27ed Mon Sep 17 00:00:00 2001
From: Bruno Haible <br...@clisp.org>
Date: Thu, 24 Dec 2020 01:14:49 +0100
Subject: [PATCH 2/3] Add unit tests regarding execution of scripts.

* tests/executable-script: New file.
* tests/executable-shell-script: New file.
* tests/test-posix_spawn-script.c: New file.
* tests/test-posix_spawnp-script.c: New file.
* tests/test-execute-script.c: New file.
* tests/test-spawn-pipe-script.c: New file.
* modules/posix_spawn-tests (Files): Add
tests/test-posix_spawn-script.c, tests/executable-script,
tests/executable-shell-script.
(Makefile.am): Compile and run test-posix_spawn-script.
* modules/posix_spawnp-tests (Files): Add
tests/test-posix_spawnp-script.c, tests/executable-script,
tests/executable-shell-script.
(Makefile.am): Compile and run test-posix_spawnp-script.
* modules/execute-tests (Files): Add tests/test-execute-script.c,
tests/executable-script, tests/executable-shell-script.
(Makefile.am): Compile and run test-execute-script.
* modules/spawn-pipe-tests (Files): Add tests/test-spawn-pipe-script.c,
tests/executable-script, tests/executable-shell-script.
(Makefile.am): Compile and run test-spawn-pipe-script.
---
 ChangeLog                        |  24 +++++++
 modules/execute-tests            |   8 +++
 modules/posix_spawn-tests        |  10 ++-
 modules/posix_spawnp-tests       |  15 +++-
 modules/spawn-pipe-tests         |   8 +++
 tests/executable-script          |   4 ++
 tests/executable-shell-script    |   4 ++
 tests/test-execute-script.c      |  88 ++++++++++++++++++++++++
 tests/test-posix_spawn-script.c  | 143 +++++++++++++++++++++++++++++++++++++++
 tests/test-posix_spawnp-script.c | 143 +++++++++++++++++++++++++++++++++++++++
 tests/test-spawn-pipe-script.c   | 100 +++++++++++++++++++++++++++
 11 files changed, 543 insertions(+), 4 deletions(-)
 create mode 100755 tests/executable-script
 create mode 100755 tests/executable-shell-script
 create mode 100644 tests/test-execute-script.c
 create mode 100644 tests/test-posix_spawn-script.c
 create mode 100644 tests/test-posix_spawnp-script.c
 create mode 100644 tests/test-spawn-pipe-script.c

diff --git a/ChangeLog b/ChangeLog
index b0d67da..bfb7f88 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,29 @@
 2020-12-23  Bruno Haible  <br...@clisp.org>
 
+	Add unit tests regarding execution of scripts.
+	* tests/executable-script: New file.
+	* tests/executable-shell-script: New file.
+	* tests/test-posix_spawn-script.c: New file.
+	* tests/test-posix_spawnp-script.c: New file.
+	* tests/test-execute-script.c: New file.
+	* tests/test-spawn-pipe-script.c: New file.
+	* modules/posix_spawn-tests (Files): Add
+	tests/test-posix_spawn-script.c, tests/executable-script,
+	tests/executable-shell-script.
+	(Makefile.am): Compile and run test-posix_spawn-script.
+	* modules/posix_spawnp-tests (Files): Add
+	tests/test-posix_spawnp-script.c, tests/executable-script,
+	tests/executable-shell-script.
+	(Makefile.am): Compile and run test-posix_spawnp-script.
+	* modules/execute-tests (Files): Add tests/test-execute-script.c,
+	tests/executable-script, tests/executable-shell-script.
+	(Makefile.am): Compile and run test-execute-script.
+	* modules/spawn-pipe-tests (Files): Add tests/test-spawn-pipe-script.c,
+	tests/executable-script, tests/executable-shell-script.
+	(Makefile.am): Compile and run test-spawn-pipe-script.
+
+2020-12-23  Bruno Haible  <br...@clisp.org>
+
 	Don't execute scripts without '#!' marker through /bin/sh.
 	This reflects the change done in glibc through
 	<https://sourceware.org/bugzilla/show_bug.cgi?id=13134> and
diff --git a/modules/execute-tests b/modules/execute-tests
index 9562182..2213a32 100644
--- a/modules/execute-tests
+++ b/modules/execute-tests
@@ -2,6 +2,9 @@ Files:
 tests/test-execute.sh
 tests/test-execute-main.c
 tests/test-execute-child.c
+tests/test-execute-script.c
+tests/executable-script
+tests/executable-shell-script
 tests/macros.h
 
 Depends-on:
@@ -23,3 +26,8 @@ test_execute_main_LDADD = $(LDADD) @LIBINTL@ $(LIBTHREAD)
 # wrapper script, and should link against as few libraries as possible.
 # Therefore don't link it against any libraries other than -lc.
 test_execute_child_LDADD =
+
+TESTS += test-execute-script
+check_PROGRAMS += test-execute-script
+test_execute_script_LDADD = $(LDADD) @LIBINTL@ $(LIBTHREAD)
+test_execute_script_CPPFLAGS = $(AM_CPPFLAGS) -DSRCDIR=\"$(srcdir)/\"
diff --git a/modules/posix_spawn-tests b/modules/posix_spawn-tests
index 2c8b4a5..451dbd1 100644
--- a/modules/posix_spawn-tests
+++ b/modules/posix_spawn-tests
@@ -3,6 +3,9 @@ tests/test-posix_spawn-open1.c
 tests/test-posix_spawn-open2.c
 tests/test-posix_spawn-inherit0.c
 tests/test-posix_spawn-inherit1.c
+tests/test-posix_spawn-script.c
+tests/executable-script
+tests/executable-shell-script
 tests/signature.h
 
 Depends-on:
@@ -31,10 +34,13 @@ TESTS += \
   test-posix_spawn-open1 \
   test-posix_spawn-open2 \
   test-posix_spawn-inherit0 \
-  test-posix_spawn-inherit1
+  test-posix_spawn-inherit1 \
+  test-posix_spawn-script
 check_PROGRAMS += \
   test-posix_spawn-open1 \
   test-posix_spawn-open2 \
   test-posix_spawn-inherit0 \
-  test-posix_spawn-inherit1
+  test-posix_spawn-inherit1 \
+  test-posix_spawn-script
+test_posix_spawn_script_CPPFLAGS = $(AM_CPPFLAGS) -DSRCDIR=\"$(srcdir)/\"
 endif
diff --git a/modules/posix_spawnp-tests b/modules/posix_spawnp-tests
index 1f6bbc7..04ccdbb 100644
--- a/modules/posix_spawnp-tests
+++ b/modules/posix_spawnp-tests
@@ -3,6 +3,9 @@ tests/test-posix_spawn-dup2-stdout.c
 tests/test-posix_spawn-dup2-stdout.in.sh
 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-shell-script
 tests/signature.h
 
 Depends-on:
@@ -35,8 +38,14 @@ AM_CONDITIONAL([POSIX_SPAWN_PORTED], [test $posix_spawn_ported = yes])
 
 Makefile.am:
 if POSIX_SPAWN_PORTED
-TESTS += test-posix_spawn-dup2-stdout test-posix_spawn-dup2-stdin
-check_PROGRAMS += test-posix_spawn-dup2-stdout test-posix_spawn-dup2-stdin
+TESTS += \
+  test-posix_spawn-dup2-stdout \
+  test-posix_spawn-dup2-stdin \
+  test-posix_spawnp-script
+check_PROGRAMS += \
+  test-posix_spawn-dup2-stdout \
+  test-posix_spawn-dup2-stdin \
+  test-posix_spawnp-script
 
 BUILT_SOURCES += test-posix_spawn-dup2-stdout.sh
 test-posix_spawn-dup2-stdout.sh: test-posix_spawn-dup2-stdout.in.sh
@@ -51,4 +60,6 @@ test-posix_spawn-dup2-stdin.sh: test-posix_spawn-dup2-stdin.in.sh
 	cp $(srcdir)/test-posix_spawn-dup2-stdin.in.sh $@-t && \
 	mv $@-t $@
 MOSTLYCLEANFILES += test-posix_spawn-dup2-stdin.sh test-posix_spawn-dup2-stdin.sh-t
+
+test_posix_spawnp_script_CPPFLAGS = $(AM_CPPFLAGS) -DSRCDIR=\"$(srcdir)/\"
 endif
diff --git a/modules/spawn-pipe-tests b/modules/spawn-pipe-tests
index 5d1372c..80614a9 100644
--- a/modules/spawn-pipe-tests
+++ b/modules/spawn-pipe-tests
@@ -2,6 +2,9 @@ Files:
 tests/test-spawn-pipe.sh
 tests/test-spawn-pipe-main.c
 tests/test-spawn-pipe-child.c
+tests/test-spawn-pipe-script.c
+tests/executable-script
+tests/executable-shell-script
 tests/macros.h
 
 Depends-on:
@@ -19,3 +22,8 @@ test_spawn_pipe_main_LDADD = $(LDADD) @LIBINTL@ $(LIBTHREAD)
 # wrapper script, and should link against as few libraries as possible.
 # Therefore don't link it against any libraries other than -lc.
 test_spawn_pipe_child_LDADD =
+
+TESTS += test-spawn-pipe-script
+check_PROGRAMS += test-spawn-pipe-script
+test_spawn_pipe_script_LDADD = $(LDADD) @LIBINTL@ $(LIBTHREAD)
+test_spawn_pipe_script_CPPFLAGS = $(AM_CPPFLAGS) -DSRCDIR=\"$(srcdir)/\"
diff --git a/tests/executable-script b/tests/executable-script
new file mode 100755
index 0000000..7d8b9cc
--- /dev/null
+++ b/tests/executable-script
@@ -0,0 +1,4 @@
+printf 'Halle '
+printf "Potta"
+# This script is intentionally not immediately recognizable as a shell script.
+# Don't add a .sh suffix. Don't add a #! header in the first line.
diff --git a/tests/executable-shell-script b/tests/executable-shell-script
new file mode 100755
index 0000000..1e38117
--- /dev/null
+++ b/tests/executable-shell-script
@@ -0,0 +1,4 @@
+#!/bin/sh
+# This script is a proper shell script.
+printf 'Halle '
+printf "Potta"
diff --git a/tests/test-execute-script.c b/tests/test-execute-script.c
new file mode 100644
index 0000000..060f0c5
--- /dev/null
+++ b/tests/test-execute-script.c
@@ -0,0 +1,88 @@
+/* Test of execute.
+   Copyright (C) 2020 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, see <https://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+#include "execute.h"
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "read-file.h"
+#include "macros.h"
+
+#define DATA_FILENAME "test-execute-script.tmp"
+
+int
+main ()
+{
+  unlink (DATA_FILENAME);
+
+  /* Check an invocation of an executable script.
+     This should only be supported if the script has a '#!' marker; otherwise
+     it is unsecure: <https://sourceware.org/bugzilla/show_bug.cgi?id=13134>.
+     POSIX says that the execlp() and execvp() functions support executing
+     shell scripts
+     <https://pubs.opengroup.org/onlinepubs/9699919799/functions/exec.html>,
+     but this is considered an antiquated feature.  */
+
+  /* This test is an extension of
+     "Check stdout is inherited, part 1 (regular file)"
+     in test-execute-main.c.  */
+  FILE *fp = freopen (DATA_FILENAME, "w", stdout);
+  ASSERT (fp != NULL);
+
+  {
+    const char *progname = "executable-script";
+    const char *prog_path = SRCDIR "executable-script";
+    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.
+     Only .bat and .cmd files are.  */
+  ASSERT (fclose (fp) == 0);
+  ASSERT (unlink (DATA_FILENAME) == 0);
+  fprintf (stderr, "Skipping test: scripts are not executable on this platform.\n");
+  return 77;
+#else
+  {
+    const char *progname = "executable-shell-script";
+    const char *prog_path = SRCDIR "executable-shell-script";
+    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 == 0);
+
+    ASSERT (fclose (fp) == 0);
+
+    size_t length;
+    char *contents = read_file (DATA_FILENAME, 0, &length);
+    ASSERT (length == 11 && memcmp (contents, "Halle Potta", 11) == 0);
+  }
+
+  ASSERT (unlink (DATA_FILENAME) == 0);
+
+  return 0;
+#endif
+}
diff --git a/tests/test-posix_spawn-script.c b/tests/test-posix_spawn-script.c
new file mode 100644
index 0000000..a632841
--- /dev/null
+++ b/tests/test-posix_spawn-script.c
@@ -0,0 +1,143 @@
+/* Test of posix_spawn() function.
+   Copyright (C) 2020 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, see <https://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+#include <spawn.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include "macros.h"
+
+#define DATA_FILENAME "test-posix_spawn-script.tmp"
+
+int
+main ()
+{
+  unlink (DATA_FILENAME);
+
+  /* Check an invocation of an executable script.
+     This should only be supported if the script has a '#!' marker; otherwise
+     it is unsecure: <https://sourceware.org/bugzilla/show_bug.cgi?id=13134>.
+     POSIX says that the execlp() and execvp() functions support executing
+     shell scripts
+     <https://pubs.opengroup.org/onlinepubs/9699919799/functions/exec.html>,
+     but this is considered an antiquated feature.  */
+  pid_t child;
+
+  posix_spawn_file_actions_t actions;
+  ASSERT (posix_spawn_file_actions_init (&actions) == 0);
+  ASSERT (posix_spawn_file_actions_addopen (&actions, STDOUT_FILENO,
+                                            DATA_FILENAME,
+                                            O_RDWR | O_CREAT | O_TRUNC, 0600)
+          == 0);
+
+  {
+    const char *prog_path = SRCDIR "executable-script";
+    const char *prog_argv[2] = { prog_path, NULL };
+
+    int err = posix_spawn (&child, prog_path, &actions, NULL,
+                           (char **) prog_argv, environ);
+    if (err != ENOEXEC)
+      {
+        if (err != 0)
+          {
+            errno = err;
+            perror ("posix_spawn");
+            return 1;
+          }
+
+        /* Wait for child.  */
+        int status = 0;
+        while (waitpid (child, &status, 0) != child)
+          ;
+        if (!WIFEXITED (status))
+          {
+            fprintf (stderr, "subprocess terminated with unexpected wait status %d\n", status);
+            return 1;
+          }
+        int exitstatus = WEXITSTATUS (status);
+        if (exitstatus != 127)
+          {
+            fprintf (stderr, "subprocess terminated with unexpected exit status %d\n", exitstatus);
+            return 1;
+          }
+      }
+  }
+
+  {
+    const char *prog_path = SRCDIR "executable-shell-script";
+    const char *prog_argv[2] = { prog_path, NULL };
+
+    int err = posix_spawn (&child, prog_path, &actions, NULL,
+                           (char **) prog_argv, environ);
+    if (err != 0)
+      {
+        errno = err;
+        perror ("posix_spawn");
+        return 1;
+      }
+
+    posix_spawn_file_actions_destroy (&actions);
+
+    /* Wait for child.  */
+    int status = 0;
+    while (waitpid (child, &status, 0) != child)
+      ;
+    if (!WIFEXITED (status))
+      {
+        fprintf (stderr, "subprocess terminated with unexpected wait status %d\n", status);
+        return 1;
+      }
+    int exitstatus = WEXITSTATUS (status);
+    if (exitstatus != 0)
+      {
+        fprintf (stderr, "subprocess terminated with unexpected exit status %d\n", exitstatus);
+        return 1;
+      }
+
+    /* Check the contents of the data file.  */
+    FILE *fp = fopen (DATA_FILENAME, "rb");
+    if (fp == NULL)
+      {
+        perror ("cannot open data file");
+        return 1;
+      }
+    char buf[1024];
+    int nread = fread (buf, 1, sizeof (buf), fp);
+    if (!(nread == 11 && memcmp (buf, "Halle Potta", 11) == 0))
+      {
+        fprintf (stderr, "data file wrong: has %d bytes, expected %d bytes\n", nread, 11);
+        return 1;
+      }
+    if (fclose (fp))
+      {
+        perror ("cannot close data file");
+        return 1;
+      }
+  }
+
+  /* Clean up data file.  */
+  unlink (DATA_FILENAME);
+
+  return 0;
+}
diff --git a/tests/test-posix_spawnp-script.c b/tests/test-posix_spawnp-script.c
new file mode 100644
index 0000000..04bf496
--- /dev/null
+++ b/tests/test-posix_spawnp-script.c
@@ -0,0 +1,143 @@
+/* Test of posix_spawnp() function.
+   Copyright (C) 2020 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, see <https://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+#include <spawn.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include "macros.h"
+
+#define DATA_FILENAME "test-posix_spawn-script.tmp"
+
+int
+main ()
+{
+  unlink (DATA_FILENAME);
+
+  /* Check an invocation of an executable script.
+     This should only be supported if the script has a '#!' marker; otherwise
+     it is unsecure: <https://sourceware.org/bugzilla/show_bug.cgi?id=13134>.
+     POSIX says that the execlp() and execvp() functions support executing
+     shell scripts
+     <https://pubs.opengroup.org/onlinepubs/9699919799/functions/exec.html>,
+     but this is considered an antiquated feature.  */
+  pid_t child;
+
+  posix_spawn_file_actions_t actions;
+  ASSERT (posix_spawn_file_actions_init (&actions) == 0);
+  ASSERT (posix_spawn_file_actions_addopen (&actions, STDOUT_FILENO,
+                                            DATA_FILENAME,
+                                            O_RDWR | O_CREAT | O_TRUNC, 0600)
+          == 0);
+
+  {
+    const char *prog_path = SRCDIR "executable-script";
+    const char *prog_argv[2] = { prog_path, NULL };
+
+    int err = posix_spawnp (&child, prog_path, &actions, NULL,
+                            (char **) prog_argv, environ);
+    if (err != ENOEXEC)
+      {
+        if (err != 0)
+          {
+            errno = err;
+            perror ("posix_spawn");
+            return 1;
+          }
+
+        /* Wait for child.  */
+        int status = 0;
+        while (waitpid (child, &status, 0) != child)
+          ;
+        if (!WIFEXITED (status))
+          {
+            fprintf (stderr, "subprocess terminated with unexpected wait status %d\n", status);
+            return 1;
+          }
+        int exitstatus = WEXITSTATUS (status);
+        if (exitstatus != 127)
+          {
+            fprintf (stderr, "subprocess terminated with unexpected exit status %d\n", exitstatus);
+            return 1;
+          }
+      }
+  }
+
+  {
+    const char *prog_path = SRCDIR "executable-shell-script";
+    const char *prog_argv[2] = { prog_path, NULL };
+
+    int err = posix_spawnp (&child, prog_path, &actions, NULL,
+                            (char **) prog_argv, environ);
+    if (err != 0)
+      {
+        errno = err;
+        perror ("posix_spawn");
+        return 1;
+      }
+
+    posix_spawn_file_actions_destroy (&actions);
+
+    /* Wait for child.  */
+    int status = 0;
+    while (waitpid (child, &status, 0) != child)
+      ;
+    if (!WIFEXITED (status))
+      {
+        fprintf (stderr, "subprocess terminated with unexpected wait status %d\n", status);
+        return 1;
+      }
+    int exitstatus = WEXITSTATUS (status);
+    if (exitstatus != 0)
+      {
+        fprintf (stderr, "subprocess terminated with unexpected exit status %d\n", exitstatus);
+        return 1;
+      }
+
+    /* Check the contents of the data file.  */
+    FILE *fp = fopen (DATA_FILENAME, "rb");
+    if (fp == NULL)
+      {
+        perror ("cannot open data file");
+        return 1;
+      }
+    char buf[1024];
+    int nread = fread (buf, 1, sizeof (buf), fp);
+    if (!(nread == 11 && memcmp (buf, "Halle Potta", 11) == 0))
+      {
+        fprintf (stderr, "data file wrong: has %d bytes, expected %d bytes\n", nread, 11);
+        return 1;
+      }
+    if (fclose (fp))
+      {
+        perror ("cannot close data file");
+        return 1;
+      }
+  }
+
+  /* Clean up data file.  */
+  unlink (DATA_FILENAME);
+
+  return 0;
+}
diff --git a/tests/test-spawn-pipe-script.c b/tests/test-spawn-pipe-script.c
new file mode 100644
index 0000000..44f9d2c
--- /dev/null
+++ b/tests/test-spawn-pipe-script.c
@@ -0,0 +1,100 @@
+/* Test of create_pipe_in/wait_subprocess.
+   Copyright (C) 2020 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, see <https://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+#include "spawn-pipe.h"
+#include "wait-process.h"
+
+#include <errno.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "macros.h"
+
+int
+main ()
+{
+  /* Check an invocation of an executable script.
+     This should only be supported if the script has a '#!' marker; otherwise
+     it is unsecure: <https://sourceware.org/bugzilla/show_bug.cgi?id=13134>.
+     POSIX says that the execlp() and execvp() functions support executing
+     shell scripts
+     <https://pubs.opengroup.org/onlinepubs/9699919799/functions/exec.html>,
+     but this is considered an antiquated feature.  */
+  int fd[1];
+  pid_t pid;
+
+  {
+    const char *progname = "executable-script";
+    const char *prog_path = SRCDIR "executable-script";
+    const char *prog_argv[2] = { prog_path, NULL };
+
+    pid = create_pipe_in (progname, prog_argv[0], prog_argv, NULL,
+                          NULL, false, true, false, fd);
+    if (pid >= 0)
+      {
+        /* Wait for child.  */
+        ASSERT (wait_subprocess (pid, progname, true, true, true, false, NULL)
+                == 127);
+      }
+    else
+      {
+        ASSERT (pid == -1);
+#if defined _WIN32 && !defined __CYGWIN__
+        ASSERT (errno == ENOENT);
+#else
+        ASSERT (errno == ENOEXEC);
+#endif
+      }
+  }
+
+#if defined _WIN32 && !defined __CYGWIN__
+  /* On native Windows, scripts - even with '#!' marker - are not executable.
+     Only .bat and .cmd files are.  */
+  fprintf (stderr, "Skipping test: scripts are not executable on this platform.\n");
+  return 77;
+#else
+  {
+    const char *progname = "executable-shell-script";
+    const char *prog_path = SRCDIR "executable-shell-script";
+    const char *prog_argv[2] = { prog_path, NULL };
+
+    pid = create_pipe_in (progname, prog_argv[0], prog_argv, NULL,
+                          NULL, false, true, false, fd);
+    ASSERT (pid >= 0);
+    ASSERT (fd[0] > STDERR_FILENO);
+
+    /* Get child's output.  */
+    char buffer[1024];
+    FILE *fp = fdopen (fd[0], "r");
+    ASSERT (fp != NULL);
+    ASSERT (fread (buffer, 1, sizeof (buffer), fp) == 11);
+
+    /* Check the result.  */
+    ASSERT (memcmp (buffer, "Halle Potta", 11) == 0);
+
+    /* Wait for child.  */
+    ASSERT (wait_subprocess (pid, progname, true, false, true, true, NULL) == 0);
+
+    ASSERT (fclose (fp) == 0);
+  }
+
+  return 0;
+#endif
+}
-- 
2.7.4

>From 2845b3bed86ca649d3206d9b1e0fe30a4ca33110 Mon Sep 17 00:00:00 2001
From: Bruno Haible <br...@clisp.org>
Date: Thu, 24 Dec 2020 03:49:20 +0100
Subject: [PATCH 3/3] posix_spawn, posix_spawnp: Fix execution of scripts.

* m4/posix_spawn.m4 (gl_POSIX_SPAWN_SECURE): New macro.
(gl_POSIX_SPAWN_BODY): Invoke it. Set REPLACE_POSIX_SPAWN if posix_spawn
or posix_spawnp allows unsecure execution of scripts.
* doc/posix-functions/posix_spawn.texi: Document the script execution
problem.
* doc/posix-functions/posix_spawnp.texi: Likewise.
---
 ChangeLog                             |  10 ++
 doc/posix-functions/posix_spawn.texi  |   5 +
 doc/posix-functions/posix_spawnp.texi |   5 +
 m4/posix_spawn.m4                     | 169 +++++++++++++++++++++++++++++-----
 4 files changed, 164 insertions(+), 25 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index bfb7f88..e7e5f11 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,15 @@
 2020-12-23  Bruno Haible  <br...@clisp.org>
 
+	posix_spawn, posix_spawnp: Fix execution of scripts.
+	* m4/posix_spawn.m4 (gl_POSIX_SPAWN_SECURE): New macro.
+	(gl_POSIX_SPAWN_BODY): Invoke it. Set REPLACE_POSIX_SPAWN if posix_spawn
+	or posix_spawnp allows unsecure execution of scripts.
+	* doc/posix-functions/posix_spawn.texi: Document the script execution
+	problem.
+	* doc/posix-functions/posix_spawnp.texi: Likewise.
+
+2020-12-23  Bruno Haible  <br...@clisp.org>
+
 	Add unit tests regarding execution of scripts.
 	* tests/executable-script: New file.
 	* tests/executable-shell-script: New file.
diff --git a/doc/posix-functions/posix_spawn.texi b/doc/posix-functions/posix_spawn.texi
index 7a3a2f6..e0b39b0 100644
--- a/doc/posix-functions/posix_spawn.texi
+++ b/doc/posix-functions/posix_spawn.texi
@@ -15,6 +15,11 @@ FreeBSD 6.0, NetBSD 5.0, OpenBSD 3.8, Minix 3.1.8, AIX 5.1, HP-UX 11, IRIX 6.5,
 When this function fails, it causes the stdio buffer contents to be output
 twice on some platforms:
 AIX 6.1.
+@item
+When the program to be invoked is an executable script without a @samp{#!}
+marker in the first line, this function executes the script as if it were
+a shell script, on some platforms:
+GNU/Hurd.
 @end itemize
 
 Portability problems not fixed by Gnulib:
diff --git a/doc/posix-functions/posix_spawnp.texi b/doc/posix-functions/posix_spawnp.texi
index c420db9..2dd9f68 100644
--- a/doc/posix-functions/posix_spawnp.texi
+++ b/doc/posix-functions/posix_spawnp.texi
@@ -15,6 +15,11 @@ FreeBSD 6.0, NetBSD 5.0, OpenBSD 3.8, Minix 3.1.8, AIX 5.1, HP-UX 11, IRIX 6.5,
 When this function fails, it causes the stdio buffer contents to be output
 twice on some platforms:
 AIX 6.1.
+@item
+When the program to be invoked is an executable script without a @samp{#!}
+marker in the first line, this function executes the script as if it were
+a shell script, on some platforms:
+glibc 2.14, GNU/Hurd, Mac OS X 10.13, FreeBSD 12.0, OpenBSD 6.7, AIX 7.2, Solaris 11.4, Cygwin 2.9.
 @end itemize
 
 Portability problems not fixed by Gnulib:
diff --git a/m4/posix_spawn.m4 b/m4/posix_spawn.m4
index 625b2ad..59e56fc 100644
--- a/m4/posix_spawn.m4
+++ b/m4/posix_spawn.m4
@@ -1,4 +1,4 @@
-# posix_spawn.m4 serial 18
+# posix_spawn.m4 serial 19
 dnl Copyright (C) 2008-2020 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -54,40 +54,52 @@ AC_DEFUN([gl_POSIX_SPAWN_BODY],
     if test $REPLACE_POSIX_SPAWN = 0; then
       gl_POSIX_SPAWN_WORKS
       case "$gl_cv_func_posix_spawn_works" in
-        *yes)
-          dnl Assume that these functions are available if POSIX_SPAWN_SETSCHEDULER
-          dnl evaluates to nonzero.
-          dnl AC_CHECK_FUNCS_ONCE([posix_spawnattr_getschedpolicy])
-          dnl AC_CHECK_FUNCS_ONCE([posix_spawnattr_setschedpolicy])
-          AC_CACHE_CHECK([whether posix_spawnattr_setschedpolicy is supported],
-            [gl_cv_func_spawnattr_setschedpolicy],
-            [AC_EGREP_CPP([POSIX scheduling supported], [
+        *yes) ;;
+        *) REPLACE_POSIX_SPAWN=1 ;;
+      esac
+    fi
+    if test $REPLACE_POSIX_SPAWN = 0; then
+      gl_POSIX_SPAWN_SECURE
+      case "$gl_cv_func_posix_spawn_secure_exec" in
+        *yes) ;;
+        *) REPLACE_POSIX_SPAWN=1 ;;
+      esac
+      case "$gl_cv_func_posix_spawnp_secure_exec" in
+        *yes) ;;
+        *) REPLACE_POSIX_SPAWN=1 ;;
+      esac
+    fi
+    if test $REPLACE_POSIX_SPAWN = 0; then
+      dnl Assume that these functions are available if POSIX_SPAWN_SETSCHEDULER
+      dnl evaluates to nonzero.
+      dnl AC_CHECK_FUNCS_ONCE([posix_spawnattr_getschedpolicy])
+      dnl AC_CHECK_FUNCS_ONCE([posix_spawnattr_setschedpolicy])
+      AC_CACHE_CHECK([whether posix_spawnattr_setschedpolicy is supported],
+        [gl_cv_func_spawnattr_setschedpolicy],
+        [AC_EGREP_CPP([POSIX scheduling supported], [
 #include <spawn.h>
 #if POSIX_SPAWN_SETSCHEDULER
  POSIX scheduling supported
 #endif
 ],
-               [gl_cv_func_spawnattr_setschedpolicy=yes],
-               [gl_cv_func_spawnattr_setschedpolicy=no])
-            ])
-          dnl Assume that these functions are available if POSIX_SPAWN_SETSCHEDPARAM
-          dnl evaluates to nonzero.
-          dnl AC_CHECK_FUNCS_ONCE([posix_spawnattr_getschedparam])
-          dnl AC_CHECK_FUNCS_ONCE([posix_spawnattr_setschedparam])
-          AC_CACHE_CHECK([whether posix_spawnattr_setschedparam is supported],
-            [gl_cv_func_spawnattr_setschedparam],
-            [AC_EGREP_CPP([POSIX scheduling supported], [
+           [gl_cv_func_spawnattr_setschedpolicy=yes],
+           [gl_cv_func_spawnattr_setschedpolicy=no])
+        ])
+      dnl Assume that these functions are available if POSIX_SPAWN_SETSCHEDPARAM
+      dnl evaluates to nonzero.
+      dnl AC_CHECK_FUNCS_ONCE([posix_spawnattr_getschedparam])
+      dnl AC_CHECK_FUNCS_ONCE([posix_spawnattr_setschedparam])
+      AC_CACHE_CHECK([whether posix_spawnattr_setschedparam is supported],
+        [gl_cv_func_spawnattr_setschedparam],
+        [AC_EGREP_CPP([POSIX scheduling supported], [
 #include <spawn.h>
 #if POSIX_SPAWN_SETSCHEDPARAM
  POSIX scheduling supported
 #endif
 ],
-               [gl_cv_func_spawnattr_setschedparam=yes],
-               [gl_cv_func_spawnattr_setschedparam=no])
-            ])
-          ;;
-        *) REPLACE_POSIX_SPAWN=1 ;;
-      esac
+           [gl_cv_func_spawnattr_setschedparam=yes],
+           [gl_cv_func_spawnattr_setschedparam=no])
+        ])
     fi
   fi
   if test $ac_cv_func_posix_spawn != yes || test $REPLACE_POSIX_SPAWN = 1; then
@@ -417,6 +429,113 @@ main (int argc, char *argv[])
     ])
 ])
 
+dnl Test whether posix_spawn and posix_spawnp are secure.
+AC_DEFUN([gl_POSIX_SPAWN_SECURE],
+[
+  AC_REQUIRE([AC_PROG_CC])
+  AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
+  dnl On many platforms, posix_spawn or posix_spawnp allow executing a
+  dnl script without a '#!' marker as a shell script. This is unsecure.
+  AC_CACHE_CHECK([whether posix_spawn rejects scripts without shebang],
+    [gl_cv_func_posix_spawn_secure_exec],
+    [echo ':' > conftest.scr
+     chmod a+x conftest.scr
+     AC_RUN_IFELSE([AC_LANG_SOURCE([[
+       #include <errno.h>
+       #include <spawn.h>
+       #include <stddef.h>
+       #include <sys/types.h>
+       #include <sys/wait.h>
+       int
+       main ()
+       {
+         const char *prog_path = "./conftest.scr";
+         const char *prog_argv[2] = { prog_path, NULL };
+         const char *environment[2] = { "PATH=.", NULL };
+         pid_t child;
+         int status;
+         int err = posix_spawn (&child, prog_path, NULL, NULL,
+                                (char **) prog_argv, (char **) environment);
+         if (err == ENOEXEC)
+           return 0;
+         if (err != 0)
+           return 1;
+         status = 0;
+         while (waitpid (child, &status, 0) != child)
+           ;
+         if (!WIFEXITED (status))
+           return 2;
+         if (WEXITSTATUS (status) != 127)
+           return 3;
+         return 0;
+       }
+       ]])],
+       [gl_cv_func_posix_spawn_secure_exec=yes],
+       [gl_cv_func_posix_spawn_secure_exec=no],
+       [case "$host_os" in
+          # Guess no on GNU/Hurd.
+          gnu*)
+            gl_cv_func_posix_spawn_secure_exec="guessing no" ;;
+          # Guess yes on all other platforms.
+          *)
+            gl_cv_func_posix_spawn_secure_exec="guessing yes" ;;
+        esac
+       ])
+     rm -f conftest.scr
+    ])
+  AC_CACHE_CHECK([whether posix_spawnp rejects scripts without shebang],
+    [gl_cv_func_posix_spawnp_secure_exec],
+    [echo ':' > conftest.scr
+     chmod a+x conftest.scr
+     AC_RUN_IFELSE([AC_LANG_SOURCE([[
+       #include <errno.h>
+       #include <spawn.h>
+       #include <stddef.h>
+       #include <sys/types.h>
+       #include <sys/wait.h>
+       int
+       main ()
+       {
+         const char *prog_path = "./conftest.scr";
+         const char *prog_argv[2] = { prog_path, NULL };
+         const char *environment[2] = { "PATH=.", NULL };
+         pid_t child;
+         int status;
+         int err = posix_spawnp (&child, prog_path, NULL, NULL,
+                                 (char **) prog_argv, (char **) environment);
+         if (err == ENOEXEC)
+           return 0;
+         if (err != 0)
+           return 1;
+         status = 0;
+         while (waitpid (child, &status, 0) != child)
+           ;
+         if (!WIFEXITED (status))
+           return 2;
+         if (WEXITSTATUS (status) != 127)
+           return 3;
+         return 0;
+       }
+       ]])],
+       [gl_cv_func_posix_spawnp_secure_exec=yes],
+       [gl_cv_func_posix_spawnp_secure_exec=no],
+       [case "$host_os" in
+          # Guess yes on glibc systems (glibc >= 2.15 actually) except GNU/Hurd,
+          # musl libc, NetBSD.
+          *-gnu* | *-musl* | netbsd*)
+            gl_cv_func_posix_spawnp_secure_exec="guessing yes" ;;
+          # Guess no on GNU/Hurd, macOS, FreeBSD, OpenBSD, AIX, Solaris, Cygwin.
+          gnu* | darwin* | freebsd* | dragonfly* | openbsd* | aix* | solaris* | cygwin*)
+            gl_cv_func_posix_spawnp_secure_exec="guessing no" ;;
+          # If we don't know, obey --enable-cross-guesses.
+          *)
+            gl_cv_func_posix_spawnp_secure_exec="$gl_cross_guess_normal" ;;
+        esac
+       ])
+     rm -f conftest.scr
+    ])
+])
+
 # Prerequisites of lib/spawni.c.
 AC_DEFUN([gl_PREREQ_POSIX_SPAWN_INTERNAL],
 [
-- 
2.7.4

Reply via email to