summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gl/Makefile.am2
-rw-r--r--gl/m4/stdio_h.m44
-rw-r--r--gl/select.c67
-rw-r--r--gl/stdio.in.h14
-rw-r--r--lib/gl/Makefile.am2
-rw-r--r--lib/gl/m4/stdio_h.m44
-rw-r--r--lib/gl/stdio.in.h14
-rw-r--r--maint.mk3
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
diff --git a/maint.mk b/maint.mk
index 4108177678..21782e5162 100644
--- a/maint.mk
+++ b/maint.mk
@@ -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$$')) && \