diff options
-rw-r--r-- | gl/Makefile.am | 2 | ||||
-rw-r--r-- | gl/m4/stdio_h.m4 | 4 | ||||
-rw-r--r-- | gl/select.c | 67 | ||||
-rw-r--r-- | gl/stdio.in.h | 14 | ||||
-rw-r--r-- | lib/gl/Makefile.am | 2 | ||||
-rw-r--r-- | lib/gl/m4/stdio_h.m4 | 4 | ||||
-rw-r--r-- | lib/gl/stdio.in.h | 14 | ||||
-rw-r--r-- | maint.mk | 3 |
8 files changed, 96 insertions, 14 deletions
diff --git a/gl/Makefile.am b/gl/Makefile.am index 1c21e7d450..10f61377f9 100644 --- a/gl/Makefile.am +++ b/gl/Makefile.am @@ -708,6 +708,7 @@ stdio.h: stdio.in.h -e 's|@''GNULIB_FPUTS''@|$(GNULIB_FPUTS)|g' \ -e 's|@''GNULIB_PUTS''@|$(GNULIB_PUTS)|g' \ -e 's|@''GNULIB_FWRITE''@|$(GNULIB_FWRITE)|g' \ + -e 's|@''GNULIB_POPEN''@|$(GNULIB_POPEN)|g' \ -e 's|@''GNULIB_GETDELIM''@|$(GNULIB_GETDELIM)|g' \ -e 's|@''GNULIB_GETLINE''@|$(GNULIB_GETLINE)|g' \ -e 's|@''GNULIB_PERROR''@|$(GNULIB_PERROR)|g' \ @@ -741,6 +742,7 @@ stdio.h: stdio.in.h -e 's|@''REPLACE_FPURGE''@|$(REPLACE_FPURGE)|g' \ -e 's|@''HAVE_DECL_FPURGE''@|$(HAVE_DECL_FPURGE)|g' \ -e 's|@''REPLACE_FCLOSE''@|$(REPLACE_FCLOSE)|g' \ + -e 's|@''REPLACE_POPEN''@|$(REPLACE_POPEN)|g' \ -e 's|@''HAVE_DECL_GETDELIM''@|$(HAVE_DECL_GETDELIM)|g' \ -e 's|@''HAVE_DECL_GETLINE''@|$(HAVE_DECL_GETLINE)|g' \ -e 's|@''REPLACE_GETLINE''@|$(REPLACE_GETLINE)|g' \ diff --git a/gl/m4/stdio_h.m4 b/gl/m4/stdio_h.m4 index fcbe68f6ba..8c9aa8f5b5 100644 --- a/gl/m4/stdio_h.m4 +++ b/gl/m4/stdio_h.m4 @@ -1,4 +1,4 @@ -# stdio_h.m4 serial 16 +# stdio_h.m4 serial 17 dnl Copyright (C) 2007-2009 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -73,6 +73,7 @@ AC_DEFUN([gl_STDIO_H_DEFAULTS], GNULIB_FPUTS=0; AC_SUBST([GNULIB_FPUTS]) GNULIB_PUTS=0; AC_SUBST([GNULIB_PUTS]) GNULIB_FWRITE=0; AC_SUBST([GNULIB_FWRITE]) + GNULIB_POPEN=0; AC_SUBST([GNULIB_POPEN]) GNULIB_GETDELIM=0; AC_SUBST([GNULIB_GETDELIM]) GNULIB_GETLINE=0; AC_SUBST([GNULIB_GETLINE]) GNULIB_PERROR=0; AC_SUBST([GNULIB_PERROR]) @@ -109,6 +110,7 @@ AC_DEFUN([gl_STDIO_H_DEFAULTS], REPLACE_FPURGE=0; AC_SUBST([REPLACE_FPURGE]) HAVE_DECL_FPURGE=1; AC_SUBST([HAVE_DECL_FPURGE]) REPLACE_FCLOSE=0; AC_SUBST([REPLACE_FCLOSE]) + REPLACE_POPEN=0; AC_SUBST([REPLACE_POPEN]) HAVE_DECL_GETDELIM=1; AC_SUBST([HAVE_DECL_GETDELIM]) HAVE_DECL_GETLINE=1; AC_SUBST([HAVE_DECL_GETLINE]) REPLACE_GETLINE=0; AC_SUBST([REPLACE_GETLINE]) diff --git a/gl/select.c b/gl/select.c index 82e438c116..bb6952ebf5 100644 --- a/gl/select.c +++ b/gl/select.c @@ -21,6 +21,7 @@ #include <config.h> #include <alloca.h> +#include <assert.h> #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ /* Native Win32. */ @@ -76,6 +77,23 @@ typedef DWORD (WINAPI *PNtQueryInformationFile) #define PIPE_BUF 512 #endif +#define IsConsoleHandle(h) (((long) (h) & 3) == 3) + +static BOOL +IsSocketHandle(HANDLE h) +{ + WSANETWORKEVENTS ev; + + if (IsConsoleHandle (h)) + return FALSE; + + /* Under Wine, it seems that getsockopt returns 0 for pipes too. + WSAEnumNetworkEvents instead distinguishes the two correctly. */ + ev.lNetworkEvents = 0xDEADBEEF; + WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev); + return ev.lNetworkEvents != 0xDEADBEEF; +} + /* Compute output fd_sets for libc descriptor FD (whose Win32 handle is H). */ static int @@ -138,19 +156,37 @@ win32_poll_handle (HANDLE h, int fd, struct bitset *rbits, struct bitset *wbits, break; case FILE_TYPE_CHAR: - ret = WaitForSingleObject (h, 0); write = TRUE; + if (!(rbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1))))) + break; + + ret = WaitForSingleObject (h, 0); if (ret == WAIT_OBJECT_0) { + if (!IsConsoleHandle (h)) + { + read = TRUE; + break; + } + nbuffer = avail = 0; bRet = GetNumberOfConsoleInputEvents (h, &nbuffer); - if (!bRet || nbuffer == 0) - except = TRUE; + + /* Screen buffers handles are filtered earlier. */ + assert (bRet); + if (nbuffer == 0) + { + except = TRUE; + break; + } irbuffer = (INPUT_RECORD *) alloca (nbuffer * sizeof (INPUT_RECORD)); bRet = PeekConsoleInput (h, irbuffer, nbuffer, &avail); if (!bRet || avail == 0) - except = TRUE; + { + except = TRUE; + break; + } for (i = 0; i < avail; i++) if (irbuffer[i].EventType == KEY_EVENT) @@ -199,7 +235,7 @@ rpl_select (int nfds, fd_set *rfds, fd_set *wfds, fd_set *xfds, fd_set handle_rfds, handle_wfds, handle_xfds; struct bitset rbits, wbits, xbits; unsigned char anyfds_in[FD_SETSIZE / CHAR_BIT]; - DWORD ret, wait_timeout, nhandles, nsock; + DWORD ret, wait_timeout, nhandles, nsock, nbuffer; MSG msg; int i, fd, rc; @@ -227,7 +263,10 @@ rpl_select (int nfds, fd_set *rfds, fd_set *wfds, fd_set *xfds, nhandles = 1; nsock = 0; - /* Copy descriptors to bitsets. */ + /* Copy descriptors to bitsets. At the same time, eliminate + bits in the "wrong" direction for console input buffers + and screen buffers, because screen buffers are waitable + and they will block until a character is available. */ memset (&rbits, 0, sizeof (rbits)); memset (&wbits, 0, sizeof (wbits)); memset (&xbits, 0, sizeof (xbits)); @@ -236,6 +275,11 @@ rpl_select (int nfds, fd_set *rfds, fd_set *wfds, fd_set *xfds, for (i = 0; i < rfds->fd_count; i++) { fd = rfds->fd_array[i]; + h = (HANDLE) _get_osfhandle (fd); + if (IsConsoleHandle (h) + && !GetNumberOfConsoleInputEvents (h, &nbuffer)) + continue; + rbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1)); anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1)); } @@ -246,6 +290,11 @@ rpl_select (int nfds, fd_set *rfds, fd_set *wfds, fd_set *xfds, for (i = 0; i < wfds->fd_count; i++) { fd = wfds->fd_array[i]; + h = (HANDLE) _get_osfhandle (fd); + if (IsConsoleHandle (h) + && GetNumberOfConsoleInputEvents (h, &nbuffer)) + continue; + wbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1)); anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1)); } @@ -285,11 +334,7 @@ rpl_select (int nfds, fd_set *rfds, fd_set *wfds, fd_set *xfds, return -1; } - /* Under Wine, it seems that getsockopt returns 0 for pipes too. - WSAEnumNetworkEvents instead distinguishes the two correctly. */ - ev.lNetworkEvents = 0xDEADBEEF; - WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev); - if (ev.lNetworkEvents != 0xDEADBEEF) + if (IsSocketHandle (h)) { int requested = FD_CLOSE; diff --git a/gl/stdio.in.h b/gl/stdio.in.h index b659b6703a..4cd3ce136d 100644 --- a/gl/stdio.in.h +++ b/gl/stdio.in.h @@ -479,6 +479,20 @@ extern int puts (const char *string); extern size_t fwrite (const void *ptr, size_t s, size_t n, FILE *stream); #endif +#if @GNULIB_POPEN@ +# if @REPLACE_POPEN@ +# undef popen +# define popen rpl_popen +extern FILE *popen (const char *cmd, const char *mode); +# endif +#elif defined GNULIB_POSIXCHECK +# undef popen +# define popen(c,m) \ + (GL_LINK_WARNING ("popen is buggy on some platforms - " \ + "use gnulib module popen or pipe for more portability"), \ + popen (c, m)) +#endif + #if @GNULIB_GETDELIM@ # if !@HAVE_DECL_GETDELIM@ /* Read input, up to (and including) the next occurrence of DELIMITER, from diff --git a/lib/gl/Makefile.am b/lib/gl/Makefile.am index a0e3cd44c3..c6654ab6fa 100644 --- a/lib/gl/Makefile.am +++ b/lib/gl/Makefile.am @@ -426,6 +426,7 @@ stdio.h: stdio.in.h -e 's|@''GNULIB_FPUTS''@|$(GNULIB_FPUTS)|g' \ -e 's|@''GNULIB_PUTS''@|$(GNULIB_PUTS)|g' \ -e 's|@''GNULIB_FWRITE''@|$(GNULIB_FWRITE)|g' \ + -e 's|@''GNULIB_POPEN''@|$(GNULIB_POPEN)|g' \ -e 's|@''GNULIB_GETDELIM''@|$(GNULIB_GETDELIM)|g' \ -e 's|@''GNULIB_GETLINE''@|$(GNULIB_GETLINE)|g' \ -e 's|@''GNULIB_PERROR''@|$(GNULIB_PERROR)|g' \ @@ -459,6 +460,7 @@ stdio.h: stdio.in.h -e 's|@''REPLACE_FPURGE''@|$(REPLACE_FPURGE)|g' \ -e 's|@''HAVE_DECL_FPURGE''@|$(HAVE_DECL_FPURGE)|g' \ -e 's|@''REPLACE_FCLOSE''@|$(REPLACE_FCLOSE)|g' \ + -e 's|@''REPLACE_POPEN''@|$(REPLACE_POPEN)|g' \ -e 's|@''HAVE_DECL_GETDELIM''@|$(HAVE_DECL_GETDELIM)|g' \ -e 's|@''HAVE_DECL_GETLINE''@|$(HAVE_DECL_GETLINE)|g' \ -e 's|@''REPLACE_GETLINE''@|$(REPLACE_GETLINE)|g' \ diff --git a/lib/gl/m4/stdio_h.m4 b/lib/gl/m4/stdio_h.m4 index fcbe68f6ba..8c9aa8f5b5 100644 --- a/lib/gl/m4/stdio_h.m4 +++ b/lib/gl/m4/stdio_h.m4 @@ -1,4 +1,4 @@ -# stdio_h.m4 serial 16 +# stdio_h.m4 serial 17 dnl Copyright (C) 2007-2009 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -73,6 +73,7 @@ AC_DEFUN([gl_STDIO_H_DEFAULTS], GNULIB_FPUTS=0; AC_SUBST([GNULIB_FPUTS]) GNULIB_PUTS=0; AC_SUBST([GNULIB_PUTS]) GNULIB_FWRITE=0; AC_SUBST([GNULIB_FWRITE]) + GNULIB_POPEN=0; AC_SUBST([GNULIB_POPEN]) GNULIB_GETDELIM=0; AC_SUBST([GNULIB_GETDELIM]) GNULIB_GETLINE=0; AC_SUBST([GNULIB_GETLINE]) GNULIB_PERROR=0; AC_SUBST([GNULIB_PERROR]) @@ -109,6 +110,7 @@ AC_DEFUN([gl_STDIO_H_DEFAULTS], REPLACE_FPURGE=0; AC_SUBST([REPLACE_FPURGE]) HAVE_DECL_FPURGE=1; AC_SUBST([HAVE_DECL_FPURGE]) REPLACE_FCLOSE=0; AC_SUBST([REPLACE_FCLOSE]) + REPLACE_POPEN=0; AC_SUBST([REPLACE_POPEN]) HAVE_DECL_GETDELIM=1; AC_SUBST([HAVE_DECL_GETDELIM]) HAVE_DECL_GETLINE=1; AC_SUBST([HAVE_DECL_GETLINE]) REPLACE_GETLINE=0; AC_SUBST([REPLACE_GETLINE]) diff --git a/lib/gl/stdio.in.h b/lib/gl/stdio.in.h index e04799bc9d..887b0ae52b 100644 --- a/lib/gl/stdio.in.h +++ b/lib/gl/stdio.in.h @@ -479,6 +479,20 @@ extern int puts (const char *string); extern size_t fwrite (const void *ptr, size_t s, size_t n, FILE *stream); #endif +#if @GNULIB_POPEN@ +# if @REPLACE_POPEN@ +# undef popen +# define popen rpl_popen +extern FILE *popen (const char *cmd, const char *mode); +# endif +#elif defined GNULIB_POSIXCHECK +# undef popen +# define popen(c,m) \ + (GL_LINK_WARNING ("popen is buggy on some platforms - " \ + "use gnulib module popen or pipe for more portability"), \ + popen (c, m)) +#endif + #if @GNULIB_GETDELIM@ # if !@HAVE_DECL_GETDELIM@ /* Read input, up to (and including) the next occurrence of DELIMITER, from @@ -235,7 +235,8 @@ sc_prohibit_HAVE_MBRTOWC: # h: the header, enclosed in <> or "" # re: a regular expression that matches IFF something provided by $h is used. define _header_without_use - h_esc=`echo "$$h"|sed 's/\./\\./g'`; \ + dummy=; : so we do not need a semicolon before each use; \ + h_esc=`echo "$$h"|sed 's/\./\\\\./g'`; \ if $(VC_LIST_EXCEPT) | grep -l '\.c$$' > /dev/null; then \ files=$$(grep -l '^# *include '"$$h_esc" \ $$($(VC_LIST_EXCEPT) | grep '\.c$$')) && \ |