bug-gnulib@gnu.org mirror (unofficial)
 help / color / mirror / Atom feed
* new modules execve, execvpe, execvp, execv, execl, execle, execlp
@ 2020-12-26 13:53 Bruno Haible
  2020-12-27 11:15 ` Jeffrey Walton
  0 siblings, 1 reply; 4+ messages in thread
From: Bruno Haible @ 2020-12-26 13:53 UTC (permalink / raw)
  To: bug-gnulib; +Cc: Eli Zaretskii

[-- Attachment #1: Type: text/plain, Size: 3682 bytes --]

Eli Zaretskii wrote in
<https://lists.gnu.org/archive/html/bug-grep/2014-05/msg00118.html>:

  ... found that the implementation of the exec* family did
  the following: it started the process that runs the child program, and
  then immediately exited without waiting for the child to finish.
  ...
  The solution was to reimplement execvp in a way that didn't exit ...
  until the child program finished.

Indeed, that is a major problem with these exec* implementations: The
parent process cannot know the exit code if the exec'd process runs
asynchronously.

Another major problem is that the Windows _spawnv* and CreateProcess
functions split the arguments when they contain spaces or special
characters.

All of these problems are fixed with these new Gnulib modules.


2020-12-26  Bruno Haible  <bruno@clisp.org>

	execlp: Add tests.
	* tests/test-execlp-main.c: New file.
	* tests/test-execlp.sh: New file.
	* modules/execlp-tests: New file.

	execlp: New module.
	* lib/execlp.c: New file.
	* m4/execlp.m4: New file.
	* modules/execlp: New file.
	* doc/posix-functions/execlp.texi: Mention more Windows problems and the
	new module.

	execle: Add tests.
	* tests/test-execle-main.c: New file.
	* tests/test-execle.sh: New file.
	* modules/execle-tests: New file.

	execle: New module.
	* lib/execle.c: New file.
	* m4/execle.m4: New file.
	* modules/execle: New file.
	* doc/posix-functions/execle.texi: Mention more Windows problems and the
	new module.

	execl: Add tests.
	* tests/test-execl-main.c: New file.
	* tests/test-execl.sh: New file.
	* modules/execl-tests: New file.

	execl: New module.
	* lib/execl.c: New file.
	* m4/execl.m4: New file.
	* modules/execl: New file.
	* doc/posix-functions/execl.texi: Mention more Windows problems and the
	new module.

	execv: Add tests.
	* tests/test-execv-main.c: New file.
	* tests/test-execv.sh: New file.
	* modules/execv-tests: New file.

	execv: New module.
	* lib/execv.c: New file.
	* m4/execv.m4: New file.
	* modules/execv: New file.
	* doc/posix-functions/execv.texi: Mention more Windows problems and the
	new module.

	execvp: Add tests.
	* tests/test-execvp-main.c: New file.
	* tests/test-execvp.sh: New file.
	* modules/execvp-tests: New file.

	execvp: New module.
	* lib/execvp.c: New file.
	* m4/execvp.m4: New file.
	* modules/execvp: New file.
	* doc/posix-functions/execvp.texi: Mention more Windows problems and the
	new module.

	execvpe: Add tests.
	* tests/test-execvpe-main.c: New file.
	* tests/test-execvpe.sh: New file.
	* modules/execvpe-tests: New file.

	execvpe: New module.
	* lib/execvpe.c: New file.
	* m4/execvpe.m4: New file.
	* modules/execvpe: New file.
	* doc/glibc-functions/execvpe.texi: Mention the Windows problems and the
	new module.

	execve: Add tests.
	* tests/test-exec-child.c: New file.
	* tests/test-execve-main.c: New file.
	* tests/test-execve.sh: New file.
	* modules/execve-tests: New file.

	execve: New module.
	* lib/execve.c: New file.
	* m4/execve.m4: New file.
	* modules/execve: New file.
	* doc/posix-functions/execve.texi: Mention more Windows problems and the
	new module.

	execve, execvpe, execvp, execv, execl, execle, execlp: Prepare modules.
	* lib/unistd.in.h (execl, execle, execlp, execv, execve, execvp,
	execvpe): Add declarations for the new modules.
	* m4/unistd_h.m4 (gl_UNISTD_H): Test whether execl, execle, execlp,
	execv, execve, execvp, execvpe are declared.
	(gl_UNISTD_H_DEFAULTS): Initialize GNULIB_EXEC*, HAVE_EXECVPE,
	REPLACE_EXEC*.
	* modules/unistd (Makefile.am): Substitute GNULIB_EXEC*, HAVE_EXECVPE,
	REPLACE_EXEC*.
	* tests/test-unistd-c++.cc: Check the signature of execl, execle,
	execlp, execv, execve, execvp, execvpe.


[-- Attachment #2: 0001-execve-execvpe-execvp-execv-execl-execle-execlp-Prep.patch --]
[-- Type: text/x-patch, Size: 19294 bytes --]

From ba3aeabdd5317c3e21d1da54577235a054ce60f3 Mon Sep 17 00:00:00 2001
From: Bruno Haible <bruno@clisp.org>
Date: Sat, 26 Dec 2020 14:09:29 +0100
Subject: [PATCH 01/15] execve, execvpe, execvp, execv, execl, execle, execlp:
 Prepare modules.

* lib/unistd.in.h (execl, execle, execlp, execv, execve, execvp,
execvpe): Add declarations for the new modules.
* m4/unistd_h.m4 (gl_UNISTD_H): Test whether execl, execle, execlp,
execv, execve, execvp, execvpe are declared.
(gl_UNISTD_H_DEFAULTS): Initialize GNULIB_EXEC*, HAVE_EXECVPE,
REPLACE_EXEC*.
* modules/unistd (Makefile.am): Substitute GNULIB_EXEC*, HAVE_EXECVPE,
REPLACE_EXEC*.
* tests/test-unistd-c++.cc: Check the signature of execl, execle,
execlp, execv, execve, execvp, execvpe.
---
 ChangeLog                |  14 ++++
 lib/unistd.in.h          | 195 +++++++++++++++++++++++++++++++++++++++++------
 m4/unistd_h.m4           |  18 ++++-
 modules/unistd           |  15 ++++
 tests/test-unistd-c++.cc |  35 +++++++++
 5 files changed, 253 insertions(+), 24 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 6752466..459df8e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,19 @@
 2020-12-26  Bruno Haible  <bruno@clisp.org>
 
+	execve, execvpe, execvp, execv, execl, execle, execlp: Prepare modules.
+	* lib/unistd.in.h (execl, execle, execlp, execv, execve, execvp,
+	execvpe): Add declarations for the new modules.
+	* m4/unistd_h.m4 (gl_UNISTD_H): Test whether execl, execle, execlp,
+	execv, execve, execvp, execvpe are declared.
+	(gl_UNISTD_H_DEFAULTS): Initialize GNULIB_EXEC*, HAVE_EXECVPE,
+	REPLACE_EXEC*.
+	* modules/unistd (Makefile.am): Substitute GNULIB_EXEC*, HAVE_EXECVPE,
+	REPLACE_EXEC*.
+	* tests/test-unistd-c++.cc: Check the signature of execl, execle,
+	execlp, execv, execve, execvp, execvpe.
+
+2020-12-26  Bruno Haible  <bruno@clisp.org>
+
 	stack: Fix typo in comments.
 	* lib/stack.h: Fix typo in comments.
 
diff --git a/lib/unistd.in.h b/lib/unistd.in.h
index 7517e3b..d43556a 100644
--- a/lib/unistd.in.h
+++ b/lib/unistd.in.h
@@ -615,7 +615,26 @@ _GL_WARN_ON_USE (euidaccess, "euidaccess is unportable - "
 #endif
 
 
-#if @GNULIB_MDA_EXECL@
+#if @GNULIB_EXECL@
+# if @REPLACE_EXECL@
+#  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+#   undef execl
+#   define execl rpl_execl
+#  endif
+_GL_FUNCDECL_RPL (execl, int, (const char *program, const char *arg, ...)
+                              _GL_ARG_NONNULL ((1)));
+_GL_CXXALIAS_RPL (execl, int, (const char *program, const char *arg, ...));
+# else
+_GL_CXXALIAS_SYS (execl, int, (const char *program, const char *arg, ...));
+# endif
+_GL_CXXALIASWARN (execl);
+#elif defined GNULIB_POSIXCHECK
+# undef execl
+# if HAVE_RAW_DECL_EXECL
+_GL_WARN_ON_USE (execl, "execl behaves very differently on mingw - "
+                 "use gnulib module execl for portability");
+# endif
+#elif @GNULIB_MDA_EXECL@
 /* On native Windows, map 'execl' to '_execl', so that -loldnames is not
    required.  In C++ with GNULIB_NAMESPACE, avoid differences between
    platforms by defining GNULIB_NAMESPACE::execl always.  */
@@ -631,7 +650,26 @@ _GL_CXXALIAS_SYS (execl, int, (const char *program, const char *arg, ...));
 _GL_CXXALIASWARN (execl);
 #endif
 
-#if @GNULIB_MDA_EXECLE@
+#if @GNULIB_EXECLE@
+# if @REPLACE_EXECLE@
+#  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+#   undef execle
+#   define execle rpl_execle
+#  endif
+_GL_FUNCDECL_RPL (execle, int, (const char *program, const char *arg, ...)
+                               _GL_ARG_NONNULL ((1)));
+_GL_CXXALIAS_RPL (execle, int, (const char *program, const char *arg, ...));
+# else
+_GL_CXXALIAS_SYS (execle, int, (const char *program, const char *arg, ...));
+# endif
+_GL_CXXALIASWARN (execle);
+#elif defined GNULIB_POSIXCHECK
+# undef execle
+# if HAVE_RAW_DECL_EXECLE
+_GL_WARN_ON_USE (execle, "execle behaves very differently on mingw - "
+                 "use gnulib module execle for portability");
+# endif
+#elif @GNULIB_MDA_EXECLE@
 /* On native Windows, map 'execle' to '_execle', so that -loldnames is not
    required.  In C++ with GNULIB_NAMESPACE, avoid differences between
    platforms by defining GNULIB_NAMESPACE::execle always.  */
@@ -640,14 +678,34 @@ _GL_CXXALIASWARN (execl);
 #   undef execle
 #   define execle _execle
 #  endif
-_GL_CXXALIAS_MDA (execle, intptr_t, (const char *program, const char *arg, ...));
+_GL_CXXALIAS_MDA (execle, intptr_t,
+                  (const char *program, const char *arg, ...));
 # else
 _GL_CXXALIAS_SYS (execle, int, (const char *program, const char *arg, ...));
 # endif
 _GL_CXXALIASWARN (execle);
 #endif
 
-#if @GNULIB_MDA_EXECLP@
+#if @GNULIB_EXECLP@
+# if @REPLACE_EXECLP@
+#  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+#   undef execlp
+#   define execlp rpl_execlp
+#  endif
+_GL_FUNCDECL_RPL (execlp, int, (const char *program, const char *arg, ...)
+                               _GL_ARG_NONNULL ((1)));
+_GL_CXXALIAS_RPL (execlp, int, (const char *program, const char *arg, ...));
+# else
+_GL_CXXALIAS_SYS (execlp, int, (const char *program, const char *arg, ...));
+# endif
+_GL_CXXALIASWARN (execlp);
+#elif defined GNULIB_POSIXCHECK
+# undef execlp
+# if HAVE_RAW_DECL_EXECLP
+_GL_WARN_ON_USE (execlp, "execlp behaves very differently on mingw - "
+                 "use gnulib module execlp for portability");
+# endif
+#elif @GNULIB_MDA_EXECLP@
 /* On native Windows, map 'execlp' to '_execlp', so that -loldnames is not
    required.  In C++ with GNULIB_NAMESPACE, avoid differences between
    platforms by defining GNULIB_NAMESPACE::execlp always.  */
@@ -656,7 +714,8 @@ _GL_CXXALIASWARN (execle);
 #   undef execlp
 #   define execlp _execlp
 #  endif
-_GL_CXXALIAS_MDA (execlp, intptr_t, (const char *program, const char *arg, ...));
+_GL_CXXALIAS_MDA (execlp, intptr_t,
+                  (const char *program, const char *arg, ...));
 # else
 _GL_CXXALIAS_SYS (execlp, int, (const char *program, const char *arg, ...));
 # endif
@@ -664,7 +723,26 @@ _GL_CXXALIASWARN (execlp);
 #endif
 
 
-#if @GNULIB_MDA_EXECV@
+#if @GNULIB_EXECV@
+# if @REPLACE_EXECV@
+#  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+#   undef execv
+#   define execv rpl_execv
+#  endif
+_GL_FUNCDECL_RPL (execv, int, (const char *program, char * const *argv)
+                              _GL_ARG_NONNULL ((1, 2)));
+_GL_CXXALIAS_RPL (execv, int, (const char *program, char * const *argv));
+# else
+_GL_CXXALIAS_SYS (execv, int, (const char *program, char * const *argv));
+# endif
+_GL_CXXALIASWARN (execv);
+#elif defined GNULIB_POSIXCHECK
+# undef execv
+# if HAVE_RAW_DECL_EXECV
+_GL_WARN_ON_USE (execv, "execv behaves very differently on mingw - "
+                 "use gnulib module execv for portability");
+# endif
+#elif @GNULIB_MDA_EXECV@
 /* On native Windows, map 'execv' to '_execv', so that -loldnames is not
    required.  In C++ with GNULIB_NAMESPACE, avoid differences between
    platforms by defining GNULIB_NAMESPACE::execv always.  */
@@ -673,15 +751,37 @@ _GL_CXXALIASWARN (execlp);
 #   undef execv
 #   define execv _execv
 #  endif
-_GL_CXXALIAS_MDA (execv, intptr_t,
-                  (const char *program, const char * const *argv));
+_GL_CXXALIAS_MDA_CAST (execv, intptr_t,
+                       (const char *program, char * const *argv));
 # else
 _GL_CXXALIAS_SYS (execv, int, (const char *program, char * const *argv));
 # endif
 _GL_CXXALIASWARN (execv);
 #endif
 
-#if @GNULIB_MDA_EXECVE@
+#if @GNULIB_EXECVE@
+# if @REPLACE_EXECVE@
+#  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+#   undef execve
+#   define execve rpl_execve
+#  endif
+_GL_FUNCDECL_RPL (execve, int,
+                  (const char *program, char * const *argv, char * const *env)
+                  _GL_ARG_NONNULL ((1, 2)));
+_GL_CXXALIAS_RPL (execve, int,
+                  (const char *program, char * const *argv, char * const *env));
+# else
+_GL_CXXALIAS_SYS (execve, int,
+                  (const char *program, char * const *argv, char * const *env));
+# endif
+_GL_CXXALIASWARN (execve);
+#elif defined GNULIB_POSIXCHECK
+# undef execve
+# if HAVE_RAW_DECL_EXECVE
+_GL_WARN_ON_USE (execve, "execve behaves very differently on mingw - "
+                 "use gnulib module execve for portability");
+# endif
+#elif @GNULIB_MDA_EXECVE@
 /* On native Windows, map 'execve' to '_execve', so that -loldnames is not
    required.  In C++ with GNULIB_NAMESPACE, avoid differences between
    platforms by defining GNULIB_NAMESPACE::execve always.  */
@@ -690,9 +790,9 @@ _GL_CXXALIASWARN (execv);
 #   undef execve
 #   define execve _execve
 #  endif
-_GL_CXXALIAS_MDA (execve, intptr_t,
-                  (const char *program, const char * const *argv,
-                   const char * const *env));
+_GL_CXXALIAS_MDA_CAST (execve, intptr_t,
+                       (const char *program, char * const *argv,
+                        char * const *env));
 # else
 _GL_CXXALIAS_SYS (execve, int,
                   (const char *program, char * const *argv, char * const *env));
@@ -700,7 +800,26 @@ _GL_CXXALIAS_SYS (execve, int,
 _GL_CXXALIASWARN (execve);
 #endif
 
-#if @GNULIB_MDA_EXECVP@
+#if @GNULIB_EXECVP@
+# if @REPLACE_EXECVP@
+#  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+#   undef execvp
+#   define execvp rpl_execvp
+#  endif
+_GL_FUNCDECL_RPL (execvp, int, (const char *program, char * const *argv)
+                               _GL_ARG_NONNULL ((1, 2)));
+_GL_CXXALIAS_RPL (execvp, int, (const char *program, char * const *argv));
+# else
+_GL_CXXALIAS_SYS (execvp, int, (const char *program, char * const *argv));
+# endif
+_GL_CXXALIASWARN (execvp);
+#elif defined GNULIB_POSIXCHECK
+# undef execvp
+# if HAVE_RAW_DECL_EXECVP
+_GL_WARN_ON_USE (execvp, "execvp behaves very differently on mingw - "
+                 "use gnulib module execvp for portability");
+# endif
+#elif @GNULIB_MDA_EXECVP@
 /* On native Windows, map 'execvp' to '_execvp', so that -loldnames is not
    required.  In C++ with GNULIB_NAMESPACE, avoid differences between
    platforms by defining GNULIB_NAMESPACE::execvp always.  */
@@ -709,15 +828,42 @@ _GL_CXXALIASWARN (execve);
 #   undef execvp
 #   define execvp _execvp
 #  endif
-_GL_CXXALIAS_MDA (execvp, intptr_t,
-                  (const char *program, const char * const *argv));
+_GL_CXXALIAS_MDA_CAST (execvp, intptr_t,
+                       (const char *program, char * const *argv));
 # else
 _GL_CXXALIAS_SYS (execvp, int, (const char *program, char * const *argv));
 # endif
 _GL_CXXALIASWARN (execvp);
 #endif
 
-#if @GNULIB_MDA_EXECVPE@
+#if @GNULIB_EXECVPE@
+# if @REPLACE_EXECVPE@
+#  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+#   undef execvpe
+#   define execvpe rpl_execvpe
+#  endif
+_GL_FUNCDECL_RPL (execvpe, int,
+                  (const char *program, char * const *argv, char * const *env)
+                  _GL_ARG_NONNULL ((1, 2)));
+_GL_CXXALIAS_RPL (execvpe, int,
+                  (const char *program, char * const *argv, char * const *env));
+# else
+#  if !@HAVE_DECL_EXECVPE@
+_GL_FUNCDECL_SYS (execvpe, int,
+                  (const char *program, char * const *argv, char * const *env)
+                  _GL_ARG_NONNULL ((1, 2)));
+#  endif
+_GL_CXXALIAS_SYS (execvpe, int,
+                  (const char *program, char * const *argv, char * const *env));
+# endif
+_GL_CXXALIASWARN (execvpe);
+#elif defined GNULIB_POSIXCHECK
+# undef execvpe
+# if HAVE_RAW_DECL_EXECVPE
+_GL_WARN_ON_USE (execvpe, "execvpe behaves very differently on mingw - "
+                 "use gnulib module execvpe for portability");
+# endif
+#elif @GNULIB_MDA_EXECVPE@
 /* On native Windows, map 'execvpe' to '_execvpe', so that -loldnames is not
    required.  In C++ with GNULIB_NAMESPACE, avoid differences between
    platforms by defining GNULIB_NAMESPACE::execvpe on all platforms that have
@@ -727,16 +873,19 @@ _GL_CXXALIASWARN (execvp);
 #   undef execvpe
 #   define execvpe _execvpe
 #  endif
-_GL_CXXALIAS_MDA (execvpe, intptr_t,
-                  (const char *program, const char * const *argv,
-                   const char * const *env));
-# else
-#  if @HAVE_DECL_EXECVPE@
+_GL_CXXALIAS_MDA_CAST (execvpe, intptr_t,
+                       (const char *program, char * const *argv,
+                        char * const *env));
+# elif @HAVE_EXECVPE@
+#  if !@HAVE_DECL_EXECVPE@
+_GL_FUNCDECL_SYS (execvpe, int,
+                  (const char *program, char * const *argv, char * const *env)
+                  _GL_ARG_NONNULL ((1, 2)));
+#  endif
 _GL_CXXALIAS_SYS (execvpe, int,
                   (const char *program, char * const *argv, char * const *env));
-#  endif
 # endif
-# if (defined _WIN32 && !defined __CYGWIN__) || @HAVE_DECL_EXECVPE@
+# if (defined _WIN32 && !defined __CYGWIN__) || @HAVE_EXECVPE@
 _GL_CXXALIASWARN (execvpe);
 # endif
 #endif
diff --git a/m4/unistd_h.m4 b/m4/unistd_h.m4
index db96e2b..f0db575 100644
--- a/m4/unistd_h.m4
+++ b/m4/unistd_h.m4
@@ -1,4 +1,4 @@
-# unistd_h.m4 serial 84
+# unistd_h.m4 serial 85
 dnl Copyright (C) 2006-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,
@@ -42,6 +42,7 @@ AC_DEFUN([gl_UNISTD_H],
 # endif
 #endif
     ]], [access chdir chown copy_file_range dup dup2 dup3 environ euidaccess
+    execl execle execlp execv execve execvp execvpe
     faccessat fchdir
     fchownat fdatasync fsync ftruncate getcwd getdomainname getdtablesize
     getentropy getgroups gethostname getlogin getlogin_r getpagesize getpass
@@ -79,6 +80,13 @@ AC_DEFUN([gl_UNISTD_H_DEFAULTS],
   GNULIB_DUP3=0;                 AC_SUBST([GNULIB_DUP3])
   GNULIB_ENVIRON=0;              AC_SUBST([GNULIB_ENVIRON])
   GNULIB_EUIDACCESS=0;           AC_SUBST([GNULIB_EUIDACCESS])
+  GNULIB_EXECL=0;                AC_SUBST([GNULIB_EXECL])
+  GNULIB_EXECLE=0;               AC_SUBST([GNULIB_EXECLE])
+  GNULIB_EXECLP=0;               AC_SUBST([GNULIB_EXECLP])
+  GNULIB_EXECV=0;                AC_SUBST([GNULIB_EXECV])
+  GNULIB_EXECVE=0;               AC_SUBST([GNULIB_EXECVE])
+  GNULIB_EXECVP=0;               AC_SUBST([GNULIB_EXECVP])
+  GNULIB_EXECVPE=0;              AC_SUBST([GNULIB_EXECVPE])
   GNULIB_FACCESSAT=0;            AC_SUBST([GNULIB_FACCESSAT])
   GNULIB_FCHDIR=0;               AC_SUBST([GNULIB_FCHDIR])
   GNULIB_FCHOWNAT=0;             AC_SUBST([GNULIB_FCHOWNAT])
@@ -150,6 +158,7 @@ AC_DEFUN([gl_UNISTD_H_DEFAULTS],
   HAVE_COPY_FILE_RANGE=1; AC_SUBST([HAVE_COPY_FILE_RANGE])
   HAVE_DUP3=1;            AC_SUBST([HAVE_DUP3])
   HAVE_EUIDACCESS=1;      AC_SUBST([HAVE_EUIDACCESS])
+  HAVE_EXECVPE=1;         AC_SUBST([HAVE_EXECVPE])
   HAVE_FACCESSAT=1;       AC_SUBST([HAVE_FACCESSAT])
   HAVE_FCHDIR=1;          AC_SUBST([HAVE_FCHDIR])
   HAVE_FCHOWNAT=1;        AC_SUBST([HAVE_FCHOWNAT])
@@ -198,6 +207,13 @@ AC_DEFUN([gl_UNISTD_H_DEFAULTS],
   REPLACE_CLOSE=0;        AC_SUBST([REPLACE_CLOSE])
   REPLACE_DUP=0;          AC_SUBST([REPLACE_DUP])
   REPLACE_DUP2=0;         AC_SUBST([REPLACE_DUP2])
+  REPLACE_EXECL=0;        AC_SUBST([REPLACE_EXECL])
+  REPLACE_EXECLE=0;       AC_SUBST([REPLACE_EXECLE])
+  REPLACE_EXECLP=0;       AC_SUBST([REPLACE_EXECLP])
+  REPLACE_EXECV=0;        AC_SUBST([REPLACE_EXECV])
+  REPLACE_EXECVE=0;       AC_SUBST([REPLACE_EXECVE])
+  REPLACE_EXECVP=0;       AC_SUBST([REPLACE_EXECVP])
+  REPLACE_EXECVPE=0;      AC_SUBST([REPLACE_EXECVPE])
   REPLACE_FACCESSAT=0;    AC_SUBST([REPLACE_FACCESSAT])
   REPLACE_FCHOWNAT=0;     AC_SUBST([REPLACE_FCHOWNAT])
   REPLACE_FTRUNCATE=0;    AC_SUBST([REPLACE_FTRUNCATE])
diff --git a/modules/unistd b/modules/unistd
index 27a4b67..442678b 100644
--- a/modules/unistd
+++ b/modules/unistd
@@ -47,6 +47,13 @@ unistd.h: unistd.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H
 	      -e 's/@''GNULIB_DUP3''@/$(GNULIB_DUP3)/g' \
 	      -e 's/@''GNULIB_ENVIRON''@/$(GNULIB_ENVIRON)/g' \
 	      -e 's/@''GNULIB_EUIDACCESS''@/$(GNULIB_EUIDACCESS)/g' \
+	      -e 's/@''GNULIB_EXECL''@/$(GNULIB_EXECL)/g' \
+	      -e 's/@''GNULIB_EXECLE''@/$(GNULIB_EXECLE)/g' \
+	      -e 's/@''GNULIB_EXECLP''@/$(GNULIB_EXECLP)/g' \
+	      -e 's/@''GNULIB_EXECV''@/$(GNULIB_EXECV)/g' \
+	      -e 's/@''GNULIB_EXECVE''@/$(GNULIB_EXECVE)/g' \
+	      -e 's/@''GNULIB_EXECVP''@/$(GNULIB_EXECVP)/g' \
+	      -e 's/@''GNULIB_EXECVPE''@/$(GNULIB_EXECVPE)/g' \
 	      -e 's/@''GNULIB_FACCESSAT''@/$(GNULIB_FACCESSAT)/g' \
 	      -e 's/@''GNULIB_FCHDIR''@/$(GNULIB_FCHDIR)/g' \
 	      -e 's/@''GNULIB_FCHOWNAT''@/$(GNULIB_FCHOWNAT)/g' \
@@ -118,6 +125,7 @@ unistd.h: unistd.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H
 	      -e 's|@''HAVE_COPY_FILE_RANGE''@|$(HAVE_COPY_FILE_RANGE)|g' \
 	      -e 's|@''HAVE_DUP3''@|$(HAVE_DUP3)|g' \
 	      -e 's|@''HAVE_EUIDACCESS''@|$(HAVE_EUIDACCESS)|g' \
+	      -e 's|@''HAVE_EXECVPE''@|$(HAVE_EXECVPE)|g' \
 	      -e 's|@''HAVE_FACCESSAT''@|$(HAVE_FACCESSAT)|g' \
 	      -e 's|@''HAVE_FCHDIR''@|$(HAVE_FCHDIR)|g' \
 	      -e 's|@''HAVE_FCHOWNAT''@|$(HAVE_FCHOWNAT)|g' \
@@ -166,6 +174,13 @@ unistd.h: unistd.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H
 	      -e 's|@''REPLACE_CLOSE''@|$(REPLACE_CLOSE)|g' \
 	      -e 's|@''REPLACE_DUP''@|$(REPLACE_DUP)|g' \
 	      -e 's|@''REPLACE_DUP2''@|$(REPLACE_DUP2)|g' \
+	      -e 's|@''REPLACE_EXECL''@|$(REPLACE_EXECL)|g' \
+	      -e 's|@''REPLACE_EXECLE''@|$(REPLACE_EXECLE)|g' \
+	      -e 's|@''REPLACE_EXECLP''@|$(REPLACE_EXECLP)|g' \
+	      -e 's|@''REPLACE_EXECV''@|$(REPLACE_EXECV)|g' \
+	      -e 's|@''REPLACE_EXECVE''@|$(REPLACE_EXECVE)|g' \
+	      -e 's|@''REPLACE_EXECVP''@|$(REPLACE_EXECVP)|g' \
+	      -e 's|@''REPLACE_EXECVPE''@|$(REPLACE_EXECVPE)|g' \
 	      -e 's|@''REPLACE_FACCESSAT''@|$(REPLACE_FACCESSAT)|g' \
 	      -e 's|@''REPLACE_FCHOWNAT''@|$(REPLACE_FCHOWNAT)|g' \
 	      -e 's|@''REPLACE_FTRUNCATE''@|$(REPLACE_FTRUNCATE)|g' \
diff --git a/tests/test-unistd-c++.cc b/tests/test-unistd-c++.cc
index 6d4c8fb..d866091 100644
--- a/tests/test-unistd-c++.cc
+++ b/tests/test-unistd-c++.cc
@@ -52,6 +52,41 @@ SIGNATURE_CHECK (GNULIB_NAMESPACE::dup2, int, (int, int));
 SIGNATURE_CHECK (GNULIB_NAMESPACE::dup3, int, (int, int, int));
 #endif
 
+#if GNULIB_TEST_EXECL
+SIGNATURE_CHECK (GNULIB_NAMESPACE::execl, int,
+                 (const char *, const char *, ...));
+#endif
+
+#if GNULIB_TEST_EXECLE
+SIGNATURE_CHECK (GNULIB_NAMESPACE::execle, int,
+                 (const char *, const char *, ...));
+#endif
+
+#if GNULIB_TEST_EXECLP
+SIGNATURE_CHECK (GNULIB_NAMESPACE::execlp, int,
+                 (const char *, const char *, ...));
+#endif
+
+#if GNULIB_TEST_EXECV
+SIGNATURE_CHECK (GNULIB_NAMESPACE::execv, int,
+                 (const char *, char * const *));
+#endif
+
+#if GNULIB_TEST_EXECVE
+SIGNATURE_CHECK (GNULIB_NAMESPACE::execve, int,
+                 (const char *, char * const *, char * const *));
+#endif
+
+#if GNULIB_TEST_EXECVP
+SIGNATURE_CHECK (GNULIB_NAMESPACE::execvp, int,
+                 (const char *, char * const *));
+#endif
+
+#if GNULIB_TEST_EXECVPE
+SIGNATURE_CHECK (GNULIB_NAMESPACE::execvpe, int,
+                 (const char *, char * const *, char * const *));
+#endif
+
 #if GNULIB_TEST_EUIDACCESS
 SIGNATURE_CHECK (GNULIB_NAMESPACE::euidaccess, int, (const char *, int));
 #endif
-- 
2.7.4


[-- Attachment #3: 0002-execve-New-module.patch --]
[-- Type: text/x-patch, Size: 6795 bytes --]

From e8f57867dc5c05e7354576df19f1151ae9cb9fbb Mon Sep 17 00:00:00 2001
From: Bruno Haible <bruno@clisp.org>
Date: Sat, 26 Dec 2020 14:13:03 +0100
Subject: [PATCH 02/15] execve: New module.

* lib/execve.c: New file.
* m4/execve.m4: New file.
* modules/execve: New file.
* doc/posix-functions/execve.texi: Mention more Windows problems and the
new module.
---
 ChangeLog                       |  7 ++++
 doc/posix-functions/execve.texi | 21 ++++++++---
 lib/execve.c                    | 79 +++++++++++++++++++++++++++++++++++++++++
 m4/execve.m4                    | 15 ++++++++
 modules/execve                  | 31 ++++++++++++++++
 5 files changed, 148 insertions(+), 5 deletions(-)
 create mode 100644 lib/execve.c
 create mode 100644 m4/execve.m4
 create mode 100644 modules/execve

diff --git a/ChangeLog b/ChangeLog
index 459df8e..750f67b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,12 @@
 2020-12-26  Bruno Haible  <bruno@clisp.org>
 
+	execve: New module.
+	* lib/execve.c: New file.
+	* m4/execve.m4: New file.
+	* modules/execve: New file.
+	* doc/posix-functions/execve.texi: Mention more Windows problems and the
+	new module.
+
 	execve, execvpe, execvp, execv, execl, execle, execlp: Prepare modules.
 	* lib/unistd.in.h (execl, execle, execlp, execv, execve, execvp,
 	execvpe): Add declarations for the new modules.
diff --git a/doc/posix-functions/execve.texi b/doc/posix-functions/execve.texi
index a07e3b5..9b4196c 100644
--- a/doc/posix-functions/execve.texi
+++ b/doc/posix-functions/execve.texi
@@ -4,19 +4,30 @@
 
 POSIX specification:@* @url{https://pubs.opengroup.org/onlinepubs/9699919799/functions/execve.html}
 
-Gnulib module: ---
+Gnulib module: execve
 
 Portability problems fixed by Gnulib:
 @itemize
+@item
+On Windows platforms (excluding Cygwin), this function does not pass
+command-line arguments correctly if they contain space, tab, backslash,
+or double-quote characters.
+@item
+On Windows platforms (excluding Cygwin), this function spawns an asynchronous
+child process and then exits the current process immediately.  As a
+consequence, the parent of the current process 1. may incorrectly proceed
+as if its child had exited, and 2. will never see the child's exit status.
+@item
+On Windows platforms (excluding Cygwin), the return type of this function is
+@code{intptr_t}, not @code{int}.
 @end itemize
 
+Note: The Gnulib replacement for this function is not async-safe, that is,
+it must not be invoked from a signal handler.
+
 Portability problems not fixed by Gnulib:
 @itemize
 @item
 On some platforms, a script without executable permission is still run:
 Cygwin 1.5.x.
-@item
-On Windows platforms (excluding Cygwin), this function operates by spawning
-and then by exiting the current process, which means the current
-process's parent may incorrectly proceed as if its child had exited.
 @end itemize
diff --git a/lib/execve.c b/lib/execve.c
new file mode 100644
index 0000000..d5987c9
--- /dev/null
+++ b/lib/execve.c
@@ -0,0 +1,79 @@
+/* execve() function: Execute a program, replacing the current process.
+   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 of the License, 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/>.  */
+
+/* Written by Bruno Haible <bruno@clisp.org>, 2020.  */
+
+/* Don't use __attribute__ __nonnull__ in this compilation unit.  Otherwise gcc
+   may optimize away the program == NULL and argv == NULL tests below.  */
+#define _GL_ARG_NONNULL(params)
+
+#include <config.h>
+
+/* Specification.  */
+#include <unistd.h>
+
+#if defined _WIN32 && !defined __CYGWIN__
+
+# include <errno.h>
+# include <stdio.h>
+# include <spawn.h>
+
+# include <sys/types.h>
+# include <sys/wait.h>
+
+int
+execve (const char *program, char * const *argv, char * const *env)
+{
+  if (program == NULL
+      || argv == NULL
+      /* The callee is not expecting a NULL argv[0].  */
+      || argv[0] == NULL
+      || env == NULL)
+    {
+      errno = EINVAL;
+      return -1;
+    }
+
+  pid_t child;
+  int err = posix_spawn (&child, program, NULL, NULL, argv, env);
+  if (err == 0)
+    {
+      /* Close all file descriptors, so that
+         - for opened files, the child may close and unlink() the file,
+         - for pipe handles, the pipe's reader or writer does not get stuck.
+         Ideally we would also suspend all other threads and close all other
+         HANDLEs (not associated with file descriptors) and SOCKETs, but we
+         can't do so since we have no way to enumerate them.  */
+      {
+        unsigned int fdmax = _getmaxstdio ();
+        unsigned int fd;
+        for (fd = 0; fd < fdmax; fd++)
+          close (fd);
+      }
+
+      /* Wait until the child process is terminated.  */
+      int status = 127;
+      waitpid (child, &status, 0);
+      int exitcode = status;
+
+      /* Pass its exit code to the parent process.  */
+      _exit (exitcode);
+    }
+  errno = err;
+  return -1;
+}
+
+#endif
diff --git a/m4/execve.m4 b/m4/execve.m4
new file mode 100644
index 0000000..9511da4
--- /dev/null
+++ b/m4/execve.m4
@@ -0,0 +1,15 @@
+# execve.m4 serial 1
+dnl Copyright (C) 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,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_FUNC_EXECVE],
+[
+  AC_REQUIRE([gl_UNISTD_H_DEFAULTS])
+  AC_REQUIRE([AC_CANONICAL_HOST])
+
+  case "$host_os" in
+    mingw*) REPLACE_EXECVE=1 ;;
+  esac
+])
diff --git a/modules/execve b/modules/execve
new file mode 100644
index 0000000..ea381a2
--- /dev/null
+++ b/modules/execve
@@ -0,0 +1,31 @@
+Description:
+execve() function: Execute a program, replacing the current process.
+
+Files:
+lib/execve.c
+m4/execve.m4
+
+Depends-on:
+unistd
+posix_spawn     [test $REPLACE_EXECVE = 1]
+close           [test $REPLACE_EXECVE = 1]
+sys_wait        [test $REPLACE_EXECVE = 1]
+waitpid         [test $REPLACE_EXECVE = 1]
+
+configure.ac:
+gl_FUNC_EXECVE
+if test $REPLACE_EXECVE = 1; then
+  AC_LIBOBJ([execve])
+fi
+gl_UNISTD_MODULE_INDICATOR([execve])
+
+Makefile.am:
+
+Include:
+<unistd.h>
+
+License:
+LGPLv2+
+
+Maintainer:
+all
-- 
2.7.4


[-- Attachment #4: 0003-execve-Add-tests.patch --]
[-- Type: text/x-patch, Size: 6303 bytes --]

From c24b5cc4a8ff7e858ad7bc019a6e112a292fe468 Mon Sep 17 00:00:00 2001
From: Bruno Haible <bruno@clisp.org>
Date: Sat, 26 Dec 2020 14:19:29 +0100
Subject: [PATCH 03/15] execve: Add tests.

* tests/test-exec-child.c: New file.
* tests/test-execve-main.c: New file.
* tests/test-execve.sh: New file.
* modules/execve-tests: New file.
---
 ChangeLog                |  6 ++++++
 modules/execve-tests     | 11 ++++++++++
 tests/test-exec-child.c  | 41 +++++++++++++++++++++++++++++++++++++
 tests/test-execve-main.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++
 tests/test-execve.sh     | 48 +++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 159 insertions(+)
 create mode 100644 modules/execve-tests
 create mode 100644 tests/test-exec-child.c
 create mode 100644 tests/test-execve-main.c
 create mode 100755 tests/test-execve.sh

diff --git a/ChangeLog b/ChangeLog
index 750f67b..f6795fb 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
 2020-12-26  Bruno Haible  <bruno@clisp.org>
 
+	execve: Add tests.
+	* tests/test-exec-child.c: New file.
+	* tests/test-execve-main.c: New file.
+	* tests/test-execve.sh: New file.
+	* modules/execve-tests: New file.
+
 	execve: New module.
 	* lib/execve.c: New file.
 	* m4/execve.m4: New file.
diff --git a/modules/execve-tests b/modules/execve-tests
new file mode 100644
index 0000000..3077c5f
--- /dev/null
+++ b/modules/execve-tests
@@ -0,0 +1,11 @@
+Files:
+tests/test-execve.sh
+tests/test-execve-main.c
+tests/test-exec-child.c
+tests/signature.h
+
+Depends-on:
+
+Makefile.am:
+TESTS += test-execve.sh
+check_PROGRAMS += test-execve-main test-exec-child
diff --git a/tests/test-exec-child.c b/tests/test-exec-child.c
new file mode 100644
index 0000000..bbcf727
--- /dev/null
+++ b/tests/test-exec-child.c
@@ -0,0 +1,41 @@
+/* Callee program for the tests of the exec*() functions.
+   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 <stdio.h>
+#include <stdlib.h>
+
+/* Do not use any gnulib replacements, since this program should
+   link against as few libraries as possible.  */
+#undef printf
+
+int
+main (int argc, char* argv[])
+{
+  /* Print the arguments.  */
+  int i;
+  printf ("argc = %d\n", argc);
+  for (i = 1; i < argc; i++)
+    printf ("argv[%d] = |%s|\n", i, argv[i]);
+
+  /* Print a particular environment variable.  */
+  const char *var = "Hommingberg";
+  if (getenv (var) != NULL)
+    printf ("%s = |%s|\n", var, getenv (var));
+
+  return 49;
+}
diff --git a/tests/test-execve-main.c b/tests/test-execve-main.c
new file mode 100644
index 0000000..3667dd2
--- /dev/null
+++ b/tests/test-execve-main.c
@@ -0,0 +1,53 @@
+/* Test of execve().
+   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/>.  */
+
+/* Written by Bruno Haible <bruno@clisp.org>, 2020.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include <unistd.h>
+
+#include "signature.h"
+SIGNATURE_CHECK (execve, int, (const char *, char * const *, char * const *));
+
+#include <stdio.h>
+
+int
+main ()
+{
+  const char *progname = "./test-exec-child";
+  const char *env[3] = { "PATH=.", "Hommingberg=Gepardenforelle", NULL };
+  const char *argv[12] =
+    {
+      progname,
+      "abc def",
+      "abc\"def\"ghi",
+      "xyz\"",
+      "abc\\def\\ghi",
+      "xyz\\",
+      "???",
+      "***",
+      "",
+      "foo",
+      "",
+      NULL
+    };
+  execve (progname, (char * const *) argv, (char * const *) env);
+
+  perror ("execve");
+  return 1;
+}
diff --git a/tests/test-execve.sh b/tests/test-execve.sh
new file mode 100755
index 0000000..3d7ac1c
--- /dev/null
+++ b/tests/test-execve.sh
@@ -0,0 +1,48 @@
+#!/bin/sh
+
+# Test of execve().
+#
+# 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 of the License, 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/>.  */
+#
+# Written by Bruno Haible <bruno@clisp.org>, 2020.
+
+${CHECKER} ./test-execve-main${EXEEXT} > test-execve.tmp
+result=$?
+test $result = 49 || exit 1
+LC_ALL=C tr -d '\r' < test-execve.tmp > test-execve.out || exit 1
+
+cat > test-execve.ok <<\EOF
+argc = 11
+argv[1] = |abc def|
+argv[2] = |abc"def"ghi|
+argv[3] = |xyz"|
+argv[4] = |abc\def\ghi|
+argv[5] = |xyz\|
+argv[6] = |???|
+argv[7] = |***|
+argv[8] = ||
+argv[9] = |foo|
+argv[10] = ||
+Hommingberg = |Gepardenforelle|
+EOF
+
+: ${DIFF=diff}
+${DIFF} test-execve.ok test-execve.out
+result=$?
+
+rm -f test-execve.tmp test-execve.out test-execve.ok
+
+exit $result
-- 
2.7.4


[-- Attachment #5: 0004-execvpe-New-module.patch --]
[-- Type: text/x-patch, Size: 6303 bytes --]

From a50484eb14bf2c2a8dc420ba2ad037fd85f9c739 Mon Sep 17 00:00:00 2001
From: Bruno Haible <bruno@clisp.org>
Date: Sat, 26 Dec 2020 14:23:10 +0100
Subject: [PATCH 04/15] execvpe: New module.

* lib/execvpe.c: New file.
* m4/execvpe.m4: New file.
* modules/execvpe: New file.
* doc/glibc-functions/execvpe.texi: Mention the Windows problems and the
new module.
---
 ChangeLog                        |  7 +++++
 doc/glibc-functions/execvpe.texi | 22 ++++++++++----
 lib/execvpe.c                    | 62 ++++++++++++++++++++++++++++++++++++++++
 m4/execvpe.m4                    | 24 ++++++++++++++++
 modules/execvpe                  | 30 +++++++++++++++++++
 5 files changed, 140 insertions(+), 5 deletions(-)
 create mode 100644 lib/execvpe.c
 create mode 100644 m4/execvpe.m4
 create mode 100644 modules/execvpe

diff --git a/ChangeLog b/ChangeLog
index f6795fb..7a9e5fb 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,12 @@
 2020-12-26  Bruno Haible  <bruno@clisp.org>
 
+	execvpe: New module.
+	* lib/execvpe.c: New file.
+	* m4/execvpe.m4: New file.
+	* modules/execvpe: New file.
+	* doc/glibc-functions/execvpe.texi: Mention the Windows problems and the
+	new module.
+
 	execve: Add tests.
 	* tests/test-exec-child.c: New file.
 	* tests/test-execve-main.c: New file.
diff --git a/doc/glibc-functions/execvpe.texi b/doc/glibc-functions/execvpe.texi
index 814b160..04ac54a 100644
--- a/doc/glibc-functions/execvpe.texi
+++ b/doc/glibc-functions/execvpe.texi
@@ -4,18 +4,30 @@
 
 Documentation:@* @uref{https://www.kernel.org/doc/man-pages/online/pages/man3/execvpe.3.html,,man execvpe}
 
-Gnulib module: ---
+Gnulib module: execvpe
 
 Portability problems fixed by Gnulib:
 @itemize
-@end itemize
-
-Portability problems not fixed by Gnulib:
-@itemize
 @item
 This function is missing on many non-glibc platforms:
 glibc 2.10, Mac OS X 10.13, FreeBSD 6.0, NetBSD 7.1, OpenBSD 3.8, Minix 3.1.8, AIX 5.1, HP-UX 11, IRIX 6.5, Solaris 11.3, Cygwin 1.5.x, mingw, Android 4.4.
 @item
 This function is not declared on some platforms:
 AIX 7.1.
+@item
+On Windows platforms (excluding Cygwin), this function does not pass
+command-line arguments correctly if they contain space, tab, backslash,
+or double-quote characters.
+@item
+On Windows platforms (excluding Cygwin), this function spawns an asynchronous
+child process and then exits the current process immediately.  As a
+consequence, the parent of the current process 1. may incorrectly proceed
+as if its child had exited, and 2. will never see the child's exit status.
+@item
+On Windows platforms (excluding Cygwin), the return type of this function is
+@code{intptr_t}, not @code{int}.
+@end itemize
+
+Portability problems not fixed by Gnulib:
+@itemize
 @end itemize
diff --git a/lib/execvpe.c b/lib/execvpe.c
new file mode 100644
index 0000000..7bc369d
--- /dev/null
+++ b/lib/execvpe.c
@@ -0,0 +1,62 @@
+/* execvpe() function: Execute a program, replacing the current process.
+   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 of the License, 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/>.  */
+
+/* Written by Bruno Haible <bruno@clisp.org>, 2020.  */
+
+/* Don't use __attribute__ __nonnull__ in this compilation unit.  Otherwise gcc
+   may optimize away the program == NULL and argv == NULL tests below.  */
+#define _GL_ARG_NONNULL(params)
+
+#include <config.h>
+
+/* Specification.  */
+#include <unistd.h>
+
+#include <errno.h>
+#include <stdlib.h>
+
+#include "findprog.h"
+
+int
+execvpe (const char *program, char * const *argv, char * const *env)
+{
+  if (program == NULL
+      || argv == NULL
+      /* The callee is not expecting a NULL argv[0].  */
+      || argv[0] == NULL
+      || env == NULL)
+    {
+      errno = EINVAL;
+      return -1;
+    }
+
+  const char *resolved_progname =
+    find_in_given_path (program, getenv ("PATH"), NULL, true);
+  if (resolved_progname == NULL)
+    return -1;
+
+  /* Invoke execve.  */
+  execve (resolved_progname, argv, env);
+
+  /* If execve returned, it must have failed.  */
+  if (resolved_progname != program)
+    {
+      int saved_errno = errno;
+      free ((char *) resolved_progname);
+      errno = saved_errno;
+    }
+  return -1;
+}
diff --git a/m4/execvpe.m4 b/m4/execvpe.m4
new file mode 100644
index 0000000..bfce909
--- /dev/null
+++ b/m4/execvpe.m4
@@ -0,0 +1,24 @@
+# execvpe.m4 serial 1
+dnl Copyright (C) 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,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_FUNC_EXECVPE],
+[
+  AC_REQUIRE([gl_UNISTD_H_DEFAULTS])
+  AC_REQUIRE([AC_CANONICAL_HOST])
+
+  dnl Persuade glibc <unistd.h> to declare execvpe().
+  AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS])
+
+  case "$host_os" in
+    mingw*) REPLACE_EXECVPE=1 ;;
+    *)
+      AC_CHECK_FUNCS([execvpe])
+      if test $ac_cv_func_execvpe != yes; then
+        HAVE_EXECVPE=0
+      fi
+      ;;
+  esac
+])
diff --git a/modules/execvpe b/modules/execvpe
new file mode 100644
index 0000000..792a2c7
--- /dev/null
+++ b/modules/execvpe
@@ -0,0 +1,30 @@
+Description:
+execvpe() function: Execute a program, replacing the current process.
+
+Files:
+lib/execvpe.c
+m4/execvpe.m4
+
+Depends-on:
+unistd
+extensions
+findprog-in     [test $HAVE_EXECVPE = 0 || test $REPLACE_EXECVPE = 1]
+execve          [test $HAVE_EXECVPE = 0 || test $REPLACE_EXECVPE = 1]
+
+configure.ac:
+gl_FUNC_EXECVPE
+if test $HAVE_EXECVPE = 0 || test $REPLACE_EXECVPE = 1; then
+  AC_LIBOBJ([execvpe])
+fi
+gl_UNISTD_MODULE_INDICATOR([execvpe])
+
+Makefile.am:
+
+Include:
+<unistd.h>
+
+License:
+LGPLv2+
+
+Maintainer:
+all
-- 
2.7.4


[-- Attachment #6: 0005-execvpe-Add-tests.patch --]
[-- Type: text/x-patch, Size: 4844 bytes --]

From 7c170cbc17521f6eb0199e78fcd18d8dddbb12b4 Mon Sep 17 00:00:00 2001
From: Bruno Haible <bruno@clisp.org>
Date: Sat, 26 Dec 2020 14:25:06 +0100
Subject: [PATCH 05/15] execvpe: Add tests.

* tests/test-execvpe-main.c: New file.
* tests/test-execvpe.sh: New file.
* modules/execvpe-tests: New file.
---
 ChangeLog                 |  5 +++++
 modules/execvpe-tests     | 11 ++++++++++
 tests/test-execvpe-main.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++
 tests/test-execvpe.sh     | 51 +++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 120 insertions(+)
 create mode 100644 modules/execvpe-tests
 create mode 100644 tests/test-execvpe-main.c
 create mode 100755 tests/test-execvpe.sh

diff --git a/ChangeLog b/ChangeLog
index 7a9e5fb..1f9acd2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,10 @@
 2020-12-26  Bruno Haible  <bruno@clisp.org>
 
+	execvpe: Add tests.
+	* tests/test-execvpe-main.c: New file.
+	* tests/test-execvpe.sh: New file.
+	* modules/execvpe-tests: New file.
+
 	execvpe: New module.
 	* lib/execvpe.c: New file.
 	* m4/execvpe.m4: New file.
diff --git a/modules/execvpe-tests b/modules/execvpe-tests
new file mode 100644
index 0000000..911d1ca
--- /dev/null
+++ b/modules/execvpe-tests
@@ -0,0 +1,11 @@
+Files:
+tests/test-execvpe.sh
+tests/test-execvpe-main.c
+tests/test-exec-child.c
+tests/signature.h
+
+Depends-on:
+
+Makefile.am:
+TESTS += test-execvpe.sh
+check_PROGRAMS += test-execvpe-main test-exec-child
diff --git a/tests/test-execvpe-main.c b/tests/test-execvpe-main.c
new file mode 100644
index 0000000..0b7ebff
--- /dev/null
+++ b/tests/test-execvpe-main.c
@@ -0,0 +1,53 @@
+/* Test of execvpe().
+   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/>.  */
+
+/* Written by Bruno Haible <bruno@clisp.org>, 2020.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include <unistd.h>
+
+#include "signature.h"
+SIGNATURE_CHECK (execvpe, int, (const char *, char * const *, char * const *));
+
+#include <stdio.h>
+
+int
+main ()
+{
+  const char *progname = "test-exec-child";
+  const char *env[3] = { "PATH=.", "Hommingberg=Gepardenforelle", NULL };
+  const char *argv[12] =
+    {
+      progname,
+      "abc def",
+      "abc\"def\"ghi",
+      "xyz\"",
+      "abc\\def\\ghi",
+      "xyz\\",
+      "???",
+      "***",
+      "",
+      "foo",
+      "",
+      NULL
+    };
+  execvpe (progname, (char * const *) argv, (char * const *) env);
+
+  perror ("execvpe");
+  return 1;
+}
diff --git a/tests/test-execvpe.sh b/tests/test-execvpe.sh
new file mode 100755
index 0000000..62fb258
--- /dev/null
+++ b/tests/test-execvpe.sh
@@ -0,0 +1,51 @@
+#!/bin/sh
+
+# Test of execvpe().
+#
+# 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 of the License, 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/>.  */
+#
+# Written by Bruno Haible <bruno@clisp.org>, 2020.
+
+rm -rf test-execvpe-subdir
+mkdir test-execvpe-subdir
+
+(cd test-execvpe-subdir && PATH="..:$PATH" ${CHECKER} ../test-execvpe-main${EXEEXT}) > test-execvpe.tmp
+result=$?
+test $result = 49 || { rm -rf test-execvpe-subdir; exit 1; }
+LC_ALL=C tr -d '\r' < test-execvpe.tmp > test-execvpe.out || { rm -rf test-execvpe-subdir; exit 1; }
+
+cat > test-execvpe.ok <<\EOF
+argc = 11
+argv[1] = |abc def|
+argv[2] = |abc"def"ghi|
+argv[3] = |xyz"|
+argv[4] = |abc\def\ghi|
+argv[5] = |xyz\|
+argv[6] = |???|
+argv[7] = |***|
+argv[8] = ||
+argv[9] = |foo|
+argv[10] = ||
+Hommingberg = |Gepardenforelle|
+EOF
+
+: ${DIFF=diff}
+${DIFF} test-execvpe.ok test-execvpe.out
+result=$?
+
+rm -rf test-execvpe-subdir test-execvpe.tmp test-execvpe.out test-execvpe.ok
+
+exit $result
-- 
2.7.4


[-- Attachment #7: 0006-execvp-New-module.patch --]
[-- Type: text/x-patch, Size: 5596 bytes --]

From 0e3778b00c4e4705cccec9261ef36c66c400e1fe Mon Sep 17 00:00:00 2001
From: Bruno Haible <bruno@clisp.org>
Date: Sat, 26 Dec 2020 14:28:16 +0100
Subject: [PATCH 06/15] execvp: New module.

* lib/execvp.c: New file.
* m4/execvp.m4: New file.
* modules/execvp: New file.
* doc/posix-functions/execvp.texi: Mention more Windows problems and the
new module.
---
 ChangeLog                       |  7 +++++++
 doc/posix-functions/execvp.texi | 18 +++++++++++++-----
 lib/execvp.c                    | 35 +++++++++++++++++++++++++++++++++++
 m4/execvp.m4                    | 15 +++++++++++++++
 modules/execvp                  | 29 +++++++++++++++++++++++++++++
 5 files changed, 99 insertions(+), 5 deletions(-)
 create mode 100644 lib/execvp.c
 create mode 100644 m4/execvp.m4
 create mode 100644 modules/execvp

diff --git a/ChangeLog b/ChangeLog
index 1f9acd2..5d20495 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,12 @@
 2020-12-26  Bruno Haible  <bruno@clisp.org>
 
+	execvp: New module.
+	* lib/execvp.c: New file.
+	* m4/execvp.m4: New file.
+	* modules/execvp: New file.
+	* doc/posix-functions/execvp.texi: Mention more Windows problems and the
+	new module.
+
 	execvpe: Add tests.
 	* tests/test-execvpe-main.c: New file.
 	* tests/test-execvpe.sh: New file.
diff --git a/doc/posix-functions/execvp.texi b/doc/posix-functions/execvp.texi
index 24a3f06..0c242b2 100644
--- a/doc/posix-functions/execvp.texi
+++ b/doc/posix-functions/execvp.texi
@@ -4,10 +4,22 @@
 
 POSIX specification:@* @url{https://pubs.opengroup.org/onlinepubs/9699919799/functions/execvp.html}
 
-Gnulib module: ---
+Gnulib module: execvp
 
 Portability problems fixed by Gnulib:
 @itemize
+@item
+On Windows platforms (excluding Cygwin), this function does not pass
+command-line arguments correctly if they contain space, tab, backslash,
+or double-quote characters.
+@item
+On Windows platforms (excluding Cygwin), this function spawns an asynchronous
+child process and then exits the current process immediately.  As a
+consequence, the parent of the current process 1. may incorrectly proceed
+as if its child had exited, and 2. will never see the child's exit status.
+@item
+On Windows platforms (excluding Cygwin), the return type of this function is
+@code{intptr_t}, not @code{int}.
 @end itemize
 
 Portability problems not fixed by Gnulib:
@@ -15,8 +27,4 @@ Portability problems not fixed by Gnulib:
 @item
 On some platforms, a script without executable permission is still run:
 Cygwin 1.5.x.
-@item
-On Windows platforms (excluding Cygwin), this function operates by spawning
-and then by exiting the current process, which means the current
-process's parent may incorrectly proceed as if its child had exited.
 @end itemize
diff --git a/lib/execvp.c b/lib/execvp.c
new file mode 100644
index 0000000..db0fcb7
--- /dev/null
+++ b/lib/execvp.c
@@ -0,0 +1,35 @@
+/* execvp() function: Execute a program, replacing the current process.
+   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 of the License, 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/>.  */
+
+/* Written by Bruno Haible <bruno@clisp.org>, 2020.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include <unistd.h>
+
+int
+execvp (const char *program, char * const *argv)
+{
+  /* Pass the environment explicitly.  This is needed if the program has
+     modified the environment using putenv() or [un]setenv().  On Windows,
+     processes have two environments, one in the "environment block" of the
+     process and managed through SetEnvironmentVariable(), and one inside the
+     process, in the location retrieved by the 'environ' macro.  If we were
+     to pass NULL, the child process would inherit a copy of the environment
+     block - ignoring the effects of putenv() and [un]setenv().  */
+  return execvpe (program, argv, environ);
+}
diff --git a/m4/execvp.m4 b/m4/execvp.m4
new file mode 100644
index 0000000..833b987
--- /dev/null
+++ b/m4/execvp.m4
@@ -0,0 +1,15 @@
+# execvp.m4 serial 1
+dnl Copyright (C) 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,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_FUNC_EXECVP],
+[
+  AC_REQUIRE([gl_UNISTD_H_DEFAULTS])
+  AC_REQUIRE([AC_CANONICAL_HOST])
+
+  case "$host_os" in
+    mingw*) REPLACE_EXECVP=1 ;;
+  esac
+])
diff --git a/modules/execvp b/modules/execvp
new file mode 100644
index 0000000..df2d313
--- /dev/null
+++ b/modules/execvp
@@ -0,0 +1,29 @@
+Description:
+execvp() function: Execute a program, replacing the current process.
+
+Files:
+lib/execvp.c
+m4/execvp.m4
+
+Depends-on:
+unistd
+environ         [test $REPLACE_EXECVP = 1]
+execvpe         [test $REPLACE_EXECVP = 1]
+
+configure.ac:
+gl_FUNC_EXECVP
+if test $REPLACE_EXECVP = 1; then
+  AC_LIBOBJ([execvp])
+fi
+gl_UNISTD_MODULE_INDICATOR([execvp])
+
+Makefile.am:
+
+Include:
+<unistd.h>
+
+License:
+LGPLv2+
+
+Maintainer:
+all
-- 
2.7.4


[-- Attachment #8: 0007-execvp-Add-tests.patch --]
[-- Type: text/x-patch, Size: 4648 bytes --]

From b7f8be836643b720a0d9207fe0927889dd8b3b2b Mon Sep 17 00:00:00 2001
From: Bruno Haible <bruno@clisp.org>
Date: Sat, 26 Dec 2020 14:29:56 +0100
Subject: [PATCH 07/15] execvp: Add tests.

* tests/test-execvp-main.c: New file.
* tests/test-execvp.sh: New file.
* modules/execvp-tests: New file.
---
 ChangeLog                |  5 +++++
 modules/execvp-tests     | 11 ++++++++++
 tests/test-execvp-main.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++
 tests/test-execvp.sh     | 50 ++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 118 insertions(+)
 create mode 100644 modules/execvp-tests
 create mode 100644 tests/test-execvp-main.c
 create mode 100755 tests/test-execvp.sh

diff --git a/ChangeLog b/ChangeLog
index 5d20495..f7a0650 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,10 @@
 2020-12-26  Bruno Haible  <bruno@clisp.org>
 
+	execvp: Add tests.
+	* tests/test-execvp-main.c: New file.
+	* tests/test-execvp.sh: New file.
+	* modules/execvp-tests: New file.
+
 	execvp: New module.
 	* lib/execvp.c: New file.
 	* m4/execvp.m4: New file.
diff --git a/modules/execvp-tests b/modules/execvp-tests
new file mode 100644
index 0000000..a1e050e
--- /dev/null
+++ b/modules/execvp-tests
@@ -0,0 +1,11 @@
+Files:
+tests/test-execvp.sh
+tests/test-execvp-main.c
+tests/test-exec-child.c
+tests/signature.h
+
+Depends-on:
+
+Makefile.am:
+TESTS += test-execvp.sh
+check_PROGRAMS += test-execvp-main test-exec-child
diff --git a/tests/test-execvp-main.c b/tests/test-execvp-main.c
new file mode 100644
index 0000000..9adc9b1
--- /dev/null
+++ b/tests/test-execvp-main.c
@@ -0,0 +1,52 @@
+/* Test of execvp().
+   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/>.  */
+
+/* Written by Bruno Haible <bruno@clisp.org>, 2020.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include <unistd.h>
+
+#include "signature.h"
+SIGNATURE_CHECK (execvp, int, (const char *, char * const *));
+
+#include <stdio.h>
+
+int
+main ()
+{
+  const char *progname = "test-exec-child";
+  const char *argv[12] =
+    {
+      progname,
+      "abc def",
+      "abc\"def\"ghi",
+      "xyz\"",
+      "abc\\def\\ghi",
+      "xyz\\",
+      "???",
+      "***",
+      "",
+      "foo",
+      "",
+      NULL
+    };
+  execvp (progname, (char * const *) argv);
+
+  perror ("execvp");
+  return 1;
+}
diff --git a/tests/test-execvp.sh b/tests/test-execvp.sh
new file mode 100755
index 0000000..bf3b307
--- /dev/null
+++ b/tests/test-execvp.sh
@@ -0,0 +1,50 @@
+#!/bin/sh
+
+# Test of execvp().
+#
+# 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 of the License, 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/>.  */
+#
+# Written by Bruno Haible <bruno@clisp.org>, 2020.
+
+rm -rf test-execvp-subdir
+mkdir test-execvp-subdir
+
+(cd test-execvp-subdir && PATH="..:$PATH" ${CHECKER} ../test-execvp-main${EXEEXT}) > test-execvp.tmp
+result=$?
+test $result = 49 || { rm -rf test-execvp-subdir; exit 1; }
+LC_ALL=C tr -d '\r' < test-execvp.tmp > test-execvp.out || { rm -rf test-execvp-subdir; exit 1; }
+
+cat > test-execvp.ok <<\EOF
+argc = 11
+argv[1] = |abc def|
+argv[2] = |abc"def"ghi|
+argv[3] = |xyz"|
+argv[4] = |abc\def\ghi|
+argv[5] = |xyz\|
+argv[6] = |???|
+argv[7] = |***|
+argv[8] = ||
+argv[9] = |foo|
+argv[10] = ||
+EOF
+
+: ${DIFF=diff}
+${DIFF} test-execvp.ok test-execvp.out
+result=$?
+
+rm -rf test-execvp-subdir test-execvp.tmp test-execvp.out test-execvp.ok
+
+exit $result
-- 
2.7.4


[-- Attachment #9: 0008-execv-New-module.patch --]
[-- Type: text/x-patch, Size: 5624 bytes --]

From 58ef9c2d18f3c158ff42cd3b7297f9e9bbc74738 Mon Sep 17 00:00:00 2001
From: Bruno Haible <bruno@clisp.org>
Date: Sat, 26 Dec 2020 14:31:50 +0100
Subject: [PATCH 08/15] execv: New module.

* lib/execv.c: New file.
* m4/execv.m4: New file.
* modules/execv: New file.
* doc/posix-functions/execv.texi: Mention more Windows problems and the
new module.
---
 ChangeLog                      |  7 +++++++
 doc/posix-functions/execv.texi | 21 ++++++++++++++++-----
 lib/execv.c                    | 35 +++++++++++++++++++++++++++++++++++
 m4/execv.m4                    | 15 +++++++++++++++
 modules/execv                  | 29 +++++++++++++++++++++++++++++
 5 files changed, 102 insertions(+), 5 deletions(-)
 create mode 100644 lib/execv.c
 create mode 100644 m4/execv.m4
 create mode 100644 modules/execv

diff --git a/ChangeLog b/ChangeLog
index f7a0650..836a115 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,12 @@
 2020-12-26  Bruno Haible  <bruno@clisp.org>
 
+	execv: New module.
+	* lib/execv.c: New file.
+	* m4/execv.m4: New file.
+	* modules/execv: New file.
+	* doc/posix-functions/execv.texi: Mention more Windows problems and the
+	new module.
+
 	execvp: Add tests.
 	* tests/test-execvp-main.c: New file.
 	* tests/test-execvp.sh: New file.
diff --git a/doc/posix-functions/execv.texi b/doc/posix-functions/execv.texi
index c18fce4..9dbea90 100644
--- a/doc/posix-functions/execv.texi
+++ b/doc/posix-functions/execv.texi
@@ -4,19 +4,30 @@
 
 POSIX specification:@* @url{https://pubs.opengroup.org/onlinepubs/9699919799/functions/execv.html}
 
-Gnulib module: ---
+Gnulib module: execv
 
 Portability problems fixed by Gnulib:
 @itemize
+@item
+On Windows platforms (excluding Cygwin), this function does not pass
+command-line arguments correctly if they contain space, tab, backslash,
+or double-quote characters.
+@item
+On Windows platforms (excluding Cygwin), this function spawns an asynchronous
+child process and then exits the current process immediately.  As a
+consequence, the parent of the current process 1. may incorrectly proceed
+as if its child had exited, and 2. will never see the child's exit status.
+@item
+On Windows platforms (excluding Cygwin), the return type of this function is
+@code{intptr_t}, not @code{int}.
 @end itemize
 
+Note: The Gnulib replacement for this function is not async-safe, that is,
+it must not be invoked from a signal handler.
+
 Portability problems not fixed by Gnulib:
 @itemize
 @item
 On some platforms, a script without executable permission is still run:
 Cygwin 1.5.x.
-@item
-On Windows platforms (excluding Cygwin), this function operates by spawning
-and then by exiting the current process, which means the current
-process's parent may incorrectly proceed as if its child had exited.
 @end itemize
diff --git a/lib/execv.c b/lib/execv.c
new file mode 100644
index 0000000..d5c88a0
--- /dev/null
+++ b/lib/execv.c
@@ -0,0 +1,35 @@
+/* execv() function: Execute a program, replacing the current process.
+   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 of the License, 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/>.  */
+
+/* Written by Bruno Haible <bruno@clisp.org>, 2020.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include <unistd.h>
+
+int
+execv (const char *program, char * const *argv)
+{
+  /* Pass the environment explicitly.  This is needed if the program has
+     modified the environment using putenv() or [un]setenv().  On Windows,
+     processes have two environments, one in the "environment block" of the
+     process and managed through SetEnvironmentVariable(), and one inside the
+     process, in the location retrieved by the 'environ' macro.  If we were
+     to pass NULL, the child process would inherit a copy of the environment
+     block - ignoring the effects of putenv() and [un]setenv().  */
+  return execve (program, argv, environ);
+}
diff --git a/m4/execv.m4 b/m4/execv.m4
new file mode 100644
index 0000000..8064482
--- /dev/null
+++ b/m4/execv.m4
@@ -0,0 +1,15 @@
+# execv.m4 serial 1
+dnl Copyright (C) 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,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_FUNC_EXECV],
+[
+  AC_REQUIRE([gl_UNISTD_H_DEFAULTS])
+  AC_REQUIRE([AC_CANONICAL_HOST])
+
+  case "$host_os" in
+    mingw*) REPLACE_EXECV=1 ;;
+  esac
+])
diff --git a/modules/execv b/modules/execv
new file mode 100644
index 0000000..db64abb
--- /dev/null
+++ b/modules/execv
@@ -0,0 +1,29 @@
+Description:
+execv() function: Execute a program, replacing the current process.
+
+Files:
+lib/execv.c
+m4/execv.m4
+
+Depends-on:
+unistd
+environ         [test $REPLACE_EXECV = 1]
+execve          [test $REPLACE_EXECV = 1]
+
+configure.ac:
+gl_FUNC_EXECV
+if test $REPLACE_EXECV = 1; then
+  AC_LIBOBJ([execv])
+fi
+gl_UNISTD_MODULE_INDICATOR([execv])
+
+Makefile.am:
+
+Include:
+<unistd.h>
+
+License:
+LGPLv2+
+
+Maintainer:
+all
-- 
2.7.4


[-- Attachment #10: 0009-execv-Add-tests.patch --]
[-- Type: text/x-patch, Size: 4421 bytes --]

From 46c14c901d0a9b3aff27b9b3dde802e0a1c98bea Mon Sep 17 00:00:00 2001
From: Bruno Haible <bruno@clisp.org>
Date: Sat, 26 Dec 2020 14:33:33 +0100
Subject: [PATCH 09/15] execv: Add tests.

* tests/test-execv-main.c: New file.
* tests/test-execv.sh: New file.
* modules/execv-tests: New file.
---
 ChangeLog               |  5 +++++
 modules/execv-tests     | 11 +++++++++++
 tests/test-execv-main.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++++
 tests/test-execv.sh     | 47 ++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 115 insertions(+)
 create mode 100644 modules/execv-tests
 create mode 100644 tests/test-execv-main.c
 create mode 100755 tests/test-execv.sh

diff --git a/ChangeLog b/ChangeLog
index 836a115..1af6b70 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,10 @@
 2020-12-26  Bruno Haible  <bruno@clisp.org>
 
+	execv: Add tests.
+	* tests/test-execv-main.c: New file.
+	* tests/test-execv.sh: New file.
+	* modules/execv-tests: New file.
+
 	execv: New module.
 	* lib/execv.c: New file.
 	* m4/execv.m4: New file.
diff --git a/modules/execv-tests b/modules/execv-tests
new file mode 100644
index 0000000..99d63d9
--- /dev/null
+++ b/modules/execv-tests
@@ -0,0 +1,11 @@
+Files:
+tests/test-execv.sh
+tests/test-execv-main.c
+tests/test-exec-child.c
+tests/signature.h
+
+Depends-on:
+
+Makefile.am:
+TESTS += test-execv.sh
+check_PROGRAMS += test-execv-main test-exec-child
diff --git a/tests/test-execv-main.c b/tests/test-execv-main.c
new file mode 100644
index 0000000..fbe4d5c
--- /dev/null
+++ b/tests/test-execv-main.c
@@ -0,0 +1,52 @@
+/* Test of execv().
+   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/>.  */
+
+/* Written by Bruno Haible <bruno@clisp.org>, 2020.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include <unistd.h>
+
+#include "signature.h"
+SIGNATURE_CHECK (execv, int, (const char *, char * const *));
+
+#include <stdio.h>
+
+int
+main ()
+{
+  const char *progname = "./test-exec-child";
+  const char *argv[12] =
+    {
+      progname,
+      "abc def",
+      "abc\"def\"ghi",
+      "xyz\"",
+      "abc\\def\\ghi",
+      "xyz\\",
+      "???",
+      "***",
+      "",
+      "foo",
+      "",
+      NULL
+    };
+  execv (progname, (char * const *) argv);
+
+  perror ("execv");
+  return 1;
+}
diff --git a/tests/test-execv.sh b/tests/test-execv.sh
new file mode 100755
index 0000000..cdea34f
--- /dev/null
+++ b/tests/test-execv.sh
@@ -0,0 +1,47 @@
+#!/bin/sh
+
+# Test of execv().
+#
+# 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 of the License, 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/>.  */
+#
+# Written by Bruno Haible <bruno@clisp.org>, 2020.
+
+${CHECKER} ./test-execv-main${EXEEXT} > test-execv.tmp
+result=$?
+test $result = 49 || exit 1
+LC_ALL=C tr -d '\r' < test-execv.tmp > test-execv.out || exit 1
+
+cat > test-execv.ok <<\EOF
+argc = 11
+argv[1] = |abc def|
+argv[2] = |abc"def"ghi|
+argv[3] = |xyz"|
+argv[4] = |abc\def\ghi|
+argv[5] = |xyz\|
+argv[6] = |???|
+argv[7] = |***|
+argv[8] = ||
+argv[9] = |foo|
+argv[10] = ||
+EOF
+
+: ${DIFF=diff}
+${DIFF} test-execv.ok test-execv.out
+result=$?
+
+rm -f test-execv.tmp test-execv.out test-execv.ok
+
+exit $result
-- 
2.7.4


[-- Attachment #11: 0010-execl-New-module.patch --]
[-- Type: text/x-patch, Size: 6278 bytes --]

From 7fbf62ebb9e7466a157b5f339d15ff1d11b18d45 Mon Sep 17 00:00:00 2001
From: Bruno Haible <bruno@clisp.org>
Date: Sat, 26 Dec 2020 14:36:35 +0100
Subject: [PATCH 10/15] execl: New module.

* lib/execl.c: New file.
* m4/execl.m4: New file.
* modules/execl: New file.
* doc/posix-functions/execl.texi: Mention more Windows problems and the
new module.
---
 ChangeLog                      |  7 ++++
 doc/posix-functions/execl.texi | 21 ++++++++---
 lib/execl.c                    | 82 ++++++++++++++++++++++++++++++++++++++++++
 m4/execl.m4                    | 15 ++++++++
 modules/execl                  | 29 +++++++++++++++
 5 files changed, 149 insertions(+), 5 deletions(-)
 create mode 100644 lib/execl.c
 create mode 100644 m4/execl.m4
 create mode 100644 modules/execl

diff --git a/ChangeLog b/ChangeLog
index 1af6b70..5b8e553 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,12 @@
 2020-12-26  Bruno Haible  <bruno@clisp.org>
 
+	execl: New module.
+	* lib/execl.c: New file.
+	* m4/execl.m4: New file.
+	* modules/execl: New file.
+	* doc/posix-functions/execl.texi: Mention more Windows problems and the
+	new module.
+
 	execv: Add tests.
 	* tests/test-execv-main.c: New file.
 	* tests/test-execv.sh: New file.
diff --git a/doc/posix-functions/execl.texi b/doc/posix-functions/execl.texi
index 70c9f8e..28460e2 100644
--- a/doc/posix-functions/execl.texi
+++ b/doc/posix-functions/execl.texi
@@ -4,19 +4,30 @@
 
 POSIX specification:@* @url{https://pubs.opengroup.org/onlinepubs/9699919799/functions/execl.html}
 
-Gnulib module: ---
+Gnulib module: execl
 
 Portability problems fixed by Gnulib:
 @itemize
+@item
+On Windows platforms (excluding Cygwin), this function does not pass
+command-line arguments correctly if they contain space, tab, backslash,
+or double-quote characters.
+@item
+On Windows platforms (excluding Cygwin), this function spawns an asynchronous
+child process and then exits the current process immediately.  As a
+consequence, the parent of the current process 1. may incorrectly proceed
+as if its child had exited, and 2. will never see the child's exit status.
+@item
+On Windows platforms (excluding Cygwin), the return type of this function is
+@code{intptr_t}, not @code{int}.
 @end itemize
 
+Note: The Gnulib replacement for this function is not async-safe, that is,
+it must not be invoked from a signal handler.
+
 Portability problems not fixed by Gnulib:
 @itemize
 @item
 On some platforms, a script without executable permission is still run:
 Cygwin 1.5.x.
-@item
-On Windows platforms (excluding Cygwin), this function operates by spawning
-and then by exiting the current process, which means the current
-process's parent may incorrectly proceed as if its child had exited.
 @end itemize
diff --git a/lib/execl.c b/lib/execl.c
new file mode 100644
index 0000000..d1df0c0
--- /dev/null
+++ b/lib/execl.c
@@ -0,0 +1,82 @@
+/* execl() function: Execute a program, replacing the current process.
+   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 of the License, 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/>.  */
+
+/* Written by Bruno Haible <bruno@clisp.org>, 2020.  */
+
+/* Don't use __attribute__ __nonnull__ in this compilation unit.  Otherwise gcc
+   may optimize away the arg0 == NULL test below.  */
+#define _GL_ARG_NONNULL(params)
+
+#include <config.h>
+
+/* Specification.  */
+#include <unistd.h>
+
+#include <errno.h>
+#include <stdarg.h>
+
+#include "malloca.h"
+
+int
+execl (const char *program, const char *arg0, ...)
+{
+  va_list args;
+
+  /* The callee is not expecting a NULL argv[0].  */
+  if (arg0 == NULL)
+    {
+      errno = EINVAL;
+      return -1;
+    }
+
+  /* Count the number of arguments (including arg0 and the trailing NULL).  */
+  size_t count = 1;
+  va_start (args, arg0);
+  for (;;)
+    {
+      count++;
+      if (va_arg (args, const char *) == NULL)
+        break;
+    }
+  va_end (args);
+
+  /* Allocate the argument vector.  */
+  const char **argv = (const char **) malloca (count * sizeof (const char *));
+  if (argv == NULL)
+    {
+      errno = ENOMEM;
+      return -1;
+    }
+
+  /* Copy the arguments into the argument vector.  */
+  {
+    size_t i = 0;
+    argv[i++] = arg0;
+    va_start (args, arg0);
+    for (; i < count;)
+      argv[i++] = va_arg (args, const char *);
+    va_end (args);
+  }
+
+  /* Invoke execv.  */
+  execv (program, argv);
+
+  /* If execv returned, it must have failed.  */
+  int saved_errno = errno;
+  freea (argv);
+  errno = saved_errno;
+  return -1;
+}
diff --git a/m4/execl.m4 b/m4/execl.m4
new file mode 100644
index 0000000..0f2c89c
--- /dev/null
+++ b/m4/execl.m4
@@ -0,0 +1,15 @@
+# execl.m4 serial 1
+dnl Copyright (C) 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,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_FUNC_EXECL],
+[
+  AC_REQUIRE([gl_UNISTD_H_DEFAULTS])
+  AC_REQUIRE([AC_CANONICAL_HOST])
+
+  case "$host_os" in
+    mingw*) REPLACE_EXECL=1 ;;
+  esac
+])
diff --git a/modules/execl b/modules/execl
new file mode 100644
index 0000000..9d64c5c
--- /dev/null
+++ b/modules/execl
@@ -0,0 +1,29 @@
+Description:
+execl() function: Execute a program, replacing the current process.
+
+Files:
+lib/execl.c
+m4/execl.m4
+
+Depends-on:
+unistd
+execv           [test $REPLACE_EXECL = 1]
+malloca         [test $REPLACE_EXECL = 1]
+
+configure.ac:
+gl_FUNC_EXECL
+if test $REPLACE_EXECL = 1; then
+  AC_LIBOBJ([execl])
+fi
+gl_UNISTD_MODULE_INDICATOR([execl])
+
+Makefile.am:
+
+Include:
+<unistd.h>
+
+License:
+LGPLv2+
+
+Maintainer:
+all
-- 
2.7.4


[-- Attachment #12: 0011-execl-Add-tests.patch --]
[-- Type: text/x-patch, Size: 4400 bytes --]

From 614b2e6c98172bdcc96ca735f4e14056dc32e59c Mon Sep 17 00:00:00 2001
From: Bruno Haible <bruno@clisp.org>
Date: Sat, 26 Dec 2020 14:37:54 +0100
Subject: [PATCH 11/15] execl: Add tests.

* tests/test-execl-main.c: New file.
* tests/test-execl.sh: New file.
* modules/execl-tests: New file.
---
 ChangeLog               |  5 +++++
 modules/execl-tests     | 11 +++++++++++
 tests/test-execl-main.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++
 tests/test-execl.sh     | 47 +++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 112 insertions(+)
 create mode 100644 modules/execl-tests
 create mode 100644 tests/test-execl-main.c
 create mode 100755 tests/test-execl.sh

diff --git a/ChangeLog b/ChangeLog
index 5b8e553..7f5c99b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,10 @@
 2020-12-26  Bruno Haible  <bruno@clisp.org>
 
+	execl: Add tests.
+	* tests/test-execl-main.c: New file.
+	* tests/test-execl.sh: New file.
+	* modules/execl-tests: New file.
+
 	execl: New module.
 	* lib/execl.c: New file.
 	* m4/execl.m4: New file.
diff --git a/modules/execl-tests b/modules/execl-tests
new file mode 100644
index 0000000..a7c56f5
--- /dev/null
+++ b/modules/execl-tests
@@ -0,0 +1,11 @@
+Files:
+tests/test-execl.sh
+tests/test-execl-main.c
+tests/test-exec-child.c
+tests/signature.h
+
+Depends-on:
+
+Makefile.am:
+TESTS += test-execl.sh
+check_PROGRAMS += test-execl-main test-exec-child
diff --git a/tests/test-execl-main.c b/tests/test-execl-main.c
new file mode 100644
index 0000000..a16cefa
--- /dev/null
+++ b/tests/test-execl-main.c
@@ -0,0 +1,49 @@
+/* Test of execl().
+   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/>.  */
+
+/* Written by Bruno Haible <bruno@clisp.org>, 2020.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include <unistd.h>
+
+#include "signature.h"
+SIGNATURE_CHECK (execl, int, (const char *, const char *, ...));
+
+#include <stdio.h>
+
+int
+main ()
+{
+  const char *progname = "./test-exec-child";
+  execl (progname,
+         progname,
+         "abc def",
+         "abc\"def\"ghi",
+         "xyz\"",
+         "abc\\def\\ghi",
+         "xyz\\",
+         "???",
+         "***",
+         "",
+         "foo",
+         "",
+         NULL);
+
+  perror ("execl");
+  return 1;
+}
diff --git a/tests/test-execl.sh b/tests/test-execl.sh
new file mode 100755
index 0000000..285059d
--- /dev/null
+++ b/tests/test-execl.sh
@@ -0,0 +1,47 @@
+#!/bin/sh
+
+# Test of execl().
+#
+# 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 of the License, 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/>.  */
+#
+# Written by Bruno Haible <bruno@clisp.org>, 2020.
+
+${CHECKER} ./test-execl-main${EXEEXT} > test-execl.tmp
+result=$?
+test $result = 49 || exit 1
+LC_ALL=C tr -d '\r' < test-execl.tmp > test-execl.out || exit 1
+
+cat > test-execl.ok <<\EOF
+argc = 11
+argv[1] = |abc def|
+argv[2] = |abc"def"ghi|
+argv[3] = |xyz"|
+argv[4] = |abc\def\ghi|
+argv[5] = |xyz\|
+argv[6] = |???|
+argv[7] = |***|
+argv[8] = ||
+argv[9] = |foo|
+argv[10] = ||
+EOF
+
+: ${DIFF=diff}
+${DIFF} test-execl.ok test-execl.out
+result=$?
+
+rm -f test-execl.tmp test-execl.out test-execl.ok
+
+exit $result
-- 
2.7.4


[-- Attachment #13: 0012-execle-New-module.patch --]
[-- Type: text/x-patch, Size: 6383 bytes --]

From 6b1f82435bc2f900429b711d90e25857d817eafe Mon Sep 17 00:00:00 2001
From: Bruno Haible <bruno@clisp.org>
Date: Sat, 26 Dec 2020 14:39:39 +0100
Subject: [PATCH 12/15] execle: New module.

* lib/execle.c: New file.
* m4/execle.m4: New file.
* modules/execle: New file.
* doc/posix-functions/execle.texi: Mention more Windows problems and the
new module.
---
 ChangeLog                       |  7 ++++
 doc/posix-functions/execle.texi | 21 ++++++++---
 lib/execle.c                    | 83 +++++++++++++++++++++++++++++++++++++++++
 m4/execle.m4                    | 15 ++++++++
 modules/execle                  | 29 ++++++++++++++
 5 files changed, 150 insertions(+), 5 deletions(-)
 create mode 100644 lib/execle.c
 create mode 100644 m4/execle.m4
 create mode 100644 modules/execle

diff --git a/ChangeLog b/ChangeLog
index 7f5c99b..6a8939c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,12 @@
 2020-12-26  Bruno Haible  <bruno@clisp.org>
 
+	execle: New module.
+	* lib/execle.c: New file.
+	* m4/execle.m4: New file.
+	* modules/execle: New file.
+	* doc/posix-functions/execle.texi: Mention more Windows problems and the
+	new module.
+
 	execl: Add tests.
 	* tests/test-execl-main.c: New file.
 	* tests/test-execl.sh: New file.
diff --git a/doc/posix-functions/execle.texi b/doc/posix-functions/execle.texi
index 04ef7c2..e556260 100644
--- a/doc/posix-functions/execle.texi
+++ b/doc/posix-functions/execle.texi
@@ -4,19 +4,30 @@
 
 POSIX specification:@* @url{https://pubs.opengroup.org/onlinepubs/9699919799/functions/execle.html}
 
-Gnulib module: ---
+Gnulib module: execle
 
 Portability problems fixed by Gnulib:
 @itemize
+@item
+On Windows platforms (excluding Cygwin), this function does not pass
+command-line arguments correctly if they contain space, tab, backslash,
+or double-quote characters.
+@item
+On Windows platforms (excluding Cygwin), this function spawns an asynchronous
+child process and then exits the current process immediately.  As a
+consequence, the parent of the current process 1. may incorrectly proceed
+as if its child had exited, and 2. will never see the child's exit status.
+@item
+On Windows platforms (excluding Cygwin), the return type of this function is
+@code{intptr_t}, not @code{int}.
 @end itemize
 
+Note: The Gnulib replacement for this function is not async-safe, that is,
+it must not be invoked from a signal handler.
+
 Portability problems not fixed by Gnulib:
 @itemize
 @item
 On some platforms, a script without executable permission is still run:
 Cygwin 1.5.x.
-@item
-On Windows platforms (excluding Cygwin), this function operates by spawning
-and then by exiting the current process, which means the current
-process's parent may incorrectly proceed as if its child had exited.
 @end itemize
diff --git a/lib/execle.c b/lib/execle.c
new file mode 100644
index 0000000..8e10d8a
--- /dev/null
+++ b/lib/execle.c
@@ -0,0 +1,83 @@
+/* execle() function: Execute a program, replacing the current process.
+   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 of the License, 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/>.  */
+
+/* Written by Bruno Haible <bruno@clisp.org>, 2020.  */
+
+/* Don't use __attribute__ __nonnull__ in this compilation unit.  Otherwise gcc
+   may optimize away the arg0 == NULL test below.  */
+#define _GL_ARG_NONNULL(params)
+
+#include <config.h>
+
+/* Specification.  */
+#include <unistd.h>
+
+#include <errno.h>
+#include <stdarg.h>
+
+#include "malloca.h"
+
+int
+execle (const char *program, const char *arg0, ...)
+{
+  va_list args;
+
+  /* The callee is not expecting a NULL argv[0].  */
+  if (arg0 == NULL)
+    {
+      errno = EINVAL;
+      return -1;
+    }
+
+  /* Count the number of arguments (including arg0 and the trailing NULL).  */
+  size_t count = 1;
+  va_start (args, arg0);
+  for (;;)
+    {
+      count++;
+      if (va_arg (args, const char *) == NULL)
+        break;
+    }
+  va_end (args);
+
+  /* Allocate the argument vector.  */
+  const char **argv = (const char **) malloca (count * sizeof (const char *));
+  if (argv == NULL)
+    {
+      errno = ENOMEM;
+      return -1;
+    }
+
+  /* Copy the arguments into the argument vector.  */
+  {
+    size_t i = 0;
+    argv[i++] = arg0;
+    va_start (args, arg0);
+    for (; i < count;)
+      argv[i++] = va_arg (args, const char *);
+  }
+  char * const *env = va_arg (args, char * const *);
+  va_end (args);
+
+  /* Invoke execve.  */
+  execve (program, argv, env);
+
+  /* If execve returned, it must have failed.  */
+  int saved_errno = errno;
+  freea (argv);
+  errno = saved_errno;
+  return -1;
+}
diff --git a/m4/execle.m4 b/m4/execle.m4
new file mode 100644
index 0000000..47b273b
--- /dev/null
+++ b/m4/execle.m4
@@ -0,0 +1,15 @@
+# execle.m4 serial 1
+dnl Copyright (C) 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,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_FUNC_EXECLE],
+[
+  AC_REQUIRE([gl_UNISTD_H_DEFAULTS])
+  AC_REQUIRE([AC_CANONICAL_HOST])
+
+  case "$host_os" in
+    mingw*) REPLACE_EXECLE=1 ;;
+  esac
+])
diff --git a/modules/execle b/modules/execle
new file mode 100644
index 0000000..dd3c9ad
--- /dev/null
+++ b/modules/execle
@@ -0,0 +1,29 @@
+Description:
+execle() function: Execute a program, replacing the current process.
+
+Files:
+lib/execle.c
+m4/execle.m4
+
+Depends-on:
+unistd
+execve          [test $REPLACE_EXECLE = 1]
+malloca         [test $REPLACE_EXECLE = 1]
+
+configure.ac:
+gl_FUNC_EXECLE
+if test $REPLACE_EXECLE = 1; then
+  AC_LIBOBJ([execle])
+fi
+gl_UNISTD_MODULE_INDICATOR([execle])
+
+Makefile.am:
+
+Include:
+<unistd.h>
+
+License:
+LGPLv2+
+
+Maintainer:
+all
-- 
2.7.4


[-- Attachment #14: 0013-execle-Add-tests.patch --]
[-- Type: text/x-patch, Size: 4579 bytes --]

From b42620e8d20cfcb5d18f452a38aa05500d3ada35 Mon Sep 17 00:00:00 2001
From: Bruno Haible <bruno@clisp.org>
Date: Sat, 26 Dec 2020 14:40:49 +0100
Subject: [PATCH 13/15] execle: Add tests.

* tests/test-execle-main.c: New file.
* tests/test-execle.sh: New file.
* modules/execle-tests: New file.
---
 ChangeLog                |  5 +++++
 modules/execle-tests     | 11 +++++++++++
 tests/test-execle-main.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++
 tests/test-execle.sh     | 48 +++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 115 insertions(+)
 create mode 100644 modules/execle-tests
 create mode 100644 tests/test-execle-main.c
 create mode 100755 tests/test-execle.sh

diff --git a/ChangeLog b/ChangeLog
index 6a8939c..e7a8228 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,10 @@
 2020-12-26  Bruno Haible  <bruno@clisp.org>
 
+	execle: Add tests.
+	* tests/test-execle-main.c: New file.
+	* tests/test-execle.sh: New file.
+	* modules/execle-tests: New file.
+
 	execle: New module.
 	* lib/execle.c: New file.
 	* m4/execle.m4: New file.
diff --git a/modules/execle-tests b/modules/execle-tests
new file mode 100644
index 0000000..d752b2c
--- /dev/null
+++ b/modules/execle-tests
@@ -0,0 +1,11 @@
+Files:
+tests/test-execle.sh
+tests/test-execle-main.c
+tests/test-exec-child.c
+tests/signature.h
+
+Depends-on:
+
+Makefile.am:
+TESTS += test-execle.sh
+check_PROGRAMS += test-execle-main test-exec-child
diff --git a/tests/test-execle-main.c b/tests/test-execle-main.c
new file mode 100644
index 0000000..50d5899
--- /dev/null
+++ b/tests/test-execle-main.c
@@ -0,0 +1,51 @@
+/* Test of execle().
+   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/>.  */
+
+/* Written by Bruno Haible <bruno@clisp.org>, 2020.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include <unistd.h>
+
+#include "signature.h"
+SIGNATURE_CHECK (execle, int, (const char *, const char *, ...));
+
+#include <stdio.h>
+
+int
+main ()
+{
+  const char *progname = "./test-exec-child";
+  const char *env[3] = { "PATH=.", "Hommingberg=Gepardenforelle", NULL };
+  execle (progname,
+          progname,
+          "abc def",
+          "abc\"def\"ghi",
+          "xyz\"",
+          "abc\\def\\ghi",
+          "xyz\\",
+          "???",
+          "***",
+          "",
+          "foo",
+          "",
+          NULL,
+          env);
+
+  perror ("execle");
+  return 1;
+}
diff --git a/tests/test-execle.sh b/tests/test-execle.sh
new file mode 100755
index 0000000..76469b7
--- /dev/null
+++ b/tests/test-execle.sh
@@ -0,0 +1,48 @@
+#!/bin/sh
+
+# Test of execle().
+#
+# 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 of the License, 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/>.  */
+#
+# Written by Bruno Haible <bruno@clisp.org>, 2020.
+
+${CHECKER} ./test-execle-main${EXEEXT} > test-execle.tmp
+result=$?
+test $result = 49 || exit 1
+LC_ALL=C tr -d '\r' < test-execle.tmp > test-execle.out || exit 1
+
+cat > test-execle.ok <<\EOF
+argc = 11
+argv[1] = |abc def|
+argv[2] = |abc"def"ghi|
+argv[3] = |xyz"|
+argv[4] = |abc\def\ghi|
+argv[5] = |xyz\|
+argv[6] = |???|
+argv[7] = |***|
+argv[8] = ||
+argv[9] = |foo|
+argv[10] = ||
+Hommingberg = |Gepardenforelle|
+EOF
+
+: ${DIFF=diff}
+${DIFF} test-execle.ok test-execle.out
+result=$?
+
+rm -f test-execle.tmp test-execle.out test-execle.ok
+
+exit $result
-- 
2.7.4


[-- Attachment #15: 0014-execlp-New-module.patch --]
[-- Type: text/x-patch, Size: 6253 bytes --]

From 761c7c948d36f58357e50913fd14b94a42e9ae14 Mon Sep 17 00:00:00 2001
From: Bruno Haible <bruno@clisp.org>
Date: Sat, 26 Dec 2020 14:42:38 +0100
Subject: [PATCH 14/15] execlp: New module.

* lib/execlp.c: New file.
* m4/execlp.m4: New file.
* modules/execlp: New file.
* doc/posix-functions/execlp.texi: Mention more Windows problems and the
new module.
---
 ChangeLog                       |  7 ++++
 doc/posix-functions/execlp.texi | 18 ++++++---
 lib/execlp.c                    | 82 +++++++++++++++++++++++++++++++++++++++++
 m4/execlp.m4                    | 15 ++++++++
 modules/execlp                  | 29 +++++++++++++++
 5 files changed, 146 insertions(+), 5 deletions(-)
 create mode 100644 lib/execlp.c
 create mode 100644 m4/execlp.m4
 create mode 100644 modules/execlp

diff --git a/ChangeLog b/ChangeLog
index e7a8228..0bda9d1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,12 @@
 2020-12-26  Bruno Haible  <bruno@clisp.org>
 
+	execlp: New module.
+	* lib/execlp.c: New file.
+	* m4/execlp.m4: New file.
+	* modules/execlp: New file.
+	* doc/posix-functions/execlp.texi: Mention more Windows problems and the
+	new module.
+
 	execle: Add tests.
 	* tests/test-execle-main.c: New file.
 	* tests/test-execle.sh: New file.
diff --git a/doc/posix-functions/execlp.texi b/doc/posix-functions/execlp.texi
index 1314c75..8935119 100644
--- a/doc/posix-functions/execlp.texi
+++ b/doc/posix-functions/execlp.texi
@@ -4,10 +4,22 @@
 
 POSIX specification:@* @url{https://pubs.opengroup.org/onlinepubs/9699919799/functions/execlp.html}
 
-Gnulib module: ---
+Gnulib module: execlp
 
 Portability problems fixed by Gnulib:
 @itemize
+@item
+On Windows platforms (excluding Cygwin), this function does not pass
+command-line arguments correctly if they contain space, tab, backslash,
+or double-quote characters.
+@item
+On Windows platforms (excluding Cygwin), this function spawns an asynchronous
+child process and then exits the current process immediately.  As a
+consequence, the parent of the current process 1. may incorrectly proceed
+as if its child had exited, and 2. will never see the child's exit status.
+@item
+On Windows platforms (excluding Cygwin), the return type of this function is
+@code{intptr_t}, not @code{int}.
 @end itemize
 
 Portability problems not fixed by Gnulib:
@@ -15,8 +27,4 @@ Portability problems not fixed by Gnulib:
 @item
 On some platforms, a script without executable permission is still run:
 Cygwin 1.5.x.
-@item
-On Windows platforms (excluding Cygwin), this function operates by spawning
-and then by exiting the current process, which means the current
-process's parent may incorrectly proceed as if its child had exited.
 @end itemize
diff --git a/lib/execlp.c b/lib/execlp.c
new file mode 100644
index 0000000..cefa3ec
--- /dev/null
+++ b/lib/execlp.c
@@ -0,0 +1,82 @@
+/* execlp() function: Execute a program, replacing the current process.
+   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 of the License, 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/>.  */
+
+/* Written by Bruno Haible <bruno@clisp.org>, 2020.  */
+
+/* Don't use __attribute__ __nonnull__ in this compilation unit.  Otherwise gcc
+   may optimize away the arg0 == NULL test below.  */
+#define _GL_ARG_NONNULL(params)
+
+#include <config.h>
+
+/* Specification.  */
+#include <unistd.h>
+
+#include <errno.h>
+#include <stdarg.h>
+
+#include "malloca.h"
+
+int
+execlp (const char *program, const char *arg0, ...)
+{
+  va_list args;
+
+  /* The callee is not expecting a NULL argv[0].  */
+  if (arg0 == NULL)
+    {
+      errno = EINVAL;
+      return -1;
+    }
+
+  /* Count the number of arguments (including arg0 and the trailing NULL).  */
+  size_t count = 1;
+  va_start (args, arg0);
+  for (;;)
+    {
+      count++;
+      if (va_arg (args, const char *) == NULL)
+        break;
+    }
+  va_end (args);
+
+  /* Allocate the argument vector.  */
+  const char **argv = (const char **) malloca (count * sizeof (const char *));
+  if (argv == NULL)
+    {
+      errno = ENOMEM;
+      return -1;
+    }
+
+  /* Copy the arguments into the argument vector.  */
+  {
+    size_t i = 0;
+    argv[i++] = arg0;
+    va_start (args, arg0);
+    for (; i < count;)
+      argv[i++] = va_arg (args, const char *);
+    va_end (args);
+  }
+
+  /* Invoke execvp.  */
+  execvp (program, argv);
+
+  /* If execvp returned, it must have failed.  */
+  int saved_errno = errno;
+  freea (argv);
+  errno = saved_errno;
+  return -1;
+}
diff --git a/m4/execlp.m4 b/m4/execlp.m4
new file mode 100644
index 0000000..09df0c6
--- /dev/null
+++ b/m4/execlp.m4
@@ -0,0 +1,15 @@
+# execlp.m4 serial 1
+dnl Copyright (C) 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,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_FUNC_EXECLP],
+[
+  AC_REQUIRE([gl_UNISTD_H_DEFAULTS])
+  AC_REQUIRE([AC_CANONICAL_HOST])
+
+  case "$host_os" in
+    mingw*) REPLACE_EXECLP=1 ;;
+  esac
+])
diff --git a/modules/execlp b/modules/execlp
new file mode 100644
index 0000000..b31191c
--- /dev/null
+++ b/modules/execlp
@@ -0,0 +1,29 @@
+Description:
+execlp() function: Execute a program, replacing the current process.
+
+Files:
+lib/execlp.c
+m4/execlp.m4
+
+Depends-on:
+unistd
+execvp          [test $REPLACE_EXECLP = 1]
+malloca         [test $REPLACE_EXECLP = 1]
+
+configure.ac:
+gl_FUNC_EXECLP
+if test $REPLACE_EXECLP = 1; then
+  AC_LIBOBJ([execlp])
+fi
+gl_UNISTD_MODULE_INDICATOR([execlp])
+
+Makefile.am:
+
+Include:
+<unistd.h>
+
+License:
+LGPLv2+
+
+Maintainer:
+all
-- 
2.7.4


[-- Attachment #16: 0015-execlp-Add-tests.patch --]
[-- Type: text/x-patch, Size: 4638 bytes --]

From 8e5c999bce06f3d09c27c40e82b1527592dfa41c Mon Sep 17 00:00:00 2001
From: Bruno Haible <bruno@clisp.org>
Date: Sat, 26 Dec 2020 14:43:58 +0100
Subject: [PATCH 15/15] execlp: Add tests.

* tests/test-execlp-main.c: New file.
* tests/test-execlp.sh: New file.
* modules/execlp-tests: New file.
---
 ChangeLog                |  5 +++++
 modules/execlp-tests     | 11 +++++++++++
 tests/test-execlp-main.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++
 tests/test-execlp.sh     | 50 ++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 115 insertions(+)
 create mode 100644 modules/execlp-tests
 create mode 100644 tests/test-execlp-main.c
 create mode 100755 tests/test-execlp.sh

diff --git a/ChangeLog b/ChangeLog
index 0bda9d1..309b5b8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,10 @@
 2020-12-26  Bruno Haible  <bruno@clisp.org>
 
+	execlp: Add tests.
+	* tests/test-execlp-main.c: New file.
+	* tests/test-execlp.sh: New file.
+	* modules/execlp-tests: New file.
+
 	execlp: New module.
 	* lib/execlp.c: New file.
 	* m4/execlp.m4: New file.
diff --git a/modules/execlp-tests b/modules/execlp-tests
new file mode 100644
index 0000000..9ae80ab
--- /dev/null
+++ b/modules/execlp-tests
@@ -0,0 +1,11 @@
+Files:
+tests/test-execlp.sh
+tests/test-execlp-main.c
+tests/test-exec-child.c
+tests/signature.h
+
+Depends-on:
+
+Makefile.am:
+TESTS += test-execlp.sh
+check_PROGRAMS += test-execlp-main test-exec-child
diff --git a/tests/test-execlp-main.c b/tests/test-execlp-main.c
new file mode 100644
index 0000000..3b91ced
--- /dev/null
+++ b/tests/test-execlp-main.c
@@ -0,0 +1,49 @@
+/* Test of execlp().
+   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/>.  */
+
+/* Written by Bruno Haible <bruno@clisp.org>, 2020.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include <unistd.h>
+
+#include "signature.h"
+SIGNATURE_CHECK (execlp, int, (const char *, const char *, ...));
+
+#include <stdio.h>
+
+int
+main ()
+{
+  const char *progname = "test-exec-child";
+  execlp (progname,
+          progname,
+          "abc def",
+          "abc\"def\"ghi",
+          "xyz\"",
+          "abc\\def\\ghi",
+          "xyz\\",
+          "???",
+          "***",
+          "",
+          "foo",
+          "",
+          NULL);
+
+  perror ("execlp");
+  return 1;
+}
diff --git a/tests/test-execlp.sh b/tests/test-execlp.sh
new file mode 100755
index 0000000..db68d54
--- /dev/null
+++ b/tests/test-execlp.sh
@@ -0,0 +1,50 @@
+#!/bin/sh
+
+# Test of execlp().
+#
+# 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 of the License, 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/>.  */
+#
+# Written by Bruno Haible <bruno@clisp.org>, 2020.
+
+rm -rf test-execlp-subdir
+mkdir test-execlp-subdir
+
+(cd test-execlp-subdir && PATH="..:$PATH" ${CHECKER} ../test-execlp-main${EXEEXT}) > test-execlp.tmp
+result=$?
+test $result = 49 || { rm -rf test-execlp-subdir; exit 1; }
+LC_ALL=C tr -d '\r' < test-execlp.tmp > test-execlp.out || { rm -rf test-execlp-subdir; exit 1; }
+
+cat > test-execlp.ok <<\EOF
+argc = 11
+argv[1] = |abc def|
+argv[2] = |abc"def"ghi|
+argv[3] = |xyz"|
+argv[4] = |abc\def\ghi|
+argv[5] = |xyz\|
+argv[6] = |???|
+argv[7] = |***|
+argv[8] = ||
+argv[9] = |foo|
+argv[10] = ||
+EOF
+
+: ${DIFF=diff}
+${DIFF} test-execlp.ok test-execlp.out
+result=$?
+
+rm -rf test-execlp-subdir test-execlp.tmp test-execlp.out test-execlp.ok
+
+exit $result
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: new modules execve, execvpe, execvp, execv, execl, execle, execlp
  2020-12-26 13:53 new modules execve, execvpe, execvp, execv, execl, execle, execlp Bruno Haible
@ 2020-12-27 11:15 ` Jeffrey Walton
  2020-12-27 12:19   ` Apple embedded OSes Bruno Haible
  0 siblings, 1 reply; 4+ messages in thread
From: Jeffrey Walton @ 2020-12-27 11:15 UTC (permalink / raw)
  To: Bruno Haible; +Cc: bug-gnulib@gnu.org List

On Sat, Dec 26, 2020 at 8:53 AM Bruno Haible <bruno@clisp.org> wrote:
>
> ...
> All of these problems are fixed with these new Gnulib modules.
>

Just an FYI in case you have not hit this wall (yet?)... The exec
family, posix_spawn and friends are _not_ available on all Apple
platforms. Be sure to check availability before using them.

For example, the iPhone/iPad SDKs has them, but the WatchOS and TvOS
SDKs lack them. To further complicate matters, you have to include
<TargetConditionals.h> before you can check for the SDK.

Here's what unbound does in libunbound/libworker.c
(https://github.com/NLnetLabs/unbound/blob/master/libunbound/libworker.c)

#ifdef HAVE_TARGETCONDITIONALS_H
#include <TargetConditionals.h>
#endif

#if (defined(TARGET_OS_TV) && TARGET_OS_TV) ||
(defined(TARGET_OS_WATCH) && TARGET_OS_WATCH)
#  undef HAVE_FORK
#endif

Jeff


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: Apple embedded OSes
  2020-12-27 11:15 ` Jeffrey Walton
@ 2020-12-27 12:19   ` Bruno Haible
  2020-12-27 19:08     ` Jeffrey Walton
  0 siblings, 1 reply; 4+ messages in thread
From: Bruno Haible @ 2020-12-27 12:19 UTC (permalink / raw)
  To: noloader; +Cc: bug-gnulib

Hi Jeffrey,

> Just an FYI in case you have not hit this wall (yet?)... The exec
> family, posix_spawn and friends are _not_ available on all Apple
> platforms. Be sure to check availability before using them.
> 
> For example, the iPhone/iPad SDKs has them, but the WatchOS and TvOS
> SDKs lack them. To further complicate matters, you have to include
> <TargetConditionals.h> before you can check for the SDK.

There are 3 questions:

1) Do you think it is technically possible to support the iOS variants
   in Gnulib?

2) Do you think it makes sense for the GNU project to support the iOS
   variants?

3) Do you think we need to document that Gnulib doesn't support the iOS
   variants?

My take on these questions would be:

1) For an OS that does not have files with file names, it's pointless to
   even think about open(), exec(), and so on.

2) Anyone buying and using these devices has surrendered their entire
   freedom and privacy to Apple. There is no point for GNU to help make
   these devices more widely spread by porting software to it.

3) I would think that the communities of POSIX / C users and iOS / Swift
   users are disjoint. Hence no need to document.

Your take?

Bruno



^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: Apple embedded OSes
  2020-12-27 12:19   ` Apple embedded OSes Bruno Haible
@ 2020-12-27 19:08     ` Jeffrey Walton
  0 siblings, 0 replies; 4+ messages in thread
From: Jeffrey Walton @ 2020-12-27 19:08 UTC (permalink / raw)
  To: Bruno Haible; +Cc: bug-gnulib@gnu.org List

On Sun, Dec 27, 2020 at 7:20 AM Bruno Haible <bruno@clisp.org> wrote:
>
> Hi Jeffrey,
>
> > Just an FYI in case you have not hit this wall (yet?)... The exec
> > family, posix_spawn and friends are _not_ available on all Apple
> > platforms. Be sure to check availability before using them.
> >
> > For example, the iPhone/iPad SDKs has them, but the WatchOS and TvOS
> > SDKs lack them. To further complicate matters, you have to include
> > <TargetConditionals.h> before you can check for the SDK.
>
> There are 3 questions:
>
> 1) Do you think it is technically possible to support the iOS variants
>    in Gnulib?

I think Yes, it is technically feasible in most instances.

I think initial support can simply be recognizing the problem
platforms and disabling code paths or returning ENOSYS (not
implemented).

I believe Apple wants folks to use NSTask or NSThread on AppleTV and
AppleWatch. So there is an upgrade path for those who are initiated.

> 2) Do you think it makes sense for the GNU project to support the iOS
>    variants?

Well, I think iOS is one of the most popular platforms, so it would be
wise to try to support it.

Android has about 70% mobile market share, and iOS has about 28%
mobile market share. I don't know the breakdown of iOS variants. But
28% is non-trivial, so I would try to support it.
https://gs.statcounter.com/os-market-share/mobile/worldwide.

iPhone and iPads should cause the least pain because they mostly
behave like you expect. Gnulib and other GNU projects already support
them.

AppleTV and AppleWatch can be more painful because they are crippled.
SOme programs and libraries won't have any problems. For those who are
using a missing function, maybe initial support for them can be a
replacement posix_spawn that simply returns ENOSYS.

> 3) Do you think we need to document that Gnulib doesn't support the iOS
>    variants?

Yes. It is a sharp edge. I imagine developers searching for "Gnulib
posix_spawn iOS" or "Gnulib posix_spawn AppleTV" to see what is going
on when they encounter a compile error.

> My take on these questions would be:
>
> 1) For an OS that does not have files with file names, it's pointless to
>    even think about open(), exec(), and so on.

For AppleTV and AppleWatch, I believe the crippled-ness is limited to
forking a new process. That's why posix_spawn and the exec family are
missing.

I think you will be OK with the other operations, like file or socket ops.

What I have found in practice is, the test suites have the most
trouble because developers fork a server to test something related to
a socket. The libraries and programs ported to AppleTV and AppleWatch
are usually OK.

> 2) Anyone buying and using these devices has surrendered their entire
>    freedom and privacy to Apple. There is no point for GNU to help make
>    these devices more widely spread by porting software to it.

Yeah, I'm not a big fan of Apple either. I stopped joining their
Developer Program years ago when they started forcing people into
their iCloud and wanted folks to indemnify their officers. Buy a
fucking insurance policy if you want indemnification...

I now support Apple platforms to poke Apple in the eye. Anything I can
do to make free software a better alternative is usually a high
priority for me.

> 3) I would think that the communities of POSIX / C users and iOS / Swift
>    users are disjoint. Hence no need to document.

Yeah, I would document it for users. Documentation is cheap.

The groups may be disjoint, but there's no sense in penalizing an iOS
user because of what Apple does. At least let iOS users know there are
technical limitations behind the lack of full support.

Jeff


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2020-12-27 19:09 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-12-26 13:53 new modules execve, execvpe, execvp, execv, execl, execle, execlp Bruno Haible
2020-12-27 11:15 ` Jeffrey Walton
2020-12-27 12:19   ` Apple embedded OSes Bruno Haible
2020-12-27 19:08     ` Jeffrey Walton

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).