From 54a1ab447fc79ed0f817e6b8e140ac2fd49b6e62 Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Mon, 2 Mar 2009 06:54:28 -0700 Subject: Use gnulib pipe module instead of popen(3). * ltdl/m4/gnulib-cache.m4: Import pipe and wait-process modules. * modules/gnu.c (M4_SYSVAL_EXITBITS, M4_SYSVAL_TERMSIGBITS): Delete. (esyscmd): Rewrite with pipe module. Resolves a failure on AIX, reported by Gary V. Vaughan. Signed-off-by: Eric Blake (cherry picked from commit 9915ef54d55fae837209bc87d35c777715653bed) --- ChangeLog | 7 +++ ltdl/m4/gnulib-cache.m4 | 4 +- modules/gnu.c | 122 +++++++++++++++++++++++++----------------------- 3 files changed, 73 insertions(+), 60 deletions(-) diff --git a/ChangeLog b/ChangeLog index 13c88952..b5f6487a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,12 @@ 2009-03-13 Eric Blake + Use gnulib pipe module instead of popen(3). + * ltdl/m4/gnulib-cache.m4: Import pipe and wait-process modules. + * modules/gnu.c (M4_SYSVAL_EXITBITS, M4_SYSVAL_TERMSIGBITS): + Delete. + (esyscmd): Rewrite with pipe module. + Resolves a failure on AIX, reported by Gary V. Vaughan. + Use gnulib execute module instead of system(3). * ltdl/m4/gnulib-cache.m4: Import execute module. * m4/utility.c (m4_info_name): New function. diff --git a/ltdl/m4/gnulib-cache.m4 b/ltdl/m4/gnulib-cache.m4 index 050fff45..9e664dab 100644 --- a/ltdl/m4/gnulib-cache.m4 +++ b/ltdl/m4/gnulib-cache.m4 @@ -15,7 +15,7 @@ # Specification in the form of a command-line invocation: -# gnulib-tool --import --dir=. --local-dir=local --lib=libgnu --source-base=gnu --m4-base=ltdl/m4 --doc-base=doc --tests-base=tests/gnu --aux-dir=build-aux --with-tests --libtool --macro-prefix=M4 assert autobuild avltree-oset binary-io clean-temp cloexec close-stream closein config-h configmake dirname error execute exit fdl-1.3 fflush filenamecat flexmember fopen fopen-safer freadptr freadseek fseeko gendocs gettext git-version-gen gnumakefile gnupload gpl-3.0 intprops memchr2 memmem mkstemp obstack obstack-printf-posix progname propername quote regex regexprops-generic sprintf-posix stdbool stdlib-safer strnlen strtod strtol tempname unlocked-io vasnprintf-posix verify verror xalloc xalloc-die xmemdup0 xprintf-posix xstrndup xvasprintf-posix +# gnulib-tool --import --dir=. --local-dir=local --lib=libgnu --source-base=gnu --m4-base=ltdl/m4 --doc-base=doc --tests-base=tests/gnu --aux-dir=build-aux --with-tests --libtool --macro-prefix=M4 assert autobuild avltree-oset binary-io clean-temp cloexec close-stream closein config-h configmake dirname error execute exit fdl-1.3 fflush filenamecat flexmember fopen fopen-safer freadptr freadseek fseeko gendocs gettext git-version-gen gnumakefile gnupload gpl-3.0 intprops memchr2 memmem mkstemp obstack obstack-printf-posix pipe progname propername quote regex regexprops-generic sprintf-posix stdbool stdlib-safer strnlen strtod strtol tempname unlocked-io vasnprintf-posix verify verror wait-process xalloc xalloc-die xmemdup0 xprintf-posix xstrndup xvasprintf-posix # Specification in the form of a few gnulib-tool.m4 macro invocations: gl_LOCAL_DIR([local]) @@ -55,6 +55,7 @@ gl_MODULES([ mkstemp obstack obstack-printf-posix + pipe progname propername quote @@ -71,6 +72,7 @@ gl_MODULES([ vasnprintf-posix verify verror + wait-process xalloc xalloc-die xmemdup0 diff --git a/modules/gnu.c b/modules/gnu.c index 122e9669..e833f552 100644 --- a/modules/gnu.c +++ b/modules/gnu.c @@ -28,10 +28,10 @@ # include "m4private.h" #endif -#include - #include "modules/m4.h" +#include "pipe.h" #include "quotearg.h" +#include "wait-process.h" /* Rename exported symbols for dlpreload()ing. */ #define m4_builtin_table gnu_LTX_m4_builtin_table @@ -639,35 +639,8 @@ M4BUILTIN_HANDLER (debugmode) } -/* Helper macros for readability. */ -#if UNIX || defined WEXITSTATUS -# define M4_SYSVAL_EXITBITS(status) \ - (WIFEXITED (status) ? WEXITSTATUS (status) : 0) -# define M4_SYSVAL_TERMSIGBITS(status) \ - (WIFSIGNALED (status) ? WTERMSIG (status) << 8 : 0) - -#else /* !UNIX && !defined WEXITSTATUS */ -/* Platforms such as mingw do not support the notion of reporting - which signal terminated a process. Furthermore if WEXITSTATUS was - not provided, then the exit value is in the low eight bits. */ -# define M4_SYSVAL_EXITBITS(status) status -# define M4_SYSVAL_TERMSIGBITS(status) 0 -#endif /* !UNIX && !defined WEXITSTATUS */ - -/* Fallback definitions if or are inadequate. */ -/* FIXME - this may fit better as a gnulib module. */ -#ifndef WEXITSTATUS -# define WEXITSTATUS(status) (((status) >> 8) & 0xff) -#endif -#ifndef WTERMSIG -# define WTERMSIG(status) ((status) & 0x7f) -#endif -#ifndef WIFSIGNALED -# define WIFSIGNALED(status) (WTERMSIG (status) != 0) -#endif -#ifndef WIFEXITED -# define WIFEXITED(status) (WTERMSIG (status) == 0) -#endif +/* FIXME */ +#define SYSCMD_SHELL "/bin/sh" /* Same as the sysymd builtin from m4.c module, but expand to the output of SHELL-COMMAND. */ @@ -686,7 +659,14 @@ M4BUILTIN_HANDLER (esyscmd) if (m4_set_sysval && m4_sysval_flush) { + pid_t child; + int fd; FILE *pin; + int status; + int sig_status; + const char *prog_args[4] = { "sh", "-c" }; + const char *caller; + const char *shell = SYSCMD_SHELL; if (m4_get_safer_opt (context)) { @@ -705,42 +685,66 @@ M4BUILTIN_HANDLER (esyscmd) } m4_sysval_flush (context, false); +#if W32_NATIVE + shell = prog_args[0] = "cmd"; + prog_args[1] = "/c"; +#endif + prog_args[2] = cmd; + caller = m4_info_name (me); errno = 0; - pin = popen (cmd, "r"); - if (pin == NULL) + child = create_pipe_in (caller, shell/*FIXME*/, (char **) prog_args, + NULL, false, true, false, &fd); + if (child == -1) { - m4_error (context, 0, errno, me, - _("cannot run command %s"), + m4_error (context, 0, errno, me, _("cannot run command %s"), quotearg_style (locale_quoting_style, cmd)); m4_set_sysval (127); + return; } - else + pin = fdopen (fd, "r"); + if (!pin) { - while (1) + m4_error (context, 0, errno, me, _("cannot run command %s"), + quotearg_style (locale_quoting_style, cmd)); + m4_set_sysval (127); + close (fd); + return; + } + while (1) + { + size_t avail = obstack_room (obs); + if (!avail) + { + int ch = getc (pin); + if (ch == EOF) + break; + obstack_1grow (obs, ch); + } + else { - size_t avail = obstack_room (obs); - if (!avail) - { - int ch = getc (pin); - if (ch == EOF) - break; - obstack_1grow (obs, ch); - } - else - { - size_t len = fread (obstack_next_free (obs), 1, avail, pin); - if (len <= 0) - break; - obstack_blank_fast (obs, len); - } + size_t len = fread (obstack_next_free (obs), 1, avail, pin); + if (len <= 0) + break; + obstack_blank_fast (obs, len); } - if (ferror (pin)) - m4_warn (context, errno, me, _("cannot read pipe to command %s"), - quotearg_style (locale_quoting_style, cmd)); - int result = pclose (pin); - m4_set_sysval (result == -1 ? 127 - : (M4_SYSVAL_EXITBITS (result) - | M4_SYSVAL_TERMSIGBITS (result))); + } + if (ferror (pin) || fclose (pin)) + m4_error (context, EXIT_FAILURE, errno, me, + _("cannot read pipe to command %s"), + quotearg_style (locale_quoting_style, cmd)); + status = wait_subprocess (child, caller, false, false, true, false, + &sig_status); + if (sig_status) + { + assert (status == 127); + m4_set_sysval (sig_status << 8); + } + else + { + if (status == 127 && errno) + m4_error (context, 0, errno, me, _("cannot run command %s"), + quotearg_style (locale_quoting_style, cmd)); + m4_set_sysval (status); } } else -- cgit v1.2.1