>From e8f57867dc5c05e7354576df19f1151ae9cb9fbb Mon Sep 17 00:00:00 2001 From: Bruno Haible 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 + 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 . */ + +/* Written by Bruno Haible , 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 + +/* Specification. */ +#include + +#if defined _WIN32 && !defined __CYGWIN__ + +# include +# include +# include + +# include +# include + +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: + + +License: +LGPLv2+ + +Maintainer: +all -- 2.7.4