On MSVC 9, there is no popen() function, only _popen. The replacement code in lib/popen.c is not made for this situation: it gives compilation errors about F_SETFD. This fixes it.
2011-09-17 Bruno Haible <[email protected]> popen: Support for MSVC. * lib/stdio.in.h (popen): Declare it if the system lacks this function. * lib/popen.c (popen): Provide alternate definition for native Windows. * m4/popen.m4 (gl_FUNC_POPEN): Test if popen exists. Set HAVE_POPEN. * m4/stdio_h.m4 (gl_STDIO_H_DEFAULTS): Initialize HAVE_POPEN. * modules/popen (Depends-on, configure.ac): Update condition. * modules/stdio (Makefile.am): Substitute HAVE_POPEN. * doc/posix-functions/popen.texi: Mention that the MSVC problem is fixed. --- doc/posix-functions/popen.texi.orig Sat Sep 17 18:22:52 2011 +++ doc/posix-functions/popen.texi Sat Sep 17 18:05:06 2011 @@ -9,6 +9,9 @@ Portability problems fixed by Gnulib: @itemize @item +This function is missing on some platforms: +MSVC 9. +@item Some platforms start the child with closed stdin or stdout if the standard descriptors were closed in the parent: Cygwin 1.5.x. @@ -17,9 +20,6 @@ Portability problems not fixed by Gnulib: @itemize @item -This function is missing on some platforms: -MSVC 9. -@item Some platforms mistakenly set the close-on-exec bit, then if it is cleared by the application, the platform then leaks file descriptors from earlier @code{popen} calls into subsequent @code{popen} children: --- lib/popen.c.orig Sat Sep 17 18:22:52 2011 +++ lib/popen.c Sat Sep 17 18:19:10 2011 @@ -21,12 +21,14 @@ /* Specification. */ #include <stdio.h> -#include <errno.h> -#include <fcntl.h> -#include <stdlib.h> -#include <unistd.h> +#if HAVE_POPEN -#undef popen +# include <errno.h> +# include <fcntl.h> +# include <stdlib.h> +# include <unistd.h> + +# undef popen FILE * rpl_popen (const char *filename, const char *mode) @@ -80,3 +82,22 @@ errno = saved_errno; return result; } + +#else +/* Native Woe32 API. */ + +# include <string.h> + +FILE * +popen (const char *filename, const char *mode) +{ + /* Use binary mode by default. */ + if (strcmp (mode, "r") == 0) + mode = "rb"; + else if (strcmp (mode, "w") == 0) + mode = "wb"; + + return _popen (filename, mode); +} + +#endif --- lib/stdio.in.h.orig Sat Sep 17 18:22:52 2011 +++ lib/stdio.in.h Sat Sep 17 18:07:45 2011 @@ -781,6 +781,10 @@ _GL_ARG_NONNULL ((1, 2))); _GL_CXXALIAS_RPL (popen, FILE *, (const char *cmd, const char *mode)); # else +# if !@HAVE_POPEN@ +_GL_FUNCDECL_SYS (popen, FILE *, (const char *cmd, const char *mode) + _GL_ARG_NONNULL ((1, 2))); +# endif _GL_CXXALIAS_SYS (popen, FILE *, (const char *cmd, const char *mode)); # endif _GL_CXXALIASWARN (popen); --- m4/popen.m4.orig Sat Sep 17 18:22:52 2011 +++ m4/popen.m4 Sat Sep 17 18:10:30 2011 @@ -1,4 +1,4 @@ -# popen.m4 serial 4 +# popen.m4 serial 5 dnl Copyright (C) 2009-2011 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -7,26 +7,35 @@ AC_DEFUN([gl_FUNC_POPEN], [ AC_REQUIRE([gl_STDIO_H_DEFAULTS]) - AC_CACHE_CHECK([whether popen works with closed stdin], - [gl_cv_func_popen_works], - [ - AC_RUN_IFELSE([AC_LANG_PROGRAM([[#include <stdio.h> -]], [int result = 0; - FILE *child; - fclose (stdin); - fclose (stdout); - child = popen ("echo a", "r"); - if (fgetc (child) != 'a') - result |= 1; - if (pclose (child) != 0) - result |= 2; - return result; -])], [gl_cv_func_popen_works=yes], [gl_cv_func_popen_works=no], - dnl For now, only cygwin 1.5 or older is known to be broken. - [gl_cv_func_popen_works='guessing yes']) - ]) - if test "$gl_cv_func_popen_works" = no; then - REPLACE_POPEN=1 + AC_CHECK_FUNCS_ONCE([popen]) + if test $ac_cv_func_popen = no; then + HAVE_POPEN=0 + else + AC_CACHE_CHECK([whether popen works with closed stdin], + [gl_cv_func_popen_works], + [ + AC_RUN_IFELSE( + [AC_LANG_PROGRAM( + [[#include <stdio.h>]], + [[int result = 0; + FILE *child; + fclose (stdin); + fclose (stdout); + child = popen ("echo a", "r"); + if (fgetc (child) != 'a') + result |= 1; + if (pclose (child) != 0) + result |= 2; + return result; + ]])], + [gl_cv_func_popen_works=yes], + [gl_cv_func_popen_works=no], + dnl For now, only cygwin 1.5 or older is known to be broken. + [gl_cv_func_popen_works='guessing yes']) + ]) + if test "$gl_cv_func_popen_works" = no; then + REPLACE_POPEN=1 + fi fi ]) --- m4/stdio_h.m4.orig Sat Sep 17 18:22:52 2011 +++ m4/stdio_h.m4 Sat Sep 17 18:06:08 2011 @@ -1,4 +1,4 @@ -# stdio_h.m4 serial 37 +# stdio_h.m4 serial 38 dnl Copyright (C) 2007-2011 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -153,6 +153,7 @@ HAVE_DPRINTF=1; AC_SUBST([HAVE_DPRINTF]) HAVE_FSEEKO=1; AC_SUBST([HAVE_FSEEKO]) HAVE_FTELLO=1; AC_SUBST([HAVE_FTELLO]) + HAVE_POPEN=1; AC_SUBST([HAVE_POPEN]) HAVE_RENAMEAT=1; AC_SUBST([HAVE_RENAMEAT]) HAVE_VASPRINTF=1; AC_SUBST([HAVE_VASPRINTF]) HAVE_VDPRINTF=1; AC_SUBST([HAVE_VDPRINTF]) --- modules/popen.orig Sat Sep 17 18:22:52 2011 +++ modules/popen Sat Sep 17 18:05:30 2011 @@ -7,11 +7,11 @@ Depends-on: stdio -open [test $REPLACE_POPEN = 1] +open [test $HAVE_POPEN = 0 || $REPLACE_POPEN = 1] configure.ac: gl_FUNC_POPEN -if test $REPLACE_POPEN = 1; then +if test $HAVE_POPEN = 0 || $REPLACE_POPEN = 1; then AC_LIBOBJ([popen]) gl_PREREQ_POPEN fi --- modules/stdio.orig Sat Sep 17 18:22:52 2011 +++ modules/stdio Sat Sep 17 18:11:33 2011 @@ -93,6 +93,7 @@ -e 's|@''HAVE_DPRINTF''@|$(HAVE_DPRINTF)|g' \ -e 's|@''HAVE_FSEEKO''@|$(HAVE_FSEEKO)|g' \ -e 's|@''HAVE_FTELLO''@|$(HAVE_FTELLO)|g' \ + -e 's|@''HAVE_POPEN''@|$(HAVE_POPEN)|g' \ -e 's|@''HAVE_RENAMEAT''@|$(HAVE_RENAMEAT)|g' \ -e 's|@''HAVE_VASPRINTF''@|$(HAVE_VASPRINTF)|g' \ -e 's|@''HAVE_VDPRINTF''@|$(HAVE_VDPRINTF)|g' \ -- In memoriam Estella Agsteribbe <http://en.wikipedia.org/wiki/Estella_Agsteribbe>
