Browse Source
A few sims use this to emulate the syscall & provide network functionality.binutils-2_37-branch
20 changed files with 2402 additions and 26 deletions
@ -0,0 +1,117 @@ |
|||
# select.m4 serial 12 |
|||
dnl Copyright (C) 2009-2021 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_C_RESTRICT]) |
|||
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> |
|||
]GL_MDA_DEFINES], |
|||
[[ |
|||
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 Linux systems. |
|||
linux-* | linux) gl_cv_func_select_detects_ebadf="guessing yes" ;; |
|||
# Guess yes on glibc systems. |
|||
*-gnu* | gnu*) gl_cv_func_select_detects_ebadf="guessing yes" ;; |
|||
# If we don't know, obey --enable-cross-guesses. |
|||
*) gl_cv_func_select_detects_ebadf="$gl_cross_guess_normal" ;; |
|||
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]) |
|||
]) |
|||
@ -0,0 +1,96 @@ |
|||
# socketlib.m4 serial 3 |
|||
dnl Copyright (C) 2008-2021 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. |
|||
|
|||
dnl gl_SOCKETLIB |
|||
dnl Determines the library to use for socket functions. |
|||
dnl Sets and AC_SUBSTs LIBSOCKET. |
|||
|
|||
AC_DEFUN([gl_SOCKETLIB], |
|||
[ |
|||
gl_PREREQ_SYS_H_WINSOCK2 dnl for HAVE_WINSOCK2_H |
|||
LIBSOCKET= |
|||
if test $HAVE_WINSOCK2_H = 1; then |
|||
dnl Native Windows API (not Cygwin). |
|||
dnl If the function WSAStartup exists (declared in <winsock2.h> and |
|||
dnl defined through -lws2_32), we need to call it. |
|||
AC_CACHE_CHECK([for WSAStartup], |
|||
[gl_cv_func_wsastartup], [ |
|||
gl_save_LIBS="$LIBS" |
|||
LIBS="$LIBS -lws2_32" |
|||
AC_LINK_IFELSE( |
|||
[AC_LANG_PROGRAM([[ |
|||
#ifdef HAVE_WINSOCK2_H |
|||
# include <winsock2.h> |
|||
#endif]], [[ |
|||
WORD wVersionRequested = MAKEWORD(1, 1); |
|||
WSADATA wsaData; |
|||
int err = WSAStartup(wVersionRequested, &wsaData); |
|||
WSACleanup (); |
|||
]]) |
|||
], |
|||
[gl_cv_func_wsastartup=yes], |
|||
[gl_cv_func_wsastartup=no]) |
|||
LIBS="$gl_save_LIBS" |
|||
]) |
|||
if test "$gl_cv_func_wsastartup" = "yes"; then |
|||
AC_DEFINE([WINDOWS_SOCKETS], [1], [Define if WSAStartup is needed.]) |
|||
LIBSOCKET='-lws2_32' |
|||
fi |
|||
else |
|||
dnl Unix API. |
|||
dnl Solaris has most socket functions in libsocket. |
|||
dnl Haiku has most socket functions in libnetwork. |
|||
dnl BeOS has most socket functions in libnet. |
|||
dnl On HP-UX, do NOT link with libxnet, because in 64-bit mode this would |
|||
dnl break code (e.g. in libraries) that invokes accept(), getpeername(), |
|||
dnl getsockname(), getsockopt(), or recvfrom() with a 32-bit addrlen. See |
|||
dnl "man xopen_networking" for details. |
|||
AC_CACHE_CHECK([for library containing setsockopt], [gl_cv_lib_socket], [ |
|||
gl_cv_lib_socket= |
|||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[extern |
|||
#ifdef __cplusplus |
|||
"C" |
|||
#endif |
|||
char setsockopt();]], [[setsockopt();]])], |
|||
[], |
|||
[gl_save_LIBS="$LIBS" |
|||
LIBS="$gl_save_LIBS -lsocket" |
|||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[extern |
|||
#ifdef __cplusplus |
|||
"C" |
|||
#endif |
|||
char setsockopt();]], [[setsockopt();]])], |
|||
[gl_cv_lib_socket="-lsocket"]) |
|||
if test -z "$gl_cv_lib_socket"; then |
|||
LIBS="$gl_save_LIBS -lnetwork" |
|||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[extern |
|||
#ifdef __cplusplus |
|||
"C" |
|||
#endif |
|||
char setsockopt();]], [[setsockopt();]])], |
|||
[gl_cv_lib_socket="-lnetwork"]) |
|||
if test -z "$gl_cv_lib_socket"; then |
|||
LIBS="$gl_save_LIBS -lnet" |
|||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[extern |
|||
#ifdef __cplusplus |
|||
"C" |
|||
#endif |
|||
char setsockopt();]], [[setsockopt();]])], |
|||
[gl_cv_lib_socket="-lnet"]) |
|||
fi |
|||
fi |
|||
LIBS="$gl_save_LIBS" |
|||
]) |
|||
if test -z "$gl_cv_lib_socket"; then |
|||
gl_cv_lib_socket="none needed" |
|||
fi |
|||
]) |
|||
if test "$gl_cv_lib_socket" != "none needed"; then |
|||
LIBSOCKET="$gl_cv_lib_socket" |
|||
fi |
|||
fi |
|||
AC_SUBST([LIBSOCKET]) |
|||
]) |
|||
@ -0,0 +1,17 @@ |
|||
# sockets.m4 serial 7 |
|||
dnl Copyright (C) 2008-2021 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_SOCKETS], |
|||
[ |
|||
AC_REQUIRE([AC_C_INLINE]) |
|||
AC_REQUIRE([gl_SOCKETLIB]) |
|||
gl_PREREQ_SOCKETS |
|||
]) |
|||
|
|||
# Prerequisites of lib/sockets.c. |
|||
AC_DEFUN([gl_PREREQ_SOCKETS], [ |
|||
: |
|||
]) |
|||
@ -0,0 +1,95 @@ |
|||
# sys_select_h.m4 serial 20 |
|||
dnl Copyright (C) 2006-2021 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]) |
|||
]) |
|||
@ -0,0 +1,597 @@ |
|||
/* Emulation for select(2)
|
|||
Contributed by Paolo Bonzini. |
|||
|
|||
Copyright 2008-2021 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 General Public License as published by |
|||
the Free Software Foundation; either version 3, 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 General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU General Public License along |
|||
with this program; if not, see <https://www.gnu.org/licenses/>. */
|
|||
|
|||
#include <config.h> |
|||
|
|||
/* Specification. */ |
|||
#include <sys/select.h> |
|||
|
|||
#if defined _WIN32 && ! defined __CYGWIN__ |
|||
/* Native Windows. */ |
|||
|
|||
#include <alloca.h> |
|||
#include <assert.h> |
|||
#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> |
|||
|
|||
#if GNULIB_MSVC_NOTHROW |
|||
# include "msvc-nothrow.h" |
|||
#else |
|||
# include <io.h> |
|||
#endif |
|||
|
|||
#undef select |
|||
|
|||
/* Don't assume that UNICODE is not defined. */ |
|||
#undef GetModuleHandle |
|||
#define GetModuleHandle GetModuleHandleA |
|||
#undef PeekConsoleInput |
|||
#define PeekConsoleInput PeekConsoleInputA |
|||
#undef CreateEvent |
|||
#define CreateEvent CreateEventA |
|||
#undef PeekMessage |
|||
#define PeekMessage PeekMessageA |
|||
#undef DispatchMessage |
|||
#define DispatchMessage DispatchMessageA |
|||
|
|||
/* Avoid warnings from gcc -Wcast-function-type. */ |
|||
#define GetProcAddress \ |
|||
(void *) GetProcAddress |
|||
|
|||
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 |
|||
|
|||
static BOOL IsConsoleHandle (HANDLE h) |
|||
{ |
|||
DWORD mode; |
|||
return GetConsoleMode (h, &mode) != 0; |
|||
} |
|||
|
|||
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; |
|||
clock_t tend; |
|||
|
|||
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; |
|||
|
|||
/* When will the waiting period expire? */ |
|||
if (wait_timeout != INFINITE) |
|||
tend = clock () + wait_timeout; |
|||
|
|||
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; |
|||
} |
|||
|
|||
/* How much is left to wait? */ |
|||
if (wait_timeout != INFINITE) |
|||
{ |
|||
clock_t tnow = clock (); |
|||
if (tend >= tnow) |
|||
wait_timeout = tend - tnow; |
|||
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 |
|||
/* If NHANDLES > 1, but no bits are set, it means we've
|
|||
been told incorrectly that some handle was signaled. |
|||
This happens with anonymous pipes, which always cause |
|||
MsgWaitForMultipleObjects to exit immediately, but no |
|||
data is found ready to be read by windows_poll_handle. |
|||
To avoid a total failure (whereby we return zero and |
|||
don't wait at all), let's poll in a more busy loop. */ |
|||
|| (wait_timeout != 0 && nhandles > 1))) |
|||
{ |
|||
/* 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; |
|||
} |
|||
if (timeout && wait_timeout == 0 && rc == 0) |
|||
timeout->tv_sec = timeout->tv_usec = 0; |
|||
} |
|||
|
|||
/* 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 <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 |
|||
@ -0,0 +1,161 @@ |
|||
/* sockets.c --- wrappers for Windows socket functions
|
|||
|
|||
Copyright (C) 2008-2021 Free Software Foundation, Inc. |
|||
|
|||
This program is free software: you can redistribute it and/or modify |
|||
it under the terms of the GNU 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 General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU General Public License |
|||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
|||
|
|||
/* Written by Simon Josefsson */ |
|||
|
|||
#include <config.h> |
|||
|
|||
/* Specification. */ |
|||
#include "sockets.h" |
|||
|
|||
#if WINDOWS_SOCKETS |
|||
|
|||
/* This includes winsock2.h on MinGW. */ |
|||
# include <sys/socket.h> |
|||
|
|||
# include "fd-hook.h" |
|||
# if GNULIB_MSVC_NOTHROW |
|||
# include "msvc-nothrow.h" |
|||
# else |
|||
# include <io.h> |
|||
# endif |
|||
|
|||
/* Get set_winsock_errno, FD_TO_SOCKET etc. */ |
|||
# include "w32sock.h" |
|||
|
|||
static int |
|||
close_fd_maybe_socket (const struct fd_hook *remaining_list, |
|||
gl_close_fn primary, |
|||
int fd) |
|||
{ |
|||
/* Note about multithread-safety: There is a race condition where, between
|
|||
our calls to closesocket() and the primary close(), some other thread |
|||
could make system calls that allocate precisely the same HANDLE value |
|||
as sock; then the primary close() would call CloseHandle() on it. */ |
|||
SOCKET sock; |
|||
WSANETWORKEVENTS ev; |
|||
|
|||
/* Test whether fd refers to a socket. */ |
|||
sock = FD_TO_SOCKET (fd); |
|||
ev.lNetworkEvents = 0xDEADBEEF; |
|||
WSAEnumNetworkEvents (sock, NULL, &ev); |
|||
if (ev.lNetworkEvents != 0xDEADBEEF) |
|||
{ |
|||
/* fd refers to a socket. */ |
|||
/* FIXME: other applications, like squid, use an undocumented
|
|||
_free_osfhnd free function. But this is not enough: The 'osfile' |
|||
flags for fd also needs to be cleared, but it is hard to access it. |
|||
Instead, here we just close twice the file descriptor. */ |
|||
if (closesocket (sock)) |
|||
{ |
|||
set_winsock_errno (); |
|||
return -1; |
|||
} |
|||
else |
|||
{ |
|||
/* This call frees the file descriptor and does a
|
|||
CloseHandle ((HANDLE) _get_osfhandle (fd)), which fails. */ |
|||
_close (fd); |
|||
return 0; |
|||
} |
|||
} |
|||
else |
|||
/* Some other type of file descriptor. */ |
|||
return execute_close_hooks (remaining_list, primary, fd); |
|||
} |
|||
|
|||
static int |
|||
ioctl_fd_maybe_socket (const struct fd_hook *remaining_list, |
|||
gl_ioctl_fn primary, |
|||
int fd, int request, void *arg) |
|||
{ |
|||
SOCKET sock; |
|||
WSANETWORKEVENTS ev; |
|||
|
|||
/* Test whether fd refers to a socket. */ |
|||
sock = FD_TO_SOCKET (fd); |
|||
ev.lNetworkEvents = 0xDEADBEEF; |
|||
WSAEnumNetworkEvents (sock, NULL, &ev); |
|||
if (ev.lNetworkEvents != 0xDEADBEEF) |
|||
{ |
|||
/* fd refers to a socket. */ |
|||
if (ioctlsocket (sock, request, arg) < 0) |
|||
{ |
|||
set_winsock_errno (); |
|||
return -1; |
|||
} |
|||
else |
|||
return 0; |
|||
} |
|||
else |
|||
/* Some other type of file descriptor. */ |
|||
return execute_ioctl_hooks (remaining_list, primary, fd, request, arg); |
|||
} |
|||
|
|||
static struct fd_hook fd_sockets_hook; |
|||
|
|||
static int initialized_sockets_version /* = 0 */; |
|||
|
|||
#endif /* WINDOWS_SOCKETS */ |
|||
|
|||
int |
|||
gl_sockets_startup (int version _GL_UNUSED) |
|||
{ |
|||
#if WINDOWS_SOCKETS |
|||
if (version > initialized_sockets_version) |
|||
{ |
|||
WSADATA data; |
|||
int err; |
|||
|
|||
err = WSAStartup (version, &data); |
|||
if (err != 0) |
|||
return 1; |
|||
|
|||
if (data.wVersion != version) |
|||
{ |
|||
WSACleanup (); |
|||
return 2; |
|||
} |
|||
|
|||
if (initialized_sockets_version == 0) |
|||
register_fd_hook (close_fd_maybe_socket, ioctl_fd_maybe_socket, |
|||
&fd_sockets_hook); |
|||
|
|||
initialized_sockets_version = version; |
|||
} |
|||
#endif |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
int |
|||
gl_sockets_cleanup (void) |
|||
{ |
|||
#if WINDOWS_SOCKETS |
|||
int err; |
|||
|
|||
initialized_sockets_version = 0; |
|||
|
|||
unregister_fd_hook (&fd_sockets_hook); |
|||
|
|||
err = WSACleanup (); |
|||
if (err != 0) |
|||
return 1; |
|||
#endif |
|||
|
|||
return 0; |
|||
} |
|||
@ -0,0 +1,66 @@ |
|||
/* sockets.h - wrappers for Windows socket functions
|
|||
|
|||
Copyright (C) 2008-2021 Free Software Foundation, Inc. |
|||
|
|||
This program is free software: you can redistribute it and/or modify |
|||
it under the terms of the GNU 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 General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU General Public License |
|||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
|||
|
|||
/* Written by Simon Josefsson */ |
|||
|
|||
#ifndef SOCKETS_H |
|||
#define SOCKETS_H 1 |
|||
|
|||
#define SOCKETS_1_0 0x0001 |
|||
#define SOCKETS_1_1 0x0101 |
|||
#define SOCKETS_2_0 0x0002 |
|||
#define SOCKETS_2_1 0x0102 |
|||
#define SOCKETS_2_2 0x0202 |
|||
|
|||
int gl_sockets_startup (int version) |
|||
#ifndef WINDOWS_SOCKETS |
|||
_GL_ATTRIBUTE_CONST |
|||
#endif |
|||
; |
|||
|
|||
int gl_sockets_cleanup (void) |
|||
#ifndef WINDOWS_SOCKETS |
|||
_GL_ATTRIBUTE_CONST |
|||
#endif |
|||
; |
|||
|
|||
/* This function is useful it you create a socket using gnulib's
|
|||
Winsock wrappers but needs to pass on the socket handle to some |
|||
other library that only accepts sockets. */ |
|||
#ifdef WINDOWS_SOCKETS |
|||
|
|||
# include <sys/socket.h> |
|||
|
|||
# if GNULIB_MSVC_NOTHROW |
|||
# include "msvc-nothrow.h" |
|||
# else |
|||
# include <io.h> |
|||
# endif |
|||
|
|||
static inline SOCKET |
|||
gl_fd_to_handle (int fd) |
|||
{ |
|||
return _get_osfhandle (fd); |
|||
} |
|||
|
|||
#else |
|||
|
|||
# define gl_fd_to_handle(x) (x) |
|||
|
|||
#endif /* WINDOWS_SOCKETS */ |
|||
|
|||
#endif /* SOCKETS_H */ |
|||
@ -0,0 +1,326 @@ |
|||
/* Substitute for <sys/select.h>.
|
|||
Copyright (C) 2007-2021 Free Software Foundation, Inc. |
|||
|
|||
This program is free software; you can redistribute it and/or modify |
|||
it under the terms of the GNU General Public License as published by |
|||
the Free Software Foundation; either version 3, 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 General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU General Public License |
|||
along with this program; if not, see <https://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>. |
|||
On Cygwin, <sys/time.h> includes <sys/select.h>. |
|||
Simply delegate to the system's header in this case. */ |
|||
#if (@HAVE_SYS_SELECT_H@ \ |
|||
&& !defined _GL_SYS_SELECT_H_REDIRECT_FROM_SYS_TYPES_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__)))) |
|||
|
|||
# define _GL_SYS_SELECT_H_REDIRECT_FROM_SYS_TYPES_H |
|||
# @INCLUDE_NEXT@ @NEXT_SYS_SELECT_H@ |
|||
|
|||
#elif (@HAVE_SYS_SELECT_H@ \ |
|||
&& (defined _CYGWIN_SYS_TIME_H \ |
|||
|| (!defined _GL_SYS_SELECT_H_REDIRECT_FROM_SYS_TIME_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__)))))) |
|||
|
|||
# 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 and "unknown type |
|||
name" problems on Cygwin. */ |
|||
# if !(defined __GLIBC__ || defined __CYGWIN__) |
|||
# 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 and "unknown type |
|||
name" problems on Cygwin. |
|||
On OS/2 kLIBC, sigset_t is defined in <sys/select.h>, too. In addition, |
|||
if <sys/param.h> is included, <types.h> -> <sys/types.h> -> <sys/select.h> |
|||
are included. Then <signal.h> -> <pthread.h> are included by GNULIB. By the |
|||
way, <pthread.h> requires PAGE_SIZE defined in <sys/param.h>. However, |
|||
<sys/param.h> has not been processed, yet. As a result, 'PAGE_SIZE' |
|||
undeclared error occurs in <pthread.h>. |
|||
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 __CYGWIN__ || defined __KLIBC__) \ |
|||
&& !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 |
|||
# elif !defined __clang__ |
|||
_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 |
|||
# elif !defined __clang__ |
|||
_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 |
|||
# elif !defined __clang__ |
|||
_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 *restrict, fd_set *restrict, fd_set *restrict, |
|||
struct timeval *restrict)); |
|||
_GL_CXXALIAS_RPL (select, int, |
|||
(int, fd_set *restrict, fd_set *restrict, fd_set *restrict, |
|||
timeval *restrict)); |
|||
# else |
|||
_GL_CXXALIAS_SYS (select, int, |
|||
(int, fd_set *restrict, fd_set *restrict, fd_set *restrict, |
|||
timeval *restrict)); |
|||
# 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 */ |
|||
@ -0,0 +1,140 @@ |
|||
/* w32sock.h --- internal auxiliary functions for Windows socket functions
|
|||
|
|||
Copyright (C) 2008-2021 Free Software Foundation, Inc. |
|||
|
|||
This program is free software: you can redistribute it and/or modify |
|||
it under the terms of the GNU 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 General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU General Public License |
|||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
|||
|
|||
/* Written by Paolo Bonzini */ |
|||
|
|||
#include <errno.h> |
|||
|
|||
/* Get O_RDWR and O_BINARY. */ |
|||
#include <fcntl.h> |
|||
|
|||
/* Get _open_osfhandle(). */ |
|||
#include <io.h> |
|||
|
|||
/* Get _get_osfhandle(). */ |
|||
#if GNULIB_MSVC_NOTHROW |
|||
# include "msvc-nothrow.h" |
|||
#else |
|||
# include <io.h> |
|||
#endif |
|||
|
|||
#define FD_TO_SOCKET(fd) ((SOCKET) _get_osfhandle ((fd))) |
|||
#define SOCKET_TO_FD(fh) (_open_osfhandle ((intptr_t) (fh), O_RDWR | O_BINARY)) |
|||
|
|||
static inline void |
|||
set_winsock_errno (void) |
|||
{ |
|||
int err = WSAGetLastError (); |
|||
|
|||
/* Map some WSAE* errors to the runtime library's error codes. */ |
|||
switch (err) |
|||
{ |
|||
case WSA_INVALID_HANDLE: |
|||
errno = EBADF; |
|||
break; |
|||
case WSA_NOT_ENOUGH_MEMORY: |
|||
errno = ENOMEM; |
|||
break; |
|||
case WSA_INVALID_PARAMETER: |
|||
errno = EINVAL; |
|||
break; |
|||
case WSAENAMETOOLONG: |
|||
errno = ENAMETOOLONG; |
|||
break; |
|||
case WSAENOTEMPTY: |
|||
errno = ENOTEMPTY; |
|||
break; |
|||
case WSAEWOULDBLOCK: |
|||
errno = EWOULDBLOCK; |
|||
break; |
|||
case WSAEINPROGRESS: |
|||
errno = EINPROGRESS; |
|||
break; |
|||
case WSAEALREADY: |
|||
errno = EALREADY; |
|||
break; |
|||
case WSAENOTSOCK: |
|||
errno = ENOTSOCK; |
|||
break; |
|||
case WSAEDESTADDRREQ: |
|||
errno = EDESTADDRREQ; |
|||
break; |
|||
case WSAEMSGSIZE: |
|||
errno = EMSGSIZE; |
|||
break; |
|||
case WSAEPROTOTYPE: |
|||
errno = EPROTOTYPE; |
|||
break; |
|||
case WSAENOPROTOOPT: |
|||
errno = ENOPROTOOPT; |
|||
break; |
|||
case WSAEPROTONOSUPPORT: |
|||
errno = EPROTONOSUPPORT; |
|||
break; |
|||
case WSAEOPNOTSUPP: |
|||
errno = EOPNOTSUPP; |
|||
break; |
|||
case WSAEAFNOSUPPORT: |
|||
errno = EAFNOSUPPORT; |
|||
break; |
|||
case WSAEADDRINUSE: |
|||
errno = EADDRINUSE; |
|||
break; |
|||
case WSAEADDRNOTAVAIL: |
|||
errno = EADDRNOTAVAIL; |
|||
break; |
|||
case WSAENETDOWN: |
|||
errno = ENETDOWN; |
|||
break; |
|||
case WSAENETUNREACH: |
|||
errno = ENETUNREACH; |
|||
break; |
|||
case WSAENETRESET: |
|||
errno = ENETRESET; |
|||
break; |
|||
case WSAECONNABORTED: |
|||
errno = ECONNABORTED; |
|||
break; |
|||
case WSAECONNRESET: |
|||
errno = ECONNRESET; |
|||
break; |
|||
case WSAENOBUFS: |
|||
errno = ENOBUFS; |
|||
break; |
|||
case WSAEISCONN: |
|||
errno = EISCONN; |
|||
break; |
|||
case WSAENOTCONN: |
|||
errno = ENOTCONN; |
|||
break; |
|||
case WSAETIMEDOUT: |
|||
errno = ETIMEDOUT; |
|||
break; |
|||
case WSAECONNREFUSED: |
|||
errno = ECONNREFUSED; |
|||
break; |
|||
case WSAELOOP: |
|||
errno = ELOOP; |
|||
break; |
|||
case WSAEHOSTUNREACH: |
|||
errno = EHOSTUNREACH; |
|||
break; |
|||
default: |
|||
errno = (err > 10000 && err < 10025) ? err - 10000 : err; |
|||
break; |
|||
} |
|||
} |
|||
Loading…
Reference in new issue