From: Bruno Haible <bruno@clisp.org>
To: bug-gnulib@gnu.org
Cc: Eli Zaretskii <eliz@gnu.org>
Subject: new modules execve, execvpe, execvp, execv, execl, execle, execlp
Date: Sat, 26 Dec 2020 14:53:36 +0100 [thread overview]
Message-ID: <19625603.TXvseGJZxX@omega> (raw)
[-- 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
next reply other threads:[~2020-12-26 13:53 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-12-26 13:53 Bruno Haible [this message]
2020-12-27 11:15 ` new modules execve, execvpe, execvp, execv, execl, execle, execlp Jeffrey Walton
2020-12-27 12:19 ` Apple embedded OSes Bruno Haible
2020-12-27 19:08 ` Jeffrey Walton
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://lists.gnu.org/mailman/listinfo/bug-gnulib
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=19625603.TXvseGJZxX@omega \
--to=bruno@clisp.org \
--cc=bug-gnulib@gnu.org \
--cc=eliz@gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).