summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/libmowgli/core/Makefile32
-rw-r--r--src/libmowgli/core/alloc.c238
-rw-r--r--src/libmowgli/core/alloc.h38
-rw-r--r--src/libmowgli/core/allocation_policy.c70
-rw-r--r--src/libmowgli/core/allocation_policy.h44
-rw-r--r--src/libmowgli/core/allocator.c46
-rw-r--r--src/libmowgli/core/allocator.h29
-rw-r--r--src/libmowgli/core/assert.h60
-rw-r--r--src/libmowgli/core/bootstrap.c82
-rw-r--r--src/libmowgli/core/bootstrap.h29
-rw-r--r--src/libmowgli/core/heap.c374
-rw-r--r--src/libmowgli/core/heap.h48
-rw-r--r--src/libmowgli/core/iterator.h44
-rw-r--r--src/libmowgli/core/logger.c95
-rw-r--r--src/libmowgli/core/logger.h62
-rw-r--r--src/libmowgli/core/mowgli_string.c201
-rw-r--r--src/libmowgli/core/mowgli_string.h53
-rw-r--r--src/libmowgli/core/process.c123
-rw-r--r--src/libmowgli/core/process.h38
-rw-r--r--src/libmowgli/core/stdinc.h109
20 files changed, 1815 insertions, 0 deletions
diff --git a/src/libmowgli/core/Makefile b/src/libmowgli/core/Makefile
new file mode 100644
index 0000000..08a5306
--- /dev/null
+++ b/src/libmowgli/core/Makefile
@@ -0,0 +1,32 @@
+include ../../../extra.mk
+
+STATIC_PIC_LIB_NOINST = ${LIBMOWGLI_SHARED_CORE}
+STATIC_LIB_NOINST = ${LIBMOWGLI_STATIC_CORE}
+
+SRCS = bootstrap.c \
+ alloc.c \
+ allocation_policy.c \
+ allocator.c \
+ heap.c \
+ logger.c \
+ mowgli_string.c \
+ process.c
+
+INCLUDES = bootstrap.h \
+ alloc.h \
+ allocation_policy.h \
+ allocator.h \
+ assert.h \
+ heap.h \
+ iterator.h \
+ logger.h \
+ mowgli_string.h \
+ stdinc.h \
+ process.h
+
+include ../../../buildsys.mk
+
+includesubdir = $(PACKAGE_NAME)/core
+
+CPPFLAGS += -I. -I.. -I../../.. -DMOWGLI_CORE
+
diff --git a/src/libmowgli/core/alloc.c b/src/libmowgli/core/alloc.c
new file mode 100644
index 0000000..e527973
--- /dev/null
+++ b/src/libmowgli/core/alloc.c
@@ -0,0 +1,238 @@
+/*
+ * libmowgli: A collection of useful routines for programming.
+ * alloc.c: Safe, portable implementations of malloc, calloc, and free.
+ *
+ * Copyright (c) 2007, 2012 William Pitcock <nenolod@dereferenced.org>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice is present in all copies.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 "mowgli.h"
+
+/*
+ * bootstrapped allocators so that we can initialise without blowing up
+ */
+typedef struct
+{
+ mowgli_allocation_policy_t *allocator;
+} alloc_tag_t;
+
+static void *
+_mowgli_bootstrap_alloc(size_t size)
+{
+ return calloc(size, 1);
+}
+
+static void
+_mowgli_bootstrap_free(void *ptr)
+{
+ if (ptr)
+ free(ptr);
+}
+
+static mowgli_allocation_policy_t _mowgli_allocator_bootstrap =
+{
+ { 0 },
+ _mowgli_bootstrap_alloc,
+ _mowgli_bootstrap_free
+};
+
+static mowgli_allocation_policy_t *_mowgli_allocator = &_mowgli_allocator_bootstrap;
+
+/*
+ * \brief Allocates an array of data that contains "count" objects,
+ * of "size" size.
+ *
+ * Usually, this wraps calloc().
+ *
+ * \param size size of objects to allocate.
+ * \param count amount of objects to allocate.
+ *
+ * \return A pointer to a memory buffer.
+ */
+void *
+mowgli_alloc_array_using_policy(mowgli_allocation_policy_t *policy, size_t size, size_t count)
+{
+ size_t adj_size;
+ void *r;
+
+ return_val_if_fail(policy != NULL, NULL);
+
+ adj_size = (size * count) + sizeof(alloc_tag_t);
+
+ r = policy->allocate(adj_size);
+ ((alloc_tag_t *) r)->allocator = policy;
+
+ return (char *) r + sizeof(alloc_tag_t);
+}
+
+/*
+ * \brief Allocates an object of "size" size.
+ *
+ * This is the equivilant of calling mowgli_alloc_array(size, 1).
+ *
+ * \param size size of object to allocate.
+ *
+ * \return A pointer to a memory buffer.
+ */
+void *
+mowgli_alloc_using_policy(mowgli_allocation_policy_t *policy, size_t size)
+{
+ return mowgli_alloc_array_using_policy(policy, size, 1);
+}
+
+/*
+ * \brief Duplicater a string using mowgli_alloc() using a specific policy.
+ */
+char *
+mowgli_strdup_using_policy(mowgli_allocation_policy_t *policy, const char *in)
+{
+ char *out;
+ size_t len;
+
+ return_val_if_fail(in != NULL, NULL);
+
+ len = strlen(in) + 1;
+ out = mowgli_alloc_using_policy(policy, len);
+ mowgli_strlcpy(out, in, len);
+
+ return out;
+}
+
+/*
+ * \brief Duplicater a string using mowgli_alloc() using a specific policy.
+ */
+char *
+mowgli_strdup(const char *in)
+{
+ return mowgli_strdup_using_policy(_mowgli_allocator, in);
+}
+
+/*
+ * \brief Duplicate a string of a specified length using mowgli_alloc() using a specific policy.
+ */
+char *
+mowgli_strndup_using_policy(mowgli_allocation_policy_t *policy, const char *in, size_t size)
+{
+ char *out;
+ size_t len;
+
+ return_val_if_fail(in != NULL, NULL);
+
+ len = strlen(in) + 1;
+
+ if (size < len)
+ len = size;
+
+ out = mowgli_alloc_using_policy(policy, len);
+ mowgli_strlcpy(out, in, len);
+
+ return out;
+}
+
+/*
+ * \brief Duplicate a string of a specified length using mowgli_alloc() using a specific policy.
+ */
+char *
+mowgli_strndup(const char *in, size_t size)
+{
+ return mowgli_strndup_using_policy(_mowgli_allocator, in, size);
+}
+
+/*
+ * \brief Allocates an array of data that contains "count" objects,
+ * of "size" size.
+ *
+ * Usually, this wraps calloc().
+ *
+ * \param size size of objects to allocate.
+ * \param count amount of objects to allocate.
+ *
+ * \return A pointer to a memory buffer.
+ */
+void *
+mowgli_alloc_array(size_t size, size_t count)
+{
+ return mowgli_alloc_array_using_policy(_mowgli_allocator, size, count);
+}
+
+/*
+ * \brief Allocates an object of "size" size.
+ *
+ * This is the equivilant of calling mowgli_alloc_array(size, 1).
+ *
+ * \param size size of object to allocate.
+ *
+ * \return A pointer to a memory buffer.
+ */
+void *
+mowgli_alloc(size_t size)
+{
+ return mowgli_alloc_array_using_policy(_mowgli_allocator, size, 1);
+}
+
+/*
+ * \brief Frees an object back to the system memory pool.
+ *
+ * Wraps free protecting against common mistakes (reports an error instead).
+ *
+ * \param ptr pointer to object to free.
+ */
+void
+mowgli_free(void *ptr)
+{
+ alloc_tag_t *tag;
+
+ return_if_fail(ptr != NULL);
+
+ tag = (alloc_tag_t *) ((char *) ptr - sizeof(alloc_tag_t));
+ tag->allocator->deallocate(tag);
+}
+
+/*
+ * \brief Sets the mowgli.allocation_policy used by the allocation primitives.
+ *
+ * \param policy The mowgli_allocation_policy_t object to use.
+ */
+void
+mowgli_allocator_set_policy(mowgli_allocation_policy_t *policy)
+{
+ return_if_fail(policy != NULL);
+
+ _mowgli_allocator = policy;
+}
+
+/*
+ * \brief Sets the mowgli.allocation_policy used by the allocation primitives,
+ * when given a name.
+ *
+ * \param name The name of the policy to use.
+ */
+void
+mowgli_allocator_set_policy_by_name(const char *name)
+{
+ mowgli_allocation_policy_t *policy;
+
+ return_if_fail(name != NULL);
+
+ policy = mowgli_allocation_policy_lookup(name);
+
+ if (policy == NULL)
+ return;
+
+ mowgli_allocator_set_policy(policy);
+}
diff --git a/src/libmowgli/core/alloc.h b/src/libmowgli/core/alloc.h
new file mode 100644
index 0000000..ac0f2f9
--- /dev/null
+++ b/src/libmowgli/core/alloc.h
@@ -0,0 +1,38 @@
+/*
+ * libmowgli: A collection of useful routines for programming.
+ * alloc.h: Safe, portable implementations of malloc, calloc, and free.
+ *
+ * Copyright (c) 2007 William Pitcock <nenolod -at- sacredspiral.co.uk>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice is present in all copies.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 __MOWGLI_ALLOC_H__
+#define __MOWGLI_ALLOC_H__
+
+extern void *mowgli_alloc_array_using_policy(mowgli_allocation_policy_t *policy, size_t size, size_t count);
+extern void *mowgli_alloc_using_policy(mowgli_allocation_policy_t *policy, size_t size);
+extern char *mowgli_strdup_using_policy(mowgli_allocation_policy_t *policy, const char *in);
+extern char *mowgli_strndup_using_policy(mowgli_allocation_policy_t *policy, const char *in, size_t size);
+
+extern void *mowgli_alloc_array(size_t size, size_t count);
+extern void *mowgli_alloc(size_t size);
+extern char *mowgli_strdup(const char *in);
+extern char *mowgli_strndup(const char *in, size_t size);
+extern void mowgli_free(void *ptr);
+
+#endif
diff --git a/src/libmowgli/core/allocation_policy.c b/src/libmowgli/core/allocation_policy.c
new file mode 100644
index 0000000..dc66cb8
--- /dev/null
+++ b/src/libmowgli/core/allocation_policy.c
@@ -0,0 +1,70 @@
+/*
+ * libmowgli: A collection of useful routines for programming.
+ * allocation_policy.h: Allocation policy management.
+ *
+ * Copyright (c) 2007 William Pitcock <nenolod -at- sacredspiral.co.uk>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice is present in all copies.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 "mowgli.h"
+
+static mowgli_object_class_t klass;
+static mowgli_patricia_t *mowgli_allocation_policy_dict = NULL;
+
+static void
+_allocation_policy_key_canon(char *str)
+{ }
+
+void
+mowgli_allocation_policy_bootstrap(void)
+{
+ mowgli_allocation_policy_dict = mowgli_patricia_create(_allocation_policy_key_canon);
+
+ mowgli_object_class_init(&klass, "mowgli.allocation_policy", NULL, FALSE);
+}
+
+mowgli_allocation_policy_t *
+mowgli_allocation_policy_create(const char *name, mowgli_allocation_func_t allocator, mowgli_deallocation_func_t deallocator)
+{
+ mowgli_allocation_policy_t *policy;
+
+ if (mowgli_allocation_policy_dict == NULL)
+ mowgli_allocation_policy_dict = mowgli_patricia_create(_allocation_policy_key_canon);
+
+ if ((policy = mowgli_patricia_retrieve(mowgli_allocation_policy_dict, name)))
+ return policy;
+
+ policy = mowgli_alloc(sizeof(mowgli_allocation_policy_t));
+ mowgli_object_init_from_class(mowgli_object(policy), name, &klass);
+
+ policy->allocate = allocator;
+ policy->deallocate = deallocator;
+
+ mowgli_patricia_add(mowgli_allocation_policy_dict, name, policy);
+
+ return policy;
+}
+
+mowgli_allocation_policy_t *
+mowgli_allocation_policy_lookup(const char *name)
+{
+ if (mowgli_allocation_policy_dict == NULL)
+ mowgli_allocation_policy_dict = mowgli_patricia_create(_allocation_policy_key_canon);
+
+ return mowgli_patricia_retrieve(mowgli_allocation_policy_dict, name);
+}
diff --git a/src/libmowgli/core/allocation_policy.h b/src/libmowgli/core/allocation_policy.h
new file mode 100644
index 0000000..5d6be62
--- /dev/null
+++ b/src/libmowgli/core/allocation_policy.h
@@ -0,0 +1,44 @@
+/*
+ * libmowgli: A collection of useful routines for programming.
+ * allocation_policy.h: Allocation policy management.
+ *
+ * Copyright (c) 2007 William Pitcock <nenolod -at- sacredspiral.co.uk>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice is present in all copies.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 __MOWGLI_ALLOCATION_POLICY_H__
+#define __MOWGLI_ALLOCATION_POLICY_H__
+
+typedef void *(*mowgli_allocation_func_t)(size_t size);
+typedef void (*mowgli_deallocation_func_t)(void *ptr);
+
+typedef struct
+{
+ mowgli_object_t parent;
+ mowgli_allocation_func_t allocate;
+ mowgli_deallocation_func_t deallocate;
+} mowgli_allocation_policy_t;
+
+mowgli_allocation_policy_t *mowgli_allocation_policy_create(const char *name, mowgli_allocation_func_t allocator, mowgli_deallocation_func_t deallocator);
+mowgli_allocation_policy_t *mowgli_allocation_policy_lookup(const char *name);
+
+/* for mowgli_alloc, et. al */
+void mowgli_allocator_set_policy(mowgli_allocation_policy_t *policy);
+void mowgli_allocator_set_policy_by_name(const char *name);
+
+#endif
diff --git a/src/libmowgli/core/allocator.c b/src/libmowgli/core/allocator.c
new file mode 100644
index 0000000..6002bb0
--- /dev/null
+++ b/src/libmowgli/core/allocator.c
@@ -0,0 +1,46 @@
+/*
+ * libmowgli: A collection of useful routines for programming.
+ * allocator.h: Builtin allocation policies (mmap/malloc).
+ *
+ * Copyright (c) 2007 William Pitcock <nenolod -at- sacredspiral.co.uk>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice is present in all copies.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 "mowgli.h"
+
+mowgli_allocation_policy_t *mowgli_allocator_malloc = NULL;
+
+static void *
+mowgli_allocator_func_malloc(size_t size)
+{
+ return calloc(size, 1);
+}
+
+static void
+mowgli_allocator_func_free(void *ptr)
+{
+ if (ptr)
+ free(ptr);
+}
+
+void
+mowgli_allocator_bootstrap(void)
+{
+ mowgli_allocator_malloc = mowgli_allocation_policy_create("malloc", mowgli_allocator_func_malloc,
+ mowgli_allocator_func_free);
+}
diff --git a/src/libmowgli/core/allocator.h b/src/libmowgli/core/allocator.h
new file mode 100644
index 0000000..c243fe2
--- /dev/null
+++ b/src/libmowgli/core/allocator.h
@@ -0,0 +1,29 @@
+/*
+ * libmowgli: A collection of useful routines for programming.
+ * allocator.h: Builtin allocation policies (mmap/malloc).
+ *
+ * Copyright (c) 2007 William Pitcock <nenolod -at- sacredspiral.co.uk>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice is present in all copies.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 __MOWGLI_ALLOCATOR_H__
+#define __MOWGLI_ALLOCATOR_H__
+
+extern mowgli_allocation_policy_t *mowgli_allocator_malloc;
+
+#endif
diff --git a/src/libmowgli/core/assert.h b/src/libmowgli/core/assert.h
new file mode 100644
index 0000000..fce30a1
--- /dev/null
+++ b/src/libmowgli/core/assert.h
@@ -0,0 +1,60 @@
+/*
+ * libmowgli: A collection of useful routines for programming.
+ * assert.h: Assertions.
+ *
+ * Copyright (c) 2007 William Pitcock <nenolod -at- sacredspiral.co.uk>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice is present in all copies.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 __MOWGLI_ASSERT_H__
+#define __MOWGLI_ASSERT_H__
+
+#define _assert_msg(exp) "assertion '" #exp "' failed."
+
+#define soft_assert(exp) \
+ do \
+ { \
+ if (!(exp)) \
+ { \
+ mowgli_log_warning(_assert_msg(exp)); \
+ } \
+ } while (0)
+
+#define return_if_fail(exp) \
+ do \
+ { \
+ if (!(exp)) \
+ { \
+ mowgli_log_warning(_assert_msg(exp)); \
+ return; \
+ } \
+ } while (0)
+
+#define return_val_if_fail(exp, val) \
+ do \
+ { \
+ if (!(exp)) \
+ { \
+ mowgli_log_warning(_assert_msg(exp)); \
+ return (val); \
+ } \
+ } while (0)
+
+#define return_null_if_fail(exp) return_val_if_fail(exp, NULL)
+
+#endif
diff --git a/src/libmowgli/core/bootstrap.c b/src/libmowgli/core/bootstrap.c
new file mode 100644
index 0000000..4aecc98
--- /dev/null
+++ b/src/libmowgli/core/bootstrap.c
@@ -0,0 +1,82 @@
+/*
+ * libmowgli: A collection of useful routines for programming.
+ * bootstrap.c: Initialization of libmowgli.
+ *
+ * Copyright (c) 2007 William Pitcock <nenolod -at- sacredspiral.co.uk>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice is present in all copies.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 "mowgli.h"
+
+extern void mowgli_log_bootstrap(void);
+extern void mowgli_node_bootstrap(void);
+extern void mowgli_queue_bootstrap(void);
+extern void mowgli_object_class_bootstrap(void);
+extern void mowgli_argstack_bootstrap(void);
+extern void mowgli_bitvector_bootstrap(void);
+extern void mowgli_global_storage_bootstrap(void);
+extern void mowgli_hook_bootstrap(void);
+extern void mowgli_random_bootstrap(void);
+extern void mowgli_allocation_policy_bootstrap(void);
+extern void mowgli_allocator_bootstrap(void);
+extern void mowgli_memslice_bootstrap(void);
+extern void mowgli_cacheline_bootstrap(void);
+extern void mowgli_interface_bootstrap(void);
+
+/* TODO: rename to mowgli_bootstrap next time there is a LIB_MAJOR bump */
+MOWGLI_BOOTSTRAP_FUNC(mowgli_bootstrap_real)
+{
+ static bool bootstrapped = 0;
+
+ if (bootstrapped)
+ return;
+
+ /* initial bootstrap */
+ mowgli_log_bootstrap();
+ mowgli_node_bootstrap();
+ mowgli_queue_bootstrap();
+ mowgli_object_class_bootstrap();
+ mowgli_argstack_bootstrap();
+ mowgli_bitvector_bootstrap();
+ mowgli_global_storage_bootstrap();
+ mowgli_hook_bootstrap();
+ mowgli_random_bootstrap();
+ mowgli_allocation_policy_bootstrap();
+ mowgli_allocator_bootstrap();
+ mowgli_memslice_bootstrap();
+ mowgli_cacheline_bootstrap();
+ mowgli_interface_bootstrap();
+
+#ifdef _WIN32
+ extern void mowgli_winsock_bootstrap(void);
+
+ mowgli_winsock_bootstrap();
+#endif
+
+ /* now that we're bootstrapped, we can use a more optimised allocator
+ if one is available. */
+ mowgli_allocator_set_policy(mowgli_allocator_malloc);
+
+ bootstrapped = true;
+}
+
+void
+mowgli_init(void)
+{
+ mowgli_log("mowgli_init() is a deprecated function, provided only for backwards compatibility with Mowgli-1. You should remove it if you no longer support using Mowgli-1.");
+}
diff --git a/src/libmowgli/core/bootstrap.h b/src/libmowgli/core/bootstrap.h
new file mode 100644
index 0000000..36f46f4
--- /dev/null
+++ b/src/libmowgli/core/bootstrap.h
@@ -0,0 +1,29 @@
+/*
+ * libmowgli: A collection of useful routines for programming.
+ * bootstrap.c: Initialization of libmowgli.
+ *
+ * Copyright (c) 2007 William Pitcock <nenolod -at- sacredspiral.co.uk>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice is present in all copies.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 __MOWGLI_BOOTSTRAP_H__
+#define __MOWGLI_BOOTSTRAP_H__
+
+extern void mowgli_bootstrap(void);
+
+#endif
diff --git a/src/libmowgli/core/heap.c b/src/libmowgli/core/heap.c
new file mode 100644
index 0000000..b4fd9d9
--- /dev/null
+++ b/src/libmowgli/core/heap.c
@@ -0,0 +1,374 @@
+/*
+ * libmowgli: A collection of useful routines for programming.
+ * heap.c: Heap allocation.
+ *
+ * Copyright (c) 2007 William Pitcock <nenolod -at- sacredspiral.co.uk>
+ * Copyright (c) 2005-2006 Theo Julienne <terminal -at- atheme.org>
+ * Copyright (c) 2011 Andrew Wilcox <awilcox -at- wilcox-tech.com>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice is present in all copies.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ *
+ * Legal note: code devised from claro.base.block module r288 (Pre MPL)
+ */
+
+#include "mowgli.h"
+
+#ifdef HAVE_MMAP
+# include <sys/mman.h>
+# if !defined(MAP_ANON) && defined(MAP_ANONYMOUS)
+# define MAP_ANON MAP_ANONYMOUS
+# endif
+#endif
+
+/* A block of memory allocated to the allocator */
+struct mowgli_block_
+{
+ mowgli_node_t node;
+
+ /* link back to our heap */
+ mowgli_heap_t *heap;
+
+ /* pointer to the first item */
+ void *data;
+
+ /* singly linked list of free items */
+ void *first_free;
+
+ unsigned int num_allocated;
+};
+
+/* A pile of blocks */
+struct mowgli_heap_
+{
+ unsigned int elem_size;
+ unsigned int mowgli_heap_elems;
+ unsigned int free_elems;
+
+ unsigned int alloc_size;
+
+ unsigned int flags;
+
+ mowgli_list_t blocks; /* list of non-empty blocks */
+
+ mowgli_allocation_policy_t *allocator;
+ mowgli_boolean_t use_mmap;
+
+ mowgli_mutex_t mutex;
+
+ mowgli_block_t *empty_block; /* a single entirely free block, or NULL */
+};
+
+typedef struct mowgli_heap_elem_header_ mowgli_heap_elem_header_t;
+
+struct mowgli_heap_elem_header_
+{
+ union
+ {
+ mowgli_block_t *block; /* for allocated elems: block ptr */
+ mowgli_heap_elem_header_t *next;/* for free elems: next free */
+ } un;
+};
+
+/* expands a mowgli_heap_t by 1 block */
+static void
+mowgli_heap_expand(mowgli_heap_t *bh)
+{
+ mowgli_block_t *block = NULL;
+ void *blp = NULL;
+ mowgli_heap_elem_header_t *node, *prev;
+ char *offset;
+ unsigned int a;
+ size_t blp_size;
+
+ blp_size = sizeof(mowgli_block_t) + (bh->alloc_size * bh->mowgli_heap_elems);
+
+ if (bh->empty_block != NULL)
+ return;
+
+#if defined(HAVE_MMAP) && defined(MAP_ANON)
+
+ if (bh->use_mmap)
+ blp = mmap(NULL, sizeof(mowgli_block_t) + (bh->alloc_size * bh->mowgli_heap_elems),
+ PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
+ else
+#elif defined(_WIN32)
+
+ if (bh->use_mmap)
+ {
+ blp = VirtualAlloc(NULL, sizeof(mowgli_block_t) + (bh->alloc_size * bh->mowgli_heap_elems),
+ MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
+ }
+ else
+#endif
+ {
+ if (bh->allocator)
+ blp = bh->allocator->allocate(blp_size);
+ else
+ blp = mowgli_alloc(blp_size);
+ }
+
+ block = (mowgli_block_t *) blp;
+
+ offset = (char *) blp + sizeof(mowgli_block_t);
+ block->data = offset;
+ block->heap = bh;
+
+ prev = NULL;
+
+ for (a = 0; a < bh->mowgli_heap_elems; a++)
+ {
+ node = (mowgli_heap_elem_header_t *) offset;
+ node->un.next = prev;
+ offset += bh->alloc_size;
+ prev = node;
+ }
+
+ block->first_free = prev;
+
+ bh->empty_block = block;
+ bh->free_elems += bh->mowgli_heap_elems;
+}
+
+/* shrinks a mowgli_heap_t by 1 block. */
+static void
+mowgli_heap_shrink(mowgli_heap_t *heap, mowgli_block_t *b)
+{
+ return_if_fail(b != NULL);
+
+ if (b == heap->empty_block)
+ heap->empty_block = NULL;
+ else
+ mowgli_node_delete(&b->node, &heap->blocks);
+
+#if defined(HAVE_MMAP)
+
+ if (heap->use_mmap)
+ munmap(b, sizeof(mowgli_block_t) + (heap->alloc_size * heap->mowgli_heap_elems));
+ else
+#elif defined(_WIN32)
+
+ if (heap->use_mmap)
+ VirtualFree(b, 0, MEM_RELEASE);
+ else
+#endif
+ if (heap->allocator)
+ heap->allocator->deallocate(b);
+ else
+ mowgli_free(b);
+
+ heap->free_elems -= heap->mowgli_heap_elems;
+}
+
+/* creates a new mowgli_heap_t */
+mowgli_heap_t *
+mowgli_heap_create_full(size_t elem_size, size_t mowgli_heap_elems, unsigned int flags, mowgli_allocation_policy_t *allocator)
+{
+ mowgli_heap_t *bh = mowgli_alloc(sizeof(mowgli_heap_t));
+ int numpages, pagesize;
+
+ bh->elem_size = elem_size;
+ bh->mowgli_heap_elems = mowgli_heap_elems;
+
+ /* at least 2, this avoids some silly special cases */
+ if (bh->mowgli_heap_elems < 2)
+ bh->mowgli_heap_elems = 2;
+
+ bh->free_elems = 0;
+
+ bh->alloc_size = bh->elem_size + sizeof(mowgli_heap_elem_header_t);
+
+ /* don't waste part of a page */
+ if (allocator == NULL)
+ {
+#ifdef HAVE_MMAP
+ pagesize = getpagesize();
+#else
+ pagesize = 4096;
+#endif
+ numpages = (sizeof(mowgli_block_t) + (bh->alloc_size * bh->mowgli_heap_elems) + pagesize - 1) / pagesize;
+ bh->mowgli_heap_elems = (numpages * pagesize - sizeof(mowgli_block_t)) / bh->alloc_size;
+ }
+
+ bh->flags = flags;
+
+ bh->allocator = allocator ? allocator : mowgli_allocator_malloc;
+
+#ifdef HAVE_MMAP
+ bh->use_mmap = allocator != NULL ? FALSE : TRUE;
+#endif
+
+ if (mowgli_mutex_init(&bh->mutex) != 0)
+ mowgli_log_fatal("heap mutex can't be created");
+
+ if (flags & BH_NOW)
+ {
+ mowgli_mutex_lock(&bh->mutex);
+ mowgli_heap_expand(bh);
+ mowgli_mutex_unlock(&bh->mutex);
+ }
+
+ return bh;
+}
+
+mowgli_heap_t *
+mowgli_heap_create(size_t elem_size, size_t mowgli_heap_elems, unsigned int flags)
+{
+ return mowgli_heap_create_full(elem_size, mowgli_heap_elems, flags, NULL);
+}
+
+/* completely frees a mowgli_heap_t and all blocks */
+void
+mowgli_heap_destroy(mowgli_heap_t *heap)
+{
+ mowgli_node_t *n, *tn;
+
+ MOWGLI_LIST_FOREACH_SAFE(n, tn, heap->blocks.head)
+ {
+ mowgli_heap_shrink(heap, n->data);
+ }
+
+ if (heap->empty_block)
+ mowgli_heap_shrink(heap, heap->empty_block);
+
+ mowgli_mutex_uninit(&heap->mutex);
+
+ /* everything related to heap has gone, time for itself */
+ mowgli_free(heap);
+}
+
+/* allocates a new item from a mowgli_heap_t */
+void *
+mowgli_heap_alloc(mowgli_heap_t *heap)
+{
+ mowgli_node_t *n;
+ mowgli_block_t *b;
+ mowgli_heap_elem_header_t *h;
+
+ if (mowgli_mutex_lock(&heap->mutex) != 0)
+ mowgli_log_fatal("heap mutex can't be locked");
+
+ /* no free space? */
+ if (heap->free_elems == 0)
+ {
+ mowgli_heap_expand(heap);
+
+ if (heap->free_elems == 0)
+ {
+ mowgli_mutex_unlock(&heap->mutex);
+ return NULL;
+ }
+ }
+
+ /* try a partially used block before using a fully free block */
+ n = heap->blocks.head;
+ b = n != NULL ? n->data : NULL;
+
+ if ((b == NULL) || (b->first_free == NULL))
+ b = heap->empty_block;
+
+ /* due to above check */
+ return_val_if_fail(b != NULL, NULL);
+
+ /* pull the first free node from the list */
+ h = b->first_free;
+ return_val_if_fail(h != NULL, NULL);
+
+ /* mark it as used */
+ b->first_free = h->un.next;
+ h->un.block = b;
+
+ /* keep count */
+ heap->free_elems--;
+ b->num_allocated++;
+
+ /* move it between the lists if needed */
+
+ /* note that a block has at least two items in it, so these cases
+ * cannot both occur in the same allocation */
+ if (b->num_allocated == 1)
+ {
+ heap->empty_block = NULL;
+ mowgli_node_add_head(b, &b->node, &heap->blocks);
+ }
+ else if (b->first_free == NULL)
+ {
+ /* move full blocks to the end of the list */
+ mowgli_node_delete(&b->node, &heap->blocks);
+ mowgli_node_add(b, &b->node, &heap->blocks);
+ }
+
+#ifdef HEAP_DEBUG
+
+ /* debug */
+ mowgli_log("mowgli_heap_alloc(heap = @%p) -> %p", heap, (char*) h + sizeof(mowgli_heap_elem_header_t));
+#endif
+
+ mowgli_mutex_unlock(&heap->mutex);
+
+ /* return pointer to it */
+ return (char *) h + sizeof(mowgli_heap_elem_header_t);
+}
+
+/* frees an item back to the mowgli_heap_t */
+void
+mowgli_heap_free(mowgli_heap_t *heap, void *data)
+{
+ mowgli_block_t *b;
+ mowgli_heap_elem_header_t *h;
+
+ if (mowgli_mutex_lock(&heap->mutex) != 0)
+ mowgli_log_fatal("heap mutex can't be locked");
+
+ h = (mowgli_heap_elem_header_t *) ((char *) data - sizeof(mowgli_heap_elem_header_t));
+ b = h->un.block;
+
+ return_if_fail(b->heap == heap);
+ return_if_fail(b->num_allocated > 0);
+
+ /* memset the element before returning it to the heap. */
+ memset(data, 0, b->heap->elem_size);
+
+ /* mark it as free */
+ h->un.next = b->first_free;
+ b->first_free = h;
+
+ /* keep count */
+ heap->free_elems++;
+ b->num_allocated--;
+#ifdef HEAP_DEBUG
+
+ /* debug */
+ mowgli_log("mowgli_heap_free(heap = @%p, data = %p)", heap, data);
+#endif
+
+ /* move it between the lists if needed */
+ if (b->num_allocated == 0)
+ {
+ if (heap->empty_block != NULL)
+ mowgli_heap_shrink(heap, heap->empty_block);
+
+ mowgli_node_delete(&b->node, &heap->blocks);
+ heap->empty_block = b;
+ }
+ else if (b->num_allocated == heap->mowgli_heap_elems - 1)
+ {
+ mowgli_node_delete(&b->node, &heap->blocks);
+ mowgli_node_add_head(b, &b->node, &heap->blocks);
+ }
+
+ mowgli_mutex_unlock(&heap->mutex);
+}
diff --git a/src/libmowgli/core/heap.h b/src/libmowgli/core/heap.h
new file mode 100644
index 0000000..e193983
--- /dev/null
+++ b/src/libmowgli/core/heap.h
@@ -0,0 +1,48 @@
+/*
+ * libmowgli: A collection of useful routines for programming.
+ * heap.h: Heap allocation.
+ *
+ * Copyright (c) 2007 William Pitcock <nenolod -at- sacredspiral.co.uk>
+ * Copyright (c) 2005-2006 Theo Julienne <terminal -at- atheme.org>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice is present in all copies.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ *
+ * Legal note: code devised from claro.base.block module r288 (Pre MPL)
+ */
+
+#ifndef __MOWGLI_HEAP_H__
+#define __MOWGLI_HEAP_H__
+
+typedef struct mowgli_heap_ mowgli_heap_t;
+typedef struct mowgli_block_ mowgli_block_t;
+
+/* Flag for mowgli_heap_create */
+#define BH_DONTCARE 0
+
+#define BH_NOW 1
+#define BH_LAZY 0
+
+/* Functions for heaps */
+extern mowgli_heap_t *mowgli_heap_create(size_t elem_size, size_t mowgli_heap_elems, unsigned int flags);
+extern mowgli_heap_t *mowgli_heap_create_full(size_t elem_size, size_t mowgli_heap_elems, unsigned int flags, mowgli_allocation_policy_t *allocator);
+extern void mowgli_heap_destroy(mowgli_heap_t *heap);
+
+/* Functions for blocks */
+extern void *mowgli_heap_alloc(mowgli_heap_t *heap);
+extern void mowgli_heap_free(mowgli_heap_t *heap, void *data);
+
+#endif
diff --git a/src/libmowgli/core/iterator.h b/src/libmowgli/core/iterator.h
new file mode 100644
index 0000000..2eac7b4
--- /dev/null
+++ b/src/libmowgli/core/iterator.h
@@ -0,0 +1,44 @@
+/*
+ * libmowgli: A collection of useful routines for programming.
+ * iterator.h: Iterators.
+ *
+ * Copyright (c) 2007 William Pitcock <nenolod -at- sacredspiral.co.uk>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice is present in all copies.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 __MOWGLI_ITERATOR_H__
+#define __MOWGLI_ITERATOR_H__
+
+typedef struct _mowgli_iterator
+{
+ struct _mowgli_iterator *prev, *next;
+
+ void *data;
+} mowgli_iterator_t;
+
+/* The following are macros which can be used with iterators. */
+#define MOWGLI_ITER_FOREACH(n, head) \
+ for (n = (head); n; n = n->next)
+#define MOWGLI_ITER_FOREACH_NEXT(n, head) \
+ for (n = (head); n->next; n = n->next)
+#define MOWGLI_ITER_FOREACH_PREV(n, tail) \
+ for (n = (tail); n; n = n->prev)
+#define MOWGLI_ITER_FOREACH_SAFE(n, tn, head) \
+ for (n = (head), tn = n ? n->next : NULL; n != NULL; n = tn, tn = n ? n->next : NULL)
+
+#endif
diff --git a/src/libmowgli/core/logger.c b/src/libmowgli/core/logger.c
new file mode 100644
index 0000000..e334dd2
--- /dev/null
+++ b/src/libmowgli/core/logger.c
@@ -0,0 +1,95 @@
+/*
+ * libmowgli: A collection of useful routines for programming.
+ * logger.c: Event and debugging message logging.
+ *
+ * Copyright (c) 2007 William Pitcock <nenolod -at- sacredspiral.co.uk>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice is present in all copies.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 "mowgli.h"
+
+#define MOWGLI_LOG_BUF_SIZE 4096
+
+char _mowgli_log_buf[MOWGLI_LOG_BUF_SIZE];
+mowgli_log_cb_t _mowgli_log_cb;
+
+void
+mowgli_log_cb_default(const char *buf)
+{
+ fprintf(stderr, "%s\n", buf);
+}
+
+void
+mowgli_log_bootstrap()
+{
+ _mowgli_log_cb = mowgli_log_cb_default;
+}
+
+void
+mowgli_log_set_cb(mowgli_log_cb_t callback)
+{
+ return_if_fail(callback != NULL);
+
+ _mowgli_log_cb = callback;
+}
+
+void
+mowgli_log_prefix_real(const char *file, int line, const char *func, const char *prefix, const char *fmt, ...)
+{
+ int len = snprintf(_mowgli_log_buf, MOWGLI_LOG_BUF_SIZE, "(%s:%d %s): %s",
+ file, line, func, prefix);
+
+ char *buf = &_mowgli_log_buf[len];
+
+ va_list va;
+
+ va_start(va, fmt);
+ vsnprintf(buf, MOWGLI_LOG_BUF_SIZE - len, fmt, va);
+ va_end(va);
+
+ _mowgli_log_cb(_mowgli_log_buf);
+}
+
+/* TODO: remove next time there is a LIB_MAJOR bump */
+void
+mowgli_log_real(const char *file, int line, const char *func, const char *fmt, ...)
+{
+ int len = snprintf(_mowgli_log_buf, 4095, "(%s:%d %s): ", file, line,
+ func);
+
+ char *buf = &_mowgli_log_buf[len];
+
+ va_list va;
+
+ va_start(va, fmt);
+ vsnprintf(buf, 4095 - len, fmt, va);
+ va_end(va);
+
+ _mowgli_log_cb(_mowgli_log_buf);
+}
+
+/* TODO: remove next time there is a LIB_MAJOR bump */
+void
+mowgli_soft_assert_log(const char *asrt, const char *file, int line, const char *function)
+{
+ snprintf(_mowgli_log_buf, 4095,
+ "(%s:%d %s): critical: Assertion '%s' failed.", file, line,
+ function, asrt);
+
+ _mowgli_log_cb(_mowgli_log_buf);
+}
diff --git a/src/libmowgli/core/logger.h b/src/libmowgli/core/logger.h
new file mode 100644
index 0000000..5c875d1
--- /dev/null
+++ b/src/libmowgli/core/logger.h
@@ -0,0 +1,62 @@
+/*
+ * libmowgli: A collection of useful routines for programming.
+ * logger.h: Event and debugging message logging.
+ *
+ * Copyright (c) 2007 William Pitcock <nenolod -at- sacredspiral.co.uk>
+ * Copyright (c) 2013 Patrick McFarland <pmcfarland@adterrasperaspera.com>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice is present in all copies.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 __MOWGLI_LOGGER_H__
+#define __MOWGLI_LOGGER_H__
+
+typedef void (*mowgli_log_cb_t)(const char *);
+
+extern void mowgli_log_set_cb(mowgli_log_cb_t callback);
+
+#define mowgli_log(...) \
+ mowgli_log_prefix("", __VA_ARGS__)
+
+#define mowgli_log_warning(...) \
+ mowgli_log_prefix("warning: ", __VA_ARGS__)
+
+#define mowgli_log_error(...) \
+ mowgli_log_prefix("error: ", __VA_ARGS__)
+
+#define mowgli_log_fatal(...) \
+ do \
+ { \
+ mowgli_log_prefix("fatal: ", __VA_ARGS__); \
+ abort(); \
+ } while (0)
+
+#define mowgli_log_prefix(prefix, ...) \
+ mowgli_log_prefix_real(__FILE__, __LINE__, _MOWGLI_FUNCNAME, prefix, __VA_ARGS__)
+
+extern MOWGLI_COLD(MOWGLI_PRINTF(void mowgli_log_prefix_real(const char *file,
+ int line, const char *func, const char *prefix, const char *fmt, ...), 5));
+
+#if defined MOWGLI_COMPILER_GCC_COMPAT
+# define _MOWGLI_FUNCNAME __PRETTY_FUNCTION__
+#elif defined MOWGLI_COMPILER_MSVC
+# define _MOWGLI_FUNCNAME __FUNCTION__
+#else
+# define _MOWGLI_FUNCNAME __func__
+#endif
+
+#endif
diff --git a/src/libmowgli/core/mowgli_string.c b/src/libmowgli/core/mowgli_string.c
new file mode 100644
index 0000000..455a12c
--- /dev/null
+++ b/src/libmowgli/core/mowgli_string.c
@@ -0,0 +1,201 @@
+/*
+ * libmowgli: A collection of useful routines for programming.
+ * mowgli_string.c: Immutable string buffers with cheap manipulation.
+ *
+ * Copyright (c) 2007 William Pitcock <nenolod -at- sacredspiral.co.uk>
+ * Copyright (c) 2007 Pippijn van Steenhoven <pippijn -at- one09.net>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice is present in all copies.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 "mowgli.h"
+
+mowgli_string_t *
+mowgli_string_create(void)
+{
+ mowgli_string_t *self = mowgli_alloc(sizeof(mowgli_string_t));
+
+ self->size = 64;
+ self->pos = 0;
+ self->str = mowgli_alloc(self->size);
+
+ self->append = &mowgli_string_append;
+ self->append_char = &mowgli_string_append_char;
+ self->reset = &mowgli_string_reset;
+ self->destroy = &mowgli_string_destroy;
+
+ return self;
+}
+
+void
+mowgli_string_reset(mowgli_string_t *self)
+{
+ return_if_fail(self != NULL);
+
+ self->str[0] = self->pos = 0;
+}
+
+void
+mowgli_string_destroy(mowgli_string_t *self)
+{
+ return_if_fail(self != NULL);
+
+ mowgli_free(self->str);
+ mowgli_free(self);
+}
+
+void
+mowgli_string_append(mowgli_string_t *self, const char *src, size_t n)
+{
+ if (self->size - self->pos <= n)
+ {
+ char *new_ptr;
+
+ self->size = MAX(self->size * 2, self->pos + n + 8);
+
+ new_ptr = mowgli_alloc(self->size);
+ mowgli_strlcpy(new_ptr, self->str, self->size);
+
+ mowgli_free(self->str);
+ self->str = new_ptr;
+ }
+
+ memcpy(self->str + self->pos, src, n);
+ self->pos += n;
+ self->str[self->pos] = 0;
+}
+
+void
+mowgli_string_append_char(mowgli_string_t *self, const char c)
+{
+ if (self->size - self->pos <= 1)
+ {
+ char *new_ptr;
+
+ self->size = MAX(self->size * 2, self->pos + 9);
+
+ new_ptr = mowgli_alloc(self->size);
+ mowgli_strlcpy(new_ptr, self->str, self->size);
+
+ mowgli_free(self->str);
+ self->str = new_ptr;
+ }
+
+ self->str[self->pos++] = c;
+ self->str[self->pos] = 0;
+}
+
+/*
+ * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+size_t
+mowgli_strlcat(char *dst, const char *src, size_t siz)
+{
+ char *d = dst;
+ const char *s = src;
+ size_t n = siz;
+ size_t dlen;
+
+ /* Find the end of dst and adjust bytes left but don't go past end */
+ while (n-- != 0 && *d != '\0')
+ {
+ d++;
+ }
+
+ dlen = d - dst;
+ n = siz - dlen;
+
+ if (n == 0)
+ return dlen + strlen(s);
+
+ while (*s != '\0')
+ {
+ if (n != 1)
+ {
+ *d++ = *s;
+ n--;
+ }
+
+ s++;
+ }
+
+ *d = '\0';
+
+ return dlen + (s - src);/* count does not include NUL */
+}
+
+size_t
+mowgli_strlcpy(char *dst, const char *src, size_t siz)
+{
+ char *d = dst;
+ const char *s = src;
+ size_t n = siz;
+
+ /* Copy as many bytes as will fit */
+ if (n != 0)
+ while (--n != 0)
+ {
+ if ((*d++ = *s++) == '\0')
+ break;
+ }
+
+ /* Not enough room in dst, add NUL and traverse rest of src */
+
+ if (n == 0)
+ {
+ if (siz != 0)
+ *d = '\0'; /* NUL-terminate dst */
+
+ while (*s++)
+ { }
+ }
+
+ return s - src - 1; /* count does not include NUL */
+}
+
+ssize_t
+mowgli_writef(mowgli_descriptor_t fd, const char *fmt, ...)
+{
+ size_t len;
+ va_list va;
+ char buf[16384];
+
+ return_val_if_fail(fmt != NULL, -1);
+
+ va_start(va, fmt);
+ len = vsnprintf(buf, sizeof buf, fmt, va);
+ va_end(va);
+
+#ifdef _WIN32
+ return send(fd, buf, len, 0);
+#else
+ return write(fd, buf, len);
+#endif
+}
diff --git a/src/libmowgli/core/mowgli_string.h b/src/libmowgli/core/mowgli_string.h
new file mode 100644
index 0000000..9652b4c
--- /dev/null
+++ b/src/libmowgli/core/mowgli_string.h
@@ -0,0 +1,53 @@
+/*
+ * libmowgli: A collection of useful routines for programming.
+ * mowgli_string.h: Immutable string buffers with cheap manipulation.
+ *
+ * Copyright (c) 2007 William Pitcock <nenolod -at- sacredspiral.co.uk>
+ * Copyright (c) 2007 Pippijn van Steenhoven <pippijn -at- one09.net>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice is present in all copies.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 __MOWGLI_STRING_H__
+#define __MOWGLI_STRING_H__
+
+typedef struct mowgli_string_
+{
+ char *str;
+ size_t pos;
+ size_t size;
+
+ void (*reset)(struct mowgli_string_ *self);
+
+ void (*append)(struct mowgli_string_ *self, const char *src, size_t n);
+
+ void (*append_char)(struct mowgli_string_ *self, const char c);
+
+ void (*destroy)(struct mowgli_string_ *self);
+} mowgli_string_t;
+
+extern mowgli_string_t *mowgli_string_create(void);
+extern void mowgli_string_reset(mowgli_string_t *self);
+extern void mowgli_string_destroy(mowgli_string_t *self);
+extern void mowgli_string_append(mowgli_string_t *self, const char *src, size_t n);
+extern void mowgli_string_append_char(mowgli_string_t *self, const char c);
+
+extern size_t mowgli_strlcat(char *dest, const char *src, size_t count);
+extern size_t mowgli_strlcpy(char *dest, const char *src, size_t count);
+extern ssize_t mowgli_writef(mowgli_descriptor_t fd, const char *fmt, ...);
+
+#endif
diff --git a/src/libmowgli/core/process.c b/src/libmowgli/core/process.c
new file mode 100644
index 0000000..9d6c8b4
--- /dev/null
+++ b/src/libmowgli/core/process.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2011 William Pitcock <nenolod@dereferenced.org>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice is present in all copies.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 "mowgli.h"
+
+typedef struct
+{
+ char *path;
+ char **argv;
+} mowgli_process_execv_req_t;
+
+static void
+mowgli_process_cloned_execv(mowgli_process_execv_req_t *execv_req)
+{
+#ifndef _WIN32
+ return_if_fail(execv_req != NULL);
+ return_if_fail(execv_req->path != NULL);
+ return_if_fail(execv_req->argv != NULL);
+
+ /* Do best to set proctitle if below hack don't work */
+ mowgli_proctitle_set("%s", execv_req->argv[0]);
+ execv(execv_req->path, execv_req->argv);
+
+ mowgli_free(execv_req->argv);
+ mowgli_free(execv_req->path);
+ mowgli_free(execv_req);
+#else
+# warning implement me :(
+#endif
+}
+
+mowgli_process_t *
+mowgli_process_clone(mowgli_process_start_fn_t start_fn, const char *procname, void *userdata)
+{
+#ifndef _WIN32
+ mowgli_process_t *out;
+
+ return_val_if_fail(start_fn != NULL, NULL);
+
+ out = mowgli_alloc(sizeof(mowgli_process_t));
+ out->userdata = userdata;
+
+ out->pid = fork();
+
+ switch (out->pid)
+ {
+ default:
+ break;
+
+ case 0:
+
+ /* Do our best to set this... */
+ mowgli_proctitle_set("%s", procname);
+ start_fn(out->userdata);
+ _exit(255);
+
+ return NULL;
+ break;
+
+ case -1:
+ mowgli_free(out);
+ return NULL;
+ break;
+ }
+
+ return out;
+#else
+# warning implement me :(
+ return NULL;
+#endif
+}
+
+mowgli_process_t *
+mowgli_process_spawn(const char *path, char *const argv[])
+{
+ size_t i;
+ mowgli_process_execv_req_t *req;
+
+ return_val_if_fail(path != NULL, NULL);
+ return_val_if_fail(argv != NULL, NULL);
+
+ req = mowgli_alloc(sizeof(mowgli_process_execv_req_t));
+ req->path = mowgli_strdup(path);
+
+ for (i = 0; argv[i] != NULL; i++)
+ ;
+
+ req->argv = mowgli_alloc_array(sizeof(char *), i + 1);
+
+ for (i = 0; argv[i] != NULL; i++)
+ req->argv[i] = argv[i];
+
+ return mowgli_process_clone((mowgli_process_start_fn_t) mowgli_process_cloned_execv, req->argv[0], req);
+}
+
+void
+mowgli_process_kill(mowgli_process_t *process)
+{
+#ifndef _WIN32
+ return_if_fail(process != NULL);
+
+ kill(process->pid, SIGKILL);
+#else
+# warning implement me :(
+#endif
+}
diff --git a/src/libmowgli/core/process.h b/src/libmowgli/core/process.h
new file mode 100644
index 0000000..c2fdcf1
--- /dev/null
+++ b/src/libmowgli/core/process.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2011 William Pitcock <nenolod@dereferenced.org>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice is present in all copies.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 __MOWGLI_PROCESS_H__
+#define __MOWGLI_PROCESS_H__
+
+typedef void (*mowgli_process_start_fn_t)(void *data);
+
+typedef pid_t mowgli_process_id_t;
+
+typedef struct
+{
+ mowgli_process_id_t pid;
+ void *userdata;
+} mowgli_process_t;
+
+extern mowgli_process_t *mowgli_process_clone(mowgli_process_start_fn_t start_fn, const char *proctitle, void *userdata);
+extern mowgli_process_t *mowgli_process_spawn(const char *path, char *const argv[]);
+extern void mowgli_process_kill(mowgli_process_t *process);
+
+#endif
diff --git a/src/libmowgli/core/stdinc.h b/src/libmowgli/core/stdinc.h
new file mode 100644
index 0000000..e1410a5
--- /dev/null
+++ b/src/libmowgli/core/stdinc.h
@@ -0,0 +1,109 @@
+/*
+ * libmowgli: A collection of useful routines for programming.
+ * stdinc.h: Pulls in the base system includes for libmowgli.
+ *
+ * Copyright (c) 2007 William Pitcock <nenolod -at- sacredspiral.co.uk>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice is present in all copies.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 __MOWGLI_STDINC_H__
+#define __MOWGLI_STDINC_H__
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+#include <signal.h>
+#include <time.h>
+#include <errno.h>
+#include <setjmp.h>
+#include <sys/stat.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <stdint.h>
+#include <stddef.h>
+#include <inttypes.h>
+#include <limits.h>
+
+/* socket stuff */
+#ifndef _WIN32
+# include <netdb.h>
+# include <netinet/in.h>
+# include <unistd.h>
+# include <grp.h>
+# include <sys/time.h>
+# include <sys/wait.h>
+# include <sys/resource.h>
+# include <sys/socket.h>
+# include <fcntl.h>
+# include <arpa/inet.h>
+# include <libgen.h>
+# include <dirent.h>
+#else
+# define WINVER 0x0501
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+# include <winsock2.h>
+# include <ws2tcpip.h>
+# include <sys/timeb.h>
+# include <direct.h>
+# include <io.h>
+# include <process.h>
+# include <fcntl.h>
+# include "platform/win32/win32_stdinc.h"
+#endif
+
+#ifdef _MSC_VER
+# pragma warning (disable: 4996)
+#endif
+
+#ifdef FALSE
+# undef FALSE
+#endif
+
+#ifdef TRUE
+# undef TRUE
+#endif
+
+typedef enum {FALSE, TRUE} mowgli_boolean_t;
+
+/* Macros for min/max. */
+#ifndef MIN
+# define MIN(a, b) (((a) < (b)) ? (a) : (b))
+#endif
+
+#ifndef MAX
+# define MAX(a, b) (((a) > (b)) ? (a) : (b))
+#endif
+
+/* OpenSSL stuff */
+#ifdef HAVE_OPENSSL
+# if defined(__APPLE__)
+# include <AvailabilityMacros.h>
+# ifdef DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER
+# undef DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER
+# define DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER
+# endif
+# endif
+# include <openssl/rand.h>
+# include <openssl/ssl.h>
+# include <openssl/err.h>
+#endif
+
+#endif