summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.windows77
-rw-r--r--configure.ac27
-rwxr-xr-xetc/install-mingw.sh69
-rw-r--r--librabbitmq/Makefile.am8
-rw-r--r--librabbitmq/amqp_api.c6
-rw-r--r--librabbitmq/amqp_connection.c20
-rw-r--r--librabbitmq/amqp_mem.c1
-rw-r--r--librabbitmq/amqp_private.h5
-rw-r--r--librabbitmq/amqp_socket.c36
-rw-r--r--librabbitmq/amqp_table.c2
-rw-r--r--librabbitmq/codegen.py1
-rw-r--r--librabbitmq/unix/socket.c85
-rw-r--r--librabbitmq/unix/socket.h80
-rw-r--r--librabbitmq/windows/socket.c88
-rw-r--r--librabbitmq/windows/socket.h92
-rw-r--r--tests/Makefile.am2
-rw-r--r--tools/Makefile.am16
-rw-r--r--tools/common.c59
-rw-r--r--tools/common.h8
-rw-r--r--tools/consume.c1
-rw-r--r--tools/unix/process.c100
-rw-r--r--tools/unix/process.h57
-rw-r--r--tools/windows/compat.c73
-rw-r--r--tools/windows/compat.h51
-rw-r--r--tools/windows/process.c204
-rw-r--r--tools/windows/process.h59
26 files changed, 1113 insertions, 114 deletions
diff --git a/README.windows b/README.windows
new file mode 100644
index 0000000..1a20c00
--- /dev/null
+++ b/README.windows
@@ -0,0 +1,77 @@
+# rabbitmq-c and Windows
+
+rabbitmq-c can now be built on Windows using the MinGW/MSYS ports of
+the GNU toolchain and miscellaneous utilities. This includes the
+example programs and tools.
+
+The results are native Windows DLLs and EXEs, and can be used without
+having MinGW installed. But the librabbitmq header files currently
+use GCC extensions, and for this reason it is still not possible to
+use Microsoft's C/C++ to build applications against the librabbitmq
+DLL. Hopefully this will get fixed before long.
+
+
+# Building rabbitmq-c
+
+rabbitmq-c is built on Windows using MinGW and MSYS. In brief, MinGW
+is a native port of the GNU toolchain to Windows; MSYS is a set of
+ports of common GNU utilities to run under Windows, so that typical
+autotools-based builds will work there. MinGW/MSYS can be used to
+build native Windows applications and DLLs, which do not depend on
+MinGW/MSYS to run.
+
+So to build rabbitmq-c on Windows, you need to download and install
+the relevant parts of MinGW/MSYS. This can be a fairly time consuming
+process - there are about 20 files to be downloaded and unpacked. To
+make it easier, we provide a bash script that automates this process,
+in rabbitmq-c/etc/install-mingw.sh. You can run this cygwin, or under
+Linux and copy the results over or put them on a shared drive. Some
+MinGW packages are .tar.lzma files, so it requires a system with xz
+and a tar that supports the -J option, which probably rules out OSX.
+
+Run install-mingw.sh specifying the destination directory, e.g.
+
+ $ etc/install-mingw.sh /tmp/mingw
+
+Python is needed for the rabbitmq-c build, so you will also need to
+install python under Windows. The Windows installer from python.org
+will do fine.
+
+You will need to get the rabbitmq-c and rabbitmq-codegen source code.
+If you are getting it from Mercurial, you will need to run "autoreconf
+-i" within rabbitmq-c somewhere other than under MinGW first (perhaps
+this can be done under MinGW/MSYS, but the packages installed by
+install-mingw.sh are not sufficient).
+
+Open a cmd window, and ensure that both the MinGW bin directory and the python install directory are in the path, e.g.
+
+ C:\>set PATH=%PATH%;C:\mingw\bin;C:\Python26
+
+Then start bash, and run the following mount command (substituting the
+Windows path of your MinGW install):
+
+ C:\>bash
+ bash-3.1$ mount 'C:\mingw' /mingw
+
+Then go to the rabbitmq-c directory, and configure and make as normal:
+
+ bash-3.1$ ./configure && make
+ [...]
+
+
+# Running the tools without mingw
+
+You can run the resulting tools EXEs without the rest of MinGW. To do
+this, copy the following files into a directory:
+
+- rabbitmq-c/tools/.libs/*.exe
+
+- rabbitmq-c/librabbitmq/.libs/librabbitmq-0.dll
+
+- /lib/libpopt-0.dll
+
+- /lib/libiconv-2.dll
+
+- /lib/libintl-8.dll
+
+
diff --git a/configure.ac b/configure.ac
index 13d1b4b..f7cfb74 100644
--- a/configure.ac
+++ b/configure.ac
@@ -9,6 +9,7 @@ AC_GNU_SOURCE
AC_PROG_CC
dnl Library checks
+AC_LIBTOOL_WIN32_DLL
AM_PROG_LIBTOOL
dnl Header-file checks
@@ -21,6 +22,26 @@ if test "x$GCC" = "xyes"; then
fi
fi
+dnl Detect the kind of host we're building for
+AC_CANONICAL_HOST
+windows=no
+case "${host}" in
+*-*-mingw*)
+ windows=yes
+ ;;
+esac
+AM_CONDITIONAL(WINDOWS, test "x$windows" = xyes)
+AS_IF([test "x$windows" = xyes],
+ [AC_DEFINE([WINDOWS], [1], [Define to 1 if on Windows.])]
+)
+
+dnl Decide which API abstraction layer to use
+PLATFORM_DIR=unix
+if test "x$windows" = xyes ; then
+ PLATFORM_DIR=windows
+fi
+AC_SUBST(PLATFORM_DIR)
+
dnl Enable -m64 if we were asked to do so
AC_ARG_ENABLE(64-bit,
[ --enable-64-bit produce 64-bit library],
@@ -65,8 +86,12 @@ AC_SUBST(AMQP_CODEGEN_DIR)
AC_SUBST(AMQP_SPEC_JSON_PATH)
AC_SUBST(PYTHON)
-# Check for libpopt, which we need to build the tools
+dnl Decide which extra win32 libs we need
+EXTRA_LIBS=
+AS_IF([test "x$windows" = xyes], [EXTRA_LIBS="-lws2_32 $EXTRA_LIBS"])
+AC_SUBST(EXTRA_LIBS)
+dnl Check for libpopt, which we need to build the tools
AC_ARG_WITH([popt],
[AS_HELP_STRING([--with-popt], [use the popt library. Needed for tools.])],
[],
diff --git a/etc/install-mingw.sh b/etc/install-mingw.sh
new file mode 100755
index 0000000..de953d4
--- /dev/null
+++ b/etc/install-mingw.sh
@@ -0,0 +1,69 @@
+#!/bin/bash
+
+if [ $# -ne 1 ] ; then
+ echo "usage: install-mingw.sh <destination directory>" 1>&2
+ exit 1
+fi
+
+unpack_dir=$1
+
+if [ -eb "$unpack_dir" ] ; then
+ echo "Destination directory already exists; please delete it if you are sure" 1>&2
+ exit 1
+fi
+
+set -e
+
+download_dir=/tmp/install-mingw.$$
+mkdir -p $download_dir $unpack_dir
+
+while read f ; do
+ wget -P $download_dir -N http://switch.dl.sourceforge.net/project/mingw/$f
+done <<EOF
+GCC%20Version%204/gcc-4.5.0-1/gcc-core-4.5.0-1-mingw32-bin.tar.lzma
+GCC%20Version%204/gcc-4.5.0-1/libgcc-4.5.0-1-mingw32-dll-1.tar.lzma
+GNU%20Binutils/binutils-2.20.1/binutils-2.20.1-2-mingw32-bin.tar.gz
+MinGW%20API%20for%20MS-Windows/w32api-3.14/w32api-3.14-mingw32-dev.tar.gz
+MinGW%20gettext/gettext-0.17-1/gettext-0.17-1-mingw32-dev.tar.lzma
+MinGW%20gettext/gettext-0.17-1/libintl-0.17-1-mingw32-dll-8.tar.lzma
+MinGW%20gmp/gmp-5.0.1-1/libgmp-5.0.1-1-mingw32-dll-10.tar.lzma
+MinGW%20gmp/gmp-5.0.1-1/libgmpxx-5.0.1-1-mingw32-dll-4.tar.lzma
+MinGW%20libiconv/libiconv-1.13.1-1/libcharset-1.13.1-1-mingw32-dll-1.tar.lzma
+MinGW%20libiconv/libiconv-1.13.1-1/libiconv-1.13.1-1-mingw32-dev.tar.lzma
+MinGW%20libiconv/libiconv-1.13.1-1/libiconv-1.13.1-1-mingw32-dll-2.tar.lzma
+MinGW%20mpc/mpc-0.8.1-1/libmpc-0.8.1-1-mingw32-dll-2.tar.lzma
+MinGW%20mpfr/mpfr-2.4.1-1/libmpfr-2.4.1-1-mingw32-dll-1.tar.lzma
+MinGW%20popt/popt-1.15-1/libpopt-1.15-1-mingw32-dev.tar.lzma
+MinGW%20popt/popt-1.15-1/libpopt-1.15-1-mingw32-dll-0.tar.lzma
+MinGW%20pthreads-w32/pthreads-w32-2.8.0-3/libpthread-2.8.0-3-mingw32-dll-2.tar.lzma
+MinGW%20Runtime/mingwrt-3.18/mingwrt-3.18-mingw32-dev.tar.gz
+MinGW%20Runtime/mingwrt-3.18/mingwrt-3.18-mingw32-dll.tar.gz
+MSYS%20Base%20System/msys-1.0.14-1/msysCORE-1.0.14-1-msys-1.0.14-bin.tar.lzma
+MSYS%20bash/bash-3.1.17-2/bash-3.1.17-2-msys-1.0.11-bin.tar.lzma
+MSYS%20coreutils/coreutils-5.97-2/coreutils-5.97-2-msys-1.0.11-bin.tar.lzma
+MSYS%20diffutils/diffutils-2.8.7.20071206cvs-2/diffutils-2.8.7.20071206cvs-2-msys-1.0.11-bin.tar.lzma
+MSYS%20gawk/gawk-3.1.7-1/gawk-3.1.7-1-msys-1.0.11-bin.tar.lzma
+MSYS%20grep/grep-2.5.4-1/grep-2.5.4-1-msys-1.0.11-bin.tar.lzma
+MSYS%20libtool/libtool-2.2.7a-1/libtool-2.2.7a-1-msys-1.0.11-bin.tar.lzma
+MSYS%20make/make-3.81-2/make-3.81-2-msys-1.0.11-bin.tar.lzma
+MSYS%20sed/sed-4.2.1-1/sed-4.2.1-1-msys-1.0.11-bin.tar.lzma
+EOF
+
+for f in $download_dir/* ; do
+ case $f in
+ *.tar.gz)
+ tar -C $unpack_dir -xzf $f
+ ;;
+
+ *.tar.lzma)
+ tar -C $unpack_dir -xJf $f
+ ;;
+
+ *)
+ echo "Don't know how to unpack $f" 1>&2
+ exit 1
+ ;;
+ esac
+done
+
+rm -rf $download_dir
diff --git a/librabbitmq/Makefile.am b/librabbitmq/Makefile.am
index b4c8843..9211c8f 100644
--- a/librabbitmq/Makefile.am
+++ b/librabbitmq/Makefile.am
@@ -1,15 +1,19 @@
lib_LTLIBRARIES = librabbitmq.la
-librabbitmq_la_SOURCES = amqp_mem.c amqp_table.c amqp_connection.c amqp_socket.c amqp_debug.c amqp_api.c
+AM_CFLAGS = -I$(PLATFORM_DIR)
+librabbitmq_la_SOURCES = amqp_mem.c amqp_table.c amqp_connection.c amqp_socket.c amqp_debug.c amqp_api.c $(PLATFORM_DIR)/socket.c
+librabbitmq_la_LDFLAGS = -no-undefined
nodist_librabbitmq_la_SOURCES = amqp_framing.c
include_HEADERS = amqp_framing.h amqp.h
-noinst_HEADERS = amqp_private.h
+noinst_HEADERS = amqp_private.h $(PLATFORM_DIR)/socket.h
BUILT_SOURCES = amqp_framing.h amqp_framing.c
CLEANFILES = amqp_framing.h amqp_framing.c
EXTRA_DIST = codegen.py
CODEGEN_PY=$(srcdir)/codegen.py
+LDADD=$(EXTRA_LIBS)
+
amqp_framing.h: $(AMQP_SPEC_JSON_PATH) $(CODEGEN_PY)
PYTHONPATH=$(AMQP_CODEGEN_DIR) $(PYTHON) $(CODEGEN_PY) header $< $@
diff --git a/librabbitmq/amqp_api.c b/librabbitmq/amqp_api.c
index 3a4440f..9918819 100644
--- a/librabbitmq/amqp_api.c
+++ b/librabbitmq/amqp_api.c
@@ -52,7 +52,6 @@
#include <stdio.h>
#include <string.h>
#include <stdint.h>
-#include <errno.h>
#include "amqp.h"
#include "amqp_framing.h"
@@ -85,9 +84,8 @@ const char *amqp_error_string(int err)
break;
case ERROR_CATEGORY_OS:
- str = strerror(err);
- break;
-
+ return amqp_os_error_string(err);
+
default:
str = "(undefined error category)";
}
diff --git a/librabbitmq/amqp_connection.c b/librabbitmq/amqp_connection.c
index a264ad3..63af96a 100644
--- a/librabbitmq/amqp_connection.c
+++ b/librabbitmq/amqp_connection.c
@@ -52,17 +52,13 @@
#include <stdio.h>
#include <string.h>
#include <stdint.h>
-#include <errno.h>
-
-#include <unistd.h>
-#include <sys/uio.h>
-#include <sys/types.h>
+#include <assert.h>
#include "amqp.h"
#include "amqp_framing.h"
#include "amqp_private.h"
-#include <assert.h>
+#include "socket.h"
#define INITIAL_FRAME_POOL_PAGE_SIZE 65536
#define INITIAL_DECODING_POOL_PAGE_SIZE 131072
@@ -173,8 +169,8 @@ void amqp_destroy_connection(amqp_connection_state_t state) {
int amqp_end_connection(amqp_connection_state_t state) {
int s = state->sockfd;
amqp_destroy_connection(state);
- if (close(s) < 0)
- return -encoded_errno();
+ if (socket_close(s) < 0)
+ return -encoded_socket_errno();
else
return 0;
}
@@ -433,8 +429,8 @@ int amqp_send_frame(amqp_connection_state_t state,
res = inner_send_frame(state, frame, &encoded, &payload_len);
switch (res) {
case 0:
- res = write(state->sockfd, state->outbound_buffer.bytes,
- payload_len + (HEADER_SIZE + FOOTER_SIZE));
+ res = socket_write(state->sockfd, state->outbound_buffer.bytes,
+ payload_len + (HEADER_SIZE + FOOTER_SIZE));
break;
case 1: {
@@ -447,7 +443,7 @@ int amqp_send_frame(amqp_connection_state_t state,
iov[2].iov_base = &frame_end_byte;
assert(FOOTER_SIZE == 1);
iov[2].iov_len = FOOTER_SIZE;
- res = writev(state->sockfd, &iov[0], 3);
+ res = socket_writev(state->sockfd, &iov[0], 3);
break;
}
@@ -456,7 +452,7 @@ int amqp_send_frame(amqp_connection_state_t state,
}
if (res < 0)
- return -encoded_errno();
+ return -encoded_socket_errno();
else
return 0;
}
diff --git a/librabbitmq/amqp_mem.c b/librabbitmq/amqp_mem.c
index 7783cbb..021151a 100644
--- a/librabbitmq/amqp_mem.c
+++ b/librabbitmq/amqp_mem.c
@@ -53,7 +53,6 @@
#include <string.h>
#include <stdint.h>
#include <sys/types.h>
-#include <errno.h>
#include <assert.h>
#include "amqp.h"
diff --git a/librabbitmq/amqp_private.h b/librabbitmq/amqp_private.h
index f922933..7206ae5 100644
--- a/librabbitmq/amqp_private.h
+++ b/librabbitmq/amqp_private.h
@@ -55,8 +55,6 @@
extern "C" {
#endif
-#include <arpa/inet.h> /* ntohl, htonl, ntohs, htons */
-
/* Error numbering: Because of differences in error numbering on
* different platforms, we want to keep error numbers opaque for
* client code. Internally, we encode the category of an error
@@ -78,8 +76,7 @@ extern "C" {
#define ERROR_CONNECTION_CLOSED 7
#define ERROR_MAX 7
-/* Get the encoded form of errno */
-#define encoded_errno() (errno | ERROR_CATEGORY_OS)
+extern const char *amqp_os_error_string(int err);
/*
* Connection states:
diff --git a/librabbitmq/amqp_socket.c b/librabbitmq/amqp_socket.c
index 8f3f05b..6425c34 100644
--- a/librabbitmq/amqp_socket.c
+++ b/librabbitmq/amqp_socket.c
@@ -52,29 +52,27 @@
#include <stdio.h>
#include <string.h>
#include <stdint.h>
-#include <errno.h>
#include <stdarg.h>
+#include <assert.h>
#include "amqp.h"
#include "amqp_framing.h"
#include "amqp_private.h"
-#include <sys/types.h>
-#include <sys/uio.h>
-#include <unistd.h>
-#include <sys/socket.h>
-#include <netdb.h>
-#include <netinet/in.h>
+#include "socket.h"
-#include <assert.h>
int amqp_open_socket(char const *hostname,
int portnumber)
{
- int sockfd;
+ int sockfd, res;
struct sockaddr_in addr;
struct hostent *he;
+ res = socket_init();
+ if (res)
+ return res;
+
he = gethostbyname(hostname);
if (he == NULL)
return -ERROR_HOST_NOT_FOUND;
@@ -83,11 +81,11 @@ int amqp_open_socket(char const *hostname,
addr.sin_port = htons(portnumber);
addr.sin_addr.s_addr = * (uint32_t *) he->h_addr_list[0];
- sockfd = socket(PF_INET, SOCK_STREAM, 0);
- if (connect(sockfd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
- int result = -encoded_errno();
- close(sockfd);
- return result;
+ sockfd = socket_socket(PF_INET, SOCK_STREAM, 0);
+ if (socket_connect(sockfd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+ res = -encoded_socket_errno();
+ socket_close(sockfd);
+ return res;
}
return sockfd;
@@ -107,7 +105,7 @@ static char *header() {
}
int amqp_send_header(amqp_connection_state_t state) {
- return write(state->sockfd, header(), 8);
+ return socket_write(state->sockfd, header(), 8);
}
int amqp_send_header_to(amqp_connection_state_t state,
@@ -190,14 +188,14 @@ static int wait_frame_inner(amqp_connection_state_t state,
assert(result != 0);
}
- result = read(state->sockfd,
- state->sock_inbound_buffer.bytes,
- state->sock_inbound_buffer.len);
+ result = socket_read(state->sockfd,
+ state->sock_inbound_buffer.bytes,
+ state->sock_inbound_buffer.len);
if (result <= 0) {
if (result == 0)
return -ERROR_CONNECTION_CLOSED;
else
- return -encoded_errno();
+ return -encoded_socket_errno();
}
state->sock_inbound_limit = result;
diff --git a/librabbitmq/amqp_table.c b/librabbitmq/amqp_table.c
index db45588..3f5eb61 100644
--- a/librabbitmq/amqp_table.c
+++ b/librabbitmq/amqp_table.c
@@ -52,10 +52,10 @@
#include <stdio.h>
#include <string.h>
#include <stdint.h>
-#include <errno.h>
#include "amqp.h"
#include "amqp_private.h"
+#include "socket.h"
#include <assert.h>
diff --git a/librabbitmq/codegen.py b/librabbitmq/codegen.py
index 9a82fbe..6b38666 100644
--- a/librabbitmq/codegen.py
+++ b/librabbitmq/codegen.py
@@ -265,6 +265,7 @@ def genErl(spec):
print '#include "amqp.h"'
print '#include "amqp_framing.h"'
print '#include "amqp_private.h"'
+ print '#include "socket.h"'
print """
char const *amqp_constant_name(int constantNumber) {
diff --git a/librabbitmq/unix/socket.c b/librabbitmq/unix/socket.c
new file mode 100644
index 0000000..51db413
--- /dev/null
+++ b/librabbitmq/unix/socket.c
@@ -0,0 +1,85 @@
+/*
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * The Original Code is librabbitmq.
+ *
+ * The Initial Developers of the Original Code are LShift Ltd, Cohesive
+ * Financial Technologies LLC, and Rabbit Technologies Ltd. Portions
+ * created before 22-Nov-2008 00:00:00 GMT by LShift Ltd, Cohesive
+ * Financial Technologies LLC, or Rabbit Technologies Ltd are Copyright
+ * (C) 2007-2008 LShift Ltd, Cohesive Financial Technologies LLC, and
+ * Rabbit Technologies Ltd.
+ *
+ * Portions created by LShift Ltd are Copyright (C) 2007-2010 LShift
+ * Ltd. Portions created by Cohesive Financial Technologies LLC are
+ * Copyright (C) 2007-2010 Cohesive Financial Technologies
+ * LLC. Portions created by Rabbit Technologies Ltd are Copyright (C)
+ * 2007-2010 Rabbit Technologies Ltd.
+ *
+ * Portions created by Tony Garnock-Jones are Copyright (C) 2009-2010
+ * LShift Ltd and Tony Garnock-Jones.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): ______________________________________.
+ *
+ * Alternatively, the contents of this file may be used under the terms
+ * of the GNU General Public License Version 2 or later (the "GPL"), in
+ * which case the provisions of the GPL are applicable instead of those
+ * above. If you wish to allow use of your version of this file only
+ * under the terms of the GPL, and not to allow others to use your
+ * version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the
+ * notice and other provisions required by the GPL. If you do not
+ * delete the provisions above, a recipient may use your version of
+ * this file under the terms of any one of the MPL or the GPL.
+ *
+ * ***** END LICENSE BLOCK *****
+ */
+
+#include <sys/socket.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdint.h>
+#include <string.h>
+
+#include "amqp.h"
+#include "amqp_private.h"
+#include "socket.h"
+
+int socket_socket(int domain, int type, int proto)
+{
+ int flags;
+
+ int s = socket(domain, type, proto);
+ if (s < 0)
+ return s;
+
+ /* Always enable CLOEXEC on the socket */
+ flags = fcntl(s, F_GETFD);
+ if (flags == -1
+ || fcntl(s, F_SETFD, (long)(flags | FD_CLOEXEC)) == -1) {
+ int e = errno;
+ close(s);
+ errno = e;
+ return -1;
+ }
+
+ return s;
+}
+
+const char *amqp_os_error_string(int err)
+{
+ return strdup(strerror(err));
+}
diff --git a/librabbitmq/unix/socket.h b/librabbitmq/unix/socket.h
new file mode 100644
index 0000000..d7295c3
--- /dev/null
+++ b/librabbitmq/unix/socket.h
@@ -0,0 +1,80 @@
+#ifndef librabbitmq_unix_socket_h
+#define librabbitmq_unix_socket_h
+
+/*
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * The Original Code is librabbitmq.
+ *
+ * The Initial Developers of the Original Code are LShift Ltd, Cohesive
+ * Financial Technologies LLC, and Rabbit Technologies Ltd. Portions
+ * created before 22-Nov-2008 00:00:00 GMT by LShift Ltd, Cohesive
+ * Financial Technologies LLC, or Rabbit Technologies Ltd are Copyright
+ * (C) 2007-2008 LShift Ltd, Cohesive Financial Technologies LLC, and
+ * Rabbit Technologies Ltd.
+ *
+ * Portions created by LShift Ltd are Copyright (C) 2007-2010 LShift
+ * Ltd. Portions created by Cohesive Financial Technologies LLC are
+ * Copyright (C) 2007-2010 Cohesive Financial Technologies
+ * LLC. Portions created by Rabbit Technologies Ltd are Copyright (C)
+ * 2007-2010 Rabbit Technologies Ltd.
+ *
+ * Portions created by Tony Garnock-Jones are Copyright (C) 2009-2010
+ * LShift Ltd and Tony Garnock-Jones.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): ______________________________________.
+ *
+ * Alternatively, the contents of this file may be used under the terms
+ * of the GNU General Public License Version 2 or later (the "GPL"), in
+ * which case the provisions of the GPL are applicable instead of those
+ * above. If you wish to allow use of your version of this file only
+ * under the terms of the GPL, and not to allow others to use your
+ * version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the
+ * notice and other provisions required by the GPL. If you do not
+ * delete the provisions above, a recipient may use your version of
+ * this file under the terms of any one of the MPL or the GPL.
+ *
+ * ***** END LICENSE BLOCK *****
+ */
+
+#include <errno.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/uio.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <netinet/in.h>
+
+static inline int socket_init(void)
+{
+ return 0;
+}
+
+extern int socket_socket(int domain, int type, int proto);
+
+#define socket_connect connect
+#define socket_close close
+#define socket_read read
+#define socket_write write
+#define socket_writev writev
+
+static inline int encoded_socket_errno()
+{
+ return errno | ERROR_CATEGORY_OS;
+}
+
+#endif
diff --git a/librabbitmq/windows/socket.c b/librabbitmq/windows/socket.c
new file mode 100644
index 0000000..f809f62
--- /dev/null
+++ b/librabbitmq/windows/socket.c
@@ -0,0 +1,88 @@
+/*
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * The Original Code is librabbitmq.
+ *
+ * The Initial Developers of the Original Code are LShift Ltd, Cohesive
+ * Financial Technologies LLC, and Rabbit Technologies Ltd. Portions
+ * created before 22-Nov-2008 00:00:00 GMT by LShift Ltd, Cohesive
+ * Financial Technologies LLC, or Rabbit Technologies Ltd are Copyright
+ * (C) 2007-2008 LShift Ltd, Cohesive Financial Technologies LLC, and
+ * Rabbit Technologies Ltd.
+ *
+ * Portions created by LShift Ltd are Copyright (C) 2007-2010 LShift
+ * Ltd. Portions created by Cohesive Financial Technologies LLC are
+ * Copyright (C) 2007-2010 Cohesive Financial Technologies
+ * LLC. Portions created by Rabbit Technologies Ltd are Copyright (C)
+ * 2007-2010 Rabbit Technologies Ltd.
+ *
+ * Portions created by Tony Garnock-Jones are Copyright (C) 2009-2010
+ * LShift Ltd and Tony Garnock-Jones.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): ______________________________________.
+ *
+ * Alternatively, the contents of this file may be used under the terms
+ * of the GNU General Public License Version 2 or later (the "GPL"), in
+ * which case the provisions of the GPL are applicable instead of those
+ * above. If you wish to allow use of your version of this file only
+ * under the terms of the GPL, and not to allow others to use your
+ * version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the
+ * notice and other provisions required by the GPL. If you do not
+ * delete the provisions above, a recipient may use your version of
+ * this file under the terms of any one of the MPL or the GPL.
+ *
+ * ***** END LICENSE BLOCK *****
+ */
+
+#include <windows.h>
+#include <stdint.h>
+
+#include "amqp.h"
+#include "amqp_private.h"
+#include "socket.h"
+
+static int called_wsastartup;
+
+int socket_init(void)
+{
+ if (!called_wsastartup) {
+ WSADATA data;
+ int res = WSAStartup(0x0202, &data);
+ if (res)
+ return -res;
+
+ called_wsastartup = 1;
+ }
+
+ return 0;
+}
+
+const char *amqp_os_error_string(int err)
+{
+ char *msg, *copy;
+
+ if (!FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
+ | FORMAT_MESSAGE_ALLOCATE_BUFFER,
+ NULL, err,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPSTR)&msg, 0, NULL))
+ return strdup("(error retrieving Windows error message)");
+
+ copy = strdup(msg);
+ LocalFree(msg);
+ return copy;
+}
diff --git a/librabbitmq/windows/socket.h b/librabbitmq/windows/socket.h
new file mode 100644
index 0000000..bff6efc
--- /dev/null
+++ b/librabbitmq/windows/socket.h
@@ -0,0 +1,92 @@
+#ifndef librabbitmq_windows_socket_h
+#define librabbitmq_windows_socket_h
+
+/*
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * The Original Code is librabbitmq.
+ *
+ * The Initial Developers of the Original Code are LShift Ltd, Cohesive
+ * Financial Technologies LLC, and Rabbit Technologies Ltd. Portions
+ * created before 22-Nov-2008 00:00:00 GMT by LShift Ltd, Cohesive
+ * Financial Technologies LLC, or Rabbit Technologies Ltd are Copyright
+ * (C) 2007-2008 LShift Ltd, Cohesive Financial Technologies LLC, and
+ * Rabbit Technologies Ltd.
+ *
+ * Portions created by LShift Ltd are Copyright (C) 2007-2010 LShift
+ * Ltd. Portions created by Cohesive Financial Technologies LLC are
+ * Copyright (C) 2007-2010 Cohesive Financial Technologies
+ * LLC. Portions created by Rabbit Technologies Ltd are Copyright (C)
+ * 2007-2010 Rabbit Technologies Ltd.
+ *
+ * Portions created by Tony Garnock-Jones are Copyright (C) 2009-2010
+ * LShift Ltd and Tony Garnock-Jones.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): ______________________________________.
+ *
+ * Alternatively, the contents of this file may be used under the terms
+ * of the GNU General Public License Version 2 or later (the "GPL"), in
+ * which case the provisions of the GPL are applicable instead of those
+ * above. If you wish to allow use of your version of this file only
+ * under the terms of the GPL, and not to allow others to use your
+ * version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the
+ * notice and other provisions required by the GPL. If you do not
+ * delete the provisions above, a recipient may use your version of
+ * this file under the terms of any one of the MPL or the GPL.
+ *
+ * ***** END LICENSE BLOCK *****
+ */
+
+#include <winsock2.h>
+
+extern int socket_init(void);
+
+#define socket_socket socket
+#define socket_connect connect
+#define socket_close closesocket
+
+static inline int socket_read(int sock, void *buf, size_t count)
+{
+ return recv(sock, buf, count, 0);
+}
+
+static inline int socket_write(int sock, void *buf, size_t count)
+{
+ return send(sock, buf, count, 0);
+}
+
+/* same as WSABUF */
+struct iovec {
+ u_long iov_len;
+ char *iov_base;
+};
+
+static inline int socket_writev(int sock, struct iovec *iov, int nvecs)
+{
+ DWORD ret;
+ if (WSASend(sock, (LPWSABUF)iov, nvecs, &ret, 0, NULL, NULL) == 0)
+ return ret;
+ else
+ return -1;
+}
+
+static inline int encoded_socket_errno()
+{
+ return WSAGetLastError() | ERROR_CATEGORY_OS;
+}
+
+#endif
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 1ac6faf..7c8a4fe 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -1,4 +1,4 @@
noinst_PROGRAMS = test_tables
-AM_CFLAGS = -I$(top_srcdir)/librabbitmq
+AM_CFLAGS = -I$(top_srcdir)/librabbitmq -I$(top_srcdir)/librabbitmq/$(PLATFORM_DIR)
AM_LDFLAGS = $(top_builddir)/librabbitmq/librabbitmq.la
diff --git a/tools/Makefile.am b/tools/Makefile.am
index 307fbd2..3f9fd6a 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -1,15 +1,21 @@
bin_PROGRAMS = amqp-publish amqp-get amqp-consume
-AM_CFLAGS = -I$(top_srcdir)/librabbitmq
+AM_CFLAGS = -I$(top_srcdir)/librabbitmq -I$(PLATFORM_DIR)
AM_LDFLAGS = $(top_builddir)/librabbitmq/librabbitmq.la
LDADD=$(LIBPOPT)
-noinst_HEADERS = common.h
+noinst_HEADERS = common.h $(PLATFORM_DIR)/process.h
-amqp_publish_SOURCES = publish.c common.c
-amqp_get_SOURCES = get.c common.c
-amqp_consume_SOURCES = consume.c common.c
+COMMON_SOURCES = common.c
+
+if WINDOWS
+COMMON_SOURCES += windows/compat.c
+endif
+
+amqp_publish_SOURCES = publish.c $(COMMON_SOURCES)
+amqp_get_SOURCES = get.c $(COMMON_SOURCES)
+amqp_consume_SOURCES = consume.c $(PLATFORM_DIR)/process.c $(COMMON_SOURCES)
if TOOLS_DOC
man_MANS = doc/amqp-publish.1 doc/amqp-consume.1 doc/amqp-get.1 doc/librabbitmq-tools.7
diff --git a/tools/common.c b/tools/common.c
index ec24085..39099c1 100644
--- a/tools/common.c
+++ b/tools/common.c
@@ -58,12 +58,12 @@
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
-#include <spawn.h>
-#include <sys/wait.h>
#include "common.h"
-extern char **environ;
+#ifdef WINDOWS
+#include "compat.h"
+#endif
void die(const char *fmt, ...)
{
@@ -169,16 +169,6 @@ void die_rpc(amqp_rpc_reply_t r, const char *fmt, ...)
exit(1);
}
-void set_cloexec(int fd)
-{
- int flags;
-
- flags = fcntl(fd, F_GETFD);
- if (flags == -1
- || fcntl(fd, F_SETFD, (long)(flags | FD_CLOEXEC)) == -1)
- die_errno(errno, "set_cloexec");
-}
-
static char *amqp_server = "localhost";
static char *amqp_vhost = "/";
static char *amqp_username = "guest";
@@ -224,8 +214,6 @@ amqp_connection_state_t make_connection(void)
s = amqp_open_socket(host, port ? port : 5672);
die_amqp_error(-s, "opening socket to %s", amqp_server);
- set_cloexec(s);
-
conn = amqp_new_connection();
amqp_set_sockfd(conn, s);
@@ -318,47 +306,6 @@ void copy_body(amqp_connection_state_t conn, int fd)
}
}
-void pipeline(const char * const *argv, struct pipeline *pl)
-{
- posix_spawn_file_actions_t file_acts;
-
- int pipefds[2];
- if (pipe(pipefds))
- die_errno(errno, "pipe");
-
- die_errno(posix_spawn_file_actions_init(&file_acts),
- "posix_spawn_file_actions_init");
- die_errno(posix_spawn_file_actions_adddup2(&file_acts, pipefds[0], 0),
- "posix_spawn_file_actions_adddup2");
- die_errno(posix_spawn_file_actions_addclose(&file_acts, pipefds[0]),
- "posix_spawn_file_actions_addclose");
- die_errno(posix_spawn_file_actions_addclose(&file_acts, pipefds[1]),
- "posix_spawn_file_actions_addclose");
-
- die_errno(posix_spawnp(&pl->pid, argv[0], &file_acts, NULL,
- (char * const *)argv, environ),
- "posix_spawnp: %s", argv[0]);
-
- die_errno(posix_spawn_file_actions_destroy(&file_acts),
- "posix_spawn_file_actions_destroy");
-
- if (close(pipefds[0]))
- die_errno(errno, "close");
-
- pl->infd = pipefds[1];
-}
-
-int finish_pipeline(struct pipeline *pl)
-{
- int status;
-
- if (close(pl->infd))
- die_errno(errno, "close");
- if (waitpid(pl->pid, &status, 0) < 0)
- die_errno(errno, "waitpid");
- return WIFEXITED(status) && WEXITSTATUS(status) == 0;
-}
-
poptContext process_options(int argc, const char **argv,
struct poptOption *options,
const char *help)
diff --git a/tools/common.h b/tools/common.h
index b3d8ab9..0caee98 100644
--- a/tools/common.h
+++ b/tools/common.h
@@ -77,14 +77,6 @@ extern void write_all(int fd, amqp_bytes_t data);
extern void copy_body(amqp_connection_state_t conn, int fd);
-struct pipeline {
- int pid;
- int infd;
-};
-
-extern void pipeline(const char * const *argv, struct pipeline *pl);
-extern int finish_pipeline(struct pipeline *pl);
-
#define INCLUDE_OPTIONS(options) \
{NULL, 0, POPT_ARG_INCLUDE_TABLE, options, 0, options ## _title, NULL}
diff --git a/tools/consume.c b/tools/consume.c
index 9999960..2117bba 100644
--- a/tools/consume.c
+++ b/tools/consume.c
@@ -54,6 +54,7 @@
#include <stdlib.h>
#include "common.h"
+#include "process.h"
/* Convert a amqp_bytes_t to an escaped string form for printing. We
use the same escaping conventions as rabbitmqctl. */
diff --git a/tools/unix/process.c b/tools/unix/process.c
new file mode 100644
index 0000000..8a02afb
--- /dev/null
+++ b/tools/unix/process.c
@@ -0,0 +1,100 @@
+/*
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * The Original Code is librabbitmq.
+ *
+ * The Initial Developers of the Original Code are LShift Ltd, Cohesive
+ * Financial Technologies LLC, and Rabbit Technologies Ltd. Portions
+ * created before 22-Nov-2008 00:00:00 GMT by LShift Ltd, Cohesive
+ * Financial Technologies LLC, or Rabbit Technologies Ltd are Copyright
+ * (C) 2007-2008 LShift Ltd, Cohesive Financial Technologies LLC, and
+ * Rabbit Technologies Ltd.
+ *
+ * Portions created by LShift Ltd are Copyright (C) 2007-2010 LShift
+ * Ltd. Portions created by Cohesive Financial Technologies LLC are
+ * Copyright (C) 2007-2010 Cohesive Financial Technologies
+ * LLC. Portions created by Rabbit Technologies Ltd are Copyright (C)
+ * 2007-2010 Rabbit Technologies Ltd.
+ *
+ * Portions created by Tony Garnock-Jones are Copyright (C) 2009-2010
+ * LShift Ltd and Tony Garnock-Jones.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): ______________________________________.
+ *
+ * Alternatively, the contents of this file may be used under the terms
+ * of the GNU General Public License Version 2 or later (the "GPL"), in
+ * which case the provisions of the GPL are applicable instead of those
+ * above. If you wish to allow use of your version of this file only
+ * under the terms of the GPL, and not to allow others to use your
+ * version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the
+ * notice and other provisions required by the GPL. If you do not
+ * delete the provisions above, a recipient may use your version of
+ * this file under the terms of any one of the MPL or the GPL.
+ *
+ * ***** END LICENSE BLOCK *****
+ */
+
+#include <unistd.h>
+#include <errno.h>
+#include <spawn.h>
+#include <sys/wait.h>
+
+#include "common.h"
+#include "process.h"
+
+extern char **environ;
+
+void pipeline(const char *const *argv, struct pipeline *pl)
+{
+ posix_spawn_file_actions_t file_acts;
+
+ int pipefds[2];
+ if (pipe(pipefds))
+ die_errno(errno, "pipe");
+
+ die_errno(posix_spawn_file_actions_init(&file_acts),
+ "posix_spawn_file_actions_init");
+ die_errno(posix_spawn_file_actions_adddup2(&file_acts, pipefds[0], 0),
+ "posix_spawn_file_actions_adddup2");
+ die_errno(posix_spawn_file_actions_addclose(&file_acts, pipefds[0]),
+ "posix_spawn_file_actions_addclose");
+ die_errno(posix_spawn_file_actions_addclose(&file_acts, pipefds[1]),
+ "posix_spawn_file_actions_addclose");
+
+ die_errno(posix_spawnp(&pl->pid, argv[0], &file_acts, NULL,
+ (char * const *)argv, environ),
+ "posix_spawnp: %s", argv[0]);
+
+ die_errno(posix_spawn_file_actions_destroy(&file_acts),
+ "posix_spawn_file_actions_destroy");
+
+ if (close(pipefds[0]))
+ die_errno(errno, "close");
+
+ pl->infd = pipefds[1];
+}
+
+int finish_pipeline(struct pipeline *pl)
+{
+ int status;
+
+ if (close(pl->infd))
+ die_errno(errno, "close");
+ if (waitpid(pl->pid, &status, 0) < 0)
+ die_errno(errno, "waitpid");
+ return WIFEXITED(status) && WEXITSTATUS(status) == 0;
+}
diff --git a/tools/unix/process.h b/tools/unix/process.h
new file mode 100644
index 0000000..ac2939d
--- /dev/null
+++ b/tools/unix/process.h
@@ -0,0 +1,57 @@
+/*
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * The Original Code is librabbitmq.
+ *
+ * The Initial Developers of the Original Code are LShift Ltd, Cohesive
+ * Financial Technologies LLC, and Rabbit Technologies Ltd. Portions
+ * created before 22-Nov-2008 00:00:00 GMT by LShift Ltd, Cohesive
+ * Financial Technologies LLC, or Rabbit Technologies Ltd are Copyright
+ * (C) 2007-2008 LShift Ltd, Cohesive Financial Technologies LLC, and
+ * Rabbit Technologies Ltd.
+ *
+ * Portions created by LShift Ltd are Copyright (C) 2007-2010 LShift
+ * Ltd. Portions created by Cohesive Financial Technologies LLC are
+ * Copyright (C) 2007-2010 Cohesive Financial Technologies
+ * LLC. Portions created by Rabbit Technologies Ltd are Copyright (C)
+ * 2007-2010 Rabbit Technologies Ltd.
+ *
+ * Portions created by Tony Garnock-Jones are Copyright (C) 2009-2010
+ * LShift Ltd and Tony Garnock-Jones.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): ______________________________________.
+ *
+ * Alternatively, the contents of this file may be used under the terms
+ * of the GNU General Public License Version 2 or later (the "GPL"), in
+ * which case the provisions of the GPL are applicable instead of those
+ * above. If you wish to allow use of your version of this file only
+ * under the terms of the GPL, and not to allow others to use your
+ * version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the
+ * notice and other provisions required by the GPL. If you do not
+ * delete the provisions above, a recipient may use your version of
+ * this file under the terms of any one of the MPL or the GPL.
+ *
+ * ***** END LICENSE BLOCK *****
+ */
+
+struct pipeline {
+ int pid;
+ int infd;
+};
+
+extern void pipeline(const char *const *argv, struct pipeline *pl);
+extern int finish_pipeline(struct pipeline *pl);
diff --git a/tools/windows/compat.c b/tools/windows/compat.c
new file mode 100644
index 0000000..f0508b2
--- /dev/null
+++ b/tools/windows/compat.c
@@ -0,0 +1,73 @@
+/*
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * The Original Code is librabbitmq.
+ *
+ * The Initial Developers of the Original Code are LShift Ltd, Cohesive
+ * Financial Technologies LLC, and Rabbit Technologies Ltd. Portions
+ * created before 22-Nov-2008 00:00:00 GMT by LShift Ltd, Cohesive
+ * Financial Technologies LLC, or Rabbit Technologies Ltd are Copyright
+ * (C) 2007-2008 LShift Ltd, Cohesive Financial Technologies LLC, and
+ * Rabbit Technologies Ltd.
+ *
+ * Portions created by LShift Ltd are Copyright (C) 2007-2010 LShift
+ * Ltd. Portions created by Cohesive Financial Technologies LLC are
+ * Copyright (C) 2007-2010 Cohesive Financial Technologies
+ * LLC. Portions created by Rabbit Technologies Ltd are Copyright (C)
+ * 2007-2010 Rabbit Technologies Ltd.
+ *
+ * Portions created by Tony Garnock-Jones are Copyright (C) 2009-2010
+ * LShift Ltd and Tony Garnock-Jones.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): ______________________________________.
+ *
+ * Alternatively, the contents of this file may be used under the terms
+ * of the GNU General Public License Version 2 or later (the "GPL"), in
+ * which case the provisions of the GPL are applicable instead of those
+ * above. If you wish to allow use of your version of this file only
+ * under the terms of the GPL, and not to allow others to use your
+ * version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the
+ * notice and other provisions required by the GPL. If you do not
+ * delete the provisions above, a recipient may use your version of
+ * this file under the terms of any one of the MPL or the GPL.
+ *
+ * ***** END LICENSE BLOCK *****
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+
+#include "compat.h"
+
+int asprintf(char **strp, const char *fmt, ...)
+{
+ va_list ap;
+ int len;
+
+ va_start(ap, fmt);
+ len = _vscprintf(fmt, ap);
+ *strp = malloc(len+1);
+ if (!*strp)
+ return -1;
+
+ len = vsprintf(*strp, fmt, ap);
+ *strp[len] = 0;
+
+ va_end(ap);
+ return len;
+}
diff --git a/tools/windows/compat.h b/tools/windows/compat.h
new file mode 100644
index 0000000..8211b37
--- /dev/null
+++ b/tools/windows/compat.h
@@ -0,0 +1,51 @@
+/*
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * The Original Code is librabbitmq.
+ *
+ * The Initial Developers of the Original Code are LShift Ltd, Cohesive
+ * Financial Technologies LLC, and Rabbit Technologies Ltd. Portions
+ * created before 22-Nov-2008 00:00:00 GMT by LShift Ltd, Cohesive
+ * Financial Technologies LLC, or Rabbit Technologies Ltd are Copyright
+ * (C) 2007-2008 LShift Ltd, Cohesive Financial Technologies LLC, and
+ * Rabbit Technologies Ltd.
+ *
+ * Portions created by LShift Ltd are Copyright (C) 2007-2010 LShift
+ * Ltd. Portions created by Cohesive Financial Technologies LLC are
+ * Copyright (C) 2007-2010 Cohesive Financial Technologies
+ * LLC. Portions created by Rabbit Technologies Ltd are Copyright (C)
+ * 2007-2010 Rabbit Technologies Ltd.
+ *
+ * Portions created by Tony Garnock-Jones are Copyright (C) 2009-2010
+ * LShift Ltd and Tony Garnock-Jones.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): ______________________________________.
+ *
+ * Alternatively, the contents of this file may be used under the terms
+ * of the GNU General Public License Version 2 or later (the "GPL"), in
+ * which case the provisions of the GPL are applicable instead of those
+ * above. If you wish to allow use of your version of this file only
+ * under the terms of the GPL, and not to allow others to use your
+ * version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the
+ * notice and other provisions required by the GPL. If you do not
+ * delete the provisions above, a recipient may use your version of
+ * this file under the terms of any one of the MPL or the GPL.
+ *
+ * ***** END LICENSE BLOCK *****
+ */
+
+extern int asprintf(char **strp, const char *fmt, ...);
diff --git a/tools/windows/process.c b/tools/windows/process.c
new file mode 100644
index 0000000..9a0b893
--- /dev/null
+++ b/tools/windows/process.c
@@ -0,0 +1,204 @@
+/*
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * The Original Code is librabbitmq.
+ *
+ * The Initial Developers of the Original Code are LShift Ltd, Cohesive
+ * Financial Technologies LLC, and Rabbit Technologies Ltd. Portions
+ * created before 22-Nov-2008 00:00:00 GMT by LShift Ltd, Cohesive
+ * Financial Technologies LLC, or Rabbit Technologies Ltd are Copyright
+ * (C) 2007-2008 LShift Ltd, Cohesive Financial Technologies LLC, and
+ * Rabbit Technologies Ltd.
+ *
+ * Portions created by LShift Ltd are Copyright (C) 2007-2010 LShift
+ * Ltd. Portions created by Cohesive Financial Technologies LLC are
+ * Copyright (C) 2007-2010 Cohesive Financial Technologies
+ * LLC. Portions created by Rabbit Technologies Ltd are Copyright (C)
+ * 2007-2010 Rabbit Technologies Ltd.
+ *
+ * Portions created by Tony Garnock-Jones are Copyright (C) 2009-2010
+ * LShift Ltd and Tony Garnock-Jones.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): ______________________________________.
+ *
+ * Alternatively, the contents of this file may be used under the terms
+ * of the GNU General Public License Version 2 or later (the "GPL"), in
+ * which case the provisions of the GPL are applicable instead of those
+ * above. If you wish to allow use of your version of this file only
+ * under the terms of the GPL, and not to allow others to use your
+ * version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the
+ * notice and other provisions required by the GPL. If you do not
+ * delete the provisions above, a recipient may use your version of
+ * this file under the terms of any one of the MPL or the GPL.
+ *
+ * ***** END LICENSE BLOCK *****
+ */
+
+#include <stdio.h>
+#include <io.h>
+#include <windows.h>
+
+#include "common.h"
+#include "process.h"
+
+void die_windows_error(const char *fmt, ...)
+{
+ char *msg;
+
+ va_list ap;
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+
+ if (!FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
+ | FORMAT_MESSAGE_ALLOCATE_BUFFER,
+ NULL, GetLastError(),
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPSTR)&msg, 0, NULL))
+ msg = "(failed to retrieving Windows error message)";
+
+ fprintf(stderr, ": %s\n", msg);
+ exit(1);
+}
+
+static char *make_command_line(const char *const *argv)
+{
+ int i;
+ size_t len = 1; /* initial quotes */
+ char *buf;
+ char *dest;
+
+ /* calculate the length of the required buffer, making worst
+ case assumptions for simplicity */
+ for (i = 0;;) {
+ len += strlen(argv[i]) * 2;
+
+ if (!argv[++i])
+ break;
+
+ len += 3; /* quotes, space, quotes */
+ }
+
+ len += 2; /* final quotes and the terminating zero */
+
+ dest = buf = malloc(len);
+ if (!buf)
+ die("allocating memory for subprocess command line");
+
+ *dest++ = '\"';
+
+ for (i = 0;;) {
+ const char *src = argv[i];
+ for (;;) {
+ switch (*src) {
+ case 0:
+ goto done;
+
+ case '\"':
+ case '\\':
+ *dest++ = '\\';
+ /* fall through */
+
+ default:
+ *dest++ = *src++;
+ break;
+ }
+ }
+ done:
+
+ if (!argv[++i])
+ break;
+
+ *dest++ = '\"';
+ *dest++ = ' ';
+ *dest++ = '\"';
+ }
+
+ *dest++ = '\"';
+ *dest++ = 0;
+ return buf;
+}
+
+void pipeline(const char *const *argv, struct pipeline *pl)
+{
+ HANDLE in_read_handle, in_write_handle;
+ SECURITY_ATTRIBUTES sec_attr;
+ PROCESS_INFORMATION proc_info;
+ STARTUPINFO start_info;
+ char *cmdline = make_command_line(argv);
+
+ sec_attr.nLength = sizeof sec_attr;
+ sec_attr.bInheritHandle = TRUE;
+ sec_attr.lpSecurityDescriptor = NULL;
+
+ if (!CreatePipe(&in_read_handle, &in_write_handle, &sec_attr, 0))
+ die_windows_error("CreatePipe");
+
+ if (!SetHandleInformation(in_write_handle, HANDLE_FLAG_INHERIT, 0))
+ die_windows_error("SetHandleInformation");
+
+ /* when in Rome... */
+ ZeroMemory(&proc_info, sizeof proc_info);
+ ZeroMemory(&start_info, sizeof start_info);
+
+ start_info.cb = sizeof start_info;
+ start_info.dwFlags |= STARTF_USESTDHANDLES;
+
+ if ((start_info.hStdError = GetStdHandle(STD_ERROR_HANDLE))
+ == INVALID_HANDLE_VALUE
+ || (start_info.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE))
+ == INVALID_HANDLE_VALUE)
+ die_windows_error("GetStdHandle");
+
+ start_info.hStdInput = in_read_handle;
+
+ if (!CreateProcess(NULL, cmdline, NULL, NULL, TRUE, 0,
+ NULL, NULL, &start_info, &proc_info))
+ die_windows_error("CreateProcess");
+
+ if (!CloseHandle(proc_info.hThread))
+ die_windows_error("CloseHandle for thread");
+ if (!CloseHandle(in_read_handle))
+ die_windows_error("CloseHandle");
+
+ pl->proc_handle = proc_info.hProcess;
+ pl->infd = _open_osfhandle((intptr_t)in_write_handle, 0);
+}
+
+int finish_pipeline(struct pipeline *pl)
+{
+ DWORD code;
+
+ if (close(pl->infd))
+ die_errno(errno, "close");
+
+ for (;;) {
+ if (!GetExitCodeProcess(pl->proc_handle, &code))
+ die_windows_error("GetExitCodeProcess");
+ if (code != STILL_ACTIVE)
+ break;
+
+ if (WaitForSingleObject(pl->proc_handle, INFINITE)
+ == WAIT_FAILED)
+ die_windows_error("WaitForSingleObject");
+ }
+
+ if (!CloseHandle(pl->proc_handle))
+ die_windows_error("CloseHandle for process");
+
+ return code;
+}
diff --git a/tools/windows/process.h b/tools/windows/process.h
new file mode 100644
index 0000000..df276a7
--- /dev/null
+++ b/tools/windows/process.h
@@ -0,0 +1,59 @@
+/*
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * The Original Code is librabbitmq.
+ *
+ * The Initial Developers of the Original Code are LShift Ltd, Cohesive
+ * Financial Technologies LLC, and Rabbit Technologies Ltd. Portions
+ * created before 22-Nov-2008 00:00:00 GMT by LShift Ltd, Cohesive
+ * Financial Technologies LLC, or Rabbit Technologies Ltd are Copyright
+ * (C) 2007-2008 LShift Ltd, Cohesive Financial Technologies LLC, and
+ * Rabbit Technologies Ltd.
+ *
+ * Portions created by LShift Ltd are Copyright (C) 2007-2010 LShift
+ * Ltd. Portions created by Cohesive Financial Technologies LLC are
+ * Copyright (C) 2007-2010 Cohesive Financial Technologies
+ * LLC. Portions created by Rabbit Technologies Ltd are Copyright (C)
+ * 2007-2010 Rabbit Technologies Ltd.
+ *
+ * Portions created by Tony Garnock-Jones are Copyright (C) 2009-2010
+ * LShift Ltd and Tony Garnock-Jones.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): ______________________________________.
+ *
+ * Alternatively, the contents of this file may be used under the terms
+ * of the GNU General Public License Version 2 or later (the "GPL"), in
+ * which case the provisions of the GPL are applicable instead of those
+ * above. If you wish to allow use of your version of this file only
+ * under the terms of the GPL, and not to allow others to use your
+ * version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the
+ * notice and other provisions required by the GPL. If you do not
+ * delete the provisions above, a recipient may use your version of
+ * this file under the terms of any one of the MPL or the GPL.
+ *
+ * ***** END LICENSE BLOCK *****
+ */
+
+#include <windef.h>
+
+struct pipeline {
+ HANDLE proc_handle;
+ int infd;
+};
+
+extern void pipeline(const char *const *argv, struct pipeline *pl);
+extern int finish_pipeline(struct pipeline *pl);