summaryrefslogtreecommitdiff
path: root/win32
diff options
context:
space:
mode:
authorPatrick Galbraith <patg@northscale.com>2010-03-25 21:02:50 +0100
committerTrond Norbye <Trond.Norbye@gmail.com>2010-03-29 22:58:09 +0200
commit95c3be87e841a9e20139e2eb3f705dfab6b53252 (patch)
tree2441681cdc526dfd06b3325498878882fa170857 /win32
parent04e0609f4fbf048cd540df7278c3afcd08aa1260 (diff)
downloadmemcached-95c3be87e841a9e20139e2eb3f705dfab6b53252.tar.gz
Changes to memcached source required for compilation on windows
Diffstat (limited to 'win32')
-rw-r--r--win32/Makefile.mingw49
-rw-r--r--win32/config.h92
-rw-r--r--win32/config.sh17
-rw-r--r--win32/defs.c51
-rw-r--r--win32/dlfcn.c62
-rw-r--r--win32/dlfcn.h12
-rw-r--r--win32/sysexits.h114
-rw-r--r--win32/win32.c395
-rw-r--r--win32/win32.h205
9 files changed, 997 insertions, 0 deletions
diff --git a/win32/Makefile.mingw b/win32/Makefile.mingw
new file mode 100644
index 0000000..6a66ece
--- /dev/null
+++ b/win32/Makefile.mingw
@@ -0,0 +1,49 @@
+# Hard coded Makefile for windows
+
+CC = gcc
+
+OBJDIR = .libs .libs/win32
+BINARIES= memcached.exe .libs/default_engine.so
+LIB=-L/lib -L/usr/lib -L/usr/local/lib
+INCLUDE=-I/include -I/usr/include -I/usr/local/include
+
+all: ${BINARIES}
+
+CFLAGS = -std=gnu99 -O2 -DNDEBUG -fno-strict-aliasing -Wall \
+ -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wredundant-decls \
+ ${INCLUDE} -Iinclude -Iwin32 -I.libs -DHAVE_CONFIG_H
+
+MEMCACHED_SRC = cache.c config_parser.c globals.c hash.c isasl.c memcached.c \
+ sasl_defs.c stats.c stdin_check.c thread.c util.c \
+ win32/defs.c win32/dlfcn.c win32/win32.c
+
+MEMCACHED_OBJS = ${MEMCACHED_SRC:%.c=.libs/%.o}
+
+DEFAULT_ENGINE_SRC = assoc.c default_engine.c items.c slabs.c util.c
+DEFAULT_ENGINE_OBJS = ${DEFAULT_ENGINE_SRC:%.c=.libs/%.o}
+
+GENFILES=.libs/config_version.h
+
+memcached.exe: ${OBJDIR} ${GENFILES} $(MEMCACHED_OBJS)
+ ${LINK.c} -o memcached.exe $(MEMCACHED_OBJS) \
+ ${LIB} -levent -lmswsock \
+ -lws2_32 -lpthread
+
+.libs/default_engine.so: ${OBJDIR} $(DEFAULT_ENGINE_OBJS)
+ ${LINK.c} -o $@ -shared ${DEFAULT_ENGINE_OBJS} \
+ ${LIB} -lpthread
+
+.libs/config_version.h:
+ ./win32/config.sh
+
+.libs .libs/win32:; -@mkdir $@
+
+.libs/%.o: %.c
+ ${COMPILE.c} -MMD $< -o $@
+
+clean:
+ $(RM) ${MEMCACHED_OBJS} ${DEFAULT_ENGINE_OBJS} \
+ ${BINARIES} ${MEMCACHED_OBJS:.o=.d} ${DEFAULT_ENGINE_OBJS:.o=.d} \
+ ${GENFILES}
+
+-include ${MEMCACHED_OBJS:.o=.d} ${DEFAULT_ENGINE_OBJS:.o=.d}
diff --git a/win32/config.h b/win32/config.h
new file mode 100644
index 0000000..cff6914
--- /dev/null
+++ b/win32/config.h
@@ -0,0 +1,92 @@
+#ifndef _CONFIG_H
+#define _CONFIG_H
+
+/* Name of package */
+#define PACKAGE "memcached"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "memcached@googlegroups.com"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "memcached"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_DESCRIPTION "memcached is a high-performance, distributed memory object caching system, generic in nature, but intended for use in speeding up dynamic web applications by alleviating database load."
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "memcached"
+
+#include "config_version.h"
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* machine is littleendian */
+#define ENDIAN_LITTLE 1
+
+#define ENABLE_ISASL 1
+
+#define HAVE_DLFCN_H 1
+
+/* Define to empty if `const' does not conform to ANSI C. */
+/* #undef const */
+
+/* define to int if socklen_t not available */
+/* #undef socklen_t */
+/* Windows-specific includes */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "win32.h"
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#include <process.h>
+/* PRIu64 */
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+/*******************************/
+/* HACKS to compile under UNIX */
+
+#define S_ISSOCK(mode) 0
+#define RLIMIT_CORE 4
+#define RLIM_INFINITY ((unsigned long int) (-0UL))
+#define RLIMIT_NOFILE 7
+
+/* Create expected type and struct definitions */
+
+typedef short int _uid_t;
+
+struct passwd {
+ char * pw_name;
+ char * pw_passwd;
+ _uid_t pw_uid;
+ _uid_t pw_gid;
+ char * pw_gecos;
+ char * pw_dir;
+ char * pw_shell;
+};
+
+struct sockaddr_un {
+ unsigned short int sun_family;
+ char sun_path[108];
+};
+
+struct rlimit {
+ unsigned long int rlim_cur, rlim_max;
+};
+
+/* Function prototypes expected by UNIX code
+ * - function definitions in dummy_defs.c
+ */
+
+int lstat(const char *path, struct stat *tstat);
+int sigignore(int sig);
+int getrlimit(int __resource, struct rlimit * __rlimits);
+int setrlimit(int __resource, struct rlimit * __rlimits);
+_uid_t getuid(void);
+_uid_t geteuid(void);
+struct passwd *getpwnam(const char *name);
+int setuid(_uid_t uid);
+int setgid(_uid_t gid);
+#endif // _CONFIG_H
diff --git a/win32/config.sh b/win32/config.sh
new file mode 100644
index 0000000..acd0ab3
--- /dev/null
+++ b/win32/config.sh
@@ -0,0 +1,17 @@
+#! /bin/sh
+MEMC_VERSION=`git describe | tr '-' '_'`;
+cat > .libs/config_version.h << EOF
+#ifndef CONFIG_VERSION_H
+#define CONFIG_VERSION_H
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "memcached $MEMC_VERSION"
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "$MEMC_VERSION"
+
+/* Version number of package */
+#define VERSION "$MEMC_VERSION"
+
+#endif // CONFIG_VERSION_H
+EOF
diff --git a/win32/defs.c b/win32/defs.c
new file mode 100644
index 0000000..279a8ef
--- /dev/null
+++ b/win32/defs.c
@@ -0,0 +1,51 @@
+/* dummy_defs.c
+ *
+ * Create blank UNIX function definitions to allow win32 builds. */
+
+#include <config.h>
+
+int lstat(const char *path, struct stat *tstat) {
+ return -1;
+}
+
+int getrlimit(int __resource, struct rlimit *__rlimits) {
+ /* HACK ALERT: This function MUST BE called from main() before any *
+ * network operation for Windows networking to work. Since the *
+ * main() is calling getrlimit() that is NOT meaningful for *
+ * Windows, this function is being used to invoke WSAStartup() *
+ * below only once during the the first call to getrlimit() *
+ */
+ static int onceonly = 0;
+ WSADATA wsaData;
+ if (!onceonly) {
+ onceonly = 1;
+ if (WSAStartup(MAKEWORD(2,0), &wsaData) != 0) {
+ fprintf(stderr, "Socket Initialization Error. Program aborted\n");
+ exit(EXIT_FAILURE);
+ }
+ }
+ return 0;
+}
+
+int setrlimit(int __resource, struct rlimit *__rlimits) {
+ return 0;
+}
+
+_uid_t getuid(void) {
+ return -1;
+}
+_uid_t geteuid(void) {
+ return -1;
+}
+
+struct passwd *getpwnam(const char *name) {
+ return 0;
+}
+
+int setuid(_uid_t uid) {
+ return -1;
+}
+
+int setgid(_uid_t gid) {
+ return -1;
+}
diff --git a/win32/dlfcn.c b/win32/dlfcn.c
new file mode 100644
index 0000000..f5ff594
--- /dev/null
+++ b/win32/dlfcn.c
@@ -0,0 +1,62 @@
+/* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+#include <stdio.h>
+#include <windows.h>
+#include <dlfcn.h>
+#include <stdbool.h>
+
+/*
+ * Keep track if the user tried to call dlopen(NULL, xx) to be able to give a sane
+ * error message
+ */
+static bool self = false;
+
+void* dlopen(const char* path, int mode) {
+ if (path == NULL) {
+ // We don't support opening ourself
+ self = true;
+ return NULL;
+ }
+
+ void* handle = LoadLibrary(path);
+ if (handle == NULL) {
+ char *buf = malloc(strlen(path) + 20);
+ sprintf(buf, "%s.dll", path);
+ handle = LoadLibrary(buf);
+ free(buf);
+ }
+
+ return handle;
+}
+
+void* dlsym(void* handle, const char* symbol) {
+ return GetProcAddress(handle, symbol);
+}
+
+int dlclose(void* handle) {
+ // dlclose returns zero on success.
+ // FreeLibrary returns nonzero on success.
+ return FreeLibrary(handle) != 0;
+}
+
+static char dlerror_buf[200];
+
+const char *dlerror(void) {
+ if (self) {
+ return "not supported";
+ }
+
+ DWORD err = GetLastError();
+ LPVOID error_msg;
+ if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL, err, 0, (LPTSTR)&error_msg, 0, NULL) != 0) {
+ strncpy(dlerror_buf, error_msg, sizeof(dlerror_buf));
+ dlerror_buf[sizeof(dlerror_buf) - 1] = '\0';
+ LocalFree(error_msg);
+ } else {
+ return "Failed to get error message";
+ }
+
+ return dlerror_buf;
+}
diff --git a/win32/dlfcn.h b/win32/dlfcn.h
new file mode 100644
index 0000000..850d622
--- /dev/null
+++ b/win32/dlfcn.h
@@ -0,0 +1,12 @@
+#ifndef DLFCN_H
+#define DLFCN_H
+void* dlopen(const char* path, int mode);
+void* dlsym(void* handle, const char* symbol);
+int dlclose(void* handle);
+const char *dlerror(void);
+
+#define RTLD_LAZY 1
+#define RTLD_LOCAL 2
+
+#define RTLD_NOW 0x00002
+#endif
diff --git a/win32/sysexits.h b/win32/sysexits.h
new file mode 100644
index 0000000..ccc247b
--- /dev/null
+++ b/win32/sysexits.h
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 1987, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)sysexits.h 8.1 (Berkeley) 6/2/93
+ */
+
+#ifndef _SYSEXITS_H
+#define _SYSEXITS_H 1
+
+/*
+ * SYSEXITS.H -- Exit status codes for system programs.
+ *
+ * This include file attempts to categorize possible error
+ * exit statuses for system programs, notably delivermail
+ * and the Berkeley network.
+ *
+ * Error numbers begin at EX__BASE to reduce the possibility of
+ * clashing with other exit statuses that random programs may
+ * already return. The meaning of the codes is approximately
+ * as follows:
+ *
+ * EX_USAGE -- The command was used incorrectly, e.g., with
+ * the wrong number of arguments, a bad flag, a bad
+ * syntax in a parameter, or whatever.
+ * EX_DATAERR -- The input data was incorrect in some way.
+ * This should only be used for user's data & not
+ * system files.
+ * EX_NOINPUT -- An input file (not a system file) did not
+ * exist or was not readable. This could also include
+ * errors like "No message" to a mailer (if it cared
+ * to catch it).
+ * EX_NOUSER -- The user specified did not exist. This might
+ * be used for mail addresses or remote logins.
+ * EX_NOHOST -- The host specified did not exist. This is used
+ * in mail addresses or network requests.
+ * EX_UNAVAILABLE -- A service is unavailable. This can occur
+ * if a support program or file does not exist. This
+ * can also be used as a catchall message when something
+ * you wanted to do doesn't work, but you don't know
+ * why.
+ * EX_SOFTWARE -- An internal software error has been detected.
+ * This should be limited to non-operating system related
+ * errors as possible.
+ * EX_OSERR -- An operating system error has been detected.
+ * This is intended to be used for such things as "cannot
+ * fork", "cannot create pipe", or the like. It includes
+ * things like getuid returning a user that does not
+ * exist in the passwd file.
+ * EX_OSFILE -- Some system file (e.g., /etc/passwd, /etc/utmp,
+ * etc.) does not exist, cannot be opened, or has some
+ * sort of error (e.g., syntax error).
+ * EX_CANTCREAT -- A (user specified) output file cannot be
+ * created.
+ * EX_IOERR -- An error occurred while doing I/O on some file.
+ * EX_TEMPFAIL -- temporary failure, indicating something that
+ * is not really an error. In sendmail, this means
+ * that a mailer (e.g.) could not create a connection,
+ * and the request should be reattempted later.
+ * EX_PROTOCOL -- the remote system returned something that
+ * was "not possible" during a protocol exchange.
+ * EX_NOPERM -- You did not have sufficient permission to
+ * perform the operation. This is not intended for
+ * file system problems, which should use NOINPUT or
+ * CANTCREAT, but rather for higher level permissions.
+ */
+
+#define EX_OK 0 /* successful termination */
+
+#define EX__BASE 64 /* base value for error messages */
+
+#define EX_USAGE 64 /* command line usage error */
+#define EX_DATAERR 65 /* data format error */
+#define EX_NOINPUT 66 /* cannot open input */
+#define EX_NOUSER 67 /* addressee unknown */
+#define EX_NOHOST 68 /* host name unknown */
+#define EX_UNAVAILABLE 69 /* service unavailable */
+#define EX_SOFTWARE 70 /* internal software error */
+#define EX_OSERR 71 /* system error (e.g., can't fork) */
+#define EX_OSFILE 72 /* critical OS file missing */
+#define EX_CANTCREAT 73 /* can't create (user) output file */
+#define EX_IOERR 74 /* input/output error */
+#define EX_TEMPFAIL 75 /* temp failure; user is invited to retry */
+#define EX_PROTOCOL 76 /* remote error in protocol */
+#define EX_NOPERM 77 /* permission denied */
+#define EX_CONFIG 78 /* configuration error */
+
+#define EX__MAX 78 /* maximum listed value */
+
+#endif /* sysexits.h */
diff --git a/win32/win32.c b/win32/win32.c
new file mode 100644
index 0000000..7c0e174
--- /dev/null
+++ b/win32/win32.c
@@ -0,0 +1,395 @@
+/* Copyright (c) 1983, 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ *
+ */
+
+#include "win32.h"
+#include <limits.h>
+#include <ctype.h>
+#include <time.h>
+
+int fcntl(SOCKET s, int cmd, int val)
+{
+ u_long imode = 1;
+ switch(cmd) {
+ case F_SETFL:
+ switch(val) {
+ case O_NONBLOCK:
+ imode = 1;
+ if(ioctlsocket(s, FIONBIO, &imode) == SOCKET_ERROR)
+ return -1;
+ break;
+ case O_BLOCK:
+ imode = 0;
+ if(ioctlsocket(s, FIONBIO, &imode) == SOCKET_ERROR)
+ return -1;
+ break;
+ default:
+ return -1;
+ }
+ case F_GETFL:
+ return 0;
+ default:
+ return -1;
+ }
+}
+
+/*
+ * Check whether "cp" is a valid ascii representation
+ * of an Internet address and convert to a binary address.
+ * Returns 1 if the address is valid, 0 if not.
+ * This replaces inet_addr, the return value from which
+ * cannot distinguish between failure and a local broadcast address.
+ */
+int inet_aton(register const char *cp, struct in_addr *addr)
+{
+ register uint32_t val;
+ register int base, n;
+ register char c;
+ u_int parts[4];
+ register u_int *pp = parts;
+
+ c = *cp;
+ for (;;) {
+ /*
+ * Collect number up to ``.''.
+ * Values are specified as for C:
+ * 0x=hex, 0=octal, isdigit=decimal.
+ */
+ if (!isdigit(c))
+ return (0);
+ val = 0; base = 10;
+ if (c == '0') {
+ c = *++cp;
+ if (c == 'x' || c == 'X')
+ base = 16, c = *++cp;
+ else
+ base = 8;
+ }
+ for (;;) {
+ if (isascii(c) && isdigit(c)) {
+ val = (val * base) + (c - '0');
+ c = *++cp;
+ } else if (base == 16 && isascii(c) && isxdigit(c)) {
+ val = (val << 4) |
+ (c + 10 - (islower(c) ? 'a' : 'A'));
+ c = *++cp;
+ } else
+ break;
+ }
+ if (c == '.') {
+ /*
+ * Internet format:
+ * a.b.c.d
+ * a.b.c (with c treated as 16 bits)
+ * a.b (with b treated as 24 bits)
+ */
+ if (pp >= parts + 3)
+ return (0);
+ *pp++ = val;
+ c = *++cp;
+ } else
+ break;
+ }
+ /*
+ * Check for trailing characters.
+ */
+ if (c != '\0' && (!isascii(c) || !isspace(c)))
+ return (0);
+ /*
+ * Concoct the address according to
+ * the number of parts specified.
+ */
+ n = pp - parts + 1;
+ switch (n) {
+
+ case 0:
+ return (0); /* initial nondigit */
+
+ case 1: /* a -- 32 bits */
+ break;
+
+ case 2: /* a.b -- 8.24 bits */
+ if (val > 0xffffff)
+ return (0);
+ val |= parts[0] << 24;
+ break;
+
+ case 3: /* a.b.c -- 8.8.16 bits */
+ if (val > 0xffff)
+ return (0);
+ val |= (parts[0] << 24) | (parts[1] << 16);
+ break;
+
+ case 4: /* a.b.c.d -- 8.8.8.8 bits */
+ if (val > 0xff)
+ return (0);
+ val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
+ break;
+ }
+ if (addr)
+ addr->s_addr = htonl(val);
+ return (1);
+}
+
+int createLocalListSock(struct sockaddr_in *serv_addr) {
+ SOCKET sockfd;
+ int slen;
+
+ if ((sockfd = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP)) == INVALID_SOCKET) {
+ fprintf(stderr,"socket call for local server socket failed. Error Number %d.\n",WSAGetLastError());
+ fflush(stderr);
+ return(-1);
+ }
+ serv_addr->sin_family = AF_INET;
+ serv_addr->sin_addr.s_addr = inet_addr("127.0.0.1");
+ serv_addr->sin_port = htons(0);
+ if (bind(sockfd,(struct sockaddr *)serv_addr,sizeof(*serv_addr)) != 0) {
+ fprintf(stderr,"bind of local server socket failed. Error Number %d.\n",WSAGetLastError());
+ fflush(stderr);
+ return(-1);
+ }
+ slen = sizeof(*serv_addr);
+ if (getsockname(sockfd,(struct sockaddr *)serv_addr,&slen) != 0) {
+ fprintf(stderr,"getsockname on local server socket failed. Error Number %d.\n",WSAGetLastError());
+ fflush(stderr);
+ return(-1);
+ }
+ if (listen(sockfd,5) == SOCKET_ERROR) {
+ fprintf(stderr,"listen on local server socket failed. Error Number %d.\n",WSAGetLastError());
+ fflush(stderr);
+ return(-1);
+ }
+ return((int)sockfd);
+}
+
+int createLocalSocketPair(int listSock, int *fds, struct sockaddr_in *serv_addr) {
+ struct sockaddr_in cli_addr;
+ fd_set myset;
+ struct timeval tv;
+ socklen_t lon;
+ int valopt, tmpVal;
+
+ if ((fds[0] = (int)socket(AF_INET,SOCK_STREAM,IPPROTO_TCP)) == INVALID_SOCKET) {
+ fprintf(stderr,"socket call for local client socket failed. Error Number %d.\n",WSAGetLastError());
+ fflush(stderr);
+ return(-1);
+ }
+ if (fcntl(fds[0],F_SETFL,O_NONBLOCK) < 0) {
+ fprintf(stderr,"fcntl call for local server socket failed. Error Number %d.\n",WSAGetLastError());
+ fflush(stderr);
+ return(-1);
+ }
+ if (connect(fds[0],(struct sockaddr *)serv_addr,sizeof(*serv_addr)) == SOCKET_ERROR) {
+ tmpVal = WSAGetLastError();
+ if (tmpVal != WSAEWOULDBLOCK) {
+ fprintf(stderr,"connect call for local server socket failed. Error Number %d.\n",tmpVal);
+ fflush(stderr);
+ return(-1);
+ }
+ }
+ else {
+ fprintf(stderr,"connect call for non-blocking local client socket unexpectedly succeeds.\n");
+ fflush(stderr);
+ return(-1);
+ }
+ Sleep(10);
+ tmpVal = sizeof(cli_addr);
+ if ((fds[1] = (int)accept(listSock, (struct sockaddr *)&cli_addr, &tmpVal))== INVALID_SOCKET) {
+ fprintf(stderr,"accept call for local server socket failed. Error Number %d.\n",WSAGetLastError());
+ fflush(stderr);
+ return(-1);
+ }
+ if (fcntl(fds[1],F_SETFL,O_NONBLOCK) < 0) {
+ fprintf(stderr,"fcntl call for local server socket failed. Error Number %d.\n",WSAGetLastError());
+ fflush(stderr);
+ return(-1);
+ }
+ tv.tv_sec = 15;
+ tv.tv_usec = 0;
+ FD_ZERO(&myset);
+ FD_SET(fds[0], &myset);
+ tmpVal = select(fds[0] + 1, NULL, &myset, NULL, &tv);
+ if (tmpVal == SOCKET_ERROR) {
+ fprintf(stderr,"socket call for local server socket failed. Error Number %d.\n",WSAGetLastError());
+ fflush(stderr);
+ return(-1);
+ }
+ else if (tmpVal > 0) {
+ lon = sizeof(int);
+ if (!getsockopt(fds[0], SOL_SOCKET, SO_ERROR, (void*)(&valopt), &lon)) {
+ if (valopt) {
+ fprintf(stderr,"getsockopt indicates error on connect completion.\n");
+ return(-1);
+ }
+ }
+ else {
+ fprintf(stderr,"getsockopt call for local client socket failed. Error Number %d.\n",WSAGetLastError());
+ fflush(stderr);
+ return(-1);
+ }
+ }
+ else if (!tmpVal) {
+ fprintf(stderr,"select on connect complete timed out.\n");
+ fflush(stderr);
+ return(-1);
+ }
+ return(0);
+}
+
+unsigned __int64 strtoull(const char *p,char **pend,int base) {
+ unsigned __int64 number = 0;
+ int c;
+ int error;
+
+ while (('\b' == *p) || ('\t' == *p)) // skip leading white space
+ p++;
+ if (*p == '+')
+ p++;
+ switch (base) {
+ case 0:
+ base = 10; // assume decimal base
+ if (*p == '0') {
+ base = 8; // could be octal
+ p++;
+ switch (*p) {
+ case 'x':
+ case 'X':
+ base = 16; // hex
+ p++;
+ break;
+#if BINARY
+ case 'b':
+ case 'B':
+ base = 2; // binary
+ p++;
+ break;
+#endif
+ }
+ }
+ break;
+ case 16: // skip over '0x' and '0X'
+ if (*p == '0' && (p[1] == 'x' || p[1] == 'X'))
+ p += 2;
+ break;
+#if BINARY
+ case 2: // skip over '0b' and '0B'
+ if (*p == '0' && (p[1] == 'b' || p[1] == 'B'))
+ p += 2;
+ break;
+#endif
+ }
+ error = 0;
+ while (1) {
+ c = *p;
+ if ('0' <= c && c <= '9')
+ c -= '0';
+ else if ('a' <= c && c <= 'z')
+ c -= 'a' - 10;
+ else if ('A' <= c && c <= 'Z')
+ c -= 'A' - 10;
+ else // unrecognized character
+ break;
+ if (c >= base) // not in number base
+ break;
+ if ((ULLONG_MAX - c) / base < number)
+ error = 1;
+ number = number * base + c;
+ p++;
+ }
+ if (pend)
+ *pend = (char *)p;
+ if (error) {
+ number = ULLONG_MAX;
+ errno = ERANGE;
+ }
+ return number;
+}
+
+int getrusage(int who, struct rusage * rusage) {
+ FILETIME starttime;
+ FILETIME exittime;
+ FILETIME kerneltime;
+ FILETIME usertime;
+ ULARGE_INTEGER li;
+
+ if (rusage == (struct rusage *)NULL) {
+ errno = EFAULT;
+ return -1;
+ }
+ memset(rusage, 0, sizeof(struct rusage));
+ if (GetProcessTimes(GetCurrentProcess(),
+ &starttime, &exittime, &kerneltime,
+ &usertime) == 0) {
+ /* Where is dosmaperr declared. Will address later. */
+ /* _dosmaperr(GetLastError()); */
+ return -1;
+ }
+ /* Convert FILETIMEs (0.1 us) to struct timeval */
+ memcpy(&li, &kerneltime, sizeof(FILETIME));
+ li.QuadPart /= 10L; /* Convert to microseconds */
+ rusage->ru_stime.tv_sec = (long)(li.QuadPart / 1000000L);
+ rusage->ru_stime.tv_usec = li.QuadPart % 1000000L;
+ memcpy(&li, &usertime, sizeof(FILETIME));
+ li.QuadPart /= 10L; /* Convert to microseconds */
+ rusage->ru_utime.tv_sec = (long)(li.QuadPart / 1000000L);
+ rusage->ru_utime.tv_usec = li.QuadPart % 1000000L;
+ return(0);
+}
+
+int sleep(int seconds) {
+ Sleep(seconds*1000);
+ return 0;
+}
+
+int kill(int pid, int sig) {
+ if (TerminateProcess((HANDLE)pid, 0))
+ return 0;
+ return -1;
+}
diff --git a/win32/win32.h b/win32/win32.h
new file mode 100644
index 0000000..c69a7c5
--- /dev/null
+++ b/win32/win32.h
@@ -0,0 +1,205 @@
+/* win32.h
+ *
+ */
+
+#ifndef WIN32_H
+#define WIN32_H
+
+#undef _WIN32_WINNT
+#define _WIN32_WINNT 0x0501 /* Needed to resolve getaddrinfo et al. */
+
+#include <winsock2.h>
+#include <ws2tcpip.h>
+
+#include <stdio.h>
+#include <io.h>
+#include <time.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdint.h>
+#include <process.h>
+
+#define EWOULDBLOCK EAGAIN
+#define EAFNOSUPPORT 47
+#define EADDRINUSE WSAEADDRINUSE
+#define EAI_SYSTEM -11
+
+typedef char *caddr_t;
+
+#define O_BLOCK 0
+#define O_NONBLOCK 1
+#define F_GETFL 3
+#define F_SETFL 4
+
+#define RUSAGE_SELF 0
+
+#define IOV_MAX 1024
+struct iovec {
+ u_long iov_len;
+ char FAR* iov_base;
+};
+
+struct msghdr {
+ void *msg_name; /* Socket name */
+ int msg_namelen; /* Length of name */
+ struct iovec *msg_iov; /* Data blocks */
+ int msg_iovlen; /* Number of blocks */
+ void *msg_accrights; /* Per protocol magic (eg BSD file descriptor passing) */
+ int msg_accrightslen; /* Length of rights list */
+};
+
+#if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
+ #define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64
+#else
+ #define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL
+#endif
+
+/* Structure which says how much of each resource has been used. */
+struct rusage {
+ /* Total amount of user time used. */
+ struct timeval ru_utime;
+ /* Total amount of system time used. */
+ struct timeval ru_stime;
+ /* Maximum resident set size (in kilobytes). */
+ long int ru_maxrss;
+ /* Amount of sharing of text segment memory
+ with other processes (kilobyte-seconds). */
+ long int ru_ixrss;
+ /* Amount of data segment memory used (kilobyte-seconds). */
+ long int ru_idrss;
+ /* Amount of stack memory used (kilobyte-seconds). */
+ long int ru_isrss;
+ /* Number of soft page faults (i.e. those serviced by reclaiming
+ a page from the list of pages awaiting reallocation. */
+ long int ru_minflt;
+ /* Number of hard page faults (i.e. those that required I/O). */
+ long int ru_majflt;
+ /* Number of times a process was swapped out of physical memory. */
+ long int ru_nswap;
+ /* Number of input operations via the file system. Note: This
+ and `ru_oublock' do not include operations with the cache. */
+ long int ru_inblock;
+ /* Number of output operations via the file system. */
+ long int ru_oublock;
+ /* Number of IPC messages sent. */
+ long int ru_msgsnd;
+ /* Number of IPC messages received. */
+ long int ru_msgrcv;
+ /* Number of signals delivered. */
+ long int ru_nsignals;
+ /* Number of voluntary context switches, i.e. because the process
+ gave up the process before it had to (usually to wait for some
+ resource to be available). */
+ long int ru_nvcsw;
+ /* Number of involuntary context switches, i.e. a higher priority process
+ became runnable or the current process used up its time slice. */
+ long int ru_nivcsw;
+};
+
+int fcntl(SOCKET s, int cmd, int val);
+int inet_aton(register const char *cp, struct in_addr *addr);
+
+#define close(s) closesocket(s)
+
+static inline void mapErr(int error) {
+ switch(error) {
+ default:
+ break;
+ case WSAEPFNOSUPPORT:
+ errno = EAFNOSUPPORT;
+ break;
+ case WSA_IO_PENDING:
+ case WSATRY_AGAIN:
+ errno = EAGAIN;
+ break;
+ case WSAEWOULDBLOCK:
+ errno = EWOULDBLOCK;
+ break;
+ case WSAEMSGSIZE:
+ errno = E2BIG;
+ break;
+ case WSAECONNRESET:
+ errno = 0;
+ break;
+ }
+}
+
+#define write mem_write
+
+static inline size_t mem_write(int s, void *buf, size_t len)
+{
+ DWORD dwBufferCount = 0;
+ int error;
+
+ WSABUF wsabuf = { len, (char *)buf} ;
+ if(WSASend(s, &wsabuf, 1, &dwBufferCount, 0, NULL, NULL) == 0) {
+ return dwBufferCount;
+ }
+ error = WSAGetLastError();
+ if(error == WSAECONNRESET) return 0;
+ mapErr(error);
+ return -1;
+}
+
+#define read mem_read
+
+static inline size_t mem_read(int s, void *buf, size_t len)
+{
+ DWORD flags = 0;
+ DWORD dwBufferCount;
+ WSABUF wsabuf = { len, (char *)buf };
+ int error;
+
+ if(WSARecv((SOCKET)s,
+ &wsabuf,
+ 1,
+ &dwBufferCount,
+ &flags,
+ NULL,
+ NULL
+ ) == 0) {
+ return dwBufferCount;
+ }
+ error = WSAGetLastError();
+ if (error == WSAECONNRESET) return 0;
+ mapErr(error);
+ return -1;
+}
+
+static inline int sendmsg(int s, const struct msghdr *msg, int flags)
+{
+ DWORD dwBufferCount;
+ int error;
+
+ if(WSASendTo((SOCKET) s,
+ (LPWSABUF)msg->msg_iov,
+ (DWORD)msg->msg_iovlen,
+ &dwBufferCount,
+ flags,
+ msg->msg_name,
+ msg->msg_namelen,
+ NULL,
+ NULL
+ ) == 0) {
+ return dwBufferCount;
+ }
+ error = WSAGetLastError();
+ if (error == WSAECONNRESET) return 0;
+ mapErr(error);
+ return -1;
+}
+
+int createLocalListSock(struct sockaddr_in *saddr);
+int createLocalSocketPair(int listSock, int *fds, struct sockaddr_in *saddr);
+int getrusage(int who, struct rusage *usage);
+int kill(int pid, int sig);
+int sleep(int seconds);
+
+#ifndef _WIN64
+static inline void _set_errno(int err)
+{
+ errno = err;
+}
+#endif
+
+#endif