You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

743 lines
20 KiB

#ifdef __MINGW32__
#include "mingw.h"
#undef socket
#undef connect
#undef accept
#undef shutdown
#include <string.h>
#include <errno.h>
#include <assert.h>
int win32_poll(struct pollfd *fds, unsigned int nfds, int timo)
{
struct timeval timeout, *toptr;
fd_set ifds, ofds, efds, *ip, *op;
unsigned int i, rc;
/* Set up the file-descriptor sets in ifds, ofds and efds. */
FD_ZERO(&ifds);
FD_ZERO(&ofds);
FD_ZERO(&efds);
for (i = 0, op = ip = 0; i < nfds; ++i) {
fds[i].revents = 0;
if(fds[i].events & (POLLIN|POLLPRI)) {
ip = &ifds;
FD_SET(fds[i].fd, ip);
}
if(fds[i].events & POLLOUT) {
op = &ofds;
FD_SET(fds[i].fd, op);
}
FD_SET(fds[i].fd, &efds);
}
/* Set up the timeval structure for the timeout parameter */
if(timo < 0) {
toptr = 0;
} else {
toptr = &timeout;
timeout.tv_sec = timo / 1000;
timeout.tv_usec = (timo - timeout.tv_sec * 1000) * 1000;
}
#ifdef DEBUG_POLL
printf("Entering select() sec=%ld usec=%ld ip=%lx op=%lx\n",
(long)timeout.tv_sec, (long)timeout.tv_usec, (long)ip, (long)op);
#endif
rc = select(0, ip, op, &efds, toptr);
#ifdef DEBUG_POLL
printf("Exiting select rc=%d\n", rc);
#endif
if(rc <= 0)
return rc;
if(rc > 0) {
for ( i = 0; i < nfds; ++i) {
int fd = fds[i].fd;
if(fds[i].events & (POLLIN|POLLPRI) && FD_ISSET(fd, &ifds))
fds[i].revents |= POLLIN;
if(fds[i].events & POLLOUT && FD_ISSET(fd, &ofds))
fds[i].revents |= POLLOUT;
if(FD_ISSET(fd, &efds))
/* Some error was detected ... should be some way to know. */
fds[i].revents |= POLLHUP;
#ifdef DEBUG_POLL
printf("%d %d %d revent = %x\n",
FD_ISSET(fd, &ifds), FD_ISSET(fd, &ofds), FD_ISSET(fd, &efds),
fds[i].revents
);
#endif
}
}
return rc;
}
static void
set_connect_errno(int winsock_err)
{
switch(winsock_err) {
case WSAEINVAL:
case WSAEALREADY:
case WSAEWOULDBLOCK:
errno = EINPROGRESS;
break;
default:
errno = winsock_err;
break;
}
}
static void
set_socket_errno(int winsock_err)
{
switch(winsock_err) {
case WSAEWOULDBLOCK:
errno = EAGAIN;
break;
default:
errno = winsock_err;
break;
}
}
/*
* A wrapper around the socket() function. The purpose of this wrapper
* is to ensure that the global errno symbol is set if an error occurs,
* even if we are using winsock.
*/
SOCKET
win32_socket(int domain, int type, int protocol)
{
SOCKET fd = socket(domain, type, protocol);
if(fd == INVALID_SOCKET) {
set_socket_errno(WSAGetLastError());
}
return fd;
}
/*
* A wrapper around the connect() function. The purpose of this wrapper
* is to ensure that the global errno symbol is set if an error occurs,
* even if we are using winsock.
*/
int
win32_connect(SOCKET fd, struct sockaddr *addr, socklen_t addr_len)
{
int rc = connect(fd, addr, addr_len);
assert(rc == 0 || rc == SOCKET_ERROR);
if(rc == SOCKET_ERROR) {
set_connect_errno(WSAGetLastError());
}
return rc;
}
/*
* A wrapper around the accept() function. The purpose of this wrapper
* is to ensure that the global errno symbol is set if an error occurs,
* even if we are using winsock.
*/
SOCKET
win32_accept(SOCKET fd, struct sockaddr *addr, socklen_t *addr_len)
{
SOCKET newfd = accept(fd, addr, addr_len);
if(newfd == INVALID_SOCKET) {
set_socket_errno(WSAGetLastError());
newfd = -1;
}
return newfd;
}
/*
* A wrapper around the shutdown() function. The purpose of this wrapper
* is to ensure that the global errno symbol is set if an error occurs,
* even if we are using winsock.
*/
int
win32_shutdown(SOCKET fd, int mode)
{
int rc = shutdown(fd, mode);
assert(rc == 0 || rc == SOCKET_ERROR);
if(rc == SOCKET_ERROR) {
set_socket_errno(WSAGetLastError());
}
return rc;
}
int win32_close_socket(SOCKET fd)
{
int rc = closesocket(fd);
if(rc == SOCKET_ERROR) {
set_socket_errno(WSAGetLastError());
}
return rc;
}
ssize_t win32_write_socket(SOCKET fd, void *buf, int n)
{
int rc = send(fd, buf, n, 0);
if(rc == SOCKET_ERROR) {
set_socket_errno(WSAGetLastError());
}
return rc;
}
ssize_t win32_read_socket(SOCKET fd, void *buf, int n)
{
int rc = recv(fd, buf, n, 0);
if(rc == SOCKET_ERROR) {
set_socket_errno(WSAGetLastError());
}
return rc;
}
char * win32_strtok_r(char *s, const char *delim, char **lasts)
{
register char *spanp;
register int c, sc;
char *tok;
if (s == NULL && (s = *lasts) == NULL)
return (NULL);
/*
* Skip (span) leading delimiters (s += strspn(s, delim), sort of).
*/
cont:
c = *s++;
for (spanp = (char *)delim; (sc = *spanp++) != 0;) {
if (c == sc)
goto cont;
}
if (c == 0) { /* no non-delimiter characters */
*lasts = NULL;
return (NULL);
}
tok = s - 1;
/*
* Scan token (scan for delimiters: s += strcspn(s, delim), sort of).
* Note that delim must have one NUL; we stop if we see that, too.
*/
for (;;) {
c = *s++;
spanp = (char *)delim;
do {
if ((sc = *spanp++) == c) {
if (c == 0)
s = NULL;
else
s[-1] = 0;
*lasts = s;
return (tok);
}
} while (sc != 0);
}
/* NOTREACHED */
}
char *win32_strsep (char **stringp, const char *delim)
{
register char *s;
register const char *spanp;
register int c, sc;
char *tok;
if ((s = *stringp) == NULL)
return (NULL);
for (tok = s;;) {
c = *s++;
spanp = delim;
do {
if ((sc = *spanp++) == c) {
if (c == 0)
s = NULL;
else
s[-1] = 0;
*stringp = s;
return (tok);
}
} while (sc != 0);
}
/* NOTREACHED */
}
#ifdef noneed
/******************************************************************************
time32.c -- extended time functions that use all 32 bits
Author: Mark Baranowski
Email: requestXXX@els-software.org (remove XXX)
Download: http://els-software.org
Last significant change: May 6, 2015
These functions are provided "as is" in the hopes that they might serve some
higher purpose. If you want these functions to serve some lower purpose,
then that too is all right. So as to keep these hopes alive you may
freely distribute these functions so long as this header remains intact.
You may also freely distribute modified versions of these functions so long
as you indicate that such versions are modified and so long as you
provide access to the unmodified original copy.
Note: The most recent version of these functions may be obtained from
http://els-software.org
The following functions support Unix time beyond Jan 19 03:14:08 2038 GMT,
assuming that the future standard will treat the 32-bits used by Unix's
present-day file system as unsigned.
These functions work by mapping years within the region 2038-2106 down
into the region of 2010-2037. All fields of the "tm" structure,
including those fields dealing with day-of-week and daylight savings time
are correct! Bear in mind, however, that the definition of daylight
savings time changes with the whims of man, thus the notion of daylight
savings held during 2010-2037 may not be the same as the notion held
thereafter.
See also: time(3)
****************************************************************************/
#include "sysdefs.h"
#include "defs.h"
#include "time32.h"
#include "sysInfo.h"
/*****************************************************************************/
#if defined(HAVE_LONG_LONG_TIME)
struct tm *localtime32_r(const time_t *clock, struct tm *res)
{return localtime_r(clock, res);}
struct tm *gmtime32_r(const time_t *clock, struct tm *res)
{return gmtime_r(clock, res);}
#ifdef USE_POSIX_TIME_R
char *asctime32_r(const struct tm *tm, char *buf)
{return asctime_r(tm, buf);}
char *ctime32_r(const time_t *clock, char *buf)
{return ctime_r(clock, buf);}
#else
char *asctime32_r(const struct tm *tm, char *buf, int buflen)
{return asctime_r(tm, buf, buflen);}
char *ctime32_r(const time_t *clock, char *buf, int buflen)
{return ctime_r(clock, buf, buflen);}
#endif
struct tm *localtime32(const time_t *clock)
{return localtime(clock);}
struct tm *gmtime32(const time_t *clock)
{return gmtime(clock);}
size_t strftime32(char *str, size_t max,
const char *format, const struct tm *tm)
{return strftime(str, max, format, tm);}
char *asctime32(const struct tm *tm)
{return asctime(tm);}
char *ctime32(const time_t *clock)
{return ctime(clock);}
#ifdef HAVE_MKTIME
time_t mktime32(const struct tm *tm)
{return mktime(tm);}
#endif
#ifdef HAVE_TIMELOCAL
/* FreeBSD/Darwin do NOT declare these args as "const": */
time_t timelocal32(struct tm *tm)
{return timelocal(tm);}
time_t timegm32(struct tm *tm)
{return timegm(tm);}
#endif
/*****************************************************************************/
#else
Local void mapclock32(time_t *clock, int *years);
Local void mapyears32(int *years, time_t *clock);
#if !defined(HAVE_TIME_R)
struct tm *localtime_r(const time_t *clock, struct tm *xtime);
struct tm *gmtime_r(const time_t *clock, struct tm *xtime);
# ifdef USE_POSIX_TIME_R
char *asctime_r(const struct tm *tm, char *buf);
char *ctime_r(const time_t *clock, char *buf);
# else
char *asctime_r(const struct tm *tm, char *buf, int buflen);
char *ctime_r(const time_t *clock, char *buf, int buflen);
# endif
#endif /* !defined(HAVE_TIME_R) */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
struct tm *localtime32_r(const time_t *clock, struct tm *xtime)
{
time_t xclock = *clock;
int xyears;
mapclock32(&xclock, &xyears);
localtime_r(&xclock, xtime);
xtime->tm_year += xyears;
return(xtime);
}
struct tm *localtime32(const time_t *clock)
{
static struct tm xtime; /* return value must be static */
return(localtime32_r(clock, &xtime));
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
struct tm *gmtime32_r(const time_t *clock, struct tm *xtime)
{
time_t xclock = *clock;
int xyears;
mapclock32(&xclock, &xyears);
gmtime_r(&xclock, xtime);
xtime->tm_year += xyears;
return(xtime);
}
struct tm *gmtime32(const time_t *clock)
{
static struct tm xtime; /* return value must be static */
return(gmtime32_r(clock, &xtime));
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* NB: strftime32 will work correctly for all years > 2038 IF and only
IF the "tm" parameter given it was generated using one of the
time32 functions: localtime32(), localtime32_r(), gmtime32(), or
gmtime32_r(). */
/* NB: strftime() is known to be in SunOS4/5, HPUX10/11, Linux2.2/4/6;
So far Only SunOS5 is known to have cftime() and ascftime() */
size_t strftime32(char *str, size_t max,
const char *format, const struct tm *tm)
{
#if defined(SUNOS)
/* SunOS 5.8, 5.9, 5.10 has a quirk where "strftime(..., ..., "%a", tm)"
corrupts tzname[0] and tzname[1] for certain values of tm_year, e.g.
"edate -C 0xd0700000" currupts tzname[], but "edate -C 0xd0800000"
doesn't. Setting tm_year within spec fixes this problem, but creates
a different problem if asked to print the year. All other OSes
including SunOS5.7 appear to take tm_year at face value. */
if (osVersion == 0) osVersion = get_osVersion();
if (osVersion >= 50800)
{
struct tm xtime = *tm;
time_t xclock = 0;
mapyears32(&xtime.tm_year, &xclock);
return(strftime(str, max, format, &xtime));
}
#endif
/* Fall through for OS versions that take tm_year at face value: */
return(strftime(str, max, format, tm));
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* NB: asctime32() and asctime32_r() will work correctly for all years > 2038
IF and only IF the "tm" parameter given it was generated using one of the
time32 functions: localtime32(), localtime32_r(), gmtime32(), or
gmtime32_r(). */
#ifdef USE_POSIX_TIME_R
char *asctime32_r(const struct tm *tm, char *buf)
{
return(asctime_r(tm, buf));
}
#else
char *asctime32_r(const struct tm *tm, char *buf, int buflen)
{
return(asctime_r(tm, buf, buflen));
}
#endif
char *asctime32(const struct tm *tm)
{
# define BUF_SIZE (26+8) /* 8 bytes of slack */
static char buf[BUF_SIZE]; /* return value must be static */
#ifdef USE_POSIX_TIME_R
return(asctime32_r(tm, buf));
#else
return(asctime32_r(tm, buf, BUF_SIZE));
#endif
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifdef USE_POSIX_TIME_R
char *ctime32_r(const time_t *clock, char *buf)
{
struct tm xtime;
return(asctime32_r(localtime32_r(clock, &xtime), buf));
}
#else
char *ctime32_r(const time_t *clock, char *buf, int buflen)
{
struct tm xtime;
return(asctime32_r(localtime32_r(clock, &xtime), buf, buflen));
}
#endif
char *ctime32(const time_t *clock)
{
# define BUF_SIZE (26+8) /* 8 bytes of slack */
static char buf[BUF_SIZE]; /* return value must be static */
#ifdef USE_POSIX_TIME_R
return(ctime32_r(clock, buf));
#else
return(ctime32_r(clock, buf, BUF_SIZE));
#endif
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* mktime is known to be supported by: HPUX 10+, SunOS5+, Linux2.2+, OSF1
mktime is known to NOT be supported by: SunOS4 */
#ifdef HAVE_MKTIME
time_t mktime32(const struct tm *tm)
{
struct tm xtime = *tm;
time_t xclock;
mapyears32(&xtime.tm_year, &xclock);
return(mktime(&xtime) + xclock);
}
#endif /*HAVE_MKTIME*/
/* timelocal and timegm are only known to be supported by SunOS4. Perhaps
older BSD-based OSes also support them, but POSIX based UNIXes do not. */
#ifdef HAVE_TIMELOCAL
time_t timelocal32(struct tm *tm)
{
struct tm xtime = *tm;
time_t xclock;
mapyears32(&xtime.tm_year, &xclock);
return(timelocal(&xtime) + xclock);
}
time_t timegm32(struct tm *tm)
{
struct tm xtime = *tm;
time_t xclock;
mapyears32(&xtime.tm_year, &xclock);
return(timegm(&xtime) + xclock);
}
#endif /*HAVE_TIMELOCAL*/
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#define _28_YEARS ( 28 * SECS_PER_YEAR)
#define _68_YEARS ( 68 * SECS_PER_YEAR)
#define _90_YEARS ( 88 * SECS_PER_YEAR + 2*365*SECS_PER_DAY)
#define _96_YEARS ( 96 * SECS_PER_YEAR)
#define JAN_1_2100 (128 * SECS_PER_YEAR + 2*365*SECS_PER_DAY)
#define JAN_1_2102 (JAN_1_2100 + 2*365*SECS_PER_DAY) /* leap year missing */
#define JAN_1_2106 (JAN_1_2102 + 4*SECS_PER_YEAR)
#define TIME32 ((Ulong)0x80000000)
Local void mapclock32(time_t *clock, int *years)
{
Ulong xclock = (Ulong)*clock;
int xyears = 0;
/* Prevent certain processors (e.g. DEC_ALPHA) from sign extending: */
if (sizeof(Ulong) > 4) xclock &= 0xffffffff;
/* Years from 1970 up until Jan 19 03:14:08 2038 GMT need no mapping. */
if (xclock >= TIME32)
{
/* Map years beyond Jan 19 03:14:08 2038 GMT: */
if (xclock >= JAN_1_2100)
{
if (xclock < JAN_1_2102)
{
/* Map years 2100 and 2101:
(These two years must be contiguously mapped in order for
localtime(JAN_1_2101) to return the correct "tm_yday" value.
Hint: think about how Jan 1 2101, 00:00 GMT maps into
Dec 31 2100 LOCAL TIME). */
xclock -= _90_YEARS;
xyears = 90;
}
else if (xclock < JAN_1_2106)
{
/* Map years from 2102 up until 2106: */
xclock -= _68_YEARS;
xclock += SECS_PER_DAY; /* Compensate for missing leap year in 2100! */
xyears = 68;
}
else
{
/* Map years from Jan 1 2106 up until Feb 7 04:28:14 2106 GMT: */
xclock -= _96_YEARS;
xclock += SECS_PER_DAY; /* Compensate for missing leap year in 2100! */
xyears = 96;
}
}
else
{
/* Map years from 2038 up until 2100: */
while (xclock >= TIME32)
{
xclock -= _28_YEARS;
xyears += 28;
}
}
}
*clock = xclock;
*years = xyears;
return;
}
#define _1970 ( 70)
#define _2038 ( 68 + _1970)
#define _2100 (130 + _1970)
#define _2102 (132 + _1970)
#define _2106 (136 + _1970)
Local void mapyears32(int *years, time_t *clock)
{
Ulong xclock = 0;
int xyears = *years;
/* Years from 1970 up until Jan 19 03:14:08 2038 GMT need no mapping. */
if (xyears >= _2038)
{
/* Map years beyond Jan 19 03:14:08 2038 GMT: */
if (xyears >= _2100)
{
if (xyears < _2102)
{
/* Map years 2100 and 2101:
(These two years must be contiguously mapped in order for
localtime(JAN_1_2101) to return the correct "tm_yday" value.
Hint: think about how Jan 1 2101, 00:00 GMT maps into
Dec 31 2100 LOCAL TIME). */
xyears -= 90;
xclock = _90_YEARS;
}
else if (xyears < _2106)
{
/* Map years from 2102 up until 2106: */
xyears -= 68;
xclock = _68_YEARS;
xclock -= SECS_PER_DAY; /* Compensate for missing leap year in 2100! */
}
else
{
/* Map years from Jan 1 2106 up until Feb 7 04:28:14 2106 GMT: */
xyears -= 96;
xclock = _96_YEARS;
xclock -= SECS_PER_DAY; /* Compensate for missing leap year in 2100! */
}
}
else
{
/* Map years from 2038 up until 2100: */
while (xyears >= _2038)
{
xyears -= 28;
xclock += _28_YEARS;
}
}
}
*years = xyears;
*clock = xclock;
return;
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* The following ERSATZ *time_r() routines localtime_r(), gmtime_r(),
asctime_r(), and ctime_r() are provided here as cheap substitutes to be
used ONLY by those Unixes that are lacking these functions. Moreover,
when building on a Unix that has NATIVE support for the following ERSATZ
functions be sure to define HAVE_TIME_R so that the compiler will instead
make use of its NATIVE *time_r() routines.
NOTE: If you must resort to using the following ERSATZ *time_r() routines
then as a consequence the *time32_r() functions in the previous section
will not be fully reentrant. HOWEVER, if you can AVOID using the
following routines and instead make use of your Unix's NATIVE *time_r()
routines then as a result the *time32_r() in the previous section will
also be reentrant! */
#if !defined(HAVE_TIME_R)
struct tm *localtime_r(const time_t *clock, struct tm *xtime)
{
*xtime = *localtime(clock);
return(xtime);
}
struct tm *gmtime_r(const time_t *clock, struct tm *xtime)
{
*xtime = *gmtime(clock);
return(xtime);
}
#include <string.h>
# ifdef USE_POSIX_TIME_R
char *asctime_r(const struct tm *tm, char *buf)
{
strcpy(buf, asctime(tm));
return(buf);
}
char *ctime_r(const time_t *clock, char *buf)
{
strcpy(buf, ctime(clock));
return(buf);
}
# else
char *asctime_r(const struct tm *tm, char *buf, int buflen)
{
strncpy(buf, asctime(tm), buflen);
return(buf);
}
char *ctime_r(const time_t *clock, char *buf, int buflen)
{
strncpy(buf, ctime(clock), buflen);
return(buf);
}
# endif
#endif /* !defined(HAVE_TIME_R) */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*****************************************************************************/
#endif /* !defined(HAVE_LONG_LONG_TIME) */
#endif
#endif