mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-04-29 19:30:36 +02:00
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.
This commit is contained in:
parent
af07e10429
commit
3dac6181c1
10 changed files with 1881 additions and 2 deletions
|
@ -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
|
||||
|
|
478
lib/alloca.c
Normal file
478
lib/alloca.c
Normal file
|
@ -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 */
|
160
lib/dup2.c
Normal file
160
lib/dup2.c
Normal file
|
@ -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 */
|
547
lib/select.c
Normal file
547
lib/select.c
Normal file
|
@ -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
|
309
lib/sys_select.in.h
Normal file
309
lib/sys_select.in.h
Normal file
|
@ -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 */
|
84
m4/dup2.m4
Normal file
84
m4/dup2.m4
Normal file
|
@ -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], [])
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
113
m4/select.m4
Normal file
113
m4/select.m4
Normal file
|
@ -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])
|
||||
])
|
95
m4/sys_select_h.m4
Normal file
95
m4/sys_select_h.m4
Normal file
|
@ -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])
|
||||
])
|
Loading…
Add table
Add a link
Reference in a new issue