execvpe: New module.
authorBruno Haible <bruno@clisp.org>
Sat, 26 Dec 2020 13:23:10 +0000 (14:23 +0100)
committerBruno Haible <bruno@clisp.org>
Sat, 26 Dec 2020 13:23:10 +0000 (14:23 +0100)
* 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
doc/glibc-functions/execvpe.texi
lib/execvpe.c [new file with mode: 0644]
m4/execvpe.m4 [new file with mode: 0644]
modules/execvpe [new file with mode: 0644]

index f6795fb9d71c99a863d98aa8bd5cf434d0912055..7a9e5fb9fdf8aa906d0148ce484b73aa66c31f03 100644 (file)
--- 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.
index 814b16031e56d8c754e09fda93cb66bec070b34c..04ac54a3c170ddbe633c76c95d471ef72eb876ae 100644 (file)
@@ -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 (file)
index 0000000..7bc369d
--- /dev/null
@@ -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 (file)
index 0000000..bfce909
--- /dev/null
@@ -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 (file)
index 0000000..792a2c7
--- /dev/null
@@ -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