>From 40f235a8897feb556815d6bce90f16448a6ec17d Mon Sep 17 00:00:00 2001
From: Angus Salkeld <asalkeld@redhat.com>
Date: Thu, 15 Apr 2010 23:25:29 +1000
Subject: [PATCH] libtool and code re-structure

Signed-off-by: Angus Salkeld <asalkeld@redhat.com>
---
 .gitignore                        |   13 +-
 Makefile.am                       |    9 +-
 autogen.sh                        |    5 +-
 configure.ac                      |   96 +--
 lib/Makefile.am                   |   62 ++-
 lib/PLUGIN_README                 |  113 +++
 lib/hash.c                        |  286 ++++++
 lib/hash/Makefile.am              |   95 --
 lib/hash/hash.c                   |  286 ------
 lib/hash/libqbhash.versions       |   15 -
 lib/ipc/Makefile.am               |   96 --
 lib/ipc/ipc_int.h                 |  159 ----
 lib/ipc/ipcc.c                    | 1203 -------------------------
 lib/ipc/ipcs.c                    | 1795 -------------------------------------
 lib/ipc/libqbipcc.versions        |   16 -
 lib/ipc/libqbipcs.versions        |   16 -
 lib/ipc_int.h                     |  159 ++++
 lib/ipcc.c                        | 1203 +++++++++++++++++++++++++
 lib/ipcs.c                        | 1795 +++++++++++++++++++++++++++++++++++++
 lib/logsys.c                      | 1698 +++++++++++++++++++++++++++++++++++
 lib/logsys/Makefile.am            |   95 --
 lib/logsys/libqblogsys.versions   |   25 -
 lib/logsys/logsys.c               | 1698 -----------------------------------
 lib/plugin/Makefile.am            |   78 --
 lib/plugin/README                 |  113 ---
 lib/plugin/libtest_a.c            |  166 ----
 lib/plugin/libtest_b.c            |  174 ----
 lib/plugin/plugin_loader.c        |  566 ------------
 lib/plugin/test.c                 |  129 ---
 lib/plugin/uic.c                  |  157 ----
 lib/plugin/uis.c                  |  193 ----
 lib/plugin_loader.c               |  567 ++++++++++++
 lib/poll.c                        |  441 +++++++++
 lib/poll/Makefile.am              |   95 --
 lib/poll/libqbpoll.versions       |   13 -
 lib/poll/poll.c                   |  441 ---------
 lib/timer.c                       |  271 ++++++
 lib/timer/Makefile.am             |   95 --
 lib/timer/libqbtimer.versions     |   13 -
 lib/timer/timer.c                 |  271 ------
 lib/tsafe.c                       | 1082 ++++++++++++++++++++++
 lib/tsafe/Makefile.am             |   95 --
 lib/tsafe/libqbtsafe.versions     |    7 -
 lib/tsafe/tsafe.c                 | 1082 ----------------------
 lib/wthread.c                     |  215 +++++
 lib/wthread/Makefile.am           |   95 --
 lib/wthread/libqbwthread.versions |    9 -
 lib/wthread/wthread.c             |  215 -----
 libqb.spec.in                     |  107 +++
 quarterback.spec.in               |   99 --
 tests/.gitignore                  |    1 +
 tests/Makefile.am                 |   23 +-
 tests/check_plugin.c              |  155 ++++
 tests/libtest_a.c                 |  166 ++++
 tests/libtest_b.c                 |  174 ++++
 55 files changed, 8572 insertions(+), 9674 deletions(-)
 create mode 100644 lib/PLUGIN_README
 create mode 100644 lib/hash.c
 delete mode 100644 lib/hash/Makefile.am
 delete mode 100644 lib/hash/hash.c
 delete mode 100644 lib/hash/libqbhash.versions
 delete mode 100644 lib/ipc/Makefile.am
 delete mode 100644 lib/ipc/ipc_int.h
 delete mode 100644 lib/ipc/ipcc.c
 delete mode 100644 lib/ipc/ipcs.c
 delete mode 100644 lib/ipc/libqbipcc.versions
 delete mode 100644 lib/ipc/libqbipcs.versions
 create mode 100644 lib/ipc_int.h
 create mode 100644 lib/ipcc.c
 create mode 100644 lib/ipcs.c
 create mode 100644 lib/logsys.c
 delete mode 100644 lib/logsys/Makefile.am
 delete mode 100644 lib/logsys/libqblogsys.versions
 delete mode 100644 lib/logsys/logsys.c
 delete mode 100644 lib/plugin/Makefile.am
 delete mode 100644 lib/plugin/README
 delete mode 100644 lib/plugin/libtest_a.c
 delete mode 100644 lib/plugin/libtest_b.c
 delete mode 100644 lib/plugin/plugin_loader.c
 delete mode 100644 lib/plugin/test.c
 delete mode 100755 lib/plugin/uic.c
 delete mode 100755 lib/plugin/uis.c
 create mode 100644 lib/plugin_loader.c
 create mode 100644 lib/poll.c
 delete mode 100644 lib/poll/Makefile.am
 delete mode 100644 lib/poll/libqbpoll.versions
 delete mode 100644 lib/poll/poll.c
 create mode 100644 lib/timer.c
 delete mode 100644 lib/timer/Makefile.am
 delete mode 100644 lib/timer/libqbtimer.versions
 delete mode 100644 lib/timer/timer.c
 create mode 100644 lib/tsafe.c
 delete mode 100644 lib/tsafe/Makefile.am
 delete mode 100644 lib/tsafe/libqbtsafe.versions
 delete mode 100644 lib/tsafe/tsafe.c
 create mode 100644 lib/wthread.c
 delete mode 100644 lib/wthread/Makefile.am
 delete mode 100644 lib/wthread/libqbwthread.versions
 delete mode 100644 lib/wthread/wthread.c
 create mode 100644 libqb.spec.in
 delete mode 100644 quarterback.spec.in
 create mode 100644 tests/check_plugin.c
 create mode 100644 tests/libtest_a.c
 create mode 100644 tests/libtest_b.c

diff --git a/.gitignore b/.gitignore
index af27046..2c1263a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,8 @@
 *.[oa]
 *.deps
 *.so
+*.la
+*.lo
 *.so.*
 *.3
 *.rpm
@@ -8,6 +10,7 @@ Makefile
 Makefile.in
 include/config.h
 include/config.h.in
+include/stamp-h1
 aclocal.m4
 autom4te.cache/
 config.guess
@@ -16,10 +19,10 @@ config.status
 config.sub
 configure
 depcomp
-include/stamp-h1
 install-sh
 missing
-lib/plugin/test
-lib/plugin/test_static
-lib/plugin/uic
-quarterback-?.?.?
+.libs
+m4
+libtool
+ltmain.sh
+libqb-*
diff --git a/Makefile.am b/Makefile.am
index 2e825e1..2d9c40b 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -40,7 +40,11 @@ AUTOMAKE_OPTIONS	= foreign
 
 MAINTAINERCLEANFILES	= Makefile.in aclocal.m4 configure depcomp \
 			  config.guess config.sub missing install-sh \
-			  autoheader automake autoconf
+			  autoheader automake autoconf libtool libtoolize \
+			  ltmain.sh compile
+
+
+ACLOCAL_AMFLAGS		= -I m4
 
 dist_doc_DATA		= LICENSE INSTALL README TODO 
 
@@ -62,6 +66,9 @@ doxygen:
 dist-clean-local:
 	rm -f autoconf automake autoheader
 
+maintainer-clean-local:
+	rm -rf m4
+
 clean-generic:
 	rm -rf doc/api $(SPEC) $(TARFILE) 
 
diff --git a/autogen.sh b/autogen.sh
index 83770a1..3c5e1d9 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -1,5 +1,4 @@
 #!/bin/sh
 # Run this to generate all the initial makefiles, etc.
-
-echo Building configuration system...
-autoreconf -i && echo Now run ./configure and make
+mkdir -p m4
+autoreconf -i -v && echo Now run ./configure and make
diff --git a/configure.ac b/configure.ac
index 83066e0..7196e8f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,32 +1,30 @@
-#                                               -*- Autoconf -*-
+
 # Process this file with autoconf to produce a configure script.
 
-# bootstrap / init
 AC_PREREQ([2.61])
-
-AC_INIT([quarterback], [0.1.0], [quarterback-devel@fedorahosted.org])
+AC_INIT([libqb], [0.1.0], [quarterback-devel@fedorahosted.org])
 AM_INIT_AUTOMAKE([-Wno-portability])
+LT_PREREQ([2.2.6])
+LT_INIT
 
-AC_CONFIG_SRCDIR([lib/tsafe/tsafe.c])
+AC_CONFIG_MACRO_DIR([m4])
+AC_CONFIG_SRCDIR([lib/tsafe.c])
 AC_CONFIG_HEADER([include/config.h])
 
 AC_CANONICAL_HOST
+AC_PROG_LIBTOOL
 
 AC_LANG([C])
 
 dnl Fix default variables - "prefix" variable if not specified
 if test "$prefix" = "NONE"; then
 	prefix="/usr"
-
-	dnl Fix "localstatedir" variable if not specified
 	if test "$localstatedir" = "\${prefix}/var"; then
 		localstatedir="/var"
 	fi
-	dnl Fix "sysconfdir" variable if not specified
 	if test "$sysconfdir" = "\${prefix}/etc"; then
 		sysconfdir="/etc"
 	fi
-	dnl Fix "libdir" variable if not specified
 	if test "$libdir" = "\${exec_prefix}/lib"; then
 		if test -e /usr/lib64; then
 			libdir="/usr/lib64"
@@ -50,15 +48,38 @@ if ! ${MAKE-make} --version /cannot/make/this >/dev/null 2>&1; then
 	AC_MSG_ERROR([you don't seem to have GNU make; it is required])
 fi
 
-sinclude(coroysync-default.m4)
-
 AC_PROG_CC
-AC_PROG_INSTALL
+AM_PROG_CC_C_O
 AC_PROG_LN_S
+AC_PROG_INSTALL
 AC_PROG_MAKE_SET
-AC_PROG_RANLIB
 AC_CHECK_PROGS([PKGCONFIG], [pkg-config])
 
+## local helper functions
+
+# this function checks if CC support options passed as
+# args. Global CFLAGS are ignored during this test.
+cc_supports_flag() {
+	local CFLAGS="$@"
+	AC_MSG_CHECKING([whether $CC supports "$@"])
+	AC_COMPILE_IFELSE([int main(){return 0;}] ,
+			  [RC=0; AC_MSG_RESULT([yes])],
+			  [RC=1; AC_MSG_RESULT([no])])
+	return $RC
+}
+
+## cleanup
+AC_MSG_NOTICE(Sanitizing prefix: ${prefix})
+case $prefix in
+  NONE) prefix=/usr/local;;
+esac
+
+AC_MSG_NOTICE(Sanitizing exec_prefix: ${exec_prefix})
+case $exec_prefix in
+  NONE)   exec_prefix=$prefix;;
+  prefix) exec_prefix=$prefix;;
+esac
+
 # Checks for libraries.
 AC_CHECK_LIB([dl], [dlopen])
 AC_CHECK_LIB([pthread], [pthread_create])
@@ -112,48 +133,7 @@ AC_CHECK_FUNCS([alarm alphasort atexit bzero dup2 endgrent endpwent fcntl \
 		pthread_spin_unlock pututxline lgammal setkey \
 		crypt encrypt getdate strsignal])
 
-AC_CONFIG_FILES([Makefile
-		 include/Makefile
-		 include/qb/Makefile
-		 lib/Makefile
-		 lib/tsafe/Makefile
-		 lib/poll/Makefile
-		 lib/timer/Makefile
-		 lib/plugin/Makefile
-		 lib/ipc/Makefile
-		 lib/wthread/Makefile
-		 lib/logsys/Makefile
-		 lib/hash/Makefile
-		 man/Makefile
-		 tests/Makefile])
-
-### Local business
-
-# ===============================================
-# Helpers
-# ===============================================
-
-## helper for CC stuff
-cc_supports_flag() {
-	local CFLAGS="$@"
-	AC_MSG_CHECKING([whether $CC supports "$@"])
-	AC_COMPILE_IFELSE([int main(){return 0;}] ,
-			  [RC=0; AC_MSG_RESULT([yes])],
-			  [RC=1; AC_MSG_RESULT([no])])
-	return $RC
-}
-
-## cleanup
-AC_MSG_NOTICE(Sanitizing prefix: ${prefix})
-case $prefix in
-  NONE) prefix=/usr/local;;
-esac
 
-AC_MSG_NOTICE(Sanitizing exec_prefix: ${exec_prefix})
-case $exec_prefix in
-  NONE)   exec_prefix=$prefix;;
-  prefix) exec_prefix=$prefix;;
-esac
 
 ## local defines
 PACKAGE_FEATURES=""
@@ -372,6 +352,14 @@ AC_DEFINE_UNQUOTED([LOCALSTATEDIR], "$(eval echo ${localstatedir})", [localstate
 
 AC_DEFINE_UNQUOTED([PACKAGE_FEATURES], "${PACKAGE_FEATURES}", [quarterback built-in features])
 
+
+AC_CONFIG_FILES([Makefile
+		 include/Makefile
+		 include/qb/Makefile
+		 lib/Makefile
+		 man/Makefile
+		 tests/Makefile])
+
 AC_OUTPUT
 
 AC_MSG_RESULT([])
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 39c8f05..491e18b 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -1,6 +1,7 @@
+#
 # Copyright (c) 2010 Red Hat, Inc.
 #
-# Authors: Angus Salkeld <asalkeld@redhat.com>
+# Author: Angus Salkeld <asaslkeld@redhat.com>
 #
 # This software licensed under BSD license, the text of which follows:
 #
@@ -28,7 +29,62 @@
 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 # THE POSSIBILITY OF SUCH DAMAGE.
 
-MAINTAINERCLEANFILES    = Makefile.in
 
-SUBDIRS			= tsafe poll timer plugin ipc wthread logsys hash
+MAINTAINERCLEANFILES	= Makefile.in
+
+noinst_HEADERS          = ipc_int.h
+
+#pkgconfigdir		= $(libdir)/pkgconfig
+#pkgconfig_DATA		= libqbhash.pc
+#libqbhash_la_LIBADD	= 
+
+#
+# Here are a set of rules to help you update your library version information:
+# Start with version information of ‘0:0:0’ for each libtool library.
+# Update the version information only immediately before a public release of your software. 
+# More frequent updates are unnecessary, and only guarantee that the current interface number gets larger faster.
+# If the library source code has changed at all since the last update, then increment revision (‘c:r:a’ becomes ‘c:r+1:a’).
+# If any interfaces have been added, removed, or changed since the last update, increment current, and set revision to 0.
+# If any interfaces have been added since the last public release, then increment age.
+# If any interfaces have been removed since the last public release, then set age to 0.
+#
+
+lib_LTLIBRARIES		= libqbhash.la libqbpoll.la libqbtimer.la libqblogsys.la \
+			  libqbtsafe.la  libqbwthread.la libqbipcc.la libqbipcs.la
+
+lib_LIBRARIES		= libqbplugin.a
+
+libqbplugin_a_SOURCES	= plugin_loader.c
+
+libqbhash_la_CPPFLAGS	= -I$(top_builddir)/include -I$(top_srcdir)/include
+libqbhash_la_LDFLAGS	= -version-info 0:0:0
+libqbhash_la_SOURCES	= hash.c
+
+libqbpoll_la_CPPFLAGS	= -I$(top_builddir)/include -I$(top_srcdir)/include
+libqbpoll_la_LDFLAGS	= -version-info 0:0:0
+libqbpoll_la_SOURCES	= poll.c
+
+libqbtimer_la_CPPFLAGS	= -I$(top_builddir)/include -I$(top_srcdir)/include
+libqbtimer_la_LDFLAGS	= -version-info 0:0:0
+libqbtimer_la_SOURCES	= timer.c
+
+libqblogsys_la_CPPFLAGS	= -I$(top_builddir)/include -I$(top_srcdir)/include
+libqblogsys_la_LDFLAGS	= -version-info 0:0:0
+libqblogsys_la_SOURCES	= logsys.c
+
+libqbtsafe_la_CPPFLAGS	= -I$(top_builddir)/include -I$(top_srcdir)/include
+libqbtsafe_la_LDFLAGS	= -version-info 0:0:0
+libqbtsafe_la_SOURCES	= tsafe.c
+
+libqbwthread_la_CPPFLAGS = -I$(top_builddir)/include -I$(top_srcdir)/include
+libqbwthread_la_LDFLAGS	= -version-info 0:0:0
+libqbwthread_la_SOURCES	= wthread.c
+
+libqbipcc_la_CPPFLAGS = -I$(top_builddir)/include -I$(top_srcdir)/include
+libqbipcc_la_LDFLAGS	= -version-info 0:0:0
+libqbipcc_la_SOURCES	= ipcc.c
+
+libqbipcs_la_CPPFLAGS = -I$(top_builddir)/include -I$(top_srcdir)/include
+libqbipcs_la_LDFLAGS	= -version-info 0:0:0
+libqbipcs_la_SOURCES	= ipcs.c
 
diff --git a/lib/PLUGIN_README b/lib/PLUGIN_README
new file mode 100644
index 0000000..ad782d0
--- /dev/null
+++ b/lib/PLUGIN_README
@@ -0,0 +1,113 @@
+Live Component Replacement
+--------------------------
+All software is composed of components, which contain multiple software classes.
+Components generally depend upon other components and sometimes classes from
+other components.
+
+Some components of corosync are the evt service, the ckpt service, the clm
+service, the totem protocol, and others.  If a defect is found in any of
+these components, the entire ais executive must be stopped, replaced, and
+restarted.
+
+The lcr code formalizes the concept of components into dynamic libraries.  A
+component may have multiple classes.  Each class (the lcr code uses the word
+interface) may have multiple functions within the class.  Each interface may
+depend upon other interfaces, and those interfaces are then loaded prior to the
+requested interface being referenced.
+
+Note that with recent changes, the lcr interface factory can be used when
+statically linking without additional steps.  The interface for notifying
+lcr of a component has changed.
+
+A list of shared objects is scanned each time an interface is requested to
+load via the following interface:
+
+int lcr_ifact_reference (
+        void **handle,
+        char *iface_name,
+        int version,
+        void **interface,
+        void *context);
+
+The iface_name is the name of the interface, the version is the version,
+the void **interface is the list of functions returned once the interface
+has been dynamically loaded and referenced, and context is passed to the
+constructor and destructor.
+
+The interface is loaded, the interface constructor is called, and the list
+of interfaces is returned back to the caller.
+
+First the list of interfaces is described in an iface_list data structure:
+struct iface_list iface_list = {
+        .iface1_func1           = iface1_func1,
+        .iface1_func2           = iface1_func2,
+        .iface1_func3           = iface1_func3,
+};
+iface1_func1 is a simple function call.
+
+Then the lcr_iface data structure is defined for the c file:
+
+struct lcr_iface iface1_ver0 = {
+        .name                   = "iface1",
+        .version                = 0,
+        .versions_replace       = 0,
+        .versions_replace_count = 0,
+        .dependencies           = 0,
+        .dependency_count       = 0,
+        .constructor            = iface1_constructor,
+        .destructor             = iface1_destructor,
+        .interfaces             = (void **)&iface_list,
+};
+
+The name and version fields provide naming and versioning.  The constructor
+and destructor functions execute at reference and release times.  Finally
+the .interfaces type describes the list of functions used for the interface.
+
+Next, an lcr_comp must be described:
+
+struct lcr_comp test_comp = {
+        .iface_count            = 2,
+        .ifaces                 = lcr_ifaces
+};
+
+the iface count describes the number of interfaces within the component,
+and lcr_ifaces is an array of pointers to lcr_iface data types.
+
+The lcr_comp_get method has been replaced.  The final step is to setup a
+constructor that is started when the task is started.  This ctor will
+register the component with the lcr framework.
+
+static void register_this_component (void) {
+        lcr_component_register (&test_comp);
+}
+
+static void (*const __init_this_component[1]) (void) __attribute__ ((section(".ctors"))) = { register_this_component };
+
+
+Now the component can be referenced and used in another application.
+int main ()
+{
+
+.....
+
+	lcr_ifact_reference (
+		&ifact_handle_ver0,
+		"iface1",
+		0, /* version 0 */
+		(void **)&iface_ver0,
+		(void *)0xdeadbeef);
+
+	iface_ver0->func1();
+	iface_ver0->func2();
+	iface_ver0->func3();
+}
+
+
+See libtest_a and libtest_b for two sample components.  The test program
+demonstrates usage.  The test_static demonstrates operation when statically
+linked.  Note the dynamic inteface factory is still available for use when
+statically linking components.
+
+On startup, a thread is created which listens for requests from the "uic"
+application.  These requests are then processed by the lcr service which
+would execute a live replacement.
diff --git a/lib/hash.c b/lib/hash.c
new file mode 100644
index 0000000..93d27bc
--- /dev/null
+++ b/lib/hash.c
@@ -0,0 +1,286 @@
+/*
+ * Copyright (c) 2010 Red Hat, Inc.
+ *
+ * Author: Steven Dake (sdake@redhat.com)
+ *
+ * This software licensed under BSD license, the text of which follows:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - 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.
+ * - Neither the name of Red Hat 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
+ */
+#include <stdint.h>
+#include <qb/qbhdb.h>
+
+#include <config.h>
+
+#include "os_base.h"
+
+#include <qb/qbhdb.h>
+#include <qb/qblist.h>
+#include <qb/qbhash.h>
+
+#define FNV_32_PRIME ((uint32_t)0x01000193)
+
+DECLARE_HDB_DATABASE(qb_hash_handle_db,NULL);
+
+struct hash_node {
+	struct qb_list_head list;
+	void *value;
+	uint32_t value_len;
+	char key[0];
+};
+	
+struct hash_bucket {
+	pthread_mutex_t mutex;
+	struct qb_list_head list_head;
+};
+
+struct hash_table {
+	uint64_t memory_data;
+	uint64_t memory_overhead;
+	uint32_t order;
+	uint32_t hash_buckets_len;
+	struct hash_bucket hash_buckets[0];
+};
+
+static uint32_t hash_fnv (
+	const void *value,
+	uint32_t valuelen,
+	uint32_t order)
+{
+	uint8_t *cd = (uint8_t *)value;
+	uint8_t *ed = (uint8_t *)value + valuelen;
+	uint32_t hash_result = 0x811c9dc5;
+	int res;
+
+	while (cd < ed) {
+		hash_result ^= *cd;
+		hash_result *= FNV_32_PRIME;
+		cd++;
+	}
+	res = ((hash_result >> order) ^ hash_result) & ((1 << order) - 1);
+	return (res);
+}
+
+int32_t qb_hash_initialize (
+	qb_hdb_handle_t *handle,
+	uint32_t order,
+	uint32_t context_size)
+{
+	struct hash_table *hash_table;
+	int i;
+	uint64_t size;
+	int32_t res;
+
+	size = sizeof (struct hash_table) +
+		(sizeof (struct hash_bucket) * (1 << order));
+
+	res = qb_hdb_handle_create (&qb_hash_handle_db, size, handle);
+	if (res != 0) {
+		return (res);
+	}
+	res = qb_hdb_handle_get (&qb_hash_handle_db, *handle, (void *)&hash_table);
+	if (res != 0) {
+		goto hash_destroy;
+	}
+
+	hash_table->memory_data = 0;
+	hash_table->memory_overhead = size;
+
+	hash_table->order = order;
+	hash_table->hash_buckets_len = 1 << order;
+	for (i = 0; i < hash_table->hash_buckets_len; i++) {
+		qb_list_init (&hash_table->hash_buckets[i].list_head);
+		pthread_mutex_init (&hash_table->hash_buckets[i].mutex, NULL);
+	}
+
+	qb_hdb_handle_put (&qb_hash_handle_db, *handle);
+	return (0);
+
+hash_destroy:
+	res = qb_hdb_handle_destroy (&qb_hash_handle_db,  *handle);
+	return (-1);
+}
+
+int32_t qb_hash_key_set (
+	qb_hdb_handle_t handle,
+	const char *key,
+	const void *value,
+	uint32_t value_len)
+{
+	struct hash_table *hash_table;
+	uint32_t hash_entry;
+	struct qb_list_head *list;
+	int found = 0;
+	struct hash_node *hash_node;
+	int res;
+
+	res = qb_hdb_handle_get (&qb_hash_handle_db, handle, (void *)&hash_table);
+	if (res != 0) { 
+		return (res);
+	}
+	hash_entry = hash_fnv (key, strlen (key), hash_table->order);
+	pthread_mutex_lock (&hash_table->hash_buckets[hash_entry].mutex);
+	for (list = hash_table->hash_buckets[hash_entry].list_head.next;
+		list != &hash_table->hash_buckets[hash_entry].list_head;
+		list = list->next) {
+
+		hash_node = qb_list_entry (list, struct hash_node, list);
+
+		if (strcmp (hash_node->key, key) == 0) {
+			hash_table->memory_data -= value_len;
+			free (hash_node->value);
+			found = 1;
+			break;
+		}
+	}
+	if (found == 0) {
+		hash_node = malloc (sizeof (struct hash_node) + strlen (key) + 1);
+		if (hash_node == 0) {
+			goto error_exit;
+		}
+
+		hash_table->memory_overhead += sizeof (struct hash_node);
+		hash_table->memory_data += strlen (key) + 1;
+
+		memcpy (&hash_node->key, key, strlen (key) + 1);
+		qb_list_add_tail (&hash_node->list,
+			&hash_table->hash_buckets[hash_entry].list_head);
+	}
+	if (value_len) {
+		hash_node->value = malloc (value_len);
+		hash_table->memory_data += value_len;
+	} else {
+		hash_node->value = NULL;
+	}
+	hash_node->value_len = value_len;
+	if (value) {
+		memcpy (hash_node->value, value, value_len);
+	}
+
+error_exit:
+	pthread_mutex_unlock (&hash_table->hash_buckets[hash_entry].mutex);
+	qb_hdb_handle_put (&qb_hash_handle_db, handle);
+
+	return (0);
+}
+
+
+int32_t qb_hash_key_get (
+	qb_hdb_handle_t handle,
+	const char *key,
+	void **value,
+	uint64_t *value_len)
+{
+	struct hash_table *hash_table;
+	uint32_t hash_entry;
+	uint32_t res = -1;
+	struct qb_list_head *list;
+	struct hash_node *hash_node;
+
+	res = qb_hdb_handle_get (&qb_hash_handle_db, handle, (void *)&hash_table);
+	if (res != 0) {
+		return (res);
+	}
+	res = -1;
+
+	hash_entry = hash_fnv (key, strlen (key), hash_table->order);
+
+	pthread_mutex_lock (&hash_table->hash_buckets[hash_entry].mutex);
+	for (list = hash_table->hash_buckets[hash_entry].list_head.next;
+		list != &hash_table->hash_buckets[hash_entry].list_head;
+		list = list->next) {
+
+		hash_node = qb_list_entry (list, struct hash_node, list);
+		if (strcmp (hash_node->key, key) == 0) {
+			*value = hash_node->value;
+			*value_len = hash_node->value_len;
+			res = 0;
+			goto unlock_exit;
+		}
+	}
+
+unlock_exit:
+	pthread_mutex_unlock (&hash_table->hash_buckets[hash_entry].mutex);
+	qb_hdb_handle_put (&qb_hash_handle_db, handle);
+	if (res == -1) {
+		errno = ENOENT;
+	}
+	return (res);
+}
+
+int32_t qb_hash_key_delete (
+	qb_hdb_handle_t handle,
+	const char *key)
+{
+	struct hash_table *hash_table;
+	struct qb_list_head *list;
+	uint32_t hash_entry;
+	uint32_t res = ENOENT;
+	struct hash_node *hash_node;
+
+	res = qb_hdb_handle_get (&qb_hash_handle_db, handle, (void *)&hash_table);
+	if (res != 0) {
+		return (res);
+	}
+	res = -1;
+
+	hash_entry = hash_fnv (key, strlen (key), hash_table->order);
+	pthread_mutex_lock (&hash_table->hash_buckets[hash_entry].mutex);
+	for (list = hash_table->hash_buckets[hash_entry].list_head.next;
+		list != &hash_table->hash_buckets[hash_entry].list_head;
+		list = list->next) {
+
+		hash_node = qb_list_entry (list, struct hash_node, list);
+		if (strcmp (hash_node->key, key) == 0) {
+			free (hash_node->value);
+			qb_list_del (&hash_node->list);
+			free (hash_node);
+			res = 0;
+			goto unlock_exit;
+		}
+	}
+
+unlock_exit:
+	pthread_mutex_unlock (&hash_table->hash_buckets[hash_entry].mutex);
+	qb_hdb_handle_put (&qb_hash_handle_db, handle);
+	if (res == -1)  {
+		errno = ENOENT;
+	}
+	return (res);
+}
+
+int32_t qb_hash_key_context_get (
+	qb_hdb_handle_t handle,
+	const char *key,
+	void **context)
+{
+	struct hash_table *hash_table;
+	int res = 0;
+
+	qb_hdb_handle_get (&qb_hash_handle_db, handle, (void *)&hash_table);
+	qb_hdb_handle_put (&qb_hash_handle_db, handle);
+	return (res);
+}
+
diff --git a/lib/hash/Makefile.am b/lib/hash/Makefile.am
deleted file mode 100644
index d1309e2..0000000
--- a/lib/hash/Makefile.am
+++ /dev/null
@@ -1,95 +0,0 @@
-#
-# Copyright (c) 2010 Red Hat, Inc.
-#
-# Authors: Andrew Beekhof
-#	   Steven Dake (sdake@redhat.com)
-#	   Angus Salkeld <asaslkeld@redhat.com>
-#
-# This software licensed under BSD license, the text of which follows:
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are met:
-#
-# - Redistributions of source code must retain the above copyright notice,
-#   this list of conditions and the following disclaimer.
-# - 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.
-# - Neither the name of the MontaVista Software, Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
-
-MAINTAINERCLEANFILES    = Makefile.in
-
-AM_CFLAGS		= -fPIC
-
-AM_LDFLAGS		= -lpthread
-
-INCLUDES		= -I$(top_builddir)/include -I$(top_srcdir)/include
-
-lib_LIBRARIES		= libqbhash.a
-SHARED_LIBS		= $(lib_LIBRARIES:%.a=%.so.$(SONAME))
-SHARED_LIBS_SO		= $(lib_LIBRARIES:%.a=%.so)
-SHARED_LIBS_SO_TWO	= $(lib_LIBRARIES:%.a=%.so.$(SOMAJOR))
-
-libqbhash_a_SOURCES	= hash.c
-
-noinst_HEADERS		= libqbhash.versions 
-
-if BUILD_DARWIN
-
-lib%.so.$(SONAME): %.o
-	$(CC) $(DARWIN_OPTS) $^ -o $@
-	ln -sf lib$*.so.$(SONAME) lib$*.so
-	ln -sf lib$*.so.$(SONAME) lib$*.so.$(SOMAJOR)
-
-else
-
-if BUILD_SOLARIS
-
-lib%.so.$(SONAME): %.o
-	$(LD) $(SOLARIS_OPTS) -G $^ -o $@
-	ln -sf lib$*.so.$(SONAME) lib$*.so
-	ln -sf lib$*.so.$(SONAME) lib$*.so.$(SOMAJOR)
-
-else
-
-libqb%.so.$(SONAME): %.o
-	$(CC) -shared -o $@ \
-		-Wl,-soname=libqb$*.so.$(SOMAJOR) \
-		-Wl,-version-script=$(srcdir)/libqb$*.versions \
-		$^ $(LDFLAGS) $(AM_LDFLAGS)
-	ln -sf libqb$*.so.$(SONAME) libqb$*.so
-	ln -sf libqb$*.so.$(SONAME) libqb$*.so.$(SOMAJOR)
-
-endif
-
-endif
-
-all-local: $(SHARED_LIBS)
-	@echo Built shared libs
-
-install-exec-local:
-	$(INSTALL) -d $(DESTDIR)/$(libdir)
-	$(INSTALL) -m 755 $(SHARED_LIBS) $(DESTDIR)/$(libdir)
-	$(CP) -a $(SHARED_LIBS_SO) $(SHARED_LIBS_SO_TWO) $(DESTDIR)/$(libdir)
-
-uninstall-local:
-	cd $(DESTDIR)/$(libdir)/ && \
-		rm -f $(SHARED_LIBS) $(SHARED_LIBS_SO) $(SHARED_LIBS_SO_TWO)
-
-clean-local:
-	rm -f *.o *.a *.so* *.da *.bb *.bbg
-
diff --git a/lib/hash/hash.c b/lib/hash/hash.c
deleted file mode 100644
index 93d27bc..0000000
--- a/lib/hash/hash.c
+++ /dev/null
@@ -1,286 +0,0 @@
-/*
- * Copyright (c) 2010 Red Hat, Inc.
- *
- * Author: Steven Dake (sdake@redhat.com)
- *
- * This software licensed under BSD license, the text of which follows:
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * - Redistributions of source code must retain the above copyright notice,
- *   this list of conditions and the following disclaimer.
- * - 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.
- * - Neither the name of Red Hat 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
- */
-#include <stdint.h>
-#include <qb/qbhdb.h>
-
-#include <config.h>
-
-#include "os_base.h"
-
-#include <qb/qbhdb.h>
-#include <qb/qblist.h>
-#include <qb/qbhash.h>
-
-#define FNV_32_PRIME ((uint32_t)0x01000193)
-
-DECLARE_HDB_DATABASE(qb_hash_handle_db,NULL);
-
-struct hash_node {
-	struct qb_list_head list;
-	void *value;
-	uint32_t value_len;
-	char key[0];
-};
-	
-struct hash_bucket {
-	pthread_mutex_t mutex;
-	struct qb_list_head list_head;
-};
-
-struct hash_table {
-	uint64_t memory_data;
-	uint64_t memory_overhead;
-	uint32_t order;
-	uint32_t hash_buckets_len;
-	struct hash_bucket hash_buckets[0];
-};
-
-static uint32_t hash_fnv (
-	const void *value,
-	uint32_t valuelen,
-	uint32_t order)
-{
-	uint8_t *cd = (uint8_t *)value;
-	uint8_t *ed = (uint8_t *)value + valuelen;
-	uint32_t hash_result = 0x811c9dc5;
-	int res;
-
-	while (cd < ed) {
-		hash_result ^= *cd;
-		hash_result *= FNV_32_PRIME;
-		cd++;
-	}
-	res = ((hash_result >> order) ^ hash_result) & ((1 << order) - 1);
-	return (res);
-}
-
-int32_t qb_hash_initialize (
-	qb_hdb_handle_t *handle,
-	uint32_t order,
-	uint32_t context_size)
-{
-	struct hash_table *hash_table;
-	int i;
-	uint64_t size;
-	int32_t res;
-
-	size = sizeof (struct hash_table) +
-		(sizeof (struct hash_bucket) * (1 << order));
-
-	res = qb_hdb_handle_create (&qb_hash_handle_db, size, handle);
-	if (res != 0) {
-		return (res);
-	}
-	res = qb_hdb_handle_get (&qb_hash_handle_db, *handle, (void *)&hash_table);
-	if (res != 0) {
-		goto hash_destroy;
-	}
-
-	hash_table->memory_data = 0;
-	hash_table->memory_overhead = size;
-
-	hash_table->order = order;
-	hash_table->hash_buckets_len = 1 << order;
-	for (i = 0; i < hash_table->hash_buckets_len; i++) {
-		qb_list_init (&hash_table->hash_buckets[i].list_head);
-		pthread_mutex_init (&hash_table->hash_buckets[i].mutex, NULL);
-	}
-
-	qb_hdb_handle_put (&qb_hash_handle_db, *handle);
-	return (0);
-
-hash_destroy:
-	res = qb_hdb_handle_destroy (&qb_hash_handle_db,  *handle);
-	return (-1);
-}
-
-int32_t qb_hash_key_set (
-	qb_hdb_handle_t handle,
-	const char *key,
-	const void *value,
-	uint32_t value_len)
-{
-	struct hash_table *hash_table;
-	uint32_t hash_entry;
-	struct qb_list_head *list;
-	int found = 0;
-	struct hash_node *hash_node;
-	int res;
-
-	res = qb_hdb_handle_get (&qb_hash_handle_db, handle, (void *)&hash_table);
-	if (res != 0) { 
-		return (res);
-	}
-	hash_entry = hash_fnv (key, strlen (key), hash_table->order);
-	pthread_mutex_lock (&hash_table->hash_buckets[hash_entry].mutex);
-	for (list = hash_table->hash_buckets[hash_entry].list_head.next;
-		list != &hash_table->hash_buckets[hash_entry].list_head;
-		list = list->next) {
-
-		hash_node = qb_list_entry (list, struct hash_node, list);
-
-		if (strcmp (hash_node->key, key) == 0) {
-			hash_table->memory_data -= value_len;
-			free (hash_node->value);
-			found = 1;
-			break;
-		}
-	}
-	if (found == 0) {
-		hash_node = malloc (sizeof (struct hash_node) + strlen (key) + 1);
-		if (hash_node == 0) {
-			goto error_exit;
-		}
-
-		hash_table->memory_overhead += sizeof (struct hash_node);
-		hash_table->memory_data += strlen (key) + 1;
-
-		memcpy (&hash_node->key, key, strlen (key) + 1);
-		qb_list_add_tail (&hash_node->list,
-			&hash_table->hash_buckets[hash_entry].list_head);
-	}
-	if (value_len) {
-		hash_node->value = malloc (value_len);
-		hash_table->memory_data += value_len;
-	} else {
-		hash_node->value = NULL;
-	}
-	hash_node->value_len = value_len;
-	if (value) {
-		memcpy (hash_node->value, value, value_len);
-	}
-
-error_exit:
-	pthread_mutex_unlock (&hash_table->hash_buckets[hash_entry].mutex);
-	qb_hdb_handle_put (&qb_hash_handle_db, handle);
-
-	return (0);
-}
-
-
-int32_t qb_hash_key_get (
-	qb_hdb_handle_t handle,
-	const char *key,
-	void **value,
-	uint64_t *value_len)
-{
-	struct hash_table *hash_table;
-	uint32_t hash_entry;
-	uint32_t res = -1;
-	struct qb_list_head *list;
-	struct hash_node *hash_node;
-
-	res = qb_hdb_handle_get (&qb_hash_handle_db, handle, (void *)&hash_table);
-	if (res != 0) {
-		return (res);
-	}
-	res = -1;
-
-	hash_entry = hash_fnv (key, strlen (key), hash_table->order);
-
-	pthread_mutex_lock (&hash_table->hash_buckets[hash_entry].mutex);
-	for (list = hash_table->hash_buckets[hash_entry].list_head.next;
-		list != &hash_table->hash_buckets[hash_entry].list_head;
-		list = list->next) {
-
-		hash_node = qb_list_entry (list, struct hash_node, list);
-		if (strcmp (hash_node->key, key) == 0) {
-			*value = hash_node->value;
-			*value_len = hash_node->value_len;
-			res = 0;
-			goto unlock_exit;
-		}
-	}
-
-unlock_exit:
-	pthread_mutex_unlock (&hash_table->hash_buckets[hash_entry].mutex);
-	qb_hdb_handle_put (&qb_hash_handle_db, handle);
-	if (res == -1) {
-		errno = ENOENT;
-	}
-	return (res);
-}
-
-int32_t qb_hash_key_delete (
-	qb_hdb_handle_t handle,
-	const char *key)
-{
-	struct hash_table *hash_table;
-	struct qb_list_head *list;
-	uint32_t hash_entry;
-	uint32_t res = ENOENT;
-	struct hash_node *hash_node;
-
-	res = qb_hdb_handle_get (&qb_hash_handle_db, handle, (void *)&hash_table);
-	if (res != 0) {
-		return (res);
-	}
-	res = -1;
-
-	hash_entry = hash_fnv (key, strlen (key), hash_table->order);
-	pthread_mutex_lock (&hash_table->hash_buckets[hash_entry].mutex);
-	for (list = hash_table->hash_buckets[hash_entry].list_head.next;
-		list != &hash_table->hash_buckets[hash_entry].list_head;
-		list = list->next) {
-
-		hash_node = qb_list_entry (list, struct hash_node, list);
-		if (strcmp (hash_node->key, key) == 0) {
-			free (hash_node->value);
-			qb_list_del (&hash_node->list);
-			free (hash_node);
-			res = 0;
-			goto unlock_exit;
-		}
-	}
-
-unlock_exit:
-	pthread_mutex_unlock (&hash_table->hash_buckets[hash_entry].mutex);
-	qb_hdb_handle_put (&qb_hash_handle_db, handle);
-	if (res == -1)  {
-		errno = ENOENT;
-	}
-	return (res);
-}
-
-int32_t qb_hash_key_context_get (
-	qb_hdb_handle_t handle,
-	const char *key,
-	void **context)
-{
-	struct hash_table *hash_table;
-	int res = 0;
-
-	qb_hdb_handle_get (&qb_hash_handle_db, handle, (void *)&hash_table);
-	qb_hdb_handle_put (&qb_hash_handle_db, handle);
-	return (res);
-}
-
diff --git a/lib/hash/libqbhash.versions b/lib/hash/libqbhash.versions
deleted file mode 100644
index 0fbbcae..0000000
--- a/lib/hash/libqbhash.versions
+++ /dev/null
@@ -1,15 +0,0 @@
-QB_HASH_0.1 {
-	global:
-		qb_hash_initialize;
-		qb_hash_key_set;
-		qb_hash_key_get;
-		qb_hash_key_delete;
-		qb_hash_key_context_get;
-		qb_hash_edge_create;
-		qb_hash_edge_destroy;
-		qb_hash_edge_follow;
-		qb_hash_edge_value_set;
-		qb_hash_edge_value_get;
-		
-	local: *;
-};
diff --git a/lib/ipc/Makefile.am b/lib/ipc/Makefile.am
deleted file mode 100644
index e22ba73..0000000
--- a/lib/ipc/Makefile.am
+++ /dev/null
@@ -1,96 +0,0 @@
-#
-# Copyright (c) 2010 Red Hat, Inc.
-#
-# Authors: Andrew Beekhof
-#	   Steven Dake (sdake@redhat.com)
-#	   Angus Salkeld <asaslkeld@redhat.com>
-#
-# This software licensed under BSD license, the text of which follows:
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are met:
-#
-# - Redistributions of source code must retain the above copyright notice,
-#   this list of conditions and the following disclaimer.
-# - 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.
-# - Neither the name of the MontaVista Software, Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
-
-MAINTAINERCLEANFILES    = Makefile.in
-
-AM_CFLAGS		= -fPIC
-
-AM_LDFLAGS		= -lpthread
-
-INCLUDES		= -I$(top_builddir)/include -I$(top_srcdir)/include
-
-lib_LIBRARIES		= libqbipcc.a libqbipcs.a
-SHARED_LIBS		= $(lib_LIBRARIES:%.a=%.so.$(SONAME))
-SHARED_LIBS_SO		= $(lib_LIBRARIES:%.a=%.so)
-SHARED_LIBS_SO_TWO	= $(lib_LIBRARIES:%.a=%.so.$(SOMAJOR))
-
-libqbipcc_a_SOURCES	= ipcc.c
-libqbipcs_a_SOURCES	= ipcs.c
-
-noinst_HEADERS		= ipc_int.h libqbipcc.versions libqbipcs.versions
-
-if BUILD_DARWIN
-
-lib%.so.$(SONAME): %.o
-	$(CC) $(DARWIN_OPTS) $^ -o $@
-	ln -sf lib$*.so.$(SONAME) lib$*.so
-	ln -sf lib$*.so.$(SONAME) lib$*.so.$(SOMAJOR)
-
-else
-
-if BUILD_SOLARIS
-
-lib%.so.$(SONAME): %.o
-	$(LD) $(SOLARIS_OPTS) -G $^ -o $@
-	ln -sf lib$*.so.$(SONAME) lib$*.so
-	ln -sf lib$*.so.$(SONAME) lib$*.so.$(SOMAJOR)
-
-else
-
-libqb%.so.$(SONAME): %.o
-	$(CC) -shared -o $@ \
-		-Wl,-soname=libqb$*.so.$(SOMAJOR) \
-		-Wl,-version-script=$(srcdir)/libqb$*.versions \
-		$^ $(LDFLAGS) $(AM_LDFLAGS)
-	ln -sf libqb$*.so.$(SONAME) libqb$*.so
-	ln -sf libqb$*.so.$(SONAME) libqb$*.so.$(SOMAJOR)
-
-endif
-
-endif
-
-all-local: $(SHARED_LIBS)
-	@echo Built shared libs
-
-install-exec-local:
-	$(INSTALL) -d $(DESTDIR)/$(libdir)
-	$(INSTALL) -m 755 $(SHARED_LIBS) $(DESTDIR)/$(libdir)
-	$(CP) -a $(SHARED_LIBS_SO) $(SHARED_LIBS_SO_TWO) $(DESTDIR)/$(libdir)
-
-uninstall-local:
-	cd $(DESTDIR)/$(libdir)/ && \
-		rm -f $(SHARED_LIBS) $(SHARED_LIBS_SO) $(SHARED_LIBS_SO_TWO)
-
-clean-local:
-	rm -f *.o *.a *.so* *.da *.bb *.bbg
-
diff --git a/lib/ipc/ipc_int.h b/lib/ipc/ipc_int.h
deleted file mode 100644
index ecca917..0000000
--- a/lib/ipc/ipc_int.h
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * Copyright (c) 2009 Red Hat, Inc.
- *
- * All rights reserved.
- *
- * Author: Steven Dake (sdake@redhat.com)
- *
- * This software licensed under BSD license, the text of which follows:
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * - Redistributions of source code must retain the above copyright notice,
- *   this list of conditions and the following disclaimer.
- * - 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.
- * - Neither the name of the MontaVista Software, Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
- */
-#ifndef QB_IPC_IPC_H_DEFINED
-#define QB_IPC_IPC_H_DEFINED
-
-#include <unistd.h>
-#include "config.h"
-
-/*
- * Darwin claims to support process shared synchronization
- * but it really does not.  The unistd.h header file is wrong.
- */
-#if defined(QB_DARWIN) || defined(__UCLIBC__)
-#undef _POSIX_THREAD_PROCESS_SHARED
-#define _POSIX_THREAD_PROCESS_SHARED -1
-#endif
-
-#ifndef _POSIX_THREAD_PROCESS_SHARED
-#define _POSIX_THREAD_PROCESS_SHARED -1
-#endif
-
-#if _POSIX_THREAD_PROCESS_SHARED > 0
-#include <semaphore.h>
-#endif
-
-enum req_init_types {
-	MESSAGE_REQ_RESPONSE_INIT = 0,
-	MESSAGE_REQ_DISPATCH_INIT = 1
-};
-
-#define MESSAGE_REQ_CHANGE_EUID		1
-#define MESSAGE_REQ_OUTQ_FLUSH		2
-
-#define MESSAGE_RES_OUTQ_EMPTY         0
-#define MESSAGE_RES_OUTQ_NOT_EMPTY     1
-#define MESSAGE_RES_ENABLE_FLOWCONTROL 2
-#define MESSAGE_RES_OUTQ_FLUSH_NR      3
-
-typedef struct {
-	int size __attribute__((aligned(8)));
-	int id __attribute__((aligned(8)));
-} qb_ipc_request_header_t __attribute__((aligned(8)));
-
-typedef struct {
-	int size __attribute__((aligned(8)));
-	int id __attribute__((aligned(8)));
-	int32_t error __attribute__((aligned(8)));
-} qb_ipc_response_header_t __attribute__((aligned(8)));
-
-struct control_buffer {
-	unsigned int read;
-	unsigned int write;
-#if _POSIX_THREAD_PROCESS_SHARED > 0
-	sem_t sem0;
-	sem_t sem1;
-	sem_t sem2;
-#endif
-};
-
-enum res_init_types {
-	MESSAGE_RES_INIT
-};
-
-typedef struct {
-	int service __attribute__((aligned(8)));
-	unsigned long long semkey __attribute__((aligned(8)));
-	char control_file[64] __attribute__((aligned(8)));
-	char request_file[64] __attribute__((aligned(8)));
-	char response_file[64] __attribute__((aligned(8)));
-	char dispatch_file[64] __attribute__((aligned(8)));
-	size_t control_size __attribute__((aligned(8)));
-	size_t request_size __attribute__((aligned(8)));
-	size_t response_size __attribute__((aligned(8)));
-	size_t dispatch_size __attribute__((aligned(8)));
-} mar_req_setup_t __attribute__((aligned(8)));
-
-typedef struct {
-	int error __attribute__((aligned(8)));
-} mar_res_setup_t __attribute__((aligned(8)));
-
-typedef struct {
-        uid_t euid __attribute__((aligned(8)));
-        gid_t egid __attribute__((aligned(8)));
-} mar_req_priv_change __attribute__((aligned(8)));
-
-typedef struct {
-	qb_ipc_response_header_t header __attribute__((aligned(8)));
-	uint64_t conn_info __attribute__((aligned(8)));
-} mar_res_lib_response_init_t __attribute__((aligned(8)));
-
-typedef struct {
-	qb_ipc_response_header_t header __attribute__((aligned(8)));
-} mar_res_lib_dispatch_init_t __attribute__((aligned(8)));
-
-typedef struct {
-	uint32_t nodeid __attribute__((aligned(8)));
-	void *conn __attribute__((aligned(8)));
-} mar_message_source_t __attribute__((aligned(8)));
-
-typedef struct {
-        qb_ipc_request_header_t header __attribute__((aligned(8)));
-        size_t map_size __attribute__((aligned(8)));
-        char path_to_file[128] __attribute__((aligned(8)));
-} mar_req_qb_ipcc_zc_alloc_t __attribute__((aligned(8)));
-
-typedef struct {
-        qb_ipc_request_header_t header __attribute__((aligned(8)));
-        size_t map_size __attribute__((aligned(8)));
-	uint64_t server_address __attribute__((aligned(8)));
-} mar_req_qb_ipcc_zc_free_t __attribute__((aligned(8)));
-
-typedef struct {
-        qb_ipc_request_header_t header __attribute__((aligned(8)));
-	uint64_t server_address __attribute__((aligned(8)));
-} mar_req_qb_ipcc_zc_execute_t __attribute__((aligned(8)));
-
-struct qb_ipcs_zc_header {
-	int map_size;
-	uint64_t server_address;
-};
-
-#define SOCKET_SERVICE_INIT	0xFFFFFFFF
-
-#define ZC_ALLOC_HEADER		0xFFFFFFFF
-#define ZC_FREE_HEADER		0xFFFFFFFE
-#define ZC_EXECUTE_HEADER	0xFFFFFFFD
-
-#endif /* QB_IPC_IPC_H_DEFINED */
diff --git a/lib/ipc/ipcc.c b/lib/ipc/ipcc.c
deleted file mode 100644
index a21f3f0..0000000
--- a/lib/ipc/ipcc.c
+++ /dev/null
@@ -1,1203 +0,0 @@
-/*
- * vi: set autoindent tabstop=4 shiftwidth=4 :
- *
- * Copyright (c) 2002-2006 MontaVista Software, Inc.
- * Copyright (c) 2006-2009 Red Hat, Inc.
- *
- * All rights reserved.
- *
- * Author: Steven Dake (sdake@redhat.com)
- *
- * This software licensed under BSD license, the text of which follows:
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * - Redistributions of source code must retain the above copyright notice,
- *   this list of conditions and the following disclaimer.
- * - 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.
- * - Neither the name of the MontaVista Software, Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
- */
-
-#include <config.h>
-
-#include "os_base.h"
-#include <sys/shm.h>
-#include <sys/mman.h>
-
-#include <qb/qbipcc.h>
-#include <qb/qbhdb.h>
-#include "ipc_int.h"
-
-#if _POSIX_THREAD_PROCESS_SHARED > 0
-#include <semaphore.h>
-#else
-#include <sys/sem.h>
-#endif
-
-
-/*
- * Define sem_wait timeout (real timeout will be (n-1;n) )
- */
-#define IPC_SEMWAIT_TIMEOUT 2
-
-struct ipc_instance {
-	int fd;
-#if _POSIX_THREAD_PROCESS_SHARED < 1
-	int semid;
-#endif
-	int flow_control_state;
-	struct control_buffer *control_buffer;
-	char *request_buffer;
-	char *response_buffer;
-	char *dispatch_buffer;
-	size_t control_size;
-	size_t request_size;
-	size_t response_size;
-	size_t dispatch_size;
-	uid_t euid;
-	pthread_mutex_t mutex;
-};
-
-void ipc_hdb_destructor (void *context);
-
-DECLARE_HDB_DATABASE(ipc_hdb,ipc_hdb_destructor);
-
-#if defined(QB_LINUX) || defined(QB_SOLARIS)
-#define QB_SUN_LEN(a) sizeof(*(a))
-#else
-#define QB_SUN_LEN(a) SUN_LEN(a)
-#endif
-
-#ifdef SO_NOSIGPIPE
-static void socket_nosigpipe(int s)
-{
-	int on = 1;
-	setsockopt(s, SOL_SOCKET, SO_NOSIGPIPE, (void *)&on, sizeof(on));
-}
-#endif
-
-#ifndef MSG_NOSIGNAL
-#define MSG_NOSIGNAL 0
-#endif
-
-static int32_t
-socket_send (
-	int s,
-	void *msg,
-	size_t len)
-{
-	int32_t res = 0;
-	int result;
-	struct msghdr msg_send;
-	struct iovec iov_send;
-	char *rbuf = msg;
-	int processed = 0;
-
-	msg_send.msg_iov = &iov_send;
-	msg_send.msg_iovlen = 1;
-	msg_send.msg_name = 0;
-	msg_send.msg_namelen = 0;
-
-#if !defined(QB_SOLARIS)
-	msg_send.msg_control = 0;
-	msg_send.msg_controllen = 0;
-	msg_send.msg_flags = 0;
-#else
-	msg_send.msg_accrights = NULL;
-	msg_send.msg_accrightslen = 0;
-#endif
-
-retry_send:
-	iov_send.iov_base = &rbuf[processed];
-	iov_send.iov_len = len - processed;
-
-	result = sendmsg (s, &msg_send, MSG_NOSIGNAL);
-	if (result == -1) {
-		switch (errno) {
-		case EINTR:
-			res = EAGAIN;
-			goto res_exit;
-		case EAGAIN:
-			goto retry_send;
-			break;
-		default:
-			res = EBADE;
-			goto res_exit;
-		}
-	}
-
-	processed += result;
-	if (processed != len) {
-		goto retry_send;
-	}
-
-	return 0;
-
-res_exit:
-	return (res);
-}
-
-static int32_t
-socket_recv (
-	int s,
-	void *msg,
-	size_t len)
-{
-	int32_t res = 0;
-	int result;
-	struct msghdr msg_recv;
-	struct iovec iov_recv;
-	char *rbuf = msg;
-	int processed = 0;
-
-	msg_recv.msg_iov = &iov_recv;
-	msg_recv.msg_iovlen = 1;
-	msg_recv.msg_name = 0;
-	msg_recv.msg_namelen = 0;
-#if !defined (QB_SOLARIS)
-	msg_recv.msg_control = 0;
-	msg_recv.msg_controllen = 0;
-	msg_recv.msg_flags = 0;
-#else
-	msg_recv.msg_accrights = NULL;
-	msg_recv.msg_accrightslen = 0;
-#endif
-
-
-retry_recv:
-	iov_recv.iov_base = (void *)&rbuf[processed];
-	iov_recv.iov_len = len - processed;
-
-	result = recvmsg (s, &msg_recv, MSG_NOSIGNAL|MSG_WAITALL);
-	if (result == -1) {
-		switch (errno) {
-		case EINTR:
-			res = EAGAIN;
-			goto res_exit;
-		case EAGAIN:
-			goto retry_recv;
-			break;
-		default:
-			res = EBADE;
-			goto res_exit;
-		}
-	}
-#if defined(QB_SOLARIS) || defined(QB_BSD) || defined(QB_DARWIN)
-	/* On many OS poll never return POLLHUP or POLLERR.
-	 * EOF is detected when recvmsg return 0.
-	 */
-	if (result == 0) {
-		res = EBADE;
-		goto res_exit;
-	}
-#endif
-
-	processed += result;
-	if (processed != len) {
-		goto retry_recv;
-	}
-	assert (processed == len);
-res_exit:
-	return (res);
-}
-
-#if _POSIX_THREAD_PROCESS_SHARED < 1
-static int
-priv_change_send (struct ipc_instance *ipc_instance)
-{
-	char buf_req;
-	mar_req_priv_change req_priv_change;
-	unsigned int res;
-
-	req_priv_change.euid = geteuid();
-	/*
-	 * Don't resend request unless euid has changed
-	*/
-	if (ipc_instance->euid == req_priv_change.euid) {
-		return (0);
-	}
-	req_priv_change.egid = getegid();
-
-	buf_req = MESSAGE_REQ_CHANGE_EUID;
-	res = socket_send (ipc_instance->fd, &buf_req, 1);
-	if (res == -1) {
-		return (-1);
-	}
-
-	res = socket_send (ipc_instance->fd, &req_priv_change,
-		sizeof (req_priv_change));
-	if (res == -1) {
-		return (-1);
-	}
-
-	ipc_instance->euid = req_priv_change.euid;
-	return (0);
-}
-
-#if defined(_SEM_SEMUN_UNDEFINED)
-union semun {
-        int val;
-        struct semid_ds *buf;
-        unsigned short int *array;
-        struct seminfo *__buf;
-};
-#endif
-#endif
-
-static int
-circular_memory_map (char *path, const char *file, void **buf, size_t bytes)
-{
-	int fd;
-	void *addr_orig;
-	void *addr;
-	int res;
-
-	sprintf (path, "/dev/shm/%s", file);
-
-	fd = mkstemp (path);
-	if (fd == -1) {
-		sprintf (path, LOCALSTATEDIR "/run/%s", file);
-		fd = mkstemp (path);
-		if (fd == -1) {
-			return (-1);
-		}
-	}
-
-	res = ftruncate (fd, bytes);
-
-	addr_orig = mmap (NULL, bytes << 1, PROT_NONE,
-		MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
-
-	if (addr_orig == MAP_FAILED) {
-		return (-1);
-	}
-
-	addr = mmap (addr_orig, bytes, PROT_READ | PROT_WRITE,
-		MAP_FIXED | MAP_SHARED, fd, 0);
-
-	if (addr != addr_orig) {
-		return (-1);
-	}
-#ifdef QB_BSD
-	madvise(addr_orig, bytes, MADV_NOSYNC);
-#endif
-
-	addr = mmap (((char *)addr_orig) + bytes,
-                  bytes, PROT_READ | PROT_WRITE,
-                  MAP_FIXED | MAP_SHARED, fd, 0);
-#ifdef QB_BSD
-	madvise(((char *)addr_orig) + bytes, bytes, MADV_NOSYNC);
-#endif
-
-	res = close (fd);
-	if (res) {
-		return (-1);
-	}
-	*buf = addr_orig;
-	return (0);
-}
-
-static void
-memory_unmap (void *addr, size_t bytes)
-{
-	int res;
-
-	res = munmap (addr, bytes);
-}
-
-void ipc_hdb_destructor (void *context ) {
-	struct ipc_instance *ipc_instance = (struct ipc_instance *)context;
-
-	/*
-	 * << 1 (or multiplied by 2) because this is a wrapped memory buffer
-	 */
-	memory_unmap (ipc_instance->control_buffer, ipc_instance->control_size);
-	memory_unmap (ipc_instance->request_buffer, ipc_instance->request_size);
-	memory_unmap (ipc_instance->response_buffer, ipc_instance->response_size);
-	memory_unmap (ipc_instance->dispatch_buffer, (ipc_instance->dispatch_size) << 1);
-}
-static int
-memory_map (char *path, const char *file, void **buf, size_t bytes)
-{
-	int fd;
-	void *addr_orig;
-	void *addr;
-	int res;
-
-	sprintf (path, "/dev/shm/%s", file);
-
-	fd = mkstemp (path);
-	if (fd == -1) {
-		sprintf (path, LOCALSTATEDIR "/run/%s", file);
-		fd = mkstemp (path);
-		if (fd == -1) {
-			return (-1);
-		}
-	}
-
-	res = ftruncate (fd, bytes);
-
-	addr_orig = mmap (NULL, bytes, PROT_NONE,
-		MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
-
-	if (addr_orig == MAP_FAILED) {
-		return (-1);
-	}
-
-	addr = mmap (addr_orig, bytes, PROT_READ | PROT_WRITE,
-		MAP_FIXED | MAP_SHARED, fd, 0);
-
-	if (addr != addr_orig) {
-		return (-1);
-	}
-#ifdef QB_BSD
-	madvise(addr_orig, bytes, MADV_NOSYNC);
-#endif
-
-	res = close (fd);
-	if (res) {
-		return (-1);
-	}
-	*buf = addr_orig;
-	return (0);
-}
-
-static int32_t
-msg_send (
-	struct ipc_instance *ipc_instance,
-	const struct iovec *iov,
-	unsigned int iov_len)
-{
-#if _POSIX_THREAD_PROCESS_SHARED < 1
-	struct sembuf sop;
-#endif
-
-	int i;
-	int res;
-	int req_buffer_idx = 0;
-
-	for (i = 0; i < iov_len; i++) {
-		if ((req_buffer_idx + iov[i].iov_len) > 
-			ipc_instance->request_size) {
-			return (EINVAL);
-		}
-		memcpy (&ipc_instance->request_buffer[req_buffer_idx],
-			iov[i].iov_base,
-			iov[i].iov_len);
-		req_buffer_idx += iov[i].iov_len;
-	}
-
-#if _POSIX_THREAD_PROCESS_SHARED > 0
-	res = sem_post (&ipc_instance->control_buffer->sem0);
-	if (res == -1) {
-		return EBADE;
-	}
-#else 
-	/*
-	 * Signal semaphore #0 indicting a new message from client
-	 * to server request queue
-	 */
-	sop.sem_num = 0;
-	sop.sem_op = 1;
-	sop.sem_flg = 0;
-
-retry_semop:
-	res = semop (ipc_instance->semid, &sop, 1);
-	if (res == -1 && errno == EINTR) {
-		return (EAGAIN);
-	} else
-	if (res == -1 && errno == EACCES) {
-		priv_change_send (ipc_instance);
-		goto retry_semop;
-	} else
-	if (res == -1) {
-		return (EBADE);
-	}
-#endif
-	return 0;
-}
-
-static int32_t
-reply_receive (
-	struct ipc_instance *ipc_instance,
-	void *res_msg,
-	size_t res_len)
-{
-#if _POSIX_THREAD_PROCESS_SHARED < 1
-	struct sembuf sop;
-#else
-	struct timespec timeout;
-	struct pollfd pfd;
-#endif
-	qb_ipc_response_header_t *response_header;
-	int res;
-
-#if _POSIX_THREAD_PROCESS_SHARED > 0
-retry_semwait:
-	timeout.tv_sec = time(NULL) + IPC_SEMWAIT_TIMEOUT;
-	timeout.tv_nsec = 0;
-
-	res = sem_timedwait (&ipc_instance->control_buffer->sem1, &timeout);
-	if (res == -1 && errno == ETIMEDOUT) {
-		pfd.fd = ipc_instance->fd;
-		pfd.events = 0;
-
-		poll (&pfd, 1, 0);
-		if (pfd.revents == POLLERR || pfd.revents == POLLHUP) {
-			return EBADE;
-		}
-
-		goto retry_semwait;
-	}
-
-	if (res == -1 && errno == EINTR) {
-		goto retry_semwait;
-	}
-#else
-	/*
-	 * Wait for semaphore #1 indicating a new message from server
-	 * to client in the response queue
-	 */
-	sop.sem_num = 1;
-	sop.sem_op = -1;
-	sop.sem_flg = 0;
-
-retry_semop:
-	res = semop (ipc_instance->semid, &sop, 1);
-	if (res == -1 && errno == EINTR) {
-		return (EAGAIN);
-	} else
-	if (res == -1 && errno == EACCES) {
-		priv_change_send (ipc_instance);
-		goto retry_semop;
-	} else
-	if (res == -1) {
-		return (EBADE);
-	}
-#endif
-
-	response_header = (qb_ipc_response_header_t *)ipc_instance->response_buffer;
-	if (response_header->error == EAGAIN) {
-		return EAGAIN;
-	}
-
-	memcpy (res_msg, ipc_instance->response_buffer, res_len);
-	return 0;
-}
-
-static int32_t
-reply_receive_in_buf (
-	struct ipc_instance *ipc_instance,
-	void **res_msg)
-{
-#if _POSIX_THREAD_PROCESS_SHARED < 1
-	struct sembuf sop;
-#else
-	struct timespec timeout;
-	struct pollfd pfd;
-#endif
-	int res;
-
-#if _POSIX_THREAD_PROCESS_SHARED > 0
-retry_semwait:
-	timeout.tv_sec = time(NULL) + IPC_SEMWAIT_TIMEOUT;
-	timeout.tv_nsec = 0;
-
-	res = sem_timedwait (&ipc_instance->control_buffer->sem1, &timeout);
-	if (res == -1 && errno == ETIMEDOUT) {
-		pfd.fd = ipc_instance->fd;
-		pfd.events = 0;
-
-		poll (&pfd, 1, 0);
-		if (pfd.revents == POLLERR || pfd.revents == POLLHUP) {
-			return EBADE;
-		}
-
-		goto retry_semwait;
-	}
-
-	if (res == -1 && errno == EINTR) {
-		goto retry_semwait;
-	}
-#else
-	/*
-	 * Wait for semaphore #1 indicating a new message from server
-	 * to client in the response queue
-	 */
-	sop.sem_num = 1;
-	sop.sem_op = -1;
-	sop.sem_flg = 0;
-
-retry_semop:
-	res = semop (ipc_instance->semid, &sop, 1);
-	if (res == -1 && errno == EINTR) {
-		return (EAGAIN);
-	} else
-	if (res == -1 && errno == EACCES) {
-		priv_change_send (ipc_instance);
-		goto retry_semop;
-	} else
-	if (res == -1) {
-		return (EBADE);
-	}
-#endif
-
-	*res_msg = (char *)ipc_instance->response_buffer;
-	return 0;
-}
-
-/*
- * External API
- */
-int32_t
-qb_ipcc_service_connect (
-	const char *socket_name,
-	unsigned int service,
-	size_t request_size,
-	size_t response_size,
-	size_t dispatch_size,
-	qb_hdb_handle_t *handle)
-
-{
-	int request_fd;
-	struct sockaddr_un address;
-	int32_t res;
-	struct ipc_instance *ipc_instance;
-#if _POSIX_THREAD_PROCESS_SHARED < 1
-	key_t semkey = 0;
-	union semun semun;
-#endif
-	int sys_res;
-	mar_req_setup_t req_setup;
-	mar_res_setup_t res_setup;
-	char control_map_path[128];
-	char request_map_path[128];
-	char response_map_path[128];
-	char dispatch_map_path[128];
-
-	res = qb_hdb_handle_create (&ipc_hdb,
-		sizeof (struct ipc_instance), handle);
-	if (res != 0) {
-		return (res);
-	}
-
-	res = qb_hdb_handle_get (&ipc_hdb, *handle, (void **)&ipc_instance);
-	if (res != 0) {
-		return (res);
-	}
-
-	res_setup.error = EBADE;
-
-#if defined(QB_SOLARIS)
-	request_fd = socket (PF_UNIX, SOCK_STREAM, 0);
-#else
-	request_fd = socket (PF_LOCAL, SOCK_STREAM, 0);
-#endif
-	if (request_fd == -1) {
-		return (EBADE);
-	}
-#ifdef SO_NOSIGPIPE
-	socket_nosigpipe (request_fd);
-#endif
-
-	memset (&address, 0, sizeof (struct sockaddr_un));
-	address.sun_family = AF_UNIX;
-#if defined(QB_BSD) || defined(QB_DARWIN)
-	address.sun_len = SUN_LEN(&address);
-#endif
-
-#if defined(QB_LINUX)
-	sprintf (address.sun_path + 1, "%s", socket_name);
-#else
-	sprintf (address.sun_path, "%s/%s", SOCKETDIR, socket_name);
-#endif
-	sys_res = connect (request_fd, (struct sockaddr *)&address,
-		QB_SUN_LEN(&address));
-	if (sys_res == -1) {
-		res = EAGAIN;
-		goto error_connect;
-	}
-
-	res = memory_map (
-		control_map_path,
-		"control_buffer-XXXXXX",
-		(void *)&ipc_instance->control_buffer,
-		8192);
-	if (res == -1) {
-		res = EBADE;
-		goto error_connect;
-	}
-
-	res = memory_map (
-		request_map_path,
-		"request_buffer-XXXXXX",
-		(void *)&ipc_instance->request_buffer,
-		request_size);
-	if (res == -1) {
-		res = EBADE;
-		goto error_request_buffer;
-	}
-
-	res = memory_map (
-		response_map_path,
-		"response_buffer-XXXXXX",
-		(void *)&ipc_instance->response_buffer,
-		response_size);
-	if (res == -1) {
-		res = EBADE;
-		goto error_response_buffer;
-	}
-
-	res = circular_memory_map (
-		dispatch_map_path,
-		"dispatch_buffer-XXXXXX",
-		(void *)&ipc_instance->dispatch_buffer,
-		dispatch_size);
-	if (res == -1) {
-		res = EBADE;
-		goto error_dispatch_buffer;
-	}
-
-#if _POSIX_THREAD_PROCESS_SHARED > 0
-	sem_init (&ipc_instance->control_buffer->sem0, 1, 0);
-	sem_init (&ipc_instance->control_buffer->sem1, 1, 0);
-	sem_init (&ipc_instance->control_buffer->sem2, 1, 0);
-#else
-
-	/*
-	 * Allocate a semaphore segment
-	 */
-	while (1) {
-		semkey = random();
-		ipc_instance->euid = geteuid ();
-		if ((ipc_instance->semid
-		     = semget (semkey, 3, IPC_CREAT|IPC_EXCL|0600)) != -1) {
-		      break;
-		}
-		/*
-		 * EACCESS can be returned as non root user when opening a different
-		 * users semaphore.
-		 *
-		 * EEXIST can happen when we are a root or nonroot user opening
-		 * an existing shared memory segment for which we have access
-		 */
-		if (errno != EEXIST && errno != EACCES) {
-			goto error_exit;
-		}
-	}
-
-	semun.val = 0;
-	res = semctl (ipc_instance->semid, 0, SETVAL, semun);
-	if (res != 0) {
-		goto error_exit;
-	}
-
-	res = semctl (ipc_instance->semid, 1, SETVAL, semun);
-	if (res != 0) {
-		goto error_exit;
-	}
-#endif
-
-	/*
-	 * Initialize IPC setup message
-	 */
-	req_setup.service = service;
-	strcpy (req_setup.control_file, control_map_path);
-	strcpy (req_setup.request_file, request_map_path);
-	strcpy (req_setup.response_file, response_map_path);
-	strcpy (req_setup.dispatch_file, dispatch_map_path);
-	req_setup.control_size = 8192;
-	req_setup.request_size = request_size;
-	req_setup.response_size = response_size;
-	req_setup.dispatch_size = dispatch_size;
-
-#if _POSIX_THREAD_PROCESS_SHARED < 1
-	req_setup.semkey = semkey;
-#endif
-
-	res = socket_send (request_fd, &req_setup, sizeof (mar_req_setup_t));
-	if (res != 0) {
-		goto error_exit;
-	}
-	res = socket_recv (request_fd, &res_setup, sizeof (mar_res_setup_t));
-	if (res != 0) {
-		goto error_exit;
-	}
-
-	ipc_instance->fd = request_fd;
-	ipc_instance->flow_control_state = 0;
-
-	if (res_setup.error == EAGAIN) {
-		res = res_setup.error;
-		goto error_exit;
-	}
-
-	ipc_instance->control_size = 8192;
-	ipc_instance->request_size = request_size;
-	ipc_instance->response_size = response_size;
-	ipc_instance->dispatch_size = dispatch_size;
-
-	pthread_mutex_init (&ipc_instance->mutex, NULL);
-
-	qb_hdb_handle_put (&ipc_hdb, *handle);
-
-	return (res_setup.error);
-
-error_exit:
-#if _POSIX_THREAD_PROCESS_SHARED < 1
-	if (ipc_instance->semid > 0)
-		semctl (ipc_instance->semid, 0, IPC_RMID);
-#endif
-	memory_unmap (ipc_instance->dispatch_buffer, dispatch_size);
-error_dispatch_buffer:
-	memory_unmap (ipc_instance->response_buffer, response_size);
-error_response_buffer:
-	memory_unmap (ipc_instance->request_buffer, request_size);
-error_request_buffer:
-	memory_unmap (ipc_instance->control_buffer, 8192);
-error_connect:
-	close (request_fd);
-
-	qb_hdb_handle_destroy (&ipc_hdb, *handle);
-	qb_hdb_handle_put (&ipc_hdb, *handle);
-
-	return (res);
-}
-
-int32_t
-qb_ipcc_service_disconnect (
-	qb_hdb_handle_t handle)
-{
-	int32_t res;
-	struct ipc_instance *ipc_instance;
-
-	res = qb_hdb_handle_get (&ipc_hdb, handle, (void **)&ipc_instance);
-	if (res != 0) {
-		return (res);
-	}
-
-	shutdown (ipc_instance->fd, SHUT_RDWR);
-	close (ipc_instance->fd);
-	qb_hdb_handle_destroy (&ipc_hdb, handle);
-	qb_hdb_handle_put (&ipc_hdb, handle);
-	return (0);
-}
-
-int32_t
-qb_ipcc_dispatch_flow_control_get (
-	qb_hdb_handle_t handle,
-	unsigned int *flow_control_state)
-{
-	struct ipc_instance *ipc_instance;
-	int32_t res;
-
-	res = qb_hdb_handle_get (&ipc_hdb, handle, (void **)&ipc_instance);
-	if (res != 0) {
-		return (res);
-	}
-
-	*flow_control_state = ipc_instance->flow_control_state;
-
-	qb_hdb_handle_put (&ipc_hdb, handle);
-	return (res);
-}
-
-int32_t
-qb_ipcc_fd_get (
-	qb_hdb_handle_t handle,
-	int *fd)
-{
-	struct ipc_instance *ipc_instance;
-	int32_t res;
-
-	res = qb_hdb_handle_get (&ipc_hdb, handle, (void **)&ipc_instance);
-	if (res != 0) {
-		return (res);
-	}
-
-	*fd = ipc_instance->fd;
-
-	qb_hdb_handle_put (&ipc_hdb, handle);
-	return (res);
-}
-
-int32_t
-qb_ipcc_dispatch_get (
-	qb_hdb_handle_t handle,
-	void **data,
-	int timeout)
-{
-	struct pollfd ufds;
-	int poll_events;
-	char buf;
-	struct ipc_instance *ipc_instance;
-	int res;
-	char buf_two = 1;
-	char *data_addr;
-	int32_t error = 0;
-
-	error = qb_hdb_handle_get (&ipc_hdb, handle, (void **)&ipc_instance);
-	if (error != 0) {
-		return (error);
-	}
-
-	*data = NULL;
-
-	ufds.fd = ipc_instance->fd;
-	ufds.events = POLLIN;
-	ufds.revents = 0;
-
-	poll_events = poll (&ufds, 1, timeout);
-	if (poll_events == -1 && errno == EINTR) {
-		error = EAGAIN;
-		goto error_put;
-	} else
-	if (poll_events == -1) {
-		error = EBADE;
-		goto error_put;
-	} else
-	if (poll_events == 0) {
-		error = EAGAIN;
-		goto error_put;
-	}
-	if (poll_events == 1 && (ufds.revents & (POLLERR|POLLHUP))) {
-		error = EBADE;
-		goto error_put;
-	}
-
-	res = recv (ipc_instance->fd, &buf, 1, 0);
-	if (res == -1 && errno == EINTR) {
-		error = EAGAIN;
-		goto error_put;
-	} else
-	if (res == -1) {
-		error = EBADE;
-		goto error_put;
-	} else
-	if (res == 0) {
-		/* Means that the peer closed cleanly the socket. However, it should
-		 * happen only on BSD and Darwing systems since poll() returns a
-		 * POLLHUP event on other systems.
-		 */
-		error = EBADE;
-		goto error_put;
-	}
-	ipc_instance->flow_control_state = 0;
-	if (buf == MESSAGE_RES_OUTQ_NOT_EMPTY || buf == MESSAGE_RES_ENABLE_FLOWCONTROL) {
-		ipc_instance->flow_control_state = 1;
-	}
-	/*
-	 * Notify executive to flush any pending dispatch messages
-	 */
-	if (ipc_instance->flow_control_state) {
-		buf_two = MESSAGE_REQ_OUTQ_FLUSH;
-		res = socket_send (ipc_instance->fd, &buf_two, 1);
-		assert (res == 0); /* TODO */
-	}
-	/*
-	 * This is just a notification of flow control starting at the addition
-	 * of a new pending message, not a message to dispatch
-	 */
-	if (buf == MESSAGE_RES_ENABLE_FLOWCONTROL) {
-		error = EAGAIN;
-		goto error_put;
-	}
-	if (buf == MESSAGE_RES_OUTQ_FLUSH_NR) {
-		error = EAGAIN;
-		goto error_put;
-	}
-
-	data_addr = ipc_instance->dispatch_buffer;
-
-	data_addr = &data_addr[ipc_instance->control_buffer->read];
-
-	*data = (void *)data_addr;
-
-	return (0);
-error_put:
-	qb_hdb_handle_put (&ipc_hdb, handle);
-	return (error);
-}
-
-int32_t
-qb_ipcc_dispatch_put (qb_hdb_handle_t handle)
-{
-#if _POSIX_THREAD_PROCESS_SHARED < 1
-	struct sembuf sop;
-#endif
-	qb_ipc_response_header_t *header;
-	struct ipc_instance *ipc_instance;
-	int res;
-	char *addr;
-	unsigned int read_idx;
-
-	res = qb_hdb_handle_get_always (&ipc_hdb, handle, (void **)&ipc_instance);
-	if (res != 0) {
-		return (res);
-	}
-#if _POSIX_THREAD_PROCESS_SHARED > 0
-retry_semwait:
-	res = sem_wait (&ipc_instance->control_buffer->sem2);
-	if (res == -1 && errno == EINTR) {
-		goto retry_semwait;
-	}
-#else
-	sop.sem_num = 2;
-	sop.sem_op = -1;
-	sop.sem_flg = 0;
-retry_semop:
-	res = semop (ipc_instance->semid, &sop, 1);
-	if (res == -1 && errno == EINTR) {
-		res = EAGAIN;
-		goto error_exit;
-	} else
-	if (res == -1 && errno == EACCES) {
-		priv_change_send (ipc_instance);
-		goto retry_semop;
-	} else
-	if (res == -1) {
-		res = EBADE;
-		goto error_exit;
-	}
-#endif
-
-	addr = ipc_instance->dispatch_buffer;
-
-	read_idx = ipc_instance->control_buffer->read;
-	header = (qb_ipc_response_header_t *) &addr[read_idx];
-	ipc_instance->control_buffer->read =
-		(read_idx + header->size) % ipc_instance->dispatch_size;
-	/*
-	 * Put from dispatch get and also from this call's get
-	 */
-	res = 0;
-	
-#if _POSIX_THREAD_PROCESS_SHARED < 1
-error_exit:
-#endif
-	qb_hdb_handle_put (&ipc_hdb, handle);
-	qb_hdb_handle_put (&ipc_hdb, handle);
-
-	return (res);
-}
-
-int32_t
-qb_ipcc_msg_send_reply_receive (
-	qb_hdb_handle_t handle,
-	const struct iovec *iov,
-	unsigned int iov_len,
-	void *res_msg,
-	size_t res_len)
-{
-	int32_t res;
-	struct ipc_instance *ipc_instance;
-
-	res = qb_hdb_handle_get (&ipc_hdb, handle, (void **)&ipc_instance);
-	if (res != 0) {
-		return (res);
-	}
-
-	pthread_mutex_lock (&ipc_instance->mutex);
-
-	res = msg_send (ipc_instance, iov, iov_len);
-	if (res != 0) {
-		goto error_exit;
-	}
-
-	res = reply_receive (ipc_instance, res_msg, res_len);
-
-error_exit:
-	qb_hdb_handle_put (&ipc_hdb, handle);
-	pthread_mutex_unlock (&ipc_instance->mutex);
-
-	return (res);
-}
-
-int32_t
-qb_ipcc_msg_send_reply_receive_in_buf_get (
-	qb_hdb_handle_t handle,
-	const struct iovec *iov,
-	unsigned int iov_len,
-	void **res_msg)
-{
-	unsigned int res;
-	struct ipc_instance *ipc_instance;
-
-	res = qb_hdb_handle_get (&ipc_hdb, handle, (void **)&ipc_instance);
-	if (res != 0) {
-		return (res);
-	}
-
-	pthread_mutex_lock (&ipc_instance->mutex);
-
-	res = msg_send (ipc_instance, iov, iov_len);
-	if (res != 0) {
-		goto error_exit;
-	}
-
-	res = reply_receive_in_buf (ipc_instance, res_msg);
-
-error_exit:
-	pthread_mutex_unlock (&ipc_instance->mutex);
-
-	return (res);
-}
-
-int32_t
-qb_ipcc_msg_send_reply_receive_in_buf_put (
-	qb_hdb_handle_t handle)
-{
-	unsigned int res;
-	struct ipc_instance *ipc_instance;
-
-	res = qb_hdb_handle_get (&ipc_hdb, handle, (void **)&ipc_instance);
-	if (res != 0) {
-		return (res);
-	}
-	qb_hdb_handle_put (&ipc_hdb, handle);
-	qb_hdb_handle_put (&ipc_hdb, handle);
-
-	return (res);
-}
-
-int32_t
-qb_ipcc_zcb_alloc (
-	qb_hdb_handle_t handle,
-	void **buffer,
-	size_t size,
-	size_t header_size)
-{
-	struct ipc_instance *ipc_instance;
-	void *buf = NULL;
-	char path[128];
-	unsigned int res;
-	mar_req_qb_ipcc_zc_alloc_t req_qb_ipcc_zc_alloc;
-	qb_ipc_response_header_t res_qb_ipcs_zc_alloc;
-	size_t map_size;
-	struct iovec iovec;
-	struct qb_ipcs_zc_header *hdr;
-
-	res = qb_hdb_handle_get (&ipc_hdb, handle, (void **)&ipc_instance);
-	if (res != 0) {
-		return (res);
-	}
-	map_size = size + header_size + sizeof (struct qb_ipcs_zc_header);
-	res = memory_map (path, "qb_zerocopy-XXXXXX", &buf, map_size);
-	assert (res != -1);
-
-	req_qb_ipcc_zc_alloc.header.size = sizeof (mar_req_qb_ipcc_zc_alloc_t);
-	req_qb_ipcc_zc_alloc.header.id = ZC_ALLOC_HEADER;
-	req_qb_ipcc_zc_alloc.map_size = map_size;
-	strcpy (req_qb_ipcc_zc_alloc.path_to_file, path);
-
-
-	iovec.iov_base = (void *)&req_qb_ipcc_zc_alloc;
-	iovec.iov_len = sizeof (mar_req_qb_ipcc_zc_alloc_t);
-
-	res = qb_ipcc_msg_send_reply_receive (
-		handle,
-		&iovec,
-		1,
-		&res_qb_ipcs_zc_alloc,
-		sizeof (qb_ipc_response_header_t));
-
-	hdr = (struct qb_ipcs_zc_header *)buf;
-	hdr->map_size = map_size;
-	*buffer = ((char *)buf) + sizeof (struct qb_ipcs_zc_header);
-
-	qb_hdb_handle_put (&ipc_hdb, handle);
-	return (res);
-}
-
-int32_t
-qb_ipcc_zcb_free (
-	qb_hdb_handle_t handle,
-	void *buffer)
-{
-	struct ipc_instance *ipc_instance;
-	mar_req_qb_ipcc_zc_free_t req_qb_ipcc_zc_free;
-	qb_ipc_response_header_t res_qb_ipcs_zc_free;
-	struct iovec iovec;
-	unsigned int res;
-	struct qb_ipcs_zc_header *header = (struct qb_ipcs_zc_header *)((char *)buffer - sizeof (struct qb_ipcs_zc_header));
-
-	res = qb_hdb_handle_get (&ipc_hdb, handle, (void **)&ipc_instance);
-	if (res != 0) {
-		return (res);
-	}
-
-	req_qb_ipcc_zc_free.header.size = sizeof (mar_req_qb_ipcc_zc_free_t);
-	req_qb_ipcc_zc_free.header.id = ZC_FREE_HEADER;
-	req_qb_ipcc_zc_free.map_size = header->map_size;
-	req_qb_ipcc_zc_free.server_address = header->server_address;
-
-	iovec.iov_base = (void *)&req_qb_ipcc_zc_free;
-	iovec.iov_len = sizeof (mar_req_qb_ipcc_zc_free_t);
-
-	res = qb_ipcc_msg_send_reply_receive (
-		handle,
-		&iovec,
-		1,
-		&res_qb_ipcs_zc_free,
-		sizeof (qb_ipc_response_header_t));
-
-	munmap ((void *)header, header->map_size);
-
-	qb_hdb_handle_put (&ipc_hdb, handle);
-
-	return (res);
-}
-
-int32_t
-qb_ipcc_zcb_msg_send_reply_receive (
-	qb_hdb_handle_t handle,
-        void *msg,
-        void *res_msg,
-        size_t res_len)
-{
-	struct ipc_instance *ipc_instance;
-	mar_req_qb_ipcc_zc_execute_t req_qb_ipcc_zc_execute;
-	struct qb_ipcs_zc_header *hdr;
-	struct iovec iovec;
-	int32_t res;
-
-	res = qb_hdb_handle_get (&ipc_hdb, handle, (void **)&ipc_instance);
-	if (res != 0) {
-		return (res);
-	}
-	hdr = (struct qb_ipcs_zc_header *)(((char *)msg) - sizeof (struct qb_ipcs_zc_header));
-
-	req_qb_ipcc_zc_execute.header.size = sizeof (mar_req_qb_ipcc_zc_execute_t);
-	req_qb_ipcc_zc_execute.header.id = ZC_EXECUTE_HEADER;
-	req_qb_ipcc_zc_execute.server_address = hdr->server_address;
-
-	iovec.iov_base = (void *)&req_qb_ipcc_zc_execute;
-	iovec.iov_len = sizeof (mar_req_qb_ipcc_zc_execute_t);
-
-	res = qb_ipcc_msg_send_reply_receive (
-		handle,
-		&iovec,
-		1,
-		res_msg,
-		res_len);
-
-	qb_hdb_handle_put (&ipc_hdb, handle);
-	return (res);
-}
diff --git a/lib/ipc/ipcs.c b/lib/ipc/ipcs.c
deleted file mode 100644
index 7a69047..0000000
--- a/lib/ipc/ipcs.c
+++ /dev/null
@@ -1,1795 +0,0 @@
-/*
- * Copyright (c) 2006-2009 Red Hat, Inc.
- *
- * All rights reserved.
- *
- * Author: Steven Dake (sdake@redhat.com)
- *
- * This software licensed under BSD license, the text of which follows:
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * - Redistributions of source code must retain the above copyright notice,
- *   this list of conditions and the following disclaimer.
- * - 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.
- * - Neither the name of the MontaVista Software, Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
- */
-
-#include <config.h>
-
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE 1
-#endif
-
-#include "os_base.h"
-#include <sys/mman.h>
-#include <sys/poll.h>
-#if defined(HAVE_GETPEERUCRED)
-#include <ucred.h>
-#endif
-#include <sys/shm.h>
-
-#include <qb/qblist.h>
-#include <qb/qbhdb.h>
-#include "ipc_int.h"
-#include <qb/qbipcs.h>
-
-//#define LOGSYS_UTILS_ONLY 1
-#include <syslog.h>
-//#include <qb/engine/logsys.h>
-
-#if _POSIX_THREAD_PROCESS_SHARED > 0
-#include <semaphore.h>
-#else
-#include <sys/sem.h>
-#endif
-
-#ifndef MSG_NOSIGNAL
-#define MSG_NOSIGNAL 0
-#endif
-
-#define SERVER_BACKLOG 5
-
-#define MSG_SEND_LOCKED		0
-#define MSG_SEND_UNLOCKED	1
-
-static struct qb_ipcs_init_state_v2 *api = NULL;
-
-QB_DECLARE_LIST_INIT (conn_info_qb_list_head);
-
-QB_DECLARE_LIST_INIT (conn_info_exit_qb_list_head);
-
-struct outq_item {
-	void *msg;
-	size_t mlen;
-	struct qb_list_head list;
-};
-
-struct zcb_mapped {
-	struct qb_list_head list;
-	void *addr;
-	size_t size;
-};
-
-#if _POSIX_THREAD_PROCESS_SHARED < 1
-#if defined(_SEM_SEMUN_UNDEFINED)
-union semun {
-	int val;
-	struct semid_ds *buf;
-	unsigned short int *array;
-	struct seminfo *__buf;
-};
-#endif
-#endif
-
-
-enum conn_state {
-	CONN_STATE_THREAD_INACTIVE = 0,
-	CONN_STATE_THREAD_ACTIVE = 1,
-	CONN_STATE_THREAD_REQUEST_EXIT = 2,
-	CONN_STATE_THREAD_DESTROYED = 3,
-	CONN_STATE_LIB_EXIT_CALLED = 4,
-	CONN_STATE_DISCONNECT_INACTIVE = 5
-};
-
-struct conn_info {
-	int fd;
-	pthread_t thread;
-	pid_t client_pid;
-	pthread_attr_t thread_attr;
-	unsigned int service;
-	enum conn_state state;
-	int notify_flow_control_enabled;
-	int flow_control_state;
-	int refcount;
-	qb_hdb_handle_t stats_handle;
-#if _POSIX_THREAD_PROCESS_SHARED < 1
-	key_t semkey;
-	int semid;
-#endif
-	unsigned int pending_semops;
-	pthread_mutex_t mutex;
-	struct control_buffer *control_buffer;
-	char *request_buffer;
-	char *response_buffer;
-	char *dispatch_buffer;
-	size_t control_size;
-	size_t request_size;
-	size_t response_size;
-	size_t dispatch_size;
-	struct qb_list_head outq_head;
-	void *private_data;
-	struct qb_list_head list;
-	char setup_msg[sizeof (mar_req_setup_t)];
-	unsigned int setup_bytes_read;
-	struct qb_list_head zcb_mapped_qb_list_head;
-	char *sending_allowed_private_data[64];
-};
-
-static int shared_mem_dispatch_bytes_left (const struct conn_info *conn_info);
-
-static void outq_flush (struct conn_info *conn_info);
-
-static int priv_change (struct conn_info *conn_info);
-
-static void ipc_disconnect (struct conn_info *conn_info);
-
-static void msg_send (void *conn, const struct iovec *iov, unsigned int iov_len,
-		      int locked);
-
-static void _qb_ipc_init(void);
-
-#define log_printf(level, format, args...) \
-do { \
-        api->log_printf ( level, \
-                /*LOGSYS_ENCODE_RECID(level, */\
-                                    /*api->log_subsys_id,*/ \
-                                    /*LOGSYS_RECID_LOG),*/ \
-                __FUNCTION__, __FILE__, __LINE__, \
-                (const char *)format, ##args); \
-} while (0)
-
-static qb_hdb_handle_t dummy_stats_create_connection (
-	const char *name,
-	pid_t pid,
-	int fd)
-{
-	return (0ULL);
-}
-
-static void dummy_stats_destroy_connection (
-	qb_hdb_handle_t handle)
-{
-}
-
-static void dummy_stats_update_value (
-	qb_hdb_handle_t handle,
-	const char *name,
-	const void *value,
-	size_t value_size)
-{
-}
-
-static void dummy_stats_increment_value (
-	qb_hdb_handle_t handle,
-	const char *name)
-{
-}
-
-static void sem_post_exit_thread (struct conn_info *conn_info)
-{
-#if _POSIX_THREAD_PROCESS_SHARED < 1
-	struct sembuf sop;
-#endif
-	int res;
-
-#if _POSIX_THREAD_PROCESS_SHARED > 0
-retry_semop:
-	res = sem_post (&conn_info->control_buffer->sem0);
-	if (res == -1 && errno == EINTR) {
-		api->stats_increment_value (conn_info->stats_handle, "sem_retry_count");
-		goto retry_semop;
-	}
-#else
-	sop.sem_num = 0;
-	sop.sem_op = 1;
-	sop.sem_flg = 0;
-
-retry_semop:
-	res = semop (conn_info->semid, &sop, 1);
-	if ((res == -1) && (errno == EINTR || errno == EAGAIN)) {
-		api->stats_increment_value (conn_info->stats_handle, "sem_retry_count");
-		goto retry_semop;
-	}
-#endif
-}
-
-static int
-memory_map (
-	const char *path,
-	size_t bytes,
-	void **buf)
-{
-	int fd;
-	void *addr_orig;
-	void *addr;
-	int res;
-
-	fd = open (path, O_RDWR, 0600);
-
-	unlink (path);
-
-	res = ftruncate (fd, bytes);
-
-	addr_orig = mmap (NULL, bytes, PROT_NONE,
-		MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
-
-	if (addr_orig == MAP_FAILED) {
-		return (-1);
-	}
-
-	addr = mmap (addr_orig, bytes, PROT_READ | PROT_WRITE,
-		MAP_FIXED | MAP_SHARED, fd, 0);
-
-	if (addr != addr_orig) {
-		return (-1);
-	}
-#ifdef QB_BSD
-	madvise(addr, bytes, MADV_NOSYNC);
-#endif
-
-	res = close (fd);
-	if (res) {
-		return (-1);
-	}
-	*buf = addr_orig;
-	return (0);
-}
-
-static int
-circular_memory_map (
-	const char *path,
-	size_t bytes,
-	void **buf)
-{
-	int fd;
-	void *addr_orig;
-	void *addr;
-	int res;
-
-	fd = open (path, O_RDWR, 0600);
-
-	unlink (path);
-
-	res = ftruncate (fd, bytes);
-
-	addr_orig = mmap (NULL, bytes << 1, PROT_NONE,
-		MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
-
-	if (addr_orig == MAP_FAILED) {
-		return (-1);
-	}
-
-	addr = mmap (addr_orig, bytes, PROT_READ | PROT_WRITE,
-		MAP_FIXED | MAP_SHARED, fd, 0);
-
-	if (addr != addr_orig) {
-		return (-1);
-	}
-#ifdef QB_BSD
-	madvise(addr_orig, bytes, MADV_NOSYNC);
-#endif
-
-	addr = mmap (((char *)addr_orig) + bytes,
-                  bytes, PROT_READ | PROT_WRITE,
-                  MAP_FIXED | MAP_SHARED, fd, 0);
-#ifdef QB_BSD
-	madvise(((char *)addr_orig) + bytes, bytes, MADV_NOSYNC);
-#endif
-
-	res = close (fd);
-	if (res) {
-		return (-1);
-	}
-	*buf = addr_orig;
-	return (0);
-}
-
-static inline int
-circular_memory_unmap (void *buf, size_t bytes)
-{
-	int res;
-
-	res = munmap (buf, bytes << 1);
-
-	return (res);
-}
-
-static inline int zcb_free (struct zcb_mapped *zcb_mapped)
-{
-	unsigned int res;
-
-	res = munmap (zcb_mapped->addr, zcb_mapped->size);
-	qb_list_del (&zcb_mapped->list);
-	free (zcb_mapped);
-	return (res);
-}
-
-static inline int zcb_by_addr_free (struct conn_info *conn_info, void *addr)
-{
-	struct qb_list_head *list;
-	struct zcb_mapped *zcb_mapped;
-	unsigned int res = 0;
-
-	for (list = conn_info->zcb_mapped_qb_list_head.next;
-		list != &conn_info->zcb_mapped_qb_list_head; list = list->next) {
-
-		zcb_mapped = qb_list_entry (list, struct zcb_mapped, list);
-
-		if (zcb_mapped->addr == addr) {
-			res = zcb_free (zcb_mapped);
-			break;
-		}
-
-	}
-	return (res);
-}
-
-static inline int zcb_all_free (
-	struct conn_info *conn_info)
-{
-	struct qb_list_head *list;
-	struct zcb_mapped *zcb_mapped;
-
-	for (list = conn_info->zcb_mapped_qb_list_head.next;
-		list != &conn_info->zcb_mapped_qb_list_head;) {
-
-		zcb_mapped = qb_list_entry (list, struct zcb_mapped, list);
-
-		list = list->next;
-
-		zcb_free (zcb_mapped);
-	}
-	return (0);
-}
-
-static inline int zcb_alloc (
-	struct conn_info *conn_info,
-	const char *path_to_file,
-	size_t size,
-	void **addr)
-{
-	struct zcb_mapped *zcb_mapped;
-	unsigned int res;
-
-	zcb_mapped = malloc (sizeof (struct zcb_mapped));
-	if (zcb_mapped == NULL) {
-		return (-1);
-	}
-
-	res = memory_map (
-		path_to_file,
-		size,
-		addr);
-	if (res == -1) {
-		free (zcb_mapped);
-		return (-1);
-	}
-
-	qb_list_init (&zcb_mapped->list);
-	zcb_mapped->addr = *addr;
-	zcb_mapped->size = size;
-	qb_list_add_tail (&zcb_mapped->list, &conn_info->zcb_mapped_qb_list_head);
-	return (0);
-}
-
-static int ipc_thread_active (void *conn)
-{
-	struct conn_info *conn_info = (struct conn_info *)conn;
-	int retval = 0;
-
-	pthread_mutex_lock (&conn_info->mutex);
-	if (conn_info->state == CONN_STATE_THREAD_ACTIVE) {
-		retval = 1;
-	}
-	pthread_mutex_unlock (&conn_info->mutex);
-	return (retval);
-}
-
-static int ipc_thread_exiting (void *conn)
-{
-	struct conn_info *conn_info = (struct conn_info *)conn;
-	int retval = 1;
-
-	pthread_mutex_lock (&conn_info->mutex);
-	if (conn_info->state == CONN_STATE_THREAD_INACTIVE) {
-		retval = 0;
-	} else
-	if (conn_info->state == CONN_STATE_THREAD_ACTIVE) {
-		retval = 0;
-	}
-	pthread_mutex_unlock (&conn_info->mutex);
-	return (retval);
-}
-
-/*
- * returns 0 if should be called again, -1 if finished
- */
-static inline int conn_info_destroy (struct conn_info *conn_info)
-{
-	unsigned int res;
-	void *retval;
-
-	qb_list_del (&conn_info->list);
-	qb_list_init (&conn_info->list);
-	qb_list_add (&conn_info->list, &conn_info_exit_qb_list_head);
-
-	if (conn_info->state == CONN_STATE_THREAD_REQUEST_EXIT) {
-		res = pthread_join (conn_info->thread, &retval);
-		conn_info->state = CONN_STATE_THREAD_DESTROYED;
-		return (0);
-	}
-
-	if (conn_info->state == CONN_STATE_THREAD_INACTIVE ||
-		conn_info->state == CONN_STATE_DISCONNECT_INACTIVE) {
-		qb_list_del (&conn_info->list);
-		close (conn_info->fd);
-		api->free (conn_info);
-		return (-1);
-	}
-
-	if (conn_info->state == CONN_STATE_THREAD_ACTIVE) {
-		sem_post_exit_thread (conn_info);
-		return (0);
-	}
-
-	api->serialize_lock ();
-	/*
-	 * Retry library exit function if busy
-	 */
-	if (conn_info->state == CONN_STATE_THREAD_DESTROYED) {
-		api->stats_destroy_connection (conn_info->stats_handle);
-		res = api->exit_fn_get (conn_info->service) (conn_info);
-		if (res == -1) {
-			api->serialize_unlock ();
-			return (0);
-		} else {
-			conn_info->state = CONN_STATE_LIB_EXIT_CALLED;
-		}
-	}
-
-	pthread_mutex_lock (&conn_info->mutex);
-	if (conn_info->refcount > 0) {
-		pthread_mutex_unlock (&conn_info->mutex);
-		api->serialize_unlock ();
-		return (0);
-	}
-	qb_list_del (&conn_info->list);
-	pthread_mutex_unlock (&conn_info->mutex);
-
-#if _POSIX_THREAD_PROCESS_SHARED > 0
-	sem_destroy (&conn_info->control_buffer->sem0);
-	sem_destroy (&conn_info->control_buffer->sem1);
-	sem_destroy (&conn_info->control_buffer->sem2);
-#else
-	semctl (conn_info->semid, 0, IPC_RMID);
-#endif
-	/*
-	 * Destroy shared memory segment and semaphore
-	 */
-	res = munmap ((void *)conn_info->control_buffer, conn_info->control_size);
-	res = munmap ((void *)conn_info->request_buffer, conn_info->request_size);
-	res = munmap ((void *)conn_info->response_buffer, conn_info->response_size);
-
-	/*
-	 * Free allocated data needed to retry exiting library IPC connection
-	 */
-	if (conn_info->private_data) {
-		api->free (conn_info->private_data);
-	}
-	close (conn_info->fd);
-	res = circular_memory_unmap (conn_info->dispatch_buffer, conn_info->dispatch_size);
-	zcb_all_free (conn_info);
-	api->free (conn_info);
-	api->serialize_unlock ();
-	return (-1);
-}
-
-union u {
-	uint64_t server_addr;
-	void *server_ptr;
-};
-
-static uint64_t void2serveraddr (void *server_ptr)
-{
-	union u u;
-
-	u.server_ptr = server_ptr;
-	return (u.server_addr);
-}
-
-static void *serveraddr2void (uint64_t server_addr)
-{
-	union u u;
-
-	u.server_addr = server_addr;
-	return (u.server_ptr);
-};
-
-static inline void zerocopy_operations_process (
-	struct conn_info *conn_info,
-	qb_ipc_request_header_t **header_out,
-	unsigned int *new_message)
-{
-	qb_ipc_request_header_t *header;
-
-	header = (qb_ipc_request_header_t *)conn_info->request_buffer;
-	if (header->id == ZC_ALLOC_HEADER) {
-		mar_req_qb_ipcc_zc_alloc_t *hdr = (mar_req_qb_ipcc_zc_alloc_t *)header;
-		qb_ipc_response_header_t res_header;
-		void *addr = NULL;
-		struct qb_ipcs_zc_header *zc_header;
-		unsigned int res;
-
-		res = zcb_alloc (conn_info, hdr->path_to_file, hdr->map_size,
-			&addr);
-
-		zc_header = (struct qb_ipcs_zc_header *)addr;
-		zc_header->server_address = void2serveraddr(addr);
-
-		res_header.size = sizeof (qb_ipc_response_header_t);
-		res_header.id = 0;
-		qb_ipcs_response_send (
-			conn_info, &res_header,
-			res_header.size);
-		*new_message = 0;
-		return;
-	} else
-	if (header->id == ZC_FREE_HEADER) {
-		mar_req_qb_ipcc_zc_free_t *hdr = (mar_req_qb_ipcc_zc_free_t *)header;
-		qb_ipc_response_header_t res_header;
-		void *addr = NULL;
-
-		addr = serveraddr2void (hdr->server_address);
-
-		zcb_by_addr_free (conn_info, addr);
-
-		res_header.size = sizeof (qb_ipc_response_header_t);
-		res_header.id = 0;
-		qb_ipcs_response_send (
-			conn_info, &res_header,
-			res_header.size);
-
-		*new_message = 0;
-		return;
-	} else
-	if (header->id == ZC_EXECUTE_HEADER) {
-		mar_req_qb_ipcc_zc_execute_t *hdr = (mar_req_qb_ipcc_zc_execute_t *)header;
-
-		header = (qb_ipc_request_header_t *)(((char *)serveraddr2void(hdr->server_address) + sizeof (struct qb_ipcs_zc_header)));
-	}
-	*header_out = header;
-	*new_message = 1;
-}
-
-static void *pthread_ipc_consumer (void *conn)
-{
-	struct conn_info *conn_info = (struct conn_info *)conn;
-#if _POSIX_THREAD_PROCESS_SHARED < 1
-	struct sembuf sop;
-#endif
-	int res;
-	qb_ipc_request_header_t *header;
-	qb_ipc_response_header_t qb_ipc_response_header;
-	int send_ok;
-	unsigned int new_message;
-
-#if defined(HAVE_PTHREAD_SETSCHEDPARAM) && defined(HAVE_SCHED_GET_PRIORITY_MAX)
-	if (api->sched_policy != 0) {
-		res = pthread_setschedparam (conn_info->thread,
-			api->sched_policy, api->sched_param);
-	}
-#endif
-
-	for (;;) {
-#if _POSIX_THREAD_PROCESS_SHARED > 0
-retry_semwait:
-		res = sem_wait (&conn_info->control_buffer->sem0);
-		if (ipc_thread_active (conn_info) == 0) {
-			qb_ipcs_refcount_dec (conn_info);
-			pthread_exit (0);
-		}
-		if ((res == -1) && (errno == EINTR)) {
-			api->stats_increment_value (conn_info->stats_handle, "sem_retry_count");
-			goto retry_semwait;
-		}
-#else
-
-		sop.sem_num = 0;
-		sop.sem_op = -1;
-		sop.sem_flg = 0;
-retry_semop:
-		res = semop (conn_info->semid, &sop, 1);
-		if (ipc_thread_active (conn_info) == 0) {
-			qb_ipcs_refcount_dec (conn_info);
-			pthread_exit (0);
-		}
-		if ((res == -1) && (errno == EINTR || errno == EAGAIN)) {
-			api->stats_increment_value (conn_info->stats_handle, "sem_retry_count");
-			goto retry_semop;
-		} else
-		if ((res == -1) && (errno == EINVAL || errno == EIDRM)) {
-			qb_ipcs_refcount_dec (conn_info);
-			pthread_exit (0);
-		}
-#endif
-
-		zerocopy_operations_process (conn_info, &header, &new_message);
-		/*
-		 * There is no new message to process, continue for loop
-		 */
-		if (new_message == 0) {
-			continue;
-		}
-
-		qb_ipcs_refcount_inc (conn);
-
-		send_ok = api->sending_allowed (conn_info->service,
-			header->id,
-			header,
-			conn_info->sending_allowed_private_data);
-
-		/*
-		 * This happens when the message contains some kind of invalid
-		 * parameter, such as an invalid size
-		 */
-		if (send_ok == -1) {
-			qb_ipc_response_header.size = sizeof (qb_ipc_response_header_t);
-			qb_ipc_response_header.id = 0;
-			qb_ipc_response_header.error = EINVAL;
-			qb_ipcs_response_send (conn_info,
-				&qb_ipc_response_header,
-				sizeof (qb_ipc_response_header_t));
-		} else 
-		if (send_ok) {
-			api->serialize_lock();
-			api->stats_increment_value (conn_info->stats_handle, "requests");
-			api->handler_fn_get (conn_info->service, header->id) (conn_info, header);
-			api->serialize_unlock();
-		} else {
-			/*
-			 * Overload, tell library to retry
-			 */
-			api->stats_increment_value (conn_info->stats_handle, "sem_retry_count");
-			qb_ipc_response_header.size = sizeof (qb_ipc_response_header_t);
-			qb_ipc_response_header.id = 0;
-			qb_ipc_response_header.error = EAGAIN;
-			qb_ipcs_response_send (conn_info,
-				&qb_ipc_response_header,
-				sizeof (qb_ipc_response_header_t));
-		}
-
-		api->sending_allowed_release (conn_info->sending_allowed_private_data);
-		qb_ipcs_refcount_dec (conn);
-	}
-	pthread_exit (0);
-}
-
-static int
-req_setup_send (
-	struct conn_info *conn_info,
-	int error)
-{
-	mar_res_setup_t res_setup;
-	unsigned int res;
-
-	res_setup.error = error;
-
-retry_send:
-	res = send (conn_info->fd, &res_setup, sizeof (mar_res_setup_t), MSG_WAITALL);
-	if (res == -1 && errno == EINTR) {
-		api->stats_increment_value (conn_info->stats_handle, "send_retry_count");
-		goto retry_send;
-	} else
-	if (res == -1 && errno == EAGAIN) {
-		api->stats_increment_value (conn_info->stats_handle, "send_retry_count");
-		goto retry_send;
-	}
-	return (0);
-}
-
-static int
-req_setup_recv (
-	struct conn_info *conn_info)
-{
-	int res;
-	struct msghdr msg_recv;
-	struct iovec iov_recv;
-	int authenticated = 0;
-
-#ifdef QB_LINUX
-	struct cmsghdr *cmsg;
-	char cmsg_cred[CMSG_SPACE (sizeof (struct ucred))];
-	int off = 0;
-	int on = 1;
-	struct ucred *cred;
-#endif
-
-	msg_recv.msg_iov = &iov_recv;
-	msg_recv.msg_iovlen = 1;
-	msg_recv.msg_name = 0;
-	msg_recv.msg_namelen = 0;
-#ifdef QB_LINUX
-	msg_recv.msg_control = (void *)cmsg_cred;
-	msg_recv.msg_controllen = sizeof (cmsg_cred);
-#endif
-#ifdef QB_SOLARIS
-	msg_recv.msg_accrights = 0;
-	msg_recv.msg_accrightslen = 0;
-#endif /* QB_SOLARIS */
-
-	iov_recv.iov_base = &conn_info->setup_msg[conn_info->setup_bytes_read];
-	iov_recv.iov_len = sizeof (mar_req_setup_t) - conn_info->setup_bytes_read;
-#ifdef QB_LINUX
-	setsockopt(conn_info->fd, SOL_SOCKET, SO_PASSCRED, &on, sizeof (on));
-#endif
-
-retry_recv:
-	res = recvmsg (conn_info->fd, &msg_recv, MSG_NOSIGNAL);
-	if (res == -1 && errno == EINTR) {
-		api->stats_increment_value (conn_info->stats_handle, "recv_retry_count");
-		goto retry_recv;
-	} else
-	if (res == -1 && errno != EAGAIN) {
-		return (0);
-	} else
-	if (res == 0) {
-#if defined(QB_SOLARIS) || defined(QB_BSD) || defined(QB_DARWIN)
-		/* On many OS poll never return POLLHUP or POLLERR.
-		 * EOF is detected when recvmsg return 0.
-		 */
-		ipc_disconnect (conn_info);
-		return 0;
-#else
-		return (-1);
-#endif
-	}
-	conn_info->setup_bytes_read += res;
-
-/*
- * currently support getpeerucred, getpeereid, and SO_PASSCRED credential
- * retrieval mechanisms for various Platforms
- */
-#ifdef HAVE_GETPEERUCRED
-/*
- * Solaris and some BSD systems
- */
-	{
-		ucred_t *uc = NULL;
-		uid_t euid = -1;
-		gid_t egid = -1;
-
-		if (getpeerucred (conn_info->fd, &uc) == 0) {
-			euid = ucred_geteuid (uc);
-			egid = ucred_getegid (uc);
-			conn_info->client_pid = ucred_getpid (uc);
-			if (api->security_valid (euid, egid)) {
-				authenticated = 1;
-			}
-			ucred_free(uc);
-		}
-	}
-#elif HAVE_GETPEEREID
-/*
- * Usually MacOSX systems
- */
-
-	{
-		uid_t euid;
-		gid_t egid;
-
-		/*
-		 * TODO get the peer's pid.
-		 * conn_info->client_pid = ?;
-		 */
-		euid = -1;
-		egid = -1;
-		if (getpeereid (conn_info->fd, &euid, &egid) == 0) {
-			if (api->security_valid (euid, egid)) {
-				authenticated = 1;
-			}
-		}
-	}
-
-#elif SO_PASSCRED
-/*
- * Usually Linux systems
- */
-	cmsg = CMSG_FIRSTHDR (&msg_recv);
-	assert (cmsg);
-	cred = (struct ucred *)CMSG_DATA (cmsg);
-	if (cred) {
-		conn_info->client_pid = cred->pid;
-		if (api->security_valid (cred->uid, cred->gid)) {
-			authenticated = 1;
-		}
-	}
-
-#else /* no credentials */
-	authenticated = 1;
- 	log_printf (LOG_ERR, "Platform does not support IPC authentication.  Using no authentication\n");
-#endif /* no credentials */
-
-	if (authenticated == 0) {
-		log_printf (LOG_ERR, "Invalid IPC credentials.\n");
-		ipc_disconnect (conn_info);
-		return (-1);
- 	}
-
-	if (conn_info->setup_bytes_read == sizeof (mar_req_setup_t)) {
-#ifdef QB_LINUX
-		setsockopt(conn_info->fd, SOL_SOCKET, SO_PASSCRED,
-			&off, sizeof (off));
-#endif
-		return (1);
-	}
-	return (0);
-}
-
-static void ipc_disconnect (struct conn_info *conn_info)
-{
-	if (conn_info->state == CONN_STATE_THREAD_INACTIVE) {
-		conn_info->state = CONN_STATE_DISCONNECT_INACTIVE;
-		return;
-	}
-	if (conn_info->state != CONN_STATE_THREAD_ACTIVE) {
-		return;
-	}
-	pthread_mutex_lock (&conn_info->mutex);
-	conn_info->state = CONN_STATE_THREAD_REQUEST_EXIT;
-	pthread_mutex_unlock (&conn_info->mutex);
-
-	sem_post_exit_thread (conn_info);
-}
-
-static int conn_info_create (int fd)
-{
-	struct conn_info *conn_info;
-
-	conn_info = api->malloc (sizeof (struct conn_info));
-	if (conn_info == NULL) {
-		return (-1);
-	}
-	memset (conn_info, 0, sizeof (struct conn_info));
-
-	conn_info->fd = fd;
-	conn_info->client_pid = 0;
-	conn_info->service = SOCKET_SERVICE_INIT;
-	conn_info->state = CONN_STATE_THREAD_INACTIVE;
-	qb_list_init (&conn_info->outq_head);
-	qb_list_init (&conn_info->list);
-	qb_list_init (&conn_info->zcb_mapped_qb_list_head);
-	qb_list_add (&conn_info->list, &conn_info_qb_list_head);
-
-	api->poll_dispatch_add (fd, conn_info);
-
-	return (0);
-}
-
-#if defined(QB_LINUX) || defined(QB_SOLARIS)
-/* SUN_LEN is broken for abstract namespace
- */
-#define QB_SUN_LEN(a) sizeof(*(a))
-#else
-#define QB_SUN_LEN(a) SUN_LEN(a)
-#endif
-
-
-/*
- * Exported functions
- */
-extern void qb_ipcs_ipc_init_v2 (
-	struct qb_ipcs_init_state_v2 *init_state_v2)
-{
-	api = init_state_v2;
-	api->old_log_printf	= NULL;
-
-	log_printf (LOG_DEBUG, "you are using ipc api v2\n");
-	_qb_ipc_init ();
-}
-
-extern void qb_ipcs_ipc_init (
-        struct qb_ipcs_init_state *init_state)
-{
-	api = calloc (sizeof(struct qb_ipcs_init_state_v2), 1);
-	/* v2 api */
-	api->stats_create_connection	= dummy_stats_create_connection;
-	api->stats_destroy_connection	= dummy_stats_destroy_connection;
-	api->stats_update_value		= dummy_stats_update_value;
-	api->stats_increment_value	= dummy_stats_increment_value;
-	api->log_printf			= NULL;
-
-	/* v1 api */
-	api->socket_name		= init_state->socket_name;
-	api->sched_policy		= init_state->sched_policy;
-	api->sched_param		= init_state->sched_param;
-	api->malloc			= init_state->malloc;
-	api->free			= init_state->free;
-	api->old_log_printf		= init_state->log_printf;
-	api->fatal_error		= init_state->fatal_error;
-	api->security_valid		= init_state->security_valid;
-	api->service_available		= init_state->service_available;
-	api->private_data_size_get	= init_state->private_data_size_get;
-	api->serialize_lock		= init_state->serialize_lock;
-	api->serialize_unlock		= init_state->serialize_unlock;
-	api->sending_allowed		= init_state->sending_allowed;
-	api->sending_allowed_release	= init_state->sending_allowed_release;
-	api->poll_accept_add		= init_state->poll_accept_add;
-	api->poll_dispatch_add		= init_state->poll_dispatch_add;
-	api->poll_dispatch_modify	= init_state->poll_dispatch_modify;
-	api->init_fn_get		= init_state->init_fn_get;
-	api->exit_fn_get		= init_state->exit_fn_get;
-	api->handler_fn_get		= init_state->handler_fn_get;
-
-	log_printf (LOG_DEBUG, "you are using ipc api v1\n");
-
-	_qb_ipc_init ();
-}
-
-static void _qb_ipc_init(void)
-{
-	int server_fd;
-	struct sockaddr_un un_addr;
-	int res;
-
-	/*
-	 * Create socket for IPC clients, name socket, listen for connections
-	 */
-#if defined(QB_SOLARIS)
-	server_fd = socket (PF_UNIX, SOCK_STREAM, 0);
-#else
-	server_fd = socket (PF_LOCAL, SOCK_STREAM, 0);
-#endif
-	if (server_fd == -1) {
-		log_printf (LOG_CRIT, "Cannot create client connections socket.\n");
-		api->fatal_error ("Can't create library listen socket");
-	};
-
-	res = fcntl (server_fd, F_SETFL, O_NONBLOCK);
-	if (res == -1) {
-		char error_str[100];
-		strerror_r (errno, error_str, 100);
-		log_printf (LOG_CRIT, "Could not set non-blocking operation on server socket: %s\n", error_str);
-		api->fatal_error ("Could not set non-blocking operation on server socket");
-	}
-
-	memset (&un_addr, 0, sizeof (struct sockaddr_un));
-	un_addr.sun_family = AF_UNIX;
-#if defined(QB_BSD) || defined(QB_DARWIN)
-	un_addr.sun_len = SUN_LEN(&un_addr);
-#endif
-
-#if defined(QB_LINUX)
-	sprintf (un_addr.sun_path + 1, "%s", api->socket_name);
-#else
-	{
-		struct stat stat_out;
-		res = stat (SOCKETDIR, &stat_out);
-		if (res == -1 || (res == 0 && !S_ISDIR(stat_out.st_mode))) {
-			log_printf (LOG_CRIT, "Required directory not present %s\n", SOCKETDIR);
-			api->fatal_error ("Please create required directory.");
-		}
-		sprintf (un_addr.sun_path, "%s/%s", SOCKETDIR, api->socket_name);
-		unlink (un_addr.sun_path);
-	}
-#endif
-
-	res = bind (server_fd, (struct sockaddr *)&un_addr, QB_SUN_LEN(&un_addr));
-	if (res) {
-		char error_str[100];
-		strerror_r (errno, error_str, 100);
-		log_printf (LOG_CRIT, "Could not bind AF_UNIX (%s): %s.\n", un_addr.sun_path, error_str);
-		api->fatal_error ("Could not bind to AF_UNIX socket\n");
-	}
-
-	/*
-	 * Allow eveyrone to write to the socket since the IPC layer handles
-	 * security automatically
-	 */
-#if !defined(QB_LINUX)
-	res = chmod (un_addr.sun_path, S_IRWXU|S_IRWXG|S_IRWXO);
-#endif
-	listen (server_fd, SERVER_BACKLOG);
-
-	/*
-	 * Setup connection dispatch routine
-	 */
-	api->poll_accept_add (server_fd);
-}
-
-void qb_ipcs_ipc_exit (void)
-{
-	struct qb_list_head *list;
-	struct conn_info *conn_info;
-	unsigned int res;
-
-	for (list = conn_info_qb_list_head.next; list != &conn_info_qb_list_head;
-		list = list->next) {
-
-		conn_info = qb_list_entry (list, struct conn_info, list);
-
-		if (conn_info->state != CONN_STATE_THREAD_ACTIVE)
-			continue;
-
-		ipc_disconnect (conn_info);
-
-#if _POSIX_THREAD_PROCESS_SHARED > 0
-		sem_destroy (&conn_info->control_buffer->sem0);
-		sem_destroy (&conn_info->control_buffer->sem1);
-		sem_destroy (&conn_info->control_buffer->sem2);
-#else
-		semctl (conn_info->semid, 0, IPC_RMID);
-#endif
-
-		/*
-		 * Unmap memory segments
-		 */
-		res = munmap ((void *)conn_info->control_buffer,
-			conn_info->control_size);
-		res = munmap ((void *)conn_info->request_buffer,
-			conn_info->request_size);
-		res = munmap ((void *)conn_info->response_buffer,
-			conn_info->response_size);
-		res = circular_memory_unmap (conn_info->dispatch_buffer,
-			conn_info->dispatch_size);
-	}
-}
-
-int qb_ipcs_ipc_service_exit (unsigned int service)
-{
-	struct qb_list_head *list, *list_next;
-	struct conn_info *conn_info;
-
-	for (list = conn_info_qb_list_head.next; list != &conn_info_qb_list_head;
-		list = list_next) {
-
-		list_next = list->next;
-
-		conn_info = qb_list_entry (list, struct conn_info, list);
-
-		if (conn_info->service != service ||
-		    (conn_info->state != CONN_STATE_THREAD_ACTIVE && conn_info->state != CONN_STATE_THREAD_REQUEST_EXIT)) {
-			continue;
-		}
-
-		ipc_disconnect (conn_info);
-		api->poll_dispatch_destroy (conn_info->fd, NULL);
-		while (conn_info_destroy (conn_info) != -1)
-			;
-
-		/*
-		 * We will return to prevent token loss. Schedwrk will call us again.
-		 */
-		return (-1);
-	}
-
-	/*
-	 * No conn info left in active list. We will traverse thru exit list. If there is any
-	 * conn_info->service == service, we will wait to proper end -> return -1
-	 */
-
-	for (list = conn_info_exit_qb_list_head.next; list != &conn_info_exit_qb_list_head; list = list->next) {
-		conn_info = qb_list_entry (list, struct conn_info, list);
-
-		if (conn_info->service == service) {
-			return (-1);
-		}
-	}
-
-	return (0);
-}
-
-/*
- * Get the conn info private data
- */
-void *qb_ipcs_private_data_get (void *conn)
-{
-	struct conn_info *conn_info = (struct conn_info *)conn;
-
-	return (conn_info->private_data);
-}
-
-int qb_ipcs_response_send (void *conn, const void *msg, size_t mlen)
-{
-	struct conn_info *conn_info = (struct conn_info *)conn;
-#if _POSIX_THREAD_PROCESS_SHARED < 1
-	struct sembuf sop;
-#endif
-	int res;
-
-	memcpy (conn_info->response_buffer, msg, mlen);
-
-#if _POSIX_THREAD_PROCESS_SHARED > 0
-	res = sem_post (&conn_info->control_buffer->sem1);
-	if (res == -1) {
-		return (-1);
-	}
-#else
-	sop.sem_num = 1;
-	sop.sem_op = 1;
-	sop.sem_flg = 0;
-
-retry_semop:
-	res = semop (conn_info->semid, &sop, 1);
-	if ((res == -1) && (errno == EINTR || errno == EAGAIN)) {
-		api->stats_increment_value (conn_info->stats_handle, "sem_retry_count");
-		goto retry_semop;
-	} else
-	if ((res == -1) && (errno == EINVAL || errno == EIDRM)) {
-		return (0);
-	}
-#endif
-	api->stats_increment_value (conn_info->stats_handle, "responses");
-	return (0);
-}
-
-int qb_ipcs_response_iov_send (void *conn, const struct iovec *iov, unsigned int iov_len)
-{
-	struct conn_info *conn_info = (struct conn_info *)conn;
-#if _POSIX_THREAD_PROCESS_SHARED < 1
-	struct sembuf sop;
-#endif
-	int res;
-	int write_idx = 0;
-	int i;
-
-	for (i = 0; i < iov_len; i++) {
-		memcpy (&conn_info->response_buffer[write_idx],
-			iov[i].iov_base, iov[i].iov_len);
-		write_idx += iov[i].iov_len;
-	}
-
-#if _POSIX_THREAD_PROCESS_SHARED > 0
-	res = sem_post (&conn_info->control_buffer->sem1);
-	if (res == -1) {
-		return (-1);
-	}
-#else
-	sop.sem_num = 1;
-	sop.sem_op = 1;
-	sop.sem_flg = 0;
-
-retry_semop:
-	res = semop (conn_info->semid, &sop, 1);
-	if ((res == -1) && (errno == EINTR || errno == EAGAIN)) {
-		api->stats_increment_value (conn_info->stats_handle, "sem_retry_count");
-		goto retry_semop;
-	} else
-	if ((res == -1) && (errno == EINVAL || errno == EIDRM)) {
-		return (0);
-	}
-#endif
-	api->stats_increment_value (conn_info->stats_handle, "responses");
-	return (0);
-}
-
-static int shared_mem_dispatch_bytes_left (const struct conn_info *conn_info)
-{
-	unsigned int n_read;
-	unsigned int n_write;
-	unsigned int bytes_left;
-
-	n_read = conn_info->control_buffer->read;
-	n_write = conn_info->control_buffer->write;
-
-	if (n_read <= n_write) {
-		bytes_left = conn_info->dispatch_size - n_write + n_read;
-	} else {
-		bytes_left = n_read - n_write;
-	}
-	if (bytes_left > 0) {
-		bytes_left--;
-	}
-
-	return (bytes_left);
-}
-
-static void memcpy_dwrap (struct conn_info *conn_info, void *msg, unsigned int len)
-{
-	unsigned int write_idx;
-
-	write_idx = conn_info->control_buffer->write;
-
-	memcpy (&conn_info->dispatch_buffer[write_idx], msg, len);
-	conn_info->control_buffer->write = (write_idx + len) % conn_info->dispatch_size;
-}
-
-/**
- * simulate the behaviour in qb_ipcc.c
- */
-static int flow_control_event_send (struct conn_info *conn_info, char event)
-{
-	int new_fc = 0;
-
-	if (event == MESSAGE_RES_OUTQ_NOT_EMPTY ||
-		event == MESSAGE_RES_ENABLE_FLOWCONTROL) {
-		new_fc = 1;
-	}
-
-	if (conn_info->flow_control_state != new_fc) {
-		if (new_fc == 1) {
-			log_printf (LOG_INFO, "Enabling flow control for %d, event %d\n",
-				conn_info->client_pid, event);
-		} else {
-			log_printf (LOG_INFO, "Disabling flow control for %d, event %d\n",
-				conn_info->client_pid, event);
-		}
-		conn_info->flow_control_state = new_fc;
-		api->stats_update_value (conn_info->stats_handle, "flow_control",
-			&conn_info->flow_control_state,
-			sizeof(conn_info->flow_control_state));
-		api->stats_increment_value (conn_info->stats_handle, "flow_control_count");
-	}
-
-	return send (conn_info->fd, &event, 1, MSG_NOSIGNAL);
-}
-
-static void msg_send (void *conn, const struct iovec *iov, unsigned int iov_len,
-		      int locked)
-{
-	struct conn_info *conn_info = (struct conn_info *)conn;
-#if _POSIX_THREAD_PROCESS_SHARED < 1
-	struct sembuf sop;
-#endif
-	int res;
-	int i;
-
-	for (i = 0; i < iov_len; i++) {
-		memcpy_dwrap (conn_info, iov[i].iov_base, iov[i].iov_len);
-	}
-
-	if (qb_list_empty (&conn_info->outq_head))
-		res = flow_control_event_send (conn_info, MESSAGE_RES_OUTQ_EMPTY);
-	else
-		res = flow_control_event_send (conn_info, MESSAGE_RES_OUTQ_NOT_EMPTY);
-
-	if (res == -1 && errno == EAGAIN) {
-		if (locked == 0) {
-			pthread_mutex_lock (&conn_info->mutex);
-		}
-		conn_info->pending_semops += 1;
-		if (locked == 0) {
-			pthread_mutex_unlock (&conn_info->mutex);
-		}
-		api->poll_dispatch_modify (conn_info->fd,
-			POLLIN|POLLOUT|POLLNVAL);
-	} else
-	if (res == -1) {
-		ipc_disconnect (conn_info);
-	}
-#if _POSIX_THREAD_PROCESS_SHARED > 0
-	res = sem_post (&conn_info->control_buffer->sem2);
-#else
-	sop.sem_num = 2;
-	sop.sem_op = 1;
-	sop.sem_flg = 0;
-
-retry_semop:
-	res = semop (conn_info->semid, &sop, 1);
-	if ((res == -1) && (errno == EINTR || errno == EAGAIN)) {
-		api->stats_increment_value (conn_info->stats_handle, "sem_retry_count");
-		goto retry_semop;
-	} else
-	if ((res == -1) && (errno == EINVAL || errno == EIDRM)) {
-		return;
-	}
-#endif
-	api->stats_increment_value (conn_info->stats_handle, "dispatched");
-}
-
-static void outq_flush (struct conn_info *conn_info) {
-	struct qb_list_head *list, *list_next;
-	struct outq_item *outq_item;
-	unsigned int bytes_left;
-	struct iovec iov;
-	int res;
-
-	pthread_mutex_lock (&conn_info->mutex);
-	if (qb_list_empty (&conn_info->outq_head)) {
-		res = flow_control_event_send (conn_info, MESSAGE_RES_OUTQ_FLUSH_NR);
-		pthread_mutex_unlock (&conn_info->mutex);
-		return;
-	}
-	for (list = conn_info->outq_head.next;
-		list != &conn_info->outq_head; list = list_next) {
-
-		list_next = list->next;
-		outq_item = qb_list_entry (list, struct outq_item, list);
-		bytes_left = shared_mem_dispatch_bytes_left (conn_info);
-		if (bytes_left > outq_item->mlen) {
-			iov.iov_base = outq_item->msg;
-			iov.iov_len = outq_item->mlen;
-			msg_send (conn_info, &iov, 1, MSG_SEND_UNLOCKED);
-			qb_list_del (list);
-			api->free (iov.iov_base);
-			api->free (outq_item);
-			api->stats_decrement_value (conn_info->stats_handle, "queue_size");
-		} else {
-			break;
-		}
-	}
-	pthread_mutex_unlock (&conn_info->mutex);
-}
-
-static int priv_change (struct conn_info *conn_info)
-{
-	mar_req_priv_change req_priv_change;
-	unsigned int res;
-#if _POSIX_THREAD_PROCESS_SHARED < 1
-	union semun semun;
-	struct semid_ds ipc_set;
-	int i;
-#endif
-
-retry_recv:
-	res = recv (conn_info->fd, &req_priv_change,
-		sizeof (mar_req_priv_change),
-		MSG_NOSIGNAL);
-	if (res == -1 && errno == EINTR) {
-		api->stats_increment_value (conn_info->stats_handle, "recv_retry_count");
-		goto retry_recv;
-	}
-	if (res == -1 && errno == EAGAIN) {
-		api->stats_increment_value (conn_info->stats_handle, "recv_retry_count");
-		goto retry_recv;
-	}
-	if (res == -1 && errno != EAGAIN) {
-		return (-1);
-	}
-#if defined(QB_SOLARIS) || defined(QB_BSD) || defined(QB_DARWIN)
-	/* Error on socket, EOF is detected when recv return 0
-	 */
-	if (res == 0) {
-		return (-1);
-	}
-#endif
-
-#if _POSIX_THREAD_PROCESS_SHARED < 1
-	ipc_set.sem_perm.uid = req_priv_change.euid;
-	ipc_set.sem_perm.gid = req_priv_change.egid;
-	ipc_set.sem_perm.mode = 0600;
-
-	semun.buf = &ipc_set;
-
-	for (i = 0; i < 3; i++) {
-		res = semctl (conn_info->semid, 0, IPC_SET, semun);
-		if (res == -1) {
-			return (-1);
-		}
-	}
-#endif
-	return (0);
-}
-
-static void msg_send_or_queue (void *conn, const struct iovec *iov, unsigned int iov_len)
-{
-	struct conn_info *conn_info = (struct conn_info *)conn;
-	unsigned int bytes_left;
-	unsigned int bytes_msg = 0;
-	int i;
-	struct outq_item *outq_item;
-	char *write_buf = 0;
-
-	/*
-	 * Exit transmission if the connection is dead
-	 */
-	if (ipc_thread_active (conn) == 0) {
-		return;
-	}
-
-	bytes_left = shared_mem_dispatch_bytes_left (conn_info);
-	for (i = 0; i < iov_len; i++) {
-		bytes_msg += iov[i].iov_len;
-	}
-	if (bytes_left < bytes_msg || qb_list_empty (&conn_info->outq_head) == 0) {
-		outq_item = api->malloc (sizeof (struct outq_item));
-		if (outq_item == NULL) {
-			ipc_disconnect (conn);
-			return;
-		}
-		outq_item->msg = api->malloc (bytes_msg);
-		if (outq_item->msg == 0) {
-			api->free (outq_item);
-			ipc_disconnect (conn);
-			return;
-		}
-
-		write_buf = outq_item->msg;
-		for (i = 0; i < iov_len; i++) {
-			memcpy (write_buf, iov[i].iov_base, iov[i].iov_len);
-			write_buf += iov[i].iov_len;
-		}
-		outq_item->mlen = bytes_msg;
-		qb_list_init (&outq_item->list);
-		pthread_mutex_lock (&conn_info->mutex);
-		if (qb_list_empty (&conn_info->outq_head)) {
-			conn_info->notify_flow_control_enabled = 1;
-			api->poll_dispatch_modify (conn_info->fd,
-				POLLIN|POLLOUT|POLLNVAL);
-		}
-		qb_list_add_tail (&outq_item->list, &conn_info->outq_head);
-		pthread_mutex_unlock (&conn_info->mutex);
-		api->stats_increment_value (conn_info->stats_handle, "queue_size");
-		return;
-	}
-	msg_send (conn, iov, iov_len, MSG_SEND_LOCKED);
-}
-
-void qb_ipcs_refcount_inc (void *conn)
-{
-	struct conn_info *conn_info = (struct conn_info *)conn;
-
-	pthread_mutex_lock (&conn_info->mutex);
-	conn_info->refcount++;
-	pthread_mutex_unlock (&conn_info->mutex);
-}
-
-void qb_ipcs_refcount_dec (void *conn)
-{
-	struct conn_info *conn_info = (struct conn_info *)conn;
-
-	pthread_mutex_lock (&conn_info->mutex);
-	conn_info->refcount--;
-	pthread_mutex_unlock (&conn_info->mutex);
-}
-
-int qb_ipcs_dispatch_send (void *conn, const void *msg, size_t mlen)
-{
-	struct iovec iov;
-
-	iov.iov_base = (void *)msg;
-	iov.iov_len = mlen;
-
-	msg_send_or_queue (conn, &iov, 1);
-	return (0);
-}
-
-int qb_ipcs_dispatch_iov_send (void *conn, const struct iovec *iov, unsigned int iov_len)
-{
-	msg_send_or_queue (conn, iov, iov_len);
-	return (0);
-}
-
-int qb_ipcs_handler_accept (
-	int fd,
-	int revent,
-	void *data)
-{
-	socklen_t addrlen;
-	struct sockaddr_un un_addr;
-	int new_fd;
-#ifdef QB_LINUX
-	int on = 1;
-#endif
-	int res;
-
-	addrlen = sizeof (struct sockaddr_un);
-
-retry_accept:
-	new_fd = accept (fd, (struct sockaddr *)&un_addr, &addrlen);
-	if (new_fd == -1 && errno == EINTR) {
-		goto retry_accept;
-	}
-
-	if (new_fd == -1) {
-		char error_str[100];
-		strerror_r (errno, error_str, 100);
-		log_printf (LOG_ERR,
-			"Could not accept Library connection: %s\n", error_str);
-		return (0); /* This is an error, but -1 would indicate disconnect from poll loop */
-	}
-
-	res = fcntl (new_fd, F_SETFL, O_NONBLOCK);
-	if (res == -1) {
-		char error_str[100];
-		strerror_r (errno, error_str, 100);
-		log_printf (LOG_ERR,
-			"Could not set non-blocking operation on library connection: %s\n",
-			error_str);
-		close (new_fd);
-		return (0); /* This is an error, but -1 would indicate disconnect from poll loop */
-	}
-
-	/*
-	 * Valid accept
-	 */
-
-	/*
-	 * Request credentials of sender provided by kernel
-	 */
-#ifdef QB_LINUX
-	setsockopt(new_fd, SOL_SOCKET, SO_PASSCRED, &on, sizeof (on));
-#endif
-
-	res = conn_info_create (new_fd);
-	if (res != 0) {
-		close (new_fd);
-	}
-
-	return (0);
-}
-
-static char * pid_to_name (pid_t pid, char *out_name, size_t name_len)
-{
-	char *name;
-	char *rest;
-	FILE *fp;
-	char fname[32];
-	char buf[256];
-
-	snprintf (fname, 32, "/proc/%d/stat", pid);
-	fp = fopen (fname, "r");
-	if (!fp) {
-		return NULL;
-	}
-
-	if (fgets (buf, sizeof (buf), fp) == NULL) {
-		fclose (fp);
-		return NULL;
-	}
-	fclose (fp);
-
-	name = strrchr (buf, '(');
-	if (!name) {
-		return NULL;
-	}
-
-	/* move past the bracket */
-	name++;
-
-	rest = strrchr (buf, ')');
-
-	if (rest == NULL || rest[1] != ' ') {
-		return NULL;
-	}
-
-	*rest = '\0';
-	/* move past the NULL and space */
-	rest += 2;
-
-	/* copy the name */
-	strncpy (out_name, name, name_len);
-	out_name[name_len - 1] = '\0';
-	return out_name;
-}
-
-static void qb_ipcs_init_conn_stats (
-	struct conn_info *conn)
-{
-	char conn_name[42];
-	char proc_name[32];
-
-	if (conn->client_pid > 0) {
-		if (pid_to_name (conn->client_pid, proc_name, sizeof(proc_name)))
-			snprintf (conn_name, sizeof(conn_name), "%s:%d:%d", proc_name, conn->client_pid, conn->fd);
-		else
-			snprintf (conn_name, sizeof(conn_name), "%d:%d", conn->client_pid, conn->fd);
-	} else
-		snprintf (conn_name, sizeof(conn_name), "%d", conn->fd);
-
-	conn->stats_handle = api->stats_create_connection (conn_name, conn->client_pid, conn->fd);
-	api->stats_update_value (conn->stats_handle, "service_id",
-		&conn->service, sizeof(conn->service));
-}
-
-int qb_ipcs_handler_dispatch (
-	int fd,
-	int revent,
-	void *context)
-{
-	mar_req_setup_t *req_setup;
-	struct conn_info *conn_info = (struct conn_info *)context;
-	int res;
-	char buf;
-
-
-	if (ipc_thread_exiting (conn_info)) {
-		return conn_info_destroy (conn_info);
-	}
-
-	/*
-	 * If an error occurs, request exit
-	 */
-	if (revent & (POLLERR|POLLHUP)) {
-		ipc_disconnect (conn_info);
-		return (0);
-	}
-
-	/*
-	 * Read the header and process it
-	 */
-	if (conn_info->service == SOCKET_SERVICE_INIT && (revent & POLLIN)) {
-		/*
-		 * Receive in a nonblocking fashion the request
-		 * IF security invalid, send ERR_SECURITY, otherwise
-		 * send OK
-		 */
-		res = req_setup_recv (conn_info);
-		if (res == -1) {
-			req_setup_send (conn_info, EACCES);
-		}
-		if (res != 1) {
-			return (0);
-		}
-
-		pthread_mutex_init (&conn_info->mutex, NULL);
-		req_setup = (mar_req_setup_t *)conn_info->setup_msg;
-		/*
-		 * Is the service registered ?
-		 */
-		if (api->service_available (req_setup->service) == 0) {
-			req_setup_send (conn_info, EEXIST);
-			ipc_disconnect (conn_info);
-			return (0);
-		}
-		req_setup_send (conn_info, 0);
-
-#if _POSIX_THREAD_PROCESS_SHARED < 1
-		conn_info->semkey = req_setup->semkey;
-#endif
-		res = memory_map (
-			req_setup->control_file,
-			req_setup->control_size,
-			(void *)&conn_info->control_buffer);
-		conn_info->control_size = req_setup->control_size;
-
-		res = memory_map (
-			req_setup->request_file,
-			req_setup->request_size,
-			(void *)&conn_info->request_buffer);
-		conn_info->request_size = req_setup->request_size;
-
-		res = memory_map (
-			req_setup->response_file,
-			req_setup->response_size,
-			(void *)&conn_info->response_buffer);
-		conn_info->response_size = req_setup->response_size;
-
-		res = circular_memory_map (
-			req_setup->dispatch_file,
-			req_setup->dispatch_size,
-			(void *)&conn_info->dispatch_buffer);
-		conn_info->dispatch_size = req_setup->dispatch_size;
-
-		conn_info->service = req_setup->service;
-		conn_info->refcount = 0;
-		conn_info->notify_flow_control_enabled = 0;
-		conn_info->setup_bytes_read = 0;
-
-#if _POSIX_THREAD_PROCESS_SHARED < 1
-		conn_info->semid = semget (conn_info->semkey, 3, 0600);
-#endif
-		conn_info->pending_semops = 0;
-
-		/*
-		 * ipc thread is the only reference at startup
-		 */
-		conn_info->refcount = 1;
-		conn_info->state = CONN_STATE_THREAD_ACTIVE;
-
-		conn_info->private_data = api->malloc (api->private_data_size_get (conn_info->service));
-		memset (conn_info->private_data, 0,
-			api->private_data_size_get (conn_info->service));
-
-		api->init_fn_get (conn_info->service) (conn_info);
-
-		/* create stats objects */
-		qb_ipcs_init_conn_stats (conn_info);
-
-		pthread_attr_init (&conn_info->thread_attr);
-		/*
-		* IA64 needs more stack space then other arches
-		*/
-		#if defined(__ia64__)
-		pthread_attr_setstacksize (&conn_info->thread_attr, 400000);
-		#else
-		pthread_attr_setstacksize (&conn_info->thread_attr, 200000);
-		#endif
-
-		pthread_attr_setdetachstate (&conn_info->thread_attr, PTHREAD_CREATE_JOINABLE);
-		res = pthread_create (&conn_info->thread,
-			&conn_info->thread_attr,
-			pthread_ipc_consumer,
-			conn_info);
-
-		/*
-		 * Security check - disallow multiple configurations of
-		 * the ipc connection
-		 */
-		if (conn_info->service == SOCKET_SERVICE_INIT) {
-			conn_info->service = -1;
-		}
-	} else
-	if (revent & POLLIN) {
-		qb_ipcs_refcount_inc (conn_info);
-		res = recv (fd, &buf, 1, MSG_NOSIGNAL);
-		if (res == 1) {
-			switch (buf) {
-			case MESSAGE_REQ_OUTQ_FLUSH:
-				outq_flush (conn_info);
-				break;
-			case MESSAGE_REQ_CHANGE_EUID:
-				if (priv_change (conn_info) == -1) {
-					ipc_disconnect (conn_info);
-				}
-				break;
-			default:
-				res = 0;
-				break;
-			}
-		}
-#if defined(QB_SOLARIS) || defined(QB_BSD) || defined(QB_DARWIN)
-		/* On many OS poll never return POLLHUP or POLLERR.
-		 * EOF is detected when recvmsg return 0.
-		 */
-		if (res == 0) {
-			ipc_disconnect (conn_info);
-			qb_ipcs_refcount_dec (conn_info);
-			return (0);
-		}
-#endif
-		qb_ipcs_refcount_dec (conn_info);
-	}
-
-	qb_ipcs_refcount_inc (conn_info);
-	pthread_mutex_lock (&conn_info->mutex);
-	if ((conn_info->state == CONN_STATE_THREAD_ACTIVE) && (revent & POLLOUT)) {
-		if (qb_list_empty (&conn_info->outq_head))
-			buf = MESSAGE_RES_OUTQ_EMPTY;
-		else
-			buf = MESSAGE_RES_OUTQ_NOT_EMPTY;
-
-		for (; conn_info->pending_semops;) {
-			res = flow_control_event_send (conn_info, buf);
-			if (res == 1) {
-				conn_info->pending_semops--;
-			} else {
-				break;
-			}
-		}
-		if (conn_info->notify_flow_control_enabled) {
-			res = flow_control_event_send (conn_info, MESSAGE_RES_ENABLE_FLOWCONTROL);
-			if (res == 1) {
-				conn_info->notify_flow_control_enabled = 0;
-			}
-		}
-		if (conn_info->notify_flow_control_enabled == 0 &&
-			conn_info->pending_semops == 0) {
-
-			api->poll_dispatch_modify (conn_info->fd,
-				POLLIN|POLLNVAL);
-		}
-	}
-	pthread_mutex_unlock (&conn_info->mutex);
-	qb_ipcs_refcount_dec (conn_info);
-
-	return (0);
-}
-
diff --git a/lib/ipc/libqbipcc.versions b/lib/ipc/libqbipcc.versions
deleted file mode 100644
index e161d1f..0000000
--- a/lib/ipc/libqbipcc.versions
+++ /dev/null
@@ -1,16 +0,0 @@
-QB_IPCC_0.1 {
-	global:
-		qb_ipcc_service_connect;
-		qb_ipcc_service_disconnect;
-		qb_ipcc_dispatch_flow_control_get;
-		qb_ipcc_fd_get;
-		qb_ipcc_dispatch_get;
-		qb_ipcc_dispatch_put;
-		qb_ipcc_msg_send_reply_receive;
-		qb_ipcc_msg_send_reply_receive_in_buf_get;
-		qb_ipcc_msg_send_reply_receive_in_buf_put;
-		qb_ipcc_zcb_alloc;
-		qb_ipcc_zcb_free;
-		qb_ipcc_zcb_msg_send_reply_receive;
-	local: *;
-};
diff --git a/lib/ipc/libqbipcs.versions b/lib/ipc/libqbipcs.versions
deleted file mode 100644
index c2e72b0..0000000
--- a/lib/ipc/libqbipcs.versions
+++ /dev/null
@@ -1,16 +0,0 @@
-QB_IPCS_0.1 {
-	global:
-		qb_ipcs_ipc_init;
-		qb_ipcs_private_data_get;
-		qb_ipcs_response_send;
-		qb_ipcs_response_iov_send;
-		qb_ipcs_dispatch_send;
-		qb_ipcs_dispatch_iov_send;
-		qb_ipcs_refcount_inc;
-		qb_ipcs_refcount_dec;
-		qb_ipcs_ipc_exit;
-		qb_ipcs_ipc_service_exit;
-		qb_ipcs_handler_accept;
-		qb_ipcs_handler_dispatch;
-	local: *;
-};
diff --git a/lib/ipc_int.h b/lib/ipc_int.h
new file mode 100644
index 0000000..ecca917
--- /dev/null
+++ b/lib/ipc_int.h
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2009 Red Hat, Inc.
+ *
+ * All rights reserved.
+ *
+ * Author: Steven Dake (sdake@redhat.com)
+ *
+ * This software licensed under BSD license, the text of which follows:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - 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.
+ * - Neither the name of the MontaVista Software, Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
+ */
+#ifndef QB_IPC_IPC_H_DEFINED
+#define QB_IPC_IPC_H_DEFINED
+
+#include <unistd.h>
+#include "config.h"
+
+/*
+ * Darwin claims to support process shared synchronization
+ * but it really does not.  The unistd.h header file is wrong.
+ */
+#if defined(QB_DARWIN) || defined(__UCLIBC__)
+#undef _POSIX_THREAD_PROCESS_SHARED
+#define _POSIX_THREAD_PROCESS_SHARED -1
+#endif
+
+#ifndef _POSIX_THREAD_PROCESS_SHARED
+#define _POSIX_THREAD_PROCESS_SHARED -1
+#endif
+
+#if _POSIX_THREAD_PROCESS_SHARED > 0
+#include <semaphore.h>
+#endif
+
+enum req_init_types {
+	MESSAGE_REQ_RESPONSE_INIT = 0,
+	MESSAGE_REQ_DISPATCH_INIT = 1
+};
+
+#define MESSAGE_REQ_CHANGE_EUID		1
+#define MESSAGE_REQ_OUTQ_FLUSH		2
+
+#define MESSAGE_RES_OUTQ_EMPTY         0
+#define MESSAGE_RES_OUTQ_NOT_EMPTY     1
+#define MESSAGE_RES_ENABLE_FLOWCONTROL 2
+#define MESSAGE_RES_OUTQ_FLUSH_NR      3
+
+typedef struct {
+	int size __attribute__((aligned(8)));
+	int id __attribute__((aligned(8)));
+} qb_ipc_request_header_t __attribute__((aligned(8)));
+
+typedef struct {
+	int size __attribute__((aligned(8)));
+	int id __attribute__((aligned(8)));
+	int32_t error __attribute__((aligned(8)));
+} qb_ipc_response_header_t __attribute__((aligned(8)));
+
+struct control_buffer {
+	unsigned int read;
+	unsigned int write;
+#if _POSIX_THREAD_PROCESS_SHARED > 0
+	sem_t sem0;
+	sem_t sem1;
+	sem_t sem2;
+#endif
+};
+
+enum res_init_types {
+	MESSAGE_RES_INIT
+};
+
+typedef struct {
+	int service __attribute__((aligned(8)));
+	unsigned long long semkey __attribute__((aligned(8)));
+	char control_file[64] __attribute__((aligned(8)));
+	char request_file[64] __attribute__((aligned(8)));
+	char response_file[64] __attribute__((aligned(8)));
+	char dispatch_file[64] __attribute__((aligned(8)));
+	size_t control_size __attribute__((aligned(8)));
+	size_t request_size __attribute__((aligned(8)));
+	size_t response_size __attribute__((aligned(8)));
+	size_t dispatch_size __attribute__((aligned(8)));
+} mar_req_setup_t __attribute__((aligned(8)));
+
+typedef struct {
+	int error __attribute__((aligned(8)));
+} mar_res_setup_t __attribute__((aligned(8)));
+
+typedef struct {
+        uid_t euid __attribute__((aligned(8)));
+        gid_t egid __attribute__((aligned(8)));
+} mar_req_priv_change __attribute__((aligned(8)));
+
+typedef struct {
+	qb_ipc_response_header_t header __attribute__((aligned(8)));
+	uint64_t conn_info __attribute__((aligned(8)));
+} mar_res_lib_response_init_t __attribute__((aligned(8)));
+
+typedef struct {
+	qb_ipc_response_header_t header __attribute__((aligned(8)));
+} mar_res_lib_dispatch_init_t __attribute__((aligned(8)));
+
+typedef struct {
+	uint32_t nodeid __attribute__((aligned(8)));
+	void *conn __attribute__((aligned(8)));
+} mar_message_source_t __attribute__((aligned(8)));
+
+typedef struct {
+        qb_ipc_request_header_t header __attribute__((aligned(8)));
+        size_t map_size __attribute__((aligned(8)));
+        char path_to_file[128] __attribute__((aligned(8)));
+} mar_req_qb_ipcc_zc_alloc_t __attribute__((aligned(8)));
+
+typedef struct {
+        qb_ipc_request_header_t header __attribute__((aligned(8)));
+        size_t map_size __attribute__((aligned(8)));
+	uint64_t server_address __attribute__((aligned(8)));
+} mar_req_qb_ipcc_zc_free_t __attribute__((aligned(8)));
+
+typedef struct {
+        qb_ipc_request_header_t header __attribute__((aligned(8)));
+	uint64_t server_address __attribute__((aligned(8)));
+} mar_req_qb_ipcc_zc_execute_t __attribute__((aligned(8)));
+
+struct qb_ipcs_zc_header {
+	int map_size;
+	uint64_t server_address;
+};
+
+#define SOCKET_SERVICE_INIT	0xFFFFFFFF
+
+#define ZC_ALLOC_HEADER		0xFFFFFFFF
+#define ZC_FREE_HEADER		0xFFFFFFFE
+#define ZC_EXECUTE_HEADER	0xFFFFFFFD
+
+#endif /* QB_IPC_IPC_H_DEFINED */
diff --git a/lib/ipcc.c b/lib/ipcc.c
new file mode 100644
index 0000000..a21f3f0
--- /dev/null
+++ b/lib/ipcc.c
@@ -0,0 +1,1203 @@
+/*
+ * vi: set autoindent tabstop=4 shiftwidth=4 :
+ *
+ * Copyright (c) 2002-2006 MontaVista Software, Inc.
+ * Copyright (c) 2006-2009 Red Hat, Inc.
+ *
+ * All rights reserved.
+ *
+ * Author: Steven Dake (sdake@redhat.com)
+ *
+ * This software licensed under BSD license, the text of which follows:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - 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.
+ * - Neither the name of the MontaVista Software, Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
+ */
+
+#include <config.h>
+
+#include "os_base.h"
+#include <sys/shm.h>
+#include <sys/mman.h>
+
+#include <qb/qbipcc.h>
+#include <qb/qbhdb.h>
+#include "ipc_int.h"
+
+#if _POSIX_THREAD_PROCESS_SHARED > 0
+#include <semaphore.h>
+#else
+#include <sys/sem.h>
+#endif
+
+
+/*
+ * Define sem_wait timeout (real timeout will be (n-1;n) )
+ */
+#define IPC_SEMWAIT_TIMEOUT 2
+
+struct ipc_instance {
+	int fd;
+#if _POSIX_THREAD_PROCESS_SHARED < 1
+	int semid;
+#endif
+	int flow_control_state;
+	struct control_buffer *control_buffer;
+	char *request_buffer;
+	char *response_buffer;
+	char *dispatch_buffer;
+	size_t control_size;
+	size_t request_size;
+	size_t response_size;
+	size_t dispatch_size;
+	uid_t euid;
+	pthread_mutex_t mutex;
+};
+
+void ipc_hdb_destructor (void *context);
+
+DECLARE_HDB_DATABASE(ipc_hdb,ipc_hdb_destructor);
+
+#if defined(QB_LINUX) || defined(QB_SOLARIS)
+#define QB_SUN_LEN(a) sizeof(*(a))
+#else
+#define QB_SUN_LEN(a) SUN_LEN(a)
+#endif
+
+#ifdef SO_NOSIGPIPE
+static void socket_nosigpipe(int s)
+{
+	int on = 1;
+	setsockopt(s, SOL_SOCKET, SO_NOSIGPIPE, (void *)&on, sizeof(on));
+}
+#endif
+
+#ifndef MSG_NOSIGNAL
+#define MSG_NOSIGNAL 0
+#endif
+
+static int32_t
+socket_send (
+	int s,
+	void *msg,
+	size_t len)
+{
+	int32_t res = 0;
+	int result;
+	struct msghdr msg_send;
+	struct iovec iov_send;
+	char *rbuf = msg;
+	int processed = 0;
+
+	msg_send.msg_iov = &iov_send;
+	msg_send.msg_iovlen = 1;
+	msg_send.msg_name = 0;
+	msg_send.msg_namelen = 0;
+
+#if !defined(QB_SOLARIS)
+	msg_send.msg_control = 0;
+	msg_send.msg_controllen = 0;
+	msg_send.msg_flags = 0;
+#else
+	msg_send.msg_accrights = NULL;
+	msg_send.msg_accrightslen = 0;
+#endif
+
+retry_send:
+	iov_send.iov_base = &rbuf[processed];
+	iov_send.iov_len = len - processed;
+
+	result = sendmsg (s, &msg_send, MSG_NOSIGNAL);
+	if (result == -1) {
+		switch (errno) {
+		case EINTR:
+			res = EAGAIN;
+			goto res_exit;
+		case EAGAIN:
+			goto retry_send;
+			break;
+		default:
+			res = EBADE;
+			goto res_exit;
+		}
+	}
+
+	processed += result;
+	if (processed != len) {
+		goto retry_send;
+	}
+
+	return 0;
+
+res_exit:
+	return (res);
+}
+
+static int32_t
+socket_recv (
+	int s,
+	void *msg,
+	size_t len)
+{
+	int32_t res = 0;
+	int result;
+	struct msghdr msg_recv;
+	struct iovec iov_recv;
+	char *rbuf = msg;
+	int processed = 0;
+
+	msg_recv.msg_iov = &iov_recv;
+	msg_recv.msg_iovlen = 1;
+	msg_recv.msg_name = 0;
+	msg_recv.msg_namelen = 0;
+#if !defined (QB_SOLARIS)
+	msg_recv.msg_control = 0;
+	msg_recv.msg_controllen = 0;
+	msg_recv.msg_flags = 0;
+#else
+	msg_recv.msg_accrights = NULL;
+	msg_recv.msg_accrightslen = 0;
+#endif
+
+
+retry_recv:
+	iov_recv.iov_base = (void *)&rbuf[processed];
+	iov_recv.iov_len = len - processed;
+
+	result = recvmsg (s, &msg_recv, MSG_NOSIGNAL|MSG_WAITALL);
+	if (result == -1) {
+		switch (errno) {
+		case EINTR:
+			res = EAGAIN;
+			goto res_exit;
+		case EAGAIN:
+			goto retry_recv;
+			break;
+		default:
+			res = EBADE;
+			goto res_exit;
+		}
+	}
+#if defined(QB_SOLARIS) || defined(QB_BSD) || defined(QB_DARWIN)
+	/* On many OS poll never return POLLHUP or POLLERR.
+	 * EOF is detected when recvmsg return 0.
+	 */
+	if (result == 0) {
+		res = EBADE;
+		goto res_exit;
+	}
+#endif
+
+	processed += result;
+	if (processed != len) {
+		goto retry_recv;
+	}
+	assert (processed == len);
+res_exit:
+	return (res);
+}
+
+#if _POSIX_THREAD_PROCESS_SHARED < 1
+static int
+priv_change_send (struct ipc_instance *ipc_instance)
+{
+	char buf_req;
+	mar_req_priv_change req_priv_change;
+	unsigned int res;
+
+	req_priv_change.euid = geteuid();
+	/*
+	 * Don't resend request unless euid has changed
+	*/
+	if (ipc_instance->euid == req_priv_change.euid) {
+		return (0);
+	}
+	req_priv_change.egid = getegid();
+
+	buf_req = MESSAGE_REQ_CHANGE_EUID;
+	res = socket_send (ipc_instance->fd, &buf_req, 1);
+	if (res == -1) {
+		return (-1);
+	}
+
+	res = socket_send (ipc_instance->fd, &req_priv_change,
+		sizeof (req_priv_change));
+	if (res == -1) {
+		return (-1);
+	}
+
+	ipc_instance->euid = req_priv_change.euid;
+	return (0);
+}
+
+#if defined(_SEM_SEMUN_UNDEFINED)
+union semun {
+        int val;
+        struct semid_ds *buf;
+        unsigned short int *array;
+        struct seminfo *__buf;
+};
+#endif
+#endif
+
+static int
+circular_memory_map (char *path, const char *file, void **buf, size_t bytes)
+{
+	int fd;
+	void *addr_orig;
+	void *addr;
+	int res;
+
+	sprintf (path, "/dev/shm/%s", file);
+
+	fd = mkstemp (path);
+	if (fd == -1) {
+		sprintf (path, LOCALSTATEDIR "/run/%s", file);
+		fd = mkstemp (path);
+		if (fd == -1) {
+			return (-1);
+		}
+	}
+
+	res = ftruncate (fd, bytes);
+
+	addr_orig = mmap (NULL, bytes << 1, PROT_NONE,
+		MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
+
+	if (addr_orig == MAP_FAILED) {
+		return (-1);
+	}
+
+	addr = mmap (addr_orig, bytes, PROT_READ | PROT_WRITE,
+		MAP_FIXED | MAP_SHARED, fd, 0);
+
+	if (addr != addr_orig) {
+		return (-1);
+	}
+#ifdef QB_BSD
+	madvise(addr_orig, bytes, MADV_NOSYNC);
+#endif
+
+	addr = mmap (((char *)addr_orig) + bytes,
+                  bytes, PROT_READ | PROT_WRITE,
+                  MAP_FIXED | MAP_SHARED, fd, 0);
+#ifdef QB_BSD
+	madvise(((char *)addr_orig) + bytes, bytes, MADV_NOSYNC);
+#endif
+
+	res = close (fd);
+	if (res) {
+		return (-1);
+	}
+	*buf = addr_orig;
+	return (0);
+}
+
+static void
+memory_unmap (void *addr, size_t bytes)
+{
+	int res;
+
+	res = munmap (addr, bytes);
+}
+
+void ipc_hdb_destructor (void *context ) {
+	struct ipc_instance *ipc_instance = (struct ipc_instance *)context;
+
+	/*
+	 * << 1 (or multiplied by 2) because this is a wrapped memory buffer
+	 */
+	memory_unmap (ipc_instance->control_buffer, ipc_instance->control_size);
+	memory_unmap (ipc_instance->request_buffer, ipc_instance->request_size);
+	memory_unmap (ipc_instance->response_buffer, ipc_instance->response_size);
+	memory_unmap (ipc_instance->dispatch_buffer, (ipc_instance->dispatch_size) << 1);
+}
+static int
+memory_map (char *path, const char *file, void **buf, size_t bytes)
+{
+	int fd;
+	void *addr_orig;
+	void *addr;
+	int res;
+
+	sprintf (path, "/dev/shm/%s", file);
+
+	fd = mkstemp (path);
+	if (fd == -1) {
+		sprintf (path, LOCALSTATEDIR "/run/%s", file);
+		fd = mkstemp (path);
+		if (fd == -1) {
+			return (-1);
+		}
+	}
+
+	res = ftruncate (fd, bytes);
+
+	addr_orig = mmap (NULL, bytes, PROT_NONE,
+		MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
+
+	if (addr_orig == MAP_FAILED) {
+		return (-1);
+	}
+
+	addr = mmap (addr_orig, bytes, PROT_READ | PROT_WRITE,
+		MAP_FIXED | MAP_SHARED, fd, 0);
+
+	if (addr != addr_orig) {
+		return (-1);
+	}
+#ifdef QB_BSD
+	madvise(addr_orig, bytes, MADV_NOSYNC);
+#endif
+
+	res = close (fd);
+	if (res) {
+		return (-1);
+	}
+	*buf = addr_orig;
+	return (0);
+}
+
+static int32_t
+msg_send (
+	struct ipc_instance *ipc_instance,
+	const struct iovec *iov,
+	unsigned int iov_len)
+{
+#if _POSIX_THREAD_PROCESS_SHARED < 1
+	struct sembuf sop;
+#endif
+
+	int i;
+	int res;
+	int req_buffer_idx = 0;
+
+	for (i = 0; i < iov_len; i++) {
+		if ((req_buffer_idx + iov[i].iov_len) > 
+			ipc_instance->request_size) {
+			return (EINVAL);
+		}
+		memcpy (&ipc_instance->request_buffer[req_buffer_idx],
+			iov[i].iov_base,
+			iov[i].iov_len);
+		req_buffer_idx += iov[i].iov_len;
+	}
+
+#if _POSIX_THREAD_PROCESS_SHARED > 0
+	res = sem_post (&ipc_instance->control_buffer->sem0);
+	if (res == -1) {
+		return EBADE;
+	}
+#else 
+	/*
+	 * Signal semaphore #0 indicting a new message from client
+	 * to server request queue
+	 */
+	sop.sem_num = 0;
+	sop.sem_op = 1;
+	sop.sem_flg = 0;
+
+retry_semop:
+	res = semop (ipc_instance->semid, &sop, 1);
+	if (res == -1 && errno == EINTR) {
+		return (EAGAIN);
+	} else
+	if (res == -1 && errno == EACCES) {
+		priv_change_send (ipc_instance);
+		goto retry_semop;
+	} else
+	if (res == -1) {
+		return (EBADE);
+	}
+#endif
+	return 0;
+}
+
+static int32_t
+reply_receive (
+	struct ipc_instance *ipc_instance,
+	void *res_msg,
+	size_t res_len)
+{
+#if _POSIX_THREAD_PROCESS_SHARED < 1
+	struct sembuf sop;
+#else
+	struct timespec timeout;
+	struct pollfd pfd;
+#endif
+	qb_ipc_response_header_t *response_header;
+	int res;
+
+#if _POSIX_THREAD_PROCESS_SHARED > 0
+retry_semwait:
+	timeout.tv_sec = time(NULL) + IPC_SEMWAIT_TIMEOUT;
+	timeout.tv_nsec = 0;
+
+	res = sem_timedwait (&ipc_instance->control_buffer->sem1, &timeout);
+	if (res == -1 && errno == ETIMEDOUT) {
+		pfd.fd = ipc_instance->fd;
+		pfd.events = 0;
+
+		poll (&pfd, 1, 0);
+		if (pfd.revents == POLLERR || pfd.revents == POLLHUP) {
+			return EBADE;
+		}
+
+		goto retry_semwait;
+	}
+
+	if (res == -1 && errno == EINTR) {
+		goto retry_semwait;
+	}
+#else
+	/*
+	 * Wait for semaphore #1 indicating a new message from server
+	 * to client in the response queue
+	 */
+	sop.sem_num = 1;
+	sop.sem_op = -1;
+	sop.sem_flg = 0;
+
+retry_semop:
+	res = semop (ipc_instance->semid, &sop, 1);
+	if (res == -1 && errno == EINTR) {
+		return (EAGAIN);
+	} else
+	if (res == -1 && errno == EACCES) {
+		priv_change_send (ipc_instance);
+		goto retry_semop;
+	} else
+	if (res == -1) {
+		return (EBADE);
+	}
+#endif
+
+	response_header = (qb_ipc_response_header_t *)ipc_instance->response_buffer;
+	if (response_header->error == EAGAIN) {
+		return EAGAIN;
+	}
+
+	memcpy (res_msg, ipc_instance->response_buffer, res_len);
+	return 0;
+}
+
+static int32_t
+reply_receive_in_buf (
+	struct ipc_instance *ipc_instance,
+	void **res_msg)
+{
+#if _POSIX_THREAD_PROCESS_SHARED < 1
+	struct sembuf sop;
+#else
+	struct timespec timeout;
+	struct pollfd pfd;
+#endif
+	int res;
+
+#if _POSIX_THREAD_PROCESS_SHARED > 0
+retry_semwait:
+	timeout.tv_sec = time(NULL) + IPC_SEMWAIT_TIMEOUT;
+	timeout.tv_nsec = 0;
+
+	res = sem_timedwait (&ipc_instance->control_buffer->sem1, &timeout);
+	if (res == -1 && errno == ETIMEDOUT) {
+		pfd.fd = ipc_instance->fd;
+		pfd.events = 0;
+
+		poll (&pfd, 1, 0);
+		if (pfd.revents == POLLERR || pfd.revents == POLLHUP) {
+			return EBADE;
+		}
+
+		goto retry_semwait;
+	}
+
+	if (res == -1 && errno == EINTR) {
+		goto retry_semwait;
+	}
+#else
+	/*
+	 * Wait for semaphore #1 indicating a new message from server
+	 * to client in the response queue
+	 */
+	sop.sem_num = 1;
+	sop.sem_op = -1;
+	sop.sem_flg = 0;
+
+retry_semop:
+	res = semop (ipc_instance->semid, &sop, 1);
+	if (res == -1 && errno == EINTR) {
+		return (EAGAIN);
+	} else
+	if (res == -1 && errno == EACCES) {
+		priv_change_send (ipc_instance);
+		goto retry_semop;
+	} else
+	if (res == -1) {
+		return (EBADE);
+	}
+#endif
+
+	*res_msg = (char *)ipc_instance->response_buffer;
+	return 0;
+}
+
+/*
+ * External API
+ */
+int32_t
+qb_ipcc_service_connect (
+	const char *socket_name,
+	unsigned int service,
+	size_t request_size,
+	size_t response_size,
+	size_t dispatch_size,
+	qb_hdb_handle_t *handle)
+
+{
+	int request_fd;
+	struct sockaddr_un address;
+	int32_t res;
+	struct ipc_instance *ipc_instance;
+#if _POSIX_THREAD_PROCESS_SHARED < 1
+	key_t semkey = 0;
+	union semun semun;
+#endif
+	int sys_res;
+	mar_req_setup_t req_setup;
+	mar_res_setup_t res_setup;
+	char control_map_path[128];
+	char request_map_path[128];
+	char response_map_path[128];
+	char dispatch_map_path[128];
+
+	res = qb_hdb_handle_create (&ipc_hdb,
+		sizeof (struct ipc_instance), handle);
+	if (res != 0) {
+		return (res);
+	}
+
+	res = qb_hdb_handle_get (&ipc_hdb, *handle, (void **)&ipc_instance);
+	if (res != 0) {
+		return (res);
+	}
+
+	res_setup.error = EBADE;
+
+#if defined(QB_SOLARIS)
+	request_fd = socket (PF_UNIX, SOCK_STREAM, 0);
+#else
+	request_fd = socket (PF_LOCAL, SOCK_STREAM, 0);
+#endif
+	if (request_fd == -1) {
+		return (EBADE);
+	}
+#ifdef SO_NOSIGPIPE
+	socket_nosigpipe (request_fd);
+#endif
+
+	memset (&address, 0, sizeof (struct sockaddr_un));
+	address.sun_family = AF_UNIX;
+#if defined(QB_BSD) || defined(QB_DARWIN)
+	address.sun_len = SUN_LEN(&address);
+#endif
+
+#if defined(QB_LINUX)
+	sprintf (address.sun_path + 1, "%s", socket_name);
+#else
+	sprintf (address.sun_path, "%s/%s", SOCKETDIR, socket_name);
+#endif
+	sys_res = connect (request_fd, (struct sockaddr *)&address,
+		QB_SUN_LEN(&address));
+	if (sys_res == -1) {
+		res = EAGAIN;
+		goto error_connect;
+	}
+
+	res = memory_map (
+		control_map_path,
+		"control_buffer-XXXXXX",
+		(void *)&ipc_instance->control_buffer,
+		8192);
+	if (res == -1) {
+		res = EBADE;
+		goto error_connect;
+	}
+
+	res = memory_map (
+		request_map_path,
+		"request_buffer-XXXXXX",
+		(void *)&ipc_instance->request_buffer,
+		request_size);
+	if (res == -1) {
+		res = EBADE;
+		goto error_request_buffer;
+	}
+
+	res = memory_map (
+		response_map_path,
+		"response_buffer-XXXXXX",
+		(void *)&ipc_instance->response_buffer,
+		response_size);
+	if (res == -1) {
+		res = EBADE;
+		goto error_response_buffer;
+	}
+
+	res = circular_memory_map (
+		dispatch_map_path,
+		"dispatch_buffer-XXXXXX",
+		(void *)&ipc_instance->dispatch_buffer,
+		dispatch_size);
+	if (res == -1) {
+		res = EBADE;
+		goto error_dispatch_buffer;
+	}
+
+#if _POSIX_THREAD_PROCESS_SHARED > 0
+	sem_init (&ipc_instance->control_buffer->sem0, 1, 0);
+	sem_init (&ipc_instance->control_buffer->sem1, 1, 0);
+	sem_init (&ipc_instance->control_buffer->sem2, 1, 0);
+#else
+
+	/*
+	 * Allocate a semaphore segment
+	 */
+	while (1) {
+		semkey = random();
+		ipc_instance->euid = geteuid ();
+		if ((ipc_instance->semid
+		     = semget (semkey, 3, IPC_CREAT|IPC_EXCL|0600)) != -1) {
+		      break;
+		}
+		/*
+		 * EACCESS can be returned as non root user when opening a different
+		 * users semaphore.
+		 *
+		 * EEXIST can happen when we are a root or nonroot user opening
+		 * an existing shared memory segment for which we have access
+		 */
+		if (errno != EEXIST && errno != EACCES) {
+			goto error_exit;
+		}
+	}
+
+	semun.val = 0;
+	res = semctl (ipc_instance->semid, 0, SETVAL, semun);
+	if (res != 0) {
+		goto error_exit;
+	}
+
+	res = semctl (ipc_instance->semid, 1, SETVAL, semun);
+	if (res != 0) {
+		goto error_exit;
+	}
+#endif
+
+	/*
+	 * Initialize IPC setup message
+	 */
+	req_setup.service = service;
+	strcpy (req_setup.control_file, control_map_path);
+	strcpy (req_setup.request_file, request_map_path);
+	strcpy (req_setup.response_file, response_map_path);
+	strcpy (req_setup.dispatch_file, dispatch_map_path);
+	req_setup.control_size = 8192;
+	req_setup.request_size = request_size;
+	req_setup.response_size = response_size;
+	req_setup.dispatch_size = dispatch_size;
+
+#if _POSIX_THREAD_PROCESS_SHARED < 1
+	req_setup.semkey = semkey;
+#endif
+
+	res = socket_send (request_fd, &req_setup, sizeof (mar_req_setup_t));
+	if (res != 0) {
+		goto error_exit;
+	}
+	res = socket_recv (request_fd, &res_setup, sizeof (mar_res_setup_t));
+	if (res != 0) {
+		goto error_exit;
+	}
+
+	ipc_instance->fd = request_fd;
+	ipc_instance->flow_control_state = 0;
+
+	if (res_setup.error == EAGAIN) {
+		res = res_setup.error;
+		goto error_exit;
+	}
+
+	ipc_instance->control_size = 8192;
+	ipc_instance->request_size = request_size;
+	ipc_instance->response_size = response_size;
+	ipc_instance->dispatch_size = dispatch_size;
+
+	pthread_mutex_init (&ipc_instance->mutex, NULL);
+
+	qb_hdb_handle_put (&ipc_hdb, *handle);
+
+	return (res_setup.error);
+
+error_exit:
+#if _POSIX_THREAD_PROCESS_SHARED < 1
+	if (ipc_instance->semid > 0)
+		semctl (ipc_instance->semid, 0, IPC_RMID);
+#endif
+	memory_unmap (ipc_instance->dispatch_buffer, dispatch_size);
+error_dispatch_buffer:
+	memory_unmap (ipc_instance->response_buffer, response_size);
+error_response_buffer:
+	memory_unmap (ipc_instance->request_buffer, request_size);
+error_request_buffer:
+	memory_unmap (ipc_instance->control_buffer, 8192);
+error_connect:
+	close (request_fd);
+
+	qb_hdb_handle_destroy (&ipc_hdb, *handle);
+	qb_hdb_handle_put (&ipc_hdb, *handle);
+
+	return (res);
+}
+
+int32_t
+qb_ipcc_service_disconnect (
+	qb_hdb_handle_t handle)
+{
+	int32_t res;
+	struct ipc_instance *ipc_instance;
+
+	res = qb_hdb_handle_get (&ipc_hdb, handle, (void **)&ipc_instance);
+	if (res != 0) {
+		return (res);
+	}
+
+	shutdown (ipc_instance->fd, SHUT_RDWR);
+	close (ipc_instance->fd);
+	qb_hdb_handle_destroy (&ipc_hdb, handle);
+	qb_hdb_handle_put (&ipc_hdb, handle);
+	return (0);
+}
+
+int32_t
+qb_ipcc_dispatch_flow_control_get (
+	qb_hdb_handle_t handle,
+	unsigned int *flow_control_state)
+{
+	struct ipc_instance *ipc_instance;
+	int32_t res;
+
+	res = qb_hdb_handle_get (&ipc_hdb, handle, (void **)&ipc_instance);
+	if (res != 0) {
+		return (res);
+	}
+
+	*flow_control_state = ipc_instance->flow_control_state;
+
+	qb_hdb_handle_put (&ipc_hdb, handle);
+	return (res);
+}
+
+int32_t
+qb_ipcc_fd_get (
+	qb_hdb_handle_t handle,
+	int *fd)
+{
+	struct ipc_instance *ipc_instance;
+	int32_t res;
+
+	res = qb_hdb_handle_get (&ipc_hdb, handle, (void **)&ipc_instance);
+	if (res != 0) {
+		return (res);
+	}
+
+	*fd = ipc_instance->fd;
+
+	qb_hdb_handle_put (&ipc_hdb, handle);
+	return (res);
+}
+
+int32_t
+qb_ipcc_dispatch_get (
+	qb_hdb_handle_t handle,
+	void **data,
+	int timeout)
+{
+	struct pollfd ufds;
+	int poll_events;
+	char buf;
+	struct ipc_instance *ipc_instance;
+	int res;
+	char buf_two = 1;
+	char *data_addr;
+	int32_t error = 0;
+
+	error = qb_hdb_handle_get (&ipc_hdb, handle, (void **)&ipc_instance);
+	if (error != 0) {
+		return (error);
+	}
+
+	*data = NULL;
+
+	ufds.fd = ipc_instance->fd;
+	ufds.events = POLLIN;
+	ufds.revents = 0;
+
+	poll_events = poll (&ufds, 1, timeout);
+	if (poll_events == -1 && errno == EINTR) {
+		error = EAGAIN;
+		goto error_put;
+	} else
+	if (poll_events == -1) {
+		error = EBADE;
+		goto error_put;
+	} else
+	if (poll_events == 0) {
+		error = EAGAIN;
+		goto error_put;
+	}
+	if (poll_events == 1 && (ufds.revents & (POLLERR|POLLHUP))) {
+		error = EBADE;
+		goto error_put;
+	}
+
+	res = recv (ipc_instance->fd, &buf, 1, 0);
+	if (res == -1 && errno == EINTR) {
+		error = EAGAIN;
+		goto error_put;
+	} else
+	if (res == -1) {
+		error = EBADE;
+		goto error_put;
+	} else
+	if (res == 0) {
+		/* Means that the peer closed cleanly the socket. However, it should
+		 * happen only on BSD and Darwing systems since poll() returns a
+		 * POLLHUP event on other systems.
+		 */
+		error = EBADE;
+		goto error_put;
+	}
+	ipc_instance->flow_control_state = 0;
+	if (buf == MESSAGE_RES_OUTQ_NOT_EMPTY || buf == MESSAGE_RES_ENABLE_FLOWCONTROL) {
+		ipc_instance->flow_control_state = 1;
+	}
+	/*
+	 * Notify executive to flush any pending dispatch messages
+	 */
+	if (ipc_instance->flow_control_state) {
+		buf_two = MESSAGE_REQ_OUTQ_FLUSH;
+		res = socket_send (ipc_instance->fd, &buf_two, 1);
+		assert (res == 0); /* TODO */
+	}
+	/*
+	 * This is just a notification of flow control starting at the addition
+	 * of a new pending message, not a message to dispatch
+	 */
+	if (buf == MESSAGE_RES_ENABLE_FLOWCONTROL) {
+		error = EAGAIN;
+		goto error_put;
+	}
+	if (buf == MESSAGE_RES_OUTQ_FLUSH_NR) {
+		error = EAGAIN;
+		goto error_put;
+	}
+
+	data_addr = ipc_instance->dispatch_buffer;
+
+	data_addr = &data_addr[ipc_instance->control_buffer->read];
+
+	*data = (void *)data_addr;
+
+	return (0);
+error_put:
+	qb_hdb_handle_put (&ipc_hdb, handle);
+	return (error);
+}
+
+int32_t
+qb_ipcc_dispatch_put (qb_hdb_handle_t handle)
+{
+#if _POSIX_THREAD_PROCESS_SHARED < 1
+	struct sembuf sop;
+#endif
+	qb_ipc_response_header_t *header;
+	struct ipc_instance *ipc_instance;
+	int res;
+	char *addr;
+	unsigned int read_idx;
+
+	res = qb_hdb_handle_get_always (&ipc_hdb, handle, (void **)&ipc_instance);
+	if (res != 0) {
+		return (res);
+	}
+#if _POSIX_THREAD_PROCESS_SHARED > 0
+retry_semwait:
+	res = sem_wait (&ipc_instance->control_buffer->sem2);
+	if (res == -1 && errno == EINTR) {
+		goto retry_semwait;
+	}
+#else
+	sop.sem_num = 2;
+	sop.sem_op = -1;
+	sop.sem_flg = 0;
+retry_semop:
+	res = semop (ipc_instance->semid, &sop, 1);
+	if (res == -1 && errno == EINTR) {
+		res = EAGAIN;
+		goto error_exit;
+	} else
+	if (res == -1 && errno == EACCES) {
+		priv_change_send (ipc_instance);
+		goto retry_semop;
+	} else
+	if (res == -1) {
+		res = EBADE;
+		goto error_exit;
+	}
+#endif
+
+	addr = ipc_instance->dispatch_buffer;
+
+	read_idx = ipc_instance->control_buffer->read;
+	header = (qb_ipc_response_header_t *) &addr[read_idx];
+	ipc_instance->control_buffer->read =
+		(read_idx + header->size) % ipc_instance->dispatch_size;
+	/*
+	 * Put from dispatch get and also from this call's get
+	 */
+	res = 0;
+	
+#if _POSIX_THREAD_PROCESS_SHARED < 1
+error_exit:
+#endif
+	qb_hdb_handle_put (&ipc_hdb, handle);
+	qb_hdb_handle_put (&ipc_hdb, handle);
+
+	return (res);
+}
+
+int32_t
+qb_ipcc_msg_send_reply_receive (
+	qb_hdb_handle_t handle,
+	const struct iovec *iov,
+	unsigned int iov_len,
+	void *res_msg,
+	size_t res_len)
+{
+	int32_t res;
+	struct ipc_instance *ipc_instance;
+
+	res = qb_hdb_handle_get (&ipc_hdb, handle, (void **)&ipc_instance);
+	if (res != 0) {
+		return (res);
+	}
+
+	pthread_mutex_lock (&ipc_instance->mutex);
+
+	res = msg_send (ipc_instance, iov, iov_len);
+	if (res != 0) {
+		goto error_exit;
+	}
+
+	res = reply_receive (ipc_instance, res_msg, res_len);
+
+error_exit:
+	qb_hdb_handle_put (&ipc_hdb, handle);
+	pthread_mutex_unlock (&ipc_instance->mutex);
+
+	return (res);
+}
+
+int32_t
+qb_ipcc_msg_send_reply_receive_in_buf_get (
+	qb_hdb_handle_t handle,
+	const struct iovec *iov,
+	unsigned int iov_len,
+	void **res_msg)
+{
+	unsigned int res;
+	struct ipc_instance *ipc_instance;
+
+	res = qb_hdb_handle_get (&ipc_hdb, handle, (void **)&ipc_instance);
+	if (res != 0) {
+		return (res);
+	}
+
+	pthread_mutex_lock (&ipc_instance->mutex);
+
+	res = msg_send (ipc_instance, iov, iov_len);
+	if (res != 0) {
+		goto error_exit;
+	}
+
+	res = reply_receive_in_buf (ipc_instance, res_msg);
+
+error_exit:
+	pthread_mutex_unlock (&ipc_instance->mutex);
+
+	return (res);
+}
+
+int32_t
+qb_ipcc_msg_send_reply_receive_in_buf_put (
+	qb_hdb_handle_t handle)
+{
+	unsigned int res;
+	struct ipc_instance *ipc_instance;
+
+	res = qb_hdb_handle_get (&ipc_hdb, handle, (void **)&ipc_instance);
+	if (res != 0) {
+		return (res);
+	}
+	qb_hdb_handle_put (&ipc_hdb, handle);
+	qb_hdb_handle_put (&ipc_hdb, handle);
+
+	return (res);
+}
+
+int32_t
+qb_ipcc_zcb_alloc (
+	qb_hdb_handle_t handle,
+	void **buffer,
+	size_t size,
+	size_t header_size)
+{
+	struct ipc_instance *ipc_instance;
+	void *buf = NULL;
+	char path[128];
+	unsigned int res;
+	mar_req_qb_ipcc_zc_alloc_t req_qb_ipcc_zc_alloc;
+	qb_ipc_response_header_t res_qb_ipcs_zc_alloc;
+	size_t map_size;
+	struct iovec iovec;
+	struct qb_ipcs_zc_header *hdr;
+
+	res = qb_hdb_handle_get (&ipc_hdb, handle, (void **)&ipc_instance);
+	if (res != 0) {
+		return (res);
+	}
+	map_size = size + header_size + sizeof (struct qb_ipcs_zc_header);
+	res = memory_map (path, "qb_zerocopy-XXXXXX", &buf, map_size);
+	assert (res != -1);
+
+	req_qb_ipcc_zc_alloc.header.size = sizeof (mar_req_qb_ipcc_zc_alloc_t);
+	req_qb_ipcc_zc_alloc.header.id = ZC_ALLOC_HEADER;
+	req_qb_ipcc_zc_alloc.map_size = map_size;
+	strcpy (req_qb_ipcc_zc_alloc.path_to_file, path);
+
+
+	iovec.iov_base = (void *)&req_qb_ipcc_zc_alloc;
+	iovec.iov_len = sizeof (mar_req_qb_ipcc_zc_alloc_t);
+
+	res = qb_ipcc_msg_send_reply_receive (
+		handle,
+		&iovec,
+		1,
+		&res_qb_ipcs_zc_alloc,
+		sizeof (qb_ipc_response_header_t));
+
+	hdr = (struct qb_ipcs_zc_header *)buf;
+	hdr->map_size = map_size;
+	*buffer = ((char *)buf) + sizeof (struct qb_ipcs_zc_header);
+
+	qb_hdb_handle_put (&ipc_hdb, handle);
+	return (res);
+}
+
+int32_t
+qb_ipcc_zcb_free (
+	qb_hdb_handle_t handle,
+	void *buffer)
+{
+	struct ipc_instance *ipc_instance;
+	mar_req_qb_ipcc_zc_free_t req_qb_ipcc_zc_free;
+	qb_ipc_response_header_t res_qb_ipcs_zc_free;
+	struct iovec iovec;
+	unsigned int res;
+	struct qb_ipcs_zc_header *header = (struct qb_ipcs_zc_header *)((char *)buffer - sizeof (struct qb_ipcs_zc_header));
+
+	res = qb_hdb_handle_get (&ipc_hdb, handle, (void **)&ipc_instance);
+	if (res != 0) {
+		return (res);
+	}
+
+	req_qb_ipcc_zc_free.header.size = sizeof (mar_req_qb_ipcc_zc_free_t);
+	req_qb_ipcc_zc_free.header.id = ZC_FREE_HEADER;
+	req_qb_ipcc_zc_free.map_size = header->map_size;
+	req_qb_ipcc_zc_free.server_address = header->server_address;
+
+	iovec.iov_base = (void *)&req_qb_ipcc_zc_free;
+	iovec.iov_len = sizeof (mar_req_qb_ipcc_zc_free_t);
+
+	res = qb_ipcc_msg_send_reply_receive (
+		handle,
+		&iovec,
+		1,
+		&res_qb_ipcs_zc_free,
+		sizeof (qb_ipc_response_header_t));
+
+	munmap ((void *)header, header->map_size);
+
+	qb_hdb_handle_put (&ipc_hdb, handle);
+
+	return (res);
+}
+
+int32_t
+qb_ipcc_zcb_msg_send_reply_receive (
+	qb_hdb_handle_t handle,
+        void *msg,
+        void *res_msg,
+        size_t res_len)
+{
+	struct ipc_instance *ipc_instance;
+	mar_req_qb_ipcc_zc_execute_t req_qb_ipcc_zc_execute;
+	struct qb_ipcs_zc_header *hdr;
+	struct iovec iovec;
+	int32_t res;
+
+	res = qb_hdb_handle_get (&ipc_hdb, handle, (void **)&ipc_instance);
+	if (res != 0) {
+		return (res);
+	}
+	hdr = (struct qb_ipcs_zc_header *)(((char *)msg) - sizeof (struct qb_ipcs_zc_header));
+
+	req_qb_ipcc_zc_execute.header.size = sizeof (mar_req_qb_ipcc_zc_execute_t);
+	req_qb_ipcc_zc_execute.header.id = ZC_EXECUTE_HEADER;
+	req_qb_ipcc_zc_execute.server_address = hdr->server_address;
+
+	iovec.iov_base = (void *)&req_qb_ipcc_zc_execute;
+	iovec.iov_len = sizeof (mar_req_qb_ipcc_zc_execute_t);
+
+	res = qb_ipcc_msg_send_reply_receive (
+		handle,
+		&iovec,
+		1,
+		res_msg,
+		res_len);
+
+	qb_hdb_handle_put (&ipc_hdb, handle);
+	return (res);
+}
diff --git a/lib/ipcs.c b/lib/ipcs.c
new file mode 100644
index 0000000..7a69047
--- /dev/null
+++ b/lib/ipcs.c
@@ -0,0 +1,1795 @@
+/*
+ * Copyright (c) 2006-2009 Red Hat, Inc.
+ *
+ * All rights reserved.
+ *
+ * Author: Steven Dake (sdake@redhat.com)
+ *
+ * This software licensed under BSD license, the text of which follows:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - 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.
+ * - Neither the name of the MontaVista Software, Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
+ */
+
+#include <config.h>
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE 1
+#endif
+
+#include "os_base.h"
+#include <sys/mman.h>
+#include <sys/poll.h>
+#if defined(HAVE_GETPEERUCRED)
+#include <ucred.h>
+#endif
+#include <sys/shm.h>
+
+#include <qb/qblist.h>
+#include <qb/qbhdb.h>
+#include "ipc_int.h"
+#include <qb/qbipcs.h>
+
+//#define LOGSYS_UTILS_ONLY 1
+#include <syslog.h>
+//#include <qb/engine/logsys.h>
+
+#if _POSIX_THREAD_PROCESS_SHARED > 0
+#include <semaphore.h>
+#else
+#include <sys/sem.h>
+#endif
+
+#ifndef MSG_NOSIGNAL
+#define MSG_NOSIGNAL 0
+#endif
+
+#define SERVER_BACKLOG 5
+
+#define MSG_SEND_LOCKED		0
+#define MSG_SEND_UNLOCKED	1
+
+static struct qb_ipcs_init_state_v2 *api = NULL;
+
+QB_DECLARE_LIST_INIT (conn_info_qb_list_head);
+
+QB_DECLARE_LIST_INIT (conn_info_exit_qb_list_head);
+
+struct outq_item {
+	void *msg;
+	size_t mlen;
+	struct qb_list_head list;
+};
+
+struct zcb_mapped {
+	struct qb_list_head list;
+	void *addr;
+	size_t size;
+};
+
+#if _POSIX_THREAD_PROCESS_SHARED < 1
+#if defined(_SEM_SEMUN_UNDEFINED)
+union semun {
+	int val;
+	struct semid_ds *buf;
+	unsigned short int *array;
+	struct seminfo *__buf;
+};
+#endif
+#endif
+
+
+enum conn_state {
+	CONN_STATE_THREAD_INACTIVE = 0,
+	CONN_STATE_THREAD_ACTIVE = 1,
+	CONN_STATE_THREAD_REQUEST_EXIT = 2,
+	CONN_STATE_THREAD_DESTROYED = 3,
+	CONN_STATE_LIB_EXIT_CALLED = 4,
+	CONN_STATE_DISCONNECT_INACTIVE = 5
+};
+
+struct conn_info {
+	int fd;
+	pthread_t thread;
+	pid_t client_pid;
+	pthread_attr_t thread_attr;
+	unsigned int service;
+	enum conn_state state;
+	int notify_flow_control_enabled;
+	int flow_control_state;
+	int refcount;
+	qb_hdb_handle_t stats_handle;
+#if _POSIX_THREAD_PROCESS_SHARED < 1
+	key_t semkey;
+	int semid;
+#endif
+	unsigned int pending_semops;
+	pthread_mutex_t mutex;
+	struct control_buffer *control_buffer;
+	char *request_buffer;
+	char *response_buffer;
+	char *dispatch_buffer;
+	size_t control_size;
+	size_t request_size;
+	size_t response_size;
+	size_t dispatch_size;
+	struct qb_list_head outq_head;
+	void *private_data;
+	struct qb_list_head list;
+	char setup_msg[sizeof (mar_req_setup_t)];
+	unsigned int setup_bytes_read;
+	struct qb_list_head zcb_mapped_qb_list_head;
+	char *sending_allowed_private_data[64];
+};
+
+static int shared_mem_dispatch_bytes_left (const struct conn_info *conn_info);
+
+static void outq_flush (struct conn_info *conn_info);
+
+static int priv_change (struct conn_info *conn_info);
+
+static void ipc_disconnect (struct conn_info *conn_info);
+
+static void msg_send (void *conn, const struct iovec *iov, unsigned int iov_len,
+		      int locked);
+
+static void _qb_ipc_init(void);
+
+#define log_printf(level, format, args...) \
+do { \
+        api->log_printf ( level, \
+                /*LOGSYS_ENCODE_RECID(level, */\
+                                    /*api->log_subsys_id,*/ \
+                                    /*LOGSYS_RECID_LOG),*/ \
+                __FUNCTION__, __FILE__, __LINE__, \
+                (const char *)format, ##args); \
+} while (0)
+
+static qb_hdb_handle_t dummy_stats_create_connection (
+	const char *name,
+	pid_t pid,
+	int fd)
+{
+	return (0ULL);
+}
+
+static void dummy_stats_destroy_connection (
+	qb_hdb_handle_t handle)
+{
+}
+
+static void dummy_stats_update_value (
+	qb_hdb_handle_t handle,
+	const char *name,
+	const void *value,
+	size_t value_size)
+{
+}
+
+static void dummy_stats_increment_value (
+	qb_hdb_handle_t handle,
+	const char *name)
+{
+}
+
+static void sem_post_exit_thread (struct conn_info *conn_info)
+{
+#if _POSIX_THREAD_PROCESS_SHARED < 1
+	struct sembuf sop;
+#endif
+	int res;
+
+#if _POSIX_THREAD_PROCESS_SHARED > 0
+retry_semop:
+	res = sem_post (&conn_info->control_buffer->sem0);
+	if (res == -1 && errno == EINTR) {
+		api->stats_increment_value (conn_info->stats_handle, "sem_retry_count");
+		goto retry_semop;
+	}
+#else
+	sop.sem_num = 0;
+	sop.sem_op = 1;
+	sop.sem_flg = 0;
+
+retry_semop:
+	res = semop (conn_info->semid, &sop, 1);
+	if ((res == -1) && (errno == EINTR || errno == EAGAIN)) {
+		api->stats_increment_value (conn_info->stats_handle, "sem_retry_count");
+		goto retry_semop;
+	}
+#endif
+}
+
+static int
+memory_map (
+	const char *path,
+	size_t bytes,
+	void **buf)
+{
+	int fd;
+	void *addr_orig;
+	void *addr;
+	int res;
+
+	fd = open (path, O_RDWR, 0600);
+
+	unlink (path);
+
+	res = ftruncate (fd, bytes);
+
+	addr_orig = mmap (NULL, bytes, PROT_NONE,
+		MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
+
+	if (addr_orig == MAP_FAILED) {
+		return (-1);
+	}
+
+	addr = mmap (addr_orig, bytes, PROT_READ | PROT_WRITE,
+		MAP_FIXED | MAP_SHARED, fd, 0);
+
+	if (addr != addr_orig) {
+		return (-1);
+	}
+#ifdef QB_BSD
+	madvise(addr, bytes, MADV_NOSYNC);
+#endif
+
+	res = close (fd);
+	if (res) {
+		return (-1);
+	}
+	*buf = addr_orig;
+	return (0);
+}
+
+static int
+circular_memory_map (
+	const char *path,
+	size_t bytes,
+	void **buf)
+{
+	int fd;
+	void *addr_orig;
+	void *addr;
+	int res;
+
+	fd = open (path, O_RDWR, 0600);
+
+	unlink (path);
+
+	res = ftruncate (fd, bytes);
+
+	addr_orig = mmap (NULL, bytes << 1, PROT_NONE,
+		MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
+
+	if (addr_orig == MAP_FAILED) {
+		return (-1);
+	}
+
+	addr = mmap (addr_orig, bytes, PROT_READ | PROT_WRITE,
+		MAP_FIXED | MAP_SHARED, fd, 0);
+
+	if (addr != addr_orig) {
+		return (-1);
+	}
+#ifdef QB_BSD
+	madvise(addr_orig, bytes, MADV_NOSYNC);
+#endif
+
+	addr = mmap (((char *)addr_orig) + bytes,
+                  bytes, PROT_READ | PROT_WRITE,
+                  MAP_FIXED | MAP_SHARED, fd, 0);
+#ifdef QB_BSD
+	madvise(((char *)addr_orig) + bytes, bytes, MADV_NOSYNC);
+#endif
+
+	res = close (fd);
+	if (res) {
+		return (-1);
+	}
+	*buf = addr_orig;
+	return (0);
+}
+
+static inline int
+circular_memory_unmap (void *buf, size_t bytes)
+{
+	int res;
+
+	res = munmap (buf, bytes << 1);
+
+	return (res);
+}
+
+static inline int zcb_free (struct zcb_mapped *zcb_mapped)
+{
+	unsigned int res;
+
+	res = munmap (zcb_mapped->addr, zcb_mapped->size);
+	qb_list_del (&zcb_mapped->list);
+	free (zcb_mapped);
+	return (res);
+}
+
+static inline int zcb_by_addr_free (struct conn_info *conn_info, void *addr)
+{
+	struct qb_list_head *list;
+	struct zcb_mapped *zcb_mapped;
+	unsigned int res = 0;
+
+	for (list = conn_info->zcb_mapped_qb_list_head.next;
+		list != &conn_info->zcb_mapped_qb_list_head; list = list->next) {
+
+		zcb_mapped = qb_list_entry (list, struct zcb_mapped, list);
+
+		if (zcb_mapped->addr == addr) {
+			res = zcb_free (zcb_mapped);
+			break;
+		}
+
+	}
+	return (res);
+}
+
+static inline int zcb_all_free (
+	struct conn_info *conn_info)
+{
+	struct qb_list_head *list;
+	struct zcb_mapped *zcb_mapped;
+
+	for (list = conn_info->zcb_mapped_qb_list_head.next;
+		list != &conn_info->zcb_mapped_qb_list_head;) {
+
+		zcb_mapped = qb_list_entry (list, struct zcb_mapped, list);
+
+		list = list->next;
+
+		zcb_free (zcb_mapped);
+	}
+	return (0);
+}
+
+static inline int zcb_alloc (
+	struct conn_info *conn_info,
+	const char *path_to_file,
+	size_t size,
+	void **addr)
+{
+	struct zcb_mapped *zcb_mapped;
+	unsigned int res;
+
+	zcb_mapped = malloc (sizeof (struct zcb_mapped));
+	if (zcb_mapped == NULL) {
+		return (-1);
+	}
+
+	res = memory_map (
+		path_to_file,
+		size,
+		addr);
+	if (res == -1) {
+		free (zcb_mapped);
+		return (-1);
+	}
+
+	qb_list_init (&zcb_mapped->list);
+	zcb_mapped->addr = *addr;
+	zcb_mapped->size = size;
+	qb_list_add_tail (&zcb_mapped->list, &conn_info->zcb_mapped_qb_list_head);
+	return (0);
+}
+
+static int ipc_thread_active (void *conn)
+{
+	struct conn_info *conn_info = (struct conn_info *)conn;
+	int retval = 0;
+
+	pthread_mutex_lock (&conn_info->mutex);
+	if (conn_info->state == CONN_STATE_THREAD_ACTIVE) {
+		retval = 1;
+	}
+	pthread_mutex_unlock (&conn_info->mutex);
+	return (retval);
+}
+
+static int ipc_thread_exiting (void *conn)
+{
+	struct conn_info *conn_info = (struct conn_info *)conn;
+	int retval = 1;
+
+	pthread_mutex_lock (&conn_info->mutex);
+	if (conn_info->state == CONN_STATE_THREAD_INACTIVE) {
+		retval = 0;
+	} else
+	if (conn_info->state == CONN_STATE_THREAD_ACTIVE) {
+		retval = 0;
+	}
+	pthread_mutex_unlock (&conn_info->mutex);
+	return (retval);
+}
+
+/*
+ * returns 0 if should be called again, -1 if finished
+ */
+static inline int conn_info_destroy (struct conn_info *conn_info)
+{
+	unsigned int res;
+	void *retval;
+
+	qb_list_del (&conn_info->list);
+	qb_list_init (&conn_info->list);
+	qb_list_add (&conn_info->list, &conn_info_exit_qb_list_head);
+
+	if (conn_info->state == CONN_STATE_THREAD_REQUEST_EXIT) {
+		res = pthread_join (conn_info->thread, &retval);
+		conn_info->state = CONN_STATE_THREAD_DESTROYED;
+		return (0);
+	}
+
+	if (conn_info->state == CONN_STATE_THREAD_INACTIVE ||
+		conn_info->state == CONN_STATE_DISCONNECT_INACTIVE) {
+		qb_list_del (&conn_info->list);
+		close (conn_info->fd);
+		api->free (conn_info);
+		return (-1);
+	}
+
+	if (conn_info->state == CONN_STATE_THREAD_ACTIVE) {
+		sem_post_exit_thread (conn_info);
+		return (0);
+	}
+
+	api->serialize_lock ();
+	/*
+	 * Retry library exit function if busy
+	 */
+	if (conn_info->state == CONN_STATE_THREAD_DESTROYED) {
+		api->stats_destroy_connection (conn_info->stats_handle);
+		res = api->exit_fn_get (conn_info->service) (conn_info);
+		if (res == -1) {
+			api->serialize_unlock ();
+			return (0);
+		} else {
+			conn_info->state = CONN_STATE_LIB_EXIT_CALLED;
+		}
+	}
+
+	pthread_mutex_lock (&conn_info->mutex);
+	if (conn_info->refcount > 0) {
+		pthread_mutex_unlock (&conn_info->mutex);
+		api->serialize_unlock ();
+		return (0);
+	}
+	qb_list_del (&conn_info->list);
+	pthread_mutex_unlock (&conn_info->mutex);
+
+#if _POSIX_THREAD_PROCESS_SHARED > 0
+	sem_destroy (&conn_info->control_buffer->sem0);
+	sem_destroy (&conn_info->control_buffer->sem1);
+	sem_destroy (&conn_info->control_buffer->sem2);
+#else
+	semctl (conn_info->semid, 0, IPC_RMID);
+#endif
+	/*
+	 * Destroy shared memory segment and semaphore
+	 */
+	res = munmap ((void *)conn_info->control_buffer, conn_info->control_size);
+	res = munmap ((void *)conn_info->request_buffer, conn_info->request_size);
+	res = munmap ((void *)conn_info->response_buffer, conn_info->response_size);
+
+	/*
+	 * Free allocated data needed to retry exiting library IPC connection
+	 */
+	if (conn_info->private_data) {
+		api->free (conn_info->private_data);
+	}
+	close (conn_info->fd);
+	res = circular_memory_unmap (conn_info->dispatch_buffer, conn_info->dispatch_size);
+	zcb_all_free (conn_info);
+	api->free (conn_info);
+	api->serialize_unlock ();
+	return (-1);
+}
+
+union u {
+	uint64_t server_addr;
+	void *server_ptr;
+};
+
+static uint64_t void2serveraddr (void *server_ptr)
+{
+	union u u;
+
+	u.server_ptr = server_ptr;
+	return (u.server_addr);
+}
+
+static void *serveraddr2void (uint64_t server_addr)
+{
+	union u u;
+
+	u.server_addr = server_addr;
+	return (u.server_ptr);
+};
+
+static inline void zerocopy_operations_process (
+	struct conn_info *conn_info,
+	qb_ipc_request_header_t **header_out,
+	unsigned int *new_message)
+{
+	qb_ipc_request_header_t *header;
+
+	header = (qb_ipc_request_header_t *)conn_info->request_buffer;
+	if (header->id == ZC_ALLOC_HEADER) {
+		mar_req_qb_ipcc_zc_alloc_t *hdr = (mar_req_qb_ipcc_zc_alloc_t *)header;
+		qb_ipc_response_header_t res_header;
+		void *addr = NULL;
+		struct qb_ipcs_zc_header *zc_header;
+		unsigned int res;
+
+		res = zcb_alloc (conn_info, hdr->path_to_file, hdr->map_size,
+			&addr);
+
+		zc_header = (struct qb_ipcs_zc_header *)addr;
+		zc_header->server_address = void2serveraddr(addr);
+
+		res_header.size = sizeof (qb_ipc_response_header_t);
+		res_header.id = 0;
+		qb_ipcs_response_send (
+			conn_info, &res_header,
+			res_header.size);
+		*new_message = 0;
+		return;
+	} else
+	if (header->id == ZC_FREE_HEADER) {
+		mar_req_qb_ipcc_zc_free_t *hdr = (mar_req_qb_ipcc_zc_free_t *)header;
+		qb_ipc_response_header_t res_header;
+		void *addr = NULL;
+
+		addr = serveraddr2void (hdr->server_address);
+
+		zcb_by_addr_free (conn_info, addr);
+
+		res_header.size = sizeof (qb_ipc_response_header_t);
+		res_header.id = 0;
+		qb_ipcs_response_send (
+			conn_info, &res_header,
+			res_header.size);
+
+		*new_message = 0;
+		return;
+	} else
+	if (header->id == ZC_EXECUTE_HEADER) {
+		mar_req_qb_ipcc_zc_execute_t *hdr = (mar_req_qb_ipcc_zc_execute_t *)header;
+
+		header = (qb_ipc_request_header_t *)(((char *)serveraddr2void(hdr->server_address) + sizeof (struct qb_ipcs_zc_header)));
+	}
+	*header_out = header;
+	*new_message = 1;
+}
+
+static void *pthread_ipc_consumer (void *conn)
+{
+	struct conn_info *conn_info = (struct conn_info *)conn;
+#if _POSIX_THREAD_PROCESS_SHARED < 1
+	struct sembuf sop;
+#endif
+	int res;
+	qb_ipc_request_header_t *header;
+	qb_ipc_response_header_t qb_ipc_response_header;
+	int send_ok;
+	unsigned int new_message;
+
+#if defined(HAVE_PTHREAD_SETSCHEDPARAM) && defined(HAVE_SCHED_GET_PRIORITY_MAX)
+	if (api->sched_policy != 0) {
+		res = pthread_setschedparam (conn_info->thread,
+			api->sched_policy, api->sched_param);
+	}
+#endif
+
+	for (;;) {
+#if _POSIX_THREAD_PROCESS_SHARED > 0
+retry_semwait:
+		res = sem_wait (&conn_info->control_buffer->sem0);
+		if (ipc_thread_active (conn_info) == 0) {
+			qb_ipcs_refcount_dec (conn_info);
+			pthread_exit (0);
+		}
+		if ((res == -1) && (errno == EINTR)) {
+			api->stats_increment_value (conn_info->stats_handle, "sem_retry_count");
+			goto retry_semwait;
+		}
+#else
+
+		sop.sem_num = 0;
+		sop.sem_op = -1;
+		sop.sem_flg = 0;
+retry_semop:
+		res = semop (conn_info->semid, &sop, 1);
+		if (ipc_thread_active (conn_info) == 0) {
+			qb_ipcs_refcount_dec (conn_info);
+			pthread_exit (0);
+		}
+		if ((res == -1) && (errno == EINTR || errno == EAGAIN)) {
+			api->stats_increment_value (conn_info->stats_handle, "sem_retry_count");
+			goto retry_semop;
+		} else
+		if ((res == -1) && (errno == EINVAL || errno == EIDRM)) {
+			qb_ipcs_refcount_dec (conn_info);
+			pthread_exit (0);
+		}
+#endif
+
+		zerocopy_operations_process (conn_info, &header, &new_message);
+		/*
+		 * There is no new message to process, continue for loop
+		 */
+		if (new_message == 0) {
+			continue;
+		}
+
+		qb_ipcs_refcount_inc (conn);
+
+		send_ok = api->sending_allowed (conn_info->service,
+			header->id,
+			header,
+			conn_info->sending_allowed_private_data);
+
+		/*
+		 * This happens when the message contains some kind of invalid
+		 * parameter, such as an invalid size
+		 */
+		if (send_ok == -1) {
+			qb_ipc_response_header.size = sizeof (qb_ipc_response_header_t);
+			qb_ipc_response_header.id = 0;
+			qb_ipc_response_header.error = EINVAL;
+			qb_ipcs_response_send (conn_info,
+				&qb_ipc_response_header,
+				sizeof (qb_ipc_response_header_t));
+		} else 
+		if (send_ok) {
+			api->serialize_lock();
+			api->stats_increment_value (conn_info->stats_handle, "requests");
+			api->handler_fn_get (conn_info->service, header->id) (conn_info, header);
+			api->serialize_unlock();
+		} else {
+			/*
+			 * Overload, tell library to retry
+			 */
+			api->stats_increment_value (conn_info->stats_handle, "sem_retry_count");
+			qb_ipc_response_header.size = sizeof (qb_ipc_response_header_t);
+			qb_ipc_response_header.id = 0;
+			qb_ipc_response_header.error = EAGAIN;
+			qb_ipcs_response_send (conn_info,
+				&qb_ipc_response_header,
+				sizeof (qb_ipc_response_header_t));
+		}
+
+		api->sending_allowed_release (conn_info->sending_allowed_private_data);
+		qb_ipcs_refcount_dec (conn);
+	}
+	pthread_exit (0);
+}
+
+static int
+req_setup_send (
+	struct conn_info *conn_info,
+	int error)
+{
+	mar_res_setup_t res_setup;
+	unsigned int res;
+
+	res_setup.error = error;
+
+retry_send:
+	res = send (conn_info->fd, &res_setup, sizeof (mar_res_setup_t), MSG_WAITALL);
+	if (res == -1 && errno == EINTR) {
+		api->stats_increment_value (conn_info->stats_handle, "send_retry_count");
+		goto retry_send;
+	} else
+	if (res == -1 && errno == EAGAIN) {
+		api->stats_increment_value (conn_info->stats_handle, "send_retry_count");
+		goto retry_send;
+	}
+	return (0);
+}
+
+static int
+req_setup_recv (
+	struct conn_info *conn_info)
+{
+	int res;
+	struct msghdr msg_recv;
+	struct iovec iov_recv;
+	int authenticated = 0;
+
+#ifdef QB_LINUX
+	struct cmsghdr *cmsg;
+	char cmsg_cred[CMSG_SPACE (sizeof (struct ucred))];
+	int off = 0;
+	int on = 1;
+	struct ucred *cred;
+#endif
+
+	msg_recv.msg_iov = &iov_recv;
+	msg_recv.msg_iovlen = 1;
+	msg_recv.msg_name = 0;
+	msg_recv.msg_namelen = 0;
+#ifdef QB_LINUX
+	msg_recv.msg_control = (void *)cmsg_cred;
+	msg_recv.msg_controllen = sizeof (cmsg_cred);
+#endif
+#ifdef QB_SOLARIS
+	msg_recv.msg_accrights = 0;
+	msg_recv.msg_accrightslen = 0;
+#endif /* QB_SOLARIS */
+
+	iov_recv.iov_base = &conn_info->setup_msg[conn_info->setup_bytes_read];
+	iov_recv.iov_len = sizeof (mar_req_setup_t) - conn_info->setup_bytes_read;
+#ifdef QB_LINUX
+	setsockopt(conn_info->fd, SOL_SOCKET, SO_PASSCRED, &on, sizeof (on));
+#endif
+
+retry_recv:
+	res = recvmsg (conn_info->fd, &msg_recv, MSG_NOSIGNAL);
+	if (res == -1 && errno == EINTR) {
+		api->stats_increment_value (conn_info->stats_handle, "recv_retry_count");
+		goto retry_recv;
+	} else
+	if (res == -1 && errno != EAGAIN) {
+		return (0);
+	} else
+	if (res == 0) {
+#if defined(QB_SOLARIS) || defined(QB_BSD) || defined(QB_DARWIN)
+		/* On many OS poll never return POLLHUP or POLLERR.
+		 * EOF is detected when recvmsg return 0.
+		 */
+		ipc_disconnect (conn_info);
+		return 0;
+#else
+		return (-1);
+#endif
+	}
+	conn_info->setup_bytes_read += res;
+
+/*
+ * currently support getpeerucred, getpeereid, and SO_PASSCRED credential
+ * retrieval mechanisms for various Platforms
+ */
+#ifdef HAVE_GETPEERUCRED
+/*
+ * Solaris and some BSD systems
+ */
+	{
+		ucred_t *uc = NULL;
+		uid_t euid = -1;
+		gid_t egid = -1;
+
+		if (getpeerucred (conn_info->fd, &uc) == 0) {
+			euid = ucred_geteuid (uc);
+			egid = ucred_getegid (uc);
+			conn_info->client_pid = ucred_getpid (uc);
+			if (api->security_valid (euid, egid)) {
+				authenticated = 1;
+			}
+			ucred_free(uc);
+		}
+	}
+#elif HAVE_GETPEEREID
+/*
+ * Usually MacOSX systems
+ */
+
+	{
+		uid_t euid;
+		gid_t egid;
+
+		/*
+		 * TODO get the peer's pid.
+		 * conn_info->client_pid = ?;
+		 */
+		euid = -1;
+		egid = -1;
+		if (getpeereid (conn_info->fd, &euid, &egid) == 0) {
+			if (api->security_valid (euid, egid)) {
+				authenticated = 1;
+			}
+		}
+	}
+
+#elif SO_PASSCRED
+/*
+ * Usually Linux systems
+ */
+	cmsg = CMSG_FIRSTHDR (&msg_recv);
+	assert (cmsg);
+	cred = (struct ucred *)CMSG_DATA (cmsg);
+	if (cred) {
+		conn_info->client_pid = cred->pid;
+		if (api->security_valid (cred->uid, cred->gid)) {
+			authenticated = 1;
+		}
+	}
+
+#else /* no credentials */
+	authenticated = 1;
+ 	log_printf (LOG_ERR, "Platform does not support IPC authentication.  Using no authentication\n");
+#endif /* no credentials */
+
+	if (authenticated == 0) {
+		log_printf (LOG_ERR, "Invalid IPC credentials.\n");
+		ipc_disconnect (conn_info);
+		return (-1);
+ 	}
+
+	if (conn_info->setup_bytes_read == sizeof (mar_req_setup_t)) {
+#ifdef QB_LINUX
+		setsockopt(conn_info->fd, SOL_SOCKET, SO_PASSCRED,
+			&off, sizeof (off));
+#endif
+		return (1);
+	}
+	return (0);
+}
+
+static void ipc_disconnect (struct conn_info *conn_info)
+{
+	if (conn_info->state == CONN_STATE_THREAD_INACTIVE) {
+		conn_info->state = CONN_STATE_DISCONNECT_INACTIVE;
+		return;
+	}
+	if (conn_info->state != CONN_STATE_THREAD_ACTIVE) {
+		return;
+	}
+	pthread_mutex_lock (&conn_info->mutex);
+	conn_info->state = CONN_STATE_THREAD_REQUEST_EXIT;
+	pthread_mutex_unlock (&conn_info->mutex);
+
+	sem_post_exit_thread (conn_info);
+}
+
+static int conn_info_create (int fd)
+{
+	struct conn_info *conn_info;
+
+	conn_info = api->malloc (sizeof (struct conn_info));
+	if (conn_info == NULL) {
+		return (-1);
+	}
+	memset (conn_info, 0, sizeof (struct conn_info));
+
+	conn_info->fd = fd;
+	conn_info->client_pid = 0;
+	conn_info->service = SOCKET_SERVICE_INIT;
+	conn_info->state = CONN_STATE_THREAD_INACTIVE;
+	qb_list_init (&conn_info->outq_head);
+	qb_list_init (&conn_info->list);
+	qb_list_init (&conn_info->zcb_mapped_qb_list_head);
+	qb_list_add (&conn_info->list, &conn_info_qb_list_head);
+
+	api->poll_dispatch_add (fd, conn_info);
+
+	return (0);
+}
+
+#if defined(QB_LINUX) || defined(QB_SOLARIS)
+/* SUN_LEN is broken for abstract namespace
+ */
+#define QB_SUN_LEN(a) sizeof(*(a))
+#else
+#define QB_SUN_LEN(a) SUN_LEN(a)
+#endif
+
+
+/*
+ * Exported functions
+ */
+extern void qb_ipcs_ipc_init_v2 (
+	struct qb_ipcs_init_state_v2 *init_state_v2)
+{
+	api = init_state_v2;
+	api->old_log_printf	= NULL;
+
+	log_printf (LOG_DEBUG, "you are using ipc api v2\n");
+	_qb_ipc_init ();
+}
+
+extern void qb_ipcs_ipc_init (
+        struct qb_ipcs_init_state *init_state)
+{
+	api = calloc (sizeof(struct qb_ipcs_init_state_v2), 1);
+	/* v2 api */
+	api->stats_create_connection	= dummy_stats_create_connection;
+	api->stats_destroy_connection	= dummy_stats_destroy_connection;
+	api->stats_update_value		= dummy_stats_update_value;
+	api->stats_increment_value	= dummy_stats_increment_value;
+	api->log_printf			= NULL;
+
+	/* v1 api */
+	api->socket_name		= init_state->socket_name;
+	api->sched_policy		= init_state->sched_policy;
+	api->sched_param		= init_state->sched_param;
+	api->malloc			= init_state->malloc;
+	api->free			= init_state->free;
+	api->old_log_printf		= init_state->log_printf;
+	api->fatal_error		= init_state->fatal_error;
+	api->security_valid		= init_state->security_valid;
+	api->service_available		= init_state->service_available;
+	api->private_data_size_get	= init_state->private_data_size_get;
+	api->serialize_lock		= init_state->serialize_lock;
+	api->serialize_unlock		= init_state->serialize_unlock;
+	api->sending_allowed		= init_state->sending_allowed;
+	api->sending_allowed_release	= init_state->sending_allowed_release;
+	api->poll_accept_add		= init_state->poll_accept_add;
+	api->poll_dispatch_add		= init_state->poll_dispatch_add;
+	api->poll_dispatch_modify	= init_state->poll_dispatch_modify;
+	api->init_fn_get		= init_state->init_fn_get;
+	api->exit_fn_get		= init_state->exit_fn_get;
+	api->handler_fn_get		= init_state->handler_fn_get;
+
+	log_printf (LOG_DEBUG, "you are using ipc api v1\n");
+
+	_qb_ipc_init ();
+}
+
+static void _qb_ipc_init(void)
+{
+	int server_fd;
+	struct sockaddr_un un_addr;
+	int res;
+
+	/*
+	 * Create socket for IPC clients, name socket, listen for connections
+	 */
+#if defined(QB_SOLARIS)
+	server_fd = socket (PF_UNIX, SOCK_STREAM, 0);
+#else
+	server_fd = socket (PF_LOCAL, SOCK_STREAM, 0);
+#endif
+	if (server_fd == -1) {
+		log_printf (LOG_CRIT, "Cannot create client connections socket.\n");
+		api->fatal_error ("Can't create library listen socket");
+	};
+
+	res = fcntl (server_fd, F_SETFL, O_NONBLOCK);
+	if (res == -1) {
+		char error_str[100];
+		strerror_r (errno, error_str, 100);
+		log_printf (LOG_CRIT, "Could not set non-blocking operation on server socket: %s\n", error_str);
+		api->fatal_error ("Could not set non-blocking operation on server socket");
+	}
+
+	memset (&un_addr, 0, sizeof (struct sockaddr_un));
+	un_addr.sun_family = AF_UNIX;
+#if defined(QB_BSD) || defined(QB_DARWIN)
+	un_addr.sun_len = SUN_LEN(&un_addr);
+#endif
+
+#if defined(QB_LINUX)
+	sprintf (un_addr.sun_path + 1, "%s", api->socket_name);
+#else
+	{
+		struct stat stat_out;
+		res = stat (SOCKETDIR, &stat_out);
+		if (res == -1 || (res == 0 && !S_ISDIR(stat_out.st_mode))) {
+			log_printf (LOG_CRIT, "Required directory not present %s\n", SOCKETDIR);
+			api->fatal_error ("Please create required directory.");
+		}
+		sprintf (un_addr.sun_path, "%s/%s", SOCKETDIR, api->socket_name);
+		unlink (un_addr.sun_path);
+	}
+#endif
+
+	res = bind (server_fd, (struct sockaddr *)&un_addr, QB_SUN_LEN(&un_addr));
+	if (res) {
+		char error_str[100];
+		strerror_r (errno, error_str, 100);
+		log_printf (LOG_CRIT, "Could not bind AF_UNIX (%s): %s.\n", un_addr.sun_path, error_str);
+		api->fatal_error ("Could not bind to AF_UNIX socket\n");
+	}
+
+	/*
+	 * Allow eveyrone to write to the socket since the IPC layer handles
+	 * security automatically
+	 */
+#if !defined(QB_LINUX)
+	res = chmod (un_addr.sun_path, S_IRWXU|S_IRWXG|S_IRWXO);
+#endif
+	listen (server_fd, SERVER_BACKLOG);
+
+	/*
+	 * Setup connection dispatch routine
+	 */
+	api->poll_accept_add (server_fd);
+}
+
+void qb_ipcs_ipc_exit (void)
+{
+	struct qb_list_head *list;
+	struct conn_info *conn_info;
+	unsigned int res;
+
+	for (list = conn_info_qb_list_head.next; list != &conn_info_qb_list_head;
+		list = list->next) {
+
+		conn_info = qb_list_entry (list, struct conn_info, list);
+
+		if (conn_info->state != CONN_STATE_THREAD_ACTIVE)
+			continue;
+
+		ipc_disconnect (conn_info);
+
+#if _POSIX_THREAD_PROCESS_SHARED > 0
+		sem_destroy (&conn_info->control_buffer->sem0);
+		sem_destroy (&conn_info->control_buffer->sem1);
+		sem_destroy (&conn_info->control_buffer->sem2);
+#else
+		semctl (conn_info->semid, 0, IPC_RMID);
+#endif
+
+		/*
+		 * Unmap memory segments
+		 */
+		res = munmap ((void *)conn_info->control_buffer,
+			conn_info->control_size);
+		res = munmap ((void *)conn_info->request_buffer,
+			conn_info->request_size);
+		res = munmap ((void *)conn_info->response_buffer,
+			conn_info->response_size);
+		res = circular_memory_unmap (conn_info->dispatch_buffer,
+			conn_info->dispatch_size);
+	}
+}
+
+int qb_ipcs_ipc_service_exit (unsigned int service)
+{
+	struct qb_list_head *list, *list_next;
+	struct conn_info *conn_info;
+
+	for (list = conn_info_qb_list_head.next; list != &conn_info_qb_list_head;
+		list = list_next) {
+
+		list_next = list->next;
+
+		conn_info = qb_list_entry (list, struct conn_info, list);
+
+		if (conn_info->service != service ||
+		    (conn_info->state != CONN_STATE_THREAD_ACTIVE && conn_info->state != CONN_STATE_THREAD_REQUEST_EXIT)) {
+			continue;
+		}
+
+		ipc_disconnect (conn_info);
+		api->poll_dispatch_destroy (conn_info->fd, NULL);
+		while (conn_info_destroy (conn_info) != -1)
+			;
+
+		/*
+		 * We will return to prevent token loss. Schedwrk will call us again.
+		 */
+		return (-1);
+	}
+
+	/*
+	 * No conn info left in active list. We will traverse thru exit list. If there is any
+	 * conn_info->service == service, we will wait to proper end -> return -1
+	 */
+
+	for (list = conn_info_exit_qb_list_head.next; list != &conn_info_exit_qb_list_head; list = list->next) {
+		conn_info = qb_list_entry (list, struct conn_info, list);
+
+		if (conn_info->service == service) {
+			return (-1);
+		}
+	}
+
+	return (0);
+}
+
+/*
+ * Get the conn info private data
+ */
+void *qb_ipcs_private_data_get (void *conn)
+{
+	struct conn_info *conn_info = (struct conn_info *)conn;
+
+	return (conn_info->private_data);
+}
+
+int qb_ipcs_response_send (void *conn, const void *msg, size_t mlen)
+{
+	struct conn_info *conn_info = (struct conn_info *)conn;
+#if _POSIX_THREAD_PROCESS_SHARED < 1
+	struct sembuf sop;
+#endif
+	int res;
+
+	memcpy (conn_info->response_buffer, msg, mlen);
+
+#if _POSIX_THREAD_PROCESS_SHARED > 0
+	res = sem_post (&conn_info->control_buffer->sem1);
+	if (res == -1) {
+		return (-1);
+	}
+#else
+	sop.sem_num = 1;
+	sop.sem_op = 1;
+	sop.sem_flg = 0;
+
+retry_semop:
+	res = semop (conn_info->semid, &sop, 1);
+	if ((res == -1) && (errno == EINTR || errno == EAGAIN)) {
+		api->stats_increment_value (conn_info->stats_handle, "sem_retry_count");
+		goto retry_semop;
+	} else
+	if ((res == -1) && (errno == EINVAL || errno == EIDRM)) {
+		return (0);
+	}
+#endif
+	api->stats_increment_value (conn_info->stats_handle, "responses");
+	return (0);
+}
+
+int qb_ipcs_response_iov_send (void *conn, const struct iovec *iov, unsigned int iov_len)
+{
+	struct conn_info *conn_info = (struct conn_info *)conn;
+#if _POSIX_THREAD_PROCESS_SHARED < 1
+	struct sembuf sop;
+#endif
+	int res;
+	int write_idx = 0;
+	int i;
+
+	for (i = 0; i < iov_len; i++) {
+		memcpy (&conn_info->response_buffer[write_idx],
+			iov[i].iov_base, iov[i].iov_len);
+		write_idx += iov[i].iov_len;
+	}
+
+#if _POSIX_THREAD_PROCESS_SHARED > 0
+	res = sem_post (&conn_info->control_buffer->sem1);
+	if (res == -1) {
+		return (-1);
+	}
+#else
+	sop.sem_num = 1;
+	sop.sem_op = 1;
+	sop.sem_flg = 0;
+
+retry_semop:
+	res = semop (conn_info->semid, &sop, 1);
+	if ((res == -1) && (errno == EINTR || errno == EAGAIN)) {
+		api->stats_increment_value (conn_info->stats_handle, "sem_retry_count");
+		goto retry_semop;
+	} else
+	if ((res == -1) && (errno == EINVAL || errno == EIDRM)) {
+		return (0);
+	}
+#endif
+	api->stats_increment_value (conn_info->stats_handle, "responses");
+	return (0);
+}
+
+static int shared_mem_dispatch_bytes_left (const struct conn_info *conn_info)
+{
+	unsigned int n_read;
+	unsigned int n_write;
+	unsigned int bytes_left;
+
+	n_read = conn_info->control_buffer->read;
+	n_write = conn_info->control_buffer->write;
+
+	if (n_read <= n_write) {
+		bytes_left = conn_info->dispatch_size - n_write + n_read;
+	} else {
+		bytes_left = n_read - n_write;
+	}
+	if (bytes_left > 0) {
+		bytes_left--;
+	}
+
+	return (bytes_left);
+}
+
+static void memcpy_dwrap (struct conn_info *conn_info, void *msg, unsigned int len)
+{
+	unsigned int write_idx;
+
+	write_idx = conn_info->control_buffer->write;
+
+	memcpy (&conn_info->dispatch_buffer[write_idx], msg, len);
+	conn_info->control_buffer->write = (write_idx + len) % conn_info->dispatch_size;
+}
+
+/**
+ * simulate the behaviour in qb_ipcc.c
+ */
+static int flow_control_event_send (struct conn_info *conn_info, char event)
+{
+	int new_fc = 0;
+
+	if (event == MESSAGE_RES_OUTQ_NOT_EMPTY ||
+		event == MESSAGE_RES_ENABLE_FLOWCONTROL) {
+		new_fc = 1;
+	}
+
+	if (conn_info->flow_control_state != new_fc) {
+		if (new_fc == 1) {
+			log_printf (LOG_INFO, "Enabling flow control for %d, event %d\n",
+				conn_info->client_pid, event);
+		} else {
+			log_printf (LOG_INFO, "Disabling flow control for %d, event %d\n",
+				conn_info->client_pid, event);
+		}
+		conn_info->flow_control_state = new_fc;
+		api->stats_update_value (conn_info->stats_handle, "flow_control",
+			&conn_info->flow_control_state,
+			sizeof(conn_info->flow_control_state));
+		api->stats_increment_value (conn_info->stats_handle, "flow_control_count");
+	}
+
+	return send (conn_info->fd, &event, 1, MSG_NOSIGNAL);
+}
+
+static void msg_send (void *conn, const struct iovec *iov, unsigned int iov_len,
+		      int locked)
+{
+	struct conn_info *conn_info = (struct conn_info *)conn;
+#if _POSIX_THREAD_PROCESS_SHARED < 1
+	struct sembuf sop;
+#endif
+	int res;
+	int i;
+
+	for (i = 0; i < iov_len; i++) {
+		memcpy_dwrap (conn_info, iov[i].iov_base, iov[i].iov_len);
+	}
+
+	if (qb_list_empty (&conn_info->outq_head))
+		res = flow_control_event_send (conn_info, MESSAGE_RES_OUTQ_EMPTY);
+	else
+		res = flow_control_event_send (conn_info, MESSAGE_RES_OUTQ_NOT_EMPTY);
+
+	if (res == -1 && errno == EAGAIN) {
+		if (locked == 0) {
+			pthread_mutex_lock (&conn_info->mutex);
+		}
+		conn_info->pending_semops += 1;
+		if (locked == 0) {
+			pthread_mutex_unlock (&conn_info->mutex);
+		}
+		api->poll_dispatch_modify (conn_info->fd,
+			POLLIN|POLLOUT|POLLNVAL);
+	} else
+	if (res == -1) {
+		ipc_disconnect (conn_info);
+	}
+#if _POSIX_THREAD_PROCESS_SHARED > 0
+	res = sem_post (&conn_info->control_buffer->sem2);
+#else
+	sop.sem_num = 2;
+	sop.sem_op = 1;
+	sop.sem_flg = 0;
+
+retry_semop:
+	res = semop (conn_info->semid, &sop, 1);
+	if ((res == -1) && (errno == EINTR || errno == EAGAIN)) {
+		api->stats_increment_value (conn_info->stats_handle, "sem_retry_count");
+		goto retry_semop;
+	} else
+	if ((res == -1) && (errno == EINVAL || errno == EIDRM)) {
+		return;
+	}
+#endif
+	api->stats_increment_value (conn_info->stats_handle, "dispatched");
+}
+
+static void outq_flush (struct conn_info *conn_info) {
+	struct qb_list_head *list, *list_next;
+	struct outq_item *outq_item;
+	unsigned int bytes_left;
+	struct iovec iov;
+	int res;
+
+	pthread_mutex_lock (&conn_info->mutex);
+	if (qb_list_empty (&conn_info->outq_head)) {
+		res = flow_control_event_send (conn_info, MESSAGE_RES_OUTQ_FLUSH_NR);
+		pthread_mutex_unlock (&conn_info->mutex);
+		return;
+	}
+	for (list = conn_info->outq_head.next;
+		list != &conn_info->outq_head; list = list_next) {
+
+		list_next = list->next;
+		outq_item = qb_list_entry (list, struct outq_item, list);
+		bytes_left = shared_mem_dispatch_bytes_left (conn_info);
+		if (bytes_left > outq_item->mlen) {
+			iov.iov_base = outq_item->msg;
+			iov.iov_len = outq_item->mlen;
+			msg_send (conn_info, &iov, 1, MSG_SEND_UNLOCKED);
+			qb_list_del (list);
+			api->free (iov.iov_base);
+			api->free (outq_item);
+			api->stats_decrement_value (conn_info->stats_handle, "queue_size");
+		} else {
+			break;
+		}
+	}
+	pthread_mutex_unlock (&conn_info->mutex);
+}
+
+static int priv_change (struct conn_info *conn_info)
+{
+	mar_req_priv_change req_priv_change;
+	unsigned int res;
+#if _POSIX_THREAD_PROCESS_SHARED < 1
+	union semun semun;
+	struct semid_ds ipc_set;
+	int i;
+#endif
+
+retry_recv:
+	res = recv (conn_info->fd, &req_priv_change,
+		sizeof (mar_req_priv_change),
+		MSG_NOSIGNAL);
+	if (res == -1 && errno == EINTR) {
+		api->stats_increment_value (conn_info->stats_handle, "recv_retry_count");
+		goto retry_recv;
+	}
+	if (res == -1 && errno == EAGAIN) {
+		api->stats_increment_value (conn_info->stats_handle, "recv_retry_count");
+		goto retry_recv;
+	}
+	if (res == -1 && errno != EAGAIN) {
+		return (-1);
+	}
+#if defined(QB_SOLARIS) || defined(QB_BSD) || defined(QB_DARWIN)
+	/* Error on socket, EOF is detected when recv return 0
+	 */
+	if (res == 0) {
+		return (-1);
+	}
+#endif
+
+#if _POSIX_THREAD_PROCESS_SHARED < 1
+	ipc_set.sem_perm.uid = req_priv_change.euid;
+	ipc_set.sem_perm.gid = req_priv_change.egid;
+	ipc_set.sem_perm.mode = 0600;
+
+	semun.buf = &ipc_set;
+
+	for (i = 0; i < 3; i++) {
+		res = semctl (conn_info->semid, 0, IPC_SET, semun);
+		if (res == -1) {
+			return (-1);
+		}
+	}
+#endif
+	return (0);
+}
+
+static void msg_send_or_queue (void *conn, const struct iovec *iov, unsigned int iov_len)
+{
+	struct conn_info *conn_info = (struct conn_info *)conn;
+	unsigned int bytes_left;
+	unsigned int bytes_msg = 0;
+	int i;
+	struct outq_item *outq_item;
+	char *write_buf = 0;
+
+	/*
+	 * Exit transmission if the connection is dead
+	 */
+	if (ipc_thread_active (conn) == 0) {
+		return;
+	}
+
+	bytes_left = shared_mem_dispatch_bytes_left (conn_info);
+	for (i = 0; i < iov_len; i++) {
+		bytes_msg += iov[i].iov_len;
+	}
+	if (bytes_left < bytes_msg || qb_list_empty (&conn_info->outq_head) == 0) {
+		outq_item = api->malloc (sizeof (struct outq_item));
+		if (outq_item == NULL) {
+			ipc_disconnect (conn);
+			return;
+		}
+		outq_item->msg = api->malloc (bytes_msg);
+		if (outq_item->msg == 0) {
+			api->free (outq_item);
+			ipc_disconnect (conn);
+			return;
+		}
+
+		write_buf = outq_item->msg;
+		for (i = 0; i < iov_len; i++) {
+			memcpy (write_buf, iov[i].iov_base, iov[i].iov_len);
+			write_buf += iov[i].iov_len;
+		}
+		outq_item->mlen = bytes_msg;
+		qb_list_init (&outq_item->list);
+		pthread_mutex_lock (&conn_info->mutex);
+		if (qb_list_empty (&conn_info->outq_head)) {
+			conn_info->notify_flow_control_enabled = 1;
+			api->poll_dispatch_modify (conn_info->fd,
+				POLLIN|POLLOUT|POLLNVAL);
+		}
+		qb_list_add_tail (&outq_item->list, &conn_info->outq_head);
+		pthread_mutex_unlock (&conn_info->mutex);
+		api->stats_increment_value (conn_info->stats_handle, "queue_size");
+		return;
+	}
+	msg_send (conn, iov, iov_len, MSG_SEND_LOCKED);
+}
+
+void qb_ipcs_refcount_inc (void *conn)
+{
+	struct conn_info *conn_info = (struct conn_info *)conn;
+
+	pthread_mutex_lock (&conn_info->mutex);
+	conn_info->refcount++;
+	pthread_mutex_unlock (&conn_info->mutex);
+}
+
+void qb_ipcs_refcount_dec (void *conn)
+{
+	struct conn_info *conn_info = (struct conn_info *)conn;
+
+	pthread_mutex_lock (&conn_info->mutex);
+	conn_info->refcount--;
+	pthread_mutex_unlock (&conn_info->mutex);
+}
+
+int qb_ipcs_dispatch_send (void *conn, const void *msg, size_t mlen)
+{
+	struct iovec iov;
+
+	iov.iov_base = (void *)msg;
+	iov.iov_len = mlen;
+
+	msg_send_or_queue (conn, &iov, 1);
+	return (0);
+}
+
+int qb_ipcs_dispatch_iov_send (void *conn, const struct iovec *iov, unsigned int iov_len)
+{
+	msg_send_or_queue (conn, iov, iov_len);
+	return (0);
+}
+
+int qb_ipcs_handler_accept (
+	int fd,
+	int revent,
+	void *data)
+{
+	socklen_t addrlen;
+	struct sockaddr_un un_addr;
+	int new_fd;
+#ifdef QB_LINUX
+	int on = 1;
+#endif
+	int res;
+
+	addrlen = sizeof (struct sockaddr_un);
+
+retry_accept:
+	new_fd = accept (fd, (struct sockaddr *)&un_addr, &addrlen);
+	if (new_fd == -1 && errno == EINTR) {
+		goto retry_accept;
+	}
+
+	if (new_fd == -1) {
+		char error_str[100];
+		strerror_r (errno, error_str, 100);
+		log_printf (LOG_ERR,
+			"Could not accept Library connection: %s\n", error_str);
+		return (0); /* This is an error, but -1 would indicate disconnect from poll loop */
+	}
+
+	res = fcntl (new_fd, F_SETFL, O_NONBLOCK);
+	if (res == -1) {
+		char error_str[100];
+		strerror_r (errno, error_str, 100);
+		log_printf (LOG_ERR,
+			"Could not set non-blocking operation on library connection: %s\n",
+			error_str);
+		close (new_fd);
+		return (0); /* This is an error, but -1 would indicate disconnect from poll loop */
+	}
+
+	/*
+	 * Valid accept
+	 */
+
+	/*
+	 * Request credentials of sender provided by kernel
+	 */
+#ifdef QB_LINUX
+	setsockopt(new_fd, SOL_SOCKET, SO_PASSCRED, &on, sizeof (on));
+#endif
+
+	res = conn_info_create (new_fd);
+	if (res != 0) {
+		close (new_fd);
+	}
+
+	return (0);
+}
+
+static char * pid_to_name (pid_t pid, char *out_name, size_t name_len)
+{
+	char *name;
+	char *rest;
+	FILE *fp;
+	char fname[32];
+	char buf[256];
+
+	snprintf (fname, 32, "/proc/%d/stat", pid);
+	fp = fopen (fname, "r");
+	if (!fp) {
+		return NULL;
+	}
+
+	if (fgets (buf, sizeof (buf), fp) == NULL) {
+		fclose (fp);
+		return NULL;
+	}
+	fclose (fp);
+
+	name = strrchr (buf, '(');
+	if (!name) {
+		return NULL;
+	}
+
+	/* move past the bracket */
+	name++;
+
+	rest = strrchr (buf, ')');
+
+	if (rest == NULL || rest[1] != ' ') {
+		return NULL;
+	}
+
+	*rest = '\0';
+	/* move past the NULL and space */
+	rest += 2;
+
+	/* copy the name */
+	strncpy (out_name, name, name_len);
+	out_name[name_len - 1] = '\0';
+	return out_name;
+}
+
+static void qb_ipcs_init_conn_stats (
+	struct conn_info *conn)
+{
+	char conn_name[42];
+	char proc_name[32];
+
+	if (conn->client_pid > 0) {
+		if (pid_to_name (conn->client_pid, proc_name, sizeof(proc_name)))
+			snprintf (conn_name, sizeof(conn_name), "%s:%d:%d", proc_name, conn->client_pid, conn->fd);
+		else
+			snprintf (conn_name, sizeof(conn_name), "%d:%d", conn->client_pid, conn->fd);
+	} else
+		snprintf (conn_name, sizeof(conn_name), "%d", conn->fd);
+
+	conn->stats_handle = api->stats_create_connection (conn_name, conn->client_pid, conn->fd);
+	api->stats_update_value (conn->stats_handle, "service_id",
+		&conn->service, sizeof(conn->service));
+}
+
+int qb_ipcs_handler_dispatch (
+	int fd,
+	int revent,
+	void *context)
+{
+	mar_req_setup_t *req_setup;
+	struct conn_info *conn_info = (struct conn_info *)context;
+	int res;
+	char buf;
+
+
+	if (ipc_thread_exiting (conn_info)) {
+		return conn_info_destroy (conn_info);
+	}
+
+	/*
+	 * If an error occurs, request exit
+	 */
+	if (revent & (POLLERR|POLLHUP)) {
+		ipc_disconnect (conn_info);
+		return (0);
+	}
+
+	/*
+	 * Read the header and process it
+	 */
+	if (conn_info->service == SOCKET_SERVICE_INIT && (revent & POLLIN)) {
+		/*
+		 * Receive in a nonblocking fashion the request
+		 * IF security invalid, send ERR_SECURITY, otherwise
+		 * send OK
+		 */
+		res = req_setup_recv (conn_info);
+		if (res == -1) {
+			req_setup_send (conn_info, EACCES);
+		}
+		if (res != 1) {
+			return (0);
+		}
+
+		pthread_mutex_init (&conn_info->mutex, NULL);
+		req_setup = (mar_req_setup_t *)conn_info->setup_msg;
+		/*
+		 * Is the service registered ?
+		 */
+		if (api->service_available (req_setup->service) == 0) {
+			req_setup_send (conn_info, EEXIST);
+			ipc_disconnect (conn_info);
+			return (0);
+		}
+		req_setup_send (conn_info, 0);
+
+#if _POSIX_THREAD_PROCESS_SHARED < 1
+		conn_info->semkey = req_setup->semkey;
+#endif
+		res = memory_map (
+			req_setup->control_file,
+			req_setup->control_size,
+			(void *)&conn_info->control_buffer);
+		conn_info->control_size = req_setup->control_size;
+
+		res = memory_map (
+			req_setup->request_file,
+			req_setup->request_size,
+			(void *)&conn_info->request_buffer);
+		conn_info->request_size = req_setup->request_size;
+
+		res = memory_map (
+			req_setup->response_file,
+			req_setup->response_size,
+			(void *)&conn_info->response_buffer);
+		conn_info->response_size = req_setup->response_size;
+
+		res = circular_memory_map (
+			req_setup->dispatch_file,
+			req_setup->dispatch_size,
+			(void *)&conn_info->dispatch_buffer);
+		conn_info->dispatch_size = req_setup->dispatch_size;
+
+		conn_info->service = req_setup->service;
+		conn_info->refcount = 0;
+		conn_info->notify_flow_control_enabled = 0;
+		conn_info->setup_bytes_read = 0;
+
+#if _POSIX_THREAD_PROCESS_SHARED < 1
+		conn_info->semid = semget (conn_info->semkey, 3, 0600);
+#endif
+		conn_info->pending_semops = 0;
+
+		/*
+		 * ipc thread is the only reference at startup
+		 */
+		conn_info->refcount = 1;
+		conn_info->state = CONN_STATE_THREAD_ACTIVE;
+
+		conn_info->private_data = api->malloc (api->private_data_size_get (conn_info->service));
+		memset (conn_info->private_data, 0,
+			api->private_data_size_get (conn_info->service));
+
+		api->init_fn_get (conn_info->service) (conn_info);
+
+		/* create stats objects */
+		qb_ipcs_init_conn_stats (conn_info);
+
+		pthread_attr_init (&conn_info->thread_attr);
+		/*
+		* IA64 needs more stack space then other arches
+		*/
+		#if defined(__ia64__)
+		pthread_attr_setstacksize (&conn_info->thread_attr, 400000);
+		#else
+		pthread_attr_setstacksize (&conn_info->thread_attr, 200000);
+		#endif
+
+		pthread_attr_setdetachstate (&conn_info->thread_attr, PTHREAD_CREATE_JOINABLE);
+		res = pthread_create (&conn_info->thread,
+			&conn_info->thread_attr,
+			pthread_ipc_consumer,
+			conn_info);
+
+		/*
+		 * Security check - disallow multiple configurations of
+		 * the ipc connection
+		 */
+		if (conn_info->service == SOCKET_SERVICE_INIT) {
+			conn_info->service = -1;
+		}
+	} else
+	if (revent & POLLIN) {
+		qb_ipcs_refcount_inc (conn_info);
+		res = recv (fd, &buf, 1, MSG_NOSIGNAL);
+		if (res == 1) {
+			switch (buf) {
+			case MESSAGE_REQ_OUTQ_FLUSH:
+				outq_flush (conn_info);
+				break;
+			case MESSAGE_REQ_CHANGE_EUID:
+				if (priv_change (conn_info) == -1) {
+					ipc_disconnect (conn_info);
+				}
+				break;
+			default:
+				res = 0;
+				break;
+			}
+		}
+#if defined(QB_SOLARIS) || defined(QB_BSD) || defined(QB_DARWIN)
+		/* On many OS poll never return POLLHUP or POLLERR.
+		 * EOF is detected when recvmsg return 0.
+		 */
+		if (res == 0) {
+			ipc_disconnect (conn_info);
+			qb_ipcs_refcount_dec (conn_info);
+			return (0);
+		}
+#endif
+		qb_ipcs_refcount_dec (conn_info);
+	}
+
+	qb_ipcs_refcount_inc (conn_info);
+	pthread_mutex_lock (&conn_info->mutex);
+	if ((conn_info->state == CONN_STATE_THREAD_ACTIVE) && (revent & POLLOUT)) {
+		if (qb_list_empty (&conn_info->outq_head))
+			buf = MESSAGE_RES_OUTQ_EMPTY;
+		else
+			buf = MESSAGE_RES_OUTQ_NOT_EMPTY;
+
+		for (; conn_info->pending_semops;) {
+			res = flow_control_event_send (conn_info, buf);
+			if (res == 1) {
+				conn_info->pending_semops--;
+			} else {
+				break;
+			}
+		}
+		if (conn_info->notify_flow_control_enabled) {
+			res = flow_control_event_send (conn_info, MESSAGE_RES_ENABLE_FLOWCONTROL);
+			if (res == 1) {
+				conn_info->notify_flow_control_enabled = 0;
+			}
+		}
+		if (conn_info->notify_flow_control_enabled == 0 &&
+			conn_info->pending_semops == 0) {
+
+			api->poll_dispatch_modify (conn_info->fd,
+				POLLIN|POLLNVAL);
+		}
+	}
+	pthread_mutex_unlock (&conn_info->mutex);
+	qb_ipcs_refcount_dec (conn_info);
+
+	return (0);
+}
+
diff --git a/lib/logsys.c b/lib/logsys.c
new file mode 100644
index 0000000..bb77e56
--- /dev/null
+++ b/lib/logsys.c
@@ -0,0 +1,1698 @@
+/*
+ * Copyright (c) 2002-2004 MontaVista Software, Inc.
+ * Copyright (c) 2006-2010 Red Hat, Inc.
+ *
+ * Author: Steven Dake (sdake@redhat.com)
+ * Author: Lon Hohberger (lhh@redhat.com)
+ * Author: Fabio M. Di Nitto (fdinitto@redhat.com)
+ *
+ * All rights reserved.
+ *
+ * This software licensed under BSD license, the text of which follows:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - 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.
+ * - Neither the name of the MontaVista Software, Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
+ */
+
+#include <config.h>
+
+#include "os_base.h"
+#include <ctype.h>
+#include <sys/time.h>
+#include <syslog.h>
+#include <pthread.h>
+
+#include <qb/qblogsys.h>
+
+#define YIELD_AFTER_LOG_OPS 10
+
+#define MIN(x,y) ((x) < (y) ? (x) : (y))
+
+#define ROUNDUP(x, y) ((((x) + ((y) - 1)) / (y)) * (y))
+
+/*
+ * syslog prioritynames, facility names to value mapping
+ * Some C libraries build this in to their headers, but it is non-portable
+ * so qb_logsys supplies its own version.
+ */
+struct syslog_names {
+	const char *c_name;
+	int c_val;
+};
+
+struct syslog_names prioritynames[] =
+{
+	{ "alert", LOG_ALERT },
+	{ "crit", LOG_CRIT },
+	{ "debug", LOG_DEBUG },
+	{ "emerg", LOG_EMERG },
+	{ "err", LOG_ERR },
+	{ "error", LOG_ERR },
+	{ "info", LOG_INFO },
+	{ "notice", LOG_NOTICE },
+	{ "warning", LOG_WARNING },
+	{ NULL, -1 }
+};
+
+struct syslog_names facilitynames[] =
+{
+	{ "auth", LOG_AUTH },
+	{ "cron", LOG_CRON },
+	{ "daemon", LOG_DAEMON },
+	{ "kern", LOG_KERN },
+	{ "lpr", LOG_LPR },
+	{ "mail", LOG_MAIL },
+	{ "news", LOG_NEWS },
+	{ "syslog", LOG_SYSLOG },
+	{ "user", LOG_USER },
+	{ "uucp", LOG_UUCP },
+	{ "local0", LOG_LOCAL0 },
+	{ "local1", LOG_LOCAL1 },
+	{ "local2", LOG_LOCAL2 },
+	{ "local3", LOG_LOCAL3 },
+	{ "local4", LOG_LOCAL4 },
+	{ "local5", LOG_LOCAL5 },
+	{ "local6", LOG_LOCAL6 },
+	{ "local7", LOG_LOCAL7 },
+	{ NULL, -1 }
+};
+
+
+/*
+ * These are not static so they can be read from the core file
+ */
+int *flt_data;
+
+unsigned int flt_data_size;
+
+#define COMBINE_BUFFER_SIZE 2048
+
+/* values for qb_logsys_logger init_status */
+#define QB_LOGSYS_LOGGER_INIT_DONE		0
+#define QB_LOGSYS_LOGGER_NEEDS_INIT	1
+
+static int qb_logsys_system_needs_init = QB_LOGSYS_LOGGER_NEEDS_INIT;
+
+static int qb_logsys_sched_param_queued = 0;
+static int qb_logsys_sched_policy;
+static struct sched_param qb_logsys_sched_param;
+
+static int qb_logsys_after_log_ops_yield = 10;
+
+/*
+ * need unlogical order to preserve 64bit alignment
+ */
+struct qb_logsys_logger {
+	char subsys[QB_LOGSYS_MAX_SUBSYS_NAMELEN];	/* subsystem name */
+	char *logfile;				/* log to file */
+	FILE *logfile_fp;			/* track file descriptor */
+	unsigned int mode;			/* subsystem mode */
+	unsigned int debug;			/* debug on|off */
+	int syslog_facility;			/* facility */
+	int syslog_priority;			/* priority */
+	int logfile_priority;			/* priority to file */
+	int init_status;			/* internal field to handle init queues
+						   for subsystems */
+};
+
+/*
+ * operating global variables
+ */
+
+static struct qb_logsys_logger qb_logsys_loggers[QB_LOGSYS_MAX_SUBSYS_COUNT + 1];
+
+static int wthread_active = 0;
+
+static int wthread_should_exit = 0;
+
+static pthread_mutex_t qb_logsys_config_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+static unsigned int records_written = 1;
+
+static pthread_t qb_logsys_thread_id;
+
+static pthread_cond_t qb_logsys_cond;
+
+static pthread_mutex_t qb_logsys_cond_mutex;
+
+#if defined(HAVE_PTHREAD_SPIN_LOCK)
+static pthread_spinlock_t qb_logsys_idx_spinlock;
+#else
+static pthread_mutex_t qb_logsys_idx_mutex = PTHREAD_MUTEX_INITIALIZER;
+#endif
+
+static unsigned int log_rec_idx;
+
+static int qb_logsys_buffer_full = 0;
+
+static char *format_buffer=NULL;
+
+static int log_requests_pending = 0;
+
+static int log_requests_lost = 0;
+
+void *qb_logsys_rec_end;
+
+#define FDHEAD_INDEX	(flt_data_size)
+
+#define FDTAIL_INDEX 	(flt_data_size + 1)
+
+#define FDMAX_ARGS	64
+
+/* forward declarations */
+static void qb_logsys_close_logfile(int subsysid);
+
+#ifdef QB_LOGSYS_DEBUG
+static char *decode_mode(int subsysid, char *buf, size_t buflen)
+{
+	memset(buf, 0, buflen);
+
+	if (qb_logsys_loggers[subsysid].mode & QB_LOGSYS_MODE_OUTPUT_FILE)
+		snprintf(buf+strlen(buf), buflen, "FILE,");
+
+	if (qb_logsys_loggers[subsysid].mode & QB_LOGSYS_MODE_OUTPUT_STDERR)
+		snprintf(buf+strlen(buf), buflen, "STDERR,");
+
+	if (qb_logsys_loggers[subsysid].mode & QB_LOGSYS_MODE_OUTPUT_SYSLOG)
+		snprintf(buf+strlen(buf), buflen, "SYSLOG,");
+
+	if (subsysid == QB_LOGSYS_MAX_SUBSYS_COUNT) {
+		if (qb_logsys_loggers[subsysid].mode & QB_LOGSYS_MODE_FORK)
+			snprintf(buf+strlen(buf), buflen, "FORK,");
+
+		if (qb_logsys_loggers[subsysid].mode & QB_LOGSYS_MODE_THREADED)
+			snprintf(buf+strlen(buf), buflen, "THREADED,");
+	}
+
+	memset(buf+strlen(buf)-1,0,1);
+
+	return buf;
+}
+
+static const char *decode_debug(int subsysid)
+{
+	if (qb_logsys_loggers[subsysid].debug)
+		return "on";
+
+	return "off";
+}
+
+static const char *decode_status(int subsysid)
+{
+	if (!qb_logsys_loggers[subsysid].init_status)
+		return "INIT_DONE";
+
+	return "NEEDS_INIT";
+}
+
+static void dump_subsys_config(int subsysid)
+{
+	char modebuf[1024];
+
+	fprintf(stderr,
+		"ID: %d\n"
+		"subsys: %s\n"
+		"logfile: %s\n"
+		"logfile_fp: %p\n"
+		"mode: %s\n"
+		"debug: %s\n"
+		"syslog_fac: %s\n"
+		"syslog_pri: %s\n"
+		"logfile_pri: %s\n"
+		"init_status: %s\n",
+		subsysid,
+		qb_logsys_loggers[subsysid].subsys,
+		qb_logsys_loggers[subsysid].logfile,
+		qb_logsys_loggers[subsysid].logfile_fp,
+		decode_mode(subsysid, modebuf, sizeof(modebuf)),
+		decode_debug(subsysid),
+		qb_logsys_facility_name_get(qb_logsys_loggers[subsysid].syslog_facility),
+		qb_logsys_priority_name_get(qb_logsys_loggers[subsysid].syslog_priority),
+		qb_logsys_priority_name_get(qb_logsys_loggers[subsysid].logfile_priority),
+		decode_status(subsysid));
+}
+
+static void dump_full_config(void)
+{
+	int i;
+
+	for (i = 0; i <= QB_LOGSYS_MAX_SUBSYS_COUNT; i++) {
+		if (strlen(qb_logsys_loggers[i].subsys) > 0)
+			dump_subsys_config(i);
+	}
+}
+#endif
+
+/*
+ * Helpers for _logsys_log_rec functionality
+ */
+static inline void my_memcpy_32bit (int *dest, const int *src, unsigned int words)
+{
+	unsigned int word_idx;
+	for (word_idx = 0; word_idx < words; word_idx++) {
+		dest[word_idx] = src[word_idx];
+	}
+}
+
+static inline void my_memcpy_8bit (char *dest, const char *src,
+				   unsigned int bytes)
+{
+	unsigned int byte_idx;
+
+	for (byte_idx = 0; byte_idx < bytes; byte_idx++) {
+		dest[byte_idx] = src[byte_idx];
+	}
+}
+
+#if defined(HAVE_PTHREAD_SPIN_LOCK)
+static void qb_logsys_lock (void)
+{
+	pthread_spin_lock (&qb_logsys_idx_spinlock);
+}
+static void qb_logsys_unlock (void)
+{
+	pthread_spin_unlock (&qb_logsys_idx_spinlock);
+}
+#else
+static void qb_logsys_lock (void)
+{
+	pthread_mutex_lock (&qb_logsys_idx_mutex);
+}
+static void qb_logsys_unlock (void)
+{
+	pthread_mutex_unlock (&qb_logsys_idx_mutex);
+}
+#endif
+
+/*
+ * Before any write operation, a reclaim on the buffer area must be executed
+ */
+static inline void records_reclaim (unsigned int idx, unsigned int words)
+{
+	unsigned int should_reclaim;
+
+	should_reclaim = 0;
+
+	if ((idx + words) >= flt_data_size) {
+		qb_logsys_buffer_full = 1;
+	}
+	if (qb_logsys_buffer_full == 0) {
+		return;
+	}
+
+	qb_logsys_lock();
+	if (flt_data[FDTAIL_INDEX] > flt_data[FDHEAD_INDEX]) {
+		if (idx + words >= flt_data[FDTAIL_INDEX]) {
+			should_reclaim = 1;
+		}
+	} else {
+		if ((idx + words) >= (flt_data[FDTAIL_INDEX] + flt_data_size)) {
+			should_reclaim = 1;
+		}
+	}
+
+	if (should_reclaim) {
+		int words_needed = 0;
+
+		words_needed = words + 1;
+		do {
+			unsigned int old_tail;
+
+			words_needed -= flt_data[flt_data[FDTAIL_INDEX]];
+			old_tail = flt_data[FDTAIL_INDEX];
+			flt_data[FDTAIL_INDEX] =
+				(flt_data[FDTAIL_INDEX] +
+				flt_data[flt_data[FDTAIL_INDEX]]) % (flt_data_size);
+			if (log_rec_idx == old_tail) {
+				log_requests_lost += 1;
+				log_rec_idx = flt_data[FDTAIL_INDEX];
+			}
+		} while (words_needed > 0);
+	}
+	qb_logsys_unlock();
+}
+
+#define idx_word_step(idx)						\
+do {									\
+	if (idx > (flt_data_size - 1)) {				\
+		idx = 0;						\
+	}								\
+} while (0);
+
+#define idx_buffer_step(idx)						\
+do {									\
+	if (idx > (flt_data_size - 1)) {				\
+		idx = ((idx) % (flt_data_size));			\
+	}								\
+} while (0);
+
+/*
+ * Internal threaded logging implementation
+ */
+static inline int strcpy_cutoff (char *dest, const char *src, size_t cutoff,
+				 size_t buf_len)
+{
+	size_t len = strlen (src);
+	if (buf_len <= 1) {
+		if (buf_len == 0)
+			dest[0] = 0;
+		return 0;
+	}
+
+	if (cutoff == 0) {
+		cutoff = len;
+	}
+
+	cutoff = MIN (cutoff, buf_len - 1);
+	len = MIN (len, cutoff);
+	memcpy (dest, src, len);
+	memset (dest + len, ' ', cutoff - len);
+	dest[cutoff] = '\0';
+
+	return (cutoff);
+}
+
+static const char log_month_name[][4] = {
+	"Jan", "Feb", "Mar", "Apr", "May", "Jun",
+	"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+};
+
+/*
+ * %s SUBSYSTEM
+ * %n FUNCTION NAME
+ * %f FILENAME
+ * %l FILELINE
+ * %p PRIORITY
+ * %t TIMESTAMP
+ * %b BUFFER
+ *
+ * any number between % and character specify field length to pad or chop
+*/
+static void log_printf_to_logs (
+	unsigned int rec_ident,
+	const char *file_name,
+	const char *function_name,
+	int file_line,
+	const char *buffer)
+{
+	char normal_output_buffer[COMBINE_BUFFER_SIZE];
+	char syslog_output_buffer[COMBINE_BUFFER_SIZE];
+	char char_time[128];
+	char line_no[30];
+	unsigned int format_buffer_idx = 0;
+	unsigned int normal_output_buffer_idx = 0;
+	unsigned int syslog_output_buffer_idx = 0;
+	struct timeval tv;
+	size_t cutoff;
+	unsigned int normal_len, syslog_len;
+	int subsysid;
+	unsigned int level;
+	int c;
+	struct tm tm_res;
+
+	if (QB_LOGSYS_DECODE_RECID(rec_ident) != QB_LOGSYS_RECID_LOG) {
+		return;
+	}
+
+	subsysid = QB_LOGSYS_DECODE_SUBSYSID(rec_ident);
+	level = QB_LOGSYS_DECODE_LEVEL(rec_ident);
+
+	while ((c = format_buffer[format_buffer_idx])) {
+		cutoff = 0;
+		if (c != '%') {
+			normal_output_buffer[normal_output_buffer_idx++] = c;
+			syslog_output_buffer[syslog_output_buffer_idx++] = c;
+			format_buffer_idx++;
+		} else {
+			const char *normal_p, *syslog_p;
+
+			format_buffer_idx += 1;
+			if (isdigit (format_buffer[format_buffer_idx])) {
+				cutoff = atoi (&format_buffer[format_buffer_idx]);
+			}
+			while (isdigit (format_buffer[format_buffer_idx])) {
+				format_buffer_idx += 1;
+			}
+
+			switch (format_buffer[format_buffer_idx]) {
+				case 's':
+					normal_p = qb_logsys_loggers[subsysid].subsys;
+					syslog_p = qb_logsys_loggers[subsysid].subsys;
+					break;
+
+				case 'n':
+					normal_p = function_name;
+					syslog_p = function_name;
+					break;
+
+				case 'f':
+					normal_p = file_name;
+					syslog_p = file_name;
+					break;
+
+				case 'l':
+					sprintf (line_no, "%d", file_line);
+					normal_p = line_no;
+					syslog_p = line_no;
+					break;
+
+				case 't':
+					gettimeofday (&tv, NULL);
+					(void)localtime_r ((time_t *)&tv.tv_sec, &tm_res);
+					snprintf (char_time, sizeof (char_time), "%s %02d %02d:%02d:%02d",
+					    log_month_name[tm_res.tm_mon], tm_res.tm_mday, tm_res.tm_hour,
+					    tm_res.tm_min, tm_res.tm_sec);
+					normal_p = char_time;
+
+					/*
+					 * syslog does timestamping on its own.
+					 * also strip extra space in case.
+					 */
+					syslog_p = "";
+					break;
+
+				case 'b':
+					normal_p = buffer;
+					syslog_p = buffer;
+					break;
+
+				case 'p':
+					normal_p = qb_logsys_loggers[QB_LOGSYS_MAX_SUBSYS_COUNT].subsys;
+					syslog_p = "";
+					break;
+
+				default:
+					normal_p = "";
+					syslog_p = "";
+					break;
+			}
+			normal_len = strcpy_cutoff (normal_output_buffer + normal_output_buffer_idx,
+					     normal_p, cutoff,
+					     (sizeof (normal_output_buffer)
+					      - normal_output_buffer_idx));
+			normal_output_buffer_idx += normal_len;
+			syslog_len = strcpy_cutoff (syslog_output_buffer + syslog_output_buffer_idx,
+					     syslog_p, cutoff,
+					     (sizeof (syslog_output_buffer)
+					      - syslog_output_buffer_idx));
+			syslog_output_buffer_idx += syslog_len;
+			format_buffer_idx += 1;
+		}
+		if ((normal_output_buffer_idx >= sizeof (normal_output_buffer) - 2) ||
+		    (syslog_output_buffer_idx >= sizeof (syslog_output_buffer) - 1)) {
+			/* Note: we make allowance for '\0' at the end of
+			 * both of these arrays and normal_output_buffer also
+			 * needs a '\n'.
+			 */
+			break;
+		}
+	}
+
+	normal_output_buffer[normal_output_buffer_idx] = '\0';
+	syslog_output_buffer[syslog_output_buffer_idx] = '\0';
+
+	/*
+	 * Output to syslog
+	 */
+	if ((qb_logsys_loggers[subsysid].mode & QB_LOGSYS_MODE_OUTPUT_SYSLOG) &&
+	     ((level <= qb_logsys_loggers[subsysid].syslog_priority) ||
+	     (qb_logsys_loggers[subsysid].debug != 0))) {
+		syslog (level | qb_logsys_loggers[subsysid].syslog_facility, "%s", syslog_output_buffer);
+	}
+
+	/*
+	 * Terminate string with \n \0
+	 */
+	normal_output_buffer[normal_output_buffer_idx++] = '\n';
+	normal_output_buffer[normal_output_buffer_idx] = '\0';
+
+	/*
+	 * Output to configured file
+	 */
+	if (((qb_logsys_loggers[subsysid].mode & QB_LOGSYS_MODE_OUTPUT_FILE) &&
+	     (qb_logsys_loggers[subsysid].logfile_fp != NULL)) &&
+	    ((level <= qb_logsys_loggers[subsysid].logfile_priority) ||
+	     (qb_logsys_loggers[subsysid].debug != 0))) {
+		/*
+		 * Output to a file
+		 */
+		if ((fwrite (normal_output_buffer, strlen (normal_output_buffer), 1,
+			    qb_logsys_loggers[subsysid].logfile_fp) < 1) ||
+		    (fflush (qb_logsys_loggers[subsysid].logfile_fp) == EOF)) {
+			char tmpbuffer[1024];
+			/*
+			 * if we are here, it's bad.. it's really really bad.
+			 * Best thing would be to light a candle in a church
+			 * and pray.
+			 */
+			snprintf(tmpbuffer, sizeof(tmpbuffer),
+				"QB_LOGSYS EMERGENCY: %s Unable to write to %s.",
+				qb_logsys_loggers[subsysid].subsys,
+				qb_logsys_loggers[subsysid].logfile);
+			pthread_mutex_lock (&qb_logsys_config_mutex);
+			qb_logsys_close_logfile(subsysid);
+			qb_logsys_loggers[subsysid].mode &= ~QB_LOGSYS_MODE_OUTPUT_FILE;
+			pthread_mutex_unlock (&qb_logsys_config_mutex);
+			log_printf_to_logs(
+					   QB_LOGSYS_ENCODE_RECID(
+						QB_LOGSYS_LEVEL_EMERG,
+						subsysid,
+						QB_LOGSYS_RECID_LOG),
+					   __FILE__, __FUNCTION__, __LINE__,
+					   tmpbuffer);
+		}
+	}
+
+	/*
+	 * Output to stderr
+	 */
+	if ((qb_logsys_loggers[subsysid].mode & QB_LOGSYS_MODE_OUTPUT_STDERR) &&
+	     ((level <= qb_logsys_loggers[subsysid].logfile_priority) ||
+	     (qb_logsys_loggers[subsysid].debug != 0))) {
+		if (write (STDERR_FILENO, normal_output_buffer, strlen (normal_output_buffer)) < 0) {
+			char tmpbuffer[1024];
+			/*
+			 * if we are here, it's bad.. it's really really bad.
+			 * Best thing would be to light 20 candles for each saint
+			 * in the calendar and pray a lot...
+			 */
+			pthread_mutex_lock (&qb_logsys_config_mutex);
+			qb_logsys_loggers[subsysid].mode &= ~QB_LOGSYS_MODE_OUTPUT_STDERR;
+			pthread_mutex_unlock (&qb_logsys_config_mutex);
+			snprintf(tmpbuffer, sizeof(tmpbuffer),
+				"QB_LOGSYS EMERGENCY: %s Unable to write to STDERR.",
+				qb_logsys_loggers[subsysid].subsys);
+			log_printf_to_logs(
+					   QB_LOGSYS_ENCODE_RECID(
+						QB_LOGSYS_LEVEL_EMERG,
+						subsysid,
+						QB_LOGSYS_RECID_LOG),
+					   __FILE__, __FUNCTION__, __LINE__,
+					   tmpbuffer);
+		}
+	}
+}
+
+static void record_print (const char *buf)
+{
+	const int *buf_uint32t = (const int *)buf;
+	unsigned int rec_size = buf_uint32t[0];
+	unsigned int rec_ident = buf_uint32t[1];
+	unsigned int file_line = buf_uint32t[2];
+	unsigned int i;
+	unsigned int words_processed;
+	unsigned int arg_size_idx;
+	const void *arguments[FDMAX_ARGS];
+	unsigned int arg_count;
+
+	arg_size_idx = 4;
+	words_processed = 4;
+	arg_count = 0;
+
+	for (i = 0; words_processed < rec_size; i++) {
+		arguments[arg_count++] = &buf_uint32t[arg_size_idx + 1];
+		arg_size_idx += buf_uint32t[arg_size_idx] + 1;
+		words_processed += buf_uint32t[arg_size_idx] + 1;
+	}
+
+	/*
+	 * (char *)arguments[0] -> subsystem
+	 * (char *)arguments[1] -> file_name
+	 * (char *)arguments[2] -> function_name
+	 * (char *)arguments[3] -> message
+	 */
+
+	log_printf_to_logs (
+		rec_ident,
+		(char *)arguments[1],
+		(char *)arguments[2],
+		file_line,
+		(char *)arguments[3]);
+}
+
+static int record_read (char *buf, int rec_idx, int *log_msg) {
+	unsigned int rec_size;
+	unsigned int rec_ident;
+	int firstcopy, secondcopy;
+
+	rec_size = flt_data[rec_idx];
+	rec_ident = flt_data[(rec_idx + 1) % flt_data_size];
+
+	/*
+	 * Not a log record
+	 */
+	if (QB_LOGSYS_DECODE_RECID(rec_ident) != QB_LOGSYS_RECID_LOG) {
+		*log_msg = 0;
+		return ((rec_idx + rec_size) % flt_data_size);
+	}
+
+	/*
+	 * A log record
+	 */
+	*log_msg = 1;
+
+        firstcopy = rec_size;
+        secondcopy = 0;
+        if (firstcopy + rec_idx > flt_data_size) {
+                firstcopy = flt_data_size - rec_idx;
+                secondcopy -= firstcopy - rec_size;
+        }
+        memcpy (&buf[0], &flt_data[rec_idx], firstcopy << 2);
+        if (secondcopy) {
+                memcpy (&buf[(firstcopy << 2)], &flt_data[0], secondcopy << 2);
+        }
+        return ((rec_idx + rec_size) % flt_data_size);
+}
+
+static inline void wthread_signal (void)
+{
+	if (wthread_active == 0) {
+		return;
+	}
+	pthread_mutex_lock (&qb_logsys_cond_mutex);
+	pthread_cond_signal (&qb_logsys_cond);
+	pthread_mutex_unlock (&qb_logsys_cond_mutex);
+}
+
+static inline void wthread_wait (void)
+{
+	pthread_mutex_lock (&qb_logsys_cond_mutex);
+	pthread_cond_wait (&qb_logsys_cond, &qb_logsys_cond_mutex);
+	pthread_mutex_unlock (&qb_logsys_cond_mutex);
+}
+
+static inline void wthread_wait_locked (void)
+{
+	pthread_cond_wait (&qb_logsys_cond, &qb_logsys_cond_mutex);
+	pthread_mutex_unlock (&qb_logsys_cond_mutex);
+}
+
+static void *qb_logsys_worker_thread (void *data) __attribute__((__noreturn__));
+static void *qb_logsys_worker_thread (void *data)
+{
+	int log_msg;
+	char buf[COMBINE_BUFFER_SIZE];
+
+	/*
+	 * Signal wthread_create that the initialization process may continue
+	 */
+	wthread_signal ();
+	qb_logsys_lock();
+	log_rec_idx = flt_data[FDTAIL_INDEX];
+	qb_logsys_unlock();
+
+	for (;;) {
+		wthread_wait ();
+		/*
+		 * Read and copy the logging record index position
+		 * It may have been updated by records_reclaim if
+		 * messages were lost or or log_rec on the first new
+		 * logging record available
+		 */
+		/*
+		 * Process any pending log messages here
+		 */
+		for (;;) {
+			int yield_counter = 1;
+
+			qb_logsys_lock();
+			if (log_requests_lost > 0) {
+				printf ("lost %d log requests\n", log_requests_lost);
+				log_requests_pending -= log_requests_lost;
+				log_requests_lost = 0;
+			}
+			if (log_requests_pending == 0) {
+				qb_logsys_unlock();
+				break;
+			}
+			log_rec_idx = record_read (buf, log_rec_idx, &log_msg);
+			if (log_msg) {
+				log_requests_pending -= 1;
+			}
+			qb_logsys_unlock();
+
+			/*
+			 * print the stored buffer
+			 */
+			if (log_msg) {
+				record_print (buf);
+				if (yield_counter++ > qb_logsys_after_log_ops_yield) {
+					yield_counter = 0;
+					sched_yield ();
+				}
+			}
+		}
+
+		if (wthread_should_exit) {
+			pthread_exit (NULL);
+		}
+	}
+}
+
+static void wthread_create (void)
+{
+	int res;
+
+	if (wthread_active) {
+		return;
+	}
+
+	wthread_active = 1;
+
+	pthread_mutex_init (&qb_logsys_cond_mutex, NULL);
+	pthread_cond_init (&qb_logsys_cond, NULL);
+	pthread_mutex_lock (&qb_logsys_cond_mutex);
+
+	/*
+	 * TODO: propagate pthread_create errors back to the caller
+	 */
+	res = pthread_create (&qb_logsys_thread_id, NULL,
+		qb_logsys_worker_thread, NULL);
+
+	if (res == 0) {
+		/*
+		 * Wait for thread to be started
+		 */
+		wthread_wait_locked ();
+		if (qb_logsys_sched_param_queued == 1) {
+			/*
+			 * TODO: propagate qb_logsys_thread_priority_set errors back to
+			 * the caller
+			 */
+			res = qb_logsys_thread_priority_set (qb_logsys_sched_policy,
+						    &qb_logsys_sched_param,
+						    qb_logsys_after_log_ops_yield);
+			qb_logsys_sched_param_queued = 0;
+		}
+	} else {
+		wthread_active = 0;
+	}
+}
+
+static int _logsys_config_subsys_get_unlocked (const char *subsys)
+{
+	unsigned int i;
+
+	if (!subsys) {
+		return QB_LOGSYS_MAX_SUBSYS_COUNT;
+	}
+
+ 	for (i = 0; i <= QB_LOGSYS_MAX_SUBSYS_COUNT; i++) {
+		if (strcmp (qb_logsys_loggers[i].subsys, subsys) == 0) {
+			return i;
+		}
+	}
+
+	return (-1);
+}
+
+static void syslog_facility_reconf (void)
+{
+	closelog();
+	openlog(qb_logsys_loggers[QB_LOGSYS_MAX_SUBSYS_COUNT].subsys,
+		LOG_CONS|LOG_PID,
+		qb_logsys_loggers[QB_LOGSYS_MAX_SUBSYS_COUNT].syslog_facility);
+}
+
+/*
+ * this is always invoked within the mutex, so it's safe to parse the
+ * whole thing as we need.
+ */
+static void qb_logsys_close_logfile (
+	int subsysid)
+{
+	int i;
+
+	if ((qb_logsys_loggers[subsysid].logfile_fp == NULL) &&
+	    (qb_logsys_loggers[subsysid].logfile == NULL)) {
+		return;
+	}
+
+	/*
+	 * if there is another subsystem or system using the same fp,
+	 * then we clean our own structs, but we can't close the file
+	 * as it is in use by somebody else.
+	 * Only the last users will be allowed to perform the fclose.
+	 */
+ 	for (i = 0; i <= QB_LOGSYS_MAX_SUBSYS_COUNT; i++) {
+		if ((qb_logsys_loggers[i].logfile_fp == qb_logsys_loggers[subsysid].logfile_fp) &&
+		    (i != subsysid)) {
+			qb_logsys_loggers[subsysid].logfile = NULL;
+			qb_logsys_loggers[subsysid].logfile_fp = NULL;
+			return;
+		}
+	}
+
+	/*
+	 * if we are here, we are the last users of that fp, so we can safely
+	 * close it.
+	 */
+	fclose (qb_logsys_loggers[subsysid].logfile_fp);
+	qb_logsys_loggers[subsysid].logfile_fp = NULL;
+	free (qb_logsys_loggers[subsysid].logfile);
+	qb_logsys_loggers[subsysid].logfile = NULL;
+}
+
+/*
+ * we need a version that can work when somebody else is already
+ * holding a config mutex lock or we will never get out of here
+ */
+static int qb_logsys_config_file_set_unlocked (
+		int subsysid,
+		const char **error_string,
+		const char *file)
+{
+	static char error_string_response[512];
+	int i;
+
+	qb_logsys_close_logfile(subsysid);
+
+	if ((file == NULL) ||
+	    (strcmp(qb_logsys_loggers[subsysid].subsys, "") == 0)) {
+		return (0);
+	}
+
+	if (strlen(file) >= PATH_MAX) {
+		snprintf (error_string_response,
+			sizeof(error_string_response),
+			"%s: logfile name exceed maximum system filename lenght\n",
+			qb_logsys_loggers[subsysid].subsys);
+		*error_string = error_string_response;
+		return (-1);
+	}
+
+	for (i = 0; i <= QB_LOGSYS_MAX_SUBSYS_COUNT; i++) {
+		if ((qb_logsys_loggers[i].logfile != NULL) &&
+			(strcmp (qb_logsys_loggers[i].logfile, file) == 0) &&
+			(i != subsysid)) {
+				qb_logsys_loggers[subsysid].logfile =
+					qb_logsys_loggers[i].logfile;
+				qb_logsys_loggers[subsysid].logfile_fp =
+					qb_logsys_loggers[i].logfile_fp;
+				return (0);
+		}
+	}
+
+	qb_logsys_loggers[subsysid].logfile = strdup(file);
+	if (qb_logsys_loggers[subsysid].logfile == NULL) {
+		snprintf (error_string_response,
+			sizeof(error_string_response),
+			"Unable to allocate memory for logfile '%s'\n",
+			file);
+		*error_string = error_string_response;
+		return (-1);
+	}
+
+	qb_logsys_loggers[subsysid].logfile_fp = fopen (file, "a+");
+	if (qb_logsys_loggers[subsysid].logfile_fp == NULL) {
+		char error_str[100];
+		strerror_r (errno, error_str, 100);
+		free(qb_logsys_loggers[subsysid].logfile);
+		qb_logsys_loggers[subsysid].logfile = NULL;
+		snprintf (error_string_response,
+			sizeof(error_string_response),
+			"Can't open logfile '%s' for reason (%s).\n",
+				 file, error_str);
+		*error_string = error_string_response;
+		return (-1);
+	}
+
+	return (0);
+}
+
+static void qb_logsys_subsys_init (
+		const char *subsys,
+		int subsysid)
+{
+	if (qb_logsys_system_needs_init == QB_LOGSYS_LOGGER_NEEDS_INIT) {
+		qb_logsys_loggers[subsysid].init_status =
+			QB_LOGSYS_LOGGER_NEEDS_INIT;
+	} else {
+		memcpy(&qb_logsys_loggers[subsysid],
+		       &qb_logsys_loggers[QB_LOGSYS_MAX_SUBSYS_COUNT],
+		       sizeof(qb_logsys_loggers[QB_LOGSYS_MAX_SUBSYS_COUNT]));
+		qb_logsys_loggers[subsysid].init_status =
+			QB_LOGSYS_LOGGER_INIT_DONE;
+	}
+	strncpy (qb_logsys_loggers[subsysid].subsys, subsys,
+		QB_LOGSYS_MAX_SUBSYS_NAMELEN);
+}
+
+/*
+ * Internal API - exported
+ */
+
+int _logsys_system_setup(
+	const char *mainsystem,
+	unsigned int mode,
+	unsigned int debug,
+	const char *logfile,
+	int logfile_priority,
+	int syslog_facility,
+	int syslog_priority)
+{
+	int i;
+	const char *errstr;
+	char tempsubsys[QB_LOGSYS_MAX_SUBSYS_NAMELEN];
+
+	if ((mainsystem == NULL) ||
+	    (strlen(mainsystem) >= QB_LOGSYS_MAX_SUBSYS_NAMELEN)) {
+		return -1;
+	}
+
+	i = QB_LOGSYS_MAX_SUBSYS_COUNT;
+
+	pthread_mutex_lock (&qb_logsys_config_mutex);
+
+	snprintf(qb_logsys_loggers[i].subsys,
+		 QB_LOGSYS_MAX_SUBSYS_NAMELEN,
+		"%s", mainsystem);
+
+	qb_logsys_loggers[i].mode = mode;
+
+	qb_logsys_loggers[i].debug = debug;
+
+	if (qb_logsys_config_file_set_unlocked (i, &errstr, logfile) < 0) {
+		pthread_mutex_unlock (&qb_logsys_config_mutex);
+		return (-1);
+	}
+	qb_logsys_loggers[i].logfile_priority = logfile_priority;
+
+	qb_logsys_loggers[i].syslog_facility = syslog_facility;
+	qb_logsys_loggers[i].syslog_priority = syslog_priority;
+	syslog_facility_reconf();
+
+	qb_logsys_loggers[i].init_status = QB_LOGSYS_LOGGER_INIT_DONE;
+
+	qb_logsys_system_needs_init = QB_LOGSYS_LOGGER_INIT_DONE;
+
+	for (i = 0; i < QB_LOGSYS_MAX_SUBSYS_COUNT; i++) {
+		if ((strcmp (qb_logsys_loggers[i].subsys, "") != 0) &&
+			(qb_logsys_loggers[i].init_status ==
+			 QB_LOGSYS_LOGGER_NEEDS_INIT)) {
+				strncpy (tempsubsys, qb_logsys_loggers[i].subsys,
+					QB_LOGSYS_MAX_SUBSYS_NAMELEN);
+				qb_logsys_subsys_init(tempsubsys, i);
+		}
+	}
+
+	pthread_mutex_unlock (&qb_logsys_config_mutex);
+
+	return (0);
+}
+
+unsigned int _logsys_subsys_create (const char *subsys)
+{
+	int i;
+
+	if ((subsys == NULL) ||
+	    (strlen(subsys) >= QB_LOGSYS_MAX_SUBSYS_NAMELEN)) {
+		return -1;
+	}
+
+	pthread_mutex_lock (&qb_logsys_config_mutex);
+
+	i = _logsys_config_subsys_get_unlocked (subsys);
+	if ((i > -1) && (i < QB_LOGSYS_MAX_SUBSYS_COUNT)) {
+		pthread_mutex_unlock (&qb_logsys_config_mutex);
+		return i;
+	}
+
+	for (i = 0; i < QB_LOGSYS_MAX_SUBSYS_COUNT; i++) {
+		if (strcmp (qb_logsys_loggers[i].subsys, "") == 0) {
+			qb_logsys_subsys_init(subsys, i);
+			break;
+		}
+	}
+
+	if (i >= QB_LOGSYS_MAX_SUBSYS_COUNT) {
+		i = -1;
+	}
+
+	pthread_mutex_unlock (&qb_logsys_config_mutex);
+	return i;
+}
+
+int _logsys_wthread_create (void)
+{
+	if (((qb_logsys_loggers[QB_LOGSYS_MAX_SUBSYS_COUNT].mode & QB_LOGSYS_MODE_FORK) == 0) &&
+		((qb_logsys_loggers[QB_LOGSYS_MAX_SUBSYS_COUNT].mode & QB_LOGSYS_MODE_THREADED) != 0)) {
+		wthread_create();
+		atexit (qb_logsys_atexit);
+	}
+	return (0);
+}
+
+int _logsys_rec_init (unsigned int fltsize)
+{
+	/*
+	 * we need to allocate:
+	 * - requested size +
+	 *   2 extra unsigned ints for HEAD/TAIL tracking
+	 *
+	 * then round it up to the next PAGESIZE
+	 */
+	size_t flt_real_size;
+
+	/*
+	 * XXX: kill me for 1.1 because I am a dirty hack
+	 * temporary workaround that will be replaced by supporting
+	 * 0 byte size flight recorder buffer.
+	 * 0 byte size buffer will enable direct printing to logs
+	 *   without flight recoder.
+	 */
+	if (fltsize < 64000) {
+		fltsize = 64000;
+	}
+
+	flt_real_size = ROUNDUP(
+			(fltsize + (2 * sizeof (unsigned int))),
+			sysconf(_SC_PAGESIZE));
+
+	flt_data = malloc (flt_real_size);
+	if (flt_data == NULL) {
+		return (-1);
+	}
+
+	/*
+	 * flt_data_size tracks data by ints and not bytes/chars.
+	 *
+	 * the last 2 ints are reserved to store HEAD/TAIL information.
+	 * hide them from the rotating buffer.
+	 */
+
+	flt_data_size = ((flt_real_size / sizeof (unsigned int)) - 2);
+
+	/*
+	 * First record starts at zero
+	 * Last record ends at zero
+	 */
+	flt_data[FDHEAD_INDEX] = 0;
+	flt_data[FDTAIL_INDEX] = 0;
+
+#if defined(HAVE_PTHREAD_SPIN_LOCK)
+	pthread_spin_init (&qb_logsys_idx_spinlock, 0);
+#endif
+
+	return (0);
+}
+
+
+/*
+ * u32 RECORD SIZE
+ * u32 record ident
+ * u32 arg count
+ * u32 file line
+ * u32 subsys length
+ * buffer null terminated subsys
+ * u32 filename length
+ * buffer null terminated filename
+ * u32 filename length
+ * buffer null terminated function
+ * u32 arg1 length
+ * buffer arg1
+ * ... repeats length & arg
+ */
+
+void _logsys_log_rec (
+	unsigned int rec_ident,
+	const char *function_name,
+	const char *file_name,
+	int file_line,
+	...)
+{
+	va_list ap;
+	const void *buf_args[FDMAX_ARGS];
+	unsigned int buf_len[FDMAX_ARGS];
+	unsigned int i;
+	unsigned int idx;
+	unsigned int arguments = 0;
+	unsigned int record_reclaim_size = 0;
+	unsigned int index_start;
+	int words_written;
+	int subsysid;
+
+	subsysid = QB_LOGSYS_DECODE_SUBSYSID(rec_ident);
+
+	/*
+	 * Decode VA Args
+	 */
+	va_start (ap, file_line);
+	arguments = 3;
+	for (;;) {
+		buf_args[arguments] = va_arg (ap, void *);
+		if (buf_args[arguments] == QB_LOGSYS_REC_END) {
+			break;
+		}
+		buf_len[arguments] = va_arg (ap, int);
+		record_reclaim_size += ((buf_len[arguments] + 3) >> 2) + 1;
+		arguments++;
+		if (arguments >= FDMAX_ARGS) {
+			break;
+		}
+	}
+	va_end (ap);
+
+	/*
+	 * Encode qb_logsys subsystem identity, filename, and function
+	 */
+	buf_args[0] = qb_logsys_loggers[subsysid].subsys;
+	buf_len[0] = strlen (qb_logsys_loggers[subsysid].subsys) + 1;
+	buf_args[1] = file_name;
+	buf_len[1] = strlen (file_name) + 1;
+	buf_args[2] = function_name;
+	buf_len[2] = strlen (function_name) + 1;
+	for (i = 0; i < 3; i++) {
+		record_reclaim_size += ((buf_len[i] + 3) >> 2) + 1;
+	}
+
+	idx = flt_data[FDHEAD_INDEX];
+	index_start = idx;
+
+	/*
+	 * Reclaim data needed for record including 4 words for the header
+	 */
+	records_reclaim (idx, record_reclaim_size + 4);
+
+	/*
+	 * Write record size of zero and rest of header information
+	 */
+	flt_data[idx++] = 0;
+	idx_word_step(idx);
+
+	flt_data[idx++] = rec_ident;
+	idx_word_step(idx);
+
+	flt_data[idx++] = file_line;
+	idx_word_step(idx);
+
+	flt_data[idx++] = records_written;
+	idx_word_step(idx);
+	/*
+	 * Encode all of the arguments into the log message
+	 */
+	for (i = 0; i < arguments; i++) {
+		unsigned int bytes;
+		unsigned int full_words;
+		unsigned int total_words;
+
+		bytes = buf_len[i];
+		full_words = bytes >> 2;
+		total_words = (bytes + 3) >> 2;
+
+		flt_data[idx++] = total_words;
+		idx_word_step(idx);
+
+		/*
+		 * determine if this is a wrapped write or normal write
+		 */
+		if (idx + total_words < flt_data_size) {
+			/*
+			 * dont need to wrap buffer
+			 */
+			my_memcpy_32bit (&flt_data[idx], buf_args[i], full_words);
+			if (bytes % 4) {
+				my_memcpy_8bit ((char *)&flt_data[idx + full_words],
+					((const char *)buf_args[i]) + (full_words << 2), bytes % 4);
+			}
+		} else {
+			/*
+			 * need to wrap buffer
+			 */
+			unsigned int first;
+			unsigned int second;
+
+			first = flt_data_size - idx;
+			if (first > full_words) {
+				first = full_words;
+			}
+			second = full_words - first;
+			my_memcpy_32bit (&flt_data[idx],
+					 (const int *)buf_args[i], first);
+			my_memcpy_32bit (&flt_data[0],
+				(const int *)(((const unsigned char *)buf_args[i]) + (first << 2)),
+				second);
+			if (bytes % 4) {
+				my_memcpy_8bit ((char *)&flt_data[0 + second],
+					((const char *)buf_args[i]) + (full_words << 2), bytes % 4);
+			}
+		}
+		idx += total_words;
+		idx_buffer_step (idx);
+	}
+	words_written = idx - index_start;
+	if (words_written < 0) {
+		words_written += flt_data_size;
+	}
+
+	/*
+	 * Commit the write of the record size now that the full record
+	 * is in the memory buffer
+	 */
+	flt_data[index_start] = words_written;
+
+	/*
+	 * If the index of the current head equals the current log_rec_idx,
+	 * and this is not a log_printf operation, set the log_rec_idx to
+	 * the new head position and commit the new head.
+	 */
+	qb_logsys_lock();
+	if (QB_LOGSYS_DECODE_RECID(rec_ident) == QB_LOGSYS_RECID_LOG) {
+		log_requests_pending += 1;
+	}
+	if (log_requests_pending == 0) {
+		log_rec_idx = idx;
+	}
+	flt_data[FDHEAD_INDEX] = idx;
+	qb_logsys_unlock();
+	records_written++;
+}
+
+void _logsys_log_vprintf (
+	unsigned int rec_ident,
+	const char *function_name,
+	const char *file_name,
+	int file_line,
+	const char *format,
+	va_list ap)
+{
+	char qb_logsys_print_buffer[COMBINE_BUFFER_SIZE];
+	unsigned int len;
+	unsigned int level;
+	int subsysid;
+	const char *short_file_name;
+
+	subsysid = QB_LOGSYS_DECODE_SUBSYSID(rec_ident);
+	level = QB_LOGSYS_DECODE_LEVEL(rec_ident);
+
+	if ((level > qb_logsys_loggers[subsysid].syslog_priority) &&
+	    (level > qb_logsys_loggers[subsysid].logfile_priority) &&
+	    (qb_logsys_loggers[subsysid].debug == 0)) {
+		return;
+	}
+
+	len = vsprintf (qb_logsys_print_buffer, format, ap);
+	if (qb_logsys_print_buffer[len - 1] == '\n') {
+		qb_logsys_print_buffer[len - 1] = '\0';
+		len -= 1;
+	}
+#ifdef BUILDING_IN_PLACE
+	short_file_name = file_name;
+#else
+	short_file_name = strrchr (file_name, '/');
+	if (short_file_name == NULL)
+		short_file_name = file_name;
+	else
+		short_file_name++; /* move past the "/" */
+#endif /* BUILDING_IN_PLACE */
+
+	/*
+	 * Create a log record
+	 */
+	_logsys_log_rec (
+		rec_ident,
+		function_name,
+		short_file_name,
+		file_line,
+		qb_logsys_print_buffer, len + 1,
+		QB_LOGSYS_REC_END);
+
+	if ((qb_logsys_loggers[QB_LOGSYS_MAX_SUBSYS_COUNT].mode & QB_LOGSYS_MODE_THREADED) == 0) {
+		/*
+		 * Output (and block) if the log mode is not threaded otherwise
+		 * expect the worker thread to output the log data once signaled
+		 */
+		log_printf_to_logs (rec_ident,
+				    short_file_name, function_name, file_line,
+				    qb_logsys_print_buffer);
+	} else {
+		/*
+		 * Signal worker thread to display logging output
+		 */
+		wthread_signal ();
+	}
+}
+
+void _logsys_log_printf (
+	unsigned int rec_ident,
+	const char *function_name,
+	const char *file_name,
+	int file_line,
+	const char *format,
+	...)
+{
+	va_list ap;
+
+	va_start (ap, format);
+	_logsys_log_vprintf (rec_ident, function_name, file_name, file_line,
+		format, ap);
+	va_end (ap);
+}
+
+int _logsys_config_subsys_get (const char *subsys)
+{
+	unsigned int i;
+
+	pthread_mutex_lock (&qb_logsys_config_mutex);
+
+	i = _logsys_config_subsys_get_unlocked (subsys);
+
+	pthread_mutex_unlock (&qb_logsys_config_mutex);
+
+	return i;
+}
+
+/*
+ * External Configuration and Initialization API
+ */
+void qb_logsys_fork_completed (void)
+{
+	qb_logsys_loggers[QB_LOGSYS_MAX_SUBSYS_COUNT].mode &= ~QB_LOGSYS_MODE_FORK;
+	_logsys_wthread_create ();
+}
+
+unsigned int qb_logsys_config_mode_set (const char *subsys, unsigned int mode)
+{
+	int i;
+
+	pthread_mutex_lock (&qb_logsys_config_mutex);
+	if (subsys != NULL) {
+		i = _logsys_config_subsys_get_unlocked (subsys);
+		if (i >= 0) {
+			qb_logsys_loggers[i].mode = mode;
+			i = 0;
+		}
+	} else {
+		for (i = 0; i <= QB_LOGSYS_MAX_SUBSYS_COUNT; i++) {
+			qb_logsys_loggers[i].mode = mode;
+		}
+		i = 0;
+	}
+	pthread_mutex_unlock (&qb_logsys_config_mutex);
+
+	return i;
+}
+
+unsigned int qb_logsys_config_mode_get (const char *subsys)
+{
+	int i;
+
+	i = _logsys_config_subsys_get (subsys);
+	if (i < 0) {
+		return i;
+	}
+
+	return qb_logsys_loggers[i].mode;
+}
+
+int qb_logsys_config_file_set (
+		const char *subsys,
+		const char **error_string,
+		const char *file)
+{
+	int i;
+	int res;
+
+	pthread_mutex_lock (&qb_logsys_config_mutex);
+
+	if (subsys != NULL) {
+		i = _logsys_config_subsys_get_unlocked (subsys);
+		if (i < 0) {
+			res = i;
+		} else {
+			res = qb_logsys_config_file_set_unlocked(i, error_string, file);
+		}
+	} else {
+		for (i = 0; i <= QB_LOGSYS_MAX_SUBSYS_COUNT; i++) {
+			res = qb_logsys_config_file_set_unlocked(i, error_string, file);
+			if (res < 0) {
+				break;
+			}
+		}
+	}
+
+	pthread_mutex_unlock (&qb_logsys_config_mutex);
+	return res;
+}
+
+int qb_logsys_format_set (const char *format)
+{
+	int ret = 0;
+
+	pthread_mutex_lock (&qb_logsys_config_mutex);
+
+	if (format_buffer) {
+		free(format_buffer);
+		format_buffer = NULL;
+	}
+
+	format_buffer = strdup(format ? format : "%p [%6s] %b");
+	if (format_buffer == NULL) {
+		ret = -1;
+	}
+
+	pthread_mutex_unlock (&qb_logsys_config_mutex);
+	return ret;
+}
+
+char *qb_logsys_format_get (void)
+{
+	return format_buffer;
+}
+
+unsigned int qb_logsys_config_syslog_facility_set (
+	const char *subsys,
+	unsigned int facility)
+{
+	int i;
+
+	pthread_mutex_lock (&qb_logsys_config_mutex);
+	if (subsys != NULL) {
+		i = _logsys_config_subsys_get_unlocked (subsys);
+		if (i >= 0) {
+			qb_logsys_loggers[i].syslog_facility = facility;
+			if (i == QB_LOGSYS_MAX_SUBSYS_COUNT) {
+				syslog_facility_reconf();
+			}
+			i = 0;
+		}
+	} else {
+		for (i = 0; i <= QB_LOGSYS_MAX_SUBSYS_COUNT; i++) {
+			qb_logsys_loggers[i].syslog_facility = facility;
+		}
+		syslog_facility_reconf();
+		i = 0;
+	}
+	pthread_mutex_unlock (&qb_logsys_config_mutex);
+
+	return i;
+}
+
+unsigned int qb_logsys_config_syslog_priority_set (
+	const char *subsys,
+	unsigned int priority)
+{
+	int i;
+
+	pthread_mutex_lock (&qb_logsys_config_mutex);
+	if (subsys != NULL) {
+		i = _logsys_config_subsys_get_unlocked (subsys);
+		if (i >= 0) {
+			qb_logsys_loggers[i].syslog_priority = priority;
+			i = 0;
+		}
+	} else {
+		for (i = 0; i <= QB_LOGSYS_MAX_SUBSYS_COUNT; i++) {
+			qb_logsys_loggers[i].syslog_priority = priority;
+		}
+		i = 0;
+	}
+	pthread_mutex_unlock (&qb_logsys_config_mutex);
+
+	return i;
+}
+
+unsigned int qb_logsys_config_logfile_priority_set (
+	const char *subsys,
+	unsigned int priority)
+{
+	int i;
+
+	pthread_mutex_lock (&qb_logsys_config_mutex);
+	if (subsys != NULL) {
+		i = _logsys_config_subsys_get_unlocked (subsys);
+		if (i >= 0) {
+			qb_logsys_loggers[i].logfile_priority = priority;
+			i = 0;
+		}
+	} else {
+		for (i = 0; i <= QB_LOGSYS_MAX_SUBSYS_COUNT; i++) {
+			qb_logsys_loggers[i].logfile_priority = priority;
+		}
+		i = 0;
+	}
+	pthread_mutex_unlock (&qb_logsys_config_mutex);
+
+	return i;
+}
+
+unsigned int qb_logsys_config_debug_set (
+	const char *subsys,
+	unsigned int debug)
+{
+	int i;
+
+	pthread_mutex_lock (&qb_logsys_config_mutex);
+	if (subsys != NULL) {
+		i = _logsys_config_subsys_get_unlocked (subsys);
+		if (i >= 0) {
+			qb_logsys_loggers[i].debug = debug;
+			i = 0;
+		}
+	} else {
+		for (i = 0; i <= QB_LOGSYS_MAX_SUBSYS_COUNT; i++) {
+			qb_logsys_loggers[i].debug = debug;
+		}
+		i = 0;
+	}
+	pthread_mutex_unlock (&qb_logsys_config_mutex);
+
+	return i;
+}
+
+int qb_logsys_facility_id_get (const char *name)
+{
+	unsigned int i;
+
+	for (i = 0; facilitynames[i].c_name != NULL; i++) {
+		if (strcasecmp(name, facilitynames[i].c_name) == 0) {
+			return (facilitynames[i].c_val);
+		}
+	}
+	return (-1);
+}
+
+const char *qb_logsys_facility_name_get (unsigned int facility)
+{
+	unsigned int i;
+
+	for (i = 0; facilitynames[i].c_name != NULL; i++) {
+		if (facility == facilitynames[i].c_val) {
+			return (facilitynames[i].c_name);
+		}
+	}
+	return (NULL);
+}
+
+int qb_logsys_priority_id_get (const char *name)
+{
+	unsigned int i;
+
+	for (i = 0; prioritynames[i].c_name != NULL; i++) {
+		if (strcasecmp(name, prioritynames[i].c_name) == 0) {
+			return (prioritynames[i].c_val);
+		}
+	}
+	return (-1);
+}
+
+const char *qb_logsys_priority_name_get (unsigned int priority)
+{
+	unsigned int i;
+
+	for (i = 0; prioritynames[i].c_name != NULL; i++) {
+		if (priority == prioritynames[i].c_val) {
+			return (prioritynames[i].c_name);
+		}
+	}
+	return (NULL);
+}
+
+int qb_logsys_thread_priority_set (
+	int policy,
+	const struct sched_param *param,
+        unsigned int after_log_ops_yield)
+
+{
+	int res = 0;
+
+#if defined(HAVE_PTHREAD_SETSCHEDPARAM) && defined(HAVE_SCHED_GET_PRIORITY_MAX)
+	if (wthread_active == 0) {
+		qb_logsys_sched_policy = policy;
+		memcpy(&qb_logsys_sched_param, &param, sizeof(struct sched_param));
+		qb_logsys_sched_param_queued = 1;
+	} else {
+		res = pthread_setschedparam (qb_logsys_thread_id, policy, param);
+	}
+#endif
+
+	if (after_log_ops_yield > 0) {
+		qb_logsys_after_log_ops_yield = after_log_ops_yield;
+	}
+
+	return (res);
+}
+
+int qb_logsys_log_rec_store (const char *filename)
+{
+	int fd;
+	ssize_t written_size;
+	size_t size_to_write = (flt_data_size + 2) * sizeof (unsigned int);
+
+	fd = open (filename, O_CREAT|O_RDWR, 0700);
+	if (fd < 0) {
+		return (-1);
+	}
+
+	written_size = write (fd, &flt_data_size, sizeof(unsigned int));
+	if ((written_size < 0) || (written_size != sizeof(unsigned int))) {
+		close (fd);
+		return (-1);
+	}
+
+	written_size = write (fd, flt_data, size_to_write);
+	if (close (fd) != 0)
+		return (-1);
+	if (written_size < 0) {
+		return (-1);
+	} else if ((size_t)written_size != size_to_write) {
+		return (-1);
+	}
+
+	return (0);
+}
+
+void qb_logsys_atexit (void)
+{
+	if (wthread_active) {
+		wthread_should_exit = 1;
+		wthread_signal ();
+		pthread_join (qb_logsys_thread_id, NULL);
+	}
+}
+
+void qb_logsys_flush (void)
+{
+	wthread_signal ();
+}
diff --git a/lib/logsys/Makefile.am b/lib/logsys/Makefile.am
deleted file mode 100644
index f8c3135..0000000
--- a/lib/logsys/Makefile.am
+++ /dev/null
@@ -1,95 +0,0 @@
-#
-# Copyright (c) 2010 Red Hat, Inc.
-#
-# Authors: Andrew Beekhof
-#	   Steven Dake (sdake@redhat.com)
-#	   Angus Salkeld <asaslkeld@redhat.com>
-#
-# This software licensed under BSD license, the text of which follows:
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are met:
-#
-# - Redistributions of source code must retain the above copyright notice,
-#   this list of conditions and the following disclaimer.
-# - 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.
-# - Neither the name of the MontaVista Software, Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
-
-MAINTAINERCLEANFILES    = Makefile.in
-
-AM_CFLAGS		= -fPIC
-
-AM_LDFLAGS		= -lpthread
-
-INCLUDES		= -I$(top_builddir)/include -I$(top_srcdir)/include
-
-lib_LIBRARIES		= libqblogsys.a
-SHARED_LIBS		= $(lib_LIBRARIES:%.a=%.so.$(SONAME))
-SHARED_LIBS_SO		= $(lib_LIBRARIES:%.a=%.so)
-SHARED_LIBS_SO_TWO	= $(lib_LIBRARIES:%.a=%.so.$(SOMAJOR))
-
-libqblogsys_a_SOURCES	= logsys.c
-
-noinst_HEADERS		= libqblogsys.versions 
-
-if BUILD_DARWIN
-
-lib%.so.$(SONAME): %.o
-	$(CC) $(DARWIN_OPTS) $^ -o $@
-	ln -sf lib$*.so.$(SONAME) lib$*.so
-	ln -sf lib$*.so.$(SONAME) lib$*.so.$(SOMAJOR)
-
-else
-
-if BUILD_SOLARIS
-
-lib%.so.$(SONAME): %.o
-	$(LD) $(SOLARIS_OPTS) -G $^ -o $@
-	ln -sf lib$*.so.$(SONAME) lib$*.so
-	ln -sf lib$*.so.$(SONAME) lib$*.so.$(SOMAJOR)
-
-else
-
-libqb%.so.$(SONAME): %.o
-	$(CC) -shared -o $@ \
-		-Wl,-soname=libqb$*.so.$(SOMAJOR) \
-		-Wl,-version-script=$(srcdir)/libqb$*.versions \
-		$^ $(LDFLAGS) $(AM_LDFLAGS)
-	ln -sf libqb$*.so.$(SONAME) libqb$*.so
-	ln -sf libqb$*.so.$(SONAME) libqb$*.so.$(SOMAJOR)
-
-endif
-
-endif
-
-all-local: $(SHARED_LIBS)
-	@echo Built shared libs
-
-install-exec-local:
-	$(INSTALL) -d $(DESTDIR)/$(libdir)
-	$(INSTALL) -m 755 $(SHARED_LIBS) $(DESTDIR)/$(libdir)
-	$(CP) -a $(SHARED_LIBS_SO) $(SHARED_LIBS_SO_TWO) $(DESTDIR)/$(libdir)
-
-uninstall-local:
-	cd $(DESTDIR)/$(libdir)/ && \
-		rm -f $(SHARED_LIBS) $(SHARED_LIBS_SO) $(SHARED_LIBS_SO_TWO)
-
-clean-local:
-	rm -f *.o *.a *.so* *.da *.bb *.bbg
-
diff --git a/lib/logsys/libqblogsys.versions b/lib/logsys/libqblogsys.versions
deleted file mode 100644
index 60b6e41..0000000
--- a/lib/logsys/libqblogsys.versions
+++ /dev/null
@@ -1,25 +0,0 @@
-QB_LOGSYS_0.1 {
-	global:
-		qb_logsys_fork_completed;
-		qb_logsys_atexit;
-		qb_logsys_flush;
-		qb_logsys_log_rec_store;
-		qb_logsys_format_set;
-		qb_logsys_format_get;
-		qb_logsys_config_syslog_facility_set;
-		qb_logsys_config_syslog_priority_set;
-		qb_logsys_config_mode_set;
-		qb_logsys_config_mode_get;
-		qb_logsys_config_file_set;
-		qb_logsys_config_logfile_priority_set;
-		qb_logsys_config_debug_set;
-		qb_logsys_facility_id_get;
-		qb_logsys_facility_name_get;
-		qb_logsys_priority_id_get;
-		qb_logsys_priority_name_get;
-		qb_logsys_thread_priority_set;
-		qb_logsys_rec_end;
-		qb_logsys_system_init;
-		qb_logsys_subsys_init;
-	local: *;
-};
diff --git a/lib/logsys/logsys.c b/lib/logsys/logsys.c
deleted file mode 100644
index bb77e56..0000000
--- a/lib/logsys/logsys.c
+++ /dev/null
@@ -1,1698 +0,0 @@
-/*
- * Copyright (c) 2002-2004 MontaVista Software, Inc.
- * Copyright (c) 2006-2010 Red Hat, Inc.
- *
- * Author: Steven Dake (sdake@redhat.com)
- * Author: Lon Hohberger (lhh@redhat.com)
- * Author: Fabio M. Di Nitto (fdinitto@redhat.com)
- *
- * All rights reserved.
- *
- * This software licensed under BSD license, the text of which follows:
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * - Redistributions of source code must retain the above copyright notice,
- *   this list of conditions and the following disclaimer.
- * - 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.
- * - Neither the name of the MontaVista Software, Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
- */
-
-#include <config.h>
-
-#include "os_base.h"
-#include <ctype.h>
-#include <sys/time.h>
-#include <syslog.h>
-#include <pthread.h>
-
-#include <qb/qblogsys.h>
-
-#define YIELD_AFTER_LOG_OPS 10
-
-#define MIN(x,y) ((x) < (y) ? (x) : (y))
-
-#define ROUNDUP(x, y) ((((x) + ((y) - 1)) / (y)) * (y))
-
-/*
- * syslog prioritynames, facility names to value mapping
- * Some C libraries build this in to their headers, but it is non-portable
- * so qb_logsys supplies its own version.
- */
-struct syslog_names {
-	const char *c_name;
-	int c_val;
-};
-
-struct syslog_names prioritynames[] =
-{
-	{ "alert", LOG_ALERT },
-	{ "crit", LOG_CRIT },
-	{ "debug", LOG_DEBUG },
-	{ "emerg", LOG_EMERG },
-	{ "err", LOG_ERR },
-	{ "error", LOG_ERR },
-	{ "info", LOG_INFO },
-	{ "notice", LOG_NOTICE },
-	{ "warning", LOG_WARNING },
-	{ NULL, -1 }
-};
-
-struct syslog_names facilitynames[] =
-{
-	{ "auth", LOG_AUTH },
-	{ "cron", LOG_CRON },
-	{ "daemon", LOG_DAEMON },
-	{ "kern", LOG_KERN },
-	{ "lpr", LOG_LPR },
-	{ "mail", LOG_MAIL },
-	{ "news", LOG_NEWS },
-	{ "syslog", LOG_SYSLOG },
-	{ "user", LOG_USER },
-	{ "uucp", LOG_UUCP },
-	{ "local0", LOG_LOCAL0 },
-	{ "local1", LOG_LOCAL1 },
-	{ "local2", LOG_LOCAL2 },
-	{ "local3", LOG_LOCAL3 },
-	{ "local4", LOG_LOCAL4 },
-	{ "local5", LOG_LOCAL5 },
-	{ "local6", LOG_LOCAL6 },
-	{ "local7", LOG_LOCAL7 },
-	{ NULL, -1 }
-};
-
-
-/*
- * These are not static so they can be read from the core file
- */
-int *flt_data;
-
-unsigned int flt_data_size;
-
-#define COMBINE_BUFFER_SIZE 2048
-
-/* values for qb_logsys_logger init_status */
-#define QB_LOGSYS_LOGGER_INIT_DONE		0
-#define QB_LOGSYS_LOGGER_NEEDS_INIT	1
-
-static int qb_logsys_system_needs_init = QB_LOGSYS_LOGGER_NEEDS_INIT;
-
-static int qb_logsys_sched_param_queued = 0;
-static int qb_logsys_sched_policy;
-static struct sched_param qb_logsys_sched_param;
-
-static int qb_logsys_after_log_ops_yield = 10;
-
-/*
- * need unlogical order to preserve 64bit alignment
- */
-struct qb_logsys_logger {
-	char subsys[QB_LOGSYS_MAX_SUBSYS_NAMELEN];	/* subsystem name */
-	char *logfile;				/* log to file */
-	FILE *logfile_fp;			/* track file descriptor */
-	unsigned int mode;			/* subsystem mode */
-	unsigned int debug;			/* debug on|off */
-	int syslog_facility;			/* facility */
-	int syslog_priority;			/* priority */
-	int logfile_priority;			/* priority to file */
-	int init_status;			/* internal field to handle init queues
-						   for subsystems */
-};
-
-/*
- * operating global variables
- */
-
-static struct qb_logsys_logger qb_logsys_loggers[QB_LOGSYS_MAX_SUBSYS_COUNT + 1];
-
-static int wthread_active = 0;
-
-static int wthread_should_exit = 0;
-
-static pthread_mutex_t qb_logsys_config_mutex = PTHREAD_MUTEX_INITIALIZER;
-
-static unsigned int records_written = 1;
-
-static pthread_t qb_logsys_thread_id;
-
-static pthread_cond_t qb_logsys_cond;
-
-static pthread_mutex_t qb_logsys_cond_mutex;
-
-#if defined(HAVE_PTHREAD_SPIN_LOCK)
-static pthread_spinlock_t qb_logsys_idx_spinlock;
-#else
-static pthread_mutex_t qb_logsys_idx_mutex = PTHREAD_MUTEX_INITIALIZER;
-#endif
-
-static unsigned int log_rec_idx;
-
-static int qb_logsys_buffer_full = 0;
-
-static char *format_buffer=NULL;
-
-static int log_requests_pending = 0;
-
-static int log_requests_lost = 0;
-
-void *qb_logsys_rec_end;
-
-#define FDHEAD_INDEX	(flt_data_size)
-
-#define FDTAIL_INDEX 	(flt_data_size + 1)
-
-#define FDMAX_ARGS	64
-
-/* forward declarations */
-static void qb_logsys_close_logfile(int subsysid);
-
-#ifdef QB_LOGSYS_DEBUG
-static char *decode_mode(int subsysid, char *buf, size_t buflen)
-{
-	memset(buf, 0, buflen);
-
-	if (qb_logsys_loggers[subsysid].mode & QB_LOGSYS_MODE_OUTPUT_FILE)
-		snprintf(buf+strlen(buf), buflen, "FILE,");
-
-	if (qb_logsys_loggers[subsysid].mode & QB_LOGSYS_MODE_OUTPUT_STDERR)
-		snprintf(buf+strlen(buf), buflen, "STDERR,");
-
-	if (qb_logsys_loggers[subsysid].mode & QB_LOGSYS_MODE_OUTPUT_SYSLOG)
-		snprintf(buf+strlen(buf), buflen, "SYSLOG,");
-
-	if (subsysid == QB_LOGSYS_MAX_SUBSYS_COUNT) {
-		if (qb_logsys_loggers[subsysid].mode & QB_LOGSYS_MODE_FORK)
-			snprintf(buf+strlen(buf), buflen, "FORK,");
-
-		if (qb_logsys_loggers[subsysid].mode & QB_LOGSYS_MODE_THREADED)
-			snprintf(buf+strlen(buf), buflen, "THREADED,");
-	}
-
-	memset(buf+strlen(buf)-1,0,1);
-
-	return buf;
-}
-
-static const char *decode_debug(int subsysid)
-{
-	if (qb_logsys_loggers[subsysid].debug)
-		return "on";
-
-	return "off";
-}
-
-static const char *decode_status(int subsysid)
-{
-	if (!qb_logsys_loggers[subsysid].init_status)
-		return "INIT_DONE";
-
-	return "NEEDS_INIT";
-}
-
-static void dump_subsys_config(int subsysid)
-{
-	char modebuf[1024];
-
-	fprintf(stderr,
-		"ID: %d\n"
-		"subsys: %s\n"
-		"logfile: %s\n"
-		"logfile_fp: %p\n"
-		"mode: %s\n"
-		"debug: %s\n"
-		"syslog_fac: %s\n"
-		"syslog_pri: %s\n"
-		"logfile_pri: %s\n"
-		"init_status: %s\n",
-		subsysid,
-		qb_logsys_loggers[subsysid].subsys,
-		qb_logsys_loggers[subsysid].logfile,
-		qb_logsys_loggers[subsysid].logfile_fp,
-		decode_mode(subsysid, modebuf, sizeof(modebuf)),
-		decode_debug(subsysid),
-		qb_logsys_facility_name_get(qb_logsys_loggers[subsysid].syslog_facility),
-		qb_logsys_priority_name_get(qb_logsys_loggers[subsysid].syslog_priority),
-		qb_logsys_priority_name_get(qb_logsys_loggers[subsysid].logfile_priority),
-		decode_status(subsysid));
-}
-
-static void dump_full_config(void)
-{
-	int i;
-
-	for (i = 0; i <= QB_LOGSYS_MAX_SUBSYS_COUNT; i++) {
-		if (strlen(qb_logsys_loggers[i].subsys) > 0)
-			dump_subsys_config(i);
-	}
-}
-#endif
-
-/*
- * Helpers for _logsys_log_rec functionality
- */
-static inline void my_memcpy_32bit (int *dest, const int *src, unsigned int words)
-{
-	unsigned int word_idx;
-	for (word_idx = 0; word_idx < words; word_idx++) {
-		dest[word_idx] = src[word_idx];
-	}
-}
-
-static inline void my_memcpy_8bit (char *dest, const char *src,
-				   unsigned int bytes)
-{
-	unsigned int byte_idx;
-
-	for (byte_idx = 0; byte_idx < bytes; byte_idx++) {
-		dest[byte_idx] = src[byte_idx];
-	}
-}
-
-#if defined(HAVE_PTHREAD_SPIN_LOCK)
-static void qb_logsys_lock (void)
-{
-	pthread_spin_lock (&qb_logsys_idx_spinlock);
-}
-static void qb_logsys_unlock (void)
-{
-	pthread_spin_unlock (&qb_logsys_idx_spinlock);
-}
-#else
-static void qb_logsys_lock (void)
-{
-	pthread_mutex_lock (&qb_logsys_idx_mutex);
-}
-static void qb_logsys_unlock (void)
-{
-	pthread_mutex_unlock (&qb_logsys_idx_mutex);
-}
-#endif
-
-/*
- * Before any write operation, a reclaim on the buffer area must be executed
- */
-static inline void records_reclaim (unsigned int idx, unsigned int words)
-{
-	unsigned int should_reclaim;
-
-	should_reclaim = 0;
-
-	if ((idx + words) >= flt_data_size) {
-		qb_logsys_buffer_full = 1;
-	}
-	if (qb_logsys_buffer_full == 0) {
-		return;
-	}
-
-	qb_logsys_lock();
-	if (flt_data[FDTAIL_INDEX] > flt_data[FDHEAD_INDEX]) {
-		if (idx + words >= flt_data[FDTAIL_INDEX]) {
-			should_reclaim = 1;
-		}
-	} else {
-		if ((idx + words) >= (flt_data[FDTAIL_INDEX] + flt_data_size)) {
-			should_reclaim = 1;
-		}
-	}
-
-	if (should_reclaim) {
-		int words_needed = 0;
-
-		words_needed = words + 1;
-		do {
-			unsigned int old_tail;
-
-			words_needed -= flt_data[flt_data[FDTAIL_INDEX]];
-			old_tail = flt_data[FDTAIL_INDEX];
-			flt_data[FDTAIL_INDEX] =
-				(flt_data[FDTAIL_INDEX] +
-				flt_data[flt_data[FDTAIL_INDEX]]) % (flt_data_size);
-			if (log_rec_idx == old_tail) {
-				log_requests_lost += 1;
-				log_rec_idx = flt_data[FDTAIL_INDEX];
-			}
-		} while (words_needed > 0);
-	}
-	qb_logsys_unlock();
-}
-
-#define idx_word_step(idx)						\
-do {									\
-	if (idx > (flt_data_size - 1)) {				\
-		idx = 0;						\
-	}								\
-} while (0);
-
-#define idx_buffer_step(idx)						\
-do {									\
-	if (idx > (flt_data_size - 1)) {				\
-		idx = ((idx) % (flt_data_size));			\
-	}								\
-} while (0);
-
-/*
- * Internal threaded logging implementation
- */
-static inline int strcpy_cutoff (char *dest, const char *src, size_t cutoff,
-				 size_t buf_len)
-{
-	size_t len = strlen (src);
-	if (buf_len <= 1) {
-		if (buf_len == 0)
-			dest[0] = 0;
-		return 0;
-	}
-
-	if (cutoff == 0) {
-		cutoff = len;
-	}
-
-	cutoff = MIN (cutoff, buf_len - 1);
-	len = MIN (len, cutoff);
-	memcpy (dest, src, len);
-	memset (dest + len, ' ', cutoff - len);
-	dest[cutoff] = '\0';
-
-	return (cutoff);
-}
-
-static const char log_month_name[][4] = {
-	"Jan", "Feb", "Mar", "Apr", "May", "Jun",
-	"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
-};
-
-/*
- * %s SUBSYSTEM
- * %n FUNCTION NAME
- * %f FILENAME
- * %l FILELINE
- * %p PRIORITY
- * %t TIMESTAMP
- * %b BUFFER
- *
- * any number between % and character specify field length to pad or chop
-*/
-static void log_printf_to_logs (
-	unsigned int rec_ident,
-	const char *file_name,
-	const char *function_name,
-	int file_line,
-	const char *buffer)
-{
-	char normal_output_buffer[COMBINE_BUFFER_SIZE];
-	char syslog_output_buffer[COMBINE_BUFFER_SIZE];
-	char char_time[128];
-	char line_no[30];
-	unsigned int format_buffer_idx = 0;
-	unsigned int normal_output_buffer_idx = 0;
-	unsigned int syslog_output_buffer_idx = 0;
-	struct timeval tv;
-	size_t cutoff;
-	unsigned int normal_len, syslog_len;
-	int subsysid;
-	unsigned int level;
-	int c;
-	struct tm tm_res;
-
-	if (QB_LOGSYS_DECODE_RECID(rec_ident) != QB_LOGSYS_RECID_LOG) {
-		return;
-	}
-
-	subsysid = QB_LOGSYS_DECODE_SUBSYSID(rec_ident);
-	level = QB_LOGSYS_DECODE_LEVEL(rec_ident);
-
-	while ((c = format_buffer[format_buffer_idx])) {
-		cutoff = 0;
-		if (c != '%') {
-			normal_output_buffer[normal_output_buffer_idx++] = c;
-			syslog_output_buffer[syslog_output_buffer_idx++] = c;
-			format_buffer_idx++;
-		} else {
-			const char *normal_p, *syslog_p;
-
-			format_buffer_idx += 1;
-			if (isdigit (format_buffer[format_buffer_idx])) {
-				cutoff = atoi (&format_buffer[format_buffer_idx]);
-			}
-			while (isdigit (format_buffer[format_buffer_idx])) {
-				format_buffer_idx += 1;
-			}
-
-			switch (format_buffer[format_buffer_idx]) {
-				case 's':
-					normal_p = qb_logsys_loggers[subsysid].subsys;
-					syslog_p = qb_logsys_loggers[subsysid].subsys;
-					break;
-
-				case 'n':
-					normal_p = function_name;
-					syslog_p = function_name;
-					break;
-
-				case 'f':
-					normal_p = file_name;
-					syslog_p = file_name;
-					break;
-
-				case 'l':
-					sprintf (line_no, "%d", file_line);
-					normal_p = line_no;
-					syslog_p = line_no;
-					break;
-
-				case 't':
-					gettimeofday (&tv, NULL);
-					(void)localtime_r ((time_t *)&tv.tv_sec, &tm_res);
-					snprintf (char_time, sizeof (char_time), "%s %02d %02d:%02d:%02d",
-					    log_month_name[tm_res.tm_mon], tm_res.tm_mday, tm_res.tm_hour,
-					    tm_res.tm_min, tm_res.tm_sec);
-					normal_p = char_time;
-
-					/*
-					 * syslog does timestamping on its own.
-					 * also strip extra space in case.
-					 */
-					syslog_p = "";
-					break;
-
-				case 'b':
-					normal_p = buffer;
-					syslog_p = buffer;
-					break;
-
-				case 'p':
-					normal_p = qb_logsys_loggers[QB_LOGSYS_MAX_SUBSYS_COUNT].subsys;
-					syslog_p = "";
-					break;
-
-				default:
-					normal_p = "";
-					syslog_p = "";
-					break;
-			}
-			normal_len = strcpy_cutoff (normal_output_buffer + normal_output_buffer_idx,
-					     normal_p, cutoff,
-					     (sizeof (normal_output_buffer)
-					      - normal_output_buffer_idx));
-			normal_output_buffer_idx += normal_len;
-			syslog_len = strcpy_cutoff (syslog_output_buffer + syslog_output_buffer_idx,
-					     syslog_p, cutoff,
-					     (sizeof (syslog_output_buffer)
-					      - syslog_output_buffer_idx));
-			syslog_output_buffer_idx += syslog_len;
-			format_buffer_idx += 1;
-		}
-		if ((normal_output_buffer_idx >= sizeof (normal_output_buffer) - 2) ||
-		    (syslog_output_buffer_idx >= sizeof (syslog_output_buffer) - 1)) {
-			/* Note: we make allowance for '\0' at the end of
-			 * both of these arrays and normal_output_buffer also
-			 * needs a '\n'.
-			 */
-			break;
-		}
-	}
-
-	normal_output_buffer[normal_output_buffer_idx] = '\0';
-	syslog_output_buffer[syslog_output_buffer_idx] = '\0';
-
-	/*
-	 * Output to syslog
-	 */
-	if ((qb_logsys_loggers[subsysid].mode & QB_LOGSYS_MODE_OUTPUT_SYSLOG) &&
-	     ((level <= qb_logsys_loggers[subsysid].syslog_priority) ||
-	     (qb_logsys_loggers[subsysid].debug != 0))) {
-		syslog (level | qb_logsys_loggers[subsysid].syslog_facility, "%s", syslog_output_buffer);
-	}
-
-	/*
-	 * Terminate string with \n \0
-	 */
-	normal_output_buffer[normal_output_buffer_idx++] = '\n';
-	normal_output_buffer[normal_output_buffer_idx] = '\0';
-
-	/*
-	 * Output to configured file
-	 */
-	if (((qb_logsys_loggers[subsysid].mode & QB_LOGSYS_MODE_OUTPUT_FILE) &&
-	     (qb_logsys_loggers[subsysid].logfile_fp != NULL)) &&
-	    ((level <= qb_logsys_loggers[subsysid].logfile_priority) ||
-	     (qb_logsys_loggers[subsysid].debug != 0))) {
-		/*
-		 * Output to a file
-		 */
-		if ((fwrite (normal_output_buffer, strlen (normal_output_buffer), 1,
-			    qb_logsys_loggers[subsysid].logfile_fp) < 1) ||
-		    (fflush (qb_logsys_loggers[subsysid].logfile_fp) == EOF)) {
-			char tmpbuffer[1024];
-			/*
-			 * if we are here, it's bad.. it's really really bad.
-			 * Best thing would be to light a candle in a church
-			 * and pray.
-			 */
-			snprintf(tmpbuffer, sizeof(tmpbuffer),
-				"QB_LOGSYS EMERGENCY: %s Unable to write to %s.",
-				qb_logsys_loggers[subsysid].subsys,
-				qb_logsys_loggers[subsysid].logfile);
-			pthread_mutex_lock (&qb_logsys_config_mutex);
-			qb_logsys_close_logfile(subsysid);
-			qb_logsys_loggers[subsysid].mode &= ~QB_LOGSYS_MODE_OUTPUT_FILE;
-			pthread_mutex_unlock (&qb_logsys_config_mutex);
-			log_printf_to_logs(
-					   QB_LOGSYS_ENCODE_RECID(
-						QB_LOGSYS_LEVEL_EMERG,
-						subsysid,
-						QB_LOGSYS_RECID_LOG),
-					   __FILE__, __FUNCTION__, __LINE__,
-					   tmpbuffer);
-		}
-	}
-
-	/*
-	 * Output to stderr
-	 */
-	if ((qb_logsys_loggers[subsysid].mode & QB_LOGSYS_MODE_OUTPUT_STDERR) &&
-	     ((level <= qb_logsys_loggers[subsysid].logfile_priority) ||
-	     (qb_logsys_loggers[subsysid].debug != 0))) {
-		if (write (STDERR_FILENO, normal_output_buffer, strlen (normal_output_buffer)) < 0) {
-			char tmpbuffer[1024];
-			/*
-			 * if we are here, it's bad.. it's really really bad.
-			 * Best thing would be to light 20 candles for each saint
-			 * in the calendar and pray a lot...
-			 */
-			pthread_mutex_lock (&qb_logsys_config_mutex);
-			qb_logsys_loggers[subsysid].mode &= ~QB_LOGSYS_MODE_OUTPUT_STDERR;
-			pthread_mutex_unlock (&qb_logsys_config_mutex);
-			snprintf(tmpbuffer, sizeof(tmpbuffer),
-				"QB_LOGSYS EMERGENCY: %s Unable to write to STDERR.",
-				qb_logsys_loggers[subsysid].subsys);
-			log_printf_to_logs(
-					   QB_LOGSYS_ENCODE_RECID(
-						QB_LOGSYS_LEVEL_EMERG,
-						subsysid,
-						QB_LOGSYS_RECID_LOG),
-					   __FILE__, __FUNCTION__, __LINE__,
-					   tmpbuffer);
-		}
-	}
-}
-
-static void record_print (const char *buf)
-{
-	const int *buf_uint32t = (const int *)buf;
-	unsigned int rec_size = buf_uint32t[0];
-	unsigned int rec_ident = buf_uint32t[1];
-	unsigned int file_line = buf_uint32t[2];
-	unsigned int i;
-	unsigned int words_processed;
-	unsigned int arg_size_idx;
-	const void *arguments[FDMAX_ARGS];
-	unsigned int arg_count;
-
-	arg_size_idx = 4;
-	words_processed = 4;
-	arg_count = 0;
-
-	for (i = 0; words_processed < rec_size; i++) {
-		arguments[arg_count++] = &buf_uint32t[arg_size_idx + 1];
-		arg_size_idx += buf_uint32t[arg_size_idx] + 1;
-		words_processed += buf_uint32t[arg_size_idx] + 1;
-	}
-
-	/*
-	 * (char *)arguments[0] -> subsystem
-	 * (char *)arguments[1] -> file_name
-	 * (char *)arguments[2] -> function_name
-	 * (char *)arguments[3] -> message
-	 */
-
-	log_printf_to_logs (
-		rec_ident,
-		(char *)arguments[1],
-		(char *)arguments[2],
-		file_line,
-		(char *)arguments[3]);
-}
-
-static int record_read (char *buf, int rec_idx, int *log_msg) {
-	unsigned int rec_size;
-	unsigned int rec_ident;
-	int firstcopy, secondcopy;
-
-	rec_size = flt_data[rec_idx];
-	rec_ident = flt_data[(rec_idx + 1) % flt_data_size];
-
-	/*
-	 * Not a log record
-	 */
-	if (QB_LOGSYS_DECODE_RECID(rec_ident) != QB_LOGSYS_RECID_LOG) {
-		*log_msg = 0;
-		return ((rec_idx + rec_size) % flt_data_size);
-	}
-
-	/*
-	 * A log record
-	 */
-	*log_msg = 1;
-
-        firstcopy = rec_size;
-        secondcopy = 0;
-        if (firstcopy + rec_idx > flt_data_size) {
-                firstcopy = flt_data_size - rec_idx;
-                secondcopy -= firstcopy - rec_size;
-        }
-        memcpy (&buf[0], &flt_data[rec_idx], firstcopy << 2);
-        if (secondcopy) {
-                memcpy (&buf[(firstcopy << 2)], &flt_data[0], secondcopy << 2);
-        }
-        return ((rec_idx + rec_size) % flt_data_size);
-}
-
-static inline void wthread_signal (void)
-{
-	if (wthread_active == 0) {
-		return;
-	}
-	pthread_mutex_lock (&qb_logsys_cond_mutex);
-	pthread_cond_signal (&qb_logsys_cond);
-	pthread_mutex_unlock (&qb_logsys_cond_mutex);
-}
-
-static inline void wthread_wait (void)
-{
-	pthread_mutex_lock (&qb_logsys_cond_mutex);
-	pthread_cond_wait (&qb_logsys_cond, &qb_logsys_cond_mutex);
-	pthread_mutex_unlock (&qb_logsys_cond_mutex);
-}
-
-static inline void wthread_wait_locked (void)
-{
-	pthread_cond_wait (&qb_logsys_cond, &qb_logsys_cond_mutex);
-	pthread_mutex_unlock (&qb_logsys_cond_mutex);
-}
-
-static void *qb_logsys_worker_thread (void *data) __attribute__((__noreturn__));
-static void *qb_logsys_worker_thread (void *data)
-{
-	int log_msg;
-	char buf[COMBINE_BUFFER_SIZE];
-
-	/*
-	 * Signal wthread_create that the initialization process may continue
-	 */
-	wthread_signal ();
-	qb_logsys_lock();
-	log_rec_idx = flt_data[FDTAIL_INDEX];
-	qb_logsys_unlock();
-
-	for (;;) {
-		wthread_wait ();
-		/*
-		 * Read and copy the logging record index position
-		 * It may have been updated by records_reclaim if
-		 * messages were lost or or log_rec on the first new
-		 * logging record available
-		 */
-		/*
-		 * Process any pending log messages here
-		 */
-		for (;;) {
-			int yield_counter = 1;
-
-			qb_logsys_lock();
-			if (log_requests_lost > 0) {
-				printf ("lost %d log requests\n", log_requests_lost);
-				log_requests_pending -= log_requests_lost;
-				log_requests_lost = 0;
-			}
-			if (log_requests_pending == 0) {
-				qb_logsys_unlock();
-				break;
-			}
-			log_rec_idx = record_read (buf, log_rec_idx, &log_msg);
-			if (log_msg) {
-				log_requests_pending -= 1;
-			}
-			qb_logsys_unlock();
-
-			/*
-			 * print the stored buffer
-			 */
-			if (log_msg) {
-				record_print (buf);
-				if (yield_counter++ > qb_logsys_after_log_ops_yield) {
-					yield_counter = 0;
-					sched_yield ();
-				}
-			}
-		}
-
-		if (wthread_should_exit) {
-			pthread_exit (NULL);
-		}
-	}
-}
-
-static void wthread_create (void)
-{
-	int res;
-
-	if (wthread_active) {
-		return;
-	}
-
-	wthread_active = 1;
-
-	pthread_mutex_init (&qb_logsys_cond_mutex, NULL);
-	pthread_cond_init (&qb_logsys_cond, NULL);
-	pthread_mutex_lock (&qb_logsys_cond_mutex);
-
-	/*
-	 * TODO: propagate pthread_create errors back to the caller
-	 */
-	res = pthread_create (&qb_logsys_thread_id, NULL,
-		qb_logsys_worker_thread, NULL);
-
-	if (res == 0) {
-		/*
-		 * Wait for thread to be started
-		 */
-		wthread_wait_locked ();
-		if (qb_logsys_sched_param_queued == 1) {
-			/*
-			 * TODO: propagate qb_logsys_thread_priority_set errors back to
-			 * the caller
-			 */
-			res = qb_logsys_thread_priority_set (qb_logsys_sched_policy,
-						    &qb_logsys_sched_param,
-						    qb_logsys_after_log_ops_yield);
-			qb_logsys_sched_param_queued = 0;
-		}
-	} else {
-		wthread_active = 0;
-	}
-}
-
-static int _logsys_config_subsys_get_unlocked (const char *subsys)
-{
-	unsigned int i;
-
-	if (!subsys) {
-		return QB_LOGSYS_MAX_SUBSYS_COUNT;
-	}
-
- 	for (i = 0; i <= QB_LOGSYS_MAX_SUBSYS_COUNT; i++) {
-		if (strcmp (qb_logsys_loggers[i].subsys, subsys) == 0) {
-			return i;
-		}
-	}
-
-	return (-1);
-}
-
-static void syslog_facility_reconf (void)
-{
-	closelog();
-	openlog(qb_logsys_loggers[QB_LOGSYS_MAX_SUBSYS_COUNT].subsys,
-		LOG_CONS|LOG_PID,
-		qb_logsys_loggers[QB_LOGSYS_MAX_SUBSYS_COUNT].syslog_facility);
-}
-
-/*
- * this is always invoked within the mutex, so it's safe to parse the
- * whole thing as we need.
- */
-static void qb_logsys_close_logfile (
-	int subsysid)
-{
-	int i;
-
-	if ((qb_logsys_loggers[subsysid].logfile_fp == NULL) &&
-	    (qb_logsys_loggers[subsysid].logfile == NULL)) {
-		return;
-	}
-
-	/*
-	 * if there is another subsystem or system using the same fp,
-	 * then we clean our own structs, but we can't close the file
-	 * as it is in use by somebody else.
-	 * Only the last users will be allowed to perform the fclose.
-	 */
- 	for (i = 0; i <= QB_LOGSYS_MAX_SUBSYS_COUNT; i++) {
-		if ((qb_logsys_loggers[i].logfile_fp == qb_logsys_loggers[subsysid].logfile_fp) &&
-		    (i != subsysid)) {
-			qb_logsys_loggers[subsysid].logfile = NULL;
-			qb_logsys_loggers[subsysid].logfile_fp = NULL;
-			return;
-		}
-	}
-
-	/*
-	 * if we are here, we are the last users of that fp, so we can safely
-	 * close it.
-	 */
-	fclose (qb_logsys_loggers[subsysid].logfile_fp);
-	qb_logsys_loggers[subsysid].logfile_fp = NULL;
-	free (qb_logsys_loggers[subsysid].logfile);
-	qb_logsys_loggers[subsysid].logfile = NULL;
-}
-
-/*
- * we need a version that can work when somebody else is already
- * holding a config mutex lock or we will never get out of here
- */
-static int qb_logsys_config_file_set_unlocked (
-		int subsysid,
-		const char **error_string,
-		const char *file)
-{
-	static char error_string_response[512];
-	int i;
-
-	qb_logsys_close_logfile(subsysid);
-
-	if ((file == NULL) ||
-	    (strcmp(qb_logsys_loggers[subsysid].subsys, "") == 0)) {
-		return (0);
-	}
-
-	if (strlen(file) >= PATH_MAX) {
-		snprintf (error_string_response,
-			sizeof(error_string_response),
-			"%s: logfile name exceed maximum system filename lenght\n",
-			qb_logsys_loggers[subsysid].subsys);
-		*error_string = error_string_response;
-		return (-1);
-	}
-
-	for (i = 0; i <= QB_LOGSYS_MAX_SUBSYS_COUNT; i++) {
-		if ((qb_logsys_loggers[i].logfile != NULL) &&
-			(strcmp (qb_logsys_loggers[i].logfile, file) == 0) &&
-			(i != subsysid)) {
-				qb_logsys_loggers[subsysid].logfile =
-					qb_logsys_loggers[i].logfile;
-				qb_logsys_loggers[subsysid].logfile_fp =
-					qb_logsys_loggers[i].logfile_fp;
-				return (0);
-		}
-	}
-
-	qb_logsys_loggers[subsysid].logfile = strdup(file);
-	if (qb_logsys_loggers[subsysid].logfile == NULL) {
-		snprintf (error_string_response,
-			sizeof(error_string_response),
-			"Unable to allocate memory for logfile '%s'\n",
-			file);
-		*error_string = error_string_response;
-		return (-1);
-	}
-
-	qb_logsys_loggers[subsysid].logfile_fp = fopen (file, "a+");
-	if (qb_logsys_loggers[subsysid].logfile_fp == NULL) {
-		char error_str[100];
-		strerror_r (errno, error_str, 100);
-		free(qb_logsys_loggers[subsysid].logfile);
-		qb_logsys_loggers[subsysid].logfile = NULL;
-		snprintf (error_string_response,
-			sizeof(error_string_response),
-			"Can't open logfile '%s' for reason (%s).\n",
-				 file, error_str);
-		*error_string = error_string_response;
-		return (-1);
-	}
-
-	return (0);
-}
-
-static void qb_logsys_subsys_init (
-		const char *subsys,
-		int subsysid)
-{
-	if (qb_logsys_system_needs_init == QB_LOGSYS_LOGGER_NEEDS_INIT) {
-		qb_logsys_loggers[subsysid].init_status =
-			QB_LOGSYS_LOGGER_NEEDS_INIT;
-	} else {
-		memcpy(&qb_logsys_loggers[subsysid],
-		       &qb_logsys_loggers[QB_LOGSYS_MAX_SUBSYS_COUNT],
-		       sizeof(qb_logsys_loggers[QB_LOGSYS_MAX_SUBSYS_COUNT]));
-		qb_logsys_loggers[subsysid].init_status =
-			QB_LOGSYS_LOGGER_INIT_DONE;
-	}
-	strncpy (qb_logsys_loggers[subsysid].subsys, subsys,
-		QB_LOGSYS_MAX_SUBSYS_NAMELEN);
-}
-
-/*
- * Internal API - exported
- */
-
-int _logsys_system_setup(
-	const char *mainsystem,
-	unsigned int mode,
-	unsigned int debug,
-	const char *logfile,
-	int logfile_priority,
-	int syslog_facility,
-	int syslog_priority)
-{
-	int i;
-	const char *errstr;
-	char tempsubsys[QB_LOGSYS_MAX_SUBSYS_NAMELEN];
-
-	if ((mainsystem == NULL) ||
-	    (strlen(mainsystem) >= QB_LOGSYS_MAX_SUBSYS_NAMELEN)) {
-		return -1;
-	}
-
-	i = QB_LOGSYS_MAX_SUBSYS_COUNT;
-
-	pthread_mutex_lock (&qb_logsys_config_mutex);
-
-	snprintf(qb_logsys_loggers[i].subsys,
-		 QB_LOGSYS_MAX_SUBSYS_NAMELEN,
-		"%s", mainsystem);
-
-	qb_logsys_loggers[i].mode = mode;
-
-	qb_logsys_loggers[i].debug = debug;
-
-	if (qb_logsys_config_file_set_unlocked (i, &errstr, logfile) < 0) {
-		pthread_mutex_unlock (&qb_logsys_config_mutex);
-		return (-1);
-	}
-	qb_logsys_loggers[i].logfile_priority = logfile_priority;
-
-	qb_logsys_loggers[i].syslog_facility = syslog_facility;
-	qb_logsys_loggers[i].syslog_priority = syslog_priority;
-	syslog_facility_reconf();
-
-	qb_logsys_loggers[i].init_status = QB_LOGSYS_LOGGER_INIT_DONE;
-
-	qb_logsys_system_needs_init = QB_LOGSYS_LOGGER_INIT_DONE;
-
-	for (i = 0; i < QB_LOGSYS_MAX_SUBSYS_COUNT; i++) {
-		if ((strcmp (qb_logsys_loggers[i].subsys, "") != 0) &&
-			(qb_logsys_loggers[i].init_status ==
-			 QB_LOGSYS_LOGGER_NEEDS_INIT)) {
-				strncpy (tempsubsys, qb_logsys_loggers[i].subsys,
-					QB_LOGSYS_MAX_SUBSYS_NAMELEN);
-				qb_logsys_subsys_init(tempsubsys, i);
-		}
-	}
-
-	pthread_mutex_unlock (&qb_logsys_config_mutex);
-
-	return (0);
-}
-
-unsigned int _logsys_subsys_create (const char *subsys)
-{
-	int i;
-
-	if ((subsys == NULL) ||
-	    (strlen(subsys) >= QB_LOGSYS_MAX_SUBSYS_NAMELEN)) {
-		return -1;
-	}
-
-	pthread_mutex_lock (&qb_logsys_config_mutex);
-
-	i = _logsys_config_subsys_get_unlocked (subsys);
-	if ((i > -1) && (i < QB_LOGSYS_MAX_SUBSYS_COUNT)) {
-		pthread_mutex_unlock (&qb_logsys_config_mutex);
-		return i;
-	}
-
-	for (i = 0; i < QB_LOGSYS_MAX_SUBSYS_COUNT; i++) {
-		if (strcmp (qb_logsys_loggers[i].subsys, "") == 0) {
-			qb_logsys_subsys_init(subsys, i);
-			break;
-		}
-	}
-
-	if (i >= QB_LOGSYS_MAX_SUBSYS_COUNT) {
-		i = -1;
-	}
-
-	pthread_mutex_unlock (&qb_logsys_config_mutex);
-	return i;
-}
-
-int _logsys_wthread_create (void)
-{
-	if (((qb_logsys_loggers[QB_LOGSYS_MAX_SUBSYS_COUNT].mode & QB_LOGSYS_MODE_FORK) == 0) &&
-		((qb_logsys_loggers[QB_LOGSYS_MAX_SUBSYS_COUNT].mode & QB_LOGSYS_MODE_THREADED) != 0)) {
-		wthread_create();
-		atexit (qb_logsys_atexit);
-	}
-	return (0);
-}
-
-int _logsys_rec_init (unsigned int fltsize)
-{
-	/*
-	 * we need to allocate:
-	 * - requested size +
-	 *   2 extra unsigned ints for HEAD/TAIL tracking
-	 *
-	 * then round it up to the next PAGESIZE
-	 */
-	size_t flt_real_size;
-
-	/*
-	 * XXX: kill me for 1.1 because I am a dirty hack
-	 * temporary workaround that will be replaced by supporting
-	 * 0 byte size flight recorder buffer.
-	 * 0 byte size buffer will enable direct printing to logs
-	 *   without flight recoder.
-	 */
-	if (fltsize < 64000) {
-		fltsize = 64000;
-	}
-
-	flt_real_size = ROUNDUP(
-			(fltsize + (2 * sizeof (unsigned int))),
-			sysconf(_SC_PAGESIZE));
-
-	flt_data = malloc (flt_real_size);
-	if (flt_data == NULL) {
-		return (-1);
-	}
-
-	/*
-	 * flt_data_size tracks data by ints and not bytes/chars.
-	 *
-	 * the last 2 ints are reserved to store HEAD/TAIL information.
-	 * hide them from the rotating buffer.
-	 */
-
-	flt_data_size = ((flt_real_size / sizeof (unsigned int)) - 2);
-
-	/*
-	 * First record starts at zero
-	 * Last record ends at zero
-	 */
-	flt_data[FDHEAD_INDEX] = 0;
-	flt_data[FDTAIL_INDEX] = 0;
-
-#if defined(HAVE_PTHREAD_SPIN_LOCK)
-	pthread_spin_init (&qb_logsys_idx_spinlock, 0);
-#endif
-
-	return (0);
-}
-
-
-/*
- * u32 RECORD SIZE
- * u32 record ident
- * u32 arg count
- * u32 file line
- * u32 subsys length
- * buffer null terminated subsys
- * u32 filename length
- * buffer null terminated filename
- * u32 filename length
- * buffer null terminated function
- * u32 arg1 length
- * buffer arg1
- * ... repeats length & arg
- */
-
-void _logsys_log_rec (
-	unsigned int rec_ident,
-	const char *function_name,
-	const char *file_name,
-	int file_line,
-	...)
-{
-	va_list ap;
-	const void *buf_args[FDMAX_ARGS];
-	unsigned int buf_len[FDMAX_ARGS];
-	unsigned int i;
-	unsigned int idx;
-	unsigned int arguments = 0;
-	unsigned int record_reclaim_size = 0;
-	unsigned int index_start;
-	int words_written;
-	int subsysid;
-
-	subsysid = QB_LOGSYS_DECODE_SUBSYSID(rec_ident);
-
-	/*
-	 * Decode VA Args
-	 */
-	va_start (ap, file_line);
-	arguments = 3;
-	for (;;) {
-		buf_args[arguments] = va_arg (ap, void *);
-		if (buf_args[arguments] == QB_LOGSYS_REC_END) {
-			break;
-		}
-		buf_len[arguments] = va_arg (ap, int);
-		record_reclaim_size += ((buf_len[arguments] + 3) >> 2) + 1;
-		arguments++;
-		if (arguments >= FDMAX_ARGS) {
-			break;
-		}
-	}
-	va_end (ap);
-
-	/*
-	 * Encode qb_logsys subsystem identity, filename, and function
-	 */
-	buf_args[0] = qb_logsys_loggers[subsysid].subsys;
-	buf_len[0] = strlen (qb_logsys_loggers[subsysid].subsys) + 1;
-	buf_args[1] = file_name;
-	buf_len[1] = strlen (file_name) + 1;
-	buf_args[2] = function_name;
-	buf_len[2] = strlen (function_name) + 1;
-	for (i = 0; i < 3; i++) {
-		record_reclaim_size += ((buf_len[i] + 3) >> 2) + 1;
-	}
-
-	idx = flt_data[FDHEAD_INDEX];
-	index_start = idx;
-
-	/*
-	 * Reclaim data needed for record including 4 words for the header
-	 */
-	records_reclaim (idx, record_reclaim_size + 4);
-
-	/*
-	 * Write record size of zero and rest of header information
-	 */
-	flt_data[idx++] = 0;
-	idx_word_step(idx);
-
-	flt_data[idx++] = rec_ident;
-	idx_word_step(idx);
-
-	flt_data[idx++] = file_line;
-	idx_word_step(idx);
-
-	flt_data[idx++] = records_written;
-	idx_word_step(idx);
-	/*
-	 * Encode all of the arguments into the log message
-	 */
-	for (i = 0; i < arguments; i++) {
-		unsigned int bytes;
-		unsigned int full_words;
-		unsigned int total_words;
-
-		bytes = buf_len[i];
-		full_words = bytes >> 2;
-		total_words = (bytes + 3) >> 2;
-
-		flt_data[idx++] = total_words;
-		idx_word_step(idx);
-
-		/*
-		 * determine if this is a wrapped write or normal write
-		 */
-		if (idx + total_words < flt_data_size) {
-			/*
-			 * dont need to wrap buffer
-			 */
-			my_memcpy_32bit (&flt_data[idx], buf_args[i], full_words);
-			if (bytes % 4) {
-				my_memcpy_8bit ((char *)&flt_data[idx + full_words],
-					((const char *)buf_args[i]) + (full_words << 2), bytes % 4);
-			}
-		} else {
-			/*
-			 * need to wrap buffer
-			 */
-			unsigned int first;
-			unsigned int second;
-
-			first = flt_data_size - idx;
-			if (first > full_words) {
-				first = full_words;
-			}
-			second = full_words - first;
-			my_memcpy_32bit (&flt_data[idx],
-					 (const int *)buf_args[i], first);
-			my_memcpy_32bit (&flt_data[0],
-				(const int *)(((const unsigned char *)buf_args[i]) + (first << 2)),
-				second);
-			if (bytes % 4) {
-				my_memcpy_8bit ((char *)&flt_data[0 + second],
-					((const char *)buf_args[i]) + (full_words << 2), bytes % 4);
-			}
-		}
-		idx += total_words;
-		idx_buffer_step (idx);
-	}
-	words_written = idx - index_start;
-	if (words_written < 0) {
-		words_written += flt_data_size;
-	}
-
-	/*
-	 * Commit the write of the record size now that the full record
-	 * is in the memory buffer
-	 */
-	flt_data[index_start] = words_written;
-
-	/*
-	 * If the index of the current head equals the current log_rec_idx,
-	 * and this is not a log_printf operation, set the log_rec_idx to
-	 * the new head position and commit the new head.
-	 */
-	qb_logsys_lock();
-	if (QB_LOGSYS_DECODE_RECID(rec_ident) == QB_LOGSYS_RECID_LOG) {
-		log_requests_pending += 1;
-	}
-	if (log_requests_pending == 0) {
-		log_rec_idx = idx;
-	}
-	flt_data[FDHEAD_INDEX] = idx;
-	qb_logsys_unlock();
-	records_written++;
-}
-
-void _logsys_log_vprintf (
-	unsigned int rec_ident,
-	const char *function_name,
-	const char *file_name,
-	int file_line,
-	const char *format,
-	va_list ap)
-{
-	char qb_logsys_print_buffer[COMBINE_BUFFER_SIZE];
-	unsigned int len;
-	unsigned int level;
-	int subsysid;
-	const char *short_file_name;
-
-	subsysid = QB_LOGSYS_DECODE_SUBSYSID(rec_ident);
-	level = QB_LOGSYS_DECODE_LEVEL(rec_ident);
-
-	if ((level > qb_logsys_loggers[subsysid].syslog_priority) &&
-	    (level > qb_logsys_loggers[subsysid].logfile_priority) &&
-	    (qb_logsys_loggers[subsysid].debug == 0)) {
-		return;
-	}
-
-	len = vsprintf (qb_logsys_print_buffer, format, ap);
-	if (qb_logsys_print_buffer[len - 1] == '\n') {
-		qb_logsys_print_buffer[len - 1] = '\0';
-		len -= 1;
-	}
-#ifdef BUILDING_IN_PLACE
-	short_file_name = file_name;
-#else
-	short_file_name = strrchr (file_name, '/');
-	if (short_file_name == NULL)
-		short_file_name = file_name;
-	else
-		short_file_name++; /* move past the "/" */
-#endif /* BUILDING_IN_PLACE */
-
-	/*
-	 * Create a log record
-	 */
-	_logsys_log_rec (
-		rec_ident,
-		function_name,
-		short_file_name,
-		file_line,
-		qb_logsys_print_buffer, len + 1,
-		QB_LOGSYS_REC_END);
-
-	if ((qb_logsys_loggers[QB_LOGSYS_MAX_SUBSYS_COUNT].mode & QB_LOGSYS_MODE_THREADED) == 0) {
-		/*
-		 * Output (and block) if the log mode is not threaded otherwise
-		 * expect the worker thread to output the log data once signaled
-		 */
-		log_printf_to_logs (rec_ident,
-				    short_file_name, function_name, file_line,
-				    qb_logsys_print_buffer);
-	} else {
-		/*
-		 * Signal worker thread to display logging output
-		 */
-		wthread_signal ();
-	}
-}
-
-void _logsys_log_printf (
-	unsigned int rec_ident,
-	const char *function_name,
-	const char *file_name,
-	int file_line,
-	const char *format,
-	...)
-{
-	va_list ap;
-
-	va_start (ap, format);
-	_logsys_log_vprintf (rec_ident, function_name, file_name, file_line,
-		format, ap);
-	va_end (ap);
-}
-
-int _logsys_config_subsys_get (const char *subsys)
-{
-	unsigned int i;
-
-	pthread_mutex_lock (&qb_logsys_config_mutex);
-
-	i = _logsys_config_subsys_get_unlocked (subsys);
-
-	pthread_mutex_unlock (&qb_logsys_config_mutex);
-
-	return i;
-}
-
-/*
- * External Configuration and Initialization API
- */
-void qb_logsys_fork_completed (void)
-{
-	qb_logsys_loggers[QB_LOGSYS_MAX_SUBSYS_COUNT].mode &= ~QB_LOGSYS_MODE_FORK;
-	_logsys_wthread_create ();
-}
-
-unsigned int qb_logsys_config_mode_set (const char *subsys, unsigned int mode)
-{
-	int i;
-
-	pthread_mutex_lock (&qb_logsys_config_mutex);
-	if (subsys != NULL) {
-		i = _logsys_config_subsys_get_unlocked (subsys);
-		if (i >= 0) {
-			qb_logsys_loggers[i].mode = mode;
-			i = 0;
-		}
-	} else {
-		for (i = 0; i <= QB_LOGSYS_MAX_SUBSYS_COUNT; i++) {
-			qb_logsys_loggers[i].mode = mode;
-		}
-		i = 0;
-	}
-	pthread_mutex_unlock (&qb_logsys_config_mutex);
-
-	return i;
-}
-
-unsigned int qb_logsys_config_mode_get (const char *subsys)
-{
-	int i;
-
-	i = _logsys_config_subsys_get (subsys);
-	if (i < 0) {
-		return i;
-	}
-
-	return qb_logsys_loggers[i].mode;
-}
-
-int qb_logsys_config_file_set (
-		const char *subsys,
-		const char **error_string,
-		const char *file)
-{
-	int i;
-	int res;
-
-	pthread_mutex_lock (&qb_logsys_config_mutex);
-
-	if (subsys != NULL) {
-		i = _logsys_config_subsys_get_unlocked (subsys);
-		if (i < 0) {
-			res = i;
-		} else {
-			res = qb_logsys_config_file_set_unlocked(i, error_string, file);
-		}
-	} else {
-		for (i = 0; i <= QB_LOGSYS_MAX_SUBSYS_COUNT; i++) {
-			res = qb_logsys_config_file_set_unlocked(i, error_string, file);
-			if (res < 0) {
-				break;
-			}
-		}
-	}
-
-	pthread_mutex_unlock (&qb_logsys_config_mutex);
-	return res;
-}
-
-int qb_logsys_format_set (const char *format)
-{
-	int ret = 0;
-
-	pthread_mutex_lock (&qb_logsys_config_mutex);
-
-	if (format_buffer) {
-		free(format_buffer);
-		format_buffer = NULL;
-	}
-
-	format_buffer = strdup(format ? format : "%p [%6s] %b");
-	if (format_buffer == NULL) {
-		ret = -1;
-	}
-
-	pthread_mutex_unlock (&qb_logsys_config_mutex);
-	return ret;
-}
-
-char *qb_logsys_format_get (void)
-{
-	return format_buffer;
-}
-
-unsigned int qb_logsys_config_syslog_facility_set (
-	const char *subsys,
-	unsigned int facility)
-{
-	int i;
-
-	pthread_mutex_lock (&qb_logsys_config_mutex);
-	if (subsys != NULL) {
-		i = _logsys_config_subsys_get_unlocked (subsys);
-		if (i >= 0) {
-			qb_logsys_loggers[i].syslog_facility = facility;
-			if (i == QB_LOGSYS_MAX_SUBSYS_COUNT) {
-				syslog_facility_reconf();
-			}
-			i = 0;
-		}
-	} else {
-		for (i = 0; i <= QB_LOGSYS_MAX_SUBSYS_COUNT; i++) {
-			qb_logsys_loggers[i].syslog_facility = facility;
-		}
-		syslog_facility_reconf();
-		i = 0;
-	}
-	pthread_mutex_unlock (&qb_logsys_config_mutex);
-
-	return i;
-}
-
-unsigned int qb_logsys_config_syslog_priority_set (
-	const char *subsys,
-	unsigned int priority)
-{
-	int i;
-
-	pthread_mutex_lock (&qb_logsys_config_mutex);
-	if (subsys != NULL) {
-		i = _logsys_config_subsys_get_unlocked (subsys);
-		if (i >= 0) {
-			qb_logsys_loggers[i].syslog_priority = priority;
-			i = 0;
-		}
-	} else {
-		for (i = 0; i <= QB_LOGSYS_MAX_SUBSYS_COUNT; i++) {
-			qb_logsys_loggers[i].syslog_priority = priority;
-		}
-		i = 0;
-	}
-	pthread_mutex_unlock (&qb_logsys_config_mutex);
-
-	return i;
-}
-
-unsigned int qb_logsys_config_logfile_priority_set (
-	const char *subsys,
-	unsigned int priority)
-{
-	int i;
-
-	pthread_mutex_lock (&qb_logsys_config_mutex);
-	if (subsys != NULL) {
-		i = _logsys_config_subsys_get_unlocked (subsys);
-		if (i >= 0) {
-			qb_logsys_loggers[i].logfile_priority = priority;
-			i = 0;
-		}
-	} else {
-		for (i = 0; i <= QB_LOGSYS_MAX_SUBSYS_COUNT; i++) {
-			qb_logsys_loggers[i].logfile_priority = priority;
-		}
-		i = 0;
-	}
-	pthread_mutex_unlock (&qb_logsys_config_mutex);
-
-	return i;
-}
-
-unsigned int qb_logsys_config_debug_set (
-	const char *subsys,
-	unsigned int debug)
-{
-	int i;
-
-	pthread_mutex_lock (&qb_logsys_config_mutex);
-	if (subsys != NULL) {
-		i = _logsys_config_subsys_get_unlocked (subsys);
-		if (i >= 0) {
-			qb_logsys_loggers[i].debug = debug;
-			i = 0;
-		}
-	} else {
-		for (i = 0; i <= QB_LOGSYS_MAX_SUBSYS_COUNT; i++) {
-			qb_logsys_loggers[i].debug = debug;
-		}
-		i = 0;
-	}
-	pthread_mutex_unlock (&qb_logsys_config_mutex);
-
-	return i;
-}
-
-int qb_logsys_facility_id_get (const char *name)
-{
-	unsigned int i;
-
-	for (i = 0; facilitynames[i].c_name != NULL; i++) {
-		if (strcasecmp(name, facilitynames[i].c_name) == 0) {
-			return (facilitynames[i].c_val);
-		}
-	}
-	return (-1);
-}
-
-const char *qb_logsys_facility_name_get (unsigned int facility)
-{
-	unsigned int i;
-
-	for (i = 0; facilitynames[i].c_name != NULL; i++) {
-		if (facility == facilitynames[i].c_val) {
-			return (facilitynames[i].c_name);
-		}
-	}
-	return (NULL);
-}
-
-int qb_logsys_priority_id_get (const char *name)
-{
-	unsigned int i;
-
-	for (i = 0; prioritynames[i].c_name != NULL; i++) {
-		if (strcasecmp(name, prioritynames[i].c_name) == 0) {
-			return (prioritynames[i].c_val);
-		}
-	}
-	return (-1);
-}
-
-const char *qb_logsys_priority_name_get (unsigned int priority)
-{
-	unsigned int i;
-
-	for (i = 0; prioritynames[i].c_name != NULL; i++) {
-		if (priority == prioritynames[i].c_val) {
-			return (prioritynames[i].c_name);
-		}
-	}
-	return (NULL);
-}
-
-int qb_logsys_thread_priority_set (
-	int policy,
-	const struct sched_param *param,
-        unsigned int after_log_ops_yield)
-
-{
-	int res = 0;
-
-#if defined(HAVE_PTHREAD_SETSCHEDPARAM) && defined(HAVE_SCHED_GET_PRIORITY_MAX)
-	if (wthread_active == 0) {
-		qb_logsys_sched_policy = policy;
-		memcpy(&qb_logsys_sched_param, &param, sizeof(struct sched_param));
-		qb_logsys_sched_param_queued = 1;
-	} else {
-		res = pthread_setschedparam (qb_logsys_thread_id, policy, param);
-	}
-#endif
-
-	if (after_log_ops_yield > 0) {
-		qb_logsys_after_log_ops_yield = after_log_ops_yield;
-	}
-
-	return (res);
-}
-
-int qb_logsys_log_rec_store (const char *filename)
-{
-	int fd;
-	ssize_t written_size;
-	size_t size_to_write = (flt_data_size + 2) * sizeof (unsigned int);
-
-	fd = open (filename, O_CREAT|O_RDWR, 0700);
-	if (fd < 0) {
-		return (-1);
-	}
-
-	written_size = write (fd, &flt_data_size, sizeof(unsigned int));
-	if ((written_size < 0) || (written_size != sizeof(unsigned int))) {
-		close (fd);
-		return (-1);
-	}
-
-	written_size = write (fd, flt_data, size_to_write);
-	if (close (fd) != 0)
-		return (-1);
-	if (written_size < 0) {
-		return (-1);
-	} else if ((size_t)written_size != size_to_write) {
-		return (-1);
-	}
-
-	return (0);
-}
-
-void qb_logsys_atexit (void)
-{
-	if (wthread_active) {
-		wthread_should_exit = 1;
-		wthread_signal ();
-		pthread_join (qb_logsys_thread_id, NULL);
-	}
-}
-
-void qb_logsys_flush (void)
-{
-	wthread_signal ();
-}
diff --git a/lib/plugin/Makefile.am b/lib/plugin/Makefile.am
deleted file mode 100644
index 9a76c42..0000000
--- a/lib/plugin/Makefile.am
+++ /dev/null
@@ -1,78 +0,0 @@
-# Copyright (c) 2009 Red Hat, Inc.
-#
-# Authors: Andrew Beekhof
-#	   Steven Dake (sdake@redhat.com)
-#
-# This software licensed under BSD license, the text of which follows:
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are met:
-#
-# - Redistributions of source code must retain the above copyright notice,
-#   this list of conditions and the following disclaimer.
-# - 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.
-# - Neither the name of the MontaVista Software, Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
-MAINTAINERCLEANFILES    = Makefile.in
-
-AM_CFLAGS		= -fPIC
-
-INCLUDES 		= -I$(top_builddir)/include -I$(top_srcdir)/include
-
-lib_LIBRARIES		= libqbplugin.a
-
-noinst_PROGRAMS		= test test_static uic
-
-noinst_PLUGIN		= libtest_a.so libtest_b.so
-
-uic_SOURCES		= uic.c
-
-libqbplugin_a_SOURCES	= plugin_loader.c
-
-test_SOURCES		= test.c uis.c
-test_LDADD		= libqbplugin.a
-
-test_static_SOURCES	= test.c libtest_a.c libtest_b.c uis.c plugin_loader.c
-
-if BUILD_DARWIN
-
-%.so: %.o
-	$(CC) $(CFLAGS) -bundle -bundle_loader ./test $^ -o $@
-else
-
-if BUILD_SOLARIS
-
-%.so: %.o
-	$(CC) $(CFLAGS) -shared $^ -o $@
-else
-
-%.so: %.o
-	$(CC) $(CFLAGS) -shared -Wl,-soname,$@ $^ -o $@
-
-endif
-
-endif
-
-lint:
-	-splint $(LINT_FLAGS) $(CFLAGS) *.c
-
-all-local: $(noinst_PLUGIN)
-	@echo Built Plugin
-
-clean-local:
-	rm -f *.o *.a *.so* *.da *.bb *.bbg *.so
diff --git a/lib/plugin/README b/lib/plugin/README
deleted file mode 100644
index ad782d0..0000000
--- a/lib/plugin/README
+++ /dev/null
@@ -1,113 +0,0 @@
-Live Component Replacement
---------------------------
-All software is composed of components, which contain multiple software classes.
-Components generally depend upon other components and sometimes classes from
-other components.
-
-Some components of corosync are the evt service, the ckpt service, the clm
-service, the totem protocol, and others.  If a defect is found in any of
-these components, the entire ais executive must be stopped, replaced, and
-restarted.
-
-The lcr code formalizes the concept of components into dynamic libraries.  A
-component may have multiple classes.  Each class (the lcr code uses the word
-interface) may have multiple functions within the class.  Each interface may
-depend upon other interfaces, and those interfaces are then loaded prior to the
-requested interface being referenced.
-
-Note that with recent changes, the lcr interface factory can be used when
-statically linking without additional steps.  The interface for notifying
-lcr of a component has changed.
-
-A list of shared objects is scanned each time an interface is requested to
-load via the following interface:
-
-int lcr_ifact_reference (
-        void **handle,
-        char *iface_name,
-        int version,
-        void **interface,
-        void *context);
-
-The iface_name is the name of the interface, the version is the version,
-the void **interface is the list of functions returned once the interface
-has been dynamically loaded and referenced, and context is passed to the
-constructor and destructor.
-
-The interface is loaded, the interface constructor is called, and the list
-of interfaces is returned back to the caller.
-
-First the list of interfaces is described in an iface_list data structure:
-struct iface_list iface_list = {
-        .iface1_func1           = iface1_func1,
-        .iface1_func2           = iface1_func2,
-        .iface1_func3           = iface1_func3,
-};
-iface1_func1 is a simple function call.
-
-Then the lcr_iface data structure is defined for the c file:
-
-struct lcr_iface iface1_ver0 = {
-        .name                   = "iface1",
-        .version                = 0,
-        .versions_replace       = 0,
-        .versions_replace_count = 0,
-        .dependencies           = 0,
-        .dependency_count       = 0,
-        .constructor            = iface1_constructor,
-        .destructor             = iface1_destructor,
-        .interfaces             = (void **)&iface_list,
-};
-
-The name and version fields provide naming and versioning.  The constructor
-and destructor functions execute at reference and release times.  Finally
-the .interfaces type describes the list of functions used for the interface.
-
-Next, an lcr_comp must be described:
-
-struct lcr_comp test_comp = {
-        .iface_count            = 2,
-        .ifaces                 = lcr_ifaces
-};
-
-the iface count describes the number of interfaces within the component,
-and lcr_ifaces is an array of pointers to lcr_iface data types.
-
-The lcr_comp_get method has been replaced.  The final step is to setup a
-constructor that is started when the task is started.  This ctor will
-register the component with the lcr framework.
-
-static void register_this_component (void) {
-        lcr_component_register (&test_comp);
-}
-
-static void (*const __init_this_component[1]) (void) __attribute__ ((section(".ctors"))) = { register_this_component };
-
-
-Now the component can be referenced and used in another application.
-int main ()
-{
-
-.....
-
-	lcr_ifact_reference (
-		&ifact_handle_ver0,
-		"iface1",
-		0, /* version 0 */
-		(void **)&iface_ver0,
-		(void *)0xdeadbeef);
-
-	iface_ver0->func1();
-	iface_ver0->func2();
-	iface_ver0->func3();
-}
-
-
-See libtest_a and libtest_b for two sample components.  The test program
-demonstrates usage.  The test_static demonstrates operation when statically
-linked.  Note the dynamic inteface factory is still available for use when
-statically linking components.
-
-On startup, a thread is created which listens for requests from the "uic"
-application.  These requests are then processed by the lcr service which
-would execute a live replacement.
diff --git a/lib/plugin/libtest_a.c b/lib/plugin/libtest_a.c
deleted file mode 100644
index f0d5f8b..0000000
--- a/lib/plugin/libtest_a.c
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * Copyright (C) 2006 Steven Dake (sdake@redhat.com)
- *
- * This software licensed under BSD license, the text of which follows:
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * - Redistributions of source code must retain the above copyright notice,
- *   this list of conditions and the following disclaimer.
- * - 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.
- * - Neither the name of the MontaVista Software, Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
- */
-
-#include <config.h>
-
-#include <stdio.h>
-#include <qb/qbplugin_comp.h>
-
-/*
- * Version 0 of the interface
- */
-static int iface1_constructor (void *context);
-
-static void iface1_destructor (void *context);
-
-static void iface1_func1 (void);
-
-static void iface1_func2 (void);
-
-static void iface1_func3 (void);
-
-/*
- * Version 1 of the interface
- */
-static int iface1_ver1_constructor (void *context);
-
-static void iface1_ver1_destructor (void *context);
-
-static void iface1_ver1_func1 (void);
-
-static void iface1_ver1_func2 (void);
-
-static void iface1_ver1_func3 (void);
-
-struct iface_list {
-	void (*iface1_func1)(void);
-	void (*iface1_func2)(void);
-	void (*iface1_func3)(void);
-};
-
-struct iface_ver1_list {
-	void (*iface1_ver1_func1)(void);
-	void (*iface1_ver1_func2)(void);
-	void (*iface1_ver1_func3)(void);
-};
-
-static struct iface_list iface_list = {
-	.iface1_func1		= iface1_func1,
-	.iface1_func2		= iface1_func2,
-	.iface1_func3		= iface1_func3,
-};
-
-static struct iface_list iface_ver1_list = {
-	.iface1_func1		= iface1_ver1_func1,
-	.iface1_func2		= iface1_ver1_func2,
-	.iface1_func3		= iface1_ver1_func3,
-};
-
-static struct plugin_iface iface1[2] = {
-	/* version 0 */
-	{
-		.name			= "A_iface1",
-		.version		= 0,
-		.versions_replace	= 0,
-		.versions_replace_count	= 0,
-		.dependencies		= 0,
-		.dependency_count	= 0,
-		.constructor		= iface1_constructor,
-		.destructor		= iface1_destructor,
-		.interfaces		= NULL
-	},
-	/* version 1 */
-	{
-		.name			= "A_iface1",
-		.version		= 1,
-		.versions_replace	= 0,
-		.versions_replace_count	= 0,
-		.dependencies		= 0,
-		.dependency_count	= 0,
-		.constructor		= iface1_ver1_constructor,
-		.destructor		= iface1_ver1_destructor,
-		.interfaces		= NULL
-	}
-};
-
-static struct plugin_comp test_comp = {
-	.iface_count 		= 2,
-	.ifaces 		= iface1
-};
-
-static int iface1_constructor (void *context)
-{
-	printf ("A - version 0 constructor context %p\n", context);
-	return (0);
-}
-
-static void iface1_destructor (void *context)
-{
-	printf ("A - version 0 destructor context %p\n", context);
-}
-static void iface1_func1 (void) {
-	printf ("A - version 0 func1\n");
-}
-
-static void iface1_func2 (void) {
-	printf ("A - version 0 func2\n");
-}
-
-static void iface1_func3 (void) {
-	printf ("A - version 0 func3\n");
-}
-
-static int iface1_ver1_constructor (void *context)
-{
-	printf ("A - version 1 constructor context %p\n", context);
-	return (0);
-}
-
-static void iface1_ver1_destructor (void *context)
-{
-	printf ("A - version 1 destructor context %p\n", context);
-}
-static void iface1_ver1_func1 (void) {
-	printf ("A - version 1 func1\n");
-}
-
-static void iface1_ver1_func2 (void) {
-	printf ("A - version 1 func2\n");
-}
-
-static void iface1_ver1_func3 (void) {
-	printf ("A - version 1 func3\n");
-}
-
-__attribute__ ((constructor)) static void register_this_component (void) {
-	plugin_interfaces_set (&iface1[0], &iface_list);
-	plugin_interfaces_set (&iface1[1], &iface_ver1_list);
-	plugin_component_register (&test_comp);
-}
diff --git a/lib/plugin/libtest_b.c b/lib/plugin/libtest_b.c
deleted file mode 100644
index 77b128a..0000000
--- a/lib/plugin/libtest_b.c
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * Copyright (C) 2006 Steven Dake (sdake@redhat.com)
- *
- * This software licensed under BSD license, the text of which follows:
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * - Redistributions of source code must retain the above copyright notice,
- *   this list of conditions and the following disclaimer.
- * - 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.
- * - Neither the name of the MontaVista Software, Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
- */
-
-#include <config.h>
-
-#include <stdio.h>
-#include <qb/qbplugin_comp.h>
-
-/*
- * Version 0 of the interface
- */
-static int iface1_constructor (void *context);
-
-static void iface1_destructor (void *context);
-
-static void iface1_func1 (void);
-
-static void iface1_func2 (void);
-
-static void iface1_func3 (void);
-
-/*
- * Version 1 of the interface
- */
-static int iface1_ver1_constructor (void *context);
-
-static void iface1_ver1_destructor (void *context);
-
-static void iface1_ver1_func1 (void);
-
-static void iface1_ver1_func2 (void);
-
-static void iface1_ver1_func3 (void);
-
-struct iface_list {
-	void (*iface1_func1)(void);
-	void (*iface1_func2)(void);
-	void (*iface1_func3)(void);
-};
-
-struct iface_ver1_list {
-	void (*iface1_ver1_func1)(void);
-	void (*iface1_ver1_func2)(void);
-	void (*iface1_ver1_func3)(void);
-};
-
-struct iface_list iface_list = {
-	.iface1_func1		= iface1_func1,
-	.iface1_func2		= iface1_func2,
-	.iface1_func3		= iface1_func3,
-};
-
-struct iface_list iface_ver1_list = {
-	.iface1_func1		= iface1_ver1_func1,
-	.iface1_func2		= iface1_ver1_func2,
-	.iface1_func3		= iface1_ver1_func3,
-};
-
-struct plugin_iface iface1[2]= {
-	/*
-	 * Version 0
-	 */
-	{
-		.name			= "B_iface1",
-		.version		= 0,
-		.versions_replace	= 0,
-		.versions_replace_count	= 0,
-		.dependencies		= 0,
-		.dependency_count	= 0,
-		.constructor		= iface1_constructor,
-		.destructor		= iface1_destructor,
-		.interfaces		= NULL
-	},
-	/*
-	 * Version 1
-	 */
-	{
-		.name			= "B_iface1",
-		.version		= 1,
-		.versions_replace	= 0,
-		.versions_replace_count	= 0,
-		.dependencies		= 0,
-		.dependency_count	= 0,
-		.constructor		= iface1_ver1_constructor,
-		.destructor		= iface1_ver1_destructor,
-		.interfaces		= NULL
-	}
-};
-
-struct plugin_comp test_comp = {
-	.iface_count 		= 2,
-	.ifaces 		= iface1
-};
-
-static int iface1_constructor (void *context)
-{
-	printf ("B - version 0 constructor context %p\n", context);
-	return (0);
-}
-
-static void iface1_destructor (void *context)
-{
-	printf ("B - version 0 destructor context %p\n", context);
-}
-
-static void iface1_func1 (void) {
-	printf ("B - version 0 func1\n");
-}
-
-static void iface1_func2 (void) {
-	printf ("B - version 0 func2\n");
-}
-
-static void iface1_func3 (void) {
-	printf ("B - version 0 func3\n");
-}
-
-static int iface1_ver1_constructor (void *context)
-{
-	printf ("B - version 1 constructor context %p\n", context);
-	return (0);
-}
-
-static void iface1_ver1_destructor (void *context)
-{
-	printf ("B - version 1 destructor context %p\n", context);
-}
-
-static void iface1_ver1_func1 (void) {
-	printf ("B - version 1 func1\n");
-}
-
-static void iface1_ver1_func2 (void) {
-	printf ("B - version 1 func2\n");
-}
-
-static void iface1_ver1_func3 (void) {
-	printf ("B - version 1 func3\n");
-}
-
-__attribute__ ((constructor)) static void register_this_component (void)
-{
-        plugin_interfaces_set (&iface1[0], &iface_list);
-        plugin_interfaces_set (&iface1[1], &iface_ver1_list);
-
-	plugin_component_register (&test_comp);
-}
diff --git a/lib/plugin/plugin_loader.c b/lib/plugin/plugin_loader.c
deleted file mode 100644
index 121023c..0000000
--- a/lib/plugin/plugin_loader.c
+++ /dev/null
@@ -1,566 +0,0 @@
-/*
- * Copyright (C) 2006 Steven Dake (sdake@redhat.com)
- *
- * This software licensed under BSD license, the text of which follows:
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * - Redistributions of source code must retain the above copyright notice,
- *   this list of conditions and the following disclaimer.
- * - 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.
- * - Neither the name of the MontaVista Software, Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
- */
-
-#include <config.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <dlfcn.h>
-#include <dirent.h>
-#include <errno.h>
-#include <string.h>
-#include <unistd.h>
-#include <fnmatch.h>
-#ifdef QB_SOLARIS
-#include <iso/limits_iso.h>
-#endif
-#include <qb/qbhdb.h>
-#include <qb/qbplugin_comp.h>
-#include <qb/qbplugin.h>
-
-struct plugin_component_instance {
-	struct plugin_iface *ifaces;
-	int iface_count;
-	qb_hdb_handle_t comp_handle;
-	void *dl_handle;
-	int refcount;
-	char library_name[256];
-};
-
-struct plugin_iface_instance {
-	qb_hdb_handle_t component_handle;
-	void *context;
-	void (*destructor) (void *context);
-};
-
-DECLARE_HDB_DATABASE (plugin_component_instance_database, NULL);
-
-DECLARE_HDB_DATABASE (plugin_iface_instance_database, NULL);
-
-/*
-static struct hdb_handle_database plugin_component_instance_database = {
-	.handle_count	= 0,
-	.handles	= 0,
-	.iterator	= 0
-};
-
-static struct hdb_handle_database plugin_iface_instance_database = {
-	.handle_count	= 0,
-	.handles	= 0,
-	.iterator	= 0
-};
-*/
-
-static qb_hdb_handle_t g_component_handle = 0xFFFFFFFF;
-
-#if defined(QB_LINUX) || defined(QB_SOLARIS)
-static int plugin_select_so (const struct dirent *dirent)
-#else
-static int plugin_select_so (struct dirent *dirent)
-#endif
-{
-	unsigned int len;
-
-	len = strlen (dirent->d_name);
-
-	if (len > 6) {
-		if (strcmp (".pluginso", dirent->d_name + len - 6) == 0) {
-			return (1);
-		}
-	}
-	return (0);
-}
-
-#if defined(QB_LINUX) || defined(QB_SOLARIS)
-static int pathlist_select (const struct dirent *dirent)
-#else
-static int pathlist_select (struct dirent *dirent)
-#endif
-{
-	if (fnmatch ("*.conf", dirent->d_name, 0) == 0) {
-		return (1);
-	}
-
-	return (0);
-}
-
-static inline struct plugin_component_instance *plugin_comp_find (
-	const char *iface_name,
-	unsigned int version,
-	unsigned int *iface_number)
-{
-	struct plugin_component_instance *instance;
-	void *instance_p = NULL;
-	qb_hdb_handle_t component_handle = 0;
-	int i;
-
-	/*
-	 * Try to find interface in already loaded component
-	 */
-	qb_hdb_iterator_reset (&plugin_component_instance_database);
-	while (qb_hdb_iterator_next (&plugin_component_instance_database,
-		&instance_p, &component_handle) == 0) {
-
-		instance = (struct plugin_component_instance *)instance_p;
-
-		for (i = 0; i < instance->iface_count; i++) {
-			if ((strcmp (instance->ifaces[i].name, iface_name) == 0) &&
-				instance->ifaces[i].version == version) {
-
-				*iface_number = i;
-				return (instance);
-			}
-		}
-		qb_hdb_handle_put (&plugin_component_instance_database, component_handle);
-	}
-
-	return (NULL);
-}
-
-static inline int plugin_lib_loaded (
-	char *library_name)
-{
-	struct plugin_component_instance *instance;
-	void *instance_p = NULL;
-	qb_hdb_handle_t component_handle = 0;
-
-	/*
-	 * Try to find interface in already loaded component
-	 */
-	qb_hdb_iterator_reset (&plugin_component_instance_database);
-	while (qb_hdb_iterator_next (&plugin_component_instance_database,
-		(void *)&instance_p, &component_handle) == 0) {
-
-		instance = (struct plugin_component_instance *)instance_p;
-
-		if (strcmp (instance->library_name, library_name) == 0) {
-			return (1);
-		}
-
-		qb_hdb_handle_put (&plugin_component_instance_database, component_handle);
-	}
-
-	return (0);
-}
-
-enum { PATH_LIST_SIZE = 128 };
-const char *path_list[PATH_LIST_SIZE];
-unsigned int path_list_entries = 0;
-
-static void defaults_path_build (void)
-{
-	char cwd[1024];
-	char *res;
-
-	res = getcwd (cwd, sizeof (cwd));
-	if (res != NULL && (path_list[0] = strdup (cwd)) != NULL) {
-		path_list_entries++;
-	}
-
-	path_list[path_list_entries++] = PLUGINSODIR;
-}
-
-static void ld_library_path_build (void)
-{
-	char *ld_library_path;
-	char *my_ld_library_path;
-	char *p_s, *ptrptr;
-
-	ld_library_path = getenv ("LD_LIBRARY_PATH");
-	if (ld_library_path == NULL) {
-		return;
-	}
-	my_ld_library_path = strdup (ld_library_path);
-	if (my_ld_library_path == NULL) {
-		return;
-	}
-
-	p_s = strtok_r (my_ld_library_path, ":", &ptrptr);
-	while (p_s != NULL) {
-		char *p = strdup (p_s);
-		if (p && path_list_entries < PATH_LIST_SIZE) {
-			path_list[path_list_entries++] = p;
-		}
-		p_s = strtok_r (NULL, ":", &ptrptr);
-	}
-
-	free (my_ld_library_path);
-}
-
-static int ldso_path_build (const char *path, const char *filename)
-{
-	FILE *fp;
-	char string[1024];
-	char filename_cat[1024];
-	char newpath[1024];
-	char *newpath_tmp;
-	char *new_filename;
-	int j;
-	struct dirent **scandir_list;
-	unsigned int scandir_entries;
-
-	snprintf (filename_cat, sizeof(filename_cat), "%s/%s", path, filename);
-	if (filename[0] == '*') {
-		scandir_entries = scandir (
-			path,
-			&scandir_list,
-			pathlist_select, alphasort);
-		if (scandir_entries == 0) {
-			return 0;
-		} else if (scandir_entries == -1) {
-			return -1;
-		} else {
-			for (j = 0; j < scandir_entries; j++) {
-				ldso_path_build (path, scandir_list[j]->d_name);
-			}
-		}
-	}
-
-	fp = fopen (filename_cat, "r");
-	if (fp == NULL) {
-		return (-1);
-	}
-
-	while (fgets (string, sizeof (string), fp)) {
-		char *p;
-		if (strlen(string) > 0)
-			string[strlen(string) - 1] = '\0';
-		if (strncmp (string, "include", strlen ("include")) == 0) {
-			newpath_tmp = string + strlen ("include") + 1;
-			for (j = strlen (string);
-				string[j] != ' ' &&
-					string[j] != '/' &&
-					j > 0;
-				j--) {
-			}
-			string[j] = '\0';
-			new_filename = &string[j] + 1;
-			strcpy (newpath, path);
-			strcat (newpath, "/");
-			strcat (newpath, newpath_tmp);
-			ldso_path_build (newpath, new_filename);
-			continue;
-		}
-		p = strdup (string);
-		if (p && path_list_entries < PATH_LIST_SIZE) {
-			path_list[path_list_entries++] = p;
-		}
-	}
-	fclose(fp);
-	return (0);
-}
-
-#if defined (QB_SOLARIS) && !defined(HAVE_SCANDIR)
-static int scandir (
-	const char *dir, struct dirent ***namelist,
-	int (*filter)(const struct dirent *),
-	int (*compar)(const struct dirent **, const struct dirent **))
-{
-	DIR *d;
-	struct dirent *entry;
-	struct dirent *result;
-	struct dirent **names = NULL;
-	int namelist_items = 0, namelist_size = 0;
-	size_t len;
-	int return_code;
-
-	d = opendir(dir);
-	if (d == NULL)
-		return -1;
-
-	names = NULL;
-
-	len = offsetof(struct dirent, d_name) +
-                     pathconf(dir, _PC_NAME_MAX) + 1;
-	entry = malloc(len);
-
-	for (return_code = readdir_r (d, entry, &result);
-		dirent != NULL && return_code == 0;
-		return_code = readdir_r(d, entry, &result)) {
-
-		struct dirent *tmpentry;
-		if ((filter != NULL) && ((*filter)(result) == 0)) {
-			continue;
-		}
-		if (namelist_items >= namelist_size) {
-			struct dirent **tmp;
-			namelist_size += 512;
-			if ((unsigned long)namelist_size > INT_MAX) {
-				errno = EOVERFLOW;
-				goto fail;
-			}
-			tmp = realloc (names,
-				namelist_size * sizeof(struct dirent *));
-			if (tmp == NULL) {
-				goto fail;
-			}
-			names = tmp;
-		}
-		tmpentry = malloc (result->d_reclen);
-		if (tmpentry == NULL) {
-			goto fail;
-		}
-		(void) memcpy (tmpentry, result, result->d_reclen);
-		names[namelist_items++] = tmpentry;
-	}
-	(void) closedir (d);
-	if ((namelist_items > 1) && (compar != NULL)) {
-		qsort (names, namelist_items, sizeof (struct dirent *),
-			(int (*)(const void *, const void *))compar);
-	}
-
-	*namelist = names;
-
-	return namelist_items;
-
-fail:
-	{
-	int err = errno;
-	(void) closedir (d);
-	while (namelist_items != 0) {
-		namelist_items--;
-		free (*namelist[namelist_items]);
-	}
-	free (entry);
-	free (names);
-	*namelist = NULL;
-	errno = err;
-	return -1;
-	}
-}
-#endif
-
-#if defined (QB_SOLARIS) && !defined(HAVE_ALPHASORT)
-static int alphasort (const struct dirent **a, const struct dirent **b)
-{
-	return strcmp ((*a)->d_name, (*b)->d_name);
-}
-#endif
-
-static int interface_find_and_load (
-	const char *path,
-	const char *iface_name,
-	int version,
-	struct plugin_component_instance **instance_ret,
-	unsigned int *iface_number)
-{
-	struct plugin_component_instance *instance;
-	void *dl_handle;
-	struct dirent **scandir_list;
-	int scandir_entries;
-	unsigned int libs_to_scan;
-	char dl_name[1024];
-#ifdef QB_SOLARIS
-	void (*comp_reg)(void);
-#endif
-
-	scandir_entries = scandir (path,  &scandir_list, plugin_select_so, alphasort);
-	if (scandir_entries > 0)
-	/*
-	 * no error so load the object
-	 */
-	for (libs_to_scan = 0; libs_to_scan < scandir_entries; libs_to_scan++) {
-		/*
-		 * Load objects, scan them, unload them if they are not a match
-		 */
-		snprintf (dl_name, sizeof(dl_name), "%s/%s",
-			path, scandir_list[libs_to_scan]->d_name);
-		/*
-	 	 * Don't reload already loaded libraries
-		 */
-		if (plugin_lib_loaded (dl_name)) {
-			continue;
-		}
-		dl_handle = dlopen (dl_name, RTLD_NOW);
-		if (dl_handle == NULL) {
-			fprintf(stderr, "%s: open failed: %s\n",
-				dl_name, dlerror());
-			continue;
-		}
-/*
- * constructors don't work in Solaris dlopen, so we have to specifically call
- * a function to register the component
- */
-#ifdef QB_SOLARIS
-		comp_reg = dlsym (dl_handle, "corosync_plugin_component_register");
-		comp_reg ();
-#endif
-		instance = plugin_comp_find (iface_name, version, iface_number);
-		if (instance) {
-			instance->dl_handle = dl_handle;
-			strcpy (instance->library_name, dl_name);
-			goto found;
-		}
-
-		/*
-		* No matching interfaces found, try next shared object
-		*/
-		if (g_component_handle != 0xFFFFFFFF) {
-			qb_hdb_handle_destroy (&plugin_component_instance_database,
-				g_component_handle);
-			g_component_handle = 0xFFFFFFFF;
-		}
-		dlclose (dl_handle);
-	} /* scanning for pluginso loop */
-
-
-	if (scandir_entries > 0) {
-		int i;
-		for (i = 0; i < scandir_entries; i++) {
-			free (scandir_list[i]);
-		}
-		free (scandir_list);
-	}
-	g_component_handle = 0xFFFFFFFF;
-	return -1;
-
-found:
-	*instance_ret = instance;
-	if (scandir_entries > 0) {
-		int i;
-		for (i = 0; i < scandir_entries; i++) {
-			free (scandir_list[i]);
-		}
-		free (scandir_list);
-	}
-	g_component_handle = 0xFFFFFFFF;
-	return 0;
-}
-
-static unsigned int plugin_initialized = 0;
-
-int plugin_ifact_reference (
-	qb_hdb_handle_t *iface_handle,
-	const char *iface_name,
-	int version,
-	void **iface,
-	void *context)
-{
-	struct plugin_iface_instance *iface_instance;
-	struct plugin_component_instance *instance;
-	unsigned int iface_number;
-	unsigned int res;
-	unsigned int i;
-
-	/*
-	 * Determine if the component is already loaded
-	 */
-	instance = plugin_comp_find (iface_name, version, &iface_number);
-	if (instance) {
-		goto found;
-	}
-
-	if (plugin_initialized == 0) {
-		plugin_initialized = 1;
-		defaults_path_build ();
-		ld_library_path_build ();
-		ldso_path_build ("/etc", "ld.so.conf");
-	}
-
-// TODO error checking in this code is weak
-	/*
-	 * Search through all pluginso files for desired interface
-	 */
-	for (i = 0; i < path_list_entries; i++) {
-		res = interface_find_and_load (
-			path_list[i],
-			iface_name,
-			version,
-			&instance,
-			&iface_number);
-
-		if (res == 0) {
-			goto found;
-		}
-	}
-
-	/*
-	 * No matching interfaces found in all shared objects
-	 */
-	return (-1);
-
-found:
-	*iface = instance->ifaces[iface_number].interfaces;
-	if (instance->ifaces[iface_number].constructor) {
-		instance->ifaces[iface_number].constructor (context);
-	}
-	qb_hdb_handle_create (&plugin_iface_instance_database,
-		sizeof (struct plugin_iface_instance),
-		iface_handle);
-	qb_hdb_handle_get (&plugin_iface_instance_database,
-		*iface_handle, (void *)&iface_instance);
-	iface_instance->component_handle = instance->comp_handle;
-	iface_instance->context = context;
-	iface_instance->destructor = instance->ifaces[iface_number].destructor;
-	qb_hdb_handle_put (&plugin_iface_instance_database, *iface_handle);
-	return (0);
-}
-
-int plugin_ifact_release (qb_hdb_handle_t handle)
-{
-	struct plugin_iface_instance *iface_instance;
-	int res = 0;
-
-	res = qb_hdb_handle_get (&plugin_iface_instance_database,
-		handle, (void *)&iface_instance);
-
-	if (iface_instance->destructor) {
-		iface_instance->destructor (iface_instance->context);
-	}
-
-	qb_hdb_handle_put (&plugin_component_instance_database,
-		iface_instance->component_handle);
-	qb_hdb_handle_put (&plugin_iface_instance_database, handle);
-	qb_hdb_handle_destroy (&plugin_iface_instance_database, handle);
-
-	return (res);
-}
-
-void plugin_component_register (struct plugin_comp *comp)
-{
-	struct plugin_component_instance *instance;
-	static qb_hdb_handle_t comp_handle;
-
-	qb_hdb_handle_create (&plugin_component_instance_database,
-		sizeof (struct plugin_component_instance),
-		&comp_handle);
-	qb_hdb_handle_get (&plugin_component_instance_database,
-		comp_handle, (void *)&instance);
-
-	instance->ifaces = comp->ifaces;
-	instance->iface_count = comp->iface_count;
-	instance->comp_handle = comp_handle;
-	instance->dl_handle = NULL;
-
-	qb_hdb_handle_put (&plugin_component_instance_database,
-		comp_handle);
-
-	g_component_handle = comp_handle;
-}
diff --git a/lib/plugin/test.c b/lib/plugin/test.c
deleted file mode 100644
index ca5e011..0000000
--- a/lib/plugin/test.c
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Copyright (C) 2006 Steven Dake (sdake@redhat.com)
- *
- * This software licensed under BSD license, the text of which follows:
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * - Redistributions of source code must retain the above copyright notice,
- *   this list of conditions and the following disclaimer.
- * - 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.
- * - Neither the name of the MontaVista Software, Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
- */
-
-#include <config.h>
-
-#include <assert.h>
-#include <unistd.h>
-#include <qb/qbhdb.h>
-#include <qb/qbplugin.h>
-
-struct iface {
-	void (*func1) (void);
-	void (*func2) (void);
-	void (*func3) (void);
-};
-
-int main (void) {
-	qb_hdb_handle_t a_ifact_handle_ver0;
-	qb_hdb_handle_t b_ifact_handle_ver0;
-	struct iface *a_iface_ver0;
-	struct iface *a_iface_ver1;
-	void *a_iface_ver0_p;
-	void *a_iface_ver1_p;
-
-	qb_hdb_handle_t a_ifact_handle_ver1;
-	qb_hdb_handle_t b_ifact_handle_ver1;
-	struct iface *b_iface_ver0;
-	struct iface *b_iface_ver1;
-	void *b_iface_ver0_p;
-	void *b_iface_ver1_p;
-
-	unsigned int res;
-
-	/*
-	 * Reference version 0 and 1 of A and B interfaces
-	 */
-	res = plugin_ifact_reference (
-		&a_ifact_handle_ver0,
-		"A_iface1",
-		0, /* version 0 */
-		&a_iface_ver0_p,
-		(void *)0xaaaa0000);
-	assert (res == 0);
-
-	a_iface_ver0 = (struct iface *)a_iface_ver0_p;
-
-	res = plugin_ifact_reference (
-		&b_ifact_handle_ver0,
-		"B_iface1",
-		0, /* version 0 */
-		&b_iface_ver0_p,
-		(void *)0xbbbb0000);
-	assert (res == 0);
-
-	b_iface_ver0 = (struct iface *)b_iface_ver0_p;
-
-	res = plugin_ifact_reference (
-		&a_ifact_handle_ver1,
-		"A_iface1",
-		1, /* version 1 */
-		&a_iface_ver1_p,
-		(void *)0xaaaa1111);
-	assert (res == 0);
-
-	a_iface_ver1 = (struct iface *)a_iface_ver1_p;
-
-	res = plugin_ifact_reference (
-		&b_ifact_handle_ver1,
-		"B_iface1",
-		1, /* version 1 */
-		&b_iface_ver1_p,
-		(void *)0xbbbb1111);
-	assert (res == 0);
-
-	b_iface_ver1 = (struct iface *)b_iface_ver1_p;
-
-	a_iface_ver0->func1();
-	a_iface_ver0->func2();
-	a_iface_ver0->func3();
-
-	plugin_ifact_release (a_ifact_handle_ver0);
-
-	a_iface_ver1->func1();
-	a_iface_ver1->func2();
-	a_iface_ver1->func3();
-
-	plugin_ifact_release (a_ifact_handle_ver1);
-
-	b_iface_ver0->func1();
-	b_iface_ver0->func2();
-	b_iface_ver0->func3();
-
-	plugin_ifact_release (b_ifact_handle_ver0);
-
-	b_iface_ver1->func1();
-	b_iface_ver1->func2();
-	b_iface_ver1->func3();
-
-	plugin_ifact_release (b_ifact_handle_ver1);
-
-	return (0);
-}
diff --git a/lib/plugin/uic.c b/lib/plugin/uic.c
deleted file mode 100755
index 9e2688e..0000000
--- a/lib/plugin/uic.c
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Copyright (c) 2006 Steven Dake (sdake@redhat.com)
- *
- * This software licensed under BSD license, the text of which follows:
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * - Redistributions of source code must retain the above copyright notice,
- *   this list of conditions and the following disclaimer.
- * - 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.
- * - Neither the name of the MontaVista Software, Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
- */
-
-#include <config.h>
-
-#include <sys/uio.h>
-#include <sys/mman.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <sys/time.h>
-#include <sys/resource.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <errno.h>
-#include <sched.h>
-#include <time.h>
-#include <pthread.h>
-#include <sys/poll.h>
-#include <string.h>
-
-#if defined(COROSYNC_LINUX) || defined(COROSYNC_SOLARIS)
-/* SUN_LEN is broken for abstract namespace
- */
-#define AIS_SUN_LEN(a) sizeof(*(a))
-#else
-#define AIS_SUN_LEN(a) SUN_LEN(a)
-#endif
-
-#ifdef COROSYNC_LINUX
-static const char *socketname = "lcr.socket";
-#else
-static const char *socketname = SOCKETDIR "/lcr.socket";
-#endif
-
-static int uic_connect (int *fd);
-
-static int uic_msg_send (int fd, void *msg);
-
-int uic_connect (int *fd)
-{
-	int res;
-	struct sockaddr_un addr;
-
-	memset (&addr, 0, sizeof (struct sockaddr_un));
-#if defined(COROSYNC_BSD) || defined(COROSYNC_DARWIN)
-	addr.sun_len = sizeof(struct sockaddr_un);
-#endif
-	addr.sun_family = PF_UNIX;
-#if defined(COROSYNC_LINUX)
-	strcpy (addr.sun_path + 1, socketname);
-#else
-	strcpy (addr.sun_path, socketname);
-#endif
-	*fd = socket (PF_UNIX, SOCK_STREAM, 0);
-	if (*fd == -1) {
-		return -errno;
-	}
-	res = connect (*fd, (struct sockaddr *)&addr, AIS_SUN_LEN(&addr));
-	if (res == -1) {
-		return -errno;
-	}
-	return 0;
-}
-
-struct uic_req_msg {
-	int len;
-	char msg[0];
-};
-
-static int uic_msg_send (int fd, void *msg)
-{
-	struct msghdr msg_send;
-	struct iovec iov_send[2];
-	struct uic_req_msg req_msg;
-	ssize_t send_res;
-	int res;
-
-	req_msg.len = strlen (msg) + 1;
-	iov_send[0].iov_base = (void *)&req_msg;
-	iov_send[0].iov_len = sizeof (struct uic_req_msg);
-	iov_send[1].iov_base = msg;
-	iov_send[1].iov_len = req_msg.len;
-
-	msg_send.msg_iov = iov_send;
-	msg_send.msg_iovlen = 2;
-	msg_send.msg_name = 0;
-	msg_send.msg_namelen = 0;
-#ifndef COROSYNC_SOLARIS
-	msg_send.msg_control = 0;
-	msg_send.msg_controllen = 0;
-	msg_send.msg_flags = 0;
-#else
-	msg_send.msg_accrights = NULL;
-	msg_send.msg_accrightslen = 0;
-#endif
-
-	retry_send:
-	send_res = sendmsg (fd, &msg_send, 0);
-	if (send_res == -1 && errno == EINTR) {
-                goto retry_send;
-        }
-	if (send_res == -1) {
-		res = -errno;
-	} else {
-		res = (int)send_res;
-	}
-	return (res);
-
-}
-
-
-int main (void)
-{
-	int client_fd;
-	int res;
-	char command[128] = "livereplace ckpt version2";
-
-	res = uic_connect (&client_fd);
-	if (res != 0) {
-		printf ("Couldn't connect to live replacement service\n");
-	}
-	uic_msg_send (client_fd, (void *)command);
-
-	return 0;
-}
diff --git a/lib/plugin/uis.c b/lib/plugin/uis.c
deleted file mode 100755
index 004c464..0000000
--- a/lib/plugin/uis.c
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * Copyright (c) 2006 Steven Dake (sdake@redhat.com)
- *
- * This software licensed under BSD license, the text of which follows:
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * - Redistributions of source code must retain the above copyright notice,
- *   this list of conditions and the following disclaimer.
- * - 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.
- * - Neither the name of the MontaVista Software, Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
- */
-
-#include <config.h>
-
-#include <sys/uio.h>
-#include <sys/mman.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <sys/time.h>
-#include <sys/resource.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <errno.h>
-#include <sched.h>
-#include <time.h>
-#include <pthread.h>
-#include <sys/poll.h>
-#include <string.h>
-
-#define SERVER_BACKLOG 5
-
-#if defined(COROSYNC_LINUX) || defined(COROSYNC_SOLARIS)
-/* SUN_LEN is broken for abstract namespace
- */
-#define AIS_SUN_LEN(a) sizeof(*(a))
-#else
-#define AIS_SUN_LEN(a) SUN_LEN(a)
-#endif
-
-#ifdef COROSYNC_LINUX
-static const char *socketname = "lcr.socket";
-#else
-static const char *socketname = SOCKETDIR "/lcr.socket";
-#endif
-
-static void uis_lcr_bind (int *server_fd)
-{
-	int fd;
-	struct sockaddr_un un_addr;
-	int res;
-
-	/*
-	 * Create socket for lcr clients, name socket, listen for connections
-	 */
-	fd = socket (PF_UNIX, SOCK_STREAM, 0);
-	if (fd == -1) {
-		printf ("lcr_bind failed\n");
-	};
-
-#if !defined(COROSYNC_LINUX)
-	unlink(socketname);
-#endif
-	memset (&un_addr, 0, sizeof (struct sockaddr_un));
-#if defined(COROSYNC_BSD) || defined(COROSYNC_DARWIN)
-	un_addr.sun_len = sizeof(struct sockaddr_un);
-#endif
-	un_addr.sun_family = AF_UNIX;
-#if defined(COROSYNC_LINUX)
-	strcpy (un_addr.sun_path + 1, socketname);
-#else
-	strcpy (un_addr.sun_path, socketname);
-#endif
-
-	res = bind (fd, (struct sockaddr *)&un_addr, AIS_SUN_LEN(&un_addr));
-	if (res) {
-		char error_str[100];
-		strerror_r (errno, error_str, 100);
-		printf ("Could not bind AF_UNIX: %s\n", error_str);
-	}
-	listen (fd, SERVER_BACKLOG);
-	*server_fd = fd;
-}
-
-struct uis_commands {
-	const char *command;
-	void (*cmd_handler) (char *);
-};
-
-static void cmd1 (char *cmd) {
-	printf ("cmd1 executed with cmd line %s\n", cmd);
-}
-
-struct uis_commands uis_commands[] = {
-	{
-		"cmd1", cmd1
-	}
-};
-
-struct uis_req_msg {
-        int len;
-        char msg[0];
-};
-
-static void lcr_uis_dispatch (int fd)
-{
-	struct uis_req_msg header;
-	char msg_contents[512];
-	ssize_t readsize;
-
-	/*
-	 * TODO this doesn't handle short reads
-	 */
-	readsize = read (fd, &header, sizeof (header));
-	if (readsize == -1) {
-		return;
-	}
-	readsize = read (fd, msg_contents, sizeof (msg_contents));
-	if (readsize == -1) {
-		return;
-	}
-
-	printf ("msg contents %s\n", msg_contents);
-}
-
-static void *lcr_uis_server (void *data)
-{
-	struct pollfd ufds[2];
-	struct sockaddr_un un_addr;
-	socklen_t addrlen;
-	int nfds = 1;
-#ifdef COROSYNC_LINUX
-	int on = 1;
-#endif
-
-	/*
-	 * Main acceptance and dispatch loop
-	 */
-	uis_lcr_bind (&ufds[0].fd);
-	printf ("UIS server thread started %d\n", ufds[0].fd);
-	ufds[0].events = POLLIN;
-	ufds[1].events = POLLOUT;
-	for (;;) {
-		int res = poll (ufds, nfds, -1);
-		if (res == 0 || (res < 0 && errno == EINTR))
-			continue;
-		if (res < 0)
-			return NULL;
-		if (nfds == 1 && ufds[0].revents & POLLIN) {
-			ufds[1].fd = accept (ufds[0].fd,
-				(struct sockaddr *)&un_addr, &addrlen);
-#ifdef COROSYNC_LINUX
-			setsockopt(ufds[1].fd, SOL_SOCKET, SO_PASSCRED,
-				&on, sizeof (on));
-#endif
-			nfds = 2;
-		}
-		if (ufds[0].revents & POLLIN) {
-			lcr_uis_dispatch (ufds[1].fd);
-		}
-	}
-}
-
-__attribute__ ((constructor)) static int lcr_uis_ctors (void)
-{
-	pthread_t thread;
-
-	pthread_create (&thread, NULL, lcr_uis_server, NULL);
-
-	return (0);
-}
diff --git a/lib/plugin_loader.c b/lib/plugin_loader.c
new file mode 100644
index 0000000..57ba204
--- /dev/null
+++ b/lib/plugin_loader.c
@@ -0,0 +1,567 @@
+/*
+ * Copyright (C) 2006 Steven Dake (sdake@redhat.com)
+ *
+ * This software licensed under BSD license, the text of which follows:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - 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.
+ * - Neither the name of the MontaVista Software, Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <dlfcn.h>
+#include <dirent.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <fnmatch.h>
+#ifdef QB_SOLARIS
+#include <iso/limits_iso.h>
+#endif
+#include <qb/qbhdb.h>
+#include <qb/qbplugin_comp.h>
+#include <qb/qbplugin.h>
+
+struct plugin_component_instance {
+	struct plugin_iface *ifaces;
+	int iface_count;
+	qb_hdb_handle_t comp_handle;
+	void *dl_handle;
+	int refcount;
+	char library_name[256];
+};
+
+struct plugin_iface_instance {
+	qb_hdb_handle_t component_handle;
+	void *context;
+	void (*destructor) (void *context);
+};
+
+DECLARE_HDB_DATABASE (plugin_component_instance_database, NULL);
+
+DECLARE_HDB_DATABASE (plugin_iface_instance_database, NULL);
+
+/*
+static struct hdb_handle_database plugin_component_instance_database = {
+	.handle_count	= 0,
+	.handles	= 0,
+	.iterator	= 0
+};
+
+static struct hdb_handle_database plugin_iface_instance_database = {
+	.handle_count	= 0,
+	.handles	= 0,
+	.iterator	= 0
+};
+*/
+
+static qb_hdb_handle_t g_component_handle = 0xFFFFFFFF;
+
+#if defined(QB_LINUX) || defined(QB_SOLARIS)
+static int plugin_select_so (const struct dirent *dirent)
+#else
+static int plugin_select_so (struct dirent *dirent)
+#endif
+{
+	unsigned int len;
+	/*
+	 * TODO check .lcrso > .so
+	 */
+	len = strlen (dirent->d_name);
+	if (len > 3) {
+		if (strcmp (".so", dirent->d_name + len - 3) == 0) {
+			return (1);
+		}
+	}
+	return (0);
+}
+
+#if defined(QB_LINUX) || defined(QB_SOLARIS)
+static int pathlist_select (const struct dirent *dirent)
+#else
+static int pathlist_select (struct dirent *dirent)
+#endif
+{
+	if (fnmatch ("*.conf", dirent->d_name, 0) == 0) {
+		return (1);
+	}
+
+	return (0);
+}
+
+static inline struct plugin_component_instance *plugin_comp_find (
+	const char *iface_name,
+	unsigned int version,
+	unsigned int *iface_number)
+{
+	struct plugin_component_instance *instance;
+	void *instance_p = NULL;
+	qb_hdb_handle_t component_handle = 0;
+	int i;
+
+	/*
+	 * Try to find interface in already loaded component
+	 */
+	qb_hdb_iterator_reset (&plugin_component_instance_database);
+	while (qb_hdb_iterator_next (&plugin_component_instance_database,
+		&instance_p, &component_handle) == 0) {
+
+		instance = (struct plugin_component_instance *)instance_p;
+
+		for (i = 0; i < instance->iface_count; i++) {
+			if ((strcmp (instance->ifaces[i].name, iface_name) == 0) &&
+				instance->ifaces[i].version == version) {
+
+				*iface_number = i;
+				return (instance);
+			}
+		}
+		qb_hdb_handle_put (&plugin_component_instance_database, component_handle);
+	}
+
+	return (NULL);
+}
+
+static inline int plugin_lib_loaded (
+	char *library_name)
+{
+	struct plugin_component_instance *instance;
+	void *instance_p = NULL;
+	qb_hdb_handle_t component_handle = 0;
+
+	/*
+	 * Try to find interface in already loaded component
+	 */
+	qb_hdb_iterator_reset (&plugin_component_instance_database);
+	while (qb_hdb_iterator_next (&plugin_component_instance_database,
+		(void *)&instance_p, &component_handle) == 0) {
+
+		instance = (struct plugin_component_instance *)instance_p;
+
+		if (strcmp (instance->library_name, library_name) == 0) {
+			return (1);
+		}
+
+		qb_hdb_handle_put (&plugin_component_instance_database, component_handle);
+	}
+
+	return (0);
+}
+
+enum { PATH_LIST_SIZE = 128 };
+const char *path_list[PATH_LIST_SIZE];
+unsigned int path_list_entries = 0;
+
+static void defaults_path_build (void)
+{
+	char cwd[1024];
+	char *res;
+
+	res = getcwd (cwd, sizeof (cwd));
+	if (res != NULL && (path_list[0] = strdup (cwd)) != NULL) {
+		path_list_entries++;
+	}
+
+	path_list[path_list_entries++] = PLUGINSODIR;
+}
+
+static void ld_library_path_build (void)
+{
+	char *ld_library_path;
+	char *my_ld_library_path;
+	char *p_s, *ptrptr;
+
+	ld_library_path = getenv ("LD_LIBRARY_PATH");
+	if (ld_library_path == NULL) {
+		return;
+	}
+	my_ld_library_path = strdup (ld_library_path);
+	if (my_ld_library_path == NULL) {
+		return;
+	}
+
+	p_s = strtok_r (my_ld_library_path, ":", &ptrptr);
+	while (p_s != NULL) {
+		char *p = strdup (p_s);
+		if (p && path_list_entries < PATH_LIST_SIZE) {
+			path_list[path_list_entries++] = p;
+		}
+		p_s = strtok_r (NULL, ":", &ptrptr);
+	}
+
+	free (my_ld_library_path);
+}
+
+static int ldso_path_build (const char *path, const char *filename)
+{
+	FILE *fp;
+	char string[1024];
+	char filename_cat[1024];
+	char newpath[1024];
+	char *newpath_tmp;
+	char *new_filename;
+	int j;
+	struct dirent **scandir_list;
+	unsigned int scandir_entries;
+
+	snprintf (filename_cat, sizeof(filename_cat), "%s/%s", path, filename);
+	if (filename[0] == '*') {
+		scandir_entries = scandir (
+			path,
+			&scandir_list,
+			pathlist_select, alphasort);
+		if (scandir_entries == 0) {
+			return 0;
+		} else if (scandir_entries == -1) {
+			return -1;
+		} else {
+			for (j = 0; j < scandir_entries; j++) {
+				ldso_path_build (path, scandir_list[j]->d_name);
+			}
+		}
+	}
+
+	fp = fopen (filename_cat, "r");
+	if (fp == NULL) {
+		return (-1);
+	}
+
+	while (fgets (string, sizeof (string), fp)) {
+		char *p;
+		if (strlen(string) > 0)
+			string[strlen(string) - 1] = '\0';
+		if (strncmp (string, "include", strlen ("include")) == 0) {
+			newpath_tmp = string + strlen ("include") + 1;
+			for (j = strlen (string);
+				string[j] != ' ' &&
+					string[j] != '/' &&
+					j > 0;
+				j--) {
+			}
+			string[j] = '\0';
+			new_filename = &string[j] + 1;
+			strcpy (newpath, path);
+			strcat (newpath, "/");
+			strcat (newpath, newpath_tmp);
+			ldso_path_build (newpath, new_filename);
+			continue;
+		}
+		p = strdup (string);
+		if (p && path_list_entries < PATH_LIST_SIZE) {
+			path_list[path_list_entries++] = p;
+		}
+	}
+	fclose(fp);
+	return (0);
+}
+
+#if defined (QB_SOLARIS) && !defined(HAVE_SCANDIR)
+static int scandir (
+	const char *dir, struct dirent ***namelist,
+	int (*filter)(const struct dirent *),
+	int (*compar)(const struct dirent **, const struct dirent **))
+{
+	DIR *d;
+	struct dirent *entry;
+	struct dirent *result;
+	struct dirent **names = NULL;
+	int namelist_items = 0, namelist_size = 0;
+	size_t len;
+	int return_code;
+
+	d = opendir(dir);
+	if (d == NULL)
+		return -1;
+
+	names = NULL;
+
+	len = offsetof(struct dirent, d_name) +
+                     pathconf(dir, _PC_NAME_MAX) + 1;
+	entry = malloc(len);
+
+	for (return_code = readdir_r (d, entry, &result);
+		dirent != NULL && return_code == 0;
+		return_code = readdir_r(d, entry, &result)) {
+
+		struct dirent *tmpentry;
+		if ((filter != NULL) && ((*filter)(result) == 0)) {
+			continue;
+		}
+		if (namelist_items >= namelist_size) {
+			struct dirent **tmp;
+			namelist_size += 512;
+			if ((unsigned long)namelist_size > INT_MAX) {
+				errno = EOVERFLOW;
+				goto fail;
+			}
+			tmp = realloc (names,
+				namelist_size * sizeof(struct dirent *));
+			if (tmp == NULL) {
+				goto fail;
+			}
+			names = tmp;
+		}
+		tmpentry = malloc (result->d_reclen);
+		if (tmpentry == NULL) {
+			goto fail;
+		}
+		(void) memcpy (tmpentry, result, result->d_reclen);
+		names[namelist_items++] = tmpentry;
+	}
+	(void) closedir (d);
+	if ((namelist_items > 1) && (compar != NULL)) {
+		qsort (names, namelist_items, sizeof (struct dirent *),
+			(int (*)(const void *, const void *))compar);
+	}
+
+	*namelist = names;
+
+	return namelist_items;
+
+fail:
+	{
+	int err = errno;
+	(void) closedir (d);
+	while (namelist_items != 0) {
+		namelist_items--;
+		free (*namelist[namelist_items]);
+	}
+	free (entry);
+	free (names);
+	*namelist = NULL;
+	errno = err;
+	return -1;
+	}
+}
+#endif
+
+#if defined (QB_SOLARIS) && !defined(HAVE_ALPHASORT)
+static int alphasort (const struct dirent **a, const struct dirent **b)
+{
+	return strcmp ((*a)->d_name, (*b)->d_name);
+}
+#endif
+
+static int interface_find_and_load (
+	const char *path,
+	const char *iface_name,
+	int version,
+	struct plugin_component_instance **instance_ret,
+	unsigned int *iface_number)
+{
+	struct plugin_component_instance *instance;
+	void *dl_handle;
+	struct dirent **scandir_list;
+	int scandir_entries;
+	unsigned int libs_to_scan;
+	char dl_name[1024];
+#ifdef QB_SOLARIS
+	void (*comp_reg)(void);
+#endif
+
+	scandir_entries = scandir (path,  &scandir_list, plugin_select_so, alphasort);
+	if (scandir_entries > 0)
+	/*
+	 * no error so load the object
+	 */
+	for (libs_to_scan = 0; libs_to_scan < scandir_entries; libs_to_scan++) {
+		/*
+		 * Load objects, scan them, unload them if they are not a match
+		 */
+		snprintf (dl_name, sizeof(dl_name), "%s/%s",
+			path, scandir_list[libs_to_scan]->d_name);
+		/*
+		 * Don't reload already loaded libraries
+		 */
+		if (plugin_lib_loaded (dl_name)) {
+			continue;
+		}
+		dl_handle = dlopen (dl_name, RTLD_NOW);
+		if (dl_handle == NULL) {
+			fprintf(stderr, "%s: open failed: %s\n",
+				dl_name, dlerror());
+			continue;
+		}
+/*
+ * constructors don't work in Solaris dlopen, so we have to specifically call
+ * a function to register the component
+ */
+#ifdef QB_SOLARIS
+		comp_reg = dlsym (dl_handle, "corosync_plugin_component_register");
+		comp_reg ();
+#endif
+		instance = plugin_comp_find (iface_name, version, iface_number);
+		if (instance) {
+			instance->dl_handle = dl_handle;
+			strcpy (instance->library_name, dl_name);
+			goto found;
+		}
+
+		/*
+		* No matching interfaces found, try next shared object
+		*/
+		if (g_component_handle != 0xFFFFFFFF) {
+			qb_hdb_handle_destroy (&plugin_component_instance_database,
+				g_component_handle);
+			g_component_handle = 0xFFFFFFFF;
+		}
+		dlclose (dl_handle);
+	} /* scanning for pluginso loop */
+
+
+	if (scandir_entries > 0) {
+		int i;
+		for (i = 0; i < scandir_entries; i++) {
+			free (scandir_list[i]);
+		}
+		free (scandir_list);
+	}
+	g_component_handle = 0xFFFFFFFF;
+	return -1;
+
+found:
+	*instance_ret = instance;
+	if (scandir_entries > 0) {
+		int i;
+		for (i = 0; i < scandir_entries; i++) {
+			free (scandir_list[i]);
+		}
+		free (scandir_list);
+	}
+	g_component_handle = 0xFFFFFFFF;
+	return 0;
+}
+
+static unsigned int plugin_initialized = 0;
+
+int plugin_ifact_reference (
+	qb_hdb_handle_t *iface_handle,
+	const char *iface_name,
+	int version,
+	void **iface,
+	void *context)
+{
+	struct plugin_iface_instance *iface_instance;
+	struct plugin_component_instance *instance;
+	unsigned int iface_number;
+	unsigned int res;
+	unsigned int i;
+
+	/*
+	 * Determine if the component is already loaded
+	 */
+	instance = plugin_comp_find (iface_name, version, &iface_number);
+	if (instance) {
+		goto found;
+	}
+
+	if (plugin_initialized == 0) {
+		plugin_initialized = 1;
+		defaults_path_build ();
+		ld_library_path_build ();
+		ldso_path_build ("/etc", "ld.so.conf");
+	}
+
+// TODO error checking in this code is weak
+	/*
+	 * Search through all pluginso files for desired interface
+	 */
+	for (i = 0; i < path_list_entries; i++) {
+		res = interface_find_and_load (
+			path_list[i],
+			iface_name,
+			version,
+			&instance,
+			&iface_number);
+
+		if (res == 0) {
+			goto found;
+		}
+	}
+
+	/*
+	 * No matching interfaces found in all shared objects
+	 */
+	return (-1);
+
+found:
+	*iface = instance->ifaces[iface_number].interfaces;
+	if (instance->ifaces[iface_number].constructor) {
+		instance->ifaces[iface_number].constructor (context);
+	}
+	qb_hdb_handle_create (&plugin_iface_instance_database,
+		sizeof (struct plugin_iface_instance),
+		iface_handle);
+	qb_hdb_handle_get (&plugin_iface_instance_database,
+		*iface_handle, (void *)&iface_instance);
+	iface_instance->component_handle = instance->comp_handle;
+	iface_instance->context = context;
+	iface_instance->destructor = instance->ifaces[iface_number].destructor;
+	qb_hdb_handle_put (&plugin_iface_instance_database, *iface_handle);
+	return (0);
+}
+
+int plugin_ifact_release (qb_hdb_handle_t handle)
+{
+	struct plugin_iface_instance *iface_instance;
+	int res = 0;
+
+	res = qb_hdb_handle_get (&plugin_iface_instance_database,
+		handle, (void *)&iface_instance);
+
+	if (iface_instance->destructor) {
+		iface_instance->destructor (iface_instance->context);
+	}
+
+	qb_hdb_handle_put (&plugin_component_instance_database,
+		iface_instance->component_handle);
+	qb_hdb_handle_put (&plugin_iface_instance_database, handle);
+	qb_hdb_handle_destroy (&plugin_iface_instance_database, handle);
+
+	return (res);
+}
+
+void plugin_component_register (struct plugin_comp *comp)
+{
+	struct plugin_component_instance *instance;
+	static qb_hdb_handle_t comp_handle;
+
+	qb_hdb_handle_create (&plugin_component_instance_database,
+		sizeof (struct plugin_component_instance),
+		&comp_handle);
+	qb_hdb_handle_get (&plugin_component_instance_database,
+		comp_handle, (void *)&instance);
+
+	instance->ifaces = comp->ifaces;
+	instance->iface_count = comp->iface_count;
+	instance->comp_handle = comp_handle;
+	instance->dl_handle = NULL;
+
+	qb_hdb_handle_put (&plugin_component_instance_database,
+		comp_handle);
+
+	g_component_handle = comp_handle;
+}
diff --git a/lib/poll.c b/lib/poll.c
new file mode 100644
index 0000000..be779da
--- /dev/null
+++ b/lib/poll.c
@@ -0,0 +1,441 @@
+/*
+ * Copyright (c) 2003-2004 MontaVista Software, Inc.
+ * Copyright (c) 2006-2010 Red Hat, Inc.
+ *
+ * All rights reserved.
+ *
+ * Author: Steven Dake (sdake@redhat.com)
+ *
+ * This software licensed under BSD license, the text of which follows:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - 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.
+ * - Neither the name of the MontaVista Software, Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
+ */
+
+#include <config.h>
+
+#include <errno.h>
+#include <pthread.h>
+#include <sys/poll.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#include <qb/qbhdb.h>
+#include <qb/qbpoll.h>
+#include <qb/qblist.h>
+#include "tlist.h"
+
+typedef int (*dispatch_fn_t) (qb_hdb_handle_t hdb_handle, int fd, int revents, void *data);
+
+struct qb_poll_entry {
+	struct pollfd ufd;
+	dispatch_fn_t dispatch_fn;
+	void *data;
+};
+
+struct qb_poll_instance {
+	struct qb_poll_entry *poll_entries;
+	struct pollfd *ufds;
+	int poll_entry_count;
+	struct timerlist timerlist;
+	int stop_requested;
+};
+
+DECLARE_HDB_DATABASE (poll_instance_database,NULL);
+
+qb_hdb_handle_t qb_poll_create (void)
+{
+	qb_hdb_handle_t handle;
+	struct qb_poll_instance *poll_instance;
+	unsigned int res;
+
+	res = qb_hdb_handle_create (&poll_instance_database,
+		sizeof (struct qb_poll_instance), &handle);
+	if (res != 0) {
+		goto error_exit;
+	}
+	res = qb_hdb_handle_get (&poll_instance_database, handle,
+		(void *)&poll_instance);
+	if (res != 0) {
+		goto error_destroy;
+	}
+
+	poll_instance->poll_entries = 0;
+	poll_instance->ufds = 0;
+	poll_instance->poll_entry_count = 0;
+	poll_instance->stop_requested = 0;
+	timerlist_init (&poll_instance->timerlist);
+
+	return (handle);
+
+error_destroy:
+	qb_hdb_handle_destroy (&poll_instance_database, handle);
+
+error_exit:
+	return (-1);
+}
+
+int qb_poll_destroy (qb_hdb_handle_t handle)
+{
+	struct qb_poll_instance *poll_instance;
+	int res = 0;
+
+	res = qb_hdb_handle_get (&poll_instance_database, handle,
+		(void *)&poll_instance);
+	if (res != 0) {
+		res = -ENOENT;
+		goto error_exit;
+	}
+
+	free (poll_instance->poll_entries);
+	free (poll_instance->ufds);
+
+	qb_hdb_handle_destroy (&poll_instance_database, handle);
+
+	qb_hdb_handle_put (&poll_instance_database, handle);
+
+error_exit:
+	return (res);
+}
+
+int qb_poll_dispatch_add (
+	qb_hdb_handle_t handle,
+	int fd,
+	int events,
+	void *data,
+	int (*dispatch_fn) (
+		qb_hdb_handle_t hdb_handle_t,
+		int fd,
+		int revents,
+		void *data))
+{
+	struct qb_poll_instance *poll_instance;
+	struct qb_poll_entry *poll_entries;
+	struct pollfd *ufds;
+	int found = 0;
+	int install_pos;
+	int res = 0;
+
+	res = qb_hdb_handle_get (&poll_instance_database, handle,
+		(void *)&poll_instance);
+	if (res != 0) {
+		res = -ENOENT;
+		goto error_exit;
+	}
+
+	for (found = 0, install_pos = 0; install_pos < poll_instance->poll_entry_count; install_pos++) {
+		if (poll_instance->poll_entries[install_pos].ufd.fd == -1) {
+			found = 1;
+			break;
+		}
+	}
+
+	if (found == 0) {
+		/*
+		 * Grow pollfd list
+		 */
+		poll_entries = (struct qb_poll_entry *)realloc (poll_instance->poll_entries,
+			(poll_instance->poll_entry_count + 1) *
+			sizeof (struct qb_poll_entry));
+		if (poll_entries == NULL) {
+			res = -ENOMEM;
+			goto error_put;
+		}
+		poll_instance->poll_entries = poll_entries;
+
+		ufds = (struct pollfd *)realloc (poll_instance->ufds,
+			(poll_instance->poll_entry_count + 1) *
+			sizeof (struct pollfd));
+		if (ufds == NULL) {
+			res = -ENOMEM;
+			goto error_put;
+		}
+		poll_instance->ufds = ufds;
+
+		poll_instance->poll_entry_count += 1;
+		install_pos = poll_instance->poll_entry_count - 1;
+	}
+
+	/*
+	 * Install new dispatch handler
+	 */
+	poll_instance->poll_entries[install_pos].ufd.fd = fd;
+	poll_instance->poll_entries[install_pos].ufd.events = events;
+	poll_instance->poll_entries[install_pos].ufd.revents = 0;
+	poll_instance->poll_entries[install_pos].dispatch_fn = dispatch_fn;
+	poll_instance->poll_entries[install_pos].data = data;
+
+error_put:
+	qb_hdb_handle_put (&poll_instance_database, handle);
+
+error_exit:
+	return (res);
+}
+
+int qb_poll_dispatch_modify (
+	qb_hdb_handle_t handle,
+	int fd,
+	int events,
+	int (*dispatch_fn) (
+		qb_hdb_handle_t hdb_handle_t,
+		int fd,
+		int revents,
+		void *data))
+{
+	struct qb_poll_instance *poll_instance;
+	int i;
+	int res = 0;
+
+	res = qb_hdb_handle_get (&poll_instance_database, handle,
+		(void *)&poll_instance);
+	if (res != 0) {
+		res = -ENOENT;
+		goto error_exit;
+	}
+
+	/*
+	 * Find file descriptor to modify events and dispatch function
+	 */
+	for (i = 0; i < poll_instance->poll_entry_count; i++) {
+		if (poll_instance->poll_entries[i].ufd.fd == fd) {
+			poll_instance->poll_entries[i].ufd.events = events;
+			poll_instance->poll_entries[i].dispatch_fn = dispatch_fn;
+
+			goto error_put;
+		}
+	}
+
+	res = -EBADF;
+
+error_put:
+	qb_hdb_handle_put (&poll_instance_database, handle);
+
+error_exit:
+	return (res);
+}
+
+int qb_poll_dispatch_delete (
+	qb_hdb_handle_t handle,
+	int fd)
+{
+	struct qb_poll_instance *poll_instance;
+	int i;
+	int res = 0;
+
+	res = qb_hdb_handle_get (&poll_instance_database, handle,
+		(void *)&poll_instance);
+	if (res != 0) {
+		res = -ENOENT;
+		goto error_exit;
+	}
+
+	/*
+	 * Find dispatch fd to delete
+	 */
+	res = -EBADF;
+	for (i = 0; i < poll_instance->poll_entry_count; i++) {
+		if (poll_instance->poll_entries[i].ufd.fd == fd) {
+			poll_instance->ufds[i].fd = -1;
+			poll_instance->poll_entries[i].ufd.fd = -1;
+			poll_instance->poll_entries[i].ufd.revents = 0;
+
+			res = 0;
+			break;
+		}
+	}
+
+
+	qb_hdb_handle_put (&poll_instance_database, handle);
+
+error_exit:
+	return (res);
+}
+
+int qb_poll_timer_add (
+	qb_hdb_handle_t handle,
+	int msec_duration, void *data,
+	void (*timer_fn) (void *data),
+	qb_poll_timer_handle *timer_handle_out)
+{
+	struct qb_poll_instance *poll_instance;
+	int res = 0;
+
+	if (timer_handle_out == NULL) {
+		res = -ENOENT;
+		goto error_exit;
+	}
+
+	res = qb_hdb_handle_get (&poll_instance_database, handle,
+		(void *)&poll_instance);
+	if (res != 0) {
+		res = -ENOENT;
+		goto error_exit;
+	}
+
+	timerlist_add_duration (&poll_instance->timerlist,
+		timer_fn, data, ((unsigned long long)msec_duration) * 1000000ULL, timer_handle_out);
+
+	qb_hdb_handle_put (&poll_instance_database, handle);
+error_exit:
+	return (res);
+}
+
+int qb_poll_timer_delete (
+	qb_hdb_handle_t handle,
+	qb_poll_timer_handle th)
+{
+	struct qb_poll_instance *poll_instance;
+	int res = 0;
+
+	if (th == 0) {
+		return (0);
+	}
+	res = qb_hdb_handle_get (&poll_instance_database, handle,
+		(void *)&poll_instance);
+	if (res != 0) {
+		res = -ENOENT;
+		goto error_exit;
+	}
+
+	timerlist_del (&poll_instance->timerlist, (void *)th);
+
+	qb_hdb_handle_put (&poll_instance_database, handle);
+
+error_exit:
+	return (res);
+}
+
+int qb_poll_stop (
+	qb_hdb_handle_t handle)
+{
+	struct qb_poll_instance *poll_instance;
+	unsigned int res;
+
+	res = qb_hdb_handle_get (&poll_instance_database, handle,
+		(void *)&poll_instance);
+	if (res != 0) {
+		res = -ENOENT;
+		goto error_exit;
+	}
+
+	poll_instance->stop_requested = 1;
+
+	qb_hdb_handle_put (&poll_instance_database, handle);
+error_exit:
+	return (res);
+}
+
+
+int qb_poll_run (
+	qb_hdb_handle_t handle)
+{
+	struct qb_poll_instance *poll_instance;
+	int i;
+	unsigned long long expire_timeout_msec = -1;
+	int res;
+	int poll_entry_count;
+
+	res = qb_hdb_handle_get (&poll_instance_database, handle,
+		(void *)&poll_instance);
+	if (res != 0) {
+		goto error_exit;
+	}
+
+	for (;;) {
+		for (i = 0; i < poll_instance->poll_entry_count; i++) {
+			memcpy (&poll_instance->ufds[i],
+				&poll_instance->poll_entries[i].ufd,
+				sizeof (struct pollfd));
+		}
+		expire_timeout_msec = timerlist_msec_duration_to_expire (&poll_instance->timerlist);
+
+		if (expire_timeout_msec != -1 && expire_timeout_msec > 0xFFFFFFFF) {
+			expire_timeout_msec = 0xFFFFFFFE;
+		}
+
+retry_poll:
+		res = poll (poll_instance->ufds,
+			poll_instance->poll_entry_count, expire_timeout_msec);
+		if (poll_instance->stop_requested) {
+			return (0);
+		}
+		if (errno == EINTR && res == -1) {
+			goto retry_poll;
+		} else
+		if (res == -1) {
+			goto error_exit;
+		}
+
+		poll_entry_count = poll_instance->poll_entry_count;
+		for (i = 0; i < poll_entry_count; i++) {
+			if (poll_instance->ufds[i].fd != -1 &&
+				poll_instance->ufds[i].revents) {
+
+				res = poll_instance->poll_entries[i].dispatch_fn (handle,
+					poll_instance->ufds[i].fd,
+					poll_instance->ufds[i].revents,
+					poll_instance->poll_entries[i].data);
+
+				/*
+				 * Remove dispatch functions that return -1
+				 */
+				if (res == -1) {
+					poll_instance->poll_entries[i].ufd.fd = -1; /* empty entry */
+				}
+			}
+		}
+		timerlist_expire (&poll_instance->timerlist);
+	} /* for (;;) */
+
+	qb_hdb_handle_put (&poll_instance_database, handle);
+error_exit:
+	return (-1);
+}
+
+#ifdef COMPILE_OUT
+void qb_poll_print_state (
+	qb_hdb_handle_t handle,
+	int fd)
+{
+	struct qb_poll_instance *poll_instance;
+	int i;
+	int res = 0;
+	res = qb_hdb_handle_get (&poll_instance_database, handle,
+		(void *)&poll_instance);
+	if (res != 0) {
+		res = -ENOENT;
+		exit (1);
+	}
+
+	for (i = 0; i < poll_instance->poll_entry_count; i++) {
+		if (poll_instance->poll_entries[i].ufd.fd == fd) {
+		printf ("fd %d\n", poll_instance->poll_entries[i].ufd.fd);
+		printf ("events %d\n", poll_instance->poll_entries[i].ufd.events);
+		printf ("dispatch_fn %p\n", poll_instance->poll_entries[i].dispatch_fn);
+		}
+	}
+}
+
+#endif
diff --git a/lib/poll/Makefile.am b/lib/poll/Makefile.am
deleted file mode 100644
index 1302ebc..0000000
--- a/lib/poll/Makefile.am
+++ /dev/null
@@ -1,95 +0,0 @@
-#
-# Copyright (c) 2010 Red Hat, Inc.
-#
-# Authors: Andrew Beekhof
-#	   Steven Dake (sdake@redhat.com)
-#	   Angus Salkeld <asaslkeld@redhat.com>
-#
-# This software licensed under BSD license, the text of which follows:
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are met:
-#
-# - Redistributions of source code must retain the above copyright notice,
-#   this list of conditions and the following disclaimer.
-# - 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.
-# - Neither the name of the MontaVista Software, Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
-
-MAINTAINERCLEANFILES    = Makefile.in
-
-AM_CFLAGS		= -fPIC
-
-AM_LDFLAGS		= -lpthread
-
-INCLUDES		= -I$(top_builddir)/include -I$(top_srcdir)/include
-
-lib_LIBRARIES		= libqbpoll.a
-SHARED_LIBS		= $(lib_LIBRARIES:%.a=%.so.$(SONAME))
-SHARED_LIBS_SO		= $(lib_LIBRARIES:%.a=%.so)
-SHARED_LIBS_SO_TWO	= $(lib_LIBRARIES:%.a=%.so.$(SOMAJOR))
-
-libqbpoll_a_SOURCES	= poll.c
-
-noinst_HEADERS		= libqbpoll.versions 
-
-if BUILD_DARWIN
-
-lib%.so.$(SONAME): %.o
-	$(CC) $(DARWIN_OPTS) $^ -o $@
-	ln -sf lib$*.so.$(SONAME) lib$*.so
-	ln -sf lib$*.so.$(SONAME) lib$*.so.$(SOMAJOR)
-
-else
-
-if BUILD_SOLARIS
-
-lib%.so.$(SONAME): %.o
-	$(LD) $(SOLARIS_OPTS) -G $^ -o $@
-	ln -sf lib$*.so.$(SONAME) lib$*.so
-	ln -sf lib$*.so.$(SONAME) lib$*.so.$(SOMAJOR)
-
-else
-
-libqb%.so.$(SONAME): %.o
-	$(CC) -shared -o $@ \
-		-Wl,-soname=libqb$*.so.$(SOMAJOR) \
-		-Wl,-version-script=$(srcdir)/libqb$*.versions \
-		$^ $(LDFLAGS) $(AM_LDFLAGS)
-	ln -sf libqb$*.so.$(SONAME) libqb$*.so
-	ln -sf libqb$*.so.$(SONAME) libqb$*.so.$(SOMAJOR)
-
-endif
-
-endif
-
-all-local: $(SHARED_LIBS)
-	@echo Built shared libs
-
-install-exec-local:
-	$(INSTALL) -d $(DESTDIR)/$(libdir)
-	$(INSTALL) -m 755 $(SHARED_LIBS) $(DESTDIR)/$(libdir)
-	$(CP) -a $(SHARED_LIBS_SO) $(SHARED_LIBS_SO_TWO) $(DESTDIR)/$(libdir)
-
-uninstall-local:
-	cd $(DESTDIR)/$(libdir)/ && \
-		rm -f $(SHARED_LIBS) $(SHARED_LIBS_SO) $(SHARED_LIBS_SO_TWO)
-
-clean-local:
-	rm -f *.o *.a *.so* *.da *.bb *.bbg
-
diff --git a/lib/poll/libqbpoll.versions b/lib/poll/libqbpoll.versions
deleted file mode 100644
index d743f9c..0000000
--- a/lib/poll/libqbpoll.versions
+++ /dev/null
@@ -1,13 +0,0 @@
-QB_POLL_0.1 {
-	global:
-		qb_poll_create;
-		qb_poll_destroy;
-		qb_poll_dispatch_add;
-		qb_poll_dispatch_modify;
-		qb_poll_dispatch_delete;
-		qb_poll_timer_add;
-		qb_poll_timer_delete;
-		qb_poll_run;
-		qb_poll_stop;
-	local: *;
-};
diff --git a/lib/poll/poll.c b/lib/poll/poll.c
deleted file mode 100644
index be779da..0000000
--- a/lib/poll/poll.c
+++ /dev/null
@@ -1,441 +0,0 @@
-/*
- * Copyright (c) 2003-2004 MontaVista Software, Inc.
- * Copyright (c) 2006-2010 Red Hat, Inc.
- *
- * All rights reserved.
- *
- * Author: Steven Dake (sdake@redhat.com)
- *
- * This software licensed under BSD license, the text of which follows:
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * - Redistributions of source code must retain the above copyright notice,
- *   this list of conditions and the following disclaimer.
- * - 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.
- * - Neither the name of the MontaVista Software, Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
- */
-
-#include <config.h>
-
-#include <errno.h>
-#include <pthread.h>
-#include <sys/poll.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-
-#include <qb/qbhdb.h>
-#include <qb/qbpoll.h>
-#include <qb/qblist.h>
-#include "tlist.h"
-
-typedef int (*dispatch_fn_t) (qb_hdb_handle_t hdb_handle, int fd, int revents, void *data);
-
-struct qb_poll_entry {
-	struct pollfd ufd;
-	dispatch_fn_t dispatch_fn;
-	void *data;
-};
-
-struct qb_poll_instance {
-	struct qb_poll_entry *poll_entries;
-	struct pollfd *ufds;
-	int poll_entry_count;
-	struct timerlist timerlist;
-	int stop_requested;
-};
-
-DECLARE_HDB_DATABASE (poll_instance_database,NULL);
-
-qb_hdb_handle_t qb_poll_create (void)
-{
-	qb_hdb_handle_t handle;
-	struct qb_poll_instance *poll_instance;
-	unsigned int res;
-
-	res = qb_hdb_handle_create (&poll_instance_database,
-		sizeof (struct qb_poll_instance), &handle);
-	if (res != 0) {
-		goto error_exit;
-	}
-	res = qb_hdb_handle_get (&poll_instance_database, handle,
-		(void *)&poll_instance);
-	if (res != 0) {
-		goto error_destroy;
-	}
-
-	poll_instance->poll_entries = 0;
-	poll_instance->ufds = 0;
-	poll_instance->poll_entry_count = 0;
-	poll_instance->stop_requested = 0;
-	timerlist_init (&poll_instance->timerlist);
-
-	return (handle);
-
-error_destroy:
-	qb_hdb_handle_destroy (&poll_instance_database, handle);
-
-error_exit:
-	return (-1);
-}
-
-int qb_poll_destroy (qb_hdb_handle_t handle)
-{
-	struct qb_poll_instance *poll_instance;
-	int res = 0;
-
-	res = qb_hdb_handle_get (&poll_instance_database, handle,
-		(void *)&poll_instance);
-	if (res != 0) {
-		res = -ENOENT;
-		goto error_exit;
-	}
-
-	free (poll_instance->poll_entries);
-	free (poll_instance->ufds);
-
-	qb_hdb_handle_destroy (&poll_instance_database, handle);
-
-	qb_hdb_handle_put (&poll_instance_database, handle);
-
-error_exit:
-	return (res);
-}
-
-int qb_poll_dispatch_add (
-	qb_hdb_handle_t handle,
-	int fd,
-	int events,
-	void *data,
-	int (*dispatch_fn) (
-		qb_hdb_handle_t hdb_handle_t,
-		int fd,
-		int revents,
-		void *data))
-{
-	struct qb_poll_instance *poll_instance;
-	struct qb_poll_entry *poll_entries;
-	struct pollfd *ufds;
-	int found = 0;
-	int install_pos;
-	int res = 0;
-
-	res = qb_hdb_handle_get (&poll_instance_database, handle,
-		(void *)&poll_instance);
-	if (res != 0) {
-		res = -ENOENT;
-		goto error_exit;
-	}
-
-	for (found = 0, install_pos = 0; install_pos < poll_instance->poll_entry_count; install_pos++) {
-		if (poll_instance->poll_entries[install_pos].ufd.fd == -1) {
-			found = 1;
-			break;
-		}
-	}
-
-	if (found == 0) {
-		/*
-		 * Grow pollfd list
-		 */
-		poll_entries = (struct qb_poll_entry *)realloc (poll_instance->poll_entries,
-			(poll_instance->poll_entry_count + 1) *
-			sizeof (struct qb_poll_entry));
-		if (poll_entries == NULL) {
-			res = -ENOMEM;
-			goto error_put;
-		}
-		poll_instance->poll_entries = poll_entries;
-
-		ufds = (struct pollfd *)realloc (poll_instance->ufds,
-			(poll_instance->poll_entry_count + 1) *
-			sizeof (struct pollfd));
-		if (ufds == NULL) {
-			res = -ENOMEM;
-			goto error_put;
-		}
-		poll_instance->ufds = ufds;
-
-		poll_instance->poll_entry_count += 1;
-		install_pos = poll_instance->poll_entry_count - 1;
-	}
-
-	/*
-	 * Install new dispatch handler
-	 */
-	poll_instance->poll_entries[install_pos].ufd.fd = fd;
-	poll_instance->poll_entries[install_pos].ufd.events = events;
-	poll_instance->poll_entries[install_pos].ufd.revents = 0;
-	poll_instance->poll_entries[install_pos].dispatch_fn = dispatch_fn;
-	poll_instance->poll_entries[install_pos].data = data;
-
-error_put:
-	qb_hdb_handle_put (&poll_instance_database, handle);
-
-error_exit:
-	return (res);
-}
-
-int qb_poll_dispatch_modify (
-	qb_hdb_handle_t handle,
-	int fd,
-	int events,
-	int (*dispatch_fn) (
-		qb_hdb_handle_t hdb_handle_t,
-		int fd,
-		int revents,
-		void *data))
-{
-	struct qb_poll_instance *poll_instance;
-	int i;
-	int res = 0;
-
-	res = qb_hdb_handle_get (&poll_instance_database, handle,
-		(void *)&poll_instance);
-	if (res != 0) {
-		res = -ENOENT;
-		goto error_exit;
-	}
-
-	/*
-	 * Find file descriptor to modify events and dispatch function
-	 */
-	for (i = 0; i < poll_instance->poll_entry_count; i++) {
-		if (poll_instance->poll_entries[i].ufd.fd == fd) {
-			poll_instance->poll_entries[i].ufd.events = events;
-			poll_instance->poll_entries[i].dispatch_fn = dispatch_fn;
-
-			goto error_put;
-		}
-	}
-
-	res = -EBADF;
-
-error_put:
-	qb_hdb_handle_put (&poll_instance_database, handle);
-
-error_exit:
-	return (res);
-}
-
-int qb_poll_dispatch_delete (
-	qb_hdb_handle_t handle,
-	int fd)
-{
-	struct qb_poll_instance *poll_instance;
-	int i;
-	int res = 0;
-
-	res = qb_hdb_handle_get (&poll_instance_database, handle,
-		(void *)&poll_instance);
-	if (res != 0) {
-		res = -ENOENT;
-		goto error_exit;
-	}
-
-	/*
-	 * Find dispatch fd to delete
-	 */
-	res = -EBADF;
-	for (i = 0; i < poll_instance->poll_entry_count; i++) {
-		if (poll_instance->poll_entries[i].ufd.fd == fd) {
-			poll_instance->ufds[i].fd = -1;
-			poll_instance->poll_entries[i].ufd.fd = -1;
-			poll_instance->poll_entries[i].ufd.revents = 0;
-
-			res = 0;
-			break;
-		}
-	}
-
-
-	qb_hdb_handle_put (&poll_instance_database, handle);
-
-error_exit:
-	return (res);
-}
-
-int qb_poll_timer_add (
-	qb_hdb_handle_t handle,
-	int msec_duration, void *data,
-	void (*timer_fn) (void *data),
-	qb_poll_timer_handle *timer_handle_out)
-{
-	struct qb_poll_instance *poll_instance;
-	int res = 0;
-
-	if (timer_handle_out == NULL) {
-		res = -ENOENT;
-		goto error_exit;
-	}
-
-	res = qb_hdb_handle_get (&poll_instance_database, handle,
-		(void *)&poll_instance);
-	if (res != 0) {
-		res = -ENOENT;
-		goto error_exit;
-	}
-
-	timerlist_add_duration (&poll_instance->timerlist,
-		timer_fn, data, ((unsigned long long)msec_duration) * 1000000ULL, timer_handle_out);
-
-	qb_hdb_handle_put (&poll_instance_database, handle);
-error_exit:
-	return (res);
-}
-
-int qb_poll_timer_delete (
-	qb_hdb_handle_t handle,
-	qb_poll_timer_handle th)
-{
-	struct qb_poll_instance *poll_instance;
-	int res = 0;
-
-	if (th == 0) {
-		return (0);
-	}
-	res = qb_hdb_handle_get (&poll_instance_database, handle,
-		(void *)&poll_instance);
-	if (res != 0) {
-		res = -ENOENT;
-		goto error_exit;
-	}
-
-	timerlist_del (&poll_instance->timerlist, (void *)th);
-
-	qb_hdb_handle_put (&poll_instance_database, handle);
-
-error_exit:
-	return (res);
-}
-
-int qb_poll_stop (
-	qb_hdb_handle_t handle)
-{
-	struct qb_poll_instance *poll_instance;
-	unsigned int res;
-
-	res = qb_hdb_handle_get (&poll_instance_database, handle,
-		(void *)&poll_instance);
-	if (res != 0) {
-		res = -ENOENT;
-		goto error_exit;
-	}
-
-	poll_instance->stop_requested = 1;
-
-	qb_hdb_handle_put (&poll_instance_database, handle);
-error_exit:
-	return (res);
-}
-
-
-int qb_poll_run (
-	qb_hdb_handle_t handle)
-{
-	struct qb_poll_instance *poll_instance;
-	int i;
-	unsigned long long expire_timeout_msec = -1;
-	int res;
-	int poll_entry_count;
-
-	res = qb_hdb_handle_get (&poll_instance_database, handle,
-		(void *)&poll_instance);
-	if (res != 0) {
-		goto error_exit;
-	}
-
-	for (;;) {
-		for (i = 0; i < poll_instance->poll_entry_count; i++) {
-			memcpy (&poll_instance->ufds[i],
-				&poll_instance->poll_entries[i].ufd,
-				sizeof (struct pollfd));
-		}
-		expire_timeout_msec = timerlist_msec_duration_to_expire (&poll_instance->timerlist);
-
-		if (expire_timeout_msec != -1 && expire_timeout_msec > 0xFFFFFFFF) {
-			expire_timeout_msec = 0xFFFFFFFE;
-		}
-
-retry_poll:
-		res = poll (poll_instance->ufds,
-			poll_instance->poll_entry_count, expire_timeout_msec);
-		if (poll_instance->stop_requested) {
-			return (0);
-		}
-		if (errno == EINTR && res == -1) {
-			goto retry_poll;
-		} else
-		if (res == -1) {
-			goto error_exit;
-		}
-
-		poll_entry_count = poll_instance->poll_entry_count;
-		for (i = 0; i < poll_entry_count; i++) {
-			if (poll_instance->ufds[i].fd != -1 &&
-				poll_instance->ufds[i].revents) {
-
-				res = poll_instance->poll_entries[i].dispatch_fn (handle,
-					poll_instance->ufds[i].fd,
-					poll_instance->ufds[i].revents,
-					poll_instance->poll_entries[i].data);
-
-				/*
-				 * Remove dispatch functions that return -1
-				 */
-				if (res == -1) {
-					poll_instance->poll_entries[i].ufd.fd = -1; /* empty entry */
-				}
-			}
-		}
-		timerlist_expire (&poll_instance->timerlist);
-	} /* for (;;) */
-
-	qb_hdb_handle_put (&poll_instance_database, handle);
-error_exit:
-	return (-1);
-}
-
-#ifdef COMPILE_OUT
-void qb_poll_print_state (
-	qb_hdb_handle_t handle,
-	int fd)
-{
-	struct qb_poll_instance *poll_instance;
-	int i;
-	int res = 0;
-	res = qb_hdb_handle_get (&poll_instance_database, handle,
-		(void *)&poll_instance);
-	if (res != 0) {
-		res = -ENOENT;
-		exit (1);
-	}
-
-	for (i = 0; i < poll_instance->poll_entry_count; i++) {
-		if (poll_instance->poll_entries[i].ufd.fd == fd) {
-		printf ("fd %d\n", poll_instance->poll_entries[i].ufd.fd);
-		printf ("events %d\n", poll_instance->poll_entries[i].ufd.events);
-		printf ("dispatch_fn %p\n", poll_instance->poll_entries[i].dispatch_fn);
-		}
-	}
-}
-
-#endif
diff --git a/lib/timer.c b/lib/timer.c
new file mode 100644
index 0000000..7238a87
--- /dev/null
+++ b/lib/timer.c
@@ -0,0 +1,271 @@
+/*
+ * Copyright (c) 2002-2006 MontaVista Software, Inc.
+ * Copyright (c) 2006-2009 Red Hat, Inc.
+ *
+ * All rights reserved.
+ *
+ * Author: Steven Dake (sdake@redhat.com)
+ *
+ * This software licensed under BSD license, the text of which follows:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - 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.
+ * - Neither the name of the MontaVista Software, Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
+ */
+
+#include <config.h>
+
+#include "os_base.h"
+
+#include <poll.h>
+#include <signal.h>
+#include <time.h>
+
+#include "tlist.h"
+
+#include <qb/qblist.h>
+#include <qb/qbpoll.h>
+#include <qb/qbtimer.h>
+
+
+#define SERVER_BACKLOG 5
+
+static pthread_mutex_t timer_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+static pthread_t expiry_thread;
+
+static pthread_attr_t thread_attr;
+
+static struct timerlist timers_timerlist;
+
+static int sched_priority = 0;
+
+static void (*timer_serialize_lock_fn) (void);
+
+static void (*timer_serialize_unlock_fn) (void);
+
+static void *prioritized_timer_thread (void *data);
+
+extern void pthread_exit(void *) __attribute__((noreturn));
+
+/*
+ * This thread runs at the highest priority to run system wide timers
+ */
+static void *prioritized_timer_thread (void *data)
+{
+	int fds;
+	unsigned long long timeout;
+
+#if defined(HAVE_PTHREAD_SETSCHEDPARAM) && defined(HAVE_SCHED_GET_PRIORITY_MAX)
+	if (sched_priority != 0) {
+		struct sched_param sched_param;
+
+		sched_param.sched_priority = sched_priority;
+		pthread_setschedparam (expiry_thread, SCHED_RR, &sched_param);
+	}
+#endif
+
+	pthread_mutex_unlock (&timer_mutex);
+	for (;;) {
+		timer_serialize_lock_fn ();
+		timeout = timerlist_msec_duration_to_expire (&timers_timerlist);
+		if (timeout != -1 && timeout > 0xFFFFFFFF) {
+			timeout = 0xFFFFFFFE;
+		}
+		timer_serialize_unlock_fn ();
+		fds = poll (NULL, 0, timeout);
+		if (fds < 0 && errno == EINTR) {
+			continue;
+		}
+		if (fds < 0) {
+			return NULL;
+		}
+		pthread_mutex_lock (&timer_mutex);
+		timer_serialize_lock_fn ();
+
+		timerlist_expire (&timers_timerlist);
+
+		timer_serialize_unlock_fn ();
+		pthread_mutex_unlock (&timer_mutex);
+	}
+}
+
+static void sigusr1_handler (int num) {
+#ifdef qb_SOLARIS
+	/* Rearm the signal facility */
+        signal (num, sigusr1_handler);
+#endif
+}
+
+int qb_timer_init (
+        void (*serialize_lock_fn) (void),
+        void (*serialize_unlock_fn) (void),
+	int sched_priority_in)
+{
+	int res;
+
+	timer_serialize_lock_fn = serialize_lock_fn;
+	timer_serialize_unlock_fn = serialize_unlock_fn;
+	sched_priority = sched_priority_in;
+
+	timerlist_init (&timers_timerlist);
+
+	signal (SIGUSR1, sigusr1_handler);
+
+	pthread_mutex_lock (&timer_mutex);
+	pthread_attr_init (&thread_attr);
+	pthread_attr_setstacksize (&thread_attr, 100000);
+	pthread_attr_setdetachstate (&thread_attr, PTHREAD_CREATE_DETACHED);
+	res = pthread_create (&expiry_thread, &thread_attr,
+		prioritized_timer_thread, NULL);
+
+	return (res);
+}
+
+int qb_timer_add_absolute (
+	unsigned long long nanosec_from_epoch,
+	void *data,
+	void (*timer_fn) (void *data),
+	timer_handle *handle)
+{
+	int res;
+	int unlock;
+
+	if (pthread_equal (pthread_self(), expiry_thread) != 0) {
+		unlock = 0;
+	} else {
+		unlock = 1;
+		pthread_mutex_lock (&timer_mutex);
+	}
+
+	res = timerlist_add_absolute (
+		&timers_timerlist,
+		timer_fn,
+		data,
+		nanosec_from_epoch,
+		handle);
+
+	if (unlock) {
+		pthread_mutex_unlock (&timer_mutex);
+	}
+
+	pthread_kill (expiry_thread, SIGUSR1);
+
+	return (res);
+}
+
+int qb_timer_add_duration (
+	unsigned long long nanosec_duration,
+	void *data,
+	void (*timer_fn) (void *data),
+	timer_handle *handle)
+{
+	int res;
+	int unlock;
+
+	if (pthread_equal (pthread_self(), expiry_thread) != 0) {
+		unlock = 0;
+	} else {
+		unlock = 1;
+		pthread_mutex_lock (&timer_mutex);
+	}
+
+	res = timerlist_add_duration (
+		&timers_timerlist,
+		timer_fn,
+		data,
+		nanosec_duration,
+		handle);
+
+	if (unlock) {
+		pthread_mutex_unlock (&timer_mutex);
+	}
+
+	pthread_kill (expiry_thread, SIGUSR1);
+
+	return (res);
+}
+
+void qb_timer_delete (
+	timer_handle th)
+{
+	int unlock;
+
+	if (th == 0) {
+		return;
+	}
+
+	if (pthread_equal (pthread_self(), expiry_thread) != 0) {
+		unlock = 0;
+	} else {
+		unlock = 1;
+		pthread_mutex_lock (&timer_mutex);
+	}
+
+	timerlist_del (&timers_timerlist, th);
+
+	if (unlock) {
+		pthread_mutex_unlock (&timer_mutex);
+	}
+}
+
+void qb_timer_lock (void)
+{
+	pthread_mutex_lock (&timer_mutex);
+}
+
+void qb_timer_unlock (void)
+{
+	pthread_mutex_unlock (&timer_mutex);
+}
+
+unsigned long long qb_timer_time_get (void)
+{
+	return (timerlist_nano_from_epoch());
+}
+
+unsigned long long qb_timer_expire_time_get (
+	timer_handle th)
+{
+	int unlock;
+	unsigned long long expire;
+
+	if (th == 0) {
+		return (0);
+	}
+
+	if (pthread_equal (pthread_self(), expiry_thread) != 0) {
+		unlock = 0;
+	} else {
+		unlock = 1;
+		pthread_mutex_lock (&timer_mutex);
+	}
+
+	expire = timerlist_expire_time (&timers_timerlist, th);
+
+	if (unlock) {
+		pthread_mutex_unlock (&timer_mutex);
+	}
+
+	return (expire);
+}
diff --git a/lib/timer/Makefile.am b/lib/timer/Makefile.am
deleted file mode 100644
index bb99fdb..0000000
--- a/lib/timer/Makefile.am
+++ /dev/null
@@ -1,95 +0,0 @@
-#
-# Copyright (c) 2010 Red Hat, Inc.
-#
-# Authors: Andrew Beekhof
-#	   Steven Dake (sdake@redhat.com)
-#	   Angus Salkeld <asaslkeld@redhat.com>
-#
-# This software licensed under BSD license, the text of which follows:
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are met:
-#
-# - Redistributions of source code must retain the above copyright notice,
-#   this list of conditions and the following disclaimer.
-# - 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.
-# - Neither the name of the MontaVista Software, Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
-
-MAINTAINERCLEANFILES    = Makefile.in
-
-AM_CFLAGS		= -fPIC
-
-AM_LDFLAGS		= -lpthread
-
-INCLUDES		= -I$(top_builddir)/include -I$(top_srcdir)/include
-
-lib_LIBRARIES		= libqbtimer.a
-SHARED_LIBS		= $(lib_LIBRARIES:%.a=%.so.$(SONAME))
-SHARED_LIBS_SO		= $(lib_LIBRARIES:%.a=%.so)
-SHARED_LIBS_SO_TWO	= $(lib_LIBRARIES:%.a=%.so.$(SOMAJOR))
-
-libqbtimer_a_SOURCES	= timer.c
-
-noinst_HEADERS		= libqbtimer.versions 
-
-if BUILD_DARWIN
-
-lib%.so.$(SONAME): %.o
-	$(CC) $(DARWIN_OPTS) $^ -o $@
-	ln -sf lib$*.so.$(SONAME) lib$*.so
-	ln -sf lib$*.so.$(SONAME) lib$*.so.$(SOMAJOR)
-
-else
-
-if BUILD_SOLARIS
-
-lib%.so.$(SONAME): %.o
-	$(LD) $(SOLARIS_OPTS) -G $^ -o $@
-	ln -sf lib$*.so.$(SONAME) lib$*.so
-	ln -sf lib$*.so.$(SONAME) lib$*.so.$(SOMAJOR)
-
-else
-
-libqb%.so.$(SONAME): %.o
-	$(CC) -shared -o $@ \
-		-Wl,-soname=libqb$*.so.$(SOMAJOR) \
-		-Wl,-version-script=$(srcdir)/libqb$*.versions \
-		$^ $(LDFLAGS) $(AM_LDFLAGS)
-	ln -sf libqb$*.so.$(SONAME) libqb$*.so
-	ln -sf libqb$*.so.$(SONAME) libqb$*.so.$(SOMAJOR)
-
-endif
-
-endif
-
-all-local: $(SHARED_LIBS)
-	@echo Built shared libs
-
-install-exec-local:
-	$(INSTALL) -d $(DESTDIR)/$(libdir)
-	$(INSTALL) -m 755 $(SHARED_LIBS) $(DESTDIR)/$(libdir)
-	$(CP) -a $(SHARED_LIBS_SO) $(SHARED_LIBS_SO_TWO) $(DESTDIR)/$(libdir)
-
-uninstall-local:
-	cd $(DESTDIR)/$(libdir)/ && \
-		rm -f $(SHARED_LIBS) $(SHARED_LIBS_SO) $(SHARED_LIBS_SO_TWO)
-
-clean-local:
-	rm -f *.o *.a *.so* *.da *.bb *.bbg
-
diff --git a/lib/timer/libqbtimer.versions b/lib/timer/libqbtimer.versions
deleted file mode 100644
index 1a7ed4d..0000000
--- a/lib/timer/libqbtimer.versions
+++ /dev/null
@@ -1,13 +0,0 @@
-QB_TIMER_0.1 {
-	global:
-		qb_timer_init;
-		qb_timer_add_duration;
-		qb_timer_add_absolute;
-		qb_timer_delete;
-		qb_timer_delete_data;
-		qb_timer_lock;
-		qb_timer_unlock;
-		qb_timer_time_get;
-		qb_timer_expire_time_get;
-	local: *;
-};
diff --git a/lib/timer/timer.c b/lib/timer/timer.c
deleted file mode 100644
index 7238a87..0000000
--- a/lib/timer/timer.c
+++ /dev/null
@@ -1,271 +0,0 @@
-/*
- * Copyright (c) 2002-2006 MontaVista Software, Inc.
- * Copyright (c) 2006-2009 Red Hat, Inc.
- *
- * All rights reserved.
- *
- * Author: Steven Dake (sdake@redhat.com)
- *
- * This software licensed under BSD license, the text of which follows:
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * - Redistributions of source code must retain the above copyright notice,
- *   this list of conditions and the following disclaimer.
- * - 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.
- * - Neither the name of the MontaVista Software, Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
- */
-
-#include <config.h>
-
-#include "os_base.h"
-
-#include <poll.h>
-#include <signal.h>
-#include <time.h>
-
-#include "tlist.h"
-
-#include <qb/qblist.h>
-#include <qb/qbpoll.h>
-#include <qb/qbtimer.h>
-
-
-#define SERVER_BACKLOG 5
-
-static pthread_mutex_t timer_mutex = PTHREAD_MUTEX_INITIALIZER;
-
-static pthread_t expiry_thread;
-
-static pthread_attr_t thread_attr;
-
-static struct timerlist timers_timerlist;
-
-static int sched_priority = 0;
-
-static void (*timer_serialize_lock_fn) (void);
-
-static void (*timer_serialize_unlock_fn) (void);
-
-static void *prioritized_timer_thread (void *data);
-
-extern void pthread_exit(void *) __attribute__((noreturn));
-
-/*
- * This thread runs at the highest priority to run system wide timers
- */
-static void *prioritized_timer_thread (void *data)
-{
-	int fds;
-	unsigned long long timeout;
-
-#if defined(HAVE_PTHREAD_SETSCHEDPARAM) && defined(HAVE_SCHED_GET_PRIORITY_MAX)
-	if (sched_priority != 0) {
-		struct sched_param sched_param;
-
-		sched_param.sched_priority = sched_priority;
-		pthread_setschedparam (expiry_thread, SCHED_RR, &sched_param);
-	}
-#endif
-
-	pthread_mutex_unlock (&timer_mutex);
-	for (;;) {
-		timer_serialize_lock_fn ();
-		timeout = timerlist_msec_duration_to_expire (&timers_timerlist);
-		if (timeout != -1 && timeout > 0xFFFFFFFF) {
-			timeout = 0xFFFFFFFE;
-		}
-		timer_serialize_unlock_fn ();
-		fds = poll (NULL, 0, timeout);
-		if (fds < 0 && errno == EINTR) {
-			continue;
-		}
-		if (fds < 0) {
-			return NULL;
-		}
-		pthread_mutex_lock (&timer_mutex);
-		timer_serialize_lock_fn ();
-
-		timerlist_expire (&timers_timerlist);
-
-		timer_serialize_unlock_fn ();
-		pthread_mutex_unlock (&timer_mutex);
-	}
-}
-
-static void sigusr1_handler (int num) {
-#ifdef qb_SOLARIS
-	/* Rearm the signal facility */
-        signal (num, sigusr1_handler);
-#endif
-}
-
-int qb_timer_init (
-        void (*serialize_lock_fn) (void),
-        void (*serialize_unlock_fn) (void),
-	int sched_priority_in)
-{
-	int res;
-
-	timer_serialize_lock_fn = serialize_lock_fn;
-	timer_serialize_unlock_fn = serialize_unlock_fn;
-	sched_priority = sched_priority_in;
-
-	timerlist_init (&timers_timerlist);
-
-	signal (SIGUSR1, sigusr1_handler);
-
-	pthread_mutex_lock (&timer_mutex);
-	pthread_attr_init (&thread_attr);
-	pthread_attr_setstacksize (&thread_attr, 100000);
-	pthread_attr_setdetachstate (&thread_attr, PTHREAD_CREATE_DETACHED);
-	res = pthread_create (&expiry_thread, &thread_attr,
-		prioritized_timer_thread, NULL);
-
-	return (res);
-}
-
-int qb_timer_add_absolute (
-	unsigned long long nanosec_from_epoch,
-	void *data,
-	void (*timer_fn) (void *data),
-	timer_handle *handle)
-{
-	int res;
-	int unlock;
-
-	if (pthread_equal (pthread_self(), expiry_thread) != 0) {
-		unlock = 0;
-	} else {
-		unlock = 1;
-		pthread_mutex_lock (&timer_mutex);
-	}
-
-	res = timerlist_add_absolute (
-		&timers_timerlist,
-		timer_fn,
-		data,
-		nanosec_from_epoch,
-		handle);
-
-	if (unlock) {
-		pthread_mutex_unlock (&timer_mutex);
-	}
-
-	pthread_kill (expiry_thread, SIGUSR1);
-
-	return (res);
-}
-
-int qb_timer_add_duration (
-	unsigned long long nanosec_duration,
-	void *data,
-	void (*timer_fn) (void *data),
-	timer_handle *handle)
-{
-	int res;
-	int unlock;
-
-	if (pthread_equal (pthread_self(), expiry_thread) != 0) {
-		unlock = 0;
-	} else {
-		unlock = 1;
-		pthread_mutex_lock (&timer_mutex);
-	}
-
-	res = timerlist_add_duration (
-		&timers_timerlist,
-		timer_fn,
-		data,
-		nanosec_duration,
-		handle);
-
-	if (unlock) {
-		pthread_mutex_unlock (&timer_mutex);
-	}
-
-	pthread_kill (expiry_thread, SIGUSR1);
-
-	return (res);
-}
-
-void qb_timer_delete (
-	timer_handle th)
-{
-	int unlock;
-
-	if (th == 0) {
-		return;
-	}
-
-	if (pthread_equal (pthread_self(), expiry_thread) != 0) {
-		unlock = 0;
-	} else {
-		unlock = 1;
-		pthread_mutex_lock (&timer_mutex);
-	}
-
-	timerlist_del (&timers_timerlist, th);
-
-	if (unlock) {
-		pthread_mutex_unlock (&timer_mutex);
-	}
-}
-
-void qb_timer_lock (void)
-{
-	pthread_mutex_lock (&timer_mutex);
-}
-
-void qb_timer_unlock (void)
-{
-	pthread_mutex_unlock (&timer_mutex);
-}
-
-unsigned long long qb_timer_time_get (void)
-{
-	return (timerlist_nano_from_epoch());
-}
-
-unsigned long long qb_timer_expire_time_get (
-	timer_handle th)
-{
-	int unlock;
-	unsigned long long expire;
-
-	if (th == 0) {
-		return (0);
-	}
-
-	if (pthread_equal (pthread_self(), expiry_thread) != 0) {
-		unlock = 0;
-	} else {
-		unlock = 1;
-		pthread_mutex_lock (&timer_mutex);
-	}
-
-	expire = timerlist_expire_time (&timers_timerlist, th);
-
-	if (unlock) {
-		pthread_mutex_unlock (&timer_mutex);
-	}
-
-	return (expire);
-}
diff --git a/lib/tsafe.c b/lib/tsafe.c
new file mode 100644
index 0000000..d803189
--- /dev/null
+++ b/lib/tsafe.c
@@ -0,0 +1,1082 @@
+/*
+ * Copyright (c) 2010 Red Hat, Inc.
+ *
+ * All rights reserved.
+ *
+ * Author: Angus Salkeld <asalkeld@redhat.com>
+ *
+ * This software licensed under BSD license, the text of which follows:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - 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.
+ * - Neither the name of the MontaVista Software, Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
+ */
+
+#include <config.h>
+
+#define _XOPEN_SOURCE 600
+#define _GNU_SOURCE 1
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+#include <string.h>
+#include <assert.h>
+#include <time.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <grp.h>
+#include <pwd.h>
+#include <netdb.h>
+#include <nl_types.h>
+#include <libgen.h>
+#include <dlfcn.h>
+#ifdef HAVE_UTMPX_H
+#include <utmpx.h>
+#endif /* HAVE_UTMPX_H */
+#include <search.h>
+#include <locale.h>
+#include <dirent.h>
+#include <pthread.h>
+
+#include <qb/qbtsafe.h>
+
+#ifndef RTLD_NEXT
+#define RTLD_NEXT       ((void *) -1l)
+#endif /* !RTLD_NEXT */
+
+#ifdef QB_BSD
+#define CONST_ON_BSD const
+#else
+#define CONST_ON_BSD
+#endif /* QB_BSD */
+
+
+
+/*
+ * The point of this file is to prevent people from using functions that are
+ * known not to be thread safe (see man pthreads).
+ */
+
+static int tsafe_disabled = 1;
+static int tsafe_inited = 0;
+static char **coro_environ;
+static void atfork_prepare (void);
+static void atfork_parent (void);
+static void atfork_child (void);
+
+#if defined(HAVE_PTHREAD_SPIN_LOCK)
+static pthread_spinlock_t tsafe_enabled_mutex;
+#else
+static pthread_mutex_t tsafe_enabled_mutex = PTHREAD_MUTEX_INITIALIZER;
+#endif
+
+
+void qb_tsafe_init (char **envp)
+{
+	int i;
+	int size = 1;
+
+	for (i = 0; envp[i] != NULL; i++) {
+		size++;
+	}
+	coro_environ = malloc (sizeof (char*) * size);
+	for (i = 0; envp[i] != NULL; i++) {
+		coro_environ[i] = strdup (envp[i]);
+	}
+	coro_environ[size-1] = NULL;
+
+#if defined(HAVE_PTHREAD_SPIN_LOCK)
+	pthread_spin_init (&tsafe_enabled_mutex, 0);
+#endif
+
+	pthread_atfork (atfork_prepare, atfork_parent, atfork_child);
+
+	tsafe_disabled = 1;
+	tsafe_inited = 1;
+}
+
+static void tsafe_lock (void)
+{
+#if defined(HAVE_PTHREAD_SPIN_LOCK)
+	pthread_spin_lock (&tsafe_enabled_mutex);
+#else
+	pthread_mutex_lock (&tsafe_enabled_mutex);
+#endif
+}
+
+static void tsafe_unlock (void)
+{
+#if defined(HAVE_PTHREAD_SPIN_LOCK)
+	pthread_spin_unlock (&tsafe_enabled_mutex);
+#else
+	pthread_mutex_unlock (&tsafe_enabled_mutex);
+#endif
+}
+
+void qb_tsafe_off (void)
+{
+	tsafe_lock ();
+	tsafe_disabled = 1;
+	tsafe_unlock ();
+}
+
+void qb_tsafe_on (void)
+{
+	tsafe_lock ();
+	tsafe_disabled = 0;
+	tsafe_unlock ();
+}
+
+static void atfork_prepare (void)
+{
+	tsafe_lock ();
+}
+
+static void atfork_parent (void)
+{
+	tsafe_unlock ();
+}
+
+static void atfork_child (void)
+{
+	if (tsafe_inited && !tsafe_disabled) {
+		tsafe_disabled = 1;
+	}
+	tsafe_unlock ();
+}
+
+static void* _get_real_func_(const char * func_name)
+{
+	void * func = NULL;
+#ifdef QB_BSD
+	static void *handle;
+	/*
+	 * On BSD we open the libc and retrive the pointer to "func_name".
+	 */
+	handle = dlopen("/usr/lib/libc.so", RTLD_LAZY);
+	func = dlsym (handle, func_name);
+#else
+	/*
+	 * On linux/Sun we can set func to next instance of "func_name",
+	 * which is the original "func_name"
+	 */
+	func = dlsym (RTLD_NEXT, func_name);
+#endif
+	return func;
+}
+
+#ifdef QB_LINUX
+/* we are implementing these functions only to know when to turn tsafe
+ * on and off.
+ */
+int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
+                   void *(*start_routine) (void *), void *arg)
+{
+	static int (*real_pthread_create)(pthread_t *thread, const pthread_attr_t *attr,
+                   void *(*start_routine) (void *), void *arg) = NULL;
+
+	if (tsafe_inited && tsafe_disabled) {
+		qb_tsafe_on ();
+	}
+
+	if (real_pthread_create == NULL) {
+		real_pthread_create = _get_real_func_ ("pthread_create");
+	}
+	return real_pthread_create (thread, attr, start_routine, arg);
+}
+
+#endif /* QB_LINUX */
+
+/*
+ * we will allow this one as there doesn't seem to be any other option.
+ * and only used in lcr
+ * char *dlerror(void)
+ * {
+ * }
+ */
+
+/* the following functions are needed so we are either banning them or
+ * re-implementing them (depending on tsafe_on).
+ */
+char *getenv(const char *name)
+{
+	static char* (*real_getenv)(const char *name) = NULL;
+	int entry;
+	int found = 0;
+	char *eq;
+	size_t name_len;
+
+	if (!tsafe_inited || tsafe_disabled) {
+		if (real_getenv == NULL) {
+			real_getenv = _get_real_func_ ("getenv");
+		}
+		return real_getenv (name);
+	}
+	for (entry = 0; coro_environ[entry] != NULL; entry++) {
+		eq = strchr (coro_environ[entry], '=');
+		name_len = eq - coro_environ[entry];
+
+		if (name_len == strlen (name) &&
+			strncmp(name, coro_environ[entry], name_len) == 0) {
+			found = 1;
+			break;
+		}
+	}
+
+	if (found) {
+		eq = strchr (coro_environ[entry], '=');
+		return (eq + 1);
+	}
+	return NULL;
+}
+
+/* all the following functions are banned and will result in an abort.
+ */
+
+int setenv(const char *name, const char *value, int overwrite)
+{
+	static int (*real_setenv)(const char *name, const char *value, int overwrite) = NULL;
+
+	if (!tsafe_inited || tsafe_disabled) {
+		if (real_setenv == NULL) {
+			real_setenv = _get_real_func_ ("setenv");
+		}
+		return real_setenv (name, value, overwrite);
+	}
+	assert (0);
+	return 0;
+}
+
+int unsetenv(const char *name)
+{
+	static int (*real_unsetenv)(const char *name) = NULL;
+
+	if (!tsafe_inited || tsafe_disabled) {
+		if (real_unsetenv == NULL) {
+			real_unsetenv = _get_real_func_ ("unsetenv");
+		}
+		return real_unsetenv (name);
+	}
+	assert (0);
+	return 0;
+}
+
+int putenv(char *string)
+{
+	static int (*real_putenv)(char *string) = NULL;
+
+	if (!tsafe_inited || tsafe_disabled) {
+		if (real_putenv == NULL) {
+			real_putenv = _get_real_func_ ("putenv");
+		}
+		return real_putenv (string);
+	}
+	assert (0);
+	return 0;
+}
+
+char *asctime(const struct tm *tm)
+{
+	static char * (*real_asctime)(const struct tm *tm) = NULL;
+
+	if (!tsafe_inited || tsafe_disabled) {
+		if (real_asctime == NULL) {
+			real_asctime = _get_real_func_ ("asctime");
+		}
+		return real_asctime (tm);
+	}
+	assert(0);
+	return NULL;
+}
+
+char *basename (CONST_ON_BSD char *path)
+{
+	static char *(*real_basename)(CONST_ON_BSD char *path) = NULL;
+	if (!tsafe_inited || tsafe_disabled) {
+		if (real_basename == NULL) {
+			real_basename = _get_real_func_ ("basename");
+		}
+		return real_basename (path);
+	}
+	assert(0);
+	return NULL;
+}
+
+char *catgets(nl_catd catalog, int set_number,
+	int message_number, const char *message)
+{
+	return NULL;
+}
+
+#ifdef HAVE_CRYPT
+char *crypt(const char *key, const char *salt)
+{
+	static char *(*real_crypt)(const char *key, const char *salt) = NULL;
+	if (!tsafe_inited || tsafe_disabled) {
+		if (real_crypt == NULL) {
+			real_crypt = _get_real_func_ ("crypt");
+		}
+		return real_crypt (salt);
+	}
+	assert(0);
+	return NULL;
+}
+#endif /* HAVE_CRYPT */
+
+char *ctermid(char *s)
+{
+	static char *(*real_ctermid)(char *s) = NULL;
+	if (!tsafe_inited || tsafe_disabled) {
+		if (real_ctermid == NULL) {
+			real_ctermid = _get_real_func_ ("ctermid");
+		}
+		return real_ctermid (s);
+	}
+	assert(0);
+	return NULL;
+}
+
+char *ctime(const time_t *timep)
+{
+	static char *(*real_ctime)(const time_t *timep) = NULL;
+	if (!tsafe_inited || tsafe_disabled) {
+		if (real_ctime == NULL) {
+			real_ctime = _get_real_func_ ("ctime");
+		}
+		return real_ctime (timep);
+	}
+	assert(0);
+	return NULL;
+}
+
+char *dirname(CONST_ON_BSD char *path)
+{
+	static char *(*real_dirname)(CONST_ON_BSD char *path) = NULL;
+
+	if (!tsafe_inited || tsafe_disabled) {
+		if (real_dirname == NULL) {
+			real_dirname = _get_real_func_ ("dirname");
+		}
+		return real_dirname (path);
+	}
+	assert(0);
+	return NULL;
+}
+
+double drand48(void)
+{
+	static double (*real_drand48)(void) = NULL;
+	if (!tsafe_inited || tsafe_disabled) {
+		if (real_drand48 == NULL) {
+			real_drand48 = _get_real_func_ ("drand48");
+		}
+		return real_drand48 ();
+	}
+	assert(0);
+	return 0;
+}
+
+#ifdef HAVE_ENCRYPT
+void encrypt(char block[64], int edflag)
+{
+	static void (*real_encrypt)(char block[64], int edflag) = NULL;
+	if (!tsafe_inited || tsafe_disabled) {
+		if (real_encrypt == NULL) {
+			real_encrypt = _get_real_func_ ("encrypt");
+		}
+		return real_encrypt (edflag);
+	}
+	assert(0);
+}
+#endif /* HAVE_ENCRYPT */
+
+#ifdef HAVE_ENDGRENT
+void endgrent(void)
+{
+	static void (*real_endgrent)(void) = NULL;
+	if (!tsafe_inited || tsafe_disabled) {
+		if (real_endgrent == NULL) {
+			real_endgrent = _get_real_func_ ("endgrent");
+		}
+		return real_endgrent ();
+	}
+	assert(0);
+}
+#endif /* HAVE_ENDGRENT */
+
+#ifdef HAVE_ENDPWENT
+void endpwent(void)
+{
+	static void (*real_endpwent)(void) = NULL;
+	if (!tsafe_inited || tsafe_disabled) {
+		if (real_endpwent == NULL) {
+			real_endpwent = _get_real_func_ ("endpwent");
+		}
+		return real_endpwent ();
+	}
+	assert(0);
+}
+#endif /* HAVE_ENDPWENT */
+
+#ifdef HAVE_GETDATE
+struct tm *getdate(const char *string)
+{
+	static struct tm *(*real_getdate)(const char *string) = NULL;
+	if (!tsafe_inited || tsafe_disabled) {
+		if (real_getdate == NULL) {
+			real_getdate = _get_real_func_ ("getdate");
+		}
+		return real_getdate (string);
+	}
+	assert(0);
+	return NULL;
+}
+#endif /* HAVE_GETDATE */
+
+struct group *getgrent(void)
+{
+	static struct group *(*real_getgrent)(void) = NULL;
+	if (!tsafe_inited || tsafe_disabled) {
+		if (real_getgrent == NULL) {
+			real_getgrent = _get_real_func_ ("getgrent");
+		}
+		return real_getgrent ();
+	}
+	assert(0);
+	return NULL;
+}
+
+struct group *getgrgid(gid_t gid)
+{
+	static struct group *(*real_getgrgid)(gid_t gid) = NULL;
+	if (!tsafe_inited || tsafe_disabled) {
+		if (real_getgrgid == NULL) {
+			real_getgrgid = _get_real_func_ ("getgrgid");
+		}
+		return real_getgrgid (gid);
+	}
+	assert(0);
+	return NULL;
+}
+
+struct group *getgrnam(const char *name)
+{
+	static struct group *(*real_getgrnam)(const char *name) = NULL;
+	if (!tsafe_inited || tsafe_disabled) {
+		if (real_getgrnam == NULL) {
+			real_getgrnam = _get_real_func_ ("getgrnam");
+		}
+		return real_getgrnam (name);
+	}
+	assert(0);
+	return NULL;
+}
+
+struct hostent *gethostent(void)
+{
+	static struct hostent *(*real_gethostent)(void) = NULL;
+	if (!tsafe_inited || tsafe_disabled) {
+		if (real_gethostent == NULL) {
+			real_gethostent = _get_real_func_ ("gethostent");
+		}
+		return real_gethostent ();
+	}
+	assert(0);
+	return NULL;
+}
+
+char *getlogin(void)
+{
+	static char *(*real_getlogin)(void) = NULL;
+	if (!tsafe_inited || tsafe_disabled) {
+		if (real_getlogin == NULL) {
+			real_getlogin = _get_real_func_ ("getlogin");
+		}
+		return real_getlogin ();
+	}
+	assert(0);
+	return NULL;
+}
+
+struct netent *getnetbyaddr(uint32_t net, int type)
+{
+	static struct netent *(*real_getnetbyaddr)(uint32_t net, int type) = NULL;
+	if (!tsafe_inited || tsafe_disabled) {
+		if (real_getnetbyaddr == NULL) {
+			real_getnetbyaddr = _get_real_func_ ("getnetbyaddr");
+		}
+		return real_getnetbyaddr (net, type);
+	}
+	assert(0);
+	return NULL;
+}
+
+struct netent *getnetbyname(const char *name)
+{
+	static struct netent *(*real_getnetbyname)(const char *name) = NULL;
+	if (!tsafe_inited || tsafe_disabled) {
+		if (real_getnetbyname == NULL) {
+			real_getnetbyname = _get_real_func_ ("getnetbyname");
+		}
+		return real_getnetbyname (name);
+	}
+	assert(0);
+	return NULL;
+}
+
+struct netent *getnetent(void)
+{
+	static struct netent *(*real_getnetent)(void) = NULL;
+	if (!tsafe_inited || tsafe_disabled) {
+		if (real_getnetent == NULL) {
+			real_getnetent = _get_real_func_ ("getnetent");
+		}
+		return real_getnetent ();
+	}
+	assert(0);
+	return NULL;
+}
+
+struct protoent *getprotobyname(const char *name)
+{
+	static struct protoent *(*real_getprotobyname)(const char *name) = NULL;
+	if (!tsafe_inited || tsafe_disabled) {
+		if (real_getprotobyname == NULL) {
+			real_getprotobyname = _get_real_func_ ("getprotobyname");
+		}
+		return real_getprotobyname (name);
+	}
+	assert(0);
+	return NULL;
+}
+
+struct protoent *getprotobynumber(int proto)
+{
+	static struct protoent *(*real_getprotobynumber)(int proto) = NULL;
+	if (!tsafe_inited || tsafe_disabled) {
+		if (real_getprotobynumber == NULL) {
+			real_getprotobynumber = _get_real_func_ ("getprotobynumber");
+		}
+		return real_getprotobynumber (proto);
+	}
+	assert(0);
+	return NULL;
+}
+
+struct protoent *getprotoent(void)
+{
+	static struct protoent *(*real_getprotoent)(void) = NULL;
+	if (!tsafe_inited || tsafe_disabled) {
+		if (real_getprotoent == NULL) {
+			real_getprotoent = _get_real_func_ ("getprotoent");
+		}
+		return real_getprotoent ();
+	}
+	assert(0);
+	return NULL;
+}
+
+struct passwd *getpwent(void)
+{
+	static struct passwd *(*real_getpwent)(void) = NULL;
+	if (!tsafe_inited || tsafe_disabled) {
+		if (real_getpwent == NULL) {
+			real_getpwent = _get_real_func_ ("getpwent");
+		}
+		return real_getpwent ();
+	}
+	assert(0);
+	return NULL;
+}
+
+struct passwd *getpwnam(const char *name)
+{
+	static struct passwd *(*real_getpwnam)(const char *name) = NULL;
+	if (!tsafe_inited || tsafe_disabled) {
+		if (real_getpwnam == NULL) {
+			real_getpwnam = _get_real_func_ ("getpwnam");
+		}
+		return real_getpwnam (name);
+	}
+	assert(0);
+	return NULL;
+}
+
+struct passwd *getpwuid(uid_t uid)
+{
+	static struct passwd *(*real_getpwuid)(uid_t uid) = NULL;
+	if (!tsafe_inited || tsafe_disabled) {
+		if (real_getpwuid == NULL) {
+			real_getpwuid = _get_real_func_ ("getpwuid");
+		}
+		return real_getpwuid (uid);
+	}
+	assert(0);
+	return NULL;
+}
+
+struct servent *getservent(void)
+{
+	static struct servent *(*real_getservent)(void) = NULL;
+	if (!tsafe_inited || tsafe_disabled) {
+		if (real_getservent == NULL) {
+			real_getservent = _get_real_func_ ("getservent");
+		}
+		return real_getservent ();
+	}
+	assert(0);
+	return NULL;
+}
+
+struct servent *getservbyname(const char *name, const char *proto)
+{
+	static struct servent *(*real_getservbyname)(const char *name, const char *proto) = NULL;
+	if (!tsafe_inited || tsafe_disabled) {
+		if (real_getservbyname == NULL) {
+			real_getservbyname = _get_real_func_ ("getservbyname");
+		}
+		return real_getservbyname (name, proto);
+	}
+	assert(0);
+	return NULL;
+}
+
+struct servent *getservbyport(int port, const char *proto)
+{
+	static struct servent *(*real_getservbyport)(int port, const char *proto) = NULL;
+	if (!tsafe_inited || tsafe_disabled) {
+		if (real_getservbyport == NULL) {
+			real_getservbyport = _get_real_func_ ("getservbyport");
+		}
+		return real_getservbyport (port, proto);
+	}
+	assert(0);
+	return NULL;
+}
+
+#ifdef HAVE_UTMPX_H
+struct utmpx *getutxent(void)
+{
+	static struct utmpx *(*real_getutxent)(void) = NULL;
+	if (!tsafe_inited || tsafe_disabled) {
+		if (real_getutxent == NULL) {
+			real_getutxent = _get_real_func_ ("getutxent");
+		}
+		return real_getutxent ();
+	}
+	assert(0);
+	return NULL;
+}
+
+struct utmpx *getutxid(const struct utmpx *a)
+{
+	static struct utmpx *(*real_getutxid)(const struct utmpx *a) = NULL;
+	if (!tsafe_inited || tsafe_disabled) {
+		if (real_getutxid == NULL) {
+			real_getutxid = _get_real_func_ ("getutxid");
+		}
+		return real_getutxid (a);
+	}
+	assert(0);
+	return NULL;
+}
+
+struct utmpx *getutxline(const struct utmpx *a)
+{
+	static struct utmpx *(*real_getutxline)(const struct utmpx *a) = NULL;
+	if (!tsafe_inited || tsafe_disabled) {
+		if (real_getutxline == NULL) {
+			real_getutxline = _get_real_func_ ("getutxline");
+		}
+		return real_getutxline (a);
+	}
+	assert(0);
+	return NULL;
+}
+#endif /* HAVE_UTMPX_H */
+
+struct tm *gmtime(const time_t *timep)
+{
+	static struct tm *(*real_gmtime)(const time_t *timep) = NULL;
+	if (!tsafe_inited || tsafe_disabled) {
+		if (real_gmtime == NULL) {
+			real_gmtime = _get_real_func_ ("gmtime");
+		}
+		return real_gmtime (timep);
+	}
+	assert(0);
+	return NULL;
+}
+
+int hcreate(size_t nel)
+{
+	static int (*real_hcreate)(size_t nel) = NULL;
+	if (!tsafe_inited || tsafe_disabled) {
+		if (real_hcreate == NULL) {
+			real_hcreate = _get_real_func_ ("hcreate");
+		}
+		return real_hcreate (nel);
+	}
+	assert(0);
+	return 0;
+}
+
+ENTRY *hsearch(ENTRY item, ACTION action)
+{
+	static ENTRY *(*real_hsearch)(ENTRY item, ACTION action) = NULL;
+	if (!tsafe_inited || tsafe_disabled) {
+		if (real_hsearch == NULL) {
+			real_hsearch = _get_real_func_ ("hsearch");
+		}
+		return real_hsearch (item, action);
+	}
+	assert(0);
+	return NULL;
+}
+
+void hdestroy(void)
+{
+	static void (*real_hdestroy)(void) = NULL;
+	if (!tsafe_inited || tsafe_disabled) {
+		if (real_hdestroy == NULL) {
+			real_hdestroy = _get_real_func_ ("hdestroy");
+		}
+		return real_hdestroy ();
+	}
+	assert(0);
+}
+
+char *inet_ntoa(struct in_addr in)
+{
+	static char *(*real_inet_ntoa)(struct in_addr in) = NULL;
+	if (!tsafe_inited || tsafe_disabled) {
+		if (real_inet_ntoa == NULL) {
+			real_inet_ntoa = _get_real_func_ ("inet_ntoa");
+		}
+		return real_inet_ntoa (in);
+	}
+	assert(0);
+	return NULL;
+}
+
+char *l64a(long value)
+{
+	static char *(*real_l64a)(long value) = NULL;
+	if (!tsafe_inited || tsafe_disabled) {
+		if (real_l64a == NULL) {
+			real_l64a = _get_real_func_ ("l64a");
+		}
+		return real_l64a (value);
+	}
+	assert(0);
+	return NULL;
+}
+
+double lgamma(double x)
+{
+	static double (*real_lgamma)(double x) = NULL;
+	if (!tsafe_inited || tsafe_disabled) {
+		if (real_lgamma == NULL) {
+			real_lgamma = _get_real_func_ ("lgamma");
+		}
+		return real_lgamma (x);
+	}
+	assert(0);
+	return 0;
+
+}
+
+float lgammaf(float x)
+{
+	static float (*real_lgammaf)(float x) = NULL;
+	if (!tsafe_inited || tsafe_disabled) {
+		if (real_lgammaf == NULL) {
+			real_lgammaf = _get_real_func_ ("lgammaf");
+		}
+		return real_lgammaf (x);
+	}
+	assert(0);
+	return 0;
+}
+
+#ifdef HAVE_LGAMMAL
+long double lgammal(long double x)
+{
+	static long double (*real_lgammal)(long double x) = NULL;
+	if (!tsafe_inited || tsafe_disabled) {
+		if (real_lgammal == NULL) {
+			real_lgammal = _get_real_func_ ("lgammal");
+		}
+		return real_lgammal (x);
+	}
+	assert(0);
+	return 0;
+}
+#endif /* HAVE_LGAMMAL */
+
+struct lconv *localeconv(void)
+{
+	static struct lconv *(*real_localeconv)(void) = NULL;
+	if (!tsafe_inited || tsafe_disabled) {
+		if (real_localeconv == NULL) {
+			real_localeconv = _get_real_func_ ("localeconv");
+		}
+		return real_localeconv ();
+	}
+	assert(0);
+	return NULL;
+}
+
+struct tm *localtime(const time_t *timep)
+{
+	static struct tm *(*real_localtime)(const time_t *timep) = NULL;
+	if (!tsafe_inited || tsafe_disabled) {
+		if (real_localtime == NULL) {
+			real_localtime = _get_real_func_ ("localtime");
+		}
+		return real_localtime (timep);
+	}
+	assert(0);
+	return NULL;
+}
+
+long int lrand48(void)
+{
+	static long int (*real_lrand48)(void) = NULL;
+	if (!tsafe_inited || tsafe_disabled) {
+		if (real_lrand48 == NULL) {
+			real_lrand48 = _get_real_func_ ("lrand48");
+		}
+		return real_lrand48 ();
+	}
+	assert(0);
+	return 0;
+}
+
+long int mrand48(void)
+{
+	static long int (*real_mrand48)(void) = NULL;
+	if (!tsafe_inited || tsafe_disabled) {
+		if (real_mrand48 == NULL) {
+			real_mrand48 = _get_real_func_ ("mrand48");
+		}
+		return real_mrand48 ();
+	}
+	assert(0);
+	return 0;
+}
+
+#ifdef HAVE_PUTUTXLINE
+struct utmpx *pututxline(const struct utmpx *a)
+{
+	static struct utmpx *(*real_pututxline)(const struct utmpx *a) = NULL;
+	if (!tsafe_inited || tsafe_disabled) {
+		if (real_pututxline == NULL) {
+			real_pututxline = _get_real_func_ ("pututxline");
+		}
+		return real_pututxline (a);
+	}
+	assert(0);
+	return NULL;
+}
+#endif /* HAVE_PUTUTXLINE */
+
+int rand(void)
+{
+	static int (*real_rand)(void) = NULL;
+	if (!tsafe_inited || tsafe_disabled) {
+		if (real_rand == NULL) {
+			real_rand = _get_real_func_ ("rand");
+		}
+		return real_rand ();
+	}
+	assert(0);
+	return 0;
+}
+
+
+struct dirent *readdir(DIR *dirp)
+{
+	static struct dirent *(*real_readdir)(DIR *dirp) = NULL;
+	if (!tsafe_inited || tsafe_disabled) {
+		if (real_readdir == NULL) {
+			real_readdir = _get_real_func_ ("readdir");
+		}
+		return real_readdir (dirp);
+	}
+	assert(0);
+	return NULL;
+}
+
+
+#ifdef COROSYNC_BSD
+int setgrent(void)
+{
+	static int (*real_setgrent)(void) = NULL;
+	if (!tsafe_inited || tsafe_disabled) {
+		if (real_setgrent == NULL) {
+			real_setgrent = _get_real_func_ ("setgrent");
+		}
+		return real_setgrent ();
+	}
+	assert(0);
+	return 0;
+}
+#else
+void setgrent(void)
+{
+	static void (*real_setgrent)(void) = NULL;
+	if (!tsafe_inited || tsafe_disabled) {
+		if (real_setgrent == NULL) {
+			real_setgrent = _get_real_func_ ("setgrent");
+		}
+		real_setgrent ();
+	}
+	assert(0);
+}
+#endif
+
+#ifdef HAVE_SETKEY
+void setkey(const char *key)
+{
+	static void (*real_setkey)(const char *key) = NULL;
+	if (!tsafe_inited || tsafe_disabled) {
+		if (real_setkey == NULL) {
+			real_setkey = _get_real_func_ ("setkey");
+		}
+		return real_setkey (key);
+	}
+	assert(0);
+}
+#endif /* HAVE_SETKEY */
+
+void setpwent(void)
+{
+	static void (*real_setpwent)(void) = NULL;
+	if (!tsafe_inited || tsafe_disabled) {
+		if (real_setpwent == NULL) {
+			real_setpwent = _get_real_func_ ("setpwent");
+		}
+		return real_setpwent ();
+	}
+	assert(0);
+}
+
+void setutxent(void)
+{
+	static void (*real_setutxent)(void) = NULL;
+	if (!tsafe_inited || tsafe_disabled) {
+		if (real_setutxent == NULL) {
+			real_setutxent = _get_real_func_ ("setutxent");
+		}
+		return real_setutxent ();
+	}
+	assert(0);
+}
+
+char *strerror(int errnum)
+{
+	static char *(*real_strerror)(int errnum) = NULL;
+	if (!tsafe_inited || tsafe_disabled) {
+		if (real_strerror == NULL) {
+			real_strerror = _get_real_func_ ("strerror");
+		}
+		return real_strerror (errnum);
+	}
+	assert(0);
+	return NULL;
+}
+
+#ifdef HAVE_STRSIGNAL
+char *strsignal(int sig)
+{
+	static char *(*real_strsignal)(int sig) = NULL;
+	if (!tsafe_inited || tsafe_disabled) {
+		if (real_strsignal == NULL) {
+			real_strsignal = _get_real_func_ ("strsignal");
+		}
+		return real_strsignal (sig);
+	}
+	assert(0);
+	return NULL;
+}
+#endif /* HAVE_STRSIGNAL */
+
+char *strtok(char *str, const char *delim)
+{
+	static char *(*real_strtok)(char *str, const char *delim) = NULL;
+	if (!tsafe_inited || tsafe_disabled) {
+		if (real_strtok == NULL) {
+			real_strtok = _get_real_func_ ("strtok");
+		}
+		return real_strtok (str, delim);
+	}
+	assert(0);
+	return NULL;
+}
+
+int system(const char *command)
+{
+	static int (*real_system)(const char *command) = NULL;
+	if (!tsafe_inited || tsafe_disabled) {
+		if (real_system == NULL) {
+			real_system = _get_real_func_ ("system");
+		}
+		return real_system (command);
+	}
+	assert(0);
+	return 0;
+}
+
+char *tmpnam(char *s)
+{
+	static char *(*real_tmpnam)(char *s) = NULL;
+	if (!tsafe_inited || tsafe_disabled) {
+		if (real_tmpnam == NULL) {
+			real_tmpnam = _get_real_func_ ("tmpnam");
+		}
+		return real_tmpnam (s);
+	}
+	assert(0);
+	return NULL;
+}
+
+char *ttyname(int fd)
+{
+	static char *(*real_ttyname)(int fd) = NULL;
+	if (!tsafe_inited || tsafe_disabled) {
+		if (real_ttyname == NULL) {
+			real_ttyname = _get_real_func_ ("ttyname");
+		}
+		return real_ttyname (fd);
+	}
+	assert(0);
+	return NULL;
+}
+
+
diff --git a/lib/tsafe/Makefile.am b/lib/tsafe/Makefile.am
deleted file mode 100644
index 8bb1bc6..0000000
--- a/lib/tsafe/Makefile.am
+++ /dev/null
@@ -1,95 +0,0 @@
-#
-# Copyright (c) 2010 Red Hat, Inc.
-#
-# Authors: Andrew Beekhof
-#	   Steven Dake (sdake@redhat.com)
-#	   Angus Salkeld <asaslkeld@redhat.com>
-#
-# This software licensed under BSD license, the text of which follows:
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are met:
-#
-# - Redistributions of source code must retain the above copyright notice,
-#   this list of conditions and the following disclaimer.
-# - 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.
-# - Neither the name of the MontaVista Software, Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
-
-MAINTAINERCLEANFILES    = Makefile.in
-
-AM_CFLAGS		= -fPIC
-
-AM_LDFLAGS		= -lpthread
-
-INCLUDES		= -I$(top_builddir)/include -I$(top_srcdir)/include
-
-lib_LIBRARIES		= libqbtsafe.a
-SHARED_LIBS		= $(lib_LIBRARIES:%.a=%.so.$(SONAME))
-SHARED_LIBS_SO		= $(lib_LIBRARIES:%.a=%.so)
-SHARED_LIBS_SO_TWO	= $(lib_LIBRARIES:%.a=%.so.$(SOMAJOR))
-
-libqbtsafe_a_SOURCES	= tsafe.c
-
-noinst_HEADERS		= libqbtsafe.versions 
-
-if BUILD_DARWIN
-
-lib%.so.$(SONAME): %.o
-	$(CC) $(DARWIN_OPTS) $^ -o $@
-	ln -sf lib$*.so.$(SONAME) lib$*.so
-	ln -sf lib$*.so.$(SONAME) lib$*.so.$(SOMAJOR)
-
-else
-
-if BUILD_SOLARIS
-
-lib%.so.$(SONAME): %.o
-	$(LD) $(SOLARIS_OPTS) -G $^ -o $@
-	ln -sf lib$*.so.$(SONAME) lib$*.so
-	ln -sf lib$*.so.$(SONAME) lib$*.so.$(SOMAJOR)
-
-else
-
-libqb%.so.$(SONAME): %.o
-	$(CC) -shared -o $@ \
-		-Wl,-soname=libqb$*.so.$(SOMAJOR) \
-		-Wl,-version-script=$(srcdir)/libqb$*.versions \
-		$^ $(LDFLAGS) $(AM_LDFLAGS)
-	ln -sf libqb$*.so.$(SONAME) libqb$*.so
-	ln -sf libqb$*.so.$(SONAME) libqb$*.so.$(SOMAJOR)
-
-endif
-
-endif
-
-all-local: $(SHARED_LIBS)
-	@echo Built shared libs
-
-install-exec-local:
-	$(INSTALL) -d $(DESTDIR)/$(libdir)
-	$(INSTALL) -m 755 $(SHARED_LIBS) $(DESTDIR)/$(libdir)
-	$(CP) -a $(SHARED_LIBS_SO) $(SHARED_LIBS_SO_TWO) $(DESTDIR)/$(libdir)
-
-uninstall-local:
-	cd $(DESTDIR)/$(libdir)/ && \
-		rm -f $(SHARED_LIBS) $(SHARED_LIBS_SO) $(SHARED_LIBS_SO_TWO)
-
-clean-local:
-	rm -f *.o *.a *.so* *.da *.bb *.bbg
-
diff --git a/lib/tsafe/libqbtsafe.versions b/lib/tsafe/libqbtsafe.versions
deleted file mode 100644
index 9b545b5..0000000
--- a/lib/tsafe/libqbtsafe.versions
+++ /dev/null
@@ -1,7 +0,0 @@
-QB_TSAFE_0.1 {
-	global:
-		qb_tsafe_init;
-		qb_tsafe_off;
-		qb_tsafe_on;
-	local: *;
-};
diff --git a/lib/tsafe/tsafe.c b/lib/tsafe/tsafe.c
deleted file mode 100644
index d803189..0000000
--- a/lib/tsafe/tsafe.c
+++ /dev/null
@@ -1,1082 +0,0 @@
-/*
- * Copyright (c) 2010 Red Hat, Inc.
- *
- * All rights reserved.
- *
- * Author: Angus Salkeld <asalkeld@redhat.com>
- *
- * This software licensed under BSD license, the text of which follows:
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * - Redistributions of source code must retain the above copyright notice,
- *   this list of conditions and the following disclaimer.
- * - 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.
- * - Neither the name of the MontaVista Software, Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
- */
-
-#include <config.h>
-
-#define _XOPEN_SOURCE 600
-#define _GNU_SOURCE 1
-
-#include <unistd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <math.h>
-
-#include <string.h>
-#include <assert.h>
-#include <time.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <grp.h>
-#include <pwd.h>
-#include <netdb.h>
-#include <nl_types.h>
-#include <libgen.h>
-#include <dlfcn.h>
-#ifdef HAVE_UTMPX_H
-#include <utmpx.h>
-#endif /* HAVE_UTMPX_H */
-#include <search.h>
-#include <locale.h>
-#include <dirent.h>
-#include <pthread.h>
-
-#include <qb/qbtsafe.h>
-
-#ifndef RTLD_NEXT
-#define RTLD_NEXT       ((void *) -1l)
-#endif /* !RTLD_NEXT */
-
-#ifdef QB_BSD
-#define CONST_ON_BSD const
-#else
-#define CONST_ON_BSD
-#endif /* QB_BSD */
-
-
-
-/*
- * The point of this file is to prevent people from using functions that are
- * known not to be thread safe (see man pthreads).
- */
-
-static int tsafe_disabled = 1;
-static int tsafe_inited = 0;
-static char **coro_environ;
-static void atfork_prepare (void);
-static void atfork_parent (void);
-static void atfork_child (void);
-
-#if defined(HAVE_PTHREAD_SPIN_LOCK)
-static pthread_spinlock_t tsafe_enabled_mutex;
-#else
-static pthread_mutex_t tsafe_enabled_mutex = PTHREAD_MUTEX_INITIALIZER;
-#endif
-
-
-void qb_tsafe_init (char **envp)
-{
-	int i;
-	int size = 1;
-
-	for (i = 0; envp[i] != NULL; i++) {
-		size++;
-	}
-	coro_environ = malloc (sizeof (char*) * size);
-	for (i = 0; envp[i] != NULL; i++) {
-		coro_environ[i] = strdup (envp[i]);
-	}
-	coro_environ[size-1] = NULL;
-
-#if defined(HAVE_PTHREAD_SPIN_LOCK)
-	pthread_spin_init (&tsafe_enabled_mutex, 0);
-#endif
-
-	pthread_atfork (atfork_prepare, atfork_parent, atfork_child);
-
-	tsafe_disabled = 1;
-	tsafe_inited = 1;
-}
-
-static void tsafe_lock (void)
-{
-#if defined(HAVE_PTHREAD_SPIN_LOCK)
-	pthread_spin_lock (&tsafe_enabled_mutex);
-#else
-	pthread_mutex_lock (&tsafe_enabled_mutex);
-#endif
-}
-
-static void tsafe_unlock (void)
-{
-#if defined(HAVE_PTHREAD_SPIN_LOCK)
-	pthread_spin_unlock (&tsafe_enabled_mutex);
-#else
-	pthread_mutex_unlock (&tsafe_enabled_mutex);
-#endif
-}
-
-void qb_tsafe_off (void)
-{
-	tsafe_lock ();
-	tsafe_disabled = 1;
-	tsafe_unlock ();
-}
-
-void qb_tsafe_on (void)
-{
-	tsafe_lock ();
-	tsafe_disabled = 0;
-	tsafe_unlock ();
-}
-
-static void atfork_prepare (void)
-{
-	tsafe_lock ();
-}
-
-static void atfork_parent (void)
-{
-	tsafe_unlock ();
-}
-
-static void atfork_child (void)
-{
-	if (tsafe_inited && !tsafe_disabled) {
-		tsafe_disabled = 1;
-	}
-	tsafe_unlock ();
-}
-
-static void* _get_real_func_(const char * func_name)
-{
-	void * func = NULL;
-#ifdef QB_BSD
-	static void *handle;
-	/*
-	 * On BSD we open the libc and retrive the pointer to "func_name".
-	 */
-	handle = dlopen("/usr/lib/libc.so", RTLD_LAZY);
-	func = dlsym (handle, func_name);
-#else
-	/*
-	 * On linux/Sun we can set func to next instance of "func_name",
-	 * which is the original "func_name"
-	 */
-	func = dlsym (RTLD_NEXT, func_name);
-#endif
-	return func;
-}
-
-#ifdef QB_LINUX
-/* we are implementing these functions only to know when to turn tsafe
- * on and off.
- */
-int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
-                   void *(*start_routine) (void *), void *arg)
-{
-	static int (*real_pthread_create)(pthread_t *thread, const pthread_attr_t *attr,
-                   void *(*start_routine) (void *), void *arg) = NULL;
-
-	if (tsafe_inited && tsafe_disabled) {
-		qb_tsafe_on ();
-	}
-
-	if (real_pthread_create == NULL) {
-		real_pthread_create = _get_real_func_ ("pthread_create");
-	}
-	return real_pthread_create (thread, attr, start_routine, arg);
-}
-
-#endif /* QB_LINUX */
-
-/*
- * we will allow this one as there doesn't seem to be any other option.
- * and only used in lcr
- * char *dlerror(void)
- * {
- * }
- */
-
-/* the following functions are needed so we are either banning them or
- * re-implementing them (depending on tsafe_on).
- */
-char *getenv(const char *name)
-{
-	static char* (*real_getenv)(const char *name) = NULL;
-	int entry;
-	int found = 0;
-	char *eq;
-	size_t name_len;
-
-	if (!tsafe_inited || tsafe_disabled) {
-		if (real_getenv == NULL) {
-			real_getenv = _get_real_func_ ("getenv");
-		}
-		return real_getenv (name);
-	}
-	for (entry = 0; coro_environ[entry] != NULL; entry++) {
-		eq = strchr (coro_environ[entry], '=');
-		name_len = eq - coro_environ[entry];
-
-		if (name_len == strlen (name) &&
-			strncmp(name, coro_environ[entry], name_len) == 0) {
-			found = 1;
-			break;
-		}
-	}
-
-	if (found) {
-		eq = strchr (coro_environ[entry], '=');
-		return (eq + 1);
-	}
-	return NULL;
-}
-
-/* all the following functions are banned and will result in an abort.
- */
-
-int setenv(const char *name, const char *value, int overwrite)
-{
-	static int (*real_setenv)(const char *name, const char *value, int overwrite) = NULL;
-
-	if (!tsafe_inited || tsafe_disabled) {
-		if (real_setenv == NULL) {
-			real_setenv = _get_real_func_ ("setenv");
-		}
-		return real_setenv (name, value, overwrite);
-	}
-	assert (0);
-	return 0;
-}
-
-int unsetenv(const char *name)
-{
-	static int (*real_unsetenv)(const char *name) = NULL;
-
-	if (!tsafe_inited || tsafe_disabled) {
-		if (real_unsetenv == NULL) {
-			real_unsetenv = _get_real_func_ ("unsetenv");
-		}
-		return real_unsetenv (name);
-	}
-	assert (0);
-	return 0;
-}
-
-int putenv(char *string)
-{
-	static int (*real_putenv)(char *string) = NULL;
-
-	if (!tsafe_inited || tsafe_disabled) {
-		if (real_putenv == NULL) {
-			real_putenv = _get_real_func_ ("putenv");
-		}
-		return real_putenv (string);
-	}
-	assert (0);
-	return 0;
-}
-
-char *asctime(const struct tm *tm)
-{
-	static char * (*real_asctime)(const struct tm *tm) = NULL;
-
-	if (!tsafe_inited || tsafe_disabled) {
-		if (real_asctime == NULL) {
-			real_asctime = _get_real_func_ ("asctime");
-		}
-		return real_asctime (tm);
-	}
-	assert(0);
-	return NULL;
-}
-
-char *basename (CONST_ON_BSD char *path)
-{
-	static char *(*real_basename)(CONST_ON_BSD char *path) = NULL;
-	if (!tsafe_inited || tsafe_disabled) {
-		if (real_basename == NULL) {
-			real_basename = _get_real_func_ ("basename");
-		}
-		return real_basename (path);
-	}
-	assert(0);
-	return NULL;
-}
-
-char *catgets(nl_catd catalog, int set_number,
-	int message_number, const char *message)
-{
-	return NULL;
-}
-
-#ifdef HAVE_CRYPT
-char *crypt(const char *key, const char *salt)
-{
-	static char *(*real_crypt)(const char *key, const char *salt) = NULL;
-	if (!tsafe_inited || tsafe_disabled) {
-		if (real_crypt == NULL) {
-			real_crypt = _get_real_func_ ("crypt");
-		}
-		return real_crypt (salt);
-	}
-	assert(0);
-	return NULL;
-}
-#endif /* HAVE_CRYPT */
-
-char *ctermid(char *s)
-{
-	static char *(*real_ctermid)(char *s) = NULL;
-	if (!tsafe_inited || tsafe_disabled) {
-		if (real_ctermid == NULL) {
-			real_ctermid = _get_real_func_ ("ctermid");
-		}
-		return real_ctermid (s);
-	}
-	assert(0);
-	return NULL;
-}
-
-char *ctime(const time_t *timep)
-{
-	static char *(*real_ctime)(const time_t *timep) = NULL;
-	if (!tsafe_inited || tsafe_disabled) {
-		if (real_ctime == NULL) {
-			real_ctime = _get_real_func_ ("ctime");
-		}
-		return real_ctime (timep);
-	}
-	assert(0);
-	return NULL;
-}
-
-char *dirname(CONST_ON_BSD char *path)
-{
-	static char *(*real_dirname)(CONST_ON_BSD char *path) = NULL;
-
-	if (!tsafe_inited || tsafe_disabled) {
-		if (real_dirname == NULL) {
-			real_dirname = _get_real_func_ ("dirname");
-		}
-		return real_dirname (path);
-	}
-	assert(0);
-	return NULL;
-}
-
-double drand48(void)
-{
-	static double (*real_drand48)(void) = NULL;
-	if (!tsafe_inited || tsafe_disabled) {
-		if (real_drand48 == NULL) {
-			real_drand48 = _get_real_func_ ("drand48");
-		}
-		return real_drand48 ();
-	}
-	assert(0);
-	return 0;
-}
-
-#ifdef HAVE_ENCRYPT
-void encrypt(char block[64], int edflag)
-{
-	static void (*real_encrypt)(char block[64], int edflag) = NULL;
-	if (!tsafe_inited || tsafe_disabled) {
-		if (real_encrypt == NULL) {
-			real_encrypt = _get_real_func_ ("encrypt");
-		}
-		return real_encrypt (edflag);
-	}
-	assert(0);
-}
-#endif /* HAVE_ENCRYPT */
-
-#ifdef HAVE_ENDGRENT
-void endgrent(void)
-{
-	static void (*real_endgrent)(void) = NULL;
-	if (!tsafe_inited || tsafe_disabled) {
-		if (real_endgrent == NULL) {
-			real_endgrent = _get_real_func_ ("endgrent");
-		}
-		return real_endgrent ();
-	}
-	assert(0);
-}
-#endif /* HAVE_ENDGRENT */
-
-#ifdef HAVE_ENDPWENT
-void endpwent(void)
-{
-	static void (*real_endpwent)(void) = NULL;
-	if (!tsafe_inited || tsafe_disabled) {
-		if (real_endpwent == NULL) {
-			real_endpwent = _get_real_func_ ("endpwent");
-		}
-		return real_endpwent ();
-	}
-	assert(0);
-}
-#endif /* HAVE_ENDPWENT */
-
-#ifdef HAVE_GETDATE
-struct tm *getdate(const char *string)
-{
-	static struct tm *(*real_getdate)(const char *string) = NULL;
-	if (!tsafe_inited || tsafe_disabled) {
-		if (real_getdate == NULL) {
-			real_getdate = _get_real_func_ ("getdate");
-		}
-		return real_getdate (string);
-	}
-	assert(0);
-	return NULL;
-}
-#endif /* HAVE_GETDATE */
-
-struct group *getgrent(void)
-{
-	static struct group *(*real_getgrent)(void) = NULL;
-	if (!tsafe_inited || tsafe_disabled) {
-		if (real_getgrent == NULL) {
-			real_getgrent = _get_real_func_ ("getgrent");
-		}
-		return real_getgrent ();
-	}
-	assert(0);
-	return NULL;
-}
-
-struct group *getgrgid(gid_t gid)
-{
-	static struct group *(*real_getgrgid)(gid_t gid) = NULL;
-	if (!tsafe_inited || tsafe_disabled) {
-		if (real_getgrgid == NULL) {
-			real_getgrgid = _get_real_func_ ("getgrgid");
-		}
-		return real_getgrgid (gid);
-	}
-	assert(0);
-	return NULL;
-}
-
-struct group *getgrnam(const char *name)
-{
-	static struct group *(*real_getgrnam)(const char *name) = NULL;
-	if (!tsafe_inited || tsafe_disabled) {
-		if (real_getgrnam == NULL) {
-			real_getgrnam = _get_real_func_ ("getgrnam");
-		}
-		return real_getgrnam (name);
-	}
-	assert(0);
-	return NULL;
-}
-
-struct hostent *gethostent(void)
-{
-	static struct hostent *(*real_gethostent)(void) = NULL;
-	if (!tsafe_inited || tsafe_disabled) {
-		if (real_gethostent == NULL) {
-			real_gethostent = _get_real_func_ ("gethostent");
-		}
-		return real_gethostent ();
-	}
-	assert(0);
-	return NULL;
-}
-
-char *getlogin(void)
-{
-	static char *(*real_getlogin)(void) = NULL;
-	if (!tsafe_inited || tsafe_disabled) {
-		if (real_getlogin == NULL) {
-			real_getlogin = _get_real_func_ ("getlogin");
-		}
-		return real_getlogin ();
-	}
-	assert(0);
-	return NULL;
-}
-
-struct netent *getnetbyaddr(uint32_t net, int type)
-{
-	static struct netent *(*real_getnetbyaddr)(uint32_t net, int type) = NULL;
-	if (!tsafe_inited || tsafe_disabled) {
-		if (real_getnetbyaddr == NULL) {
-			real_getnetbyaddr = _get_real_func_ ("getnetbyaddr");
-		}
-		return real_getnetbyaddr (net, type);
-	}
-	assert(0);
-	return NULL;
-}
-
-struct netent *getnetbyname(const char *name)
-{
-	static struct netent *(*real_getnetbyname)(const char *name) = NULL;
-	if (!tsafe_inited || tsafe_disabled) {
-		if (real_getnetbyname == NULL) {
-			real_getnetbyname = _get_real_func_ ("getnetbyname");
-		}
-		return real_getnetbyname (name);
-	}
-	assert(0);
-	return NULL;
-}
-
-struct netent *getnetent(void)
-{
-	static struct netent *(*real_getnetent)(void) = NULL;
-	if (!tsafe_inited || tsafe_disabled) {
-		if (real_getnetent == NULL) {
-			real_getnetent = _get_real_func_ ("getnetent");
-		}
-		return real_getnetent ();
-	}
-	assert(0);
-	return NULL;
-}
-
-struct protoent *getprotobyname(const char *name)
-{
-	static struct protoent *(*real_getprotobyname)(const char *name) = NULL;
-	if (!tsafe_inited || tsafe_disabled) {
-		if (real_getprotobyname == NULL) {
-			real_getprotobyname = _get_real_func_ ("getprotobyname");
-		}
-		return real_getprotobyname (name);
-	}
-	assert(0);
-	return NULL;
-}
-
-struct protoent *getprotobynumber(int proto)
-{
-	static struct protoent *(*real_getprotobynumber)(int proto) = NULL;
-	if (!tsafe_inited || tsafe_disabled) {
-		if (real_getprotobynumber == NULL) {
-			real_getprotobynumber = _get_real_func_ ("getprotobynumber");
-		}
-		return real_getprotobynumber (proto);
-	}
-	assert(0);
-	return NULL;
-}
-
-struct protoent *getprotoent(void)
-{
-	static struct protoent *(*real_getprotoent)(void) = NULL;
-	if (!tsafe_inited || tsafe_disabled) {
-		if (real_getprotoent == NULL) {
-			real_getprotoent = _get_real_func_ ("getprotoent");
-		}
-		return real_getprotoent ();
-	}
-	assert(0);
-	return NULL;
-}
-
-struct passwd *getpwent(void)
-{
-	static struct passwd *(*real_getpwent)(void) = NULL;
-	if (!tsafe_inited || tsafe_disabled) {
-		if (real_getpwent == NULL) {
-			real_getpwent = _get_real_func_ ("getpwent");
-		}
-		return real_getpwent ();
-	}
-	assert(0);
-	return NULL;
-}
-
-struct passwd *getpwnam(const char *name)
-{
-	static struct passwd *(*real_getpwnam)(const char *name) = NULL;
-	if (!tsafe_inited || tsafe_disabled) {
-		if (real_getpwnam == NULL) {
-			real_getpwnam = _get_real_func_ ("getpwnam");
-		}
-		return real_getpwnam (name);
-	}
-	assert(0);
-	return NULL;
-}
-
-struct passwd *getpwuid(uid_t uid)
-{
-	static struct passwd *(*real_getpwuid)(uid_t uid) = NULL;
-	if (!tsafe_inited || tsafe_disabled) {
-		if (real_getpwuid == NULL) {
-			real_getpwuid = _get_real_func_ ("getpwuid");
-		}
-		return real_getpwuid (uid);
-	}
-	assert(0);
-	return NULL;
-}
-
-struct servent *getservent(void)
-{
-	static struct servent *(*real_getservent)(void) = NULL;
-	if (!tsafe_inited || tsafe_disabled) {
-		if (real_getservent == NULL) {
-			real_getservent = _get_real_func_ ("getservent");
-		}
-		return real_getservent ();
-	}
-	assert(0);
-	return NULL;
-}
-
-struct servent *getservbyname(const char *name, const char *proto)
-{
-	static struct servent *(*real_getservbyname)(const char *name, const char *proto) = NULL;
-	if (!tsafe_inited || tsafe_disabled) {
-		if (real_getservbyname == NULL) {
-			real_getservbyname = _get_real_func_ ("getservbyname");
-		}
-		return real_getservbyname (name, proto);
-	}
-	assert(0);
-	return NULL;
-}
-
-struct servent *getservbyport(int port, const char *proto)
-{
-	static struct servent *(*real_getservbyport)(int port, const char *proto) = NULL;
-	if (!tsafe_inited || tsafe_disabled) {
-		if (real_getservbyport == NULL) {
-			real_getservbyport = _get_real_func_ ("getservbyport");
-		}
-		return real_getservbyport (port, proto);
-	}
-	assert(0);
-	return NULL;
-}
-
-#ifdef HAVE_UTMPX_H
-struct utmpx *getutxent(void)
-{
-	static struct utmpx *(*real_getutxent)(void) = NULL;
-	if (!tsafe_inited || tsafe_disabled) {
-		if (real_getutxent == NULL) {
-			real_getutxent = _get_real_func_ ("getutxent");
-		}
-		return real_getutxent ();
-	}
-	assert(0);
-	return NULL;
-}
-
-struct utmpx *getutxid(const struct utmpx *a)
-{
-	static struct utmpx *(*real_getutxid)(const struct utmpx *a) = NULL;
-	if (!tsafe_inited || tsafe_disabled) {
-		if (real_getutxid == NULL) {
-			real_getutxid = _get_real_func_ ("getutxid");
-		}
-		return real_getutxid (a);
-	}
-	assert(0);
-	return NULL;
-}
-
-struct utmpx *getutxline(const struct utmpx *a)
-{
-	static struct utmpx *(*real_getutxline)(const struct utmpx *a) = NULL;
-	if (!tsafe_inited || tsafe_disabled) {
-		if (real_getutxline == NULL) {
-			real_getutxline = _get_real_func_ ("getutxline");
-		}
-		return real_getutxline (a);
-	}
-	assert(0);
-	return NULL;
-}
-#endif /* HAVE_UTMPX_H */
-
-struct tm *gmtime(const time_t *timep)
-{
-	static struct tm *(*real_gmtime)(const time_t *timep) = NULL;
-	if (!tsafe_inited || tsafe_disabled) {
-		if (real_gmtime == NULL) {
-			real_gmtime = _get_real_func_ ("gmtime");
-		}
-		return real_gmtime (timep);
-	}
-	assert(0);
-	return NULL;
-}
-
-int hcreate(size_t nel)
-{
-	static int (*real_hcreate)(size_t nel) = NULL;
-	if (!tsafe_inited || tsafe_disabled) {
-		if (real_hcreate == NULL) {
-			real_hcreate = _get_real_func_ ("hcreate");
-		}
-		return real_hcreate (nel);
-	}
-	assert(0);
-	return 0;
-}
-
-ENTRY *hsearch(ENTRY item, ACTION action)
-{
-	static ENTRY *(*real_hsearch)(ENTRY item, ACTION action) = NULL;
-	if (!tsafe_inited || tsafe_disabled) {
-		if (real_hsearch == NULL) {
-			real_hsearch = _get_real_func_ ("hsearch");
-		}
-		return real_hsearch (item, action);
-	}
-	assert(0);
-	return NULL;
-}
-
-void hdestroy(void)
-{
-	static void (*real_hdestroy)(void) = NULL;
-	if (!tsafe_inited || tsafe_disabled) {
-		if (real_hdestroy == NULL) {
-			real_hdestroy = _get_real_func_ ("hdestroy");
-		}
-		return real_hdestroy ();
-	}
-	assert(0);
-}
-
-char *inet_ntoa(struct in_addr in)
-{
-	static char *(*real_inet_ntoa)(struct in_addr in) = NULL;
-	if (!tsafe_inited || tsafe_disabled) {
-		if (real_inet_ntoa == NULL) {
-			real_inet_ntoa = _get_real_func_ ("inet_ntoa");
-		}
-		return real_inet_ntoa (in);
-	}
-	assert(0);
-	return NULL;
-}
-
-char *l64a(long value)
-{
-	static char *(*real_l64a)(long value) = NULL;
-	if (!tsafe_inited || tsafe_disabled) {
-		if (real_l64a == NULL) {
-			real_l64a = _get_real_func_ ("l64a");
-		}
-		return real_l64a (value);
-	}
-	assert(0);
-	return NULL;
-}
-
-double lgamma(double x)
-{
-	static double (*real_lgamma)(double x) = NULL;
-	if (!tsafe_inited || tsafe_disabled) {
-		if (real_lgamma == NULL) {
-			real_lgamma = _get_real_func_ ("lgamma");
-		}
-		return real_lgamma (x);
-	}
-	assert(0);
-	return 0;
-
-}
-
-float lgammaf(float x)
-{
-	static float (*real_lgammaf)(float x) = NULL;
-	if (!tsafe_inited || tsafe_disabled) {
-		if (real_lgammaf == NULL) {
-			real_lgammaf = _get_real_func_ ("lgammaf");
-		}
-		return real_lgammaf (x);
-	}
-	assert(0);
-	return 0;
-}
-
-#ifdef HAVE_LGAMMAL
-long double lgammal(long double x)
-{
-	static long double (*real_lgammal)(long double x) = NULL;
-	if (!tsafe_inited || tsafe_disabled) {
-		if (real_lgammal == NULL) {
-			real_lgammal = _get_real_func_ ("lgammal");
-		}
-		return real_lgammal (x);
-	}
-	assert(0);
-	return 0;
-}
-#endif /* HAVE_LGAMMAL */
-
-struct lconv *localeconv(void)
-{
-	static struct lconv *(*real_localeconv)(void) = NULL;
-	if (!tsafe_inited || tsafe_disabled) {
-		if (real_localeconv == NULL) {
-			real_localeconv = _get_real_func_ ("localeconv");
-		}
-		return real_localeconv ();
-	}
-	assert(0);
-	return NULL;
-}
-
-struct tm *localtime(const time_t *timep)
-{
-	static struct tm *(*real_localtime)(const time_t *timep) = NULL;
-	if (!tsafe_inited || tsafe_disabled) {
-		if (real_localtime == NULL) {
-			real_localtime = _get_real_func_ ("localtime");
-		}
-		return real_localtime (timep);
-	}
-	assert(0);
-	return NULL;
-}
-
-long int lrand48(void)
-{
-	static long int (*real_lrand48)(void) = NULL;
-	if (!tsafe_inited || tsafe_disabled) {
-		if (real_lrand48 == NULL) {
-			real_lrand48 = _get_real_func_ ("lrand48");
-		}
-		return real_lrand48 ();
-	}
-	assert(0);
-	return 0;
-}
-
-long int mrand48(void)
-{
-	static long int (*real_mrand48)(void) = NULL;
-	if (!tsafe_inited || tsafe_disabled) {
-		if (real_mrand48 == NULL) {
-			real_mrand48 = _get_real_func_ ("mrand48");
-		}
-		return real_mrand48 ();
-	}
-	assert(0);
-	return 0;
-}
-
-#ifdef HAVE_PUTUTXLINE
-struct utmpx *pututxline(const struct utmpx *a)
-{
-	static struct utmpx *(*real_pututxline)(const struct utmpx *a) = NULL;
-	if (!tsafe_inited || tsafe_disabled) {
-		if (real_pututxline == NULL) {
-			real_pututxline = _get_real_func_ ("pututxline");
-		}
-		return real_pututxline (a);
-	}
-	assert(0);
-	return NULL;
-}
-#endif /* HAVE_PUTUTXLINE */
-
-int rand(void)
-{
-	static int (*real_rand)(void) = NULL;
-	if (!tsafe_inited || tsafe_disabled) {
-		if (real_rand == NULL) {
-			real_rand = _get_real_func_ ("rand");
-		}
-		return real_rand ();
-	}
-	assert(0);
-	return 0;
-}
-
-
-struct dirent *readdir(DIR *dirp)
-{
-	static struct dirent *(*real_readdir)(DIR *dirp) = NULL;
-	if (!tsafe_inited || tsafe_disabled) {
-		if (real_readdir == NULL) {
-			real_readdir = _get_real_func_ ("readdir");
-		}
-		return real_readdir (dirp);
-	}
-	assert(0);
-	return NULL;
-}
-
-
-#ifdef COROSYNC_BSD
-int setgrent(void)
-{
-	static int (*real_setgrent)(void) = NULL;
-	if (!tsafe_inited || tsafe_disabled) {
-		if (real_setgrent == NULL) {
-			real_setgrent = _get_real_func_ ("setgrent");
-		}
-		return real_setgrent ();
-	}
-	assert(0);
-	return 0;
-}
-#else
-void setgrent(void)
-{
-	static void (*real_setgrent)(void) = NULL;
-	if (!tsafe_inited || tsafe_disabled) {
-		if (real_setgrent == NULL) {
-			real_setgrent = _get_real_func_ ("setgrent");
-		}
-		real_setgrent ();
-	}
-	assert(0);
-}
-#endif
-
-#ifdef HAVE_SETKEY
-void setkey(const char *key)
-{
-	static void (*real_setkey)(const char *key) = NULL;
-	if (!tsafe_inited || tsafe_disabled) {
-		if (real_setkey == NULL) {
-			real_setkey = _get_real_func_ ("setkey");
-		}
-		return real_setkey (key);
-	}
-	assert(0);
-}
-#endif /* HAVE_SETKEY */
-
-void setpwent(void)
-{
-	static void (*real_setpwent)(void) = NULL;
-	if (!tsafe_inited || tsafe_disabled) {
-		if (real_setpwent == NULL) {
-			real_setpwent = _get_real_func_ ("setpwent");
-		}
-		return real_setpwent ();
-	}
-	assert(0);
-}
-
-void setutxent(void)
-{
-	static void (*real_setutxent)(void) = NULL;
-	if (!tsafe_inited || tsafe_disabled) {
-		if (real_setutxent == NULL) {
-			real_setutxent = _get_real_func_ ("setutxent");
-		}
-		return real_setutxent ();
-	}
-	assert(0);
-}
-
-char *strerror(int errnum)
-{
-	static char *(*real_strerror)(int errnum) = NULL;
-	if (!tsafe_inited || tsafe_disabled) {
-		if (real_strerror == NULL) {
-			real_strerror = _get_real_func_ ("strerror");
-		}
-		return real_strerror (errnum);
-	}
-	assert(0);
-	return NULL;
-}
-
-#ifdef HAVE_STRSIGNAL
-char *strsignal(int sig)
-{
-	static char *(*real_strsignal)(int sig) = NULL;
-	if (!tsafe_inited || tsafe_disabled) {
-		if (real_strsignal == NULL) {
-			real_strsignal = _get_real_func_ ("strsignal");
-		}
-		return real_strsignal (sig);
-	}
-	assert(0);
-	return NULL;
-}
-#endif /* HAVE_STRSIGNAL */
-
-char *strtok(char *str, const char *delim)
-{
-	static char *(*real_strtok)(char *str, const char *delim) = NULL;
-	if (!tsafe_inited || tsafe_disabled) {
-		if (real_strtok == NULL) {
-			real_strtok = _get_real_func_ ("strtok");
-		}
-		return real_strtok (str, delim);
-	}
-	assert(0);
-	return NULL;
-}
-
-int system(const char *command)
-{
-	static int (*real_system)(const char *command) = NULL;
-	if (!tsafe_inited || tsafe_disabled) {
-		if (real_system == NULL) {
-			real_system = _get_real_func_ ("system");
-		}
-		return real_system (command);
-	}
-	assert(0);
-	return 0;
-}
-
-char *tmpnam(char *s)
-{
-	static char *(*real_tmpnam)(char *s) = NULL;
-	if (!tsafe_inited || tsafe_disabled) {
-		if (real_tmpnam == NULL) {
-			real_tmpnam = _get_real_func_ ("tmpnam");
-		}
-		return real_tmpnam (s);
-	}
-	assert(0);
-	return NULL;
-}
-
-char *ttyname(int fd)
-{
-	static char *(*real_ttyname)(int fd) = NULL;
-	if (!tsafe_inited || tsafe_disabled) {
-		if (real_ttyname == NULL) {
-			real_ttyname = _get_real_func_ ("ttyname");
-		}
-		return real_ttyname (fd);
-	}
-	assert(0);
-	return NULL;
-}
-
-
diff --git a/lib/wthread.c b/lib/wthread.c
new file mode 100644
index 0000000..d16d08d
--- /dev/null
+++ b/lib/wthread.c
@@ -0,0 +1,215 @@
+/*
+ * Copyright (c) 2005 MontaVista Software, Inc.
+ * Copyright (c) 2006, 2009 Red Hat, Inc.
+ *
+ * All rights reserved.
+ *
+ * Author: Steven Dake (sdake@redhat.com)
+ *
+ * This software licensed under BSD license, the text of which follows:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - 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.
+ * - Neither the name of the MontaVista Software, Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
+ */
+
+/*
+ * Add work to a work group and have threads process the work
+ * Provide blocking for all work to complete
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <pthread.h>
+#include <errno.h>
+#include <qb/qbqueue.h>
+#include <qb/qbwthread.h>
+
+struct thread_data {
+	void *thread_state;
+	void *data;
+};
+
+struct qb_wthread_t {
+	struct qb_wthread_group *worker_thread_group;
+	pthread_mutex_t new_work_mutex;
+	pthread_cond_t new_work_cond;
+	pthread_cond_t cond;
+	pthread_mutex_t done_work_mutex;
+	pthread_cond_t done_work_cond;
+	pthread_t thread_id;
+	struct qb_queue queue;
+	void *thread_state;
+	struct thread_data thread_data;
+};
+
+static void *start_worker_thread (void *thread_data_in) {
+	struct thread_data *thread_data = (struct thread_data *)thread_data_in;
+	struct qb_wthread_t *worker_thread =
+		(struct qb_wthread_t *)thread_data->data;
+	void *data_for_worker_fn;
+
+	for (;;) {
+		pthread_mutex_lock (&worker_thread->new_work_mutex);
+		if (qb_queue_is_empty (&worker_thread->queue) == 1) {
+		pthread_cond_wait (&worker_thread->new_work_cond,
+			&worker_thread->new_work_mutex);
+		}
+
+		/*
+		 * We unlock then relock the new_work_mutex to allow the
+		 * worker function to execute and also allow new work to be
+		 * added to the work queue
+		 */
+		data_for_worker_fn = qb_queue_item_get (&worker_thread->queue);
+		pthread_mutex_unlock (&worker_thread->new_work_mutex);
+		worker_thread->worker_thread_group->worker_fn (worker_thread->thread_state, data_for_worker_fn);
+		pthread_mutex_lock (&worker_thread->new_work_mutex);
+		qb_queue_item_remove (&worker_thread->queue);
+		pthread_mutex_unlock (&worker_thread->new_work_mutex);
+		pthread_mutex_lock (&worker_thread->done_work_mutex);
+		if (qb_queue_is_empty (&worker_thread->queue) == 1) {
+			pthread_cond_signal (&worker_thread->done_work_cond);
+		}
+		pthread_mutex_unlock (&worker_thread->done_work_mutex);
+	}
+	return (NULL);
+}
+
+int qb_wthread_group_init (
+	struct qb_wthread_group *worker_thread_group,
+	int threads,
+	int items_max,
+	int item_size,
+	int thread_state_size,
+	void (*thread_state_constructor)(void *),
+	void (*worker_fn)(void *thread_state, void *work_item))
+{
+	int i;
+
+	worker_thread_group->threadcount = threads;
+	worker_thread_group->last_scheduled = 0;
+	worker_thread_group->worker_fn = worker_fn;
+	worker_thread_group->threads = malloc (sizeof (struct qb_wthread_t) *
+		threads);
+	if (worker_thread_group->threads == 0) {
+		return (-1);
+	}
+
+	for (i = 0; i < threads; i++) {
+		if (thread_state_size) {
+			worker_thread_group->threads[i].thread_state = malloc (thread_state_size);
+		} else {
+			worker_thread_group->threads[i].thread_state = NULL;
+		}
+		if (thread_state_constructor) {
+			thread_state_constructor (worker_thread_group->threads[i].thread_state);
+		}
+		worker_thread_group->threads[i].worker_thread_group = worker_thread_group;
+		pthread_mutex_init (&worker_thread_group->threads[i].new_work_mutex, NULL);
+		pthread_cond_init (&worker_thread_group->threads[i].new_work_cond, NULL);
+		pthread_mutex_init (&worker_thread_group->threads[i].done_work_mutex, NULL);
+		pthread_cond_init (&worker_thread_group->threads[i].done_work_cond, NULL);
+		qb_queue_init (&worker_thread_group->threads[i].queue, items_max,
+			item_size);
+
+		worker_thread_group->threads[i].thread_data.thread_state =
+			worker_thread_group->threads[i].thread_state;
+		worker_thread_group->threads[i].thread_data.data = &worker_thread_group->threads[i];
+		pthread_create (&worker_thread_group->threads[i].thread_id,
+			NULL, start_worker_thread, &worker_thread_group->threads[i].thread_data);
+	}
+	return (0);
+}
+
+int qb_wthread_group_work_add (
+	struct qb_wthread_group *worker_thread_group,
+	void *item)
+{
+	int schedule;
+
+	schedule = (worker_thread_group->last_scheduled + 1) % (worker_thread_group->threadcount);
+	worker_thread_group->last_scheduled = schedule;
+
+	pthread_mutex_lock (&worker_thread_group->threads[schedule].new_work_mutex);
+	if (qb_queue_is_full (&worker_thread_group->threads[schedule].queue)) {
+		pthread_mutex_unlock (&worker_thread_group->threads[schedule].new_work_mutex);
+		return (-1);
+	}
+	qb_queue_item_add (&worker_thread_group->threads[schedule].queue, item);
+	pthread_cond_signal (&worker_thread_group->threads[schedule].new_work_cond);
+	pthread_mutex_unlock (&worker_thread_group->threads[schedule].new_work_mutex);
+	return (0);
+}
+
+void qb_wthread_group_wait (
+	struct qb_wthread_group *worker_thread_group)
+{
+	int i;
+
+	for (i = 0; i < worker_thread_group->threadcount; i++) {
+		pthread_mutex_lock (&worker_thread_group->threads[i].done_work_mutex);
+		if (qb_queue_is_empty (&worker_thread_group->threads[i].queue) == 0) {
+			pthread_cond_wait (&worker_thread_group->threads[i].done_work_cond,
+				&worker_thread_group->threads[i].done_work_mutex);
+		}
+		pthread_mutex_unlock (&worker_thread_group->threads[i].done_work_mutex);
+	}
+}
+
+void qb_wthread_group_exit (
+	struct qb_wthread_group *worker_thread_group)
+{
+	int i;
+
+	for (i = 0; i < worker_thread_group->threadcount; i++) {
+		pthread_cancel (worker_thread_group->threads[i].thread_id);
+
+		/* Wait for worker thread to exit gracefully before destroying
+		 * mutexes and processing items in the queue etc.
+		 */
+		pthread_join (worker_thread_group->threads[i].thread_id, NULL);
+		pthread_mutex_destroy (&worker_thread_group->threads[i].new_work_mutex);
+		pthread_cond_destroy (&worker_thread_group->threads[i].new_work_cond);
+		pthread_mutex_destroy (&worker_thread_group->threads[i].done_work_mutex);
+		pthread_cond_destroy (&worker_thread_group->threads[i].done_work_cond);
+	}
+}
+
+void qb_wthread_group_atsegv (
+	struct qb_wthread_group *worker_thread_group)
+{
+	void *data_for_worker_fn;
+	struct qb_wthread_t *worker_thread;
+	unsigned int i;
+
+	for (i = 0; i < worker_thread_group->threadcount; i++) {
+		worker_thread = &worker_thread_group->threads[i];
+		while (qb_queue_is_empty (&worker_thread->queue) == 0) {
+			data_for_worker_fn = qb_queue_item_get (&worker_thread->queue);
+			worker_thread->worker_thread_group->worker_fn (worker_thread->thread_state, data_for_worker_fn);
+			qb_queue_item_remove (&worker_thread->queue);
+		}
+	}
+}
diff --git a/lib/wthread/Makefile.am b/lib/wthread/Makefile.am
deleted file mode 100644
index 211e847..0000000
--- a/lib/wthread/Makefile.am
+++ /dev/null
@@ -1,95 +0,0 @@
-#
-# Copyright (c) 2010 Red Hat, Inc.
-#
-# Authors: Andrew Beekhof
-#	   Steven Dake (sdake@redhat.com)
-#	   Angus Salkeld <asaslkeld@redhat.com>
-#
-# This software licensed under BSD license, the text of which follows:
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are met:
-#
-# - Redistributions of source code must retain the above copyright notice,
-#   this list of conditions and the following disclaimer.
-# - 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.
-# - Neither the name of the MontaVista Software, Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
-
-MAINTAINERCLEANFILES    = Makefile.in
-
-AM_CFLAGS		= -fPIC
-
-AM_LDFLAGS		= -lpthread
-
-INCLUDES		= -I$(top_builddir)/include -I$(top_srcdir)/include
-
-lib_LIBRARIES		= libqbwthread.a
-SHARED_LIBS		= $(lib_LIBRARIES:%.a=%.so.$(SONAME))
-SHARED_LIBS_SO		= $(lib_LIBRARIES:%.a=%.so)
-SHARED_LIBS_SO_TWO	= $(lib_LIBRARIES:%.a=%.so.$(SOMAJOR))
-
-libqbwthread_a_SOURCES	= wthread.c
-
-noinst_HEADERS		= libqbwthread.versions 
-
-if BUILD_DARWIN
-
-lib%.so.$(SONAME): %.o
-	$(CC) $(DARWIN_OPTS) $^ -o $@
-	ln -sf lib$*.so.$(SONAME) lib$*.so
-	ln -sf lib$*.so.$(SONAME) lib$*.so.$(SOMAJOR)
-
-else
-
-if BUILD_SOLARIS
-
-lib%.so.$(SONAME): %.o
-	$(LD) $(SOLARIS_OPTS) -G $^ -o $@
-	ln -sf lib$*.so.$(SONAME) lib$*.so
-	ln -sf lib$*.so.$(SONAME) lib$*.so.$(SOMAJOR)
-
-else
-
-libqb%.so.$(SONAME): %.o
-	$(CC) -shared -o $@ \
-		-Wl,-soname=libqb$*.so.$(SOMAJOR) \
-		-Wl,-version-script=$(srcdir)/libqb$*.versions \
-		$^ $(LDFLAGS) $(AM_LDFLAGS)
-	ln -sf libqb$*.so.$(SONAME) libqb$*.so
-	ln -sf libqb$*.so.$(SONAME) libqb$*.so.$(SOMAJOR)
-
-endif
-
-endif
-
-all-local: $(SHARED_LIBS)
-	@echo Built shared libs
-
-install-exec-local:
-	$(INSTALL) -d $(DESTDIR)/$(libdir)
-	$(INSTALL) -m 755 $(SHARED_LIBS) $(DESTDIR)/$(libdir)
-	$(CP) -a $(SHARED_LIBS_SO) $(SHARED_LIBS_SO_TWO) $(DESTDIR)/$(libdir)
-
-uninstall-local:
-	cd $(DESTDIR)/$(libdir)/ && \
-		rm -f $(SHARED_LIBS) $(SHARED_LIBS_SO) $(SHARED_LIBS_SO_TWO)
-
-clean-local:
-	rm -f *.o *.a *.so* *.da *.bb *.bbg
-
diff --git a/lib/wthread/libqbwthread.versions b/lib/wthread/libqbwthread.versions
deleted file mode 100644
index bfc672e..0000000
--- a/lib/wthread/libqbwthread.versions
+++ /dev/null
@@ -1,9 +0,0 @@
-QB_WTHREAD_0.1 {
-	global:
-		qb_wthread_group_init;
-		qb_wthread_group_work_add;
-		qb_wthread_group_wait;
-		qb_wthread_group_exit;
-		qb_wthread_group_atsegv;
-	local: *;
-};
diff --git a/lib/wthread/wthread.c b/lib/wthread/wthread.c
deleted file mode 100644
index d16d08d..0000000
--- a/lib/wthread/wthread.c
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
- * Copyright (c) 2005 MontaVista Software, Inc.
- * Copyright (c) 2006, 2009 Red Hat, Inc.
- *
- * All rights reserved.
- *
- * Author: Steven Dake (sdake@redhat.com)
- *
- * This software licensed under BSD license, the text of which follows:
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * - Redistributions of source code must retain the above copyright notice,
- *   this list of conditions and the following disclaimer.
- * - 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.
- * - Neither the name of the MontaVista Software, Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
- */
-
-/*
- * Add work to a work group and have threads process the work
- * Provide blocking for all work to complete
- */
-
-#include <config.h>
-
-#include <stdlib.h>
-#include <pthread.h>
-#include <errno.h>
-#include <qb/qbqueue.h>
-#include <qb/qbwthread.h>
-
-struct thread_data {
-	void *thread_state;
-	void *data;
-};
-
-struct qb_wthread_t {
-	struct qb_wthread_group *worker_thread_group;
-	pthread_mutex_t new_work_mutex;
-	pthread_cond_t new_work_cond;
-	pthread_cond_t cond;
-	pthread_mutex_t done_work_mutex;
-	pthread_cond_t done_work_cond;
-	pthread_t thread_id;
-	struct qb_queue queue;
-	void *thread_state;
-	struct thread_data thread_data;
-};
-
-static void *start_worker_thread (void *thread_data_in) {
-	struct thread_data *thread_data = (struct thread_data *)thread_data_in;
-	struct qb_wthread_t *worker_thread =
-		(struct qb_wthread_t *)thread_data->data;
-	void *data_for_worker_fn;
-
-	for (;;) {
-		pthread_mutex_lock (&worker_thread->new_work_mutex);
-		if (qb_queue_is_empty (&worker_thread->queue) == 1) {
-		pthread_cond_wait (&worker_thread->new_work_cond,
-			&worker_thread->new_work_mutex);
-		}
-
-		/*
-		 * We unlock then relock the new_work_mutex to allow the
-		 * worker function to execute and also allow new work to be
-		 * added to the work queue
-		 */
-		data_for_worker_fn = qb_queue_item_get (&worker_thread->queue);
-		pthread_mutex_unlock (&worker_thread->new_work_mutex);
-		worker_thread->worker_thread_group->worker_fn (worker_thread->thread_state, data_for_worker_fn);
-		pthread_mutex_lock (&worker_thread->new_work_mutex);
-		qb_queue_item_remove (&worker_thread->queue);
-		pthread_mutex_unlock (&worker_thread->new_work_mutex);
-		pthread_mutex_lock (&worker_thread->done_work_mutex);
-		if (qb_queue_is_empty (&worker_thread->queue) == 1) {
-			pthread_cond_signal (&worker_thread->done_work_cond);
-		}
-		pthread_mutex_unlock (&worker_thread->done_work_mutex);
-	}
-	return (NULL);
-}
-
-int qb_wthread_group_init (
-	struct qb_wthread_group *worker_thread_group,
-	int threads,
-	int items_max,
-	int item_size,
-	int thread_state_size,
-	void (*thread_state_constructor)(void *),
-	void (*worker_fn)(void *thread_state, void *work_item))
-{
-	int i;
-
-	worker_thread_group->threadcount = threads;
-	worker_thread_group->last_scheduled = 0;
-	worker_thread_group->worker_fn = worker_fn;
-	worker_thread_group->threads = malloc (sizeof (struct qb_wthread_t) *
-		threads);
-	if (worker_thread_group->threads == 0) {
-		return (-1);
-	}
-
-	for (i = 0; i < threads; i++) {
-		if (thread_state_size) {
-			worker_thread_group->threads[i].thread_state = malloc (thread_state_size);
-		} else {
-			worker_thread_group->threads[i].thread_state = NULL;
-		}
-		if (thread_state_constructor) {
-			thread_state_constructor (worker_thread_group->threads[i].thread_state);
-		}
-		worker_thread_group->threads[i].worker_thread_group = worker_thread_group;
-		pthread_mutex_init (&worker_thread_group->threads[i].new_work_mutex, NULL);
-		pthread_cond_init (&worker_thread_group->threads[i].new_work_cond, NULL);
-		pthread_mutex_init (&worker_thread_group->threads[i].done_work_mutex, NULL);
-		pthread_cond_init (&worker_thread_group->threads[i].done_work_cond, NULL);
-		qb_queue_init (&worker_thread_group->threads[i].queue, items_max,
-			item_size);
-
-		worker_thread_group->threads[i].thread_data.thread_state =
-			worker_thread_group->threads[i].thread_state;
-		worker_thread_group->threads[i].thread_data.data = &worker_thread_group->threads[i];
-		pthread_create (&worker_thread_group->threads[i].thread_id,
-			NULL, start_worker_thread, &worker_thread_group->threads[i].thread_data);
-	}
-	return (0);
-}
-
-int qb_wthread_group_work_add (
-	struct qb_wthread_group *worker_thread_group,
-	void *item)
-{
-	int schedule;
-
-	schedule = (worker_thread_group->last_scheduled + 1) % (worker_thread_group->threadcount);
-	worker_thread_group->last_scheduled = schedule;
-
-	pthread_mutex_lock (&worker_thread_group->threads[schedule].new_work_mutex);
-	if (qb_queue_is_full (&worker_thread_group->threads[schedule].queue)) {
-		pthread_mutex_unlock (&worker_thread_group->threads[schedule].new_work_mutex);
-		return (-1);
-	}
-	qb_queue_item_add (&worker_thread_group->threads[schedule].queue, item);
-	pthread_cond_signal (&worker_thread_group->threads[schedule].new_work_cond);
-	pthread_mutex_unlock (&worker_thread_group->threads[schedule].new_work_mutex);
-	return (0);
-}
-
-void qb_wthread_group_wait (
-	struct qb_wthread_group *worker_thread_group)
-{
-	int i;
-
-	for (i = 0; i < worker_thread_group->threadcount; i++) {
-		pthread_mutex_lock (&worker_thread_group->threads[i].done_work_mutex);
-		if (qb_queue_is_empty (&worker_thread_group->threads[i].queue) == 0) {
-			pthread_cond_wait (&worker_thread_group->threads[i].done_work_cond,
-				&worker_thread_group->threads[i].done_work_mutex);
-		}
-		pthread_mutex_unlock (&worker_thread_group->threads[i].done_work_mutex);
-	}
-}
-
-void qb_wthread_group_exit (
-	struct qb_wthread_group *worker_thread_group)
-{
-	int i;
-
-	for (i = 0; i < worker_thread_group->threadcount; i++) {
-		pthread_cancel (worker_thread_group->threads[i].thread_id);
-
-		/* Wait for worker thread to exit gracefully before destroying
-		 * mutexes and processing items in the queue etc.
-		 */
-		pthread_join (worker_thread_group->threads[i].thread_id, NULL);
-		pthread_mutex_destroy (&worker_thread_group->threads[i].new_work_mutex);
-		pthread_cond_destroy (&worker_thread_group->threads[i].new_work_cond);
-		pthread_mutex_destroy (&worker_thread_group->threads[i].done_work_mutex);
-		pthread_cond_destroy (&worker_thread_group->threads[i].done_work_cond);
-	}
-}
-
-void qb_wthread_group_atsegv (
-	struct qb_wthread_group *worker_thread_group)
-{
-	void *data_for_worker_fn;
-	struct qb_wthread_t *worker_thread;
-	unsigned int i;
-
-	for (i = 0; i < worker_thread_group->threadcount; i++) {
-		worker_thread = &worker_thread_group->threads[i];
-		while (qb_queue_is_empty (&worker_thread->queue) == 0) {
-			data_for_worker_fn = qb_queue_item_get (&worker_thread->queue);
-			worker_thread->worker_thread_group->worker_fn (worker_thread->thread_state, data_for_worker_fn);
-			qb_queue_item_remove (&worker_thread->queue);
-		}
-	}
-}
diff --git a/libqb.spec.in b/libqb.spec.in
new file mode 100644
index 0000000..ae299cf
--- /dev/null
+++ b/libqb.spec.in
@@ -0,0 +1,107 @@
+%global alphatag @alphatag@
+
+Name: libqb
+Summary: The Quarterback Client Server Developer Library
+Version: @version@
+Release: 1%{?alphatag:.%{alphatag}}%{?dist}
+License: BSD
+Group: System Environment/Libraries
+URL: http://www.openais.org
+Source0: http://developer.osdl.org/dev/openais/downloads/%{name}-%{version}/%{name}-%{version}.tar.gz
+
+BuildRequires: autoconf automake
+
+BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX)
+
+%prep
+%setup -q -n %{name}-%{version}
+
+./autogen.sh
+
+%{configure}
+
+%build
+make %{_smp_mflags}
+
+%install
+rm -rf %{buildroot}
+
+make install DESTDIR=%{buildroot}
+
+## tree fixup
+# drop static libs
+rm -f %{buildroot}%{_libdir}/*.a
+# drop docs and html docs for now
+rm -rf %{buildroot}%{_docdir}/*
+
+%clean
+rm -rf %{buildroot}
+
+%description
+This package contains libqb libraries.
+
+%files -n libqb
+%defattr(-,root,root,-)
+%doc LICENSE
+%{_libdir}/libqbtsafe.so.*
+%{_libdir}/libqbpoll.so.*
+%{_libdir}/libqbtimer.so.*
+%{_libdir}/libqbipcc.so.*
+%{_libdir}/libqbipcs.so.*
+%{_libdir}/libqbwthread.so.*
+%{_libdir}/libqblogsys.so.*
+%{_libdir}/libqbhash.so.*
+
+%post -n libqb -p /sbin/ldconfig
+
+%postun -n libqb -p /sbin/ldconfig
+
+%package -n libqb-devel
+Summary: The Quarterback Development Kit
+Group: Development/Libraries
+Requires: libqb = %{version}-%{release}
+Requires: pkgconfig
+Provides: libqb-devel = %{version}
+
+%description -n libqb-devel
+This package contains include files and man pages used to develop using
+The Quarterback APIs.
+
+%files -n libqb-devel
+%defattr(-,root,root,-)
+%doc LICENSE README
+%dir %{_includedir}/qb/
+%{_libdir}/libqbtsafe.so
+%{_libdir}/libqbpoll.so
+%{_libdir}/libqbtimer.so
+%{_libdir}/libqbipcc.so
+%{_libdir}/libqbipcs.so
+%{_libdir}/libqbwthread.so
+%{_libdir}/libqbhash.so
+%{_libdir}/libqblogsys.so
+%{_libdir}/libqbtsafe.la
+%{_libdir}/libqbpoll.la
+%{_libdir}/libqbtimer.la
+%{_libdir}/libqbipcc.la
+%{_libdir}/libqbipcs.la
+%{_libdir}/libqbwthread.la
+%{_libdir}/libqbhash.la
+%{_libdir}/libqblogsys.la
+%{_includedir}/qb/qbtsafe.h
+%{_includedir}/qb/qbpoll.h
+%{_includedir}/qb/qbhdb.h
+%{_includedir}/qb/qblist.h
+%{_includedir}/qb/qbtimer.h
+%{_includedir}/qb/qbplugin.h
+%{_includedir}/qb/qbplugin_comp.h
+%{_includedir}/qb/qbipcc.h
+%{_includedir}/qb/qbipcs.h
+%{_includedir}/qb/qbqueue.h
+%{_includedir}/qb/qbwthread.h
+%{_includedir}/qb/qblogsys.h
+%{_includedir}/qb/qbhash.h
+%{_mandir}/man3/qb*3*
+
+%changelog
+* @date@ Autotools generated version <nobody@nowhere.org> - @version@-1.@alphatag@
+- Autotools generated version
diff --git a/quarterback.spec.in b/quarterback.spec.in
deleted file mode 100644
index 046d815..0000000
--- a/quarterback.spec.in
+++ /dev/null
@@ -1,99 +0,0 @@
-%global alphatag @alphatag@
-
-Name: quarterback
-Summary: The Quarterback Client Server Developer Library
-Version: @version@
-Release: 1%{?alphatag:.%{alphatag}}%{?dist}
-License: BSD
-Group: System Environment/Libraries
-URL: http://www.openais.org
-Source0: http://developer.osdl.org/dev/openais/downloads/%{name}-%{version}/%{name}-%{version}.tar.gz
-
-BuildRequires: autoconf automake
-
-BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX)
-
-%prep
-%setup -q -n %{name}-%{version}
-
-./autogen.sh
-
-%{configure}
-
-%build
-make %{_smp_mflags}
-
-%install
-rm -rf %{buildroot}
-
-make install DESTDIR=%{buildroot}
-
-## tree fixup
-# drop static libs
-rm -f %{buildroot}%{_libdir}/*.a
-# drop docs and html docs for now
-rm -rf %{buildroot}%{_docdir}/*
-
-%clean
-rm -rf %{buildroot}
-
-%description
-This package contains quarterback libraries.
-
-%files -n quarterback
-%defattr(-,root,root,-)
-%doc LICENSE
-%{_libdir}/libqbtsafe.so.*
-%{_libdir}/libqbpoll.so.*
-%{_libdir}/libqbtimer.so.*
-%{_libdir}/libqbipcc.so.*
-%{_libdir}/libqbipcs.so.*
-%{_libdir}/libqbwthread.so.*
-%{_libdir}/libqblogsys.so.*
-%{_libdir}/libqbhash.so.*
-
-%post -n quarterback -p /sbin/ldconfig
-
-%postun -n quarterback -p /sbin/ldconfig
-
-%package -n quarterback-devel
-Summary: The Quarterback Development Kit
-Group: Development/Libraries
-Requires: quarterback = %{version}-%{release}
-Requires: pkgconfig
-Provides: quarterback-devel = %{version}
-
-%description -n quarterback-devel
-This package contains include files and man pages used to develop using
-The Quarterback APIs.
-
-%files -n quarterback-devel
-%defattr(-,root,root,-)
-%doc LICENSE README
-%dir %{_includedir}/qb/
-%{_libdir}/libqbtsafe.so
-%{_libdir}/libqbpoll.so
-%{_libdir}/libqbtimer.so
-%{_libdir}/libqbipcc.so
-%{_libdir}/libqbipcs.so
-%{_libdir}/libqbwthread.so
-%{_libdir}/libqbhash.so
-%{_libdir}/libqblogsys.so
-%{_includedir}/qb/qbtsafe.h
-%{_includedir}/qb/qbpoll.h
-%{_includedir}/qb/qbhdb.h
-%{_includedir}/qb/qblist.h
-%{_includedir}/qb/qbtimer.h
-%{_includedir}/qb/qbplugin.h
-%{_includedir}/qb/qbplugin_comp.h
-%{_includedir}/qb/qbipcc.h
-%{_includedir}/qb/qbipcs.h
-%{_includedir}/qb/qbqueue.h
-%{_includedir}/qb/qbwthread.h
-%{_includedir}/qb/qblogsys.h
-%{_includedir}/qb/qbhash.h
-%{_mandir}/man3/qb*3*
-
-%changelog
-* @date@ Autotools generated version <nobody@nowhere.org> - @version@-1.@alphatag@
-- Autotools generated version
diff --git a/tests/.gitignore b/tests/.gitignore
index b27b9da..da2110e 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -1 +1,2 @@
+check_plugin
 check_hash
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 28223fb..b269d88 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -29,13 +29,30 @@
 # THE POSSIBILITY OF SUCH DAMAGE.
 
 if HAVE_CHECK
-TESTS = check_hash
 
-check_PROGRAMS = check_hash
+TESTS = check_hash check_plugin
+
+check_PROGRAMS = check_hash check_plugin
 
 check_hash_SOURCES = check_hash.c $(top_builddir)/include/qb/qbhash.h
 check_hash_CFLAGS = @CHECK_CFLAGS@ -I$(top_srcdir)/include
-check_hash_LDADD = $(top_builddir)/lib/hash/libqbhash.a @CHECK_LIBS@
+check_hash_LDADD = $(top_builddir)/lib/libqbhash.la @CHECK_LIBS@
+
+check_plugin_SOURCES = check_plugin.c
+check_plugin_CFLAGS = @CHECK_CFLAGS@ -I$(top_srcdir)/include
+check_plugin_LDADD = $(top_builddir)/lib/libqbplugin.a @CHECK_LIBS@
+
+noinst_libdir = $(shell pwd)/$(top_builddir)/tests
+
+noinst_lib_LTLIBRARIES = libtest_a.la libtest_b.la
+
+libtest_a_la_CPPFLAGS	= -I$(top_builddir)/include -I$(top_srcdir)/include
+libtest_a_la_LDFLAGS	= -version-info 0:0:0
+libtest_a_la_SOURCES	= libtest_a.c
+
+libtest_b_la_CPPFLAGS	= -I$(top_builddir)/include -I$(top_srcdir)/include
+libtest_b_la_LDFLAGS	= -version-info 0:0:0
+libtest_b_la_SOURCES	= libtest_b.c
 
 endif
 
diff --git a/tests/check_plugin.c b/tests/check_plugin.c
new file mode 100644
index 0000000..327adc9
--- /dev/null
+++ b/tests/check_plugin.c
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2006 Steven Dake (sdake@redhat.com)
+ *
+ * This software licensed under BSD license, the text of which follows:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - 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.
+ * - Neither the name of the MontaVista Software, Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
+ */
+
+#include <config.h>
+
+#include <check.h>
+#include <assert.h>
+#include <unistd.h>
+#include <qb/qbhdb.h>
+#include <qb/qbplugin.h>
+
+struct iface {
+	void (*func1) (void);
+	void (*func2) (void);
+	void (*func3) (void);
+};
+
+START_TEST (test_plugin)
+{
+	qb_hdb_handle_t a_ifact_handle_ver0;
+	qb_hdb_handle_t b_ifact_handle_ver0;
+	struct iface *a_iface_ver0;
+	struct iface *a_iface_ver1;
+	void *a_iface_ver0_p;
+	void *a_iface_ver1_p;
+
+	qb_hdb_handle_t a_ifact_handle_ver1;
+	qb_hdb_handle_t b_ifact_handle_ver1;
+	struct iface *b_iface_ver0;
+	struct iface *b_iface_ver1;
+	void *b_iface_ver0_p;
+	void *b_iface_ver1_p;
+
+	unsigned int res;
+
+	setenv ("LD_LIBRARY_PATH", ".libs", 1);
+	/*
+	 * Reference version 0 and 1 of A and B interfaces
+	 */
+	res = plugin_ifact_reference (
+		&a_ifact_handle_ver0,
+		"A_iface1",
+		0, /* version 0 */
+		&a_iface_ver0_p,
+		(void *)0xaaaa0000);
+	ck_assert_int_eq (res, 0);
+
+	a_iface_ver0 = (struct iface *)a_iface_ver0_p;
+
+	res = plugin_ifact_reference (
+		&b_ifact_handle_ver0,
+		"B_iface1",
+		0, /* version 0 */
+		&b_iface_ver0_p,
+		(void *)0xbbbb0000);
+	ck_assert_int_eq (res, 0);
+
+	b_iface_ver0 = (struct iface *)b_iface_ver0_p;
+
+	res = plugin_ifact_reference (
+		&a_ifact_handle_ver1,
+		"A_iface1",
+		1, /* version 1 */
+		&a_iface_ver1_p,
+		(void *)0xaaaa1111);
+	ck_assert_int_eq (res, 0);
+
+	a_iface_ver1 = (struct iface *)a_iface_ver1_p;
+
+	res = plugin_ifact_reference (
+		&b_ifact_handle_ver1,
+		"B_iface1",
+		1, /* version 1 */
+		&b_iface_ver1_p,
+		(void *)0xbbbb1111);
+	ck_assert_int_eq (res, 0);
+
+	b_iface_ver1 = (struct iface *)b_iface_ver1_p;
+
+	a_iface_ver0->func1();
+	a_iface_ver0->func2();
+	a_iface_ver0->func3();
+
+	plugin_ifact_release (a_ifact_handle_ver0);
+
+	a_iface_ver1->func1();
+	a_iface_ver1->func2();
+	a_iface_ver1->func3();
+
+	plugin_ifact_release (a_ifact_handle_ver1);
+
+	b_iface_ver0->func1();
+	b_iface_ver0->func2();
+	b_iface_ver0->func3();
+
+	plugin_ifact_release (b_ifact_handle_ver0);
+
+	b_iface_ver1->func1();
+	b_iface_ver1->func2();
+	b_iface_ver1->func3();
+
+	plugin_ifact_release (b_ifact_handle_ver1);
+}
+END_TEST
+
+static Suite *hash_suite (void)
+{
+	TCase *tc_plugin;
+	Suite *s = suite_create ("plugin");
+	tc_plugin = tcase_create ("load");
+	tcase_add_test (tc_plugin, test_plugin);
+	suite_add_tcase (s, tc_plugin);
+
+	return s;
+}
+
+int main (void)
+{
+	int number_failed;
+
+	Suite *s = hash_suite ();
+	SRunner *sr = srunner_create (s);
+	srunner_run_all (sr, CK_NORMAL);
+	number_failed = srunner_ntests_failed (sr);
+	srunner_free (sr);
+	return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
+}
+
diff --git a/tests/libtest_a.c b/tests/libtest_a.c
new file mode 100644
index 0000000..f0d5f8b
--- /dev/null
+++ b/tests/libtest_a.c
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2006 Steven Dake (sdake@redhat.com)
+ *
+ * This software licensed under BSD license, the text of which follows:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - 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.
+ * - Neither the name of the MontaVista Software, Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <qb/qbplugin_comp.h>
+
+/*
+ * Version 0 of the interface
+ */
+static int iface1_constructor (void *context);
+
+static void iface1_destructor (void *context);
+
+static void iface1_func1 (void);
+
+static void iface1_func2 (void);
+
+static void iface1_func3 (void);
+
+/*
+ * Version 1 of the interface
+ */
+static int iface1_ver1_constructor (void *context);
+
+static void iface1_ver1_destructor (void *context);
+
+static void iface1_ver1_func1 (void);
+
+static void iface1_ver1_func2 (void);
+
+static void iface1_ver1_func3 (void);
+
+struct iface_list {
+	void (*iface1_func1)(void);
+	void (*iface1_func2)(void);
+	void (*iface1_func3)(void);
+};
+
+struct iface_ver1_list {
+	void (*iface1_ver1_func1)(void);
+	void (*iface1_ver1_func2)(void);
+	void (*iface1_ver1_func3)(void);
+};
+
+static struct iface_list iface_list = {
+	.iface1_func1		= iface1_func1,
+	.iface1_func2		= iface1_func2,
+	.iface1_func3		= iface1_func3,
+};
+
+static struct iface_list iface_ver1_list = {
+	.iface1_func1		= iface1_ver1_func1,
+	.iface1_func2		= iface1_ver1_func2,
+	.iface1_func3		= iface1_ver1_func3,
+};
+
+static struct plugin_iface iface1[2] = {
+	/* version 0 */
+	{
+		.name			= "A_iface1",
+		.version		= 0,
+		.versions_replace	= 0,
+		.versions_replace_count	= 0,
+		.dependencies		= 0,
+		.dependency_count	= 0,
+		.constructor		= iface1_constructor,
+		.destructor		= iface1_destructor,
+		.interfaces		= NULL
+	},
+	/* version 1 */
+	{
+		.name			= "A_iface1",
+		.version		= 1,
+		.versions_replace	= 0,
+		.versions_replace_count	= 0,
+		.dependencies		= 0,
+		.dependency_count	= 0,
+		.constructor		= iface1_ver1_constructor,
+		.destructor		= iface1_ver1_destructor,
+		.interfaces		= NULL
+	}
+};
+
+static struct plugin_comp test_comp = {
+	.iface_count 		= 2,
+	.ifaces 		= iface1
+};
+
+static int iface1_constructor (void *context)
+{
+	printf ("A - version 0 constructor context %p\n", context);
+	return (0);
+}
+
+static void iface1_destructor (void *context)
+{
+	printf ("A - version 0 destructor context %p\n", context);
+}
+static void iface1_func1 (void) {
+	printf ("A - version 0 func1\n");
+}
+
+static void iface1_func2 (void) {
+	printf ("A - version 0 func2\n");
+}
+
+static void iface1_func3 (void) {
+	printf ("A - version 0 func3\n");
+}
+
+static int iface1_ver1_constructor (void *context)
+{
+	printf ("A - version 1 constructor context %p\n", context);
+	return (0);
+}
+
+static void iface1_ver1_destructor (void *context)
+{
+	printf ("A - version 1 destructor context %p\n", context);
+}
+static void iface1_ver1_func1 (void) {
+	printf ("A - version 1 func1\n");
+}
+
+static void iface1_ver1_func2 (void) {
+	printf ("A - version 1 func2\n");
+}
+
+static void iface1_ver1_func3 (void) {
+	printf ("A - version 1 func3\n");
+}
+
+__attribute__ ((constructor)) static void register_this_component (void) {
+	plugin_interfaces_set (&iface1[0], &iface_list);
+	plugin_interfaces_set (&iface1[1], &iface_ver1_list);
+	plugin_component_register (&test_comp);
+}
diff --git a/tests/libtest_b.c b/tests/libtest_b.c
new file mode 100644
index 0000000..77b128a
--- /dev/null
+++ b/tests/libtest_b.c
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 2006 Steven Dake (sdake@redhat.com)
+ *
+ * This software licensed under BSD license, the text of which follows:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - 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.
+ * - Neither the name of the MontaVista Software, Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <qb/qbplugin_comp.h>
+
+/*
+ * Version 0 of the interface
+ */
+static int iface1_constructor (void *context);
+
+static void iface1_destructor (void *context);
+
+static void iface1_func1 (void);
+
+static void iface1_func2 (void);
+
+static void iface1_func3 (void);
+
+/*
+ * Version 1 of the interface
+ */
+static int iface1_ver1_constructor (void *context);
+
+static void iface1_ver1_destructor (void *context);
+
+static void iface1_ver1_func1 (void);
+
+static void iface1_ver1_func2 (void);
+
+static void iface1_ver1_func3 (void);
+
+struct iface_list {
+	void (*iface1_func1)(void);
+	void (*iface1_func2)(void);
+	void (*iface1_func3)(void);
+};
+
+struct iface_ver1_list {
+	void (*iface1_ver1_func1)(void);
+	void (*iface1_ver1_func2)(void);
+	void (*iface1_ver1_func3)(void);
+};
+
+struct iface_list iface_list = {
+	.iface1_func1		= iface1_func1,
+	.iface1_func2		= iface1_func2,
+	.iface1_func3		= iface1_func3,
+};
+
+struct iface_list iface_ver1_list = {
+	.iface1_func1		= iface1_ver1_func1,
+	.iface1_func2		= iface1_ver1_func2,
+	.iface1_func3		= iface1_ver1_func3,
+};
+
+struct plugin_iface iface1[2]= {
+	/*
+	 * Version 0
+	 */
+	{
+		.name			= "B_iface1",
+		.version		= 0,
+		.versions_replace	= 0,
+		.versions_replace_count	= 0,
+		.dependencies		= 0,
+		.dependency_count	= 0,
+		.constructor		= iface1_constructor,
+		.destructor		= iface1_destructor,
+		.interfaces		= NULL
+	},
+	/*
+	 * Version 1
+	 */
+	{
+		.name			= "B_iface1",
+		.version		= 1,
+		.versions_replace	= 0,
+		.versions_replace_count	= 0,
+		.dependencies		= 0,
+		.dependency_count	= 0,
+		.constructor		= iface1_ver1_constructor,
+		.destructor		= iface1_ver1_destructor,
+		.interfaces		= NULL
+	}
+};
+
+struct plugin_comp test_comp = {
+	.iface_count 		= 2,
+	.ifaces 		= iface1
+};
+
+static int iface1_constructor (void *context)
+{
+	printf ("B - version 0 constructor context %p\n", context);
+	return (0);
+}
+
+static void iface1_destructor (void *context)
+{
+	printf ("B - version 0 destructor context %p\n", context);
+}
+
+static void iface1_func1 (void) {
+	printf ("B - version 0 func1\n");
+}
+
+static void iface1_func2 (void) {
+	printf ("B - version 0 func2\n");
+}
+
+static void iface1_func3 (void) {
+	printf ("B - version 0 func3\n");
+}
+
+static int iface1_ver1_constructor (void *context)
+{
+	printf ("B - version 1 constructor context %p\n", context);
+	return (0);
+}
+
+static void iface1_ver1_destructor (void *context)
+{
+	printf ("B - version 1 destructor context %p\n", context);
+}
+
+static void iface1_ver1_func1 (void) {
+	printf ("B - version 1 func1\n");
+}
+
+static void iface1_ver1_func2 (void) {
+	printf ("B - version 1 func2\n");
+}
+
+static void iface1_ver1_func3 (void) {
+	printf ("B - version 1 func3\n");
+}
+
+__attribute__ ((constructor)) static void register_this_component (void)
+{
+        plugin_interfaces_set (&iface1[0], &iface_list);
+        plugin_interfaces_set (&iface1[1], &iface_ver1_list);
+
+	plugin_component_register (&test_comp);
+}
-- 
1.6.6.1

