summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndy Wingo <wingo@pobox.com>2013-02-18 18:53:46 +0100
committerAndy Wingo <wingo@pobox.com>2013-02-18 18:53:46 +0100
commit3dac6181c18508a194f240d633c8c3f7304adb3f (patch)
tree17fc19cb909eedd93ec16ad3c5cd0a00173bd9c9
parentaf07e10429c1513c2348289888b240926264b32b (diff)
Add gnulib `select' module.
Should fix fport_input_waiting when neither poll nor select nor FIONREAD are available, which is the case on MinGW. Thanks to Eli Zaretskii for the report.
-rw-r--r--lib/Makefile.am66
-rw-r--r--lib/alloca.c478
-rw-r--r--lib/dup2.c160
-rw-r--r--lib/select.c547
-rw-r--r--lib/sys_select.in.h309
-rw-r--r--m4/dup2.m484
-rw-r--r--m4/gnulib-cache.m43
-rw-r--r--m4/gnulib-comp.m428
-rw-r--r--m4/select.m4113
-rw-r--r--m4/sys_select_h.m495
10 files changed, 1881 insertions, 2 deletions
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 1714cbb8c..c99a7550b 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -21,7 +21,7 @@
# the same distribution terms as the rest of that program.
#
# Generated by gnulib-tool.
-# Reproduce by: gnulib-tool --import --dir=. --local-dir=gnulib-local --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --lgpl=3 --no-conditional-dependencies --libtool --macro-prefix=gl --no-vc-files accept alignof alloca-opt announce-gen autobuild bind byteswap canonicalize-lgpl ceil clock-time close connect dirfd duplocale environ extensions flock floor fpieee frexp full-read full-write func gendocs getaddrinfo getpeername getsockname getsockopt git-version-gen gitlog-to-changelog gnu-web-doc-update gnupload havelib iconv_open-utf inet_ntop inet_pton isinf isnan ldexp lib-symbol-versions lib-symbol-visibility libunistring listen localcharset locale log1p maintainer-makefile malloc-gnu malloca nl_langinfo nproc open pipe2 putenv recv recvfrom regex rename send sendto setenv setsockopt shutdown socket stat-time stdlib strftime striconveh string sys_stat trunc verify vsnprintf warnings wchar
+# Reproduce by: gnulib-tool --import --dir=. --local-dir=gnulib-local --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --lgpl=3 --no-conditional-dependencies --libtool --macro-prefix=gl --no-vc-files accept alignof alloca-opt announce-gen autobuild bind byteswap canonicalize-lgpl ceil clock-time close connect dirfd duplocale environ extensions flock floor fpieee frexp full-read full-write func gendocs getaddrinfo getpeername getsockname getsockopt git-version-gen gitlog-to-changelog gnu-web-doc-update gnupload havelib iconv_open-utf inet_ntop inet_pton isinf isnan ldexp lib-symbol-versions lib-symbol-visibility libunistring listen localcharset locale log1p maintainer-makefile malloc-gnu malloca nl_langinfo nproc open pipe2 putenv recv recvfrom regex rename select send sendto setenv setsockopt shutdown socket stat-time stdlib strftime striconveh string sys_stat trunc verify vsnprintf warnings wchar
AUTOMAKE_OPTIONS = 1.5 gnits subdir-objects
@@ -62,6 +62,7 @@ libgnu_la_LDFLAGS += $(ISNANL_LIBM)
libgnu_la_LDFLAGS += $(LDEXP_LIBM)
libgnu_la_LDFLAGS += $(LIBSOCKET)
libgnu_la_LDFLAGS += $(LIB_CLOCK_GETTIME)
+libgnu_la_LDFLAGS += $(LIB_SELECT)
libgnu_la_LDFLAGS += $(LOG1P_LIBM)
libgnu_la_LDFLAGS += $(LOG_LIBM)
libgnu_la_LDFLAGS += $(LTLIBICONV)
@@ -87,6 +88,17 @@ EXTRA_DIST += alignof.h
## end gnulib module alignof
+## begin gnulib module alloca
+
+
+libgnu_la_LIBADD += @LTALLOCA@
+libgnu_la_DEPENDENCIES += @LTALLOCA@
+EXTRA_DIST += alloca.c
+
+EXTRA_libgnu_la_SOURCES += alloca.c
+
+## end gnulib module alloca
+
## begin gnulib module alloca-opt
BUILT_SOURCES += $(ALLOCA_H)
@@ -371,6 +383,15 @@ EXTRA_DIST += dosname.h
## end gnulib module dosname
+## begin gnulib module dup2
+
+
+EXTRA_DIST += dup2.c
+
+EXTRA_libgnu_la_SOURCES += dup2.c
+
+## end gnulib module dup2
+
## begin gnulib module duplocale
@@ -1560,6 +1581,15 @@ EXTRA_DIST += same-inode.h
## end gnulib module same-inode
+## begin gnulib module select
+
+
+EXTRA_DIST += select.c
+
+EXTRA_libgnu_la_SOURCES += select.c
+
+## end gnulib module select
+
## begin gnulib module send
@@ -2314,6 +2344,40 @@ EXTRA_DIST += sys_file.in.h
## end gnulib module sys_file
+## begin gnulib module sys_select
+
+BUILT_SOURCES += sys/select.h
+
+# We need the following in order to create <sys/select.h> when the system
+# doesn't have one that works with the given compiler.
+sys/select.h: sys_select.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(WARN_ON_USE_H)
+ $(AM_V_at)$(MKDIR_P) sys
+ $(AM_V_GEN)rm -f $@-t $@ && \
+ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
+ sed -e 's|@''GUARD_PREFIX''@|GL|g' \
+ -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \
+ -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \
+ -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \
+ -e 's|@''NEXT_SYS_SELECT_H''@|$(NEXT_SYS_SELECT_H)|g' \
+ -e 's|@''HAVE_SYS_SELECT_H''@|$(HAVE_SYS_SELECT_H)|g' \
+ -e 's/@''GNULIB_PSELECT''@/$(GNULIB_PSELECT)/g' \
+ -e 's/@''GNULIB_SELECT''@/$(GNULIB_SELECT)/g' \
+ -e 's|@''HAVE_WINSOCK2_H''@|$(HAVE_WINSOCK2_H)|g' \
+ -e 's|@''HAVE_PSELECT''@|$(HAVE_PSELECT)|g' \
+ -e 's|@''REPLACE_PSELECT''@|$(REPLACE_PSELECT)|g' \
+ -e 's|@''REPLACE_SELECT''@|$(REPLACE_SELECT)|g' \
+ -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \
+ -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \
+ < $(srcdir)/sys_select.in.h; \
+ } > $@-t && \
+ mv $@-t $@
+MOSTLYCLEANFILES += sys/select.h sys/select.h-t
+MOSTLYCLEANDIRS += sys
+
+EXTRA_DIST += sys_select.in.h
+
+## end gnulib module sys_select
+
## begin gnulib module sys_socket
BUILT_SOURCES += sys/socket.h
diff --git a/lib/alloca.c b/lib/alloca.c
new file mode 100644
index 000000000..ee0f01886
--- /dev/null
+++ b/lib/alloca.c
@@ -0,0 +1,478 @@
+/* alloca.c -- allocate automatically reclaimed memory
+ (Mostly) portable public-domain implementation -- D A Gwyn
+
+ This implementation of the PWB library alloca function,
+ which is used to allocate space off the run-time stack so
+ that it is automatically reclaimed upon procedure exit,
+ was inspired by discussions with J. Q. Johnson of Cornell.
+ J.Otto Tennant <jot@cray.com> contributed the Cray support.
+
+ There are some preprocessor constants that can
+ be defined when compiling for your specific system, for
+ improved efficiency; however, the defaults should be okay.
+
+ The general concept of this implementation is to keep
+ track of all alloca-allocated blocks, and reclaim any
+ that are found to be deeper in the stack than the current
+ invocation. This heuristic does not reclaim storage as
+ soon as it becomes invalid, but it will do so eventually.
+
+ As a special case, alloca(0) reclaims storage without
+ allocating any. It is a good idea to use alloca(0) in
+ your main control loop, etc. to force garbage collection. */
+
+#include <config.h>
+
+#include <alloca.h>
+
+#include <string.h>
+#include <stdlib.h>
+
+#ifdef emacs
+# include "lisp.h"
+# include "blockinput.h"
+# ifdef EMACS_FREE
+# undef free
+# define free EMACS_FREE
+# endif
+#else
+# define memory_full() abort ()
+#endif
+
+/* If compiling with GCC 2, this file's not needed. */
+#if !defined (__GNUC__) || __GNUC__ < 2
+
+/* If someone has defined alloca as a macro,
+ there must be some other way alloca is supposed to work. */
+# ifndef alloca
+
+# ifdef emacs
+# ifdef static
+/* actually, only want this if static is defined as ""
+ -- this is for usg, in which emacs must undefine static
+ in order to make unexec workable
+ */
+# ifndef STACK_DIRECTION
+you
+lose
+-- must know STACK_DIRECTION at compile-time
+/* Using #error here is not wise since this file should work for
+ old and obscure compilers. */
+# endif /* STACK_DIRECTION undefined */
+# endif /* static */
+# endif /* emacs */
+
+/* If your stack is a linked list of frames, you have to
+ provide an "address metric" ADDRESS_FUNCTION macro. */
+
+# if defined (CRAY) && defined (CRAY_STACKSEG_END)
+long i00afunc ();
+# define ADDRESS_FUNCTION(arg) (char *) i00afunc (&(arg))
+# else
+# define ADDRESS_FUNCTION(arg) &(arg)
+# endif
+
+/* Define STACK_DIRECTION if you know the direction of stack
+ growth for your system; otherwise it will be automatically
+ deduced at run-time.
+
+ STACK_DIRECTION > 0 => grows toward higher addresses
+ STACK_DIRECTION < 0 => grows toward lower addresses
+ STACK_DIRECTION = 0 => direction of growth unknown */
+
+# ifndef STACK_DIRECTION
+# define STACK_DIRECTION 0 /* Direction unknown. */
+# endif
+
+# if STACK_DIRECTION != 0
+
+# define STACK_DIR STACK_DIRECTION /* Known at compile-time. */
+
+# else /* STACK_DIRECTION == 0; need run-time code. */
+
+static int stack_dir; /* 1 or -1 once known. */
+# define STACK_DIR stack_dir
+
+static int
+find_stack_direction (int *addr, int depth)
+{
+ int dir, dummy = 0;
+ if (! addr)
+ addr = &dummy;
+ *addr = addr < &dummy ? 1 : addr == &dummy ? 0 : -1;
+ dir = depth ? find_stack_direction (addr, depth - 1) : 0;
+ return dir + dummy;
+}
+
+# endif /* STACK_DIRECTION == 0 */
+
+/* An "alloca header" is used to:
+ (a) chain together all alloca'ed blocks;
+ (b) keep track of stack depth.
+
+ It is very important that sizeof(header) agree with malloc
+ alignment chunk size. The following default should work okay. */
+
+# ifndef ALIGN_SIZE
+# define ALIGN_SIZE sizeof(double)
+# endif
+
+typedef union hdr
+{
+ char align[ALIGN_SIZE]; /* To force sizeof(header). */
+ struct
+ {
+ union hdr *next; /* For chaining headers. */
+ char *deep; /* For stack depth measure. */
+ } h;
+} header;
+
+static header *last_alloca_header = NULL; /* -> last alloca header. */
+
+/* Return a pointer to at least SIZE bytes of storage,
+ which will be automatically reclaimed upon exit from
+ the procedure that called alloca. Originally, this space
+ was supposed to be taken from the current stack frame of the
+ caller, but that method cannot be made to work for some
+ implementations of C, for example under Gould's UTX/32. */
+
+void *
+alloca (size_t size)
+{
+ auto char probe; /* Probes stack depth: */
+ register char *depth = ADDRESS_FUNCTION (probe);
+
+# if STACK_DIRECTION == 0
+ if (STACK_DIR == 0) /* Unknown growth direction. */
+ STACK_DIR = find_stack_direction (NULL, (size & 1) + 20);
+# endif
+
+ /* Reclaim garbage, defined as all alloca'd storage that
+ was allocated from deeper in the stack than currently. */
+
+ {
+ register header *hp; /* Traverses linked list. */
+
+# ifdef emacs
+ BLOCK_INPUT;
+# endif
+
+ for (hp = last_alloca_header; hp != NULL;)
+ if ((STACK_DIR > 0 && hp->h.deep > depth)
+ || (STACK_DIR < 0 && hp->h.deep < depth))
+ {
+ register header *np = hp->h.next;
+
+ free (hp); /* Collect garbage. */
+
+ hp = np; /* -> next header. */
+ }
+ else
+ break; /* Rest are not deeper. */
+
+ last_alloca_header = hp; /* -> last valid storage. */
+
+# ifdef emacs
+ UNBLOCK_INPUT;
+# endif
+ }
+
+ if (size == 0)
+ return NULL; /* No allocation required. */
+
+ /* Allocate combined header + user data storage. */
+
+ {
+ /* Address of header. */
+ register header *new;
+
+ size_t combined_size = sizeof (header) + size;
+ if (combined_size < sizeof (header))
+ memory_full ();
+
+ new = malloc (combined_size);
+
+ if (! new)
+ memory_full ();
+
+ new->h.next = last_alloca_header;
+ new->h.deep = depth;
+
+ last_alloca_header = new;
+
+ /* User storage begins just after header. */
+
+ return (void *) (new + 1);
+ }
+}
+
+# if defined (CRAY) && defined (CRAY_STACKSEG_END)
+
+# ifdef DEBUG_I00AFUNC
+# include <stdio.h>
+# endif
+
+# ifndef CRAY_STACK
+# define CRAY_STACK
+# ifndef CRAY2
+/* Stack structures for CRAY-1, CRAY X-MP, and CRAY Y-MP */
+struct stack_control_header
+ {
+ long shgrow:32; /* Number of times stack has grown. */
+ long shaseg:32; /* Size of increments to stack. */
+ long shhwm:32; /* High water mark of stack. */
+ long shsize:32; /* Current size of stack (all segments). */
+ };
+
+/* The stack segment linkage control information occurs at
+ the high-address end of a stack segment. (The stack
+ grows from low addresses to high addresses.) The initial
+ part of the stack segment linkage control information is
+ 0200 (octal) words. This provides for register storage
+ for the routine which overflows the stack. */
+
+struct stack_segment_linkage
+ {
+ long ss[0200]; /* 0200 overflow words. */
+ long sssize:32; /* Number of words in this segment. */
+ long ssbase:32; /* Offset to stack base. */
+ long:32;
+ long sspseg:32; /* Offset to linkage control of previous
+ segment of stack. */
+ long:32;
+ long sstcpt:32; /* Pointer to task common address block. */
+ long sscsnm; /* Private control structure number for
+ microtasking. */
+ long ssusr1; /* Reserved for user. */
+ long ssusr2; /* Reserved for user. */
+ long sstpid; /* Process ID for pid based multi-tasking. */
+ long ssgvup; /* Pointer to multitasking thread giveup. */
+ long sscray[7]; /* Reserved for Cray Research. */
+ long ssa0;
+ long ssa1;
+ long ssa2;
+ long ssa3;
+ long ssa4;
+ long ssa5;
+ long ssa6;
+ long ssa7;
+ long sss0;
+ long sss1;
+ long sss2;
+ long sss3;
+ long sss4;
+ long sss5;
+ long sss6;
+ long sss7;
+ };
+
+# else /* CRAY2 */
+/* The following structure defines the vector of words
+ returned by the STKSTAT library routine. */
+struct stk_stat
+ {
+ long now; /* Current total stack size. */
+ long maxc; /* Amount of contiguous space which would
+ be required to satisfy the maximum
+ stack demand to date. */
+ long high_water; /* Stack high-water mark. */
+ long overflows; /* Number of stack overflow ($STKOFEN) calls. */
+ long hits; /* Number of internal buffer hits. */
+ long extends; /* Number of block extensions. */
+ long stko_mallocs; /* Block allocations by $STKOFEN. */
+ long underflows; /* Number of stack underflow calls ($STKRETN). */
+ long stko_free; /* Number of deallocations by $STKRETN. */
+ long stkm_free; /* Number of deallocations by $STKMRET. */
+ long segments; /* Current number of stack segments. */
+ long maxs; /* Maximum number of stack segments so far. */
+ long pad_size; /* Stack pad size. */
+ long current_address; /* Current stack segment address. */
+ long current_size; /* Current stack segment size. This
+ number is actually corrupted by STKSTAT to
+ include the fifteen word trailer area. */
+ long initial_address; /* Address of initial segment. */
+ long initial_size; /* Size of initial segment. */
+ };
+
+/* The following structure describes the data structure which trails
+ any stack segment. I think that the description in 'asdef' is
+ out of date. I only describe the parts that I am sure about. */
+
+struct stk_trailer
+ {
+ long this_address; /* Address of this block. */
+ long this_size; /* Size of this block (does not include
+ this trailer). */
+ long unknown2;
+ long unknown3;
+ long link; /* Address of trailer block of previous
+ segment. */
+ long unknown5;
+ long unknown6;
+ long unknown7;
+ long unknown8;
+ long unknown9;
+ long unknown10;
+ long unknown11;
+ long unknown12;
+ long unknown13;
+ long unknown14;
+ };
+
+# endif /* CRAY2 */
+# endif /* not CRAY_STACK */
+
+# ifdef CRAY2
+/* Determine a "stack measure" for an arbitrary ADDRESS.
+ I doubt that "lint" will like this much. */
+
+static long
+i00afunc (long *address)
+{
+ struct stk_stat status;
+ struct stk_trailer *trailer;
+ long *block, size;
+ long result = 0;
+
+ /* We want to iterate through all of the segments. The first
+ step is to get the stack status structure. We could do this
+ more quickly and more directly, perhaps, by referencing the
+ $LM00 common block, but I know that this works. */
+
+ STKSTAT (&status);
+
+ /* Set up the iteration. */
+
+ trailer = (struct stk_trailer *) (status.current_address
+ + status.current_size
+ - 15);
+
+ /* There must be at least one stack segment. Therefore it is
+ a fatal error if "trailer" is null. */
+
+ if (trailer == 0)
+ abort ();
+
+ /* Discard segments that do not contain our argument address. */
+
+ while (trailer != 0)
+ {
+ block = (long *) trailer->this_address;
+ size = trailer->this_size;
+ if (block == 0 || size == 0)
+ abort ();
+ trailer = (struct stk_trailer *) trailer->link;
+ if ((block <= address) && (address < (block + size)))
+ break;
+ }
+
+ /* Set the result to the offset in this segment and add the sizes
+ of all predecessor segments. */
+
+ result = address - block;
+
+ if (trailer == 0)
+ {
+ return result;
+ }
+
+ do
+ {
+ if (trailer->this_size <= 0)
+ abort ();
+ result += trailer->this_size;
+ trailer = (struct stk_trailer *) trailer->link;
+ }
+ while (trailer != 0);
+
+ /* We are done. Note that if you present a bogus address (one
+ not in any segment), you will get a different number back, formed
+ from subtracting the address of the first block. This is probably
+ not what you want. */
+
+ return (result);
+}
+
+# else /* not CRAY2 */
+/* Stack address function for a CRAY-1, CRAY X-MP, or CRAY Y-MP.
+ Determine the number of the cell within the stack,
+ given the address of the cell. The purpose of this
+ routine is to linearize, in some sense, stack addresses
+ for alloca. */
+
+static long
+i00afunc (long address)
+{
+ long stkl = 0;
+
+ long size, pseg, this_segment, stack;
+ long result = 0;
+
+ struct stack_segment_linkage *ssptr;
+
+ /* Register B67 contains the address of the end of the
+ current stack segment. If you (as a subprogram) store
+ your registers on the stack and find that you are past
+ the contents of B67, you have overflowed the segment.
+
+ B67 also points to the stack segment linkage control
+ area, which is what we are really interested in. */
+
+ stkl = CRAY_STACKSEG_END ();
+ ssptr = (struct stack_segment_linkage *) stkl;
+
+ /* If one subtracts 'size' from the end of the segment,
+ one has the address of the first word of the segment.
+
+ If this is not the first segment, 'pseg' will be
+ nonzero. */
+
+ pseg = ssptr->sspseg;
+ size = ssptr->sssize;
+
+ this_segment = stkl - size;
+
+ /* It is possible that calling this routine itself caused
+ a stack overflow. Discard stack segments which do not
+ contain the target address. */
+
+ while (!(this_segment <= address && address <= stkl))
+ {
+# ifdef DEBUG_I00AFUNC
+ fprintf (stderr, "%011o %011o %011o\n", this_segment, address, stkl);
+# endif
+ if (pseg == 0)
+ break;
+ stkl = stkl - pseg;
+ ssptr = (struct stack_segment_linkage *) stkl;
+ size = ssptr->sssize;
+ pseg = ssptr->sspseg;
+ this_segment = stkl - size;
+ }
+
+ result = address - this_segment;
+
+ /* If you subtract pseg from the current end of the stack,
+ you get the address of the previous stack segment's end.
+ This seems a little convoluted to me, but I'll bet you save
+ a cycle somewhere. */
+
+ while (pseg != 0)
+ {
+# ifdef DEBUG_I00AFUNC
+ fprintf (stderr, "%011o %011o\n", pseg, size);
+# endif
+ stkl = stkl - pseg;
+ ssptr = (struct stack_segment_linkage *) stkl;
+ size = ssptr->sssize;
+ pseg = ssptr->sspseg;
+ result += size;
+ }
+ return (result);
+}
+
+# endif /* not CRAY2 */
+# endif /* CRAY */
+
+# endif /* no alloca */
+#endif /* not GCC 2 */
diff --git a/lib/dup2.c b/lib/dup2.c
new file mode 100644
index 000000000..89b40c466
--- /dev/null
+++ b/lib/dup2.c
@@ -0,0 +1,160 @@
+/* Duplicate an open file descriptor to a specified file descriptor.
+
+ Copyright (C) 1999, 2004-2007, 2009-2013 Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+/* written by Paul Eggert */
+
+#include <config.h>
+
+/* Specification. */
+#include <unistd.h>
+
+#include <errno.h>
+#include <fcntl.h>
+
+#if HAVE_DUP2
+
+# undef dup2
+
+# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+
+/* Get declarations of the native Windows API functions. */
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+
+# include "msvc-inval.h"
+
+/* Get _get_osfhandle. */
+# include "msvc-nothrow.h"
+
+static int
+ms_windows_dup2 (int fd, int desired_fd)
+{
+ int result;
+
+ /* If fd is closed, mingw hangs on dup2 (fd, fd). If fd is open,
+ dup2 (fd, fd) returns 0, but all further attempts to use fd in
+ future dup2 calls will hang. */
+ if (fd == desired_fd)
+ {
+ if ((HANDLE) _get_osfhandle (fd) == INVALID_HANDLE_VALUE)
+ {
+ errno = EBADF;
+ return -1;
+ }
+ return fd;
+ }
+
+ /* Wine 1.0.1 return 0 when desired_fd is negative but not -1:
+ http://bugs.winehq.org/show_bug.cgi?id=21289 */
+ if (desired_fd < 0)
+ {
+ errno = EBADF;
+ return -1;
+ }
+
+ TRY_MSVC_INVAL
+ {
+ result = dup2 (fd, desired_fd);
+ }
+ CATCH_MSVC_INVAL
+ {
+ errno = EBADF;
+ result = -1;
+ }
+ DONE_MSVC_INVAL;
+
+ if (result == 0)
+ result = desired_fd;
+
+ return result;
+}
+
+# define dup2 ms_windows_dup2
+
+# endif
+
+int
+rpl_dup2 (int fd, int desired_fd)
+{
+ int result;
+
+# ifdef F_GETFL
+ /* On Linux kernels 2.6.26-2.6.29, dup2 (fd, fd) returns -EBADF.
+ On Cygwin 1.5.x, dup2 (1, 1) returns 0.
+ On Cygwin 1.7.17, dup2 (1, -1) dumps core.
+ On Haiku, dup2 (fd, fd) mistakenly clears FD_CLOEXEC. */
+ if (desired_fd < 0)
+ fd = desired_fd;
+ if (fd == desired_fd)
+ return fcntl (fd, F_GETFL) == -1 ? -1 : fd;
+# endif
+
+ result = dup2 (fd, desired_fd);
+
+ /* Correct an errno value on FreeBSD 6.1 and Cygwin 1.5.x. */
+ if (result == -1 && errno == EMFILE)
+ errno = EBADF;
+# if REPLACE_FCHDIR
+ if (fd != desired_fd && result != -1)
+ result = _gl_register_dup (fd, result);
+# endif
+ return result;
+}
+
+#else /* !HAVE_DUP2 */
+
+/* On older platforms, dup2 did not exist. */
+
+# ifndef F_DUPFD
+static int
+dupfd (int fd, int desired_fd)
+{
+ int duplicated_fd = dup (fd);
+ if (duplicated_fd < 0 || duplicated_fd == desired_fd)
+ return duplicated_fd;
+ else
+ {
+ int r = dupfd (fd, desired_fd);
+ int e = errno;
+ close (duplicated_fd);
+ errno = e;
+ return r;
+ }
+}
+# endif
+
+int
+dup2 (int fd, int desired_fd)
+{
+ int result = fcntl (fd, F_GETFL) < 0 ? -1 : fd;
+ if (result == -1 || fd == desired_fd)
+ return result;
+ close (desired_fd);
+# ifdef F_DUPFD
+ result = fcntl (fd, F_DUPFD, desired_fd);
+# if REPLACE_FCHDIR
+ if (0 <= result)
+ result = _gl_register_dup (fd, result);
+# endif
+# else
+ result = dupfd (fd, desired_fd);
+# endif
+ if (result == -1 && (errno == EMFILE || errno == EINVAL))
+ errno = EBADF;
+ return result;
+}
+#endif /* !HAVE_DUP2 */
diff --git a/lib/select.c b/lib/select.c
new file mode 100644
index 000000000..13ca15006
--- /dev/null
+++ b/lib/select.c
@@ -0,0 +1,547 @@
+/* Emulation for select(2)
+ Contributed by Paolo Bonzini.
+
+ Copyright 2008-2013 Free Software Foundation, Inc.
+
+ This file is part of gnulib.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2, 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 Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License along
+ with this program; if not, see <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+#include <alloca.h>
+#include <assert.h>
+
+#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+/* Native Windows. */
+
+#include <sys/types.h>
+#include <errno.h>
+#include <limits.h>
+
+#include <winsock2.h>
+#include <windows.h>
+#include <io.h>
+#include <stdio.h>
+#include <conio.h>
+#include <time.h>
+
+/* Get the overridden 'struct timeval'. */
+#include <sys/time.h>
+
+#include "msvc-nothrow.h"
+
+#undef select
+
+struct bitset {
+ unsigned char in[FD_SETSIZE / CHAR_BIT];
+ unsigned char out[FD_SETSIZE / CHAR_BIT];
+};
+
+/* Declare data structures for ntdll functions. */
+typedef struct _FILE_PIPE_LOCAL_INFORMATION {
+ ULONG NamedPipeType;
+ ULONG NamedPipeConfiguration;
+ ULONG MaximumInstances;
+ ULONG CurrentInstances;
+ ULONG InboundQuota;
+ ULONG ReadDataAvailable;
+ ULONG OutboundQuota;
+ ULONG WriteQuotaAvailable;
+ ULONG NamedPipeState;
+ ULONG NamedPipeEnd;
+} FILE_PIPE_LOCAL_INFORMATION, *PFILE_PIPE_LOCAL_INFORMATION;
+
+typedef struct _IO_STATUS_BLOCK
+{
+ union {
+ DWORD Status;
+ PVOID Pointer;
+ } u;
+ ULONG_PTR Information;
+} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
+
+typedef enum _FILE_INFORMATION_CLASS {
+ FilePipeLocalInformation = 24
+} FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;
+
+typedef DWORD (WINAPI *PNtQueryInformationFile)
+ (HANDLE, IO_STATUS_BLOCK *, VOID *, ULONG, FILE_INFORMATION_CLASS);
+
+#ifndef PIPE_BUF
+#define PIPE_BUF 512
+#endif
+
+/* Optimized test whether a HANDLE refers to a console.
+ See <http://lists.gnu.org/archive/html/bug-gnulib/2009-08/msg00065.html>. */
+#define IsConsoleHandle(h) (((intptr_t) (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 Windows handle is
+ H). */
+
+static int
+windows_poll_handle (HANDLE h, int fd,
+ struct bitset *rbits,
+ struct bitset *wbits,
+ struct bitset *xbits)
+{
+ BOOL read, write, except;
+ int i, ret;
+ INPUT_RECORD *irbuffer;
+ DWORD avail, nbuffer;
+ BOOL bRet;
+ IO_STATUS_BLOCK iosb;
+ FILE_PIPE_LOCAL_INFORMATION fpli;
+ static PNtQueryInformationFile NtQueryInformationFile;
+ static BOOL once_only;
+
+ read = write = except = FALSE;
+ switch (GetFileType (h))
+ {
+ case FILE_TYPE_DISK:
+ read = TRUE;
+ write = TRUE;
+ break;
+
+ case FILE_TYPE_PIPE:
+ if (!once_only)
+ {
+ NtQueryInformationFile = (PNtQueryInformationFile)
+ GetProcAddress (GetModuleHandle ("ntdll.dll"),
+ "NtQueryInformationFile");
+ once_only = TRUE;
+ }
+
+ if (PeekNamedPipe (h, NULL, 0, NULL, &avail, NULL) != 0)
+ {
+ if (avail)
+ read = TRUE;
+ }
+ else if (GetLastError () == ERROR_BROKEN_PIPE)
+ ;
+
+ else
+ {
+ /* It was the write-end of the pipe. Check if it is writable.
+ If NtQueryInformationFile fails, optimistically assume the pipe is
+ writable. This could happen on Windows 9x, where
+ NtQueryInformationFile is not available, or if we inherit a pipe
+ that doesn't permit FILE_READ_ATTRIBUTES access on the write end
+ (I think this should not happen since Windows XP SP2; WINE seems
+ fine too). Otherwise, ensure that enough space is available for
+ atomic writes. */
+ memset (&iosb, 0, sizeof (iosb));
+ memset (&fpli, 0, sizeof (fpli));
+
+ if (!NtQueryInformationFile
+ || NtQueryInformationFile (h, &iosb, &fpli, sizeof (fpli),
+ FilePipeLocalInformation)
+ || fpli.WriteQuotaAvailable >= PIPE_BUF
+ || (fpli.OutboundQuota < PIPE_BUF &&
+ fpli.WriteQuotaAvailable == fpli.OutboundQuota))
+ write = TRUE;
+ }
+ break;
+
+ case FILE_TYPE_CHAR:
+ 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);
+
+ /* 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;
+ break;
+ }
+
+ for (i = 0; i < avail; i++)
+ if (irbuffer[i].EventType == KEY_EVENT)
+ read = TRUE;
+ }
+ break;
+
+ default:
+ ret = WaitForSingleObject (h, 0);
+ write = TRUE;
+ if (ret == WAIT_OBJECT_0)
+ read = TRUE;
+
+ break;
+ }
+
+ ret = 0;
+ if (read && (rbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
+ {
+ rbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
+ ret++;
+ }
+
+ if (write && (wbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
+ {
+ wbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
+ ret++;
+ }
+
+ if (except && (xbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
+ {
+ xbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
+ ret++;
+ }
+
+ return ret;
+}
+
+int
+rpl_select (int nfds, fd_set *rfds, fd_set *wfds, fd_set *xfds,
+ struct timeval *timeout)
+#undef timeval
+{
+ static struct timeval tv0;
+ static HANDLE hEvent;
+ HANDLE h, handle_array[FD_SETSIZE + 2];
+ 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, nbuffer;
+ MSG msg;
+ int i, fd, rc;
+
+ if (nfds > FD_SETSIZE)
+ nfds = FD_SETSIZE;
+
+ if (!timeout)
+ wait_timeout = INFINITE;
+ else
+ {
+ wait_timeout = timeout->tv_sec * 1000 + timeout->tv_usec / 1000;
+
+ /* select is also used as a portable usleep. */
+ if (!rfds && !wfds && !xfds)
+ {
+ Sleep (wait_timeout);
+ return 0;
+ }
+ }
+
+ if (!hEvent)
+ hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
+
+ handle_array[0] = hEvent;
+ nhandles = 1;
+ nsock = 0;
+
+ /* 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));
+ memset (anyfds_in, 0, sizeof (anyfds_in));
+ if (rfds)
+ 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));
+ }
+ else
+ rfds = (fd_set *) alloca (sizeof (fd_set));
+
+ if (wfds)
+ 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));
+ }
+ else
+ wfds = (fd_set *) alloca (sizeof (fd_set));
+
+ if (xfds)
+ for (i = 0; i < xfds->fd_count; i++)
+ {
+ fd = xfds->fd_array[i];
+ xbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
+ anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
+ }
+ else
+ xfds = (fd_set *) alloca (sizeof (fd_set));
+
+ /* Zero all the fd_sets, including the application's. */
+ FD_ZERO (rfds);
+ FD_ZERO (wfds);
+ FD_ZERO (xfds);
+ FD_ZERO (&handle_rfds);
+ FD_ZERO (&handle_wfds);
+ FD_ZERO (&handle_xfds);
+
+ /* Classify handles. Create fd sets for sockets, poll the others. */
+ for (i = 0; i < nfds; i++)
+ {
+ if ((anyfds_in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))) == 0)
+ continue;
+
+ h = (HANDLE) _get_osfhandle (i);
+ if (!h)
+ {
+ errno = EBADF;
+ return -1;
+ }
+
+ if (IsSocketHandle (h))
+ {
+ int requested = FD_CLOSE;
+
+ /* See above; socket handles are mapped onto select, but we
+ need to map descriptors to handles. */
+ if (rbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
+ {
+ requested |= FD_READ | FD_ACCEPT;
+ FD_SET ((SOCKET) h, rfds);
+ FD_SET ((SOCKET) h, &handle_rfds);
+ }
+ if (wbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
+ {
+ requested |= FD_WRITE | FD_CONNECT;
+ FD_SET ((SOCKET) h, wfds);
+ FD_SET ((SOCKET) h, &handle_wfds);
+ }
+ if (xbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
+ {
+ requested |= FD_OOB;
+ FD_SET ((SOCKET) h, xfds);
+ FD_SET ((SOCKET) h, &handle_xfds);
+ }
+
+ WSAEventSelect ((SOCKET) h, hEvent, requested);
+ nsock++;
+ }
+ else
+ {
+ handle_array[nhandles++] = h;
+
+ /* Poll now. If we get an event, do not wait below. */
+ if (wait_timeout != 0
+ && windows_poll_handle (h, i, &rbits, &wbits, &xbits))
+ wait_timeout = 0;
+ }
+ }
+
+ /* Place a sentinel at the end of the array. */
+ handle_array[nhandles] = NULL;
+
+restart:
+ if (wait_timeout == 0 || nsock == 0)
+ rc = 0;
+ else
+ {
+ /* See if we need to wait in the loop below. If any select is ready,
+ do MsgWaitForMultipleObjects anyway to dispatch messages, but
+ no need to call select again. */
+ rc = select (0, &handle_rfds, &handle_wfds, &handle_xfds, &tv0);
+ if (rc == 0)
+ {
+ /* Restore the fd_sets for the other select we do below. */
+ memcpy (&handle_rfds, rfds, sizeof (fd_set));
+ memcpy (&handle_wfds, wfds, sizeof (fd_set));
+ memcpy (&handle_xfds, xfds, sizeof (fd_set));
+ }
+ else
+ wait_timeout = 0;
+ }
+
+ for (;;)
+ {
+ ret = MsgWaitForMultipleObjects (nhandles, handle_array, FALSE,
+ wait_timeout, QS_ALLINPUT);
+
+ if (ret == WAIT_OBJECT_0 + nhandles)
+ {
+ /* new input of some other kind */
+ BOOL bRet;
+ while ((bRet = PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) != 0)
+ {
+ TranslateMessage (&msg);
+ DispatchMessage (&msg);
+ }
+ }
+ else
+ break;
+ }
+
+ /* If we haven't done it yet, check the status of the sockets. */
+ if (rc == 0 && nsock > 0)
+ rc = select (0, &handle_rfds, &handle_wfds, &handle_xfds, &tv0);
+
+ if (nhandles > 1)
+ {
+ /* Count results that are not counted in the return value of select. */
+ nhandles = 1;
+ for (i = 0; i < nfds; i++)
+ {
+ if ((anyfds_in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))) == 0)
+ continue;
+
+ h = (HANDLE) _get_osfhandle (i);
+ if (h == handle_array[nhandles])
+ {
+ /* Not a socket. */
+ nhandles++;
+ windows_poll_handle (h, i, &rbits, &wbits, &xbits);
+ if (rbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))
+ || wbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))
+ || xbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
+ rc++;
+ }
+ }
+
+ if (rc == 0 && wait_timeout == INFINITE)
+ {
+ /* Sleep 1 millisecond to avoid busy wait and retry with the
+ original fd_sets. */
+ memcpy (&handle_rfds, rfds, sizeof (fd_set));
+ memcpy (&handle_wfds, wfds, sizeof (fd_set));
+ memcpy (&handle_xfds, xfds, sizeof (fd_set));
+ SleepEx (1, TRUE);
+ goto restart;
+ }
+ }
+
+ /* Now fill in the results. */
+ FD_ZERO (rfds);
+ FD_ZERO (wfds);
+ FD_ZERO (xfds);
+ nhandles = 1;
+ for (i = 0; i < nfds; i++)
+ {
+ if ((anyfds_in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))) == 0)
+ continue;
+
+ h = (HANDLE) _get_osfhandle (i);
+ if (h != handle_array[nhandles])
+ {
+ /* Perform handle->descriptor mapping. */
+ WSAEventSelect ((SOCKET) h, NULL, 0);
+ if (FD_ISSET (h, &handle_rfds))
+ FD_SET (i, rfds);
+ if (FD_ISSET (h, &handle_wfds))
+ FD_SET (i, wfds);
+ if (FD_ISSET (h, &handle_xfds))
+ FD_SET (i, xfds);
+ }
+ else
+ {
+ /* Not a socket. */
+ nhandles++;
+ if (rbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
+ FD_SET (i, rfds);
+ if (wbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
+ FD_SET (i, wfds);
+ if (xbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
+ FD_SET (i, xfds);
+ }
+ }
+
+ return rc;
+}
+
+#else /* ! Native Windows. */
+
+#include <sys/select.h>
+#include <stddef.h> /* NULL */
+#include <errno.h>
+#include <unistd.h>
+
+#undef select
+
+int
+rpl_select (int nfds, fd_set *rfds, fd_set *wfds, fd_set *xfds,
+ struct timeval *timeout)
+{
+ int i;
+
+ /* FreeBSD 8.2 has a bug: it does not always detect invalid fds. */
+ if (nfds < 0 || nfds > FD_SETSIZE)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+ for (i = 0; i < nfds; i++)
+ {
+ if (((rfds && FD_ISSET (i, rfds))
+ || (wfds && FD_ISSET (i, wfds))
+ || (xfds && FD_ISSET (i, xfds)))
+ && dup2 (i, i) != i)
+ return -1;
+ }
+
+ /* Interix 3.5 has a bug: it does not support nfds == 0. */
+ if (nfds == 0)
+ {
+ nfds = 1;
+ rfds = NULL;
+ wfds = NULL;
+ xfds = NULL;
+ }
+ return select (nfds, rfds, wfds, xfds, timeout);
+}
+
+#endif
diff --git a/lib/sys_select.in.h b/lib/sys_select.in.h
new file mode 100644
index 000000000..0e3e32d82
--- /dev/null
+++ b/lib/sys_select.in.h
@@ -0,0 +1,309 @@
+/* Substitute for <sys/select.h>.
+ Copyright (C) 2007-2013 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2, 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 Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program; if not, see <http://www.gnu.org/licenses/>. */
+
+# if __GNUC__ >= 3
+@PRAGMA_SYSTEM_HEADER@
+# endif
+@PRAGMA_COLUMNS@
+
+/* On OSF/1 and Solaris 2.6, <sys/types.h> and <sys/time.h>
+ both include <sys/select.h>.
+ Simply delegate to the system's header in this case. */
+#if (@HAVE_SYS_SELECT_H@ \
+ && ((defined __osf__ && defined _SYS_TYPES_H_ && defined _OSF_SOURCE) \
+ || (defined __sun && defined _SYS_TYPES_H \
+ && (! (defined _XOPEN_SOURCE || defined _POSIX_C_SOURCE) \
+ || defined __EXTENSIONS__))) \
+ && !defined _GL_SYS_SELECT_H_REDIRECT_FROM_SYS_TYPES_H)
+
+# define _GL_SYS_SELECT_H_REDIRECT_FROM_SYS_TYPES_H
+# @INCLUDE_NEXT@ @NEXT_SYS_SELECT_H@
+
+#elif (@HAVE_SYS_SELECT_H@ \
+ && ((defined __osf__ && defined _SYS_TIME_H_ && defined _OSF_SOURCE) \
+ || (defined __sun && defined _SYS_TIME_H \
+ && (! (defined _XOPEN_SOURCE || defined _POSIX_C_SOURCE) \
+ || defined __EXTENSIONS__))) \
+ && !defined _GL_SYS_SELECT_H_REDIRECT_FROM_SYS_TIME_H)
+
+# define _GL_SYS_SELECT_H_REDIRECT_FROM_SYS_TIME_H
+# @INCLUDE_NEXT@ @NEXT_SYS_SELECT_H@
+
+/* On IRIX 6.5, <sys/timespec.h> includes <sys/types.h>, which includes
+ <sys/bsd_types.h>, which includes <sys/select.h>. At this point we cannot
+ include <signal.h>, because that includes <internal/signal_core.h>, which
+ gives a syntax error because <sys/timespec.h> has not been completely
+ processed. Simply delegate to the system's header in this case. */
+#elif @HAVE_SYS_SELECT_H@ && defined __sgi && (defined _SYS_BSD_TYPES_H && !defined _GL_SYS_SELECT_H_REDIRECT_FROM_SYS_BSD_TYPES_H)
+
+# define _GL_SYS_SELECT_H_REDIRECT_FROM_SYS_BSD_TYPES_H
+# @INCLUDE_NEXT@ @NEXT_SYS_SELECT_H@
+
+/* On OpenBSD 5.0, <pthread.h> includes <sys/types.h>, which includes
+ <sys/select.h>. At this point we cannot include <signal.h>, because that
+ includes gnulib's pthread.h override, which gives a syntax error because
+ /usr/include/pthread.h has not been completely processed. Simply delegate
+ to the system's header in this case. */
+#elif @HAVE_SYS_SELECT_H@ && defined __OpenBSD__ && (defined _PTHREAD_H_ && !defined PTHREAD_MUTEX_INITIALIZER)
+
+# @INCLUDE_NEXT@ @NEXT_SYS_SELECT_H@
+
+#else
+
+#ifndef _@GUARD_PREFIX@_SYS_SELECT_H
+
+/* On many platforms, <sys/select.h> assumes prior inclusion of
+ <sys/types.h>. Also, mingw defines sigset_t there, instead of
+ in <signal.h> where it belongs. */
+#include <sys/types.h>
+
+#if @HAVE_SYS_SELECT_H@
+
+/* On OSF/1 4.0, <sys/select.h> provides only a forward declaration
+ of 'struct timeval', and no definition of this type.
+ Also, Mac OS X, AIX, HP-UX, IRIX, Solaris, Interix declare select()
+ in <sys/time.h>.
+ But avoid namespace pollution on glibc systems. */
+# ifndef __GLIBC__
+# include <sys/time.h>
+# endif
+
+/* On AIX 7 and Solaris 10, <sys/select.h> provides an FD_ZERO implementation
+ that relies on memset(), but without including <string.h>.
+ But in any case avoid namespace pollution on glibc systems. */
+# if (defined __OpenBSD__ || defined _AIX || defined __sun || defined __osf__ || defined __BEOS__) \
+ && ! defined __GLIBC__
+# include <string.h>
+# endif
+
+/* The include_next requires a split double-inclusion guard. */
+# @INCLUDE_NEXT@ @NEXT_SYS_SELECT_H@
+
+#endif
+
+/* Get definition of 'sigset_t'.
+ But avoid namespace pollution on glibc systems.
+ Do this after the include_next (for the sake of OpenBSD 5.0) but before
+ the split double-inclusion guard (for the sake of Solaris). */
+#if !(defined __GLIBC__ && !defined __UCLIBC__)
+# include <signal.h>
+#endif
+
+#ifndef _@GUARD_PREFIX@_SYS_SELECT_H
+#define _@GUARD_PREFIX@_SYS_SELECT_H
+
+#if !@HAVE_SYS_SELECT_H@
+/* A platform that lacks <sys/select.h>. */
+/* Get the 'struct timeval' and 'fd_set' types and the FD_* macros
+ on most platforms. */
+# include <sys/time.h>
+/* On HP-UX 11, <sys/time.h> provides an FD_ZERO implementation
+ that relies on memset(), but without including <string.h>. */
+# if defined __hpux
+# include <string.h>
+# endif
+/* On native Windows platforms:
+ Get the 'fd_set' type.
+ Get the close() declaration before we override it. */
+# if @HAVE_WINSOCK2_H@
+# if !defined _GL_INCLUDING_WINSOCK2_H
+# define _GL_INCLUDING_WINSOCK2_H
+# include <winsock2.h>
+# undef _GL_INCLUDING_WINSOCK2_H
+# endif
+# include <io.h>
+# endif
+#endif
+
+/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */
+
+/* The definition of _GL_WARN_ON_USE is copied here. */
+
+
+/* Fix some definitions from <winsock2.h>. */
+
+#if @HAVE_WINSOCK2_H@
+
+# if !GNULIB_defined_rpl_fd_isset
+
+/* Re-define FD_ISSET to avoid a WSA call while we are not using
+ network sockets. */
+static int
+rpl_fd_isset (SOCKET fd, fd_set * set)
+{
+ u_int i;
+ if (set == NULL)
+ return 0;
+
+ for (i = 0; i < set->fd_count; i++)
+ if (set->fd_array[i] == fd)
+ return 1;
+
+ return 0;
+}
+
+# define GNULIB_defined_rpl_fd_isset 1
+# endif
+
+# undef FD_ISSET
+# define FD_ISSET(fd, set) rpl_fd_isset(fd, set)
+
+#endif
+
+/* Hide some function declarations from <winsock2.h>. */
+
+#if @HAVE_WINSOCK2_H@
+# if !defined _@GUARD_PREFIX@_UNISTD_H
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef close
+# define close close_used_without_including_unistd_h
+# else
+ _GL_WARN_ON_USE (close,
+ "close() used without including <unistd.h>");
+# endif
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef gethostname
+# define gethostname gethostname_used_without_including_unistd_h
+# else
+ _GL_WARN_ON_USE (gethostname,
+ "gethostname() used without including <unistd.h>");
+# endif
+# endif
+# if !defined _@GUARD_PREFIX@_SYS_SOCKET_H
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef socket
+# define socket socket_used_without_including_sys_socket_h
+# undef connect
+# define connect connect_used_without_including_sys_socket_h
+# undef accept
+# define accept accept_used_without_including_sys_socket_h
+# undef bind
+# define bind bind_used_without_including_sys_socket_h
+# undef getpeername
+# define getpeername getpeername_used_without_including_sys_socket_h
+# undef getsockname
+# define getsockname getsockname_used_without_including_sys_socket_h
+# undef getsockopt
+# define getsockopt getsockopt_used_without_including_sys_socket_h
+# undef listen
+# define listen listen_used_without_including_sys_socket_h
+# undef recv
+# define recv recv_used_without_including_sys_socket_h
+# undef send
+# define send send_used_without_including_sys_socket_h
+# undef recvfrom
+# define recvfrom recvfrom_used_without_including_sys_socket_h
+# undef sendto
+# define sendto sendto_used_without_including_sys_socket_h
+# undef setsockopt
+# define setsockopt setsockopt_used_without_including_sys_socket_h
+# undef shutdown
+# define shutdown shutdown_used_without_including_sys_socket_h
+# else
+ _GL_WARN_ON_USE (socket,
+ "socket() used without including <sys/socket.h>");
+ _GL_WARN_ON_USE (connect,
+ "connect() used without including <sys/socket.h>");
+ _GL_WARN_ON_USE (accept,
+ "accept() used without including <sys/socket.h>");
+ _GL_WARN_ON_USE (bind,
+ "bind() used without including <sys/socket.h>");
+ _GL_WARN_ON_USE (getpeername,
+ "getpeername() used without including <sys/socket.h>");
+ _GL_WARN_ON_USE (getsockname,
+ "getsockname() used without including <sys/socket.h>");
+ _GL_WARN_ON_USE (getsockopt,
+ "getsockopt() used without including <sys/socket.h>");
+ _GL_WARN_ON_USE (listen,
+ "listen() used without including <sys/socket.h>");
+ _GL_WARN_ON_USE (recv,
+ "recv() used without including <sys/socket.h>");
+ _GL_WARN_ON_USE (send,
+ "send() used without including <sys/socket.h>");
+ _GL_WARN_ON_USE (recvfrom,
+ "recvfrom() used without including <sys/socket.h>");
+ _GL_WARN_ON_USE (sendto,
+ "sendto() used without including <sys/socket.h>");
+ _GL_WARN_ON_USE (setsockopt,
+ "setsockopt() used without including <sys/socket.h>");
+ _GL_WARN_ON_USE (shutdown,
+ "shutdown() used without including <sys/socket.h>");
+# endif
+# endif
+#endif
+
+
+#if @GNULIB_PSELECT@
+# if @REPLACE_PSELECT@
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef pselect
+# define pselect rpl_pselect
+# endif
+_GL_FUNCDECL_RPL (pselect, int,
+ (int, fd_set *restrict, fd_set *restrict, fd_set *restrict,
+ struct timespec const *restrict, const sigset_t *restrict));
+_GL_CXXALIAS_RPL (pselect, int,
+ (int, fd_set *restrict, fd_set *restrict, fd_set *restrict,
+ struct timespec const *restrict, const sigset_t *restrict));
+# else
+# if !@HAVE_PSELECT@
+_GL_FUNCDECL_SYS (pselect, int,
+ (int, fd_set *restrict, fd_set *restrict, fd_set *restrict,
+ struct timespec const *restrict, const sigset_t *restrict));
+# endif
+_GL_CXXALIAS_SYS (pselect, int,
+ (int, fd_set *restrict, fd_set *restrict, fd_set *restrict,
+ struct timespec const *restrict, const sigset_t *restrict));
+# endif
+_GL_CXXALIASWARN (pselect);
+#elif defined GNULIB_POSIXCHECK
+# undef pselect
+# if HAVE_RAW_DECL_PSELECT
+_GL_WARN_ON_USE (pselect, "pselect is not portable - "
+ "use gnulib module pselect for portability");
+# endif
+#endif
+
+#if @GNULIB_SELECT@
+# if @REPLACE_SELECT@
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef select
+# define select rpl_select
+# endif
+_GL_FUNCDECL_RPL (select, int,
+ (int, fd_set *, fd_set *, fd_set *, struct timeval *));
+_GL_CXXALIAS_RPL (select, int,
+ (int, fd_set *, fd_set *, fd_set *, struct timeval *));
+# else
+_GL_CXXALIAS_SYS (select, int,
+ (int, fd_set *, fd_set *, fd_set *, struct timeval *));
+# endif
+_GL_CXXALIASWARN (select);
+#elif @HAVE_WINSOCK2_H@
+# undef select
+# define select select_used_without_requesting_gnulib_module_select
+#elif defined GNULIB_POSIXCHECK
+# undef select
+# if HAVE_RAW_DECL_SELECT
+_GL_WARN_ON_USE (select, "select is not always POSIX compliant - "
+ "use gnulib module select for portability");
+# endif
+#endif
+
+
+#endif /* _@GUARD_PREFIX@_SYS_SELECT_H */
+#endif /* _@GUARD_PREFIX@_SYS_SELECT_H */
+#endif /* OSF/1 */
diff --git a/m4/dup2.m4 b/m4/dup2.m4
new file mode 100644
index 000000000..269cfdc11
--- /dev/null
+++ b/m4/dup2.m4
@@ -0,0 +1,84 @@
+#serial 19
+dnl Copyright (C) 2002, 2005, 2007, 2009-2013 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_DUP2],
+[
+ AC_REQUIRE([gl_UNISTD_H_DEFAULTS])
+ AC_REQUIRE([AC_CANONICAL_HOST])
+ m4_ifdef([gl_FUNC_DUP2_OBSOLETE], [
+ AC_CHECK_FUNCS_ONCE([dup2])
+ if test $ac_cv_func_dup2 = no; then
+ HAVE_DUP2=0
+ fi
+ ], [
+ AC_DEFINE([HAVE_DUP2], [1], [Define to 1 if you have the 'dup2' function.])
+ ])
+ if test $HAVE_DUP2 = 1; then
+ AC_CACHE_CHECK([whether dup2 works], [gl_cv_func_dup2_works],
+ [AC_RUN_IFELSE([
+ AC_LANG_PROGRAM([[#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>]],
+ [int result = 0;
+#ifdef FD_CLOEXEC
+ if (fcntl (1, F_SETFD, FD_CLOEXEC) == -1)
+ result |= 1;
+#endif
+ if (dup2 (1, 1) == 0)
+ result |= 2;
+#ifdef FD_CLOEXEC
+ if (fcntl (1, F_GETFD) != FD_CLOEXEC)
+ result |= 4;
+#endif
+ close (0);
+ if (dup2 (0, 0) != -1)
+ result |= 8;
+ /* Many gnulib modules require POSIX conformance of EBADF. */
+ if (dup2 (2, 1000000) == -1 && errno != EBADF)
+ result |= 16;
+ /* Flush out a cygwin core dump. */
+ if (dup2 (2, -1) != -1 || errno != EBADF)
+ result |= 32;
+ return result;
+ ])
+ ],
+ [gl_cv_func_dup2_works=yes], [gl_cv_func_dup2_works=no],
+ [case "$host_os" in
+ mingw*) # on this platform, dup2 always returns 0 for success
+ gl_cv_func_dup2_works="guessing no" ;;
+ cygwin*) # on cygwin 1.5.x, dup2(1,1) returns 0
+ gl_cv_func_dup2_works="guessing no" ;;
+ linux*) # On linux between 2008-07-27 and 2009-05-11, dup2 of a
+ # closed fd may yield -EBADF instead of -1 / errno=EBADF.
+ gl_cv_func_dup2_works="guessing no" ;;
+ freebsd*) # on FreeBSD 6.1, dup2(1,1000000) gives EMFILE, not EBADF.
+ gl_cv_func_dup2_works="guessing no" ;;
+ haiku*) # on Haiku alpha 2, dup2(1, 1) resets FD_CLOEXEC.
+ gl_cv_func_dup2_works="guessing no" ;;
+ *) gl_cv_func_dup2_works="guessing yes" ;;
+ esac])
+ ])
+ case "$gl_cv_func_dup2_works" in
+ *yes) ;;
+ *)
+ REPLACE_DUP2=1
+ ;;
+ esac
+ fi
+ dnl Replace dup2() for supporting the gnulib-defined fchdir() function,
+ dnl to keep fchdir's bookkeeping up-to-date.
+ m4_ifdef([gl_FUNC_FCHDIR], [
+ gl_TEST_FCHDIR
+ if test $HAVE_FCHDIR = 0; then
+ if test $HAVE_DUP2 = 1; then
+ REPLACE_DUP2=1
+ fi
+ fi
+ ])
+])
+
+# Prerequisites of lib/dup2.c.
+AC_DEFUN([gl_PREREQ_DUP2], [])
diff --git a/m4/gnulib-cache.m4 b/m4/gnulib-cache.m4
index c0fd22691..9fb3a9096 100644
--- a/m4/gnulib-cache.m4
+++ b/m4/gnulib-cache.m4
@@ -27,7 +27,7 @@
# Specification in the form of a command-line invocation:
-# gnulib-tool --import --dir=. --local-dir=gnulib-local --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --lgpl=3 --no-conditional-dependencies --libtool --macro-prefix=gl --no-vc-files accept alignof alloca-opt announce-gen autobuild bind byteswap canonicalize-lgpl ceil clock-time close connect dirfd duplocale environ extensions flock floor fpieee frexp full-read full-write func gendocs getaddrinfo getpeername getsockname getsockopt git-version-gen gitlog-to-changelog gnu-web-doc-update gnupload havelib iconv_open-utf inet_ntop inet_pton isinf isnan ldexp lib-symbol-versions lib-symbol-visibility libunistring listen localcharset locale log1p maintainer-makefile malloc-gnu malloca nl_langinfo nproc open pipe2 putenv recv recvfrom regex rename send sendto setenv setsockopt shutdown socket stat-time stdlib strftime striconveh string sys_stat trunc verify vsnprintf warnings wchar
+# gnulib-tool --import --dir=. --local-dir=gnulib-local --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --lgpl=3 --no-conditional-dependencies --libtool --macro-prefix=gl --no-vc-files accept alignof alloca-opt announce-gen autobuild bind byteswap canonicalize-lgpl ceil clock-time close connect dirfd duplocale environ extensions flock floor fpieee frexp full-read full-write func gendocs getaddrinfo getpeername getsockname getsockopt git-version-gen gitlog-to-changelog gnu-web-doc-update gnupload havelib iconv_open-utf inet_ntop inet_pton isinf isnan ldexp lib-symbol-versions lib-symbol-visibility libunistring listen localcharset locale log1p maintainer-makefile malloc-gnu malloca nl_langinfo nproc open pipe2 putenv recv recvfrom regex rename select send sendto setenv setsockopt shutdown socket stat-time stdlib strftime striconveh string sys_stat trunc verify vsnprintf warnings wchar
# Specification in the form of a few gnulib-tool.m4 macro invocations:
gl_LOCAL_DIR([gnulib-local])
@@ -90,6 +90,7 @@ gl_MODULES([
recvfrom
regex
rename
+ select
send
sendto
setenv
diff --git a/m4/gnulib-comp.m4 b/m4/gnulib-comp.m4
index ce1be65fe..ef150cb3c 100644
--- a/m4/gnulib-comp.m4
+++ b/m4/gnulib-comp.m4
@@ -41,6 +41,7 @@ AC_DEFUN([gl_EARLY],
AC_REQUIRE([AM_PROG_CC_C_O])
# Code from module accept:
# Code from module alignof:
+ # Code from module alloca:
# Code from module alloca-opt:
# Code from module announce-gen:
# Code from module arpa_inet:
@@ -65,6 +66,7 @@ AC_DEFUN([gl_EARLY],
# Code from module dirname-lgpl:
# Code from module dosname:
# Code from module double-slash-root:
+ # Code from module dup2:
# Code from module duplocale:
# Code from module environ:
# Code from module errno:
@@ -158,6 +160,7 @@ AC_DEFUN([gl_EARLY],
# Code from module safe-read:
# Code from module safe-write:
# Code from module same-inode:
+ # Code from module select:
# Code from module send:
# Code from module sendto:
# Code from module servent:
@@ -190,6 +193,7 @@ AC_DEFUN([gl_EARLY],
# Code from module striconveh:
# Code from module string:
# Code from module sys_file:
+ # Code from module sys_select:
# Code from module sys_socket:
# Code from module sys_stat:
# Code from module sys_time:
@@ -238,6 +242,10 @@ AC_DEFUN([gl_INIT],
AC_LIBOBJ([accept])
fi
gl_SYS_SOCKET_MODULE_INDICATOR([accept])
+changequote(,)dnl
+LTALLOCA=`echo "$ALLOCA" | sed -e 's/\.[^.]* /.lo /g;s/\.[^.]*$/.lo/'`
+changequote([, ])dnl
+AC_SUBST([LTALLOCA])
gl_FUNC_ALLOCA
gl_HEADER_ARPA_INET
AC_PROG_MKDIR_P
@@ -287,6 +295,12 @@ AC_DEFUN([gl_INIT],
gl_DIRENT_MODULE_INDICATOR([dirfd])
gl_DIRNAME_LGPL
gl_DOUBLE_SLASH_ROOT
+ gl_FUNC_DUP2
+ if test $HAVE_DUP2 = 0 || test $REPLACE_DUP2 = 1; then
+ AC_LIBOBJ([dup2])
+ gl_PREREQ_DUP2
+ fi
+ gl_UNISTD_MODULE_INDICATOR([dup2])
gl_FUNC_DUPLOCALE
if test $REPLACE_DUPLOCALE = 1; then
AC_LIBOBJ([duplocale])
@@ -587,6 +601,11 @@ AC_DEFUN([gl_INIT],
gl_MATH_MODULE_INDICATOR([round])
gl_PREREQ_SAFE_READ
gl_PREREQ_SAFE_WRITE
+ gl_FUNC_SELECT
+ if test $REPLACE_SELECT = 1; then
+ AC_LIBOBJ([select])
+ fi
+ gl_SYS_SELECT_MODULE_INDICATOR([select])
AC_REQUIRE([gl_HEADER_SYS_SOCKET])
if test "$ac_cv_header_winsock2_h" = yes; then
AC_LIBOBJ([send])
@@ -658,6 +677,8 @@ AC_DEFUN([gl_INIT],
gl_HEADER_STRING_H
gl_HEADER_SYS_FILE_H
AC_PROG_MKDIR_P
+ gl_HEADER_SYS_SELECT
+ AC_PROG_MKDIR_P
gl_HEADER_SYS_SOCKET
AC_PROG_MKDIR_P
gl_HEADER_SYS_STAT_H
@@ -863,6 +884,7 @@ AC_DEFUN([gl_FILE_LIST], [
doc/gendocs_template
lib/accept.c
lib/alignof.h
+ lib/alloca.c
lib/alloca.in.h
lib/arpa_inet.in.h
lib/asnprintf.c
@@ -888,6 +910,7 @@ AC_DEFUN([gl_FILE_LIST], [
lib/dirname-lgpl.c
lib/dirname.h
lib/dosname.h
+ lib/dup2.c
lib/duplocale.c
lib/errno.in.h
lib/fcntl.in.h
@@ -989,6 +1012,7 @@ AC_DEFUN([gl_FILE_LIST], [
lib/safe-write.c
lib/safe-write.h
lib/same-inode.h
+ lib/select.c
lib/send.c
lib/sendto.c
lib/setenv.c
@@ -1017,6 +1041,7 @@ AC_DEFUN([gl_FILE_LIST], [
lib/string.in.h
lib/stripslash.c
lib/sys_file.in.h
+ lib/sys_select.in.h
lib/sys_socket.c
lib/sys_socket.in.h
lib/sys_stat.in.h
@@ -1068,6 +1093,7 @@ AC_DEFUN([gl_FILE_LIST], [
m4/dirfd.m4
m4/dirname.m4
m4/double-slash-root.m4
+ m4/dup2.m4
m4/duplocale.m4
m4/eealloc.m4
m4/environ.m4
@@ -1158,6 +1184,7 @@ AC_DEFUN([gl_FILE_LIST], [
m4/round.m4
m4/safe-read.m4
m4/safe-write.m4
+ m4/select.m4
m4/servent.m4
m4/setenv.m4
m4/signal_h.m4
@@ -1180,6 +1207,7 @@ AC_DEFUN([gl_FILE_LIST], [
m4/strftime.m4
m4/string_h.m4
m4/sys_file_h.m4
+ m4/sys_select_h.m4
m4/sys_socket_h.m4
m4/sys_stat_h.m4
m4/sys_time_h.m4
diff --git a/m4/select.m4 b/m4/select.m4
new file mode 100644
index 000000000..d025355f9
--- /dev/null
+++ b/m4/select.m4
@@ -0,0 +1,113 @@
+# select.m4 serial 7
+dnl Copyright (C) 2009-2013 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_SELECT],
+[
+ AC_REQUIRE([gl_HEADER_SYS_SELECT])
+ AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
+ AC_REQUIRE([gl_SOCKETS])
+ if test "$ac_cv_header_winsock2_h" = yes; then
+ REPLACE_SELECT=1
+ else
+ dnl On Interix 3.5, select(0, NULL, NULL, NULL, timeout) fails with error
+ dnl EFAULT.
+ AC_CHECK_HEADERS_ONCE([sys/select.h])
+ AC_CACHE_CHECK([whether select supports a 0 argument],
+ [gl_cv_func_select_supports0],
+ [
+ AC_RUN_IFELSE([AC_LANG_SOURCE([[
+#include <sys/types.h>
+#include <sys/time.h>
+#if HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+int main ()
+{
+ struct timeval timeout;
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 5;
+ return select (0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &timeout) < 0;
+}]])], [gl_cv_func_select_supports0=yes], [gl_cv_func_select_supports0=no],
+ [
+changequote(,)dnl
+ case "$host_os" in
+ # Guess no on Interix.
+ interix*) gl_cv_func_select_supports0="guessing no";;
+ # Guess yes otherwise.
+ *) gl_cv_func_select_supports0="guessing yes";;
+ esac
+changequote([,])dnl
+ ])
+ ])
+ case "$gl_cv_func_select_supports0" in
+ *yes) ;;
+ *) REPLACE_SELECT=1 ;;
+ esac
+
+ dnl On FreeBSD 8.2, select() doesn't always reject bad fds.
+ AC_CACHE_CHECK([whether select detects invalid fds],
+ [gl_cv_func_select_detects_ebadf],
+ [
+ AC_RUN_IFELSE([AC_LANG_PROGRAM([[
+#include <sys/types.h>
+#include <sys/time.h>
+#if HAVE_SYS_SELECT_H
+# include <sys/select.h>
+#endif
+#include <unistd.h>
+#include <errno.h>
+]],[[
+ fd_set set;
+ dup2(0, 16);
+ FD_ZERO(&set);
+ FD_SET(16, &set);
+ close(16);
+ struct timeval timeout;
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 5;
+ return select (17, &set, NULL, NULL, &timeout) != -1 || errno != EBADF;
+]])], [gl_cv_func_select_detects_ebadf=yes],
+ [gl_cv_func_select_detects_ebadf=no],
+ [
+ case "$host_os" in
+ # Guess yes on glibc systems.
+ *-gnu*) gl_cv_func_select_detects_ebadf="guessing yes" ;;
+ # If we don't know, assume the worst.
+ *) gl_cv_func_select_detects_ebadf="guessing no" ;;
+ esac
+ ])
+ ])
+ case $gl_cv_func_select_detects_ebadf in
+ *yes) ;;
+ *) REPLACE_SELECT=1 ;;
+ esac
+ fi
+
+ dnl Determine the needed libraries.
+ LIB_SELECT="$LIBSOCKET"
+ if test $REPLACE_SELECT = 1; then
+ case "$host_os" in
+ mingw*)
+ dnl On the MSVC platform, the function MsgWaitForMultipleObjects
+ dnl (used in lib/select.c) requires linking with -luser32. On mingw,
+ dnl it is implicit.
+ AC_LINK_IFELSE(
+ [AC_LANG_SOURCE([[
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+int
+main ()
+{
+ MsgWaitForMultipleObjects (0, NULL, 0, 0, 0);
+ return 0;
+}]])],
+ [],
+ [LIB_SELECT="$LIB_SELECT -luser32"])
+ ;;
+ esac
+ fi
+ AC_SUBST([LIB_SELECT])
+])
diff --git a/m4/sys_select_h.m4 b/m4/sys_select_h.m4
new file mode 100644
index 000000000..496232851
--- /dev/null
+++ b/m4/sys_select_h.m4
@@ -0,0 +1,95 @@
+# sys_select_h.m4 serial 20
+dnl Copyright (C) 2006-2013 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_HEADER_SYS_SELECT],
+[
+ AC_REQUIRE([AC_C_RESTRICT])
+ AC_REQUIRE([gl_SYS_SELECT_H_DEFAULTS])
+ AC_CACHE_CHECK([whether <sys/select.h> is self-contained],
+ [gl_cv_header_sys_select_h_selfcontained],
+ [
+ dnl Test against two bugs:
+ dnl 1. On many platforms, <sys/select.h> assumes prior inclusion of
+ dnl <sys/types.h>.
+ dnl 2. On OSF/1 4.0, <sys/select.h> provides only a forward declaration
+ dnl of 'struct timeval', and no definition of this type.
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/select.h>]],
+ [[struct timeval b;]])],
+ [gl_cv_header_sys_select_h_selfcontained=yes],
+ [gl_cv_header_sys_select_h_selfcontained=no])
+ dnl Test against another bug:
+ dnl 3. On Solaris 10, <sys/select.h> provides an FD_ZERO implementation
+ dnl that relies on memset(), but without including <string.h>.
+ if test $gl_cv_header_sys_select_h_selfcontained = yes; then
+ AC_COMPILE_IFELSE(
+ [AC_LANG_PROGRAM([[#include <sys/select.h>]],
+ [[int memset; int bzero;]])
+ ],
+ [AC_LINK_IFELSE(
+ [AC_LANG_PROGRAM([[#include <sys/select.h>]], [[
+ #undef memset
+ #define memset nonexistent_memset
+ extern
+ #ifdef __cplusplus
+ "C"
+ #endif
+ void *memset (void *, int, unsigned long);
+ #undef bzero
+ #define bzero nonexistent_bzero
+ extern
+ #ifdef __cplusplus
+ "C"
+ #endif
+ void bzero (void *, unsigned long);
+ fd_set fds;
+ FD_ZERO (&fds);
+ ]])
+ ],
+ [],
+ [gl_cv_header_sys_select_h_selfcontained=no])
+ ])
+ fi
+ ])
+ dnl <sys/select.h> is always overridden, because of GNULIB_POSIXCHECK.
+ gl_CHECK_NEXT_HEADERS([sys/select.h])
+ if test $ac_cv_header_sys_select_h = yes; then
+ HAVE_SYS_SELECT_H=1
+ else
+ HAVE_SYS_SELECT_H=0
+ fi
+ AC_SUBST([HAVE_SYS_SELECT_H])
+ gl_PREREQ_SYS_H_WINSOCK2
+
+ dnl Check for declarations of anything we want to poison if the
+ dnl corresponding gnulib module is not in use.
+ gl_WARN_ON_USE_PREPARE([[
+/* Some systems require prerequisite headers. */
+#include <sys/types.h>
+#if !(defined __GLIBC__ && !defined __UCLIBC__) && HAVE_SYS_TIME_H
+# include <sys/time.h>
+#endif
+#include <sys/select.h>
+ ]], [pselect select])
+])
+
+AC_DEFUN([gl_SYS_SELECT_MODULE_INDICATOR],
+[
+ dnl Use AC_REQUIRE here, so that the default settings are expanded once only.
+ AC_REQUIRE([gl_SYS_SELECT_H_DEFAULTS])
+ gl_MODULE_INDICATOR_SET_VARIABLE([$1])
+ dnl Define it also as a C macro, for the benefit of the unit tests.
+ gl_MODULE_INDICATOR_FOR_TESTS([$1])
+])
+
+AC_DEFUN([gl_SYS_SELECT_H_DEFAULTS],
+[
+ GNULIB_PSELECT=0; AC_SUBST([GNULIB_PSELECT])
+ GNULIB_SELECT=0; AC_SUBST([GNULIB_SELECT])
+ dnl Assume proper GNU behavior unless another module says otherwise.
+ HAVE_PSELECT=1; AC_SUBST([HAVE_PSELECT])
+ REPLACE_PSELECT=0; AC_SUBST([REPLACE_PSELECT])
+ REPLACE_SELECT=0; AC_SUBST([REPLACE_SELECT])
+])