From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on dcvr.yhbt.net X-Spam-Level: X-Spam-Status: No, score=-2.6 required=3.0 tests=AWL,BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,LONGWORDS,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED,RCVD_IN_MSPIKE_H4,RCVD_IN_MSPIKE_WL,SPF_HELO_PASS, SPF_PASS shortcircuit=no autolearn=no autolearn_force=no version=3.4.2 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dcvr.yhbt.net (Postfix) with ESMTPS id 1533D1F4B4 for ; Sat, 26 Dec 2020 13:53:56 +0000 (UTC) Received: from localhost ([::1]:48924 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ktA14-0007V7-Og for normalperson@yhbt.net; Sat, 26 Dec 2020 08:53:54 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:50030) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ktA11-0007V0-3C for bug-gnulib@gnu.org; Sat, 26 Dec 2020 08:53:51 -0500 Received: from mo4-p00-ob.smtp.rzone.de ([81.169.146.217]:34101) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ktA0s-0003ts-V1; Sat, 26 Dec 2020 08:53:50 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; t=1608990819; s=strato-dkim-0002; d=clisp.org; h=Message-ID:Date:Subject:Cc:To:From:From:Subject:Sender; bh=4PRk6ARYAS/+RL5TUJI2Ol6yF6RxWnrmNrDnsh6GA14=; b=A0STcM8BnKIj6ZbueKqJMu1vwK8CpUW/WEKnu9m3+X1v/LJraWL8wspG4h4+KT1cam ye6pZJ+PszAevKTwAHHWaBLkYR0YkHaFPJhlGZ0XQoyRNSZCaKu+vrG4gYGk/gYsTgeU +t2UN8zZb8tz9xdyzLeQIzvfjMjfjxEURksuFGm3mNDOfrQuH/bssng2Zn4aPnqVFHNf XVeCaaXw8pI7kKosQdq3f8I5C+G8TrUYYPvrgKSaXxlyMOW533lHqrbA0D3fiTgU5O9a 4N2nV7h9UoL3gQOY3VqDS1zsA3MyI3+gfYazlmbJuaMydoL9APx+Ee+IuB8+GaJt+FWe u1yQ== X-RZG-AUTH: ":Ln4Re0+Ic/6oZXR1YgKryK8brlshOcZlIWs+iCP5vnk6shH+AHjwLuWOHqfzyPs=" X-RZG-CLASS-ID: mo00 Received: from bruno.haible.de by smtp.strato.de (RZmta 47.10.7 DYNA|AUTH) with ESMTPSA id e012d5wBQDrb6jG (using TLSv1 with cipher ECDHE-RSA-AES256-SHA (curve X9_62_prime256v1 with 256 ECDH bits, eq. 3072 bits RSA)) (Client did not present a certificate); Sat, 26 Dec 2020 14:53:37 +0100 (CET) From: Bruno Haible To: bug-gnulib@gnu.org Subject: new modules execve, execvpe, execvp, execv, execl, execle, execlp Date: Sat, 26 Dec 2020 14:53:36 +0100 Message-ID: <19625603.TXvseGJZxX@omega> User-Agent: KMail/5.1.3 (Linux/4.4.0-197-generic; KDE/5.18.0; x86_64; ; ) MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="nextPart4282994.057l8VpAd0" Content-Transfer-Encoding: 7Bit Received-SPF: none client-ip=81.169.146.217; envelope-from=bruno@clisp.org; helo=mo4-p00-ob.smtp.rzone.de X-Spam_score_int: 0 X-Spam_score: -0.1 X-Spam_bar: / X-Spam_report: (-0.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, LONGWORDS=2.035, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_PASS=-0.001, SPF_NONE=0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: bug-gnulib@gnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Gnulib discussion list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Eli Zaretskii Errors-To: bug-gnulib-bounces+normalperson=yhbt.net@gnu.org Sender: "bug-gnulib" This is a multi-part message in MIME format. --nextPart4282994.057l8VpAd0 Content-Transfer-Encoding: 7Bit Content-Type: text/plain; charset="us-ascii" Eli Zaretskii wrote in : ... 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 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. --nextPart4282994.057l8VpAd0 Content-Disposition: attachment; filename="0001-execve-execvpe-execvp-execv-execl-execle-execlp-Prep.patch" Content-Transfer-Encoding: 7Bit Content-Type: text/x-patch; charset="UTF-8"; name="0001-execve-execvpe-execvp-execv-execl-execle-execlp-Prep.patch" >From ba3aeabdd5317c3e21d1da54577235a054ce60f3 Mon Sep 17 00:00:00 2001 From: Bruno Haible 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 + 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 + 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 --nextPart4282994.057l8VpAd0 Content-Disposition: attachment; filename="0002-execve-New-module.patch" Content-Transfer-Encoding: 7Bit Content-Type: text/x-patch; charset="UTF-8"; name="0002-execve-New-module.patch" >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 --nextPart4282994.057l8VpAd0 Content-Disposition: attachment; filename="0003-execve-Add-tests.patch" Content-Transfer-Encoding: 7Bit Content-Type: text/x-patch; charset="UTF-8"; name="0003-execve-Add-tests.patch" >From c24b5cc4a8ff7e858ad7bc019a6e112a292fe468 Mon Sep 17 00:00:00 2001 From: Bruno Haible 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 + 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 . */ + +#include + +#include +#include + +/* 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 . */ + +/* Written by Bruno Haible , 2020. */ + +#include + +/* Specification. */ +#include + +#include "signature.h" +SIGNATURE_CHECK (execve, int, (const char *, char * const *, char * const *)); + +#include + +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 . */ +# +# Written by Bruno Haible , 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 --nextPart4282994.057l8VpAd0 Content-Disposition: attachment; filename="0004-execvpe-New-module.patch" Content-Transfer-Encoding: 7Bit Content-Type: text/x-patch; charset="UTF-8"; name="0004-execvpe-New-module.patch" >From a50484eb14bf2c2a8dc420ba2ad037fd85f9c739 Mon Sep 17 00:00:00 2001 From: Bruno Haible 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 + 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 . */ + +/* 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 + +#include +#include + +#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 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: + + +License: +LGPLv2+ + +Maintainer: +all -- 2.7.4 --nextPart4282994.057l8VpAd0 Content-Disposition: attachment; filename="0005-execvpe-Add-tests.patch" Content-Transfer-Encoding: 7Bit Content-Type: text/x-patch; charset="UTF-8"; name="0005-execvpe-Add-tests.patch" >From 7c170cbc17521f6eb0199e78fcd18d8dddbb12b4 Mon Sep 17 00:00:00 2001 From: Bruno Haible 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 + 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 . */ + +/* Written by Bruno Haible , 2020. */ + +#include + +/* Specification. */ +#include + +#include "signature.h" +SIGNATURE_CHECK (execvpe, int, (const char *, char * const *, char * const *)); + +#include + +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 . */ +# +# Written by Bruno Haible , 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 --nextPart4282994.057l8VpAd0 Content-Disposition: attachment; filename="0006-execvp-New-module.patch" Content-Transfer-Encoding: 7Bit Content-Type: text/x-patch; charset="UTF-8"; name="0006-execvp-New-module.patch" >From 0e3778b00c4e4705cccec9261ef36c66c400e1fe Mon Sep 17 00:00:00 2001 From: Bruno Haible 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 + 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 . */ + +/* Written by Bruno Haible , 2020. */ + +#include + +/* Specification. */ +#include + +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: + + +License: +LGPLv2+ + +Maintainer: +all -- 2.7.4 --nextPart4282994.057l8VpAd0 Content-Disposition: attachment; filename="0007-execvp-Add-tests.patch" Content-Transfer-Encoding: 7Bit Content-Type: text/x-patch; charset="UTF-8"; name="0007-execvp-Add-tests.patch" >From b7f8be836643b720a0d9207fe0927889dd8b3b2b Mon Sep 17 00:00:00 2001 From: Bruno Haible 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 + 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 . */ + +/* Written by Bruno Haible , 2020. */ + +#include + +/* Specification. */ +#include + +#include "signature.h" +SIGNATURE_CHECK (execvp, int, (const char *, char * const *)); + +#include + +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 . */ +# +# Written by Bruno Haible , 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 --nextPart4282994.057l8VpAd0 Content-Disposition: attachment; filename="0008-execv-New-module.patch" Content-Transfer-Encoding: 7Bit Content-Type: text/x-patch; charset="UTF-8"; name="0008-execv-New-module.patch" >From 58ef9c2d18f3c158ff42cd3b7297f9e9bbc74738 Mon Sep 17 00:00:00 2001 From: Bruno Haible 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 + 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 . */ + +/* Written by Bruno Haible , 2020. */ + +#include + +/* Specification. */ +#include + +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: + + +License: +LGPLv2+ + +Maintainer: +all -- 2.7.4 --nextPart4282994.057l8VpAd0 Content-Disposition: attachment; filename="0009-execv-Add-tests.patch" Content-Transfer-Encoding: 7Bit Content-Type: text/x-patch; charset="UTF-8"; name="0009-execv-Add-tests.patch" >From 46c14c901d0a9b3aff27b9b3dde802e0a1c98bea Mon Sep 17 00:00:00 2001 From: Bruno Haible 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 + 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 . */ + +/* Written by Bruno Haible , 2020. */ + +#include + +/* Specification. */ +#include + +#include "signature.h" +SIGNATURE_CHECK (execv, int, (const char *, char * const *)); + +#include + +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 . */ +# +# Written by Bruno Haible , 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 --nextPart4282994.057l8VpAd0 Content-Disposition: attachment; filename="0010-execl-New-module.patch" Content-Transfer-Encoding: 7Bit Content-Type: text/x-patch; charset="UTF-8"; name="0010-execl-New-module.patch" >From 7fbf62ebb9e7466a157b5f339d15ff1d11b18d45 Mon Sep 17 00:00:00 2001 From: Bruno Haible 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 + 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 . */ + +/* Written by Bruno Haible , 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 + +/* Specification. */ +#include + +#include +#include + +#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: + + +License: +LGPLv2+ + +Maintainer: +all -- 2.7.4 --nextPart4282994.057l8VpAd0 Content-Disposition: attachment; filename="0011-execl-Add-tests.patch" Content-Transfer-Encoding: 7Bit Content-Type: text/x-patch; charset="UTF-8"; name="0011-execl-Add-tests.patch" >From 614b2e6c98172bdcc96ca735f4e14056dc32e59c Mon Sep 17 00:00:00 2001 From: Bruno Haible 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 + 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 . */ + +/* Written by Bruno Haible , 2020. */ + +#include + +/* Specification. */ +#include + +#include "signature.h" +SIGNATURE_CHECK (execl, int, (const char *, const char *, ...)); + +#include + +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 . */ +# +# Written by Bruno Haible , 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 --nextPart4282994.057l8VpAd0 Content-Disposition: attachment; filename="0012-execle-New-module.patch" Content-Transfer-Encoding: 7Bit Content-Type: text/x-patch; charset="UTF-8"; name="0012-execle-New-module.patch" >From 6b1f82435bc2f900429b711d90e25857d817eafe Mon Sep 17 00:00:00 2001 From: Bruno Haible 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 + 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 . */ + +/* Written by Bruno Haible , 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 + +/* Specification. */ +#include + +#include +#include + +#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: + + +License: +LGPLv2+ + +Maintainer: +all -- 2.7.4 --nextPart4282994.057l8VpAd0 Content-Disposition: attachment; filename="0013-execle-Add-tests.patch" Content-Transfer-Encoding: 7Bit Content-Type: text/x-patch; charset="UTF-8"; name="0013-execle-Add-tests.patch" >From b42620e8d20cfcb5d18f452a38aa05500d3ada35 Mon Sep 17 00:00:00 2001 From: Bruno Haible 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 + 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 . */ + +/* Written by Bruno Haible , 2020. */ + +#include + +/* Specification. */ +#include + +#include "signature.h" +SIGNATURE_CHECK (execle, int, (const char *, const char *, ...)); + +#include + +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 . */ +# +# Written by Bruno Haible , 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 --nextPart4282994.057l8VpAd0 Content-Disposition: attachment; filename="0014-execlp-New-module.patch" Content-Transfer-Encoding: 7Bit Content-Type: text/x-patch; charset="UTF-8"; name="0014-execlp-New-module.patch" >From 761c7c948d36f58357e50913fd14b94a42e9ae14 Mon Sep 17 00:00:00 2001 From: Bruno Haible 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 + 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 . */ + +/* Written by Bruno Haible , 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 + +/* Specification. */ +#include + +#include +#include + +#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: + + +License: +LGPLv2+ + +Maintainer: +all -- 2.7.4 --nextPart4282994.057l8VpAd0 Content-Disposition: attachment; filename="0015-execlp-Add-tests.patch" Content-Transfer-Encoding: 7Bit Content-Type: text/x-patch; charset="UTF-8"; name="0015-execlp-Add-tests.patch" >From 8e5c999bce06f3d09c27c40e82b1527592dfa41c Mon Sep 17 00:00:00 2001 From: Bruno Haible 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 + 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 . */ + +/* Written by Bruno Haible , 2020. */ + +#include + +/* Specification. */ +#include + +#include "signature.h" +SIGNATURE_CHECK (execlp, int, (const char *, const char *, ...)); + +#include + +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 . */ +# +# Written by Bruno Haible , 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 --nextPart4282994.057l8VpAd0--